Mercurial > hg > nnchat
diff main.c @ 513:ef5a2aa8382b
Refactor input handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2012 22:16:42 +0300 |
parents | 93c8ba1ef55f |
children | 151edcb79ce4 |
line wrap: on
line diff
--- a/main.c Tue Jun 05 19:56:57 2012 +0300 +++ b/main.c Tue Jun 05 22:16:42 2012 +0300 @@ -19,11 +19,9 @@ #ifdef __WIN32 #define SET_CONFIG_FILE "nnchat.txt" #define SET_DIR_SEPARATOR "\\" -#define SET_DELAY (0) #else #define SET_CONFIG_FILE ".nnchat" #define SET_DIR_SEPARATOR "/" -#define SET_DELAY (5) #endif #define SET_PROFILE_PREFIX "http://www.newbienudes.com/profile/%s/" @@ -63,6 +61,9 @@ *setBrowser = NULL; cfgitem_t *cfg = NULL; +nn_editbuf_t *editHistBuf[SET_MAX_HISTORY+2]; +int editHistPos = 0, + editHistMax = 0; /* Logging mode flags */ @@ -313,6 +314,19 @@ } +void debugMsg(const char *fmt, ...) +{ + if (optDebug) + { + va_list ap; + + va_start(ap, fmt); + printMsgV(NULL, LOG_FILE|LOG_WINDOW, fmt, ap); + va_end(ap); + } +} + + void errorFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap) { (void) conn; @@ -1292,24 +1306,161 @@ } +BOOL processUserInput(int c, nn_editbuf_t *editBuf, nn_editstate_t *editState) +{ + // Chat window switching via Meta/Esc-[1..9] + if (c >= 0x5001 && c <= 0x5009) + { + nn_window_t *win = nnwin_get(c - 0x5000); + if (win != NULL) + { + currWin = win; + editState->update = TRUE; + } + } + else + switch (c) + { + case KEY_ENTER: + // Call the user input handler + if (editBuf->len > 0) + { + int result; + + if (editHistMax > 0) + { + nn_editbuf_free(editHistBuf[SET_MAX_HISTORY+1]); + editHistBuf[SET_MAX_HISTORY+1] = NULL; + memmove(&editHistBuf[2], &editHistBuf[1], + editHistMax * sizeof(editHistBuf[0])); + } + + editHistPos = 0; + editHistBuf[1] = nn_editbuf_copy(editBuf); + if (editHistMax < SET_MAX_HISTORY) + editHistMax++; + + result = nn_handle_input(editState->conn, editBuf->data, editBuf->len); + + nn_editbuf_clear(editBuf); + + if (result < 0) + { + errorMsg("Fatal error handling user input: %s\n", editBuf->data); + editState->isError = TRUE; + } + else + { + // Update time value of last sent message for unidle timeouts + editState->prevKeepAlive = time(NULL); + } + } + break; + + case KEY_NPAGE: + case KEY_PPAGE: + // Page Up / Page Down + if (currWin != NULL) + { + int oldPos = currWin->pos, page = (scrHeight - 4) / 3; + + currWin->pos += (c == KEY_NPAGE) ? - page : page; + + if (currWin->pos >= currWin->data->n - page) + currWin->pos = currWin->data->n - page; + if (currWin->pos < 0) + currWin->pos = 0; + + if (oldPos != currWin->pos) + editState->update = TRUE; + } + break; + + case KEY_UP: // Backwards in input history + if (editHistPos == 0) + { + nn_editbuf_free(editHistBuf[0]); + editHistBuf[0] = nn_editbuf_copy(editBuf); + } + if (editHistPos < editHistMax) + { + editHistPos++; + nn_editbuf_free(editBuf); + editBuf = nn_editbuf_copy(editHistBuf[editHistPos]); + } + break; + + case KEY_DOWN: // Forwards in input history + if (editHistPos > 0) + { + editHistPos--; + nn_editbuf_free(editBuf); + editBuf = nn_editbuf_copy(editHistBuf[editHistPos]); + } + break; + + case KEY_F(5): // F5 = Ignore mode + setIgnoreMode = setIgnoreMode; + printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF"); + break; + + case 0x03: // ^C = quit + case KEY_F(9): // F9 = Quit + printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c); + editState->exitProg = TRUE; + break; + + case 0x09: // Tab = complete username or command + nn_tabcomplete_buffer(editBuf); + break; + + default: + return FALSE; + } + + return TRUE; +} + + +BOOL processUserPrompt(int c, nn_editbuf_t *editBuf, nn_editstate_t *editState) +{ + (void) editBuf; + + switch (c) + { + case KEY_ENTER: + editState->done = TRUE; + break; + + default: + return FALSE; + } + + return TRUE; +} + + +void updateUserPrompt(nn_editbuf_t *editBuf, nn_editstate_t *editState) +{ + nnwin_update(editState->update, editState->mask, editBuf, optUserName, optUserColor); +} + + int main(int argc, char *argv[]) { + char *tmpStr; + int index, updateCount = 0; + BOOL argsOK, colorSet = FALSE; nn_conn_t *conn = NULL; - int updateCount = 0; - BOOL argsOK, isError = FALSE, - exitProg = FALSE, - colorSet = FALSE, - insertMode = TRUE; - time_t prevKeepAlive; - char *tmpStr; nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); - nn_editbuf_t *histBuf[SET_MAX_HISTORY+2]; - int histPos = 0, histMax = 0, index; - + nn_editstate_t editState; cfgitem_t *tmpcfg; char *setHomeDir = NULL; - memset(histBuf, 0, sizeof(histBuf)); + memset(editHistBuf, 0, sizeof(editHistBuf)); + memset(&editState, 0, sizeof(editState)); + editState.insertMode = TRUE; + editState.debugMsg = debugMsg; // Initialize th_init("NNChat", "Newbie Nudes chat client", NN_VERSION, @@ -1417,6 +1568,7 @@ if (optUserNameCmd != NULL) { + THMSG(1, "Username set on commandline.\n"); optUserName = optUserNameCmd; optPassword = optPasswordCmd; } @@ -1453,14 +1605,26 @@ if (cursesInit) { - nnwin_update(TRUE, NULL, optUserName, optUserColor); - } + printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); + printMsg(NULL, "%s\n", th_prog_author); + printMsg(NULL, "%s\n", th_prog_license); + + nnwin_update(TRUE, FALSE, NULL, optUserName, optUserColor); - // Check if we have username and password - if (cursesInit && (optUserName == NULL || optPassword == NULL)) - { - optUserName = nnwin_prompt_requester("You can avoid this prompt by issuing '/save' after logging in.\nNN username: ", FALSE); - optPassword = nnwin_prompt_requester("NN password: ", TRUE); + // Check if we have username and password + if (optUserName == NULL || optPassword == NULL) + { + printMsg(NULL, "Please enter your NN login credentials.\n"); + printMsg(NULL, "You can avoid doing this every time by issuing '/save' after logging in.\n"); + + printMsg(NULL, "Enter your NN username ...\n"); + optUserName = nnwin_prompt_requester(FALSE, &editState, processUserPrompt, updateUserPrompt); + + editState.mask = TRUE; + printMsg(NULL, "Enter your NN password ...\n"); + optPassword = nnwin_prompt_requester(TRUE, &editState, processUserPrompt, updateUserPrompt); + editState.mask = FALSE; + } } if (optUserName == NULL || optPassword == NULL) @@ -1476,6 +1640,8 @@ errorMsg("Could not create connection structure.\n"); goto err_exit; } + + editState.conn = conn; // Are we using a proxy? if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL) @@ -1541,25 +1707,12 @@ nn_usercmd_init(); // Initialize random numbers - prevKeepAlive = time(NULL); - srandom((int) prevKeepAlive); - - if (cursesInit) - { - // Initialize rest of interactive UI code - nn_editbuf_clear(editBuf); - - // First update of screen - nnwin_update(TRUE, editBuf, optUserName, optUserColor); - - printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); - printMsg(NULL, "%s\n", th_prog_author); - printMsg(NULL, "%s\n", th_prog_license); - } + editState.prevKeepAlive = time(NULL); + srandom((int) editState.prevKeepAlive); // Enter mainloop nn_conn_reset(conn); - while (!isError && !exitProg) + while (!editState.isError && !editState.exitProg) { int retries = 3, cres; @@ -1569,7 +1722,7 @@ { while (conn->ptr < conn->in_ptr && *(conn->in_ptr - 1) == 0 && - retries > 0 && !isError) + retries > 0 && !editState.isError) { // nn_conn_dump_buffer(stderr, conn); int result = nn_parse_protocol(conn); @@ -1589,326 +1742,29 @@ nn_conn_buf_skip(conn, strlen(conn->ptr) + 1); } else - isError = TRUE; + editState.isError = TRUE; } } else if (cres < 0 || !nn_conn_check(conn)) - isError = TRUE; + editState.isError = TRUE; // Handle user input if (cursesInit) { - int c, cnt = 0; - BOOL update = FALSE; - - // Handle several buffered keypresses at once - do - { - c = wgetch(stdscr); - - /* Handle various problematic cases where terminal - * keycodes do not get properly translated by curses - */ - if (c == 0x1b) - { - // ^[O - c = wgetch(stdscr); - if (c == 'O') - { - c = wgetch(stdscr); - switch (c) - { - case 'd': - c = 0x204; - break; - case 'c': - c = 0x206; - break; - default: - if (optDebug) - printMsg(currWin, "Unhandled ESC-O key sequence 0x%02x\n", c); - break; - } - } - // ^[[ - else if (c == '[') - { - c = wgetch(stdscr); - switch (c) - { - case 0x31: - c = wgetch(stdscr); - if (c >= 0x31 && c <= 0x39) - c = KEY_F(c - 0x30); - else - c = ERR; - break; - - case 0x32: - c = KEY_IC; - break; - case 0x33: - c = KEY_DC; - break; - - case 0x35: - c = KEY_PPAGE; - break; - case 0x36: - c = KEY_NPAGE; - break; - - case 0x37: - c = KEY_HOME; - break; - case 0x38: - c = KEY_END; - break; - - default: - if (optDebug) - printMsg(currWin, "Unhandled ESC-[*~ key sequence 0x%02x\n", c); - c = ERR; - break; - } - // Get the trailing ~ - if (c != ERR) - wgetch(stdscr); - } - if (c >= 0x31 && c <= 0x39) - { - // Chat window switching via Meta/Esc-[1..9] - nn_window_t *win = nnwin_get(c - 0x30); - if (win != NULL) - { - currWin = win; - update = TRUE; - } - c = ERR; - } - else - { - if (optDebug) - printMsg(currWin, "Unhandled ESC key sequence 0x%02x\n", c); - } - } -#if defined(__WIN32) && defined(PDCURSES) - else if (c >= 0x198 && c <= 0x1a0) - { - // Chat window switching via Meta/Esc-[1..9] - nn_window_t *win = nnwin_get(c - 0x198); - if (win != NULL) - { - currWin = win; - update = TRUE; - } - c = ERR; - } -#endif - - switch (c) - { -#ifdef KEY_RESIZE - case KEY_RESIZE: - resize_term(0, 0); - erase(); - timeout(SET_DELAY); - nnwin_reset(); - update = TRUE; - break; -#endif - - case KEY_ENTER: - case '\n': - case '\r': - // Call the user input handler - if (editBuf->len > 0) - { - int result; - - if (histMax > 0) - { - nn_editbuf_free(histBuf[SET_MAX_HISTORY+1]); - histBuf[SET_MAX_HISTORY+1] = NULL; - memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0])); - } - - histPos = 0; - histBuf[1] = nn_editbuf_copy(editBuf); - if (histMax < SET_MAX_HISTORY) histMax++; - - result = nn_handle_input(conn, editBuf->data, editBuf->len); - - nn_editbuf_clear(editBuf); - - if (result < 0) - { - errorMsg("Fatal error handling user input: %s\n", editBuf->data); - isError = TRUE; - } - else - { - // Update time value of last sent message for unidle timeouts - prevKeepAlive = time(NULL); - } - } - break; - - case KEY_UP: // Backwards in input history - if (histPos == 0) - { - nn_editbuf_free(histBuf[0]); - histBuf[0] = nn_editbuf_copy(editBuf); - } - if (histPos < histMax) - { - histPos++; - nn_editbuf_free(editBuf); - editBuf = nn_editbuf_copy(histBuf[histPos]); - } - break; - - case KEY_DOWN: // Forwards in input history - if (histPos > 0) - { - histPos--; - nn_editbuf_free(editBuf); - editBuf = nn_editbuf_copy(histBuf[histPos]); - } - break; - - case 0x204: // ctrl+left arrow = Skip words left - case 0x20b: - while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1])) - editBuf->pos--; - while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1])) - editBuf->pos--; - editBuf->dirty = TRUE; - break; - - case 0x206: // ctrl+right arrow = Skip words right - case 0x210: - while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos])) - editBuf->pos++; - while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos])) - editBuf->pos++; - editBuf->dirty = TRUE; - break; - - case KEY_HOME: - nn_editbuf_setpos(editBuf, 0); - break; - case KEY_END: - nn_editbuf_setpos(editBuf, editBuf->len); - break; - case KEY_LEFT: - nn_editbuf_setpos(editBuf, editBuf->pos - 1); - break; - case KEY_RIGHT: - nn_editbuf_setpos(editBuf, editBuf->pos + 1); - break; - - case KEY_BACKSPACE: - case 0x08: - case 0x7f: - nn_editbuf_delete(editBuf, editBuf->pos - 1); - nn_editbuf_setpos(editBuf, editBuf->pos - 1); - break; - - case KEY_DC: // Delete character - nn_editbuf_delete(editBuf, editBuf->pos); - break; - - - case KEY_IC: // Ins = Toggle insert / overwrite mode - insertMode = !insertMode; - break; - - case KEY_F(2): // F2 = Clear editbuffer - nn_editbuf_clear(editBuf); - break; - - case KEY_F(5): // F5 = Ignore mode - setIgnoreMode = !setIgnoreMode; - printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF"); - break; - -#if 0 - case KEY_F(8): // F8 = Debug - optDebug = !optDebug; - update = TRUE; - break; -#endif - - case 0x03: // ^C = quit - case KEY_F(9): // F9 = Quit - printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c); - exitProg = TRUE; - break; - - case 0x09: // Tab = complete username or command - nn_tabcomplete_buffer(editBuf); - break; - - case 0x0c: // Ctrl + L - update = TRUE; - break; - - case KEY_NPAGE: - case KEY_PPAGE: - // Page Up / Page Down - if (currWin != NULL) - { - int oldPos = currWin->pos, page = scrHeight - 4; - - currWin->pos += (c == KEY_NPAGE) ? - page : page; - - if (currWin->pos >= currWin->data->n - page) - currWin->pos = currWin->data->n - page; - if (currWin->pos < 0) - currWin->pos = 0; - - if (oldPos != currWin->pos) - update = TRUE; - } - break; - - case ERR: - // Ignore - break; - - default: - if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) - { - if (insertMode) - nn_editbuf_insert(editBuf, editBuf->pos, c); - else - nn_editbuf_write(editBuf, editBuf->pos, c); - nn_editbuf_setpos(editBuf, editBuf->pos + 1); - } - else - { - if (optDebug) - printMsg(currWin, "Unhandled key: 0x%02x\n", c); - } - break; - } - } - while (c != ERR && !exitProg && ++cnt < 10); - - nnwin_update(update, editBuf, optUserName, optUserColor); - } // cursesInit + nnwin_input_process(editBuf, &editState, processUserInput); + nnwin_update(editState.update, editState.mask, editBuf, optUserName, optUserColor); + } if (++updateCount > 10) { time_t tmpTime = time(NULL); - if (tmpTime - prevKeepAlive > SET_KEEPALIVE) + if (tmpTime - editState.prevKeepAlive > SET_KEEPALIVE) { size_t n = ((size_t) random()) % th_llist_length(setIdleMessages); qlist_t *node = th_llist_get_nth(setIdleMessages, n); nn_conn_send_msg(conn, optUserNameEnc, node->data); - prevKeepAlive = tmpTime; + editState.prevKeepAlive = tmpTime; } if (!colorSet) @@ -1916,8 +1772,12 @@ colorSet = TRUE; nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); } + + if (cursesInit) + { + nnwin_update(FALSE, editState.mask, editBuf, optUserName, optUserColor); + } - nnwin_update(FALSE, editBuf, optUserName, optUserColor); updateCount = 0; } @@ -1932,7 +1792,7 @@ nn_editbuf_free(editBuf); for (index = 0; index <= SET_MAX_HISTORY; index++) - nn_editbuf_free(histBuf[index]); + nn_editbuf_free(editHistBuf[index]); #ifdef __WIN32 if (errorMessages)