summaryrefslogtreecommitdiffstats
path: root/mbbsd
diff options
context:
space:
mode:
Diffstat (limited to 'mbbsd')
-rw-r--r--mbbsd/chat.c10
-rw-r--r--mbbsd/edit.c2
-rw-r--r--mbbsd/io.c60
-rw-r--r--mbbsd/talk.c14
-rw-r--r--mbbsd/visio.c286
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;
diff --git a/mbbsd/io.c b/mbbsd/io.c
index 3e1adbaa..ebf74f79 100644
--- a/mbbsd/io.c
+++ b/mbbsd/io.c
@@ -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;
+}