Mercurial > hg > nnchat
comparison main.c @ 419:d015ecbd231d
Use C99 style comments, too.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 24 May 2012 07:37:36 +0300 |
parents | 8ca09a6cca09 |
children | 4b7cd24dc943 |
comparison
equal
deleted
inserted
replaced
418:8ca09a6cca09 | 419:d015ecbd231d |
---|---|
8 #include "th_args.h" | 8 #include "th_args.h" |
9 #include "th_config.h" | 9 #include "th_config.h" |
10 #include <errno.h> | 10 #include <errno.h> |
11 #include <time.h> | 11 #include <time.h> |
12 #ifdef __WIN32 | 12 #ifdef __WIN32 |
13 /* Undefine because both windows.h and curses.h #define it */ | 13 // Undefine because both windows.h and curses.h #define it |
14 #undef MOUSE_MOVED | 14 #undef MOUSE_MOVED |
15 #include <shlwapi.h> | 15 #include <shlwapi.h> |
16 #else | 16 #else |
17 #include <sys/wait.h> | 17 #include <sys/wait.h> |
18 #endif | 18 #endif |
32 #define SET_DELAY (5) | 32 #define SET_DELAY (5) |
33 #endif | 33 #endif |
34 | 34 |
35 #define SET_NICK_SEPARATOR ':' | 35 #define SET_NICK_SEPARATOR ':' |
36 | 36 |
37 #define SET_MAX_HISTORY (16) /* Command history length */ | 37 #define SET_MAX_HISTORY (16) // Command history length |
38 #define SET_KEEPALIVE (15*60) /* Ping/keepalive period in seconds */ | 38 #define SET_KEEPALIVE (15*60) // Ping/keepalive period in seconds |
39 #define SET_MAX_WINDOWS (32) | 39 #define SET_MAX_WINDOWS (32) |
40 | 40 |
41 | 41 |
42 /* Options | 42 /* Options |
43 */ | 43 */ |
468 BOOL updateMainWin(BOOL force) | 468 BOOL updateMainWin(BOOL force) |
469 { | 469 { |
470 int h, offs; | 470 int h, offs; |
471 qringbuf_t *buf; | 471 qringbuf_t *buf; |
472 | 472 |
473 /* Check pointers */ | 473 // Check pointers |
474 if (mainWin == NULL || currWin == NULL) | 474 if (mainWin == NULL || currWin == NULL) |
475 return FALSE; | 475 return FALSE; |
476 | 476 |
477 /* Check if update is forced or if the window is dirty */ | 477 // Check if update is forced or if the window is dirty |
478 if (!force && !currWin->dirty) | 478 if (!force && !currWin->dirty) |
479 return FALSE; | 479 return FALSE; |
480 | 480 |
481 /* Compute how many lines from backbuffer fit on the screen */ | 481 // Compute how many lines from backbuffer fit on the screen |
482 buf = currWin->data; | 482 buf = currWin->data; |
483 h = getmaxy(mainWin); | 483 h = getmaxy(mainWin); |
484 | 484 |
485 /* Clear and redraw window */ | 485 // Clear and redraw window |
486 werase(mainWin); | 486 werase(mainWin); |
487 scrollok(mainWin, 1); | 487 scrollok(mainWin, 1); |
488 for (offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size; offs++) | 488 for (offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size; offs++) |
489 { | 489 { |
490 if (buf->data[offs] != NULL) | 490 if (buf->data[offs] != NULL) |
641 int nnproto_parse_user(nn_conn_t *conn) | 641 int nnproto_parse_user(nn_conn_t *conn) |
642 { | 642 { |
643 BOOL isMine, isIgnored = FALSE; | 643 BOOL isMine, isIgnored = FALSE; |
644 char *name, *msg, *t; | 644 char *name, *msg, *t; |
645 | 645 |
646 /* Find start of the message */ | 646 // Find start of the message |
647 name = conn->ptr; | 647 name = conn->ptr; |
648 t = nn_conn_buf_strstr(conn, "</USER><MESSAGE>"); | 648 t = nn_conn_buf_strstr(conn, "</USER><MESSAGE>"); |
649 if (!t) return 1; | 649 if (!t) return 1; |
650 *t = 0; | 650 *t = 0; |
651 msg = conn->ptr; | 651 msg = conn->ptr; |
652 | 652 |
653 /* Find end of the message */ | 653 // Find end of the message |
654 t = nn_conn_buf_strstr(conn, "</MESSAGE>"); | 654 t = nn_conn_buf_strstr(conn, "</MESSAGE>"); |
655 if (!t) return 3; | 655 if (!t) return 3; |
656 *t = 0; | 656 *t = 0; |
657 | 657 |
658 /* Decode message string */ | 658 // Decode message string |
659 msg = nn_decode_str1(msg); | 659 msg = nn_decode_str1(msg); |
660 if (!msg) return -1; | 660 if (!msg) return -1; |
661 | 661 |
662 /* Decode username */ | 662 // Decode username |
663 name = nn_decode_str1(name); | 663 name = nn_decode_str1(name); |
664 if (!name) | 664 if (!name) |
665 { | 665 { |
666 th_free(msg); | 666 th_free(msg); |
667 return -2; | 667 return -2; |
671 * that it is not our OWN username! | 671 * that it is not our OWN username! |
672 */ | 672 */ |
673 isMine = strcmp(name, optUserName) == 0; | 673 isMine = strcmp(name, optUserName) == 0; |
674 isIgnored = setIgnoreMode && !isMine && checkIgnoreList(name); | 674 isIgnored = setIgnoreMode && !isMine && checkIgnoreList(name); |
675 | 675 |
676 /* Is it a special control message? */ | 676 // Is it a special control message? |
677 if (*msg == '/') | 677 if (*msg == '/') |
678 { | 678 { |
679 /* Ignore room join/leave messages */ | 679 // Ignore room join/leave messages |
680 if (!optDebug && (strstr(msg, "left the room") || strstr(msg, "joined the room from"))) | 680 if (!optDebug && (strstr(msg, "left the room") || strstr(msg, "joined the room from"))) |
681 goto done; | 681 goto done; |
682 | 682 |
683 t = nn_strip_tags(msg + 1); | 683 t = nn_strip_tags(msg + 1); |
684 if (!strncmp(t, "BPRV ", 5)) | 684 if (!strncmp(t, "BPRV ", 5)) |
719 th_free(in_name); | 719 th_free(in_name); |
720 th_free(h); | 720 th_free(h); |
721 } | 721 } |
722 else | 722 else |
723 { | 723 { |
724 /* It's an action (/me) */ | 724 // It's an action (/me) |
725 char *h = nn_decode_str2(t); | 725 char *h = nn_decode_str2(t); |
726 printMsgF(NULL, isIgnored ? LOG_FILE : (LOG_WINDOW | LOG_FILE), | 726 printMsgF(NULL, isIgnored ? LOG_FILE : (LOG_WINDOW | LOG_FILE), |
727 "½9½* %s½0½\n", h); | 727 "½9½* %s½0½\n", h); |
728 th_free(h); | 728 th_free(h); |
729 } | 729 } |
730 th_free(t); | 730 th_free(t); |
731 } | 731 } |
732 else | 732 else |
733 { | 733 { |
734 /* It's a normal message */ | 734 // It's a normal message |
735 char *h; | 735 char *h; |
736 t = nn_strip_tags(msg); | 736 t = nn_strip_tags(msg); |
737 h = nn_decode_str2(t); | 737 h = nn_decode_str2(t); |
738 printMsgF(NULL, isIgnored ? LOG_FILE : (LOG_WINDOW | LOG_FILE), | 738 printMsgF(NULL, isIgnored ? LOG_FILE : (LOG_WINDOW | LOG_FILE), |
739 "½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, name, h); | 739 "½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, name, h); |
885 int nn_handle_input(nn_conn_t *conn, char *buf, size_t bufLen) | 885 int nn_handle_input(nn_conn_t *conn, char *buf, size_t bufLen) |
886 { | 886 { |
887 char *tmpStr, tmpBuf[4096]; | 887 char *tmpStr, tmpBuf[4096]; |
888 BOOL result; | 888 BOOL result; |
889 | 889 |
890 /* Trim right */ | 890 // Trim right |
891 bufLen--; | 891 bufLen--; |
892 buf[bufLen--] = 0; | 892 buf[bufLen--] = 0; |
893 while (bufLen > 0 && th_isspace(buf[bufLen])) | 893 while (bufLen > 0 && th_isspace(buf[bufLen])) |
894 buf[bufLen--] = 0; | 894 buf[bufLen--] = 0; |
895 | 895 |
896 /* Decode completed usernames */ | 896 // Decode completed usernames |
897 nn_username_decode(buf); | 897 nn_username_decode(buf); |
898 | 898 |
899 /* Check for special user commands */ | 899 // Check for special user commands |
900 if (*buf == 0) | 900 if (*buf == 0) |
901 { | 901 { |
902 return 1; | 902 return 1; |
903 } | 903 } |
904 else if (!th_strncasecmp(buf, "/color ", 7)) | 904 else if (!th_strncasecmp(buf, "/color ", 7)) |
905 { | 905 { |
906 /* Change color */ | 906 // Change color |
907 int tmpInt; | 907 int tmpInt; |
908 if ((tmpInt = th_get_hex_triplet(str_trim_left(buf + 7))) < 0) | 908 if ((tmpInt = th_get_hex_triplet(str_trim_left(buf + 7))) < 0) |
909 { | 909 { |
910 printMsgQ(currWin, "Invalid color value '%s'\n", buf+7); | 910 printMsgQ(currWin, "Invalid color value '%s'\n", buf+7); |
911 return 1; | 911 return 1; |
918 else if (!th_strncasecmp(buf, "/ignore", 7)) | 918 else if (!th_strncasecmp(buf, "/ignore", 7)) |
919 { | 919 { |
920 char *name = str_trim_left(buf + 7); | 920 char *name = str_trim_left(buf + 7); |
921 if (strlen(name) > 0) | 921 if (strlen(name) > 0) |
922 { | 922 { |
923 /* Add or remove someone to/from ignore */ | 923 // Add or remove someone to/from ignore |
924 qlist_t *user = th_llist_find_func(setIgnoreList, name, compareUsername); | 924 qlist_t *user = th_llist_find_func(setIgnoreList, name, compareUsername); |
925 if (user != NULL) | 925 if (user != NULL) |
926 { | 926 { |
927 printMsgQ(currWin, "Removed user '%s' from ignore.\n", name); | 927 printMsgQ(currWin, "Removed user '%s' from ignore.\n", name); |
928 th_llist_delete_node(&setIgnoreList, user); | 928 th_llist_delete_node(&setIgnoreList, user); |
933 th_llist_append(&setIgnoreList, th_strdup(name)); | 933 th_llist_append(&setIgnoreList, th_strdup(name)); |
934 } | 934 } |
935 } | 935 } |
936 else | 936 else |
937 { | 937 { |
938 /* Just list whomever is in ignore now */ | 938 // Just list whomever is in ignore now |
939 qlist_t *user = setIgnoreList; | 939 qlist_t *user = setIgnoreList; |
940 ssize_t nuser = th_llist_length(setIgnoreList); | 940 ssize_t nuser = th_llist_length(setIgnoreList); |
941 char *result = th_strdup_printf("Users ignored (%d): ", nuser); | 941 char *result = th_strdup_printf("Users ignored (%d): ", nuser); |
942 while (user != NULL) | 942 while (user != NULL) |
943 { | 943 { |
977 } | 977 } |
978 return 0; | 978 return 0; |
979 } | 979 } |
980 else if (!th_strncasecmp(buf, "/win", 4)) | 980 else if (!th_strncasecmp(buf, "/win", 4)) |
981 { | 981 { |
982 /* Change color */ | 982 // Change color |
983 char *tmp = str_trim_left(buf + 4); | 983 char *tmp = str_trim_left(buf + 4); |
984 if (strlen(tmp) > 0) | 984 if (strlen(tmp) > 0) |
985 { | 985 { |
986 int val = atoi(tmp); | 986 int val = atoi(tmp); |
987 if (val >= 1 && val < SET_MAX_WINDOWS) | 987 if (val >= 1 && val < SET_MAX_WINDOWS) |
1028 } | 1028 } |
1029 return 0; | 1029 return 0; |
1030 } | 1030 } |
1031 else if (!th_strncasecmp(buf, "/save", 5)) | 1031 else if (!th_strncasecmp(buf, "/save", 5)) |
1032 { | 1032 { |
1033 /* Save configuration */ | 1033 // Save configuration |
1034 FILE *cfgfile = fopen(setConfigFile, "w"); | 1034 FILE *cfgfile = fopen(setConfigFile, "w"); |
1035 if (cfgfile == NULL) | 1035 if (cfgfile == NULL) |
1036 { | 1036 { |
1037 printMsgQ(currWin, "Could not create configuration to file '%s': %s\n", | 1037 printMsgQ(currWin, "Could not create configuration to file '%s': %s\n", |
1038 setConfigFile, strerror(errno)); | 1038 setConfigFile, strerror(errno)); |
1045 fclose(cfgfile); | 1045 fclose(cfgfile); |
1046 return 0; | 1046 return 0; |
1047 } | 1047 } |
1048 else if (!th_strncasecmp(buf, "/w ", 3)) | 1048 else if (!th_strncasecmp(buf, "/w ", 3)) |
1049 { | 1049 { |
1050 /* Open given username's profile via firefox in a new tab */ | 1050 // Open given username's profile via firefox in a new tab |
1051 char *name = str_trim_left(buf + 3); | 1051 char *name = str_trim_left(buf + 3); |
1052 | 1052 |
1053 printMsg(currWin, "Opening profile for: '%s'\n", name); | 1053 printMsg(currWin, "Opening profile for: '%s'\n", name); |
1054 | 1054 |
1055 tmpStr = nn_encode_str1(name); | 1055 tmpStr = nn_encode_str1(name); |
1094 #endif | 1094 #endif |
1095 return 0; | 1095 return 0; |
1096 } | 1096 } |
1097 else if (!th_strncasecmp(buf, "/who", 4)) | 1097 else if (!th_strncasecmp(buf, "/who", 4)) |
1098 { | 1098 { |
1099 /* Alias /who to /listallusers */ | 1099 // Alias /who to /listallusers |
1100 snprintf(tmpBuf, sizeof(tmpBuf), "/listallusers"); | 1100 snprintf(tmpBuf, sizeof(tmpBuf), "/listallusers"); |
1101 buf = tmpBuf; | 1101 buf = tmpBuf; |
1102 } | 1102 } |
1103 | 1103 |
1104 if (currWin != chatWindows[0]) | 1104 if (currWin != chatWindows[0]) |
1113 printMsgQ(NULL, "No target set, exiting prv mode.\n"); | 1113 printMsgQ(NULL, "No target set, exiting prv mode.\n"); |
1114 return 1; | 1114 return 1; |
1115 } | 1115 } |
1116 } | 1116 } |
1117 | 1117 |
1118 /* Send double-encoded */ | 1118 // Send double-encoded |
1119 tmpStr = nn_dblencode_str(nn_username_decode(buf)); | 1119 tmpStr = nn_dblencode_str(nn_username_decode(buf)); |
1120 if (tmpStr == 0) return -2; | 1120 if (tmpStr == 0) return -2; |
1121 result = nn_conn_send_msg(conn, optUserNameEnc, "%s", tmpStr); | 1121 result = nn_conn_send_msg(conn, optUserNameEnc, "%s", tmpStr); |
1122 th_free(tmpStr); | 1122 th_free(tmpStr); |
1123 | 1123 |
1166 BOOL again = FALSE, hasSeparator = FALSE, newPattern = FALSE, hasSpace = FALSE; | 1166 BOOL again = FALSE, hasSeparator = FALSE, newPattern = FALSE, hasSpace = FALSE; |
1167 char *str = buf->data; | 1167 char *str = buf->data; |
1168 int mode = 0; | 1168 int mode = 0; |
1169 ssize_t endPos, startPos = buf->pos; | 1169 ssize_t endPos, startPos = buf->pos; |
1170 | 1170 |
1171 /* previous word */ | 1171 // previous word |
1172 if (startPos >= 2 && str[startPos - 1] == ' ' && str[startPos - 2] != ' ') | 1172 if (startPos >= 2 && str[startPos - 1] == ' ' && str[startPos - 2] != ' ') |
1173 { | 1173 { |
1174 startPos -= 2; | 1174 startPos -= 2; |
1175 endPos = startPos; | 1175 endPos = startPos; |
1176 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; | 1176 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; |
1177 mode = 1; | 1177 mode = 1; |
1178 } | 1178 } |
1179 else | 1179 else |
1180 /* middle of a word, new pattern */ | 1180 // middle of a word, new pattern |
1181 if (startPos < buf->len && str[startPos] != ' ') | 1181 if (startPos < buf->len && str[startPos] != ' ') |
1182 { | 1182 { |
1183 endPos = startPos; | 1183 endPos = startPos; |
1184 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; | 1184 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; |
1185 while (endPos < buf->len - 1 && str[endPos + 1] != ' ') endPos++; | 1185 while (endPos < buf->len - 1 && str[endPos + 1] != ' ') endPos++; |
1186 newPattern = TRUE; | 1186 newPattern = TRUE; |
1187 mode = 2; | 1187 mode = 2; |
1188 } | 1188 } |
1189 else | 1189 else |
1190 /* previous word, new pattern */ | 1190 // previous word, new pattern |
1191 if (startPos >= 1 && str[startPos - 1] != ' ') | 1191 if (startPos >= 1 && str[startPos - 1] != ' ') |
1192 { | 1192 { |
1193 startPos -= 1; | 1193 startPos -= 1; |
1194 endPos = startPos; | 1194 endPos = startPos; |
1195 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; | 1195 while (startPos > 0 && str[startPos - 1] != ' ') startPos--; |
1220 if (buf->pos <= buf->len && str[buf->pos] == ' ') | 1220 if (buf->pos <= buf->len && str[buf->pos] == ' ') |
1221 hasSpace = TRUE; | 1221 hasSpace = TRUE; |
1222 | 1222 |
1223 if (newPattern) | 1223 if (newPattern) |
1224 { | 1224 { |
1225 /* Get pattern, check if it matches previous pattern and set 'again' flag */ | 1225 // Get pattern, check if it matches previous pattern and set 'again' flag |
1226 char *npattern = nn_editbuf_get_string(buf, startPos, endPos); | 1226 char *npattern = nn_editbuf_get_string(buf, startPos, endPos); |
1227 if (pattern && npattern && th_strcasecmp(npattern, pattern) == 0) | 1227 if (pattern && npattern && th_strcasecmp(npattern, pattern) == 0) |
1228 again = TRUE; | 1228 again = TRUE; |
1229 | 1229 |
1230 th_free(pattern); | 1230 th_free(pattern); |
1421 cfgitem_t *tmpcfg; | 1421 cfgitem_t *tmpcfg; |
1422 char *homeDir = NULL; | 1422 char *homeDir = NULL; |
1423 | 1423 |
1424 memset(histBuf, 0, sizeof(histBuf)); | 1424 memset(histBuf, 0, sizeof(histBuf)); |
1425 | 1425 |
1426 /* Initialize */ | 1426 // Initialize |
1427 th_init("NNChat", "Newbie Nudes chat client", NN_VERSION, | 1427 th_init("NNChat", "Newbie Nudes chat client", NN_VERSION, |
1428 "Written and designed by Anonymous Finnish Guy (C) 2008-2012", | 1428 "Written and designed by Anonymous Finnish Guy (C) 2008-2012", |
1429 "This software is freeware, use and distribute as you wish."); | 1429 "This software is freeware, use and distribute as you wish."); |
1430 th_verbosityLevel = 0; | 1430 th_verbosityLevel = 0; |
1431 | 1431 |
1432 /* Read configuration file */ | 1432 // Read configuration file |
1433 tmpcfg = NULL; | 1433 tmpcfg = NULL; |
1434 th_cfg_add_comment(&tmpcfg, "General settings"); | 1434 th_cfg_add_comment(&tmpcfg, "General settings"); |
1435 th_cfg_add_string(&tmpcfg, "username", &optUserName, NULL); | 1435 th_cfg_add_string(&tmpcfg, "username", &optUserName, NULL); |
1436 th_cfg_add_string(&tmpcfg, "password", &optPassword, NULL); | 1436 th_cfg_add_string(&tmpcfg, "password", &optPassword, NULL); |
1437 | 1437 |
1509 | 1509 |
1510 setBrowser = getenv("BROWSER"); | 1510 setBrowser = getenv("BROWSER"); |
1511 if (setBrowser == NULL) | 1511 if (setBrowser == NULL) |
1512 setBrowser = "firefox"; | 1512 setBrowser = "firefox"; |
1513 | 1513 |
1514 /* Parse command line arguments */ | 1514 // Parse command line arguments |
1515 argsOK = th_args_process(argc, argv, optList, optListN, | 1515 argsOK = th_args_process(argc, argv, optList, optListN, |
1516 argHandleOpt, argHandleFile, FALSE); | 1516 argHandleOpt, argHandleFile, FALSE); |
1517 | 1517 |
1518 if (optUserNameCmd != NULL) | 1518 if (optUserNameCmd != NULL) |
1519 { | 1519 { |
1522 } | 1522 } |
1523 | 1523 |
1524 if (!argsOK) | 1524 if (!argsOK) |
1525 return -2; | 1525 return -2; |
1526 | 1526 |
1527 /* Allocate userhash */ | 1527 // Allocate userhash |
1528 if ((nnUsers = nn_userhash_new()) == NULL) | 1528 if ((nnUsers = nn_userhash_new()) == NULL) |
1529 { | 1529 { |
1530 THERR("Could not allocate userhash. Fatal error.\n"); | 1530 THERR("Could not allocate userhash. Fatal error.\n"); |
1531 return -105; | 1531 return -105; |
1532 } | 1532 } |
1533 | 1533 |
1534 /* If no idle messages are set, add default */ | 1534 // If no idle messages are set, add default |
1535 if (setIdleMessages == NULL) | 1535 if (setIdleMessages == NULL) |
1536 { | 1536 { |
1537 th_llist_append(&setIdleMessages, th_strdup(".")); | 1537 th_llist_append(&setIdleMessages, th_strdup(".")); |
1538 } | 1538 } |
1539 | 1539 |
1540 /* Open logfile */ | 1540 // Open logfile |
1541 logFileOpen(); | 1541 logFileOpen(); |
1542 | 1542 |
1543 /* Initialize network */ | 1543 // Initialize network |
1544 if (!nn_network_init()) | 1544 if (!nn_network_init()) |
1545 { | 1545 { |
1546 THERR("Could not initialize network subsystem.\n"); | 1546 THERR("Could not initialize network subsystem.\n"); |
1547 goto err_exit; | 1547 goto err_exit; |
1548 } | 1548 } |
1549 else | 1549 else |
1550 networkInit = TRUE; | 1550 networkInit = TRUE; |
1551 | 1551 |
1552 /* Initialize NCurses */ | 1552 // Initialize NCurses |
1553 if (!optDaemon) | 1553 if (!optDaemon) |
1554 { | 1554 { |
1555 if (LINES < 0 || LINES > 1000) LINES = 24; | 1555 if (LINES < 0 || LINES > 1000) LINES = 24; |
1556 if (COLS < 0 || COLS > 1000) COLS = 80; | 1556 if (COLS < 0 || COLS > 1000) COLS = 80; |
1557 initscr(); | 1557 initscr(); |
1597 chatWindows[0] = nn_window_new(NULL); | 1597 chatWindows[0] = nn_window_new(NULL); |
1598 currWin = chatWindows[0]; | 1598 currWin = chatWindows[0]; |
1599 updateStatus(); | 1599 updateStatus(); |
1600 } | 1600 } |
1601 | 1601 |
1602 /* Check if we have username and password */ | 1602 // Check if we have username and password |
1603 if (cursesInit && (optUserName == NULL || optPassword == NULL)) | 1603 if (cursesInit && (optUserName == NULL || optPassword == NULL)) |
1604 { | 1604 { |
1605 printWin(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n"); | 1605 printWin(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n"); |
1606 optUserName = promptRequester(editWin, "NN username: ", FALSE); | 1606 optUserName = promptRequester(editWin, "NN username: ", FALSE); |
1607 optPassword = promptRequester(editWin, "NN password: ", TRUE); | 1607 optPassword = promptRequester(editWin, "NN password: ", TRUE); |
1611 { | 1611 { |
1612 errorMsg("Username and/or password not specified.\n"); | 1612 errorMsg("Username and/or password not specified.\n"); |
1613 goto err_exit; | 1613 goto err_exit; |
1614 } | 1614 } |
1615 | 1615 |
1616 /* Create a connection */ | 1616 // Create a connection |
1617 conn = nn_conn_new(errorFunc, messageFunc); | 1617 conn = nn_conn_new(errorFunc, messageFunc); |
1618 if (conn == NULL) | 1618 if (conn == NULL) |
1619 { | 1619 { |
1620 errorMsg("Could not create connection structure.\n"); | 1620 errorMsg("Could not create connection structure.\n"); |
1621 goto err_exit; | 1621 goto err_exit; |
1622 } | 1622 } |
1623 | 1623 |
1624 /* Are we using a proxy? */ | 1624 // Are we using a proxy? |
1625 if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL) | 1625 if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL) |
1626 { | 1626 { |
1627 if (nn_conn_set_proxy(conn, optProxyType, optProxyPort, optProxyServer) != 0) | 1627 if (nn_conn_set_proxy(conn, optProxyType, optProxyPort, optProxyServer) != 0) |
1628 { | 1628 { |
1629 errorMsg("Error setting proxy information.\n"); | 1629 errorMsg("Error setting proxy information.\n"); |
1630 goto err_exit; | 1630 goto err_exit; |
1631 } | 1631 } |
1632 } | 1632 } |
1633 | 1633 |
1634 /* Okay ... */ | 1634 // Okay ... |
1635 printMsg(currWin, "Trying to resolve host '%s' ...\n", optServer); | 1635 printMsg(currWin, "Trying to resolve host '%s' ...\n", optServer); |
1636 conn->host = th_strdup(optServer); | 1636 conn->host = th_strdup(optServer); |
1637 conn->hst = nn_resolve_host(conn, optServer); | 1637 conn->hst = nn_resolve_host(conn, optServer); |
1638 if (conn->hst == NULL) | 1638 if (conn->hst == NULL) |
1639 { | 1639 { |
1670 } | 1670 } |
1671 } | 1671 } |
1672 nn_conn_close(conn); | 1672 nn_conn_close(conn); |
1673 #endif | 1673 #endif |
1674 | 1674 |
1675 /* Okay, now do the proper connection ... */ | 1675 // Okay, now do the proper connection ... |
1676 if (nn_conn_open(conn, optPort, NULL) != 0) | 1676 if (nn_conn_open(conn, optPort, NULL) != 0) |
1677 { | 1677 { |
1678 errorMsg("Main connection setup failed!\n"); | 1678 errorMsg("Main connection setup failed!\n"); |
1679 goto err_exit; | 1679 goto err_exit; |
1680 } | 1680 } |
1681 | 1681 |
1682 /* Send login command */ | 1682 // Send login command |
1683 optUserNameEnc = nn_dblencode_str(optUserName); | 1683 optUserNameEnc = nn_dblencode_str(optUserName); |
1684 tmpStr = nn_dblencode_str(optSite); | 1684 tmpStr = nn_dblencode_str(optSite); |
1685 nn_conn_send_msg(conn, optUserNameEnc, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword); | 1685 nn_conn_send_msg(conn, optUserNameEnc, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword); |
1686 th_free(tmpStr); | 1686 th_free(tmpStr); |
1687 | 1687 |
1688 /* Initialize random numbers */ | 1688 // Initialize random numbers |
1689 prevTime = time(NULL); | 1689 prevTime = time(NULL); |
1690 srandom((int) prevTime); | 1690 srandom((int) prevTime); |
1691 | 1691 |
1692 if (cursesInit) | 1692 if (cursesInit) |
1693 { | 1693 { |
1694 /* Initialize rest of interactive UI code */ | 1694 // Initialize rest of interactive UI code |
1695 nn_editbuf_clear(editBuf); | 1695 nn_editbuf_clear(editBuf); |
1696 | 1696 |
1697 /* First update of screen */ | 1697 // First update of screen |
1698 printEditBuf(editBuf); | 1698 printEditBuf(editBuf); |
1699 updateStatus(); | 1699 updateStatus(); |
1700 | 1700 |
1701 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); | 1701 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); |
1702 printMsg(NULL, "%s\n", th_prog_author); | 1702 printMsg(NULL, "%s\n", th_prog_author); |
1703 printMsg(NULL, "%s\n", th_prog_license); | 1703 printMsg(NULL, "%s\n", th_prog_license); |
1704 } | 1704 } |
1705 | 1705 |
1706 /* Enter mainloop */ | 1706 // Enter mainloop |
1707 nn_conn_reset(conn); | 1707 nn_conn_reset(conn); |
1708 while (!isError && !exitProg) | 1708 while (!isError && !exitProg) |
1709 { | 1709 { |
1710 nn_conn_reset(conn); | 1710 nn_conn_reset(conn); |
1711 do { | 1711 do { |
1713 if (cres == 0 && *(conn->in_ptr - 1) == 0) | 1713 if (cres == 0 && *(conn->in_ptr - 1) == 0) |
1714 { | 1714 { |
1715 int result = nn_parse_protocol(conn); | 1715 int result = nn_parse_protocol(conn); |
1716 if (result > 0) | 1716 if (result > 0) |
1717 { | 1717 { |
1718 /* Couldn't handle the message for some reason */ | 1718 // Couldn't handle the message for some reason |
1719 printMsg(currWin, "Could not handle: %s\n", conn->ptr); | 1719 printMsg(currWin, "Could not handle: %s\n", conn->ptr); |
1720 } | 1720 } |
1721 else if (result < 0) | 1721 else if (result < 0) |
1722 { | 1722 { |
1723 /* Fatal error, quit */ | 1723 // Fatal error, quit |
1724 errorMsg("Fatal error with message: %s\n", conn->ptr); | 1724 errorMsg("Fatal error with message: %s\n", conn->ptr); |
1725 isError = TRUE; | 1725 isError = TRUE; |
1726 } | 1726 } |
1727 } | 1727 } |
1728 else if (cres < 0) | 1728 else if (cres < 0) |
1733 while (conn->total_bytes > 0 && !isError); | 1733 while (conn->total_bytes > 0 && !isError); |
1734 | 1734 |
1735 if (!nn_conn_check(conn)) | 1735 if (!nn_conn_check(conn)) |
1736 isError = TRUE; | 1736 isError = TRUE; |
1737 | 1737 |
1738 /* Handle user input */ | 1738 // Handle user input |
1739 if (cursesInit) | 1739 if (cursesInit) |
1740 { | 1740 { |
1741 int c, cnt = 0; | 1741 int c, cnt = 0; |
1742 BOOL update = FALSE, updateMain = FALSE; | 1742 BOOL update = FALSE, updateMain = FALSE; |
1743 | 1743 |
1744 /* Handle several buffered keypresses at once */ | 1744 // Handle several buffered keypresses at once |
1745 do | 1745 do |
1746 { | 1746 { |
1747 c = wgetch(stdscr); | 1747 c = wgetch(stdscr); |
1748 | 1748 |
1749 /* Handle various problematic cases where terminal | 1749 /* Handle various problematic cases where terminal |
1750 * keycodes do not get properly translated by curses | 1750 * keycodes do not get properly translated by curses |
1751 */ | 1751 */ |
1752 if (c == 0x1b) | 1752 if (c == 0x1b) |
1753 { | 1753 { |
1754 /* ^[O */ | 1754 // ^[O |
1755 c = wgetch(stdscr); | 1755 c = wgetch(stdscr); |
1756 if (c == 'O') | 1756 if (c == 'O') |
1757 { | 1757 { |
1758 c = wgetch(stdscr); | 1758 c = wgetch(stdscr); |
1759 switch (c) | 1759 switch (c) |
1768 if (optDebug) | 1768 if (optDebug) |
1769 printMsg(currWin, "Unhandled ESC-O key sequence 0x%02x\n", c); | 1769 printMsg(currWin, "Unhandled ESC-O key sequence 0x%02x\n", c); |
1770 break; | 1770 break; |
1771 } | 1771 } |
1772 } | 1772 } |
1773 /* ^[[ */ | 1773 // ^[[ |
1774 else if (c == '[') | 1774 else if (c == '[') |
1775 { | 1775 { |
1776 c = wgetch(stdscr); | 1776 c = wgetch(stdscr); |
1777 switch (c) | 1777 switch (c) |
1778 { | 1778 { |
1809 if (optDebug) | 1809 if (optDebug) |
1810 printMsg(currWin, "Unhandled ESC-[*~ key sequence 0x%02x\n", c); | 1810 printMsg(currWin, "Unhandled ESC-[*~ key sequence 0x%02x\n", c); |
1811 c = ERR; | 1811 c = ERR; |
1812 break; | 1812 break; |
1813 } | 1813 } |
1814 /* Get the trailing ~ */ | 1814 // Get the trailing ~ |
1815 if (c != ERR) | 1815 if (c != ERR) |
1816 wgetch(stdscr); | 1816 wgetch(stdscr); |
1817 } | 1817 } |
1818 if (c >= 0x31 && c <= 0x39) | 1818 if (c >= 0x31 && c <= 0x39) |
1819 { | 1819 { |
1820 /* Chat window switching via Meta/Esc-[1..9] */ | 1820 // Chat window switching via Meta/Esc-[1..9] |
1821 int win = c - 0x31; | 1821 int win = c - 0x31; |
1822 if (win < SET_MAX_WINDOWS && chatWindows[win] != NULL) | 1822 if (win < SET_MAX_WINDOWS && chatWindows[win] != NULL) |
1823 { | 1823 { |
1824 currWin = chatWindows[win]; | 1824 currWin = chatWindows[win]; |
1825 update = updateMain = TRUE; | 1825 update = updateMain = TRUE; |
1833 } | 1833 } |
1834 } | 1834 } |
1835 #if defined(__WIN32) && defined(PDCURSES) | 1835 #if defined(__WIN32) && defined(PDCURSES) |
1836 else if (c >= 0x198 && c <= 0x1a0) | 1836 else if (c >= 0x198 && c <= 0x1a0) |
1837 { | 1837 { |
1838 /* Chat window switching via Meta/Esc-[1..9] */ | 1838 // Chat window switching via Meta/Esc-[1..9] |
1839 int win = c - 0x198; | 1839 int win = c - 0x198; |
1840 if (win < SET_MAX_WINDOWS && chatWindows[win] != NULL) | 1840 if (win < SET_MAX_WINDOWS && chatWindows[win] != NULL) |
1841 { | 1841 { |
1842 currWin = chatWindows[win]; | 1842 currWin = chatWindows[win]; |
1843 update = updateMain = TRUE; | 1843 update = updateMain = TRUE; |
1864 #endif | 1864 #endif |
1865 | 1865 |
1866 case KEY_ENTER: | 1866 case KEY_ENTER: |
1867 case '\n': | 1867 case '\n': |
1868 case '\r': | 1868 case '\r': |
1869 /* Call the user input handler */ | 1869 // Call the user input handler |
1870 if (editBuf->len > 0) | 1870 if (editBuf->len > 0) |
1871 { | 1871 { |
1872 int result; | 1872 int result; |
1873 | 1873 |
1874 if (histMax > 0) | 1874 if (histMax > 0) |
1892 errorMsg("Fatal error handling user input: %s\n", editBuf->data); | 1892 errorMsg("Fatal error handling user input: %s\n", editBuf->data); |
1893 isError = TRUE; | 1893 isError = TRUE; |
1894 } | 1894 } |
1895 else | 1895 else |
1896 { | 1896 { |
1897 /* Update time value of last sent message for unidle timeouts */ | 1897 // Update time value of last sent message for unidle timeouts |
1898 prevTime = time(NULL); | 1898 prevTime = time(NULL); |
1899 } | 1899 } |
1900 | 1900 |
1901 updateMain = update = TRUE; | 1901 updateMain = update = TRUE; |
1902 } | 1902 } |
1903 break; | 1903 break; |
1904 | 1904 |
1905 case KEY_UP: /* Backwards in input history */ | 1905 case KEY_UP: // Backwards in input history |
1906 if (histPos == 0) | 1906 if (histPos == 0) |
1907 { | 1907 { |
1908 nn_editbuf_free(histBuf[0]); | 1908 nn_editbuf_free(histBuf[0]); |
1909 histBuf[0] = nn_editbuf_copy(editBuf); | 1909 histBuf[0] = nn_editbuf_copy(editBuf); |
1910 } | 1910 } |
1915 editBuf = nn_editbuf_copy(histBuf[histPos]); | 1915 editBuf = nn_editbuf_copy(histBuf[histPos]); |
1916 update = TRUE; | 1916 update = TRUE; |
1917 } | 1917 } |
1918 break; | 1918 break; |
1919 | 1919 |
1920 case KEY_DOWN: /* Forwards in input history */ | 1920 case KEY_DOWN: // Forwards in input history |
1921 if (histPos > 0) | 1921 if (histPos > 0) |
1922 { | 1922 { |
1923 histPos--; | 1923 histPos--; |
1924 nn_editbuf_free(editBuf); | 1924 nn_editbuf_free(editBuf); |
1925 editBuf = nn_editbuf_copy(histBuf[histPos]); | 1925 editBuf = nn_editbuf_copy(histBuf[histPos]); |
1926 update = TRUE; | 1926 update = TRUE; |
1927 } | 1927 } |
1928 break; | 1928 break; |
1929 | 1929 |
1930 case 0x204: /* ctrl+left arrow = Skip words left */ | 1930 case 0x204: // ctrl+left arrow = Skip words left |
1931 case 0x20b: | 1931 case 0x20b: |
1932 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) | 1932 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) |
1933 editBuf->pos--; | 1933 editBuf->pos--; |
1934 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) | 1934 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) |
1935 editBuf->pos--; | 1935 editBuf->pos--; |
1936 update = TRUE; | 1936 update = TRUE; |
1937 break; | 1937 break; |
1938 | 1938 |
1939 case 0x206: /* ctrl+right arrow = Skip words right */ | 1939 case 0x206: // ctrl+right arrow = Skip words right |
1940 case 0x210: | 1940 case 0x210: |
1941 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) | 1941 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) |
1942 editBuf->pos++; | 1942 editBuf->pos++; |
1943 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) | 1943 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) |
1944 editBuf->pos++; | 1944 editBuf->pos++; |
1968 nn_editbuf_delete(editBuf, editBuf->pos - 1); | 1968 nn_editbuf_delete(editBuf, editBuf->pos - 1); |
1969 nn_editbuf_setpos(editBuf, editBuf->pos - 1); | 1969 nn_editbuf_setpos(editBuf, editBuf->pos - 1); |
1970 update = TRUE; | 1970 update = TRUE; |
1971 break; | 1971 break; |
1972 | 1972 |
1973 case KEY_DC: /* Delete character */ | 1973 case KEY_DC: // Delete character |
1974 nn_editbuf_delete(editBuf, editBuf->pos); | 1974 nn_editbuf_delete(editBuf, editBuf->pos); |
1975 update = TRUE; | 1975 update = TRUE; |
1976 break; | 1976 break; |
1977 | 1977 |
1978 | 1978 |
1979 case KEY_IC: /* Ins = Toggle insert / overwrite mode */ | 1979 case KEY_IC: // Ins = Toggle insert / overwrite mode |
1980 insertMode = !insertMode; | 1980 insertMode = !insertMode; |
1981 update = TRUE; | 1981 update = TRUE; |
1982 break; | 1982 break; |
1983 | 1983 |
1984 case KEY_F(1): /* F1 = Print help */ | 1984 case KEY_F(1): // F1 = Print help |
1985 printHelp(); | 1985 printHelp(); |
1986 updateMain = TRUE; | 1986 updateMain = TRUE; |
1987 break; | 1987 break; |
1988 | 1988 |
1989 case KEY_F(2): /* F2 = Clear editbuffer */ | 1989 case KEY_F(2): // F2 = Clear editbuffer |
1990 nn_editbuf_clear(editBuf); | 1990 nn_editbuf_clear(editBuf); |
1991 update = TRUE; | 1991 update = TRUE; |
1992 break; | 1992 break; |
1993 | 1993 |
1994 case KEY_F(5): /* F5 = Ignore mode */ | 1994 case KEY_F(5): // F5 = Ignore mode |
1995 setIgnoreMode = !setIgnoreMode; | 1995 setIgnoreMode = !setIgnoreMode; |
1996 printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF"); | 1996 printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF"); |
1997 break; | 1997 break; |
1998 | 1998 |
1999 #if 0 | 1999 #if 0 |
2000 case KEY_F(8): /* F8 = Debug */ | 2000 case KEY_F(8): // F8 = Debug |
2001 optDebug = !optDebug; | 2001 optDebug = !optDebug; |
2002 update = TRUE; | 2002 update = TRUE; |
2003 break; | 2003 break; |
2004 #endif | 2004 #endif |
2005 | 2005 |
2006 case 0x03: /* ^C = quit */ | 2006 case 0x03: // ^C = quit |
2007 case KEY_F(9): /* F9 = Quit */ | 2007 case KEY_F(9): // F9 = Quit |
2008 printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c); | 2008 printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c); |
2009 exitProg = TRUE; | 2009 exitProg = TRUE; |
2010 break; | 2010 break; |
2011 | 2011 |
2012 case 0x09: /* Tab = complete username */ | 2012 case 0x09: // Tab = complete username |
2013 performTabCompletion(editBuf); | 2013 performTabCompletion(editBuf); |
2014 update = TRUE; | 2014 update = TRUE; |
2015 break; | 2015 break; |
2016 | 2016 |
2017 case 0x0c: /* Ctrl + L */ | 2017 case 0x0c: // Ctrl + L |
2018 updateWindows(); | 2018 updateWindows(); |
2019 update = updateMain = TRUE; | 2019 update = updateMain = TRUE; |
2020 break; | 2020 break; |
2021 | 2021 |
2022 case KEY_NPAGE: | 2022 case KEY_NPAGE: |
2023 case KEY_PPAGE: | 2023 case KEY_PPAGE: |
2024 /* Page Up / Page Down */ | 2024 // Page Up / Page Down |
2025 if (currWin != NULL) | 2025 if (currWin != NULL) |
2026 { | 2026 { |
2027 int oldPos = currWin->pos; | 2027 int oldPos = currWin->pos; |
2028 | 2028 |
2029 currWin->pos += (c == KEY_NPAGE) ? -10 : +10; | 2029 currWin->pos += (c == KEY_NPAGE) ? -10 : +10; |
2037 updateMain = TRUE; | 2037 updateMain = TRUE; |
2038 } | 2038 } |
2039 break; | 2039 break; |
2040 | 2040 |
2041 case ERR: | 2041 case ERR: |
2042 /* Ignore */ | 2042 // Ignore |
2043 break; | 2043 break; |
2044 | 2044 |
2045 default: | 2045 default: |
2046 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) | 2046 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) |
2047 { | 2047 { |
2064 | 2064 |
2065 updateMainWin(updateMain); | 2065 updateMainWin(updateMain); |
2066 | 2066 |
2067 if (update || firstUpdate) | 2067 if (update || firstUpdate) |
2068 { | 2068 { |
2069 /* Update edit line */ | 2069 // Update edit line |
2070 updateStatus(); | 2070 updateStatus(); |
2071 printEditBuf(editBuf); | 2071 printEditBuf(editBuf); |
2072 firstUpdate = FALSE; /* a nasty hack ... */ | 2072 firstUpdate = FALSE; // a nasty hack ... |
2073 } | 2073 } |
2074 | 2074 |
2075 } /* cursesInit */ | 2075 } // cursesInit |
2076 | 2076 |
2077 if (++updateCount > 10) | 2077 if (++updateCount > 10) |
2078 { | 2078 { |
2079 time_t tmpTime = time(NULL); | 2079 time_t tmpTime = time(NULL); |
2080 if (tmpTime - prevTime > SET_KEEPALIVE) | 2080 if (tmpTime - prevTime > SET_KEEPALIVE) |
2096 updateCount = 0; | 2096 updateCount = 0; |
2097 } | 2097 } |
2098 | 2098 |
2099 } | 2099 } |
2100 | 2100 |
2101 /* Shutdown */ | 2101 // Shutdown |
2102 err_exit: | 2102 err_exit: |
2103 th_cfg_free(cfg); | 2103 th_cfg_free(cfg); |
2104 th_free(homeDir); | 2104 th_free(homeDir); |
2105 th_llist_free_func(setIdleMessages, th_free); | 2105 th_llist_free_func(setIdleMessages, th_free); |
2106 nn_userhash_free(nnUsers); | 2106 nn_userhash_free(nnUsers); |