Mercurial > hg > nnchat
diff ui.c @ 513:ef5a2aa8382b
Refactor input handling.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 05 Jun 2012 22:16:42 +0300 |
parents | f71c59cbc5a7 |
children | 436e86afa70a |
line wrap: on
line diff
--- a/ui.c Tue Jun 05 19:56:57 2012 +0300 +++ b/ui.c Tue Jun 05 22:16:42 2012 +0300 @@ -6,7 +6,6 @@ #include "util.h" #include "ui.h" -#define STATUS_YPOS 0 nn_window_t *chatWindows[SET_MAX_WINDOWS], *currWin = NULL; @@ -292,27 +291,6 @@ } -char *nnwin_prompt_requester(const char *info, BOOL allowEmpty) -{ - char buf[512], *ptr; - - echo(); - wattrset(stdscr, A_NORMAL); - wbkgdset(stdscr, COLOR_PAIR(0)); - waddstr(stdscr, info); - wgetnstr(stdscr, buf, sizeof(buf) - 1); - noecho(); - - str_trim_right(buf); - ptr = str_trim_left(buf); - - if (allowEmpty || ptr[0]) - return th_strdup(ptr); - else - return NULL; -} - - static void nnwin_print_str(WINDOW *win, const char *fmt, BOOL clip) { const char *s = fmt; @@ -345,7 +323,7 @@ } -void nnwin_update(BOOL force, nn_editbuf_t *ebuf, char *username, int usercolor) +void nnwin_update(BOOL force, BOOL mask, nn_editbuf_t *ebuf, char *username, int usercolor) { int sx, sy; @@ -454,20 +432,244 @@ { int yoffs = ebuf->pos / scrWidth, xoffs = ebuf->pos % scrWidth; - char *tmp; - - ebuf->dirty = FALSE; - ebuf->data[ebuf->len] = 0; - tmp = nn_username_decode(th_strdup(ebuf->data)); wmove(stdscr, scrHeight - 3, 0); wattrset(stdscr, A_NORMAL); wbkgdset(stdscr, COLOR_PAIR(0)); - waddnstr(stdscr, tmp, ebuf->len); + + ebuf->dirty = FALSE; + if (mask) + { + size_t i; + for (i = 0; i < ebuf->len; i++) + waddch(stdscr, '*'); + } + else + { + char *tmp; + ebuf->data[ebuf->len] = 0; + tmp = nn_username_decode(th_strdup(ebuf->data)); + waddnstr(stdscr, tmp, ebuf->len); + th_free(tmp); + } wmove(stdscr, scrHeight - 3 + yoffs, xoffs); - th_free(tmp); } wrefresh(stdscr); } + + +void nnwin_input_process(nn_editbuf_t *editBuf, nn_editstate_t *editState, + BOOL (*callback)(int, nn_editbuf_t *, nn_editstate_t *)) +{ + int c, cnt = 0; + + // 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 == 10 || c == 13) + c = KEY_ENTER; + else + 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: + editState->debugMsg("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: + editState->debugMsg("Unhandled ESC-[*~ key sequence 0x%02x\n", c); + c = ERR; + break; + } + // Get the trailing ~ + if (c != ERR) + wgetch(stdscr); + } + else + if (c >= 0x31 && c <= 0x39) + { + c = c - 0x30 + 0x5000; + } + else + { + editState->debugMsg("Unhandled ESC key sequence 0x%02x\n", c); + } + } +#if defined(__WIN32) && defined(PDCURSES) + else + if (c >= 0x198 && c <= 0x1a0) + { + c = c - 0x198 + 0x5000; + } +#endif + + switch (c) + { +#ifdef KEY_RESIZE + case KEY_RESIZE: + resize_term(0, 0); + erase(); + timeout(SET_DELAY); + nnwin_reset(); + editState->update = TRUE; + break; +#endif + + 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 + editState->insertMode = !editState->insertMode; + break; + + case KEY_F(2): // F2 = Clear editbuffer + nn_editbuf_clear(editBuf); + break; + + case 0x0c: // Ctrl + L + editState->update = TRUE; + break; + + case ERR: + // Ignore + break; + + default: + if (!callback(c, editBuf, editState)) + { + if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) + { + if (editState->insertMode) + nn_editbuf_insert(editBuf, editBuf->pos, c); + else + nn_editbuf_write(editBuf, editBuf->pos, c); + nn_editbuf_setpos(editBuf, editBuf->pos + 1); + } + else + editState->debugMsg("Unhandled key: 0x%02x\n", c); + } + break; + } + } + while (c != ERR && ++cnt < 10); +} + + + +char *nnwin_prompt_requester(BOOL allowEmpty, nn_editstate_t *editState, + BOOL (*callback)(int, nn_editbuf_t *, nn_editstate_t *), + void (*update)(nn_editbuf_t *, nn_editstate_t *)) +{ + nn_editbuf_t *editBuf = nn_editbuf_new(NN_TMPBUF_SIZE); + char *res; + + editState->done = FALSE; + while (!editState->isError && !editState->exitProg && !editState->done) + { + nnwin_input_process(editBuf, editState, callback); + update(editBuf, editState); + } + + if (allowEmpty || editBuf->len > 0) + res = nn_editbuf_get_string(editBuf, 0, editBuf->len); + else + res = NULL; + + nn_editbuf_free(editBuf); + + return res; +}