comparison nnchat.c @ 30:751cff550992

Hmm.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 03 Aug 2008 08:17:55 +0300
parents a27ef0e359b9
children 9b429b283786
comparison
equal deleted inserted replaced
29:a27ef0e359b9 30:751cff550992
12 #include <string.h> 12 #include <string.h>
13 #include <errno.h> 13 #include <errno.h>
14 #include <time.h> 14 #include <time.h>
15 #include <ncurses.h> 15 #include <ncurses.h>
16 16
17 17 #define SET_MAX_HISTORY (16)
18 #define SET_BUFSIZE (4096) 18 #define SET_BUFSIZE (4096)
19 #define SET_ALLOC_SIZE (128) 19 #define SET_ALLOC_SIZE (128)
20 #define SET_DELAY (15) 20 #define SET_DELAY (15)
21 #define SET_DELAY_USEC (SET_DELAY * 1000) 21 #define SET_DELAY_USEC (SET_DELAY * 1000)
22 22
33 BOOL optDaemon = FALSE; 33 BOOL optDaemon = FALSE;
34 FILE *optLogFile = NULL; 34 FILE *optLogFile = NULL;
35 WINDOW *mainWin = NULL, 35 WINDOW *mainWin = NULL,
36 *statusWin = NULL, 36 *statusWin = NULL,
37 *editWin = NULL; 37 *editWin = NULL;
38 38 BOOL setPrvMode = FALSE;
39 BOOL setInsertMode = TRUE;
40 39
41 /* Arguments 40 /* Arguments
42 */ 41 */
43 optarg_t optList[] = { 42 optarg_t optList[] = {
44 { 0, '?', "help", "Show this help", OPT_NONE }, 43 { 0, '?', "help", "Show this help", OPT_NONE },
196 { 195 {
197 buf->len = 0; 196 buf->len = 0;
198 buf->pos = 0; 197 buf->pos = 0;
199 } 198 }
200 199
200 editbuf_t * newBuf(void)
201 {
202 return (editbuf_t *) th_calloc(1, sizeof(editbuf_t));
203 }
204
205 void freeBuf(editbuf_t *buf)
206 {
207 th_free(buf);
208 }
209
210 editbuf_t * copyBuf(editbuf_t *src)
211 {
212 editbuf_t *dst = newBuf();
213
214 if (dst == NULL) return NULL;
215
216 if (src != NULL) {
217 memcpy(dst->data, src->data, SET_BUFSIZE);
218 clearBuf(dst);
219 }
220
221 return dst;
222 }
223
201 void setBufPos(editbuf_t *buf, ssize_t pos) 224 void setBufPos(editbuf_t *buf, ssize_t pos)
202 { 225 {
203 /* Check arguments */ 226 /* Check arguments */
204 if (pos < 0) 227 if (pos < 0)
205 buf->pos = 0; 228 buf->pos = 0;
207 buf->pos = buf->len; 230 buf->pos = buf->len;
208 else 231 else
209 buf->pos = pos; 232 buf->pos = pos;
210 } 233 }
211 234
212 void updateStatus(void) 235 void updateStatus(BOOL insertMode)
213 { 236 {
214 char tmpStr[128] = ""; 237 char tmpStr[128] = "";
215 time_t timeStamp; 238 time_t timeStamp;
216 struct tm *tmpTime;; 239 struct tm *tmpTime;;
217 240
225 248
226 wattrset(statusWin, A_BOLD); 249 wattrset(statusWin, A_BOLD);
227 mvwaddstr(statusWin, 0, 1, tmpStr); 250 mvwaddstr(statusWin, 0, 1, tmpStr);
228 251
229 waddstr(statusWin, " | "); 252 waddstr(statusWin, " | ");
230 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); 253 wattrset(statusWin, A_BOLD | COLOR_PAIR(16));
231 waddstr(statusWin, optUserName); 254 waddstr(statusWin, optUserName);
232 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); 255 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
233 256
234 waddstr(statusWin, " | "); 257 waddstr(statusWin, " | ");
235 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); 258 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
236 waddstr(statusWin, setInsertMode ? "INS" : "DEL"); 259 waddstr(statusWin, insertMode ? "INS" : "DEL");
237 260
238 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); 261 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
239 waddstr(statusWin, " | Prv: "); 262 waddstr(statusWin, " | Prv: ");
240 263
241 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); 264 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
242 waddstr(statusWin, setTarget != NULL ? setTarget : "-"); 265 waddstr(statusWin, setTarget != NULL ? setTarget : "-");
243 266
244 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); 267 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
245 waddstr(statusWin, " | Port: "); 268 waddstr(statusWin, " | P/C: ");
246 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); 269 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
247 snprintf(tmpStr, sizeof(tmpStr), "%d", optPort); 270 snprintf(tmpStr, sizeof(tmpStr), "%d / #%06x", optPort, optUserColor);
248 waddstr(statusWin, tmpStr); 271 waddstr(statusWin, tmpStr);
249 272
250 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
251 waddstr(statusWin, " | Col: ");
252 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
253 snprintf(tmpStr, sizeof(tmpStr), "%06x", optUserColor);
254 waddstr(statusWin, tmpStr);
255
256 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
257 snprintf(tmpStr, sizeof(tmpStr), " | %s v%s",
258 th_prog_name, th_prog_version);
259 waddstr(statusWin, tmpStr);
260
261 wrefresh(statusWin); 273 wrefresh(statusWin);
262 } 274 }
263 275
264 void printEditBuf(editbuf_t *buf) 276 void printEditBuf(char *str, editbuf_t *buf)
265 { 277 {
266 buf->data[buf->len] = 0; 278 buf->data[buf->len] = 0;
267 werase(editWin); 279 werase(editWin);
280
281 wattrset(editWin, A_BOLD);
282 mvwaddstr(editWin, 0, 0, str);
283 waddstr(editWin, "> ");
284 wattrset(editWin, A_NORMAL);
285
268 if (buf->pos < buf->len) { 286 if (buf->pos < buf->len) {
269 mvwaddnstr(editWin, 0, 0, buf->data, buf->pos); 287 waddnstr(editWin, buf->data, buf->pos);
270 wattrset(editWin, A_REVERSE); 288 wattrset(editWin, A_REVERSE);
271 waddch(editWin, buf->data[buf->pos]); 289 waddch(editWin, buf->data[buf->pos]);
272 wattrset(editWin, A_NORMAL); 290 wattrset(editWin, A_NORMAL);
273 waddnstr(editWin, buf->data + buf->pos + 1, buf->len - buf->pos - 1); 291 waddnstr(editWin, buf->data + buf->pos + 1, buf->len - buf->pos - 1);
274 } else { 292 } else {
275 mvwaddnstr(editWin, 0, 0, buf->data, buf->len); 293 waddnstr(editWin, buf->data, buf->len);
276 wattrset(editWin, A_REVERSE); 294 wattrset(editWin, A_REVERSE);
277 waddch(editWin, ' '); 295 waddch(editWin, ' ');
278 wattrset(editWin, A_NORMAL); 296 wattrset(editWin, A_NORMAL);
279 } 297 }
280 wrefresh(editWin); 298 wrefresh(editWin);
852 870
853 /* Check command */ 871 /* Check command */
854 if (*buf == 0) { 872 if (*buf == 0) {
855 return 1; 873 return 1;
856 } else if (!strncmp(buf, "/color ", 7)) { 874 } else if (!strncmp(buf, "/color ", 7)) {
857 if ((optUserColor = getColor(buf+7)) < 0) { 875 int tmpInt;
876 if ((tmpInt = getColor(buf+7)) < 0) {
858 printMsg("Invalid color value '%s'\n", buf+7); 877 printMsg("Invalid color value '%s'\n", buf+7);
859 return 1; 878 return 1;
860 } 879 }
880 optUserColor = tmpInt;
861 printMsg("Setting color to #%06x\n", optUserColor); 881 printMsg("Setting color to #%06x\n", optUserColor);
862 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); 882 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
863 return 0; 883 return 0;
864 } else if (!strncmp(buf, "/flood ", 7)) { 884 } else if (!strncmp(buf, "/flood ", 7)) {
865 int i; 885 int i;
881 usleep(250); 901 usleep(250);
882 } 902 }
883 903
884 th_free(tmpStr); 904 th_free(tmpStr);
885 th_free(tmpStr2); 905 th_free(tmpStr2);
906 return 0;
907 } else if (!strncmp(buf, "/to ", 4)) {
908 buf += 4;
909 th_free(setTarget);
910 setTarget = th_strdup(buf);
911 printMsg("Set prv target to '%s'\n", setTarget);
886 return 0; 912 return 0;
887 } else if (!strncmp(buf, "/msg ", 5)) { 913 } else if (!strncmp(buf, "/msg ", 5)) {
888 if (setTarget != NULL) { 914 if (setTarget != NULL) {
889 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf+5); 915 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf+5);
890 buf = tmpBuf; 916 buf = tmpBuf;
891 } else { 917 } else {
892 printMsg("No target set!\n"); 918 printMsg("No target set!\n");
893 return 1; 919 return 1;
894 } 920 }
895 } else if (!strncmp(buf, "/to ", 4)) { 921 } else if (setPrvMode) {
896 buf += 4; 922 if (setTarget != NULL) {
897 th_free(setTarget); 923 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf);
898 setTarget = th_strdup(buf); 924 buf = tmpBuf;
899 printMsg("Set prv target to '%s'\n", setTarget); 925 } else {
900 return 0; 926 printMsg("No target set, exiting prv mode.\n");
927 setPrvMode = FALSE;
928 return 1;
929 }
901 } 930 }
902 931
903 { 932 {
904 /* Send double-encoded */ 933 /* Send double-encoded */
905 tmpStr = encodeStr2(buf); 934 tmpStr = encodeStr2(buf);
926 int tmpSocket, curVis, updateCount = 0; 955 int tmpSocket, curVis, updateCount = 0;
927 struct hostent *tmpHost; 956 struct hostent *tmpHost;
928 BOOL argsOK, isError = FALSE, 957 BOOL argsOK, isError = FALSE,
929 exitProg = FALSE, 958 exitProg = FALSE,
930 colorSet = FALSE, 959 colorSet = FALSE,
931 cursesInit = FALSE; 960 cursesInit = FALSE,
961 insertMode = TRUE;
932 struct timeval tv; 962 struct timeval tv;
933 fd_set sockfds; 963 fd_set sockfds;
934 char *tmpStr; 964 char *tmpStr;
935 editbuf_t *editBuf = calloc(1, sizeof(editbuf_t)); 965 editbuf_t *editBuf = newBuf();
936 966 editbuf_t *histBuf[SET_MAX_HISTORY+2];
967 int histPos = 0, histMax = 0;
968
969 memset(histBuf, 0, sizeof(histBuf));
970
937 /* Initialize */ 971 /* Initialize */
938 th_init("NNChat", "Newbie Nudes chat client", "0.4", 972 th_init("NNChat", "Newbie Nudes chat client", "0.5",
939 "Written and designed by Anonymous Finnish Guy (C) 2008", 973 "Written and designed by Anonymous Finnish Guy (C) 2008",
940 "This software is freeware, use and distribute as you wish."); 974 "This software is freeware, use and distribute as you wish.");
941 th_verbosityLevel = 0; 975 th_verbosityLevel = 0;
942 976
943 /* Parse arguments */ 977 /* Parse arguments */
1043 goto err_exit; 1077 goto err_exit;
1044 } 1078 }
1045 scrollok(mainWin, 1); 1079 scrollok(mainWin, 1);
1046 1080
1047 clearBuf(editBuf); 1081 clearBuf(editBuf);
1048 printEditBuf(editBuf); 1082 printEditBuf("", editBuf);
1049 updateStatus(); 1083 updateStatus(insertMode);
1050 1084
1051 cursesInit = TRUE; 1085 cursesInit = TRUE;
1052 } 1086 }
1053 1087
1054 1088
1089 /* Enter mainloop */
1055 FD_ZERO(&sockfds); 1090 FD_ZERO(&sockfds);
1056 FD_SET(tmpSocket, &sockfds); 1091 FD_SET(tmpSocket, &sockfds);
1057 1092
1058 while (!isError && !exitProg) { 1093 while (!isError && !exitProg) {
1059 int result; 1094 int result;
1067 printMsg("Error occured in select(sockfds): %s\n", 1102 printMsg("Error occured in select(sockfds): %s\n",
1068 strerror(errno)); 1103 strerror(errno));
1069 isError = TRUE; 1104 isError = TRUE;
1070 } else if (FD_ISSET(tmpSocket, &tmpfds)) { 1105 } else if (FD_ISSET(tmpSocket, &tmpfds)) {
1071 ssize_t gotBuf; 1106 ssize_t gotBuf;
1072 char tmpBuf[4096]; 1107 char tmpBuf[8192];
1073 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); 1108 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0);
1074 1109
1075 if (gotBuf < 0) { 1110 if (gotBuf < 0) {
1076 printMsg("Error in recv: %s\n", strerror(errno)); 1111 printMsg("Error in recv: %s\n", strerror(errno));
1077 isError = TRUE; 1112 isError = TRUE;
1089 } else if (result < 0) { 1124 } else if (result < 0) {
1090 /* Fatal error, quit */ 1125 /* Fatal error, quit */
1091 printMsg("Fatal error with message: %s\n", tmpBuf); 1126 printMsg("Fatal error with message: %s\n", tmpBuf);
1092 isError = TRUE; 1127 isError = TRUE;
1093 } 1128 }
1094 updateStatus(); 1129 updateStatus(insertMode);
1095 } 1130 }
1096 } 1131 }
1097 1132
1098 /* Handle user input */ 1133 /* Handle user input */
1099 if (!optDaemon) { 1134 if (!optDaemon) {
1108 case '\n': 1143 case '\n':
1109 case '\r': 1144 case '\r':
1110 /* Call the user input handler */ 1145 /* Call the user input handler */
1111 if (editBuf->len > 0) { 1146 if (editBuf->len > 0) {
1112 insertBuf(editBuf, editBuf->pos, 0); 1147 insertBuf(editBuf, editBuf->pos, 0);
1148
1149 if (histMax > 0) {
1150 freeBuf(histBuf[histMax]);
1151 memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0]));
1152 }
1153 histPos = 0;
1154 histBuf[1] = copyBuf(editBuf);
1155 if (histMax < SET_MAX_HISTORY) histMax++;
1156
1113 result = handleUserInput(tmpSocket, editBuf->data, editBuf->len); 1157 result = handleUserInput(tmpSocket, editBuf->data, editBuf->len);
1158
1114 clearBuf(editBuf); 1159 clearBuf(editBuf);
1115 1160
1116 if (result < 0) { 1161 if (result < 0) {
1117 printMsg("Fatal error handling user input: %s\n", editBuf->data); 1162 printMsg("Fatal error handling user input: %s\n", editBuf->data);
1118 isError = TRUE; 1163 isError = TRUE;
1119 } 1164 }
1120 1165
1121 update = TRUE; 1166 update = TRUE;
1122 } 1167 }
1123 break; 1168 break;
1124 1169
1170 case 0x09: /* Tab = switch between PRV */
1171 if (setPrvMode)
1172 setPrvMode = FALSE;
1173 else {
1174 if (setTarget != NULL)
1175 setPrvMode = TRUE;
1176 }
1177 update = TRUE;
1178 break;
1179
1180 case KEY_UP:
1181 if (histPos == 0)
1182 histBuf[0] = copyBuf(editBuf);
1183 if (histPos < histMax) {
1184 histPos++;
1185 freeBuf(editBuf);
1186 editBuf = copyBuf(histBuf[histPos]);
1187 update = TRUE;
1188 }
1189 break;
1190
1191 case KEY_DOWN:
1192 if (histPos > 0) {
1193 histPos--;
1194 freeBuf(editBuf);
1195 editBuf = copyBuf(histBuf[histPos]);
1196 update = TRUE;
1197 }
1198 break;
1199
1125 case 0x109: /* F1 */ 1200 case 0x109: /* F1 */
1126 if (setInsertMode) 1201 if (insertMode)
1127 setInsertMode = FALSE; 1202 insertMode = FALSE;
1128 else 1203 else
1129 setInsertMode = TRUE; 1204 insertMode = TRUE;
1130 update = TRUE; 1205 update = TRUE;
1131 break; 1206 break;
1132 1207
1133 case 0x204: /* ctrl+left */ 1208 case 0x204: /* ctrl+left */
1134 editBuf->pos--; 1209 editBuf->pos--;
1186 /* Ignore */ 1261 /* Ignore */
1187 break; 1262 break;
1188 1263
1189 default: 1264 default:
1190 if (isprint(c)) { 1265 if (isprint(c)) {
1191 if (setInsertMode) 1266 if (insertMode)
1192 insertBuf(editBuf, editBuf->pos, c); 1267 insertBuf(editBuf, editBuf->pos, c);
1193 else 1268 else
1194 writeBuf(editBuf, editBuf->pos, c); 1269 writeBuf(editBuf, editBuf->pos, c);
1195 setBufPos(editBuf, editBuf->pos + 1); 1270 setBufPos(editBuf, editBuf->pos + 1);
1196 update = TRUE; 1271 update = TRUE;
1201 } 1276 }
1202 } while (c != ERR && !exitProg && ++cnt < 10); 1277 } while (c != ERR && !exitProg && ++cnt < 10);
1203 1278
1204 if (update) { 1279 if (update) {
1205 /* Update edit line */ 1280 /* Update edit line */
1206 printEditBuf(editBuf); 1281 printEditBuf(setPrvMode ? setTarget : "", editBuf);
1207 updateStatus(); 1282 updateStatus(insertMode);
1208 } 1283 }
1209 } /* !optDaemon */ 1284 } /* !optDaemon */
1210 1285
1211 if (++updateCount > 10) { 1286 if (++updateCount > 10) {
1212 updateStatus(); 1287 updateStatus(insertMode);
1213 updateCount = 0; 1288 updateCount = 0;
1214 } 1289 }
1215 1290
1216 if (!colorSet) { 1291 if (!colorSet) {
1217 colorSet = TRUE; 1292 colorSet = TRUE;
1293 printMsg("%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
1294 printMsg("%s\n", th_prog_author);
1295 printMsg("%s\n", th_prog_license);
1218 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); 1296 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
1219 } 1297 }
1220 } 1298 }
1221 1299
1222 /* Shutdown */ 1300 /* Shutdown */