b8f621bd7e8a0865bc1e94ae658f4c49ff9ebe8f
[citadel.git] / textclient / client_chat.c
1 /*
2  * front end for multiuser chat
3  *
4  * Copyright (c) 1987-2016 by the citadel.org team
5  *
6  * This program is open source software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  */
14
15 #include "textclient.h"
16
17 #define MIN(a, b) ((a) < (b) ? (a) : (b))
18
19 extern char temp[];
20 char last_paged[SIZ] = "";
21
22 void chatmode(CtdlIPC * ipc)
23 {
24         char wbuf[SIZ];
25         char buf[SIZ];
26         char response[SIZ];
27         char c_user[SIZ];
28         char c_text[SIZ];
29         char last_user[SIZ];
30         int send_complete_line;
31         char ch;
32         int a, pos;
33         int seq = 0;
34
35         fd_set rfds;
36         struct timeval tv;
37         int retval;
38
39         CtdlIPC_chat_send(ipc, "RCHT enter");
40         CtdlIPC_chat_recv(ipc, buf);
41         if (buf[0] != '2') {
42                 scr_printf("%s\n", &buf[4]);
43                 return;
44         }
45         scr_printf("Entering chat mode (type /quit to exit)\n");
46
47         strcpy(buf, "");
48         strcpy(wbuf, "");
49         strcpy(last_user, "");
50         color(BRIGHT_YELLOW);
51         scr_printf("\n");
52         scr_printf("> ");
53         send_complete_line = 0;
54
55         while (1) {
56                 scr_flush();
57                 FD_ZERO(&rfds);
58                 FD_SET(0, &rfds);
59                 tv.tv_sec = 1;
60                 tv.tv_usec = 0;
61                 retval = select(1, &rfds, NULL, NULL, &tv);
62
63                 if (retval < 0) {
64                         color(BRIGHT_WHITE);
65                         scr_printf("Server gone Exiting chat mode\n");
66                         scr_flush();
67                         return;
68                 }
69
70                 /* If there's data from the keyboard... */
71                 if (FD_ISSET(0, &rfds)) {
72                         ch = scr_getc(SCR_BLOCK);
73                         if ((ch == 10) || (ch == 13)) {
74                                 send_complete_line = 1;
75                         } else if ((ch == 8) || (ch == 127)) {
76                                 if (!IsEmptyStr(wbuf)) {
77                                         wbuf[strlen(wbuf) - 1] = 0;
78                                         scr_printf("%c %c", 8, 8);
79                                 }
80                         } else {
81                                 scr_putc(ch);
82                                 wbuf[strlen(wbuf) + 1] = 0;
83                                 wbuf[strlen(wbuf)] = ch;
84                         }
85                 }
86
87                 /* if the user hit return, send the line */
88                 if (send_complete_line) {
89
90                         if (!strcasecmp(wbuf, "/quit")) {
91                                 CtdlIPC_chat_send(ipc, "RCHT exit");
92                                 CtdlIPC_chat_recv(ipc, response);       /* don't care about the result */
93                                 color(BRIGHT_WHITE);
94                                 scr_printf("\rExiting chat mode\n");
95                                 scr_flush();
96                                 return;
97                         }
98
99                         CtdlIPC_chat_send(ipc, "RCHT send");
100                         CtdlIPC_chat_recv(ipc, response);
101                         if (response[0] == '4') {
102                                 CtdlIPC_chat_send(ipc, wbuf);
103                                 CtdlIPC_chat_send(ipc, "000");
104                         }
105                         strcpy(wbuf, "");
106                         send_complete_line = 0;
107                 }
108
109                 /* if it's time to word wrap, send a partial line */
110                 if (strlen(wbuf) >= (77 - strlen(fullname))) {
111                         pos = 0;
112                         for (a = 0; !IsEmptyStr(&wbuf[a]); ++a) {
113                                 if (wbuf[a] == 32)
114                                         pos = a;
115                         }
116                         if (pos == 0) {
117                                 CtdlIPC_chat_send(ipc, "RCHT send");
118                                 CtdlIPC_chat_recv(ipc, response);
119                                 if (response[0] == '4') {
120                                         CtdlIPC_chat_send(ipc, wbuf);
121                                         CtdlIPC_chat_send(ipc, "000");
122                                 }
123                                 strcpy(wbuf, "");
124                                 send_complete_line = 0;
125                         } else {
126                                 wbuf[pos] = 0;
127                                 CtdlIPC_chat_send(ipc, "RCHT send");
128                                 CtdlIPC_chat_recv(ipc, response);
129                                 if (response[0] == '4') {
130                                         CtdlIPC_chat_send(ipc, wbuf);
131                                         CtdlIPC_chat_send(ipc, "000");
132                                 }
133                                 strcpy(wbuf, &wbuf[pos + 1]);
134                         }
135                 }
136
137                 /* poll for incoming chat messages */
138                 snprintf(buf, sizeof buf, "RCHT poll|%d", seq);
139                 CtdlIPC_chat_send(ipc, buf);
140                 CtdlIPC_chat_recv(ipc, response);
141
142                 if (response[0] == '1') {
143                         seq = extract_int(&response[4], 0);
144                         extract_token(c_user, &response[4], 2, '|', sizeof c_user);
145                         while (CtdlIPC_chat_recv(ipc, c_text), strcmp(c_text, "000")) {
146                                 scr_printf("\r%79s\r", "");
147                                 if (!strcmp(c_user, fullname)) {
148                                         color(BRIGHT_YELLOW);
149                                 } else if (!strcmp(c_user, ":")) {
150                                         color(BRIGHT_RED);
151                                 } else {
152                                         color(BRIGHT_GREEN);
153                                 }
154                                 if (strcmp(c_user, last_user)) {
155                                         snprintf(buf, sizeof buf, "%s: %s", c_user, c_text);
156                                 } else {
157                                         size_t i = MIN(sizeof buf - 1, strlen(c_user) + 2);
158                                         memset(buf, ' ', i);
159                                         safestrncpy(&buf[i], c_text, sizeof buf - i);
160                                 }
161                                 while (strlen(buf) < 79) {
162                                         strcat(buf, " ");
163                                 }
164                                 if (strcmp(c_user, last_user)) {
165                                         scr_printf("\r%79s\n", "");
166                                         strcpy(last_user, c_user);
167                                 }
168                                 scr_printf("\r%s\n", buf);
169                                 scr_flush();
170                         }
171                 }
172                 color(BRIGHT_YELLOW);
173                 scr_printf("\r> %s", wbuf);
174                 scr_flush();
175                 strcpy(buf, "");
176         }
177 }
178
179
180 /*
181  * send an instant message
182  */
183 void page_user(CtdlIPC * ipc)
184 {
185         char buf[SIZ], touser[SIZ], msg[SIZ];
186         FILE *pagefp;
187
188         strcpy(touser, last_paged);
189         strprompt("Page who", touser, 30);
190
191         /* old server -- use inline paging */
192         if (ipc->ServInfo.paging_level == 0) {
193                 newprompt("Message: ", msg, 69);
194                 snprintf(buf, sizeof buf, "SEXP %s|%s", touser, msg);
195                 CtdlIPC_chat_send(ipc, buf);
196                 CtdlIPC_chat_recv(ipc, buf);
197                 if (!strncmp(buf, "200", 3)) {
198                         strcpy(last_paged, touser);
199                 }
200                 scr_printf("%s\n", &buf[4]);
201                 return;
202         }
203         /* new server -- use extended paging */
204         else if (ipc->ServInfo.paging_level >= 1) {
205                 snprintf(buf, sizeof buf, "SEXP %s||", touser);
206                 CtdlIPC_chat_send(ipc, buf);
207                 CtdlIPC_chat_recv(ipc, buf);
208                 if (buf[0] != '2') {
209                         scr_printf("%s\n", &buf[4]);
210                         return;
211                 }
212                 if (client_make_message(ipc, temp, touser, 0, 0, 0, NULL, 0) != 0) {
213                         scr_printf("No message sent.\n");
214                         return;
215                 }
216                 pagefp = fopen(temp, "r");
217                 unlink(temp);
218                 snprintf(buf, sizeof buf, "SEXP %s|-", touser);
219                 CtdlIPC_chat_send(ipc, buf);
220                 CtdlIPC_chat_recv(ipc, buf);
221                 if (buf[0] == '4') {
222                         strcpy(last_paged, touser);
223                         while (fgets(buf, sizeof buf, pagefp) != NULL) {
224                                 buf[strlen(buf) - 1] = 0;
225                                 CtdlIPC_chat_send(ipc, buf);
226                         }
227                         fclose(pagefp);
228                         CtdlIPC_chat_send(ipc, "000");
229                         scr_printf("Message sent.\n");
230                 } else {
231                         scr_printf("%s\n", &buf[4]);
232                 }
233         }
234 }
235
236
237 void quiet_mode(CtdlIPC * ipc)
238 {
239         static int quiet = 0;
240         char cret[SIZ];
241         int r;
242
243         r = CtdlIPCEnableInstantMessageReceipt(ipc, !quiet, cret);
244         if (r / 100 == 2) {
245                 quiet = !quiet;
246                 scr_printf("Quiet mode %sabled (%sother users may page you)\n", (quiet) ? "en" : "dis", (quiet) ? "no " : "");
247         } else {
248                 scr_printf("Unable to change quiet mode: %s\n", cret);
249         }
250 }
251
252
253 void stealth_mode(CtdlIPC * ipc)
254 {
255         static int stealth = 0;
256         char cret[SIZ];
257         int r;
258
259         r = CtdlIPCStealthMode(ipc, !stealth, cret);
260         if (r / 100 == 2) {
261                 stealth = !stealth;
262                 scr_printf("Stealth mode %sabled (you are %s)\n",
263                            (stealth) ? "en" : "dis", (stealth) ? "invisible" : "listed as online");
264         } else {
265                 scr_printf("Unable to change stealth mode: %s\n", cret);
266         }
267 }