Mercurial > hg > nnchat
comparison nnchat.c @ 103:eaa524e153f9
Initial implementation of functions for implementing tab-completion for user names.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 15 Oct 2010 00:34:25 +0300 |
parents | ed4067c10a8a |
children | 06e6ac51e3f2 |
comparison
equal
deleted
inserted
replaced
102:b096ae97fc7d | 103:eaa524e153f9 |
---|---|
1 /* | 1 /* |
2 * NNChat - Custom chat client for NewbieNudes.com chatrooms | 2 * NNChat - Custom chat client for NewbieNudes.com chatrooms |
3 * Written by Matti 'ccr' Hämäläinen | 3 * Written by Matti 'ccr' Hämäläinen |
4 * (C) Copyright 2008-2009 Tecnic Software productions (TNSP) | 4 * (C) Copyright 2008-2010 Tecnic Software productions (TNSP) |
5 */ | 5 */ |
6 #include "libnnchat.h" | 6 #include "libnnchat.h" |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 #include "th_args.h" | 8 #include "th_args.h" |
9 #include <string.h> | 9 #include <string.h> |
20 #define SET_MAX_HISTORY (16) | 20 #define SET_MAX_HISTORY (16) |
21 #define SET_DELAY (15) | 21 #define SET_DELAY (15) |
22 #define SET_DELAY_USEC (SET_DELAY * 1000) | 22 #define SET_DELAY_USEC (SET_DELAY * 1000) |
23 #define SET_KEEPALIVE (15*60) /* Ping/keepalive period in seconds */ | 23 #define SET_KEEPALIVE (15*60) /* Ping/keepalive period in seconds */ |
24 | 24 |
25 char *ignoreList[] = { | |
26 "purr_rr", | |
27 "moisha", | |
28 "leth", | |
29 "shaz:)", | |
30 "rayen", | |
31 "iam2qute4you_92", | |
32 NULL | |
33 }; | |
34 | |
35 nn_userhash_t *nnUsers = NULL; | |
25 | 36 |
26 /* Options | 37 /* Options |
27 */ | 38 */ |
28 int optPort = 8005; | 39 int optPort = 8005; |
29 int optUserColor = 0x006080; | 40 int optUserColor = 0x006080; |
38 FILE *optLogFile = NULL; | 49 FILE *optLogFile = NULL; |
39 WINDOW *mainWin = NULL, | 50 WINDOW *mainWin = NULL, |
40 *statusWin = NULL, | 51 *statusWin = NULL, |
41 *editWin = NULL; | 52 *editWin = NULL; |
42 BOOL setPrvMode = FALSE; | 53 BOOL setPrvMode = FALSE; |
54 BOOL ignoreMode = FALSE; | |
43 | 55 |
44 | 56 |
45 /* Arguments | 57 /* Arguments |
46 */ | 58 */ |
47 optarg_t optList[] = { | 59 optarg_t optList[] = { |
280 | 292 |
281 return 0; | 293 return 0; |
282 } | 294 } |
283 | 295 |
284 | 296 |
285 void printMsgV(const char *fmt, va_list ap) | 297 void printMsgV(BOOL addStamp, BOOL logOnly, const char *fmt, va_list ap) |
286 { | 298 { |
287 char tmpStr[128] = "", buf[8192]; | 299 char tmpStr[128] = "", buf[8192]; |
288 time_t timeStamp; | 300 time_t timeStamp; |
289 struct tm *tmpTime;; | 301 struct tm *tmpTime;; |
290 | 302 |
294 } | 306 } |
295 | 307 |
296 vsnprintf(buf, sizeof(buf), fmt, ap); | 308 vsnprintf(buf, sizeof(buf), fmt, ap); |
297 | 309 |
298 if (optLogFile) { | 310 if (optLogFile) { |
299 printFile(optLogFile, tmpStr); | 311 if (addStamp) printFile(optLogFile, tmpStr); |
300 printFile(optLogFile, buf); | 312 printFile(optLogFile, buf); |
301 fflush(optLogFile); | 313 fflush(optLogFile); |
302 } | 314 } |
303 | 315 |
304 if (!optDaemon) { | 316 if (!optDaemon && !logOnly) { |
305 printWin(mainWin, tmpStr); | 317 if (addStamp) printWin(mainWin, tmpStr); |
306 printWin(mainWin, buf); | 318 printWin(mainWin, buf); |
307 wrefresh(mainWin); | 319 wrefresh(mainWin); |
308 } | 320 } |
309 } | 321 } |
310 | 322 |
311 void printMsg(const char *fmt, ...) | 323 void printMsg(const char *fmt, ...) |
312 { | 324 { |
313 va_list ap; | 325 va_list ap; |
314 | 326 |
315 va_start(ap, fmt); | 327 va_start(ap, fmt); |
316 printMsgV(fmt, ap); | 328 printMsgV(TRUE, FALSE, fmt, ap); |
329 va_end(ap); | |
330 } | |
331 | |
332 void printMsgC(const char *fmt, ...) | |
333 { | |
334 va_list ap; | |
335 | |
336 va_start(ap, fmt); | |
337 printMsgV(FALSE, FALSE, fmt, ap); | |
338 va_end(ap); | |
339 } | |
340 | |
341 void printMsgQ(BOOL logOnly, const char *fmt, ...) | |
342 { | |
343 va_list ap; | |
344 | |
345 va_start(ap, fmt); | |
346 printMsgV(TRUE, logOnly, fmt, ap); | |
317 va_end(ap); | 347 va_end(ap); |
318 } | 348 } |
319 | 349 |
320 | 350 |
321 void errorMsg(char *fmt, ...) | 351 void errorMsg(char *fmt, ...) |
322 { | 352 { |
323 va_list ap1, ap2; | 353 va_list ap1, ap2; |
324 | 354 |
325 va_start(ap1, fmt); | 355 va_start(ap1, fmt); |
326 va_copy(ap2, ap1); | 356 va_copy(ap2, ap1); |
327 printMsgV(fmt, ap1); | 357 printMsgV(TRUE, FALSE, fmt, ap1); |
328 va_end(ap1); | 358 va_end(ap1); |
329 | 359 |
330 THERR_V(fmt, ap2); | 360 THERR_V(fmt, ap2); |
331 va_end(ap2); | 361 va_end(ap2); |
332 } | 362 } |
369 } | 399 } |
370 th_free(h); | 400 th_free(h); |
371 th_free(t); | 401 th_free(t); |
372 } else { | 402 } else { |
373 BOOL isMine = strcmp(p, optUserName) == 0; | 403 BOOL isMine = strcmp(p, optUserName) == 0; |
404 BOOL logOnly = FALSE; | |
374 t = nn_strip_tags(s); | 405 t = nn_strip_tags(s); |
375 h = nn_decode_str2(t); | 406 h = nn_decode_str2(t); |
376 printMsg("½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, p, h); | 407 if (ignoreMode) { |
408 char **user = ignoreList; | |
409 while (*user != NULL) { | |
410 if (strcasecmp(p, *user) == 0) { | |
411 logOnly = TRUE; | |
412 break; | |
413 } | |
414 user++; | |
415 } | |
416 } | |
417 printMsgQ(logOnly, "½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, p, h); | |
377 th_free(h); | 418 th_free(h); |
378 th_free(t); | 419 th_free(t); |
379 } | 420 } |
380 | 421 |
381 th_free(s); | 422 th_free(s); |
416 if (!s) return 1; | 457 if (!s) return 1; |
417 *s = 0; | 458 *s = 0; |
418 | 459 |
419 p = nn_dbldecode_str(str); | 460 p = nn_dbldecode_str(str); |
420 if (!p) return -1; | 461 if (!p) return -1; |
421 | 462 |
463 nn_userhash_insert(nnUsers, str); | |
464 | |
422 printMsg("! ½3½%s½0½ ½2½ADDED.½0½\n", p); | 465 printMsg("! ½3½%s½0½ ½2½ADDED.½0½\n", p); |
423 th_free(p); | 466 th_free(p); |
424 return 0; | 467 return 0; |
425 } | 468 } |
426 | 469 |
434 if (!s) return 1; | 477 if (!s) return 1; |
435 *s = 0; | 478 *s = 0; |
436 | 479 |
437 p = nn_dbldecode_str(str); | 480 p = nn_dbldecode_str(str); |
438 if (!p) return -1; | 481 if (!p) return -1; |
439 | 482 |
483 nn_userhash_delete(nnUsers, str); | |
440 printMsg("! ½3½%s½0½ ½1½DELETED.½0½\n", p); | 484 printMsg("! ½3½%s½0½ ½1½DELETED.½0½\n", p); |
441 th_free(p); | 485 th_free(p); |
442 return 0; | 486 return 0; |
443 } | 487 } |
444 | 488 |
552 } | 596 } |
553 | 597 |
554 | 598 |
555 /* Send double-encoded */ | 599 /* Send double-encoded */ |
556 tmpStr = nn_dblencode_str(buf); | 600 tmpStr = nn_dblencode_str(buf); |
557 if (!tmpStr) return -2; | 601 if (tmpStr == 0) return -2; |
558 | |
559 result = nn_send_msg(sock, optUserName2, "%s", tmpStr); | 602 result = nn_send_msg(sock, optUserName2, "%s", tmpStr); |
560 th_free(tmpStr); | 603 th_free(tmpStr); |
561 if (result) | 604 |
562 return 0; | 605 return result ? 0 : -1; |
563 else | |
564 return -1; | |
565 } | 606 } |
566 | 607 |
567 | 608 |
568 BOOL initializeWindows(void) | 609 BOOL initializeWindows(void) |
569 { | 610 { |
582 scrollok(mainWin, 1); | 623 scrollok(mainWin, 1); |
583 | 624 |
584 return TRUE; | 625 return TRUE; |
585 } | 626 } |
586 | 627 |
628 | |
629 int printUserFunc(const nn_user_t *user) | |
630 { | |
631 if (user) | |
632 printMsgC("%s, ", user->name); | |
633 return 0; | |
634 } | |
587 | 635 |
588 int main(int argc, char *argv[]) | 636 int main(int argc, char *argv[]) |
589 { | 637 { |
590 int tmpSocket = -1, curVis = ERR, updateCount = 0; | 638 int tmpSocket = -1, curVis = ERR, updateCount = 0; |
591 struct hostent *tmpHost; | 639 struct hostent *tmpHost; |
604 int histPos = 0, histMax = 0; | 652 int histPos = 0, histMax = 0; |
605 | 653 |
606 memset(histBuf, 0, sizeof(histBuf)); | 654 memset(histBuf, 0, sizeof(histBuf)); |
607 | 655 |
608 /* Initialize */ | 656 /* Initialize */ |
609 th_init("NNChat", "Newbie Nudes chat client", "0.7.3", | 657 th_init("NNChat", "Newbie Nudes chat client", "0.7.9", |
610 "Written and designed by Anonymous Finnish Guy (C) 2008-2009", | 658 "Written and designed by Anonymous Finnish Guy (C) 2008-2010", |
611 "This software is freeware, use and distribute as you wish."); | 659 "This software is freeware, use and distribute as you wish."); |
612 th_verbosityLevel = 0; | 660 th_verbosityLevel = 0; |
613 | 661 |
614 /* Parse arguments */ | 662 /* Parse arguments */ |
615 argsOK = th_args_process(argc, argv, optList, optListN, | 663 argsOK = th_args_process(argc, argv, optList, optListN, |
622 } | 670 } |
623 | 671 |
624 if (!argsOK) | 672 if (!argsOK) |
625 return -2; | 673 return -2; |
626 | 674 |
675 /* Allocate userhash */ | |
676 if ((nnUsers = nn_userhash_new()) == NULL) { | |
677 THERR("Could not allocate userhash. Fatal error.\n"); | |
678 return -105; | |
679 } | |
627 | 680 |
628 /* Open logfile */ | 681 /* Open logfile */ |
629 if (optLogFilename) { | 682 if (optLogFilename) { |
630 THMSG(1, "Opening logfile '%s'\n", optLogFilename); | 683 THMSG(1, "Opening logfile '%s'\n", optLogFilename); |
631 | 684 |
850 | 903 |
851 update = TRUE; | 904 update = TRUE; |
852 } | 905 } |
853 break; | 906 break; |
854 | 907 |
855 case 0x09: /* Tab = switch between PRV */ | |
856 if (setPrvMode) | |
857 setPrvMode = FALSE; | |
858 else { | |
859 if (setTarget != NULL) | |
860 setPrvMode = TRUE; | |
861 } | |
862 update = TRUE; | |
863 break; | |
864 | |
865 case KEY_UP: /* Backwards in input history */ | 908 case KEY_UP: /* Backwards in input history */ |
866 if (histPos == 0) { | 909 if (histPos == 0) { |
867 nn_editbuf_free(histBuf[0]); | 910 nn_editbuf_free(histBuf[0]); |
868 histBuf[0] = nn_editbuf_copy(editBuf); | 911 histBuf[0] = nn_editbuf_copy(editBuf); |
869 } | 912 } |
882 editBuf = nn_editbuf_copy(histBuf[histPos]); | 925 editBuf = nn_editbuf_copy(histBuf[histPos]); |
883 update = TRUE; | 926 update = TRUE; |
884 } | 927 } |
885 break; | 928 break; |
886 | 929 |
887 case 0x204: /* ctrl+left = Skip words left */ | 930 case 0x204: /* ctrl+left arrow = Skip words left */ |
888 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) | 931 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) |
889 editBuf->pos--; | 932 editBuf->pos--; |
890 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) | 933 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) |
891 editBuf->pos--; | 934 editBuf->pos--; |
892 update = TRUE; | 935 update = TRUE; |
893 break; | 936 break; |
894 | 937 |
895 case 0x206: /* ctrl+right = Skip words right */ | 938 case 0x206: /* ctrl+right arrow = Skip words right */ |
896 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) | 939 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) |
897 editBuf->pos++; | 940 editBuf->pos++; |
898 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) | 941 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) |
899 editBuf->pos++; | 942 editBuf->pos++; |
900 if (editBuf->pos > editBuf->len) | 943 if (editBuf->pos > editBuf->len) |
901 editBuf->pos = editBuf->len; | 944 editBuf->pos = editBuf->len; |
902 update = TRUE; | 945 update = TRUE; |
903 break; | 946 break; |
904 | 947 |
905 case 0x111: /* F9 = Quit */ | |
906 printMsg("Quitting per user request.\n"); | |
907 exitProg = TRUE; | |
908 break; | |
909 | |
910 case 0x109: /* F1 = Toggle insert / overwrite mode */ | |
911 insertMode = !insertMode; | |
912 update = TRUE; | |
913 break; | |
914 | |
915 case 0x10a: /* F2 = Clear editbuffer */ | |
916 nn_editbuf_clear(editBuf); | |
917 update = TRUE; | |
918 break; | |
919 | |
920 case KEY_HOME: nn_editbuf_setpos(editBuf, 0); update = TRUE; break; | 948 case KEY_HOME: nn_editbuf_setpos(editBuf, 0); update = TRUE; break; |
921 case KEY_END: nn_editbuf_setpos(editBuf, editBuf->len); update = TRUE; break; | 949 case KEY_END: nn_editbuf_setpos(editBuf, editBuf->len); update = TRUE; break; |
922 case KEY_LEFT: nn_editbuf_setpos(editBuf, editBuf->pos - 1); update = TRUE; break; | 950 case KEY_LEFT: nn_editbuf_setpos(editBuf, editBuf->pos - 1); update = TRUE; break; |
923 case KEY_RIGHT: nn_editbuf_setpos(editBuf, editBuf->pos + 1); update = TRUE; break; | 951 case KEY_RIGHT: nn_editbuf_setpos(editBuf, editBuf->pos + 1); update = TRUE; break; |
924 | 952 |
927 nn_editbuf_delete(editBuf, editBuf->pos - 1); | 955 nn_editbuf_delete(editBuf, editBuf->pos - 1); |
928 nn_editbuf_setpos(editBuf, editBuf->pos - 1); | 956 nn_editbuf_setpos(editBuf, editBuf->pos - 1); |
929 update = TRUE; | 957 update = TRUE; |
930 break; | 958 break; |
931 | 959 |
932 case 0x14a: | 960 case 0x14a: /* Delete */ |
933 /* Delete */ | |
934 nn_editbuf_delete(editBuf, editBuf->pos); | 961 nn_editbuf_delete(editBuf, editBuf->pos); |
935 update = TRUE; | 962 update = TRUE; |
936 break; | 963 break; |
937 | 964 |
938 case 0x0c: | 965 |
939 /* ctrl+l */ | 966 case 0x109: /* F1 = Toggle insert / overwrite mode */ |
967 insertMode = !insertMode; | |
968 update = TRUE; | |
969 break; | |
970 | |
971 case 0x10a: /* F2 = Clear editbuffer */ | |
972 nn_editbuf_clear(editBuf); | |
973 update = TRUE; | |
974 break; | |
975 | |
976 case 0x10c: /* F3 = Ignore mode */ | |
977 ignoreMode = !ignoreMode; | |
978 printMsg("Ignore mode = %s\n", ignoreMode ? "ON" : "OFF"); | |
979 break; | |
980 | |
981 case 0x111: /* F9 = Quit */ | |
982 printMsg("Quitting per user request.\n"); | |
983 exitProg = TRUE; | |
984 break; | |
985 | |
986 case 0x110: /* F8 = switch between PRV */ | |
987 if (setPrvMode) | |
988 setPrvMode = FALSE; | |
989 else { | |
990 if (setTarget != NULL) | |
991 setPrvMode = TRUE; | |
992 } | |
993 update = TRUE; | |
994 break; | |
995 | |
996 case 0x09: /* Tab = complete username */ | |
997 { | |
998 ssize_t pos = editBuf->pos; | |
999 while (pos > 0 && !isspace((int) editBuf->data[pos - 1])) | |
1000 pos--; | |
1001 | |
1002 if (!isspace(editBuf->data[pos])) { | |
1003 char *str = nn_editbuf_get_string(editBuf, pos, editBuf->pos); | |
1004 if (str) { | |
1005 static char *c_prev = NULL; | |
1006 nn_user_t *c_curr = nn_user_match(nnUsers, str, c_prev); | |
1007 th_free(c_prev); | |
1008 c_prev = NULL; | |
1009 | |
1010 if (c_curr) { | |
1011 c_prev = th_strdup(c_curr->name); | |
1012 printMsg("Lol: %s\n", c_curr->name); | |
1013 } | |
1014 | |
1015 } | |
1016 } | |
1017 } | |
1018 break; | |
1019 | |
1020 case 0x0c: /* Ctrl + L */ | |
940 redrawwin(mainWin); | 1021 redrawwin(mainWin); |
941 redrawwin(statusWin); | 1022 redrawwin(statusWin); |
942 redrawwin(editWin); | 1023 redrawwin(editWin); |
943 break; | 1024 break; |
944 | 1025 |
989 | 1070 |
990 } | 1071 } |
991 | 1072 |
992 /* Shutdown */ | 1073 /* Shutdown */ |
993 err_exit: | 1074 err_exit: |
1075 nn_userhash_free(nnUsers); | |
1076 | |
994 nn_editbuf_free(editBuf); | 1077 nn_editbuf_free(editBuf); |
995 for (histPos = 0; histPos <= SET_MAX_HISTORY; histPos++) | 1078 for (histPos = 0; histPos <= SET_MAX_HISTORY; histPos++) |
996 nn_editbuf_free(histBuf[histPos]); | 1079 nn_editbuf_free(histBuf[histPos]); |
997 | 1080 |
998 if (cursesInit) { | 1081 if (cursesInit) { |