Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

PATCH: zcurses bg



I will now be offline until Sunday.  You might call it a small window.


curses_bang() {
  # Arrow keys to move, anything else to exit.
  zmodload zsh/curses
  
  local REPLY key newkey
  integer h=$(( LINES - 10 )) w=$((COLUMNS - 20))
  integer x=1 y=1
  
  curses_bang.bang() {
    zcurses addwin bang 1 5 $(( y + 5 )) $(( x + 10 ))
    zcurses attr bang red/green bold
    zcurses string bang 'BANG!'
    zcurses refresh bang
    zcurses timeout bang 1000
    zcurses input bang REPLY key
    zcurses delwin bang
    zcurses touch main
    zcurses refresh stdscr main
  }
  
  curses_bang.do_move() {
    zcurses string main $3
    (( y = $1, x = $2 ))
    zcurses move main $y $x
    zcurses refresh main
  }
  
  {
    zcurses init
  
    zcurses addwin main $(( LINES - 10 )) $(( COLUMNS - 20 )) 5 10
    zcurses border main
    zcurses bg main yellow/blue reverse bold @.
    zcurses attr main white/black
  
    zcurses move main $y $x
    zcurses refresh main
  
    while true; do
      if [[ -z $key ]]; then
        zcurses input main REPLY key
      fi
      newkey=$key
      key=    
      case $newkey in
        (UP)
        if (( y == 1 )); then
          curses_bang.bang
        else
          curses_bang.do_move $(( y -1 )) $x "^"
        fi
        ;;
  
        (DOWN)
        if (( y == h - 2 )); then
          curses_bang.bang
        else
          curses_bang.do_move $(( y + 1 )) $x "v"
        fi
        ;;
  
        (LEFT)
        if (( x == 1 )); then
          curses_bang.bang
        else
          curses_bang.do_move $y $(( x - 1 )) "<"
        fi
        ;;
  
        (RIGHT)
        if (( x == w - 2 )); then
          curses_bang.bang
        else
          curses_bang.do_move $y $(( x + 1 )) ">"
        fi
        ;;
  
        ("")
        break
        ;;
      esac
    done
  
  } always {
    zcurses delwin main
    zcurses end
  }
}


Index: Doc/Zsh/mod_curses.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_curses.yo,v
retrieving revision 1.17
diff -u -d -r1.17 mod_curses.yo
--- Doc/Zsh/mod_curses.yo	28 Oct 2007 20:28:30 -0000	1.17
+++ Doc/Zsh/mod_curses.yo	30 Oct 2007 21:00:38 -0000
@@ -22,6 +22,7 @@
 xitem(tt(zcurses) tt(string) var(targetwin) var(string) )
 xitem(tt(zcurses) tt(border) var(targetwin) var(border) )(
 xitem(tt(zcurses) tt(attr) var(targetwin) [ var({+/-}attribute) | var(fg_col)tt(/)var(bg_col) ] [...])
+xitem(tt(zcurses) tt(bg) var(targetwin) [ var({+/-}attribute) | var(fg_col)tt(/)var(bg_col) | tt(@)var(char) ] [...])
 xitem(tt(zcurses) tt(scroll) [ tt(on) | tt(off) | {+/-}var(lines) ])
 xitem(tt(zcurses) tt(input) var(targetwin) [ var(param) [ var(kpparm) ] ])
 item(tt(zcurses) tt(timeout) var(targetwin) var(intval))(
@@ -42,7 +43,7 @@
 ordinary new window in that the memory of the window contents is shared
 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
+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
@@ -106,6 +107,16 @@
 or background color with which the terminal started.  The color pair
 tt(default/default) is always available.
 
+tt(bg) overrides the color and other attributes of all characters in the
+window.  Its usual use is to set the background initially, but it will
+overwrite the attributes of any characters at the time when it is called.
+In addition to the arguments allowed with tt(attr), an argument tt(@)var(char)
+specifies a character to be shown in otherwise blank areas of the window.
+Owing to limitations of curses this cannot be a multibyte character
+(use of ASCII characters only is recommended).  As the specified set
+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
Index: Src/Modules/curses.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/curses.c,v
retrieving revision 1.31
diff -u -d -r1.31 curses.c
--- Src/Modules/curses.c	30 Oct 2007 11:03:16 -0000	1.31
+++ Src/Modules/curses.c	30 Oct 2007 21:00:38 -0000
@@ -223,29 +223,20 @@
     return 0;
 }
 
-static int
-zcurses_attribute(WINDOW *w, char *attr, int op)
+static struct zcurses_namenumberpair *
+zcurses_attrget(WINDOW *w, char *attr)
 {
     struct zcurses_namenumberpair *zca;
 
     if (!attr)
-	return 1;
+	return NULL;
 
     for(zca=(struct zcurses_namenumberpair *)zcurses_attributes;zca->name;zca++)
 	if (!strcmp(attr, zca->name)) {
-	    switch(op) {
-		case ZCURSES_ATTRON:
-		    wattron(w, zca->number);
-		    break;
-		case ZCURSES_ATTROFF:
-		    wattroff(w, zca->number);
-		    break;
-	    }
-
-	    return 0;
+	    return zca;
 	}
 
-    return 1;
+    return NULL;
 }
 
 static short
@@ -261,8 +252,8 @@
     return (short)-1;
 }
 
