Mercurial > hg > nnchat
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); |