From 7f8e2298181fcbf3399eb9bde1564c1fe2fe9df3 Mon Sep 17 00:00:00 2001 From: Peter Stephenson Date: Fri, 26 Oct 2007 21:59:56 +0000 Subject: 24024: add zcurses input with keypad handling --- Src/Modules/curses.c | 114 ++++++++++++++++++++++++++++++++++++++++++++ Src/Modules/curses.mdd | 6 +++ Src/Modules/curses_keys.awk | 19 ++++++++ 3 files changed, 139 insertions(+) create mode 100644 Src/Modules/curses_keys.awk (limited to 'Src/Modules') diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c index 06ad463e1..273bb9e19 100644 --- a/Src/Modules/curses.c +++ b/Src/Modules/curses.c @@ -43,6 +43,7 @@ #ifndef MULTIBYTE_SUPPORT # undef HAVE_SETCCHAR # undef HAVE_WADDWSTR +# undef HAVE_WGET_WCH #endif #ifdef HAVE_SETCCHAR @@ -122,6 +123,9 @@ static const struct zcurses_namenumberpair zcurses_colors[] = { {NULL, 0} }; +/* Autogenerated keypad string/number mapping*/ +#include "curses_keys.h" + static char ** zcurses_pairs_to_array(const struct zcurses_namenumberpair *nnps) { @@ -335,6 +339,16 @@ zccmd_init(const char *nam, char **args) zcurses_colorpairs->printnode = NULL; } + /* + * We use cbreak mode because we don't want line buffering + * on input since we'd just need to loop over characters. + * We use noecho since the manual says that's the right + * thing to do with cbreak. + * + * Turn these on immediately to catch typeahead. + */ + cbreak(); + noecho(); gettyinfo(&curses_tty_state); } else { settyinfo(&curses_tty_state); @@ -669,6 +683,105 @@ zccmd_scroll(const char *nam, char **args) } +static int +zccmd_input(const char *nam, char **args) +{ + LinkNode node; + ZCWin w; + char *var; + int keypadnum = -1; +#ifdef HAVE_WGET_WCH + int ret; + wint_t wi; + VARARR(char, instr, 2*MB_CUR_MAX+1); +#else + int ci; + instr[3]; +#endif + + node = zcurses_validate_window(args[0], ZCURSES_USED); + if (node == NULL) { + zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]); + return 1; + } + + w = (ZCWin)getdata(node); + + if (args[1] && args[2]) { + keypad(w->win, TRUE); + } else { + keypad(w->win, FALSE); + } + +#ifdef HAVE_WGET_WCH + switch (wget_wch(w->win, &wi)) { + case OK: + ret = wctomb(instr, (wchar_t)wi); + if (ret == 0) { + instr[0] = Meta; + instr[1] = '\0' ^ 32; + instr[2] = '\0'; + } else { + (void)metafy(instr, ret, META_NOALLOC); + } + break; + + case KEY_CODE_YES: + keypadnum = (int)wi; + break; + + case ERR: + default: + return 1; + } +#else + ci = wgetch(w->win); + if (ci >= 256) { + keypadnum = ci; + } else { + if (imeta(ci)) { + instr[0] = Meta; + instr[1] = (char)ci ^ 32; + instr[2] = '\0'; + } else { + instr[0] = (char)ci; + instr[1] = '\0'; + } + } +#endif + if (args[1]) + var = args[1]; + else + var = "REPLY"; + if (!setsparam(var, ztrdup(keypadnum > 0 ? "" : instr))) + return 1; + if (args[2]) { + if (keypadnum > 0) { + const struct zcurses_namenumberpair *nnptr; + char fbuf[DIGBUFSIZE+1]; + + for (nnptr = keypad_names; nnptr->name; nnptr++) { + if (keypadnum == nnptr->number) { + setsparam(args[2], ztrdup(nnptr->name)); + return 0; + } + } + if (keypadnum > KEY_F0) { + /* assume it's a function key */ + sprintf(fbuf, "F%d", keypadnum - KEY_F0); + } else { + /* print raw number */ + sprintf(fbuf, "%d", keypadnum); + } + setsparam(args[2], ztrdup(fbuf)); + } else { + setsparam(args[2], ztrdup("")); + } + } + return 0; +} + + /********************* Main builtin handler *********************/ @@ -693,6 +806,7 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func)) {"end", zccmd_endwin, 0, 0}, {"attr", zccmd_attr, 2, -1}, {"scroll", zccmd_scroll, 2, 2}, + {"input", zccmd_input, 1, 3}, {NULL, (zccmd_t)0, 0, 0} }; diff --git a/Src/Modules/curses.mdd b/Src/Modules/curses.mdd index c9c31f267..e6f87d748 100644 --- a/Src/Modules/curses.mdd +++ b/Src/Modules/curses.mdd @@ -5,3 +5,9 @@ load=no autobins="zcurses" objects="curses.o" + +:<<\Make +curses.o curses..o: curses_keys.h + +curses_keys.h: curses_keys.awk @CURSES_KEYS_H@ + $(AWK) -f $(sdir)/curses_keys.awk @CURSES_KEYS_H@ /dev/null >curses_keys.h diff --git a/Src/Modules/curses_keys.awk b/Src/Modules/curses_keys.awk new file mode 100644 index 000000000..55a786521 --- /dev/null +++ b/Src/Modules/curses_keys.awk @@ -0,0 +1,19 @@ +BEGIN {nkeydefs = 0} + +/^[\t ]*#[\t ]*define[\t _]*KEY_[A-Z0-9_]*[\t ]/ { + keyindex = index($0, "KEY_") + keytail = substr($0, keyindex, 80) + split(keytail, tmp) + keynam = substr(tmp[1], 5, 30) + if (keynam != "MIN" && keynam != "MAX") { + name[nkeydefs++] = keynam + } +} + +END { + printf("static const struct zcurses_namenumberpair keypad_names[] = {\n") + for (i = 0; i < 0 + nkeydefs; i++) + printf(" {\"%s\", KEY_%s},\n", name[i], name[i]) + printf(" {NULL, 0}\n") + printf("};\n") +} -- cgit 1.4.1