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) {