comparison main.c @ 466:796508f828f6

Refactor much of the "windowing" UI code into a new module, ui.[ch]
author Matti Hamalainen <ccr@tnsp.org>
date Sat, 26 May 2012 06:56:18 +0300
parents 35d67bd0613b
children 607bd4491e79
comparison
equal deleted inserted replaced
465:c3b3b6d89084 466:796508f828f6
3 * Written by Matti 'ccr' Hämäläinen 3 * Written by Matti 'ccr' Hämäläinen
4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP) 4 * (C) Copyright 2008-2012 Tecnic Software productions (TNSP)
5 */ 5 */
6 #include "util.h" 6 #include "util.h"
7 #include "network.h" 7 #include "network.h"
8 #include "ui.h"
8 #include "th_args.h" 9 #include "th_args.h"
9 #include "th_config.h" 10 #include "th_config.h"
10 #include <errno.h> 11 #include <errno.h>
11 #include <time.h> 12 #include <time.h>
12 #ifdef __WIN32 13 #ifdef __WIN32
14 #undef MOUSE_MOVED 15 #undef MOUSE_MOVED
15 #include <shlwapi.h> 16 #include <shlwapi.h>
16 #else 17 #else
17 #include <sys/wait.h> 18 #include <sys/wait.h>
18 #endif 19 #endif
19 #ifdef HAVE_NCURSES_H
20 #include <ncurses.h>
21 #else
22 #include <curses.h>
23 #endif
24 20
25 #ifdef __WIN32 21 #ifdef __WIN32
26 #define SET_CONFIG_FILE "nnchat.txt" 22 #define SET_CONFIG_FILE "nnchat.txt"
27 #define SET_DIR_SEPARATOR "\\" 23 #define SET_DIR_SEPARATOR "\\"
28 #define SET_DELAY (0) 24 #define SET_DELAY (0)
35 #define SET_PROFILE_PREFIX "http://www.newbienudes.com/profile/%s/" 31 #define SET_PROFILE_PREFIX "http://www.newbienudes.com/profile/%s/"
36 #define SET_NICK_SEPARATOR ':' 32 #define SET_NICK_SEPARATOR ':'
37 33
38 #define SET_MAX_HISTORY (16) // Command history length 34 #define SET_MAX_HISTORY (16) // Command history length
39 #define SET_KEEPALIVE (15*60) // Ping/keepalive period in seconds 35 #define SET_KEEPALIVE (15*60) // Ping/keepalive period in seconds
40 #define SET_MAX_WINDOWS (32)
41 36
42 37
43 /* Options 38 /* Options
44 */ 39 */
45 int optPort = 8005, 40 int optPort = 8005,
61 FILE *optLogFile = NULL; 56 FILE *optLogFile = NULL;
62 BOOL setIgnoreMode = FALSE; 57 BOOL setIgnoreMode = FALSE;
63 BOOL optDebug = FALSE; 58 BOOL optDebug = FALSE;
64 BOOL optLogEnable = FALSE; 59 BOOL optLogEnable = FALSE;
65 60
66 nn_window_t *chatWindows[SET_MAX_WINDOWS],
67 *currWin = NULL;
68 WINDOW *mainWin = NULL,
69 *statusWin = NULL,
70 *editWin = NULL;
71
72 qlist_t *setIgnoreList = NULL, 61 qlist_t *setIgnoreList = NULL,
73 *setIdleMessages = NULL; 62 *setIdleMessages = NULL;
74 nn_userhash_t *nnUsers = NULL; 63 nn_userhash_t *nnUsers = NULL;
75 char *setConfigFile = NULL, 64 char *setConfigFile = NULL,
76 *setBrowser = NULL; 65 *setBrowser = NULL;
203 { 192 {
204 THERR("Username '%s' already specified on commandline!\n", optUserNameCmd); 193 THERR("Username '%s' already specified on commandline!\n", optUserNameCmd);
205 return FALSE; 194 return FALSE;
206 } 195 }
207 196
208 return TRUE;
209 }
210
211
212 nn_window_t *nnwin_find(const char *id)
213 {
214 int i;
215
216 for (i = 0; i < SET_MAX_WINDOWS; i++)
217 if (chatWindows[i] != NULL &&
218 chatWindows[i]->id != NULL &&
219 th_strcasecmp(id, chatWindows[i]->id) == 0)
220 return chatWindows[i];
221
222 return NULL;
223 }
224
225
226 BOOL nnwin_open(const char *name, BOOL curwin)
227 {
228 int i;
229 nn_window_t *res;
230 if (name == NULL)
231 return FALSE;
232
233 if ((res = nn_window_new(name)) == NULL)
234 return FALSE;
235
236 for (i = 1; i < SET_MAX_WINDOWS; i++)
237 if (chatWindows[i] == NULL)
238 {
239 res->num = i;
240 chatWindows[i] = res;
241 if (curwin)
242 currWin = res;
243 return TRUE;
244 }
245
246 return FALSE;
247 }
248
249
250 void nnwin_close(nn_window_t *win)
251 {
252 int i;
253 if (win == NULL) return;
254
255 for (i = 1; i < SET_MAX_WINDOWS; i++)
256 if (chatWindows[i] == win)
257 {
258 chatWindows[i] = NULL;
259 nn_window_free(win);
260 return;
261 }
262 }
263
264
265 void nnwin_update_statusline(void)
266 {
267 char tmpStr[128];
268 int i;
269
270 if (statusWin == NULL) return;
271
272 str_get_timestamp(tmpStr, sizeof(tmpStr), "%H:%M:%S");
273
274 wbkgdset(statusWin, COLOR_PAIR(10));
275 werase(statusWin);
276
277 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
278 mvwaddstr(statusWin, 0, 1, tmpStr);
279
280 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
281 waddstr(statusWin, " | ");
282 wattrset(statusWin, A_BOLD | COLOR_PAIR(16));
283 waddstr(statusWin, optUserName);
284 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
285
286 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
287 waddstr(statusWin, " | ");
288 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
289 snprintf(tmpStr, sizeof(tmpStr), "#%06x", optUserColor);
290 waddstr(statusWin, tmpStr);
291
292 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
293 waddstr(statusWin, " | WIN: ");
294 snprintf(tmpStr, sizeof(tmpStr), "%d: %s / %d",
295 currWin->num + 1,
296 currWin->id != NULL ? currWin->id : "MAIN",
297 currWin->pos);
298 waddstr(statusWin, tmpStr);
299
300 wattrset(statusWin, A_BOLD | COLOR_PAIR(13));
301 waddstr(statusWin, " | ");
302 wattrset(statusWin, A_BOLD | COLOR_PAIR(11));
303
304 for (i = 0; i < SET_MAX_WINDOWS; i++)
305 if (chatWindows[i] != NULL && chatWindows[i]->dirty)
306 {
307 snprintf(tmpStr, sizeof(tmpStr), "%d ", i + 1);
308 waddstr(statusWin, tmpStr);
309 }
310
311 wrefresh(statusWin);
312 }
313
314
315 void nnwin_update_editbuf(nn_editbuf_t *buf)
316 {
317 char *tmp;
318 if (editWin == NULL || buf == NULL) return;
319
320 buf->data[buf->len] = 0;
321 tmp = nn_username_decode(th_strdup(buf->data));
322
323 werase(editWin);
324
325 wattrset(editWin, A_NORMAL);
326
327 if (buf->pos < buf->len)
328 {
329 waddnstr(editWin, tmp, buf->pos);
330 wattrset(editWin, A_REVERSE);
331 waddch(editWin, tmp[buf->pos]);
332 wattrset(editWin, A_NORMAL);
333 waddnstr(editWin, tmp + buf->pos + 1, buf->len - buf->pos - 1);
334 }
335 else
336 {
337 waddnstr(editWin, tmp, buf->len);
338 wattrset(editWin, A_REVERSE);
339 waddch(editWin, ' ');
340 wattrset(editWin, A_NORMAL);
341 }
342 wrefresh(editWin);
343 th_free(tmp);
344 }
345
346
347 int nnwin_print(WINDOW *win, const char *fmt)
348 {
349 const char *s = fmt;
350 int col = 0;
351
352 while (*s)
353 {
354 if (*s == '½')
355 {
356 s++;
357 if (*s == '½')
358 {
359 waddch(win, ((unsigned char) *s) | col);
360 s++;
361 }
362 else
363 {
364 memcpy(&col, s, sizeof(int));
365 s += sizeof(int);
366 }
367 }
368 else
369 {
370 waddch(win, ((unsigned char) *s) | col);
371 s++;
372 }
373 }
374 return 0;
375 }
376
377
378 #define QPUTCH(ch) th_vputch(&(win->buf), &(win->bufsize), &(win->len), ch)
379
380 int nnwin_print_buf(nn_window_t *win, const char *fmt)
381 {
382 const char *s = fmt;
383 int col = 0;
384 while (*s)
385 {
386 if (*s == '½')
387 {
388 s++;
389 if (*s == '½')
390 {
391 QPUTCH(*s);
392 QPUTCH(*s);
393 win->chlen++;
394 }
395 else
396 {
397 int val = 0;
398 while (*s >= '0' && *s <= '9')
399 {
400 val *= 10;
401 val += (*s - '0');
402 s++;
403 }
404 if (*s != '½') return -1;
405
406 if (val < 9)
407 col = A_DIM | COLOR_PAIR(val);
408 else if (val < 30)
409 col = A_BOLD | COLOR_PAIR(val - 9);
410
411 QPUTCH('½');
412
413 if (!th_growbuf(&(win->buf), &(win->bufsize), &(win->len), sizeof(int)))
414 return -2;
415
416 memcpy(win->buf + win->len, &col, sizeof(int));
417 win->len += sizeof(int);
418 }
419 }
420 else if (*s == '\n')
421 {
422 QPUTCH('\n');
423 QPUTCH(0);
424 th_ringbuf_add(win->data, win->buf);
425 win->buf = NULL;
426 win->chlen = 0;
427 win->dirty = TRUE;
428 }
429 else if (*s != '\r')
430 {
431 QPUTCH((unsigned char) *s == 255 ? ' ' : *s);
432 win->chlen++;
433 }
434
435 s++;
436 }
437
438 return 0;
439 }
440
441
442 BOOL nnwin_update_main(BOOL force)
443 {
444 int h, offs;
445 qringbuf_t *buf;
446
447 // Check pointers
448 if (mainWin == NULL || currWin == NULL)
449 return FALSE;
450
451 // Check if update is forced or if the window is dirty
452 if (!force && !currWin->dirty)
453 return FALSE;
454
455 // Compute how many lines from backbuffer fit on the screen
456 buf = currWin->data;
457 h = getmaxy(mainWin);
458
459 // Clear and redraw window
460 werase(mainWin);
461 scrollok(mainWin, 1);
462 for (offs = buf->size - h - currWin->pos; offs >= 0 && offs < buf->size - currWin->pos && offs < buf->size; offs++)
463 {
464 if (buf->data[offs] != NULL)
465 nnwin_print(mainWin, buf->data[offs]);
466 }
467
468 currWin->dirty = FALSE;
469 wrefresh(mainWin);
470 return TRUE; 197 return TRUE;
471 } 198 }
472 199
473 200
474 int printFile(FILE *outFile, const char *fmt) 201 int printFile(FILE *outFile, const char *fmt)
520 fflush(optLogFile); 247 fflush(optLogFile);
521 } 248 }
522 249
523 if (!optDaemon && (flags & LOG_WINDOW)) 250 if (!optDaemon && (flags & LOG_WINDOW))
524 { 251 {
525 nn_window_t *tmp = win != NULL ? win : chatWindows[0]; 252 nn_window_t *tmp = (win != NULL) ? win : nnwin_main_window();
526 if (flags & LOG_STAMP) nnwin_print_buf(tmp, tmpStr); 253 if (flags & LOG_STAMP) nnwin_print_buf(tmp, tmpStr);
527 nnwin_print_buf(tmp, buf); 254 nnwin_print_buf(tmp, buf);
528 } 255 }
529 256
530 th_free(buf); 257 th_free(buf);
575 } 302 }
576 else 303 else
577 errorMessages = tmp; 304 errorMessages = tmp;
578 } 305 }
579 306
307
580 void errorMsg(const char *fmt, ...) 308 void errorMsg(const char *fmt, ...)
581 { 309 {
582 va_list ap; 310 va_list ap;
583 311
584 va_start(ap, fmt); 312 va_start(ap, fmt);
585 errorMsgV(fmt, ap); 313 errorMsgV(fmt, ap);
586 va_end(ap); 314 va_end(ap);
587 } 315 }
588 316
317
589 void errorFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap) 318 void errorFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap)
590 { 319 {
591 (void) conn; 320 (void) conn;
592 errorMsgV(fmt, ap); 321 errorMsgV(fmt, ap);
593 } 322 }
323
594 324
595 void messageFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap) 325 void messageFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap)
596 { 326 {
597 (void) conn; 327 (void) conn;
598 printMsgV(NULL, LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap); 328 printMsgV(NULL, LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
1026 printMsgQ(currWin, "No PRV query by name '%s'.\n", name); 756 printMsgQ(currWin, "No PRV query by name '%s'.\n", name);
1027 } 757 }
1028 } 758 }
1029 else 759 else
1030 { 760 {
1031 if (currWin != chatWindows[0]) 761 if (currWin != nnwin_main_window())
1032 { 762 {
1033 nnwin_close(currWin); 763 nnwin_close(currWin);
1034 currWin = chatWindows[0]; 764 currWin = nnwin_main_window();
1035 } 765 }
1036 else 766 else
1037 { 767 {
1038 printMsgQ(currWin, "Usage: /close [username]\n"); 768 printMsgQ(currWin, "Usage: /close [username]\n");
1039 printMsgQ(currWin, "/close without username will close the current PRV window. if any.\n"); 769 printMsgQ(currWin, "/close without username will close the current PRV window. if any.\n");
1049 (void) conn; 779 (void) conn;
1050 780
1051 if (arg[0]) 781 if (arg[0])
1052 { 782 {
1053 int val = atoi(arg); 783 int val = atoi(arg);
1054 if (val >= 1 && val < SET_MAX_WINDOWS) 784 nn_window_t *win = nnwin_get(val);
1055 { 785 if (win != NULL)
1056 if (chatWindows[val - 1] != NULL) 786 currWin = win;
1057 currWin = chatWindows[val - 1];
1058 }
1059 else 787 else
1060 { 788 {
1061 printMsgQ(currWin, "Invalid window number '%s'\n", arg); 789 printMsgQ(currWin, "Invalid window number '%s'\n", arg);
1062 return 1; 790 return 1;
1063 } 791 }
1294 // Check for commands 1022 // Check for commands
1295 if (buf[0] == '/') 1023 if (buf[0] == '/')
1296 return nn_handle_command(conn, buf); 1024 return nn_handle_command(conn, buf);
1297 1025
1298 // If current window is not the main room window, send private 1026 // If current window is not the main room window, send private
1299 if (currWin != chatWindows[0]) 1027 if (currWin != nnwin_main_window())
1300 { 1028 {
1301 if (currWin->id != NULL) 1029 if (currWin->id != NULL)
1302 { 1030 {
1303 char *msg = th_strdup_printf("/prv -to %s -msg %s", currWin->id, buf); 1031 char *msg = th_strdup_printf("/prv -to %s -msg %s", currWin->id, buf);
1304 if (msg == NULL) return -3; 1032 if (msg == NULL) return -3;
1327 th_free(tmp); 1055 th_free(tmp);
1328 return result ? 0 : -1; 1056 return result ? 0 : -1;
1329 } 1057 }
1330 1058
1331 1059
1332 void nnwin_close_windows(void)
1333 {
1334 if (mainWin) delwin(mainWin);
1335 if (statusWin) delwin(statusWin);
1336 if (editWin) delwin(editWin);
1337 }
1338
1339
1340 BOOL nnwin_initialize_windows(void)
1341 {
1342 int w, h;
1343
1344 getmaxyx(stdscr, h, w);
1345
1346 nnwin_close_windows();
1347
1348 mainWin = subwin(stdscr, h - 4, w, 0, 0);
1349 statusWin = subwin(stdscr, 1, w, h - 4, 0);
1350 editWin = subwin(stdscr, 3, w, h - 3, 0);
1351
1352 if (mainWin == NULL || statusWin == NULL || editWin == NULL)
1353 return FALSE;
1354
1355 return TRUE;
1356 }
1357
1358
1359 void nnwin_update_all(void)
1360 {
1361 if (mainWin) redrawwin(mainWin);
1362 if (statusWin) redrawwin(statusWin);
1363 if (editWin) redrawwin(editWin);
1364 }
1365
1366
1367 static void nn_tabcomplete_replace(nn_editbuf_t *buf, size_t *pi, const size_t startPos, const size_t endPos, char *c) 1060 static void nn_tabcomplete_replace(nn_editbuf_t *buf, size_t *pi, const size_t startPos, const size_t endPos, char *c)
1368 { 1061 {
1369 size_t i; 1062 size_t i;
1370 1063
1371 for (i = startPos; i <= endPos; i++) 1064 for (i = startPos; i <= endPos; i++)
1576 optLogFile = NULL; 1269 optLogFile = NULL;
1577 } 1270 }
1578 } 1271 }
1579 1272
1580 1273
1581 char *promptRequester(WINDOW *win, const char *info, BOOL allowEmpty)
1582 {
1583 char tmpBuf[512], *ptr;
1584 size_t pos;
1585 int curVis = curs_set(1);
1586
1587 echo();
1588 waddstr(win, info);
1589 wgetnstr(win, tmpBuf, sizeof(tmpBuf) - 1);
1590 noecho();
1591 if (curVis != ERR)
1592 curs_set(curVis);
1593
1594 for (pos = strlen(tmpBuf) - 1; pos > 0 && th_isspace(tmpBuf[pos]); pos--)
1595 tmpBuf[pos] = 0;
1596
1597 ptr = str_trim_left(tmpBuf);
1598
1599 if (allowEmpty || strlen(ptr) > 0)
1600 return th_strdup(ptr);
1601 else
1602 return NULL;
1603 }
1604
1605
1606 void printHelp(void) 1274 void printHelp(void)
1607 { 1275 {
1608 printMsgQ(currWin, "\n" 1276 printMsgQ(currWin, "\n"
1609 "NNChat Help\n" 1277 "NNChat Help\n"
1610 "===========\n" 1278 "===========\n"
1616 1284
1617 1285
1618 int main(int argc, char *argv[]) 1286 int main(int argc, char *argv[])
1619 { 1287 {
1620 nn_conn_t *conn = NULL; 1288 nn_conn_t *conn = NULL;
1621 int curVis = ERR, updateCount = 0; 1289 int updateCount = 0;
1622 BOOL argsOK, isError = FALSE, 1290 BOOL argsOK, isError = FALSE,
1623 exitProg = FALSE, 1291 exitProg = FALSE,
1624 colorSet = FALSE, 1292 colorSet = FALSE,
1625 cursesInit = FALSE,
1626 networkInit = FALSE, 1293 networkInit = FALSE,
1627 insertMode = TRUE, 1294 insertMode = TRUE,
1628 firstUpdate = TRUE; 1295 firstUpdate = TRUE;
1629 time_t prevTime; 1296 time_t prevTime;
1630 char *tmpStr; 1297 char *tmpStr;
1631 nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); 1298 nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE);
1632 nn_editbuf_t *histBuf[SET_MAX_HISTORY+2]; 1299 nn_editbuf_t *histBuf[SET_MAX_HISTORY+2];
1633 int histPos = 0, histMax = 0; 1300 int histPos = 0, histMax = 0, index;
1634 1301
1635 cfgitem_t *tmpcfg; 1302 cfgitem_t *tmpcfg;
1636 char *setHomeDir = NULL; 1303 char *setHomeDir = NULL;
1637 1304
1638 memset(histBuf, 0, sizeof(histBuf)); 1305 memset(histBuf, 0, sizeof(histBuf));
1761 goto err_exit; 1428 goto err_exit;
1762 } 1429 }
1763 else 1430 else
1764 networkInit = TRUE; 1431 networkInit = TRUE;
1765 1432
1766 // Initialize NCurses 1433 // Initialize curses windowing
1767 if (!optDaemon) 1434 if (!optDaemon && !nnwin_init(SET_DELAY))
1768 { 1435 goto err_exit;
1769 if (LINES < 0 || LINES > 1000) LINES = 24; 1436
1770 if (COLS < 0 || COLS > 1000) COLS = 80; 1437 if (cursesInit)
1771 initscr(); 1438 nnwin_update_statusline(optUserName, optUserColor);
1772 raw();
1773 keypad(stdscr, TRUE);
1774 noecho();
1775 meta(stdscr, TRUE);
1776 timeout(SET_DELAY);
1777 curVis = curs_set(0);
1778
1779 if (has_colors())
1780 {
1781 start_color();
1782
1783 init_pair( 1, COLOR_RED, COLOR_BLACK);
1784 init_pair( 2, COLOR_GREEN, COLOR_BLACK);
1785 init_pair( 3, COLOR_YELLOW, COLOR_BLACK);
1786 init_pair( 4, COLOR_BLUE, COLOR_BLACK);
1787 init_pair( 5, COLOR_MAGENTA, COLOR_BLACK);
1788 init_pair( 6, COLOR_CYAN, COLOR_BLACK);
1789 init_pair( 7, COLOR_WHITE, COLOR_BLACK);
1790 init_pair( 8, COLOR_BLACK, COLOR_BLACK);
1791
1792 init_pair(10, COLOR_BLACK, COLOR_RED);
1793 init_pair(11, COLOR_WHITE, COLOR_RED);
1794 init_pair(12, COLOR_GREEN, COLOR_RED);
1795 init_pair(13, COLOR_YELLOW, COLOR_RED);
1796 init_pair(14, COLOR_BLUE, COLOR_RED);
1797 init_pair(15, COLOR_MAGENTA, COLOR_RED);
1798 init_pair(16, COLOR_CYAN, COLOR_RED);
1799 }
1800
1801 cursesInit = TRUE;
1802
1803 if (!nnwin_initialize_windows())
1804 goto err_exit;
1805
1806 #ifdef PDCURSES
1807 PDC_set_title("NNChat v" NN_VERSION);
1808 #endif
1809
1810 memset(chatWindows, 0, sizeof(chatWindows));
1811 chatWindows[0] = nn_window_new(NULL);
1812 currWin = chatWindows[0];
1813 nnwin_update_statusline();
1814 }
1815 1439
1816 // Check if we have username and password 1440 // Check if we have username and password
1817 if (cursesInit && (optUserName == NULL || optPassword == NULL)) 1441 if (cursesInit && (optUserName == NULL || optPassword == NULL))
1818 { 1442 {
1819 nnwin_print(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n"); 1443 nnwin_print(editWin, "You can avoid this prompt by issuing '/save' after logging in.\n");
1820 optUserName = promptRequester(editWin, "NN username: ", FALSE); 1444 optUserName = nnwin_prompt_requester(editWin, "NN username: ", FALSE);
1821 optPassword = promptRequester(editWin, "NN password: ", TRUE); 1445 optPassword = nnwin_prompt_requester(editWin, "NN password: ", TRUE);
1822 } 1446 }
1823 1447
1824 if (optUserName == NULL || optPassword == NULL) 1448 if (optUserName == NULL || optPassword == NULL)
1825 { 1449 {
1826 errorMsg("Username and/or password not specified.\n"); 1450 errorMsg("Username and/or password not specified.\n");
1907 // Initialize rest of interactive UI code 1531 // Initialize rest of interactive UI code
1908 nn_editbuf_clear(editBuf); 1532 nn_editbuf_clear(editBuf);
1909 1533
1910 // First update of screen 1534 // First update of screen
1911 nnwin_update_editbuf(editBuf); 1535 nnwin_update_editbuf(editBuf);
1912 nnwin_update_statusline(); 1536 nnwin_update_statusline(optUserName, optUserColor);
1913 1537
1914 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); 1538 printMsg(NULL, "%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname);
1915 printMsg(NULL, "%s\n", th_prog_author); 1539 printMsg(NULL, "%s\n", th_prog_author);
1916 printMsg(NULL, "%s\n", th_prog_license); 1540 printMsg(NULL, "%s\n", th_prog_license);
1917 } 1541 }
2040 wgetch(stdscr); 1664 wgetch(stdscr);
2041 } 1665 }
2042 if (c >= 0x31 && c <= 0x39) 1666 if (c >= 0x31 && c <= 0x39)
2043 { 1667 {
2044 // Chat window switching via Meta/Esc-[1..9] 1668 // Chat window switching via Meta/Esc-[1..9]
2045 int win = c - 0x31; 1669 nn_window_t *win = nnwin_get(c - 0x30);
2046 if (win < SET_MAX_WINDOWS && chatWindows[win] != NULL) 1670 if (win != NULL)
2047 { 1671 {
2048 currWin = chatWindows[win]; 1672 currWin = win;
2049 update = updateMain = TRUE; 1673 update = updateMain = TRUE;
2050 } 1674 }
2051 c = ERR; 1675 c = ERR;
2052 } 1676 }
2053 else 1677 else
2076 case KEY_RESIZE: 1700 case KEY_RESIZE:
2077 resize_term(0, 0); 1701 resize_term(0, 0);
2078 erase(); 1702 erase();
2079 timeout(SET_DELAY); 1703 timeout(SET_DELAY);
2080 1704
2081 if (!nnwin_initialize_windows()) 1705 if (!nnwin_init_windows())
2082 { 1706 {
2083 errorMsg("Error resizing curses chatWindows\n"); 1707 errorMsg("Error resizing curses chatWindows\n");
2084 isError = TRUE; 1708 isError = TRUE;
2085 } 1709 }
2086 update = updateMain = TRUE; 1710 update = updateMain = TRUE;
2289 nnwin_update_main(updateMain); 1913 nnwin_update_main(updateMain);
2290 1914
2291 if (update || firstUpdate) 1915 if (update || firstUpdate)
2292 { 1916 {
2293 // Update edit line 1917 // Update edit line
2294 nnwin_update_statusline(); 1918 nnwin_update_statusline(optUserName, optUserColor);
2295 nnwin_update_editbuf(editBuf); 1919 nnwin_update_editbuf(editBuf);
2296 firstUpdate = FALSE; // a nasty hack ... 1920 firstUpdate = FALSE; // a nasty hack ...
2297 } 1921 }
2298 1922
2299 } // cursesInit 1923 } // cursesInit
2313 { 1937 {
2314 colorSet = TRUE; 1938 colorSet = TRUE;
2315 nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); 1939 nn_conn_send_msg_v(conn, optUserNameEnc, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor);
2316 } 1940 }
2317 1941
2318 nnwin_update_statusline(); 1942 nnwin_update_statusline(optUserName, optUserColor);
2319 nnwin_update_editbuf(editBuf); 1943 nnwin_update_editbuf(editBuf);
2320 updateCount = 0; 1944 updateCount = 0;
2321 } 1945 }
2322 1946
2323 } 1947 }
2328 th_free(setHomeDir); 1952 th_free(setHomeDir);
2329 th_llist_free_func(setIdleMessages, th_free); 1953 th_llist_free_func(setIdleMessages, th_free);
2330 nn_userhash_free(nnUsers); 1954 nn_userhash_free(nnUsers);
2331 nn_editbuf_free(editBuf); 1955 nn_editbuf_free(editBuf);
2332 1956
2333 { 1957 for (index = 0; index <= SET_MAX_HISTORY; index++)
2334 int i; 1958 nn_editbuf_free(histBuf[index]);
2335 for (i = 0; i <= SET_MAX_HISTORY; i++) 1959
2336 nn_editbuf_free(histBuf[i]); 1960 nnwin_shutdown();
2337
2338 for (i = 0; i < SET_MAX_WINDOWS; i++)
2339 nn_window_free(chatWindows[i]);
2340 }
2341 1961
2342 #ifdef __WIN32 1962 #ifdef __WIN32
2343 if (errorMessages) 1963 if (errorMessages)
2344 { 1964 {
2345 char *tmp; 1965 char *tmp;
2347 tmp = promptRequester(editWin, "Press enter to quit.\n", FALSE); 1967 tmp = promptRequester(editWin, "Press enter to quit.\n", FALSE);
2348 th_free(tmp); 1968 th_free(tmp);
2349 } 1969 }
2350 #endif 1970 #endif
2351 1971
2352 if (cursesInit)
2353 {
2354 if (curVis != ERR)
2355 curs_set(curVis);
2356 nnwin_close_windows();
2357 endwin();
2358 THMSG(1, "NCurses deinitialized.\n");
2359 }
2360 1972
2361 #ifndef __WIN32 1973 #ifndef __WIN32
2362 if (errorMessages) 1974 if (errorMessages)
2363 THERR("%s", errorMessages); 1975 THERR("%s", errorMessages);
2364 #endif 1976 #endif