about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Stephenson <pws@users.sourceforge.net>2007-11-10 20:29:27 +0000
committerPeter Stephenson <pws@users.sourceforge.net>2007-11-10 20:29:27 +0000
commited54878d7af33d7c9e487a7be887b7838be4657e (patch)
tree836598c261d542f59862958e9b6c0cbc99e16a52
parentdd85c0e955a60cc9ec19047d9814d0ce5bf37496 (diff)
downloadzsh-ed54878d7af33d7c9e487a7be887b7838be4657e.tar.gz
zsh-ed54878d7af33d7c9e487a7be887b7838be4657e.tar.xz
zsh-ed54878d7af33d7c9e487a7be887b7838be4657e.zip
24083: add zcurses querychar
-rw-r--r--ChangeLog3
-rw-r--r--Doc/Zsh/mod_curses.yo99
-rw-r--r--Src/Modules/curses.c116
-rw-r--r--configure.ac2
4 files changed, 177 insertions, 43 deletions
diff --git a/ChangeLog b/ChangeLog
index 02cda0e31..3070dee21 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-11-10  Peter Stephenson  <p.w.stephenson@ntlworld.com>
 
+	* 24083: Doc/Zsh/mod_curses, Src/Modules/curses.c: add
+	'zcurses querychar'.
+
 	* 24082: Functionz/Zle/delete-whole-word-match: failed if
 	cursor was on whitespace.
 
