diff options
Diffstat (limited to 'mbbsd')
-rw-r--r-- | mbbsd/chat.c | 10 | ||||
-rw-r--r-- | mbbsd/edit.c | 2 | ||||
-rw-r--r-- | mbbsd/io.c | 60 | ||||
-rw-r--r-- | mbbsd/talk.c | 14 | ||||
-rw-r--r-- | mbbsd/visio.c | 286 |
5 files changed, 324 insertions, 48 deletions
diff --git a/mbbsd/chat.c b/mbbsd/chat.c index e7b5f1dd..fe954bfc 100644 --- a/mbbsd/chat.c +++ b/mbbsd/chat.c @@ -402,7 +402,7 @@ t_chat(void) #ifdef DBCSAWARE if(currchar > 0 && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar) == DBCS_TRAILING) + DBCS_Status(inbuf, currchar) == DBCS_TRAILING) currchar --; #endif } @@ -414,7 +414,7 @@ t_chat(void) #ifdef DBCSAWARE if(inbuf[currchar] && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar) == DBCS_TRAILING) + DBCS_Status(inbuf, currchar) == DBCS_TRAILING) currchar++; #endif } @@ -503,12 +503,12 @@ t_chat(void) } print_chatid(chatid); move(b_lines - 1, chatid_len); - } else if (ch == Ctrl('H') || ch == '\177') { + } else if (ch == Ctrl('H') || ch == KEY_BS2) { if (currchar) { #ifdef DBCSAWARE int dbcs_off = 1; if (ISDBCSAWARE() && - getDBCSstatus((unsigned char*)inbuf, currchar-1) == DBCS_TRAILING) + DBCS_Status(inbuf, currchar-1) == DBCS_TRAILING) dbcs_off = 2; #endif currchar -= dbcs_off; @@ -532,7 +532,7 @@ t_chat(void) #ifdef DBCSAWARE int dbcs_off = 1; if (ISDBCSAWARE() && inbuf[currchar+1] && - getDBCSstatus((unsigned char*)inbuf, currchar+1) == DBCS_TRAILING) + DBCS_Status(inbuf, currchar+1) == DBCS_TRAILING) dbcs_off = 2; #endif inbuf[69] = '\0'; diff --git a/mbbsd/edit.c b/mbbsd/edit.c index 93c1735e..044517a2 100644 --- a/mbbsd/edit.c +++ b/mbbsd/edit.c @@ -3728,7 +3728,7 @@ vedit2(const char *fpath, int saveheader, int *islocal, int flags) curr_buf->insert_mode ^= 1; break; case Ctrl('H'): - case '\177': /* backspace */ + case KEY_BS2: /* backspace */ block_cancel(); if (curr_buf->ansimode) { curr_buf->ansimode = 0; @@ -757,33 +757,6 @@ peek_input(float f, int c) return 0; } - -#ifdef DBCSAWARE - -int getDBCSstatus(unsigned char *s, int pos) -{ - int sts = DBCS_ASCII; - while(pos >= 0) - { - if(sts == DBCS_LEADING) - sts = DBCS_TRAILING; - else if (*s >= 0x80) - { - sts = DBCS_LEADING; - } else { - sts = DBCS_ASCII; - } - s++, pos--; - } - return sts; -} - -#else - -#define dbcs_off (1) - -#endif - #define MAXLASTCMD 12 static int getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) @@ -828,7 +801,7 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) buf[1] = ch; // workaround for BBS-Lua break; } - if (ch == '\177' || ch == Ctrl('H')) { + if (ch == KEY_BS2 || ch == Ctrl('H')) { if (!clen) { bell(); continue; @@ -901,7 +874,7 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) --currchar; #ifdef DBCSAWARE if(currchar > 0 && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)buf, currchar) == DBCS_TRAILING) + DBCS_Status(buf, currchar) == DBCS_TRAILING) currchar --; #endif break; @@ -912,7 +885,7 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) ++currchar; #ifdef DBCSAWARE if(buf[currchar] && ISDBCSAWARE() && - getDBCSstatus((unsigned char*)buf, currchar) == DBCS_TRAILING) + DBCS_Status(buf, currchar) == DBCS_TRAILING) currchar++; #endif break; @@ -937,12 +910,12 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) clen = currchar = strlen(buf); break; - case '\177': + case KEY_BS2: case Ctrl('H'): if (!currchar) break; #ifdef DBCSAWARE - if (ISDBCSAWARE() && getDBCSstatus((unsigned char*)buf, + if (ISDBCSAWARE() && DBCS_Status(buf, currchar-1) == DBCS_TRAILING) { memmove(buf+currchar-1, buf+currchar, clen-currchar+1); @@ -958,8 +931,8 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) if (!buf[currchar]) break; #ifdef DBCSAWARE - if (ISDBCSAWARE() && buf[currchar+1] && getDBCSstatus( - (unsigned char*)buf, currchar+1) == DBCS_TRAILING) + if (ISDBCSAWARE() && buf[currchar+1] && DBCS_Status( + buf, currchar+1) == DBCS_TRAILING) { memmove(buf+currchar, buf+currchar+1, clen-currchar); clen --; @@ -1035,25 +1008,42 @@ getdata_raw(int line, int col, const char *prompt, char *buf, int len, int echo) int getdata_buf(int line, int col, const char *prompt, char *buf, int len, int echo) { +#ifdef TRY_VGETS + move(line, col); + if(prompt && *prompts) outs(prompt); + return vgetstr(buf, len, echo ? VGET_DOECHO : VGET_NOECHO, buf); +#else return getdata_raw(line, col, prompt, buf, len, echo); +#endif } int getdata_str(int line, int col, const char *prompt, char *buf, int len, int echo, const char *defaultstr) { +#ifdef TRY_VGETS + move(line, col); + if(prompt && *prompts) outs(prompt); + return vgetstr(buf, len, echo ? VGET_DOECHO : VGET_NOECHO, defaultstr); +#else // if pointer is the same, ignore copy. if (defaultstr != buf) strlcpy(buf, defaultstr, len); - return getdata_raw(line, col, prompt, buf, len, echo); +#endif } int getdata(int line, int col, const char *prompt, char *buf, int len, int echo) { +#ifdef TRY_VGETS + move(line, col); + if(prompt) outs(prompt); + return vgets(buf, len, echo ? VGET_DOECHO : VGET_NOECHO); +#else buf[0] = 0; return getdata_raw(line, col, prompt, buf, len, echo); +#endif } int diff --git a/mbbsd/talk.c b/mbbsd/talk.c index 824b4651..778e4f04 100644 --- a/mbbsd/talk.c +++ b/mbbsd/talk.c @@ -1227,7 +1227,7 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) #ifdef DBCSAWARE if(twin->curcol > 0 && twin->curcol < line->len && ISDBCSAWARE()) { - if(getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) + if(DBCS_Status((char*)line->data, twin->curcol) == DBCS_TRAILING) twin->curcol --; } #endif @@ -1241,7 +1241,7 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) #ifdef DBCSAWARE if(twin->curcol < TALK_MAXCOL && twin->curcol < line->len && ISDBCSAWARE()) { - if(getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) + if(DBCS_Status((char*)line->data, twin->curcol) == DBCS_TRAILING) twin->curcol++; } #endif @@ -1262,7 +1262,7 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) #ifdef DBCSAWARE // curln may be changed. if(twin->curcol > 0 && twin->curcol < line->len && - getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) + DBCS_Status((char*)line->data, twin->curcol) == DBCS_TRAILING) twin->curcol--; #endif move(twin->curln, twin->curcol); @@ -1282,7 +1282,7 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) // curln may be changed. line = twin->big_picture + (twin->curln -twin->sline); if(twin->curcol > 0 && twin->curcol < line->len && - getDBCSstatus(line->data, twin->curcol) == DBCS_TRAILING) + DBCS_Status((char*)line->data, twin->curcol) == DBCS_TRAILING) twin->curcol--; #endif move(twin->curln, twin->curcol); @@ -1291,14 +1291,14 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) // complex data change case Ctrl('H'): - case '\177': + case KEY_BS2: if (twin->curcol > 0) { int delta = 1; #ifdef DBCSAWARE if (twin->curcol > 1 && ISDBCSAWARE() && - getDBCSstatus(line->data, twin->curcol-1) == DBCS_TRAILING) + DBCS_Status((char*)line->data, twin->curcol-1) == DBCS_TRAILING) delta++; #endif memmove(line->data + twin->curcol-delta, line->data + twin->curcol, @@ -1317,7 +1317,7 @@ do_talk_char(talkwin_t * twin, int ch, FILE *flog) #ifdef DBCSAWARE if (ISDBCSAWARE() && - getDBCSstatus(line->data, twin->curcol) == DBCS_LEADING) + DBCS_Status((char*)line->data, twin->curcol) == DBCS_LEADING) delta++; #endif memmove(line->data + twin->curcol, line->data + twin->curcol+delta, diff --git a/mbbsd/visio.c b/mbbsd/visio.c index 7001f23e..499467a5 100644 --- a/mbbsd/visio.c +++ b/mbbsd/visio.c @@ -674,3 +674,289 @@ vs_cols(const VCOL *cols, const VCOLW *ws, int n, ...) outs(ANSI_RESET "\n"); } +//////////////////////////////////////////////////////////////////////// +// DBCS Aware Helpers +//////////////////////////////////////////////////////////////////////// + +#ifdef DBCSAWARE +# define CHKDBCSTRAIL(_buf,_i) (/*ISDBCSAWARE() &&*/ DBCS_Status(_buf, _i) == DBCS_TRAILING) +#else // !DBCSAWARE +# define CHKDBCSTRAIL(buf,i) (0) +#endif // !DBCSAWARE + +//////////////////////////////////////////////////////////////////////// +// History Helpers +//////////////////////////////////////////////////////////////////////// +// +#define IH_MAX_ENTRIES (12) + +typedef struct { + int icurr; // current retrival pointer + int iappend; // new location to append + char buf[IH_MAX_ENTRIES][STRLEN]; +} InputHistory; + +static InputHistory ih; // everything intialized to zero. + +int +InputHistoryAdd(const char *s) +{ + int i = 0; + if (!s || !*s || !*(s+1)) + return 0; + for (i = 0; i < IH_MAX_ENTRIES; i++) + if (strcmp(s, ih.buf[i]) == 0) + return 0; + // TODO if already in queue, reject. + strlcpy(ih.buf[ih.iappend], s, sizeof(ih.buf[ih.iappend])); + ih.icurr = ih.iappend; + ih.iappend ++; + ih.iappend %= IH_MAX_ENTRIES; + return 1; +} + +static void +InputHistoryDelta(char *s, int sz, int d) +{ + int i, xcurr = 0; + for (i = 1; i <= IH_MAX_ENTRIES; i++) + { + xcurr = (ih.icurr+d*i)%IH_MAX_ENTRIES; + if (ih.buf[xcurr][0]) + { + ih.icurr = xcurr; + break; + } + } + if (ih.buf[ih.icurr][0]) + { + strlcpy(s, ih.buf[ih.icurr], sz); + // ih.icurr += d; + // ih.icurr %= IH_MAX_ENTRIES; + } +} + +void +InputHistoryPrev(char *s, int sz) +{ + InputHistoryDelta(s, sz, IH_MAX_ENTRIES-1); +} + +void +InputHistoryNext(char *s, int sz) +{ + InputHistoryDelta(s, sz, +1); +} + +//////////////////////////////////////////////////////////////////////// +// vget*: mini editbox +//////////////////////////////////////////////////////////////////////// +int +vgets(char *buf, int len, int flags) +{ + return vgetstr(buf, len, flags, ""); +} + +int +vgetstr(char *_buf, int len, int flags, const char *defstr) +{ + // iend points to NUL address, and + // icurr points to cursor. + int line, col; + int icurr = 0, iend = 0, abort = 0; + int c; + + // always use internal buffer to prevent temporary input issue. + char buf[STRLEN] = ""; + + // it is wrong to design input with larger buffer + // than STRLEN. Although we support large screen, + // inputting huge line will just make troubles... + if (len > STRLEN) len = STRLEN; + assert(len <= sizeof(buf)); + + // memset(buf, 0, len); + if (defstr && *defstr) + { + strlcpy(buf, defstr, len); + icurr = iend = strlen(buf); + } + + getyx(&line, &col); // now (line,col) is the beginning of our new fields. + + while (!abort) + { + if (!(flags & VGET_NOECHO)) + { + // print current buffer + move(line, col); + clrtoeol(); + SOLVE_ANSI_CACHE(); + outs(VCLR_INPUT_FIELD); // change color to prompt fields + vfill(len, 0, buf); + outs(ANSI_RESET); + + // move to cursor position + move(line, col+icurr); + } + c = vkey(); + + 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) { + bell(); + continue; + } + InputHistoryAdd(buf); + if (c == KEY_DOWN) + InputHistoryNext(buf, len); + else + InputHistoryPrev(buf, len); + icurr = iend = strlen(buf); + break; + + // exiting keys + case '\n': case '\r': + // confirm again. + buf[iend] = 0; + abort = 1; + break; + + case Ctrl('C'): + icurr = iend = 0; + buf[1] = c; + buf[iend] = 0; + abort = 1; + break; + + // standard navigation + case KEY_HOME: case Ctrl('A'): + icurr = 0; + break; + + case KEY_END: case Ctrl('E'): + icurr = iend; + break; + + case KEY_LEFT: case Ctrl('B'): + if (icurr > 0) + icurr--; + else + bell(); + if (icurr > 0 && CHKDBCSTRAIL(buf, icurr)) + icurr--; + break; + + case KEY_RIGHT: case Ctrl('F'): + if (icurr < iend) + icurr++; + else + bell(); + if (icurr < iend && CHKDBCSTRAIL(buf, icurr)) + icurr++; + break; + + // editing keys + case KEY_DEL: case Ctrl('D'): + if (icurr+1 < iend && CHKDBCSTRAIL(buf, icurr+1)) { + // kill next one character. + memmove(buf+icurr, buf+icurr+1, iend-icurr); + iend--; + } else + bell(); + if (icurr < iend) { + // kill next one character. + memmove(buf+icurr, buf+icurr+1, iend-icurr); + iend--; + } + break; + + case Ctrl('H'): case KEY_BS2: + if (icurr > 0) { + // kill previous one charracter. + memmove(buf+icurr-1, buf+icurr, iend-icurr+1); + icurr--; iend--; + } else + bell(); + if (icurr > 0 && CHKDBCSTRAIL(buf, icurr)) { + // kill previous one charracter. + memmove(buf+icurr-1, buf+icurr, iend-icurr+1); + icurr--; iend--; + } + break; + + case Ctrl('Y'): + icurr = 0; + // reuse Ctrl-K code + case Ctrl('K'): + iend = icurr; + buf[iend] = 0; + break; + + // defaults + default: + + // content filter + if (c < ' ' || c >= 0xFF || + iend+1 >= len) + { + bell(); + continue; + } + if ((flags & VGET_DIGITS) && + ( !isascii(c) || !isdigit(c))) + { + bell(); + continue; + } + if (flags & VGET_LOWERCASE) + { + if (!isascii(c)) + { + bell(); + continue; + } + c = tolower(c); + } + + // prevent incomplete DBCS + // this check only works if DBCS-aware is active. + // Otherwise, non-DBCS-aware users will fail to + // input the final DBCS-TRAIL character. +#ifdef DBCSAWARE + if (ISDBCSAWARE() && + c > 0x80 && iend+2 >= len && + !CHKDBCSTRAIL(buf, icurr) ) + { + bell(); + continue; + } +#endif // DBCSAWARE + + // add one character. + memmove(buf+icurr+1, buf+icurr, iend-icurr+1); + buf[icurr++] = c; + iend++; + break; + } + } + + assert(iend >= 0 && iend < len); + buf[iend] = 0; + + // final filtering + if (iend && (flags & VGET_LOWERCASE)) + buf[0] = tolower(buf[0]); + + // save the history except password mode + if (!(flags & VGET_NOECHO)) + InputHistoryAdd(buf); + + // copy buffer! + memcpy(_buf, buf, len); + return iend; +} |