comparison 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
comparison
equal deleted inserted replaced
512:93c8ba1ef55f 513:ef5a2aa8382b
17 #endif 17 #endif
18 18
19 #ifdef __WIN32 19 #ifdef __WIN32
20 #define SET_CONFIG_FILE "nnchat.txt" 20 #define SET_CONFIG_FILE "nnchat.txt"
21 #define SET_DIR_SEPARATOR "\\" 21 #define SET_DIR_SEPARATOR "\\"
22 #define SET_DELAY (0)
23 #else 22 #else
24 #define SET_CONFIG_FILE ".nnchat" 23 #define SET_CONFIG_FILE ".nnchat"
25 #define SET_DIR_SEPARATOR "/" 24 #define SET_DIR_SEPARATOR "/"
26 #define SET_DELAY (5)
27 #endif 25 #endif
28 26
29 #define SET_PROFILE_PREFIX "http://www.newbienudes.com/profile/%s/" 27 #define SET_PROFILE_PREFIX "http://www.newbienudes.com/profile/%s/"
30 #define SET_NICK_SEPARATOR ':' 28 #define SET_NICK_SEPARATOR ':'
31 29
61 nn_userhash_t *nnUsers = NULL; 59 nn_userhash_t *nnUsers = NULL;
62 char *setConfigFile = NULL, 60 char *setConfigFile = NULL,
63 *setBrowser = NULL; 61 *setBrowser = NULL;
64 cfgitem_t *cfg = NULL; 62 cfgitem_t *cfg = NULL;
65 63
64 nn_editbuf_t *editHistBuf[SET_MAX_HISTORY+2];
65 int editHistPos = 0,
66 editHistMax = 0;
66 67
67 /* Logging mode flags 68 /* Logging mode flags
68 */ 69 */
69 enum 70 enum
70 { 71 {
308 va_list ap; 309 va_list ap;
309 310
310 va_start(ap, fmt); 311 va_start(ap, fmt);
311 errorMsgV(fmt, ap); 312 errorMsgV(fmt, ap);
312 va_end(ap); 313 va_end(ap);
314 }
315
316
317 void debugMsg(const char *fmt, ...)
318 {
319 if (optDebug)
320 {
321 va_list ap;
322
323 va_start(ap, fmt);
324 printMsgV(NULL, LOG_FILE|LOG_WINDOW, fmt, ap);
325 va_end(ap);
326 }
313 } 327 }
314 328
315 329
316 void errorFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap) 330 void errorFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap)
317 { 331 {
1290 optLogFile = NULL; 1304 optLogFile = NULL;
1291 } 1305 }
1292 } 1306 }
1293 1307
1294 1308
1309 BOOL processUserInput(int c, nn_editbuf_t *editBuf, nn_editstate_t *editState)
1310 {
1311 // Chat window switching via Meta/Esc-[1..9]
1312 if (c >= 0x5001 && c <= 0x5009)
1313 {
1314 nn_window_t *win = nnwin_get(c - 0x5000);
1315 if (win != NULL)
1316 {
1317 currWin = win;
1318 editState->update = TRUE;
1319 }
1320 }
1321 else
1322 switch (c)
1323 {
1324 case KEY_ENTER:
1325 // Call the user input handler
1326 if (editBuf->len > 0)
1327 {
1328 int result;
1329
1330 if (editHistMax > 0)
1331 {
1332 nn_editbuf_free(editHistBuf[SET_MAX_HISTORY+1]);
1333 editHistBuf[SET_MAX_HISTORY+1] = NULL;
1334 memmove(&editHistBuf[2], &editHistBuf[1],
1335 editHistMax * sizeof(editHistBuf[0]));
1336 }
1337
1338 editHistPos = 0;
1339 editHistBuf[1] = nn_editbuf_copy(editBuf);
1340 if (editHistMax < SET_MAX_HISTORY)
1341 editHistMax++;
1342
1343 result = nn_handle_input(editState->conn, editBuf->data, editBuf->len);
1344
1345 nn_editbuf_clear(editBuf);
1346
1347 if (result < 0)
1348 {
1349 errorMsg("Fatal error handling user input: %s\n", editBuf->data);
1350 editState->isError = TRUE;
1351 }
1352 else
1353 {
1354 // Update time value of last sent message for unidle timeouts
1355 editState->prevKeepAlive = time(NULL);
1356 }
1357 }
1358 break;
1359
1360 case KEY_NPAGE:
1361 case KEY_PPAGE:
1362 // Page Up / Page Down
1363 if (currWin != NULL)
1364 {
1365 int oldPos = currWin->pos, page = (scrHeight - 4) / 3;
1366
1367 currWin->pos += (c == KEY_NPAGE) ? - page : page;
1368
1369 if (currWin->pos >= currWin->data->n - page)
1370 currWin->pos = currWin->data->n - page;
1371 if (currWin->pos < 0)
1372 currWin->pos = 0;
1373
1374 if (oldPos != currWin->pos)
1375 editState->update = TRUE;
1376 }
1377 break;
1378
1379 case KEY_UP: // Backwards in input history
1380 if (editHistPos == 0)
1381 {
1382 nn_editbuf_free(editHistBuf[0]);
1383 editHistBuf[0] = nn_editbuf_copy(editBuf);
1384 }
1385 if (editHistPos < editHistMax)
1386 {
1387 editHistPos++;
1388 nn_editbuf_free(editBuf);
1389 editBuf = nn_editbuf_copy(editHistBuf[editHistPos]);
1390 }
1391 break;
1392
1393 case KEY_DOWN: // Forwards in input history
1394 if (editHistPos > 0)
1395 {
1396 editHistPos--;
1397 nn_editbuf_free(editBuf);
1398 editBuf = nn_editbuf_copy(editHistBuf[editHistPos]);
1399 }
1400 break;
1401
1402 case KEY_F(5): // F5 = Ignore mode
1403 setIgnoreMode = setIgnoreMode;
1404 printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF");
1405 break;
1406
1407 case 0x03: // ^C = quit
1408 case KEY_F(9): // F9 = Quit
1409 printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c);
1410 editState->exitProg = TRUE;
1411 break;
1412
1413 case 0x09: // Tab = complete username or command
1414 nn_tabcomplete_buffer(editBuf);
1415 break;
1416
1417 default:
1418 return FALSE;
1419 }
1420
1421 return TRUE;
1422 }
1423
1424
1425 BOOL processUserPrompt(int c, nn_editbuf_t *editBuf, nn_editstate_t *editState)
1426 {
1427 (void) editBuf;
1428
1429 switch (c)
1430 {
1431 case KEY_ENTER:
1432 editState->done = TRUE;
1433 break;
1434
1435 default:
1436 return FALSE;
1437 }
1438
1439 return TRUE;
1440 }
1441
1442
1443 void updateUserPrompt(nn_editbuf_t *editBuf, nn_editstate_t *editState)
1444 {
1445 nnwin_update(editState->update, editState->mask, editBuf, optUserName, optUserColor);
1446 }
1447
1448
1295 int main(int argc, char *argv[]) 1449 int main(int argc, char *argv[])
1296 { 1450 {
1451 char *tmpStr;
1452 int index, updateCount = 0;
1453 BOOL argsOK, colorSet = FALSE;
1297 nn_conn_t *conn = NULL; 1454 nn_conn_t *conn = NULL;
1298 int updateCount = 0;
1299 BOOL argsOK, isError = FALSE,
1300 exitProg = FALSE,
1301 colorSet = FALSE,
1302 insertMode = TRUE;
1303 time_t prevKeepAlive;
1304 char *tmpStr;
1305 nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); 1455 nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE);
1306 nn_editbuf_t *histBuf[SET_MAX_HISTORY+2]; 1456 nn_editstate_t editState;
1307 int histPos = 0, histMax = 0, index;
1308
1309 cfgitem_t *tmpcfg; 1457 cfgitem_t *tmpcfg;
1310 char *setHomeDir = NULL; 1458 char *setHomeDir = NULL;
1311 1459
1312 memset(histBuf, 0, sizeof(histBuf)); 1460 memset(editHistBuf, 0, sizeof(editHistBuf));
1461 memset(&editState, 0, sizeof(editState));
1462 editState.insertMode = TRUE;
1463 editState.debugMsg = debugMsg;
1313 1464
1314 // Initialize 1465 // Initialize
1315 th_init("NNChat", "Newbie Nudes chat client", NN_VERSION, 1466 th_init("NNChat", "Newbie Nudes chat client", NN_VERSION,
1316 "Written and designed by Anonymous Finnish Guy (C) 2008-2012", 1467 "Written and designed by Anonymous Finnish Guy (C) 2008-2012",
1317 "This software is freeware, use and distribute as you wish."); 1468 "This software is freeware, use and distribute as you wish.");
1415 argsOK = th_args_process(argc, argv, optList, optListN, 1566 argsOK = th_args_process(argc, argv, optList, optListN,
1416 argHandleOpt, argHandleFile, FALSE); 1567 argHandleOpt, argHandleFile, FALSE);
1417 1568
1418 if (optUserNameCmd != NULL) 1569 if (optUserNameCmd != NULL)
1419 { 1570 {
1571 THMSG(1, "Username set on commandline.\n");
1420 optUserName = optUserNameCmd; 1572 optUserName = optUserNameCmd;
1421 optPassword = optPasswordCmd; 1573 optPassword = optPasswordCmd;
1422 } 1574 }
1423 1575
1424 if (!argsOK) 1576 if (!argsOK)
1451 if (!optDaemon && !nnwin_init(SET_DELAY)) 1603 if (!optDaemon && !nnwin_init(SET_DELAY))
1452 goto err_exit; 1604 goto err_exit;
1453 1605
1454 if (cursesInit) 1606 if (cursesInit)
1455 { 1607 {
1456 nnwin_update(TRUE, NULL, optUserName, optUserColor); 1608 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
1457 } 1609 printMsg(NULL, "%s\n", th_prog_author);
1458 1610 printMsg(NULL, "%s\n", th_prog_license);
1459 // Check if we have username and password 1611
1460 if (cursesInit && (optUserName == NULL || optPassword == NULL)) 1612 nnwin_update(TRUE, FALSE, NULL, optUserName, optUserColor);
1461 { 1613
1462 optUserName = nnwin_prompt_requester("You can avoid this prompt by issuing '/save' after logging in.\nNN username: ", FALSE); 1614 // Check if we have username and password
1463 optPassword = nnwin_prompt_requester("NN password: ", TRUE); 1615 if (optUserName == NULL || optPassword == NULL)
1616 {
1617 printMsg(NULL, "Please enter your NN login credentials.\n");
1618 printMsg(NULL, "You can avoid doing this every time by issuing '/save' after logging in.\n");
1619
1620 printMsg(NULL, "Enter your NN username ...\n");
1621 optUserName = nnwin_prompt_requester(FALSE, &editState, processUserPrompt, updateUserPrompt);
1622
1623 editState.mask = TRUE;
1624 printMsg(NULL, "Enter your NN password ...\n");
1625 optPassword = nnwin_prompt_requester(TRUE, &editState, processUserPrompt, updateUserPrompt);
1626 editState.mask = FALSE;
1627 }
1464 } 1628 }
1465 1629
1466 if (optUserName == NULL || optPassword == NULL) 1630 if (optUserName == NULL || optPassword == NULL)
1467 { 1631 {
1468 errorMsg("Username and/or password not specified.\n"); 1632 errorMsg("Username and/or password not specified.\n");
1474 if (conn == NULL) 1638 if (conn == NULL)
1475 { 1639 {
1476 errorMsg("Could not create connection structure.\n"); 1640 errorMsg("Could not create connection structure.\n");
1477 goto err_exit; 1641 goto err_exit;
1478 } 1642 }
1643
1644 editState.conn = conn;
1479 1645
1480 // Are we using a proxy? 1646 // Are we using a proxy?
1481 if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL) 1647 if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL)
1482 { 1648 {
1483 if (nn_conn_set_proxy(conn, optProxyType, optProxyPort, optProxyServer) != 0) 1649 if (nn_conn_set_proxy(conn, optProxyType, optProxyPort, optProxyServer) != 0)
1539 1705
1540 // Initialize user commands 1706 // Initialize user commands
1541 nn_usercmd_init(); 1707 nn_usercmd_init();
1542 1708
1543 // Initialize random numbers 1709 // Initialize random numbers
1544 prevKeepAlive = time(NULL); 1710 editState.prevKeepAlive = time(NULL);
1545 srandom((int) prevKeepAlive); 1711 srandom((int) editState.prevKeepAlive);
1546
1547 if (cursesInit)
1548 {
1549 // Initialize rest of interactive UI code
1550 nn_editbuf_clear(editBuf);
1551
1552 // First update of screen
1553 nnwin_update(TRUE, editBuf, optUserName, optUserColor);
1554
1555 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
1556 printMsg(NULL, "%s\n", th_prog_author);
1557 printMsg(NULL, "%s\n", th_prog_license);
1558 }
1559 1712
1560 // Enter mainloop 1713 // Enter mainloop
1561 nn_conn_reset(conn); 1714 nn_conn_reset(conn);
1562 while (!isError && !exitProg) 1715 while (!editState.isError && !editState.exitProg)
1563 { 1716 {
1564 int retries = 3, cres; 1717 int retries = 3, cres;
1565 1718
1566 packet_retry: 1719 packet_retry:
1567 cres = nn_conn_pull(conn); 1720 cres = nn_conn_pull(conn);
1568 if (cres == 0) 1721 if (cres == 0)
1569 { 1722 {
1570 while (conn->ptr < conn->in_ptr && 1723 while (conn->ptr < conn->in_ptr &&
1571 *(conn->in_ptr - 1) == 0 && 1724 *(conn->in_ptr - 1) == 0 &&
1572 retries > 0 && !isError) 1725 retries > 0 && !editState.isError)
1573 { 1726 {
1574 // nn_conn_dump_buffer(stderr, conn); 1727 // nn_conn_dump_buffer(stderr, conn);
1575 int result = nn_parse_protocol(conn); 1728 int result = nn_parse_protocol(conn);
1576 if (result == 0) 1729 if (result == 0)
1577 { 1730 {
1587 // Couldn't handle the message for some reason 1740 // Couldn't handle the message for some reason
1588 printMsg(currWin, "Could not handle: %s\n", conn->ptr); 1741 printMsg(currWin, "Could not handle: %s\n", conn->ptr);
1589 nn_conn_buf_skip(conn, strlen(conn->ptr) + 1); 1742 nn_conn_buf_skip(conn, strlen(conn->ptr) + 1);
1590 } 1743 }
1591 else 1744 else
1592 isError = TRUE; 1745 editState.isError = TRUE;
1593 } 1746 }
1594 } 1747 }
1595 else 1748 else
1596 if (cres < 0 || !nn_conn_check(conn)) 1749 if (cres < 0 || !nn_conn_check(conn))
1597 isError = TRUE; 1750 editState.isError = TRUE;
1598 1751
1599 // Handle user input 1752 // Handle user input
1600 if (cursesInit) 1753 if (cursesInit)
1601 { 1754 {
1602 int c, cnt = 0; 1755 nnwin_input_process(editBuf, &editState, processUserInput);
1603 BOOL update = FALSE; 1756 nnwin_update(editState.update, editState.mask, editBuf, optUserName, optUserColor);
1604 1757 }
1605 // Handle several buffered keypresses at once
1606 do
1607 {
1608 c = wgetch(stdscr);
1609
1610 /* Handle various problematic cases where terminal
1611 * keycodes do not get properly translated by curses
1612 */
1613 if (c == 0x1b)
1614 {
1615 // ^[O
1616 c = wgetch(stdscr);
1617 if (c == 'O')
1618 {
1619 c = wgetch(stdscr);
1620 switch (c)
1621 {
1622 case 'd':
1623 c = 0x204;
1624 break;
1625 case 'c':
1626 c = 0x206;
1627 break;
1628 default:
1629 if (optDebug)
1630 printMsg(currWin, "Unhandled ESC-O key sequence 0x%02x\n", c);
1631 break;
1632 }
1633 }
1634 // ^[[
1635 else if (c == '[')
1636 {
1637 c = wgetch(stdscr);
1638 switch (c)
1639 {
1640 case 0x31:
1641 c = wgetch(stdscr);
1642 if (c >= 0x31 && c <= 0x39)
1643 c = KEY_F(c - 0x30);
1644 else
1645 c = ERR;
1646 break;
1647
1648 case 0x32:
1649 c = KEY_IC;
1650 break;
1651 case 0x33:
1652 c = KEY_DC;
1653 break;
1654
1655 case 0x35:
1656 c = KEY_PPAGE;
1657 break;
1658 case 0x36:
1659 c = KEY_NPAGE;
1660 break;
1661
1662 case 0x37:
1663 c = KEY_HOME;
1664 break;
1665 case 0x38:
1666 c = KEY_END;
1667 break;
1668
1669 default:
1670 if (optDebug)
1671 printMsg(currWin, "Unhandled ESC-[*~ key sequence 0x%02x\n", c);
1672 c = ERR;
1673 break;
1674 }
1675 // Get the trailing ~
1676 if (c != ERR)
1677 wgetch(stdscr);
1678 }
1679 if (c >= 0x31 && c <= 0x39)
1680 {
1681 // Chat window switching via Meta/Esc-[1..9]
1682 nn_window_t *win = nnwin_get(c - 0x30);
1683 if (win != NULL)
1684 {
1685 currWin = win;
1686 update = TRUE;
1687 }
1688 c = ERR;
1689 }
1690 else
1691 {
1692 if (optDebug)
1693 printMsg(currWin, "Unhandled ESC key sequence 0x%02x\n", c);
1694 }
1695 }
1696 #if defined(__WIN32) && defined(PDCURSES)
1697 else if (c >= 0x198 && c <= 0x1a0)
1698 {
1699 // Chat window switching via Meta/Esc-[1..9]
1700 nn_window_t *win = nnwin_get(c - 0x198);
1701 if (win != NULL)
1702 {
1703 currWin = win;
1704 update = TRUE;
1705 }
1706 c = ERR;
1707 }
1708 #endif
1709
1710 switch (c)
1711 {
1712 #ifdef KEY_RESIZE
1713 case KEY_RESIZE:
1714 resize_term(0, 0);
1715 erase();
1716 timeout(SET_DELAY);
1717 nnwin_reset();
1718 update = TRUE;
1719 break;
1720 #endif
1721
1722 case KEY_ENTER:
1723 case '\n':
1724 case '\r':
1725 // Call the user input handler
1726 if (editBuf->len > 0)
1727 {
1728 int result;
1729
1730 if (histMax > 0)
1731 {
1732 nn_editbuf_free(histBuf[SET_MAX_HISTORY+1]);
1733 histBuf[SET_MAX_HISTORY+1] = NULL;
1734 memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0]));
1735 }
1736
1737 histPos = 0;
1738 histBuf[1] = nn_editbuf_copy(editBuf);
1739 if (histMax < SET_MAX_HISTORY) histMax++;
1740
1741 result = nn_handle_input(conn, editBuf->data, editBuf->len);
1742
1743 nn_editbuf_clear(editBuf);
1744
1745 if (result < 0)
1746 {
1747 errorMsg("Fatal error handling user input: %s\n", editBuf->data);
1748 isError = TRUE;
1749 }
1750 else
1751 {
1752 // Update time value of last sent message for unidle timeouts
1753 prevKeepAlive = time(NULL);
1754 }
1755 }
1756 break;
1757
1758 case KEY_UP: // Backwards in input history
1759 if (histPos == 0)
1760 {
1761 nn_editbuf_free(histBuf[0]);
1762 histBuf[0] = nn_editbuf_copy(editBuf);
1763 }
1764 if (histPos < histMax)
1765 {
1766 histPos++;
1767 nn_editbuf_free(editBuf);
1768 editBuf = nn_editbuf_copy(histBuf[histPos]);
1769 }
1770 break;
1771
1772 case KEY_DOWN: // Forwards in input history
1773 if (histPos > 0)
1774 {
1775 histPos--;
1776 nn_editbuf_free(editBuf);
1777 editBuf = nn_editbuf_copy(histBuf[histPos]);
1778 }
1779 break;
1780
1781 case 0x204: // ctrl+left arrow = Skip words left
1782 case 0x20b:
1783 while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1]))
1784 editBuf->pos--;
1785 while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1]))
1786 editBuf->pos--;
1787 editBuf->dirty = TRUE;
1788 break;
1789
1790 case 0x206: // ctrl+right arrow = Skip words right
1791 case 0x210:
1792 while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos]))
1793 editBuf->pos++;
1794 while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos]))
1795 editBuf->pos++;
1796 editBuf->dirty = TRUE;
1797 break;
1798
1799 case KEY_HOME:
1800 nn_editbuf_setpos(editBuf, 0);
1801 break;
1802 case KEY_END:
1803 nn_editbuf_setpos(editBuf, editBuf->len);
1804 break;
1805 case KEY_LEFT:
1806 nn_editbuf_setpos(editBuf, editBuf->pos - 1);
1807 break;
1808 case KEY_RIGHT:
1809 nn_editbuf_setpos(editBuf, editBuf->pos + 1);
1810 break;
1811
1812 case KEY_BACKSPACE:
1813 case 0x08:
1814 case 0x7f:
1815 nn_editbuf_delete(editBuf, editBuf->pos - 1);
1816 nn_editbuf_setpos(editBuf, editBuf->pos - 1);
1817 break;
1818
1819 case KEY_DC: // Delete character
1820 nn_editbuf_delete(editBuf, editBuf->pos);
1821 break;
1822
1823
1824 case KEY_IC: // Ins = Toggle insert / overwrite mode
1825 insertMode = !insertMode;
1826 break;
1827
1828 case KEY_F(2): // F2 = Clear editbuffer
1829 nn_editbuf_clear(editBuf);
1830 break;
1831
1832 case KEY_F(5): // F5 = Ignore mode
1833 setIgnoreMode = !setIgnoreMode;
1834 printMsgQ(currWin, "Ignore mode = %s\n", setIgnoreMode ? "ON" : "OFF");
1835 break;
1836
1837 #if 0
1838 case KEY_F(8): // F8 = Debug
1839 optDebug = !optDebug;
1840 update = TRUE;
1841 break;
1842 #endif
1843
1844 case 0x03: // ^C = quit
1845 case KEY_F(9): // F9 = Quit
1846 printMsg(currWin, "Quitting per user request (%d/0x%x).\n", c, c);
1847 exitProg = TRUE;
1848 break;
1849
1850 case 0x09: // Tab = complete username or command
1851 nn_tabcomplete_buffer(editBuf);
1852 break;
1853
1854 case 0x0c: // Ctrl + L
1855 update = TRUE;
1856 break;
1857
1858 case KEY_NPAGE:
1859 case KEY_PPAGE:
1860 // Page Up / Page Down
1861 if (currWin != NULL)
1862 {
1863 int oldPos = currWin->pos, page = scrHeight - 4;
1864
1865 currWin->pos += (c == KEY_NPAGE) ? - page : page;
1866
1867 if (currWin->pos >= currWin->data->n - page)
1868 currWin->pos = currWin->data->n - page;
1869 if (currWin->pos < 0)
1870 currWin->pos = 0;
1871
1872 if (oldPos != currWin->pos)
1873 update = TRUE;
1874 }
1875 break;
1876
1877 case ERR:
1878 // Ignore
1879 break;
1880
1881 default:
1882 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6)
1883 {
1884 if (insertMode)
1885 nn_editbuf_insert(editBuf, editBuf->pos, c);
1886 else
1887 nn_editbuf_write(editBuf, editBuf->pos, c);
1888 nn_editbuf_setpos(editBuf, editBuf->pos + 1);
1889 }
1890 else
1891 {
1892 if (optDebug)
1893 printMsg(currWin, "Unhandled key: 0x%02x\n", c);
1894 }
1895 break;
1896 }
1897 }
1898 while (c != ERR && !exitProg && ++cnt < 10);
1899
1900 nnwin_update(update, editBuf, optUserName, optUserColor);
1901 } // cursesInit
1902 1758
1903 if (++updateCount > 10) 1759 if (++updateCount > 10)
1904 { 1760 {
1905 time_t tmpTime = time(NULL); 1761 time_t tmpTime = time(NULL);
1906 if (tmpTime - prevKeepAlive > SET_KEEPALIVE) 1762 if (tmpTime - editState.prevKeepAlive > SET_KEEPALIVE)
1907 { 1763 {
1908 size_t n = ((size_t) random()) % th_llist_length(setIdleMessages); 1764 size_t n = ((size_t) random()) % th_llist_length(setIdleMessages);
1909 qlist_t *node = th_llist_get_nth(setIdleMessages, n); 1765 qlist_t *node = th_llist_get_nth(setIdleMessages, n);
1910 nn_conn_send_msg(conn, optUserNameEnc, node->data); 1766 nn_conn_send_msg(conn, optUserNameEnc, node->data);
1911 prevKeepAlive = tmpTime; 1767 editState.prevKeepAlive = tmpTime;
1912 } 1768 }
1913 1769
1914 if (!colorSet) 1770 if (!colorSet)
1915 { 1771 {
1916 colorSet = TRUE; 1772 colorSet = TRUE;
1917 nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); 1773 nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
1918 } 1774 }
1919 1775
1920 nnwin_update(FALSE, editBuf, optUserName, optUserColor); 1776 if (cursesInit)
1777 {
1778 nnwin_update(FALSE, editState.mask, editBuf, optUserName, optUserColor);
1779 }
1780
1921 updateCount = 0; 1781 updateCount = 0;
1922 } 1782 }
1923 1783
1924 } 1784 }
1925 1785
1930 th_llist_free_func(setIdleMessages, th_free); 1790 th_llist_free_func(setIdleMessages, th_free);
1931 nn_userhash_free(nnUsers); 1791 nn_userhash_free(nnUsers);
1932 nn_editbuf_free(editBuf); 1792 nn_editbuf_free(editBuf);
1933 1793
1934 for (index = 0; index <= SET_MAX_HISTORY; index++) 1794 for (index = 0; index <= SET_MAX_HISTORY; index++)
1935 nn_editbuf_free(histBuf[index]); 1795 nn_editbuf_free(editHistBuf[index]);
1936 1796
1937 #ifdef __WIN32 1797 #ifdef __WIN32
1938 if (errorMessages) 1798 if (errorMessages)
1939 { 1799 {
1940 char *tmp = nnwin_prompt_requester("Press enter to quit.\n", FALSE); 1800 char *tmp = nnwin_prompt_requester("Press enter to quit.\n", FALSE);