summaryrefslogtreecommitdiff
path: root/Src/Modules/curses.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Modules/curses.c')
-rw-r--r--Src/Modules/curses.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index 12a2c3d80..ff6aff12c 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -41,9 +41,11 @@
#endif
#ifndef MULTIBYTE_SUPPORT
+# undef HAVE_GETCCHAR
# undef HAVE_SETCCHAR
# undef HAVE_WADDWSTR
# undef HAVE_WGET_WCH
+# undef HAVE_WIN_WCH
#endif
#ifdef HAVE_SETCCHAR
@@ -379,6 +381,25 @@ zcurses_colorget(const char *nam, char *colorpair)
return cpn;
}
+static Colorpairnode cpn_match;
+
+static void
+zcurses_colornode(HashNode hn, int cp)
+{
+ Colorpairnode cpn = (Colorpairnode)hn;
+ if (cpn->colorpair == (short)cp)
+ cpn_match = cpn;
+}
+
+static Colorpairnode
+zcurses_colorget_reverse(short cp)
+{
+ cpn_match = NULL;
+ scanhashtable(zcurses_colorpairs, 0, 0, 0,
+ zcurses_colornode, cp);
+ return cpn_match;
+}
+
static void
freecolorpairnode(HashNode hn)
{
@@ -1302,6 +1323,100 @@ zccmd_position(const char *nam, char **args)
static int
+zccmd_querychar(const char *nam, char **args)
+{
+ LinkNode node;
+ ZCWin w;
+ short cp;
+ Colorpairnode cpn;
+ const struct zcurses_namenumberpair *zattrp;
+ LinkList clist;
+#if defined(HAVE_WIN_WCH) && defined(HAVE_GETCCHAR)
+ wchar_t c;
+ cchar_t cc;
+ attr_t attrs;
+ int count;
+ VARARR(char, instr, 2*MB_CUR_MAX+1);
+#else
+ chtype inc;
+ char 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 defined(HAVE_WIN_WCH) && defined(HAVE_GETCCHAR)
+ if (win_wch(w->win, &cc) == ERR)
+ return 1;
+
+ if (getcchar(&cc, &c, &attrs, &cp, NULL) == ERR)
+ return 1;
+ /* Hmmm... I always get 0 for cp, whereas the following works... */
+ cp = PAIR_NUMBER(winch(w->win));
+
+ count = wctomb(instr, c);
+ if (count == -1)
+ return 1;
+ (void)metafy(instr, count, META_NOALLOC);
+#else
+ inc = winch(w->win);
+ /* I think the following is correct, the manual is a little terse */
+ cp = PAIR_NUMBER(inc);
+ inc &= A_CHARTEXT;
+ if (imeta(inc)) {
+ instr[0] = Meta;
+ instr[1] = STOUC(inc ^ 32);
+ instr[2] = '\0';
+ } else {
+ instr[0] = STOUC(inc);
+ instr[1] = '\0';
+ }
+ /*
+ * I'm guessing this is OK... header says attr_t must be at
+ * least as wide as chtype.
+ */
+ attrs = (attr_t)inc;
+#endif
+
+ /*
+ * Attribute numbers vary, so make a linked list.
+ * This also saves us from doing the permanent allocation till
+ * the end.
+ */
+ clist = newlinklist();
+ /* First the (possibly multibyte) character itself. */
+ addlinknode(clist, instr);
+ /*
+ * Next the colo[u]r.
+ * We should be able to match it in the colorpair list, but
+ * if some reason we can't, fail safe and output the number.
+ */
+ cpn = zcurses_colorget_reverse(cp);
+ if (cpn) {
+ addlinknode(clist, cpn->node.nam);
+ } else {
+ /* report color pair number */
+ char digits[DIGBUFSIZE];
+ sprintf(digits, "%d", (int)cp);
+ addlinknode(clist, digits);
+ }
+ /* Now see what attributes are present. */
+ for (zattrp = zcurses_attributes; zattrp->name; zattrp++) {
+ if (attrs & zattrp->number)
+ addlinknode(clist, zattrp->name);
+ }
+
+ /* Turn this into an array and store it. */
+ return !setaparam(args[1] ? args[1] : "reply", zlinklist2array(clist));
+}
+
+
+static int
zccmd_touch(const char *nam, char **args)
{
LinkNode node;
@@ -1354,6 +1469,7 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
{"input", zccmd_input, 1, 4},
{"timeout", zccmd_timeout, 2, 2},
{"mouse", zccmd_mouse, 0, -1},
+ {"querychar", zccmd_querychar, 1, 2},
{"touch", zccmd_touch, 1, -1},
{NULL, (zccmd_t)0, 0, 0}
};