about summary refs log tree commit diff
path: root/Src
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-10-26 21:59:56 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-10-26 21:59:56 +0000
commit7f8e2298181fcbf3399eb9bde1564c1fe2fe9df3 (patch)
tree5519c693b2684c85b642f3b600eb8a83a862bd9b /Src
parent26461dcc1b03fa0ad47c7abbec4b8999f1fe5a28 (diff)
downloadzsh-7f8e2298181fcbf3399eb9bde1564c1fe2fe9df3.tar.gz
zsh-7f8e2298181fcbf3399eb9bde1564c1fe2fe9df3.tar.xz
zsh-7f8e2298181fcbf3399eb9bde1564c1fe2fe9df3.zip
24024: add zcurses input with keypad handling
Diffstat (limited to 'Src')
-rw-r--r--Src/Modules/curses.c114
-rw-r--r--Src/Modules/curses.mdd6
-rw-r--r--Src/Modules/curses_keys.awk19
3 files changed, 139 insertions, 0 deletions
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")
+}