summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2008-04-17 09:47:43 +0800
committerpiaip <piaip@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2008-04-17 09:47:43 +0800
commit9e11577128c92707c2db3f3e44814a3be0d7bf6f (patch)
tree25d438fbc3009315f1d9c54764225325921a2ccc
parente20bd69d66148c34fee47e1f1f372963a871c047 (diff)
downloadpttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar.gz
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar.bz2
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar.lz
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar.xz
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.tar.zst
pttbbs-9e11577128c92707c2db3f3e44814a3be0d7bf6f.zip
- (internal) visio: add vgets
- (internal) add key name KEY_BS2 - (internal) move getDBCSstatus to DBCS_Status git-svn-id: http://opensvn.csie.org/pttbbs/trunk/pttbbs@4174 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
-rw-r--r--common/sys/string.c20
-rw-r--r--include/cmsys.h8
-rw-r--r--include/common.h2
-rw-r--r--include/modes.h7
-rw-r--r--include/proto.h13
-rw-r--r--include/visio.h20
-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
11 files changed, 381 insertions, 61 deletions
diff --git a/common/sys/string.c b/common/sys/string.c
index 881a0e04..908f1fb4 100644
--- a/common/sys/string.c
+++ b/common/sys/string.c
@@ -311,6 +311,26 @@ int DBCS_RemoveIntrEscape(unsigned char *buf, int *len)
return (oldl != l) ? 1 : 0;
}
+int DBCS_Status(const char *dbcstr, int pos)
+{
+ int sts = DBCS_ASCII;
+ const unsigned char *s = (const unsigned char*)dbcstr;
+
+ 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;
+}
+
/* ----------------------------------------------------- */
/* 字串檢查函數:英文、數字、檔名、E-mail address */
/* ----------------------------------------------------- */
diff --git a/include/cmsys.h b/include/cmsys.h
index 0401da26..879b75e9 100644
--- a/include/cmsys.h
+++ b/include/cmsys.h
@@ -20,10 +20,17 @@ enum STRIP_FLAG {
ONLY_COLOR, // allow only colors (ESC [ .. m)
NO_RELOAD // allow all known (color+move)
};
+
enum LOG_FLAG {
LOG_CREAT = 1,
};
+/* DBCS aware modes */
+enum _DBCS_STATUS {
+ DBCS_ASCII,
+ DBCS_LEADING,
+ DBCS_TRAILING,
+};
#ifdef TIMET64
typedef int32_t time4_t;
@@ -85,6 +92,7 @@ extern int strip_blank(char *cbuf, char *buf);
extern int strip_ansi(char *buf, const char *str, enum STRIP_FLAG flag);
extern void strip_nonebig5(unsigned char *str, int maxlen);
extern int DBCS_RemoveIntrEscape(unsigned char *buf, int *len);
+extern int DBCS_Status(const char *dbcstr, int pos);
extern int invalid_pname(const char *str);
extern int is_number(const char *p);
extern char * qp_encode (char *s, size_t slen, const char *d, const char *tocode);
diff --git a/include/common.h b/include/common.h
index 2aabc0ff..cf390eee 100644
--- a/include/common.h
+++ b/include/common.h
@@ -136,6 +136,8 @@
/* 鍵盤設定 */
#define KEY_TAB 9
#define KEY_ESC 27
+#define KEY_BS (Ctrl('H'))
+#define KEY_BS2 (0x7f)
#define KEY_UP 0x0101
#define KEY_DOWN 0x0102
#define KEY_RIGHT 0x0103
diff --git a/include/modes.h b/include/modes.h
index 178add62..7ceb7ba9 100644
--- a/include/modes.h
+++ b/include/modes.h
@@ -168,13 +168,6 @@
#define AUTHOR_NEXT (RS_AUTHOR | RS_FORWARD)
#define AUTHOR_PREV (RS_AUTHOR)
-/* DBCS aware modes */
-enum _DBCS_STATUS {
- DBCS_ASCII,
- DBCS_LEADING,
- DBCS_TRAILING,
-};
-
#define SIG_PK 0
#define SIG_TALK 1
#define SIG_BROADCAST 2
diff --git a/include/proto.h b/include/proto.h
index 0b2cebde..674fea53 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -577,12 +577,16 @@ int inansistr(char *str, int n);
void move_ansi(int y, int x);
void getyx_ansi(int *py, int *px);
void region_scroll_up(int top, int bottom);
+
+#ifndef USE_PFTERM
+# define SOLVE_ANSI_CACHE() {}
+#else // !USE_PFTERM
+# define SOLVE_ANSI_CACHE() { outs(" \b"); }
+#endif // !USE_PFTERM
+
#define HAVE_GRAYOUT
void grayout(int start, int end, int level);
-void save_cursor(void);
-void restore_cursor(void);
-
/* AIDS */
typedef uint64_t aidu_t;
aidu_t fn2aidu(char *fn);
@@ -706,9 +710,8 @@ int u_cloak(void);
int u_list(void);
#ifdef DBCSAWARE
int u_detectDBCSAwareEvilClient();
-int getDBCSstatus(unsigned char *s, int pos);
-#define ISDBCSAWARE() (cuser.uflag & DBCSAWARE_FLAG)
#endif
+#define ISDBCSAWARE() (cuser.uflag & DBCSAWARE_FLAG)
/* vote */
void b_suckinfile(FILE *fp, char *fname);
diff --git a/include/visio.h b/include/visio.h
index b3164709..06b78907 100644
--- a/include/visio.h
+++ b/include/visio.h
@@ -24,6 +24,8 @@
#define VCLR_PAUSE_PAD ANSI_COLOR(1;34;44)
#define VCLR_PAUSE ANSI_COLOR(1;37;44)
+#define VCLR_INPUT_FIELD ANSI_COLOR(0;7)
+
#define VMSG_PAUSE " 請按任意鍵繼續 "
#define VMSG_PAUSE_PAD "▄"
#define VMSG_MSG_FLOAT " [按任意鍵繼續]"
@@ -42,6 +44,13 @@
#define VFILL_HAS_BORDER VFILL_DEFAULT
#define VFILL_NO_BORDER (0x08)
+#define VGET_DEFAULT (0x00)
+#define VGET_DOECHO (VGET_DEFAULT)
+#define VGET_NOECHO (0x01)
+#define VGET_LOWERCASE (0x02)
+#define VGET_DIGITS (0x04)
+#define VGET_GCARRY (0x08)
+
// DATATYPE DEFINITION -------------------------------------------------
typedef void * VREFSCR;
typedef long VREFCUR;
@@ -66,11 +75,16 @@ typedef struct {
void prints(const char *fmt, ...) GCC_CHECK_FORMAT(1,2);
void mvouts(int y, int x, const char *str);
+// input history
+int InputHistoryAdd (const char *s);
+void InputHistoryPrev(char *s, int sz);
+void InputHistoryNext(char *s, int sz);
+
// v*: primitive rendering
void vpad (int n, const char *pattern); /// pad n fields by pattern
int vgety (void); /// return cursor position (y)
void vfill (int n, int flags, const char *s); /// fill n-width space with s
-void vfillf (int n, int flags, const char *s, ...) GCC_CHECK_FORMAT(3,4); // formatted version of vfill
+void vfillf (int n, int flags, const char *s, ...) GCC_CHECK_FORMAT(3,4); /// formatted version of vfill
void vbarlr (const char *l, const char *r); /// draw a left-right expanded bar with (l,r)
void vbarf (const char *s, ...) GCC_CHECK_FORMAT(1,2); /// vbarlr with formatted input (\t splits (l,r)
void vshowmsg(const char *msg); /// draw standard pause/message
@@ -82,6 +96,10 @@ void vshowmsg(const char *msg); /// draw standard pause/message
int vans (const char *msg); /// prompt and return (lowercase) single byte input
int vansf (const char *fmt,...) GCC_CHECK_FORMAT(1,2); /// formatted input of vans
+// vget: (y, x, ...)
+int vgets (char *buf, int len, int flags); /// input with edit box control
+int vgetstr (char *buf, int len, int flags, const char *str);/// input with default value
+int vget(int y, int x, const char *prompt, char *buf, int len, int mode);
// vs_*: formatted and themed virtual screen layout
// you cannot use ANSI escapes in these APIs.
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;
+}