diff --git a/Doc/Zsh/mod_curses.yo b/Doc/Zsh/mod_curses.yo
index 060ec8f29..e08d129e4 100644
--- a/Doc/Zsh/mod_curses.yo
+++ b/Doc/Zsh/mod_curses.yo
@@ -26,14 +26,16 @@ xitem(tt(zcurses) tt(bg) var(targetwin) [ var({+/-}attribute) | var(fg_col)tt(/)
 xitem(tt(zcurses) tt(scroll) var(targetwin) [ tt(on) | tt(off) | {+/-}var(lines) ])
 xitem(tt(zcurses) tt(input) var(targetwin) [ var(param) [ var(kparam) [ var(mparam) ] ] ])
 xitem(tt(zcurses) tt(mouse) [ tt(delay) var(num) | {+/-}tt(motion) ])
-item(tt(zcurses) tt(timeout) var(targetwin) var(intval))(
+xitem(tt(zcurses) tt(timeout) var(targetwin) var(intval))
+item(tt(zcurses) tt(querychar) var(targetwin) [ var(param) ])(
 Manipulate curses windows.  All uses of this command should be
 bracketed by `tt(zcurses init)' to initialise use of curses, and
 `tt(zcurses end)' to end it; omitting `tt(zcurses end)' can cause
 the terminal to be in an unwanted state.
 
-With tt(addwin), create a window with var(nlines) lines and var(ncols) columns.
-Its upper left corner will be placed at row var(begin_y) and column
+The subcommand tt(addwin) creates a window with var(nlines) lines and
+var(ncols) columns.  Its upper left corner will be placed at row
+var(begin_y) and column
 var(begin_x) of the screen.  var(targetwin) is a string and refers
 to the name of a window that is not currently assigned.  Note
 in particular the curses convention that vertical values appear
@@ -46,37 +48,40 @@ with the parent's memory.  Subwindows must be deleted before their parent.
 Note that the coordinates of subwindows are relative to the screen, not
 the parent, as with other windows.
 
-Use tt(delwin) to delete a window created with tt(addwin).  Note
-that tt(end) does em(not) implicitly delete windows, and that
-tt(delwin) does not erase the screen image of the window.
+Use the subcommand tt(delwin) to delete a window created with
+tt(addwin).  Note that tt(end) does em(not) implicitly delete windows,
+and that tt(delwin) does not erase the screen image of the window.
 
 The window corresponding to the full visible screen is called
 tt(stdscr); it always exists after `tt(zcurses init)' and cannot
 be delete with tt(delwin).
 
-The tt(refresh) command will refresh window var(targetwin); this is
+The subcommand tt(refresh) will refresh window var(targetwin); this is
 necessary to make any pending changes (such as characters you have
 prepared for output with tt(char)) visible on the screen.  tt(refresh)
 without an argument causes the screen to be cleared and redrawn.
 If multiple windows are given, the screen is updated once at the end.
 
-The tt(touch) command marks the var(targetwin)s listed as changed.
+The subcommand tt(touch) marks the var(targetwin)s listed as changed.
 This is necessary before tt(refresh)ing windows if a window that
 was in front of another window (which may be tt(stdscr)) is deleted.
 
-tt(move) moves the cursor position in var(targetwin) to new coordinates
-var(new_y) and var(new_x).
-
-tt(clear) erases the contents of var(targetwin).  One (and no more than one)
-of three options may be specified.  With the option tt(redraw),
-in addition the next tt(refresh) of var(targetwin) will cause the screen to be
-cleared and repainted.  With the option tt(eol), var(targetwin) is only
-cleared to the end of the current cursor line.  With the option
+The subcommand tt(move) moves the cursor position in var(targetwin) to
+new coordinates var(new_y) and var(new_x).  Note that the 
+subcommand tt(string) (but not the subcommand tt(char)) advances the
+cursor position over the characters added.
+
+The subcommand tt(clear) erases the contents of var(targetwin).  One
+(and no more than one) of three options may be specified.  With the
+option tt(redraw), in addition the next tt(refresh) of var(targetwin)
+will cause the screen to be cleared and repainted.  With the option
+tt(eol), var(targetwin) is only cleared to the end of the current cursor
+line.  With the option
 tt(bot), var(targetwin) is cleared to the end of the window, i.e
 everything to the right and below the cursor is cleared.
 
-tt(location) writes various positions associated with var(targetwin)
-into the array named var(array).
+The subcommand tt(location) writes various positions associated with
+var(targetwin) into the array named var(array).
 These are, in order:
 startsitem()
 sitem()(The y and x coordinates of the cursor relative to the top left
@@ -94,12 +99,12 @@ that the border is not subsequently handled specially:  in other words,
 the border is simply a set of characters output at the edge of the
 window.  Hence it can be overwritten, can scroll off the window, etc.
 
-tt(attr) will set var(targetwin)'s attributes or foreground/background
-color pair for any successive character output.  Each var(attribute)
-given on the line may be prepended by a tt(+) to set or a tt(-) to
-unset that attribute; tt(+) is assumed if absent.  The attributes
-supported are tt(blink), tt(bold), tt(dim), tt(reverse), tt(standout),
-and tt(underline).
+The subcommand tt(attr) will set var(targetwin)'s attributes or
+foreground/background color pair for any successive character output.
+Each var(attribute) given on the line may be prepended by a tt(+) to set
+or a tt(-) to unset that attribute; tt(+) is assumed if absent.  The
+attributes supported are tt(blink), tt(bold), tt(dim), tt(reverse),
+tt(standout), and tt(underline).
 
 Each var(fg_col)tt(/)var(bg_col) attribute (to be read as
 `var(fg_col) on var(bg_col)') sets the foreground and background color
@@ -118,18 +123,19 @@ Owing to limitations of curses this cannot be a multibyte character
 of attributes override the existing background, turning attributes
 off in the arguments is not useful, though this does not cause an error.
 
-tt(scroll) can be used with tt(on) or tt(off) to enabled or disable
-scrolling of a window when the cursor would otherwise move below the
-window due to typing or output.  It can also be used with a positive
-or negative integer to scroll the window up or down the given number
-of lines without changing the current cursor position (which therefore
-appears to move in the opposite direction relative to the window).
-In the second case, if scrolling is tt(off) it is temporarily turned tt(on)
-to allow the window to be scrolled.
+The subcommand tt(scroll) can be used with tt(on) or tt(off) to enabled
+or disable scrolling of a window when the cursor would otherwise move
+below the window due to typing or output.  It can also be used with a
+positive or negative integer to scroll the window up or down the given
+number of lines without changing the current cursor position (which
+therefore appears to move in the opposite direction relative to the
+window).  In the second case, if scrolling is tt(off) it is temporarily
+turned tt(on) to allow the window to be scrolled.
 
-tt(input) reads a single character from the window without echoing
-it back.  If var(param) is supplied the character is assigned to the
-parameter var(param), else it is assigned to the parameter var(REPLY).
+The subcommand tt(input) reads a single character from the window
+without echoing it back.  If var(param) is supplied the character is
+assigned to the parameter var(param), else it is assigned to the
+parameter var(REPLY).
 
 If both var(param) and var(kparam) are supplied, the key is read in
 `keypad' mode.  In this mode special keys such as function keys and
@@ -184,13 +190,22 @@ reporting of mouse motion in addition to clicks, presses and releases,
 which are always reported.  However, it appears reports for mouse
 motion are not currently implemented.
 
-tt(timeout) specifies a timeout value for input from var(targetwin).
-If var(intval) is negative, `tt(zcurses input)' waits indefinitely for
-a character to be typed; this is the default.  If var(intval) is zero,
-`tt(zcurses input)' returns immediately; if there is typeahead it is
-returned, else no input is done and status 1 is returned.  If var(intval)
-is positive, `tt(zcurses input)' waits var(intval) milliseconds for
-input and if there is none at the end of that period returns status 1.
+The subcommand tt(timeout) specifies a timeout value for input from
+var(targetwin).  If var(intval) is negative, `tt(zcurses input)' waits
+indefinitely for a character to be typed; this is the default.  If
+var(intval) is zero, `tt(zcurses input)' returns immediately; if there
+is typeahead it is returned, else no input is done and status 1 is
+returned.  If var(intval) is positive, `tt(zcurses input)' waits
+var(intval) milliseconds for input and if there is none at the end of
+that period returns status 1.
+
+The subcommand tt(querychar) queries the character at the current cursor
+position.  The return values are stored in the array named var(param) if
+supplied, else in the array tt(reply).  The first value is the character
+(which may be a multibyte character if the system supports them); the
+second is the color pair in the usual var(fg_col)tt(/)var(bg_col)
+notation.  Any attributes other than color that apply to the character,
+as set with the subcommand tt(attr), appear as additional elements.
 )
 enditem()
 
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}
     };
diff --git a/configure.ac b/configure.ac
index f42b90994..31ab25d45 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1145,7 +1145,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
 	       brk sbrk \
 	       pathconf sysconf \
 	       tgetent tigetflag tigetnum tigetstr setupterm initscr \
-	       setcchar waddwstr wget_wch use_default_colors \
+	       getcchar setcchar waddwstr wget_wch win_wch use_default_colors \
 	       pcre_compile pcre_study pcre_exec \
 	       nl_langinfo \
 	       erand48 open_memstream \