-static int
-zcurses_colorset(const char *nam, WINDOW *w, char *colorpair)
+static Colorpairnode
+zcurses_colorget(const char *nam, char *colorpair)
 {
     char *bg, *cp;
     short f, b;
@@ -270,7 +261,7 @@
 
     /* zcurses_colorpairs is only initialised if color is supported */
     if (!zcurses_colorpairs)
-	return 1;
+	return NULL;
 
     if (zc_color_phase==1 ||
 	!(cpn = (Colorpairnode) gethashnode(zcurses_colorpairs, colorpair))) {
@@ -280,7 +271,7 @@
 	bg = strchr(cp, '/');
 	if (bg==NULL) {
 	    zsfree(cp);
-	    return 1;
+	    return NULL;
 	}
 
 	*bg = '\0';        
@@ -294,28 +285,28 @@
 		zwarnnam(nam, "background color `%s' not known", bg+1);
 	    *bg = '/';
 	    zsfree(cp);
-	    return 1;
+	    return NULL;
 	}
 	*bg = '/';
 
 	++next_cp;
 	if (next_cp >= COLOR_PAIRS || init_pair(next_cp, f, b) == ERR)  {
 	    zsfree(cp);
-	    return 1;
+	    return NULL;
 	}
 
 	cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode));
 	
 	if (!cpn) {
 	    zsfree(cp);
-	    return 1;
+	    return NULL;
 	}
 
 	cpn->colorpair = next_cp;
 	addhashnode(zcurses_colorpairs, cp, (void *)cpn);
     }
 
-    return (wcolor_set(w, cpn->colorpair, NULL) == ERR);
+    return cpn;
 }
 
 static void
@@ -760,11 +751,14 @@
 
     for(attrs = args+1; *attrs; attrs++) {
 	if (strchr(*attrs, '/')) {
-	    if (zcurses_colorset(nam, w->win, *attrs))
+	    Colorpairnode cpn;
+	    if ((cpn = zcurses_colorget(nam, *attrs)) == NULL ||
+		wcolor_set(w->win, cpn->colorpair, NULL) == ERR)
 		ret = 1;
 	} else {
 	    char *ptr;
 	    int onoff;
+	    struct zcurses_namenumberpair *zca;
 
 	    switch(*attrs[0]) {
 	    case '-':
@@ -780,12 +774,97 @@
 		ptr = *attrs;
 		break;
 	    }
-	    if (zcurses_attribute(w->win, ptr, onoff)) {
+	    if ((zca = zcurses_attrget(w->win, ptr)) == NULL) {
+		zwarnnam(nam, "attribute `%s' not known", ptr);
+		ret = 1;
+	    }
+	    switch(onoff) {
+		case ZCURSES_ATTRON:
+		    if (wattron(w->win, zca->number) == ERR)
+			ret = 1;
+		    break;
+		case ZCURSES_ATTROFF:
+		    if (wattroff(w->win, zca->number) == ERR)
+			ret = 1;
+		    break;
+	    }
+	}
+    }
+    return ret;
+}
+
+
+static int
+zccmd_bg(const char *nam, char **args)
+{
+    LinkNode node;
+    ZCWin w;
+    char **attrs;
+    int ret = 0;
+    chtype ch = 0;
+
+    if (!args[0])
+	return 1;
+
+    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);
+
+    for(attrs = args+1; *attrs; attrs++) {
+	if (strchr(*attrs, '/')) {
+	    Colorpairnode cpn;
+	    if ((cpn = zcurses_colorget(nam, *attrs)) == NULL)
+		ret = 1;
+	    else if (cpn->colorpair >= 256) {
+		/* pretty unlikely, but... */
+		zwarnnam(nam, "bg color pair %s has index (%d) too large (max 255)",
+			 cpn->node.nam, cpn->colorpair);
+		ret = 1;
+	    } else {
+		ch |= COLOR_PAIR(cpn->colorpair);
+	    }
+	} else if (**attrs == '@') {
+	    ch |= (*attrs)[1] == Meta ? (*attrs)[2] ^ 32 : (*attrs)[1];
+	} else {
+	    char *ptr;
+	    int onoff;
+	    struct zcurses_namenumberpair *zca;
+
+	    switch(*attrs[0]) {
+	    case '-':
+		onoff = ZCURSES_ATTROFF;
+		ptr = (*attrs) + 1;
+		break;
+	    case '+':
+		onoff = ZCURSES_ATTRON;
+		ptr = (*attrs) + 1;
+		break;
+	    default:
+		onoff = ZCURSES_ATTRON;
+		ptr = *attrs;
+		break;
+	    }
+	    if ((zca = zcurses_attrget(w->win, ptr)) == NULL) {
 		zwarnnam(nam, "attribute `%s' not known", ptr);
 		ret = 1;
 	    }
+	    switch(onoff) {
+		case ZCURSES_ATTRON:
+		    ch |= zca->number;
+		    break;
+		case ZCURSES_ATTROFF:
+		    ch &= ~zca->number;
+		    break;
+	    }
 	}
     }
+
+    if (ret == 0)
+	return wbkgd(w->win, ch) != OK;
     return ret;
 }
 
@@ -1060,6 +1139,7 @@
 	{"border", zccmd_border, 1, 1},
 	{"end", zccmd_endwin, 0, 0},
 	{"attr", zccmd_attr, 2, -1},
+	{"bg", zccmd_bg, 2, -1},
 	{"scroll", zccmd_scroll, 2, 2},
 	{"input", zccmd_input, 1, 3},
 	{"timeout", zccmd_timeout, 2, 2},


-- 
Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
Web page now at http://homepage.ntlworld.com/p.w.stephenson/



Messages sorted by: Reverse Date, Date, Thread, Author