diff options
-rw-r--r-- | pttbbs/include/vtuikit.h | 9 | ||||
-rw-r--r-- | pttbbs/mbbsd/io.c | 2 | ||||
-rw-r--r-- | pttbbs/mbbsd/name.c | 19 | ||||
-rw-r--r-- | pttbbs/mbbsd/vtuikit.c | 250 |
4 files changed, 151 insertions, 129 deletions
diff --git a/pttbbs/include/vtuikit.h b/pttbbs/include/vtuikit.h index 7a2080a9..4866db4f 100644 --- a/pttbbs/include/vtuikit.h +++ b/pttbbs/include/vtuikit.h @@ -56,7 +56,11 @@ #define VGET_DIGITS (0x04) #define VGET_TRANSPARENT (0x08) #define VGET_ASCII_ONLY (0x10) -#define VGET_PASSWORD (VGET_NOECHO | VGET_ASCII_ONLY) +#define VGET_NO_NAV_HISTORY (0x20) // disable UP/DOWN +#define VGET_NO_NAV_EDIT (0x40) // disable LEFT/RIGHT/HOME/END/DEL + +#define VGETSET_DUMB_TERM (VGET_NO_NAV_HISTORY | VGET_NO_NAV_EDIT) +#define VGETSET_PASSWORD (VGET_NOECHO | VGET_ASCII_ONLY | VGETSET_DUMB_TERM) // DATATYPE DEFINITION ------------------------------------------------- typedef void * VREFSCR; @@ -95,7 +99,8 @@ typedef int (*VGET_FCALLBACK)(int key, VGET_RUNTIME *prt, void *instance); typedef struct { VGET_FCALLBACK peek; // called immediately after key hit VGET_FCALLBACK data; // called before inserting character data - VGET_FCALLBACK post; // called after every data inserted into buffer. + VGET_FCALLBACK change; // called after buffer changed (the key may be an editing key) + VGET_FCALLBACK redraw; // called before drawing input box unless VGET_NOECHO } VGET_CALLBACKS; // API DEFINITION ---------------------------------------------------- diff --git a/pttbbs/mbbsd/io.c b/pttbbs/mbbsd/io.c index 42e24f10..e0b017ba 100644 --- a/pttbbs/mbbsd/io.c +++ b/pttbbs/mbbsd/io.c @@ -713,7 +713,7 @@ getdata2vgetflag(int echo) else if (echo == NUMECHO) echo = VGET_DIGITS; else if (echo == NOECHO) - echo = VGET_PASSWORD; + echo = VGETSET_PASSWORD; else echo = VGET_DEFAULT; diff --git a/pttbbs/mbbsd/name.c b/pttbbs/mbbsd/name.c index 803434b8..d4cef005 100644 --- a/pttbbs/mbbsd/name.c +++ b/pttbbs/mbbsd/name.c @@ -108,20 +108,12 @@ nc_cb_peek(int key, VGET_RUNTIME *prt, void *instance) return VGETCB_NEXT; break; - case KEY_BS: /* backspace */ + case KEY_BS: /* backspace */ + case KEY_UP: /* history */ + case KEY_DOWN: /* history */ nc_int->dirty = -1; break; - case KEY_HOME: case Ctrl('A'): - case KEY_END: case Ctrl('E'): - case KEY_LEFT: case Ctrl('B'): - case KEY_RIGHT: case Ctrl('F'): - case KEY_DEL: case Ctrl('D'): - case Ctrl('Y'): - case Ctrl('K'): - return VGETCB_NEXT; - break; - default: if (isprint(key)) { struct Vector tmplist; @@ -158,14 +150,15 @@ namecomplete2(const struct Vector *namelist, const char *prompt, char *data) VGET_CALLBACKS vcb = { .peek = nc_cb_peek, .data = NULL, - .post = NULL, + .change = NULL, + .redraw = NULL, }; outs(prompt); clrtoeol(); Vector_init(&nc_int.sublist, IDLEN+1); Vector_sublist(namelist, &nc_int.sublist, ""); - vgetstring(data, IDLEN + 1, VGET_ASCII_ONLY, NULL, &vcb, &nc_int); + vgetstring(data, IDLEN + 1, VGET_ASCII_ONLY|VGET_NO_NAV_EDIT, NULL, &vcb, &nc_int); Vector_delete(&nc_int.sublist); } diff --git a/pttbbs/mbbsd/vtuikit.c b/pttbbs/mbbsd/vtuikit.c index a18df7a1..351c3d4e 100644 --- a/pttbbs/mbbsd/vtuikit.c +++ b/pttbbs/mbbsd/vtuikit.c @@ -971,8 +971,8 @@ vgetstring(char *_buf, int len, int flags, const char *defstr, const VGET_CALLBA // rt.iend points to NUL address, and // rt.icurr points to cursor. int line, col; - int abort = 0; - int c; + int abort = 0, dirty = 0; + int c = 0; char ismsgline = 0; // callback @@ -990,6 +990,10 @@ vgetstring(char *_buf, int len, int flags, const char *defstr, const VGET_CALLBA if (len > STRLEN) len = STRLEN; assert(len <= sizeof(buf) && len >= 2); + // adjust flags + if (flags & (VGET_NOECHO | VGET_DIGITS)) + flags |= VGET_NO_NAV_HISTORY; + // memset(buf, 0, len); if (defstr && *defstr) { @@ -1014,8 +1018,20 @@ vgetstring(char *_buf, int len, int flags, const char *defstr, const VGET_CALLBA // main loop while (!abort) { + if (dirty) + { + dirty = 0; + // callback: change + if (_vgetcbhandler(cb.change, &abort, c, &rt, instance)) + continue; + } + if (!(flags & VGET_NOECHO)) { + // callback: redraw + if (_vgetcbhandler(cb.redraw, &abort, c, &rt, instance)) + continue; + // print current buffer move(line, col); clrtoeol(); @@ -1038,74 +1054,43 @@ vgetstring(char *_buf, int len, int flags, const char *defstr, const VGET_CALLBA } c = vkey(); - // callback 1: peek + // callback: peek if (_vgetcbhandler(cb.peek, &abort, c, &rt, instance)) continue; // standard key bindings - switch(c) { - // history navigation - case KEY_DOWN: case Ctrl('N'): - c = KEY_DOWN; - // let UP do the magic. - case KEY_UP: case Ctrl('P'): - if ((flags & VGET_NOECHO) || - (flags & VGET_DIGITS)) - { - bell(); - continue; - } + // note: if you processed anything, you must use 'continue' instead of 'break'. - // NOECHO is already checked... - if (!InputHistoryExists(buf)) - InputHistoryAdd(buf); - - if (c == KEY_DOWN) - InputHistoryNext(buf, len); - else - InputHistoryPrev(buf, len); - - rt.icurr = rt.iend = strlen(buf); - break; - - // exiting keys - case KEY_ENTER: - abort = 1; - break; - - case Ctrl('C'): - rt.icurr = rt.iend = 0; - buf[0] = 0; - buf[1] = c; - abort = 1; - break; + if (flags & VGET_NO_NAV_EDIT) { + // skip navigation editing keys + } else switch (c) { // standard navigation case KEY_HOME: case Ctrl('A'): rt.icurr = 0; - break; + continue; case KEY_END: case Ctrl('E'): rt.icurr = rt.iend; - break; + continue; case KEY_LEFT: case Ctrl('B'): if (rt.icurr > 0) - rt.icurr--; + rt.icurr--; else bell(); if (rt.icurr > 0 && CHKDBCSTRAIL(buf, rt.icurr)) rt.icurr--; - break; + continue; case KEY_RIGHT: case Ctrl('F'): if (rt.icurr < rt.iend) - rt.icurr++; + rt.icurr++; else bell(); if (rt.icurr < rt.iend && CHKDBCSTRAIL(buf, rt.icurr)) rt.icurr++; - break; + continue; // editing keys case KEY_DEL: case Ctrl('D'): @@ -1113,101 +1098,140 @@ vgetstring(char *_buf, int len, int flags, const char *defstr, const VGET_CALLBA // kill next one character. memmove(buf+rt.icurr, buf+rt.icurr+1, rt.iend-rt.icurr); rt.iend--; + dirty = 1; } if (rt.icurr < rt.iend) { // kill next one character. memmove(buf+rt.icurr, buf+rt.icurr+1, rt.iend-rt.icurr); rt.iend--; + dirty = 1; } - break; + continue; + + case Ctrl('Y'): + rt.icurr = 0; + // reuse Ctrl-K code + case Ctrl('K'): + rt.iend = rt.icurr; + if (!buf[rt.iend]) + continue; + buf[rt.iend] = 0; + dirty = 1; + continue; + } + + if (flags & VGET_NO_NAV_HISTORY) { + // skip navigation history keys + } else switch (c) { + // history navigation + case KEY_DOWN: case Ctrl('N'): + c = KEY_DOWN; + // let UP do the magic. + case KEY_UP: case Ctrl('P'): + // NOECHO is already checked... + if (!InputHistoryExists(buf)) + InputHistoryAdd(buf); + if (c == KEY_DOWN) + InputHistoryNext(buf, len); + else + InputHistoryPrev(buf, len); + + rt.icurr = rt.iend = strlen(buf); + dirty = 1; + continue; + } + + // the basic keys + switch(c) + { + // exiting keys + case KEY_ENTER: + abort = 1; + continue; + + case Ctrl('C'): + rt.icurr = rt.iend = 0; + buf[0] = 0; + buf[1] = c; // XXX this is a dirty hack... + abort = 1; + continue; + + // standard editing keys: backspace case KEY_BS: if (rt.icurr > 0) { // kill previous one charracter. memmove(buf+rt.icurr-1, buf+rt.icurr, rt.iend-rt.icurr+1); rt.icurr--; rt.iend--; + dirty = 1; } else bell(); if (rt.icurr > 0 && CHKDBCSTRAIL(buf, rt.icurr)) { // kill previous one charracter. memmove(buf+rt.icurr-1, buf+rt.icurr, rt.iend-rt.icurr+1); rt.icurr--; rt.iend--; + dirty = 1; } - break; - - case Ctrl('Y'): - rt.icurr = 0; - // reuse Ctrl-K code - case Ctrl('K'): - rt.iend = rt.icurr; - buf[rt.iend] = 0; - break; - - // defaults - default: - - // content filter - if (c < ' ' || c >= 0xFF) - { - bell(); continue; - } - if ((flags & VGET_DIGITS) && - ( !isascii(c) || !isdigit(c))) - { - bell(); continue; - } - if (flags & VGET_LOWERCASE) - { - if (!isascii(c)) - { - bell(); continue; - } - c = tolower(c); - } - if (flags & VGET_ASCII_ONLY) - { - if (!isprint(c)) - { - bell(); continue; - } - } + continue; + } - // size check - if(rt.iend+1 >= len) - { - bell(); continue; - } + // all special keys were processed, now treat as 'input data'. - // prevent incomplete DBCS - if (c > 0x80 && num_in_buf() && - len - rt.iend < 3) // we need 3 for DBCS+NUL. - { - drop_input(); - bell(); - continue; - } - - // callback 2: data - if (_vgetcbhandler(cb.data, &abort, c, &rt, instance)) - continue; + // content filter + if (c < ' ' || c >= 0xFF) + { + bell(); continue; + } + if ((flags & VGET_DIGITS) && + ( !isascii(c) || !isdigit(c))) + { + bell(); continue; + } + if (flags & VGET_LOWERCASE) + { + if (!isascii(c)) + { + bell(); continue; + } + c = tolower(c); + } + if (flags & VGET_ASCII_ONLY) + { + if (!isascii(c) || !isprint(c)) + { + bell(); continue; + } + } - // size check again, due to data callback. - if(rt.iend+1 >= len) - { - bell(); continue; - } + // size check + if(rt.iend+1 >= len) + { + bell(); continue; + } - // add one character. - memmove(buf+rt.icurr+1, buf+rt.icurr, rt.iend-rt.icurr+1); - buf[rt.icurr++] = c; - rt.iend++; + // prevent incomplete DBCS + if (c > 0x80 && num_in_buf() && + len - rt.iend < 3) // we need 3 for DBCS+NUL. + { + drop_input(); + bell(); continue; + } - // callback 3: post - if (_vgetcbhandler(cb.post, &abort, c, &rt, instance)) - continue; + // callback: data + if (_vgetcbhandler(cb.data, &abort, c, &rt, instance)) + continue; - break; + // size check again, due to data callback. + if(rt.iend+1 >= len) + { + bell(); continue; } + + // add one character. + memmove(buf+rt.icurr+1, buf+rt.icurr, rt.iend-rt.icurr+1); + buf[rt.icurr++] = c; + rt.iend++; + dirty = 1; } assert(rt.iend >= 0 && rt.iend < len); |