From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18194 invoked from network); 10 Nov 2007 20:27:26 -0000 X-Spam-Checker-Version: SpamAssassin 3.2.3 (2007-08-08) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00 autolearn=ham version=3.2.3 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 10 Nov 2007 20:27:26 -0000 Received-SPF: none (ns1.primenet.com.au: domain at sunsite.dk does not designate permitted sender hosts) Received: (qmail 31116 invoked from network); 10 Nov 2007 20:27:16 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 10 Nov 2007 20:27:16 -0000 Received: (qmail 25170 invoked by alias); 10 Nov 2007 20:27:11 -0000 Mailing-List: contact zsh-workers-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 24083 Received: (qmail 25151 invoked from network); 10 Nov 2007 20:27:10 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 10 Nov 2007 20:27:10 -0000 Received: (qmail 30816 invoked from network); 10 Nov 2007 20:27:10 -0000 Received: from mtaout03-winn.ispmail.ntl.com (81.103.221.49) by a.mx.sunsite.dk with SMTP; 10 Nov 2007 20:27:02 -0000 Received: from aamtaout03-winn.ispmail.ntl.com ([81.103.221.35]) by mtaout03-winn.ispmail.ntl.com with ESMTP id <20071110202658.CJZD26125.mtaout03-winn.ispmail.ntl.com@aamtaout03-winn.ispmail.ntl.com> for ; Sat, 10 Nov 2007 20:26:58 +0000 Received: from pws-pc.ntlworld.com ([81.107.45.67]) by aamtaout03-winn.ispmail.ntl.com with SMTP id <20071110202658.DGCV26699.aamtaout03-winn.ispmail.ntl.com@pws-pc.ntlworld.com> for ; Sat, 10 Nov 2007 20:26:58 +0000 Date: Sat, 10 Nov 2007 20:26:50 +0000 From: Peter Stephenson To: zsh Subject: PATCH: zcurses querychar Message-Id: <20071110202650.7513ffb4.p.w.stephenson@ntlworld.com> In-Reply-To: <5448.1194474606@pws-pc.ntlworld.com> References: <5448.1194474606@pws-pc.ntlworld.com> X-Mailer: Sylpheed 2.3.1 (GTK+ 2.10.14; x86_64-redhat-linux-gnu) Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Wed, 07 Nov 2007 22:30:06 +0000 Peter Stephenson wrote: > I think the big thing missing now is to be able to query characters and > attributes within windows. Like so, including wide character support. I've obsessively rewritten the manual to refer to subcommands as such; the new bit is at the end of the changes to the file. There is a reason after all to have both string and char: string moves the cursor, char doesn't. We could probably do with some global querying of state, but otherwise I think we're in good shape. I tested it with this function (curses_querychar), which tests quite a lot of the system (but only in one window). # Move around the window. The first line outputs information about # the character under the cursor. ASCII keys insert, cursor and backspace # keys have the obvious effect. F1 is followed by a key for attribute: # lower case to turn on, upper case to turn off: bold, dim, reverse, standout, # underline. F2 is followed by two colors, for foreground and background: # two out of (b)lack, (B)lue, (c)yan, (d)efault, (g)reen, (m)agenta, # (r)ed, (w)hite, (y)ellow. Any other non-character input aborts. zmodload zsh/curses { zcurses init integer x=0 y=1 i local REPLY key attr local -a reply color while true; do zcurses move stdscr $y $x zcurses querychar stdscr reply zcurses move stdscr 0 0 reply=(${(qq)reply}) zcurses string stdscr "($reply)" zcurses clear stdscr eol zcurses move stdscr $y $x zcurses refresh zcurses input stdscr REPLY key case $key in (UP) (( y > 1 && y-- )) ;; (DOWN) (( y < LINES-1 && y++ )) ;; (LEFT) (( x > 0 && x-- )) ;; (RIGHT) (( x < COLUMNS-1 && x++ )) ;; (BACKSPACE) if (( x > 0 )); then (( x-- )) elif (( y > 1 )); then (( y--, x = LINES-1 )) fi zcurses move stdscr $y $x zcurses char stdscr " " ;; (F1) zcurses input stdscr REPLY case $REPLY in (b) attr=+bold ;; (B) attr=-bold ;; (d) attr=+dim ;; (D) attr=-dim ;; (r) attr=+reverse ;; (R) attr=-reverse ;; (s) attr=+standout ;; (S) attr=-standout ;; (u) attr=+underline ;; (U) attr=-underline ;; (*) continue ;; esac zcurses attr stdscr $attr ;; (F2) # read fg and bg color for (( i = 1; i <= 2; i++ )); do zcurses input stdscr case $REPLY in (b) color[i]=black;; (B) color[i]=blue;; (c) color[i]=cyan;; (d) color[i]=default;; (g) color[i]=green;; (m) color[i]=magenta;; (r) color[i]=red;; (w) color[i]=white;; (y) color[i]=yellow;; (*) continue 2 esac done zcurses attr stdscr $color[1]/$color[2] ;; ("") zcurses char stdscr $REPLY if (( x == COLUMNS-1 )); then if (( y < LINES-1 )); then (( y++, x = 0 )) fi else (( x++ )) fi ;; (*) break ;; esac done } always { zcurses end } Index: configure.ac =================================================================== RCS file: /cvsroot/zsh/zsh/configure.ac,v retrieving revision 1.77 diff -u -r1.77 configure.ac --- configure.ac 1 Nov 2007 17:57:57 -0000 1.77 +++ configure.ac 10 Nov 2007 20:19:53 -0000 @@ -1145,7 +1145,7 @@ 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 \ Index: Doc/Zsh/mod_curses.yo =================================================================== RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_curses.yo,v retrieving revision 1.20 diff -u -r1.20 mod_curses.yo --- Doc/Zsh/mod_curses.yo 7 Nov 2007 22:35:15 -0000 1.20 +++ Doc/Zsh/mod_curses.yo 10 Nov 2007 20:19:54 -0000 @@ -26,14 +26,16 @@ 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 @@ 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 @@ 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 @@ 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. - -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(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(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 @@ 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() Index: Src/Modules/curses.c =================================================================== RCS file: /cvsroot/zsh/zsh/Src/Modules/curses.c,v retrieving revision 1.37 diff -u -r1.37 curses.c --- Src/Modules/curses.c 8 Nov 2007 12:13:20 -0000 1.37 +++ Src/Modules/curses.c 10 Nov 2007 20:19:54 -0000 @@ -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 @@ 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 @@ 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 @@ {"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} }; -- Peter Stephenson Web page now at http://homepage.ntlworld.com/p.w.stephenson/