Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
PATCH: zcurses again
- X-seq: zsh-workers 24017
- From: Peter Stephenson <p.w.stephenson@xxxxxxxxxxxx>
- To: zsh-workers@xxxxxxxxxx (Zsh hackers list)
- Subject: PATCH: zcurses again
- Date: Wed, 24 Oct 2007 22:48:01 +0100
- Mailing-list: contact zsh-workers-help@xxxxxxxxxx; run by ezmlm
1. As advertised: combine attr and color, removing the latter;
add errors for bad attributes and colors; allow adding attributes
without the leading "+".
2. Get paranoid about strtok() and use strchr(); save a zsfree()
and a ztrdup().
3. Remove some unnecessary arguments to zwarnnam(), which now does
proper variable arguments handling.
4. Add readonly arrays zcurses_attrs, zcurses_colors, zcurses_windows
and integers ZCURSES_COLORS and ZCURSES_COLOR_PAIRS.
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/mod_curses.yo,v
retrieving revision 1.8
diff -u -r1.8 mod_curses.yo
--- Doc/Zsh/mod_curses.yo 23 Oct 2007 21:16:03 -0000 1.8
+++ Doc/Zsh/mod_curses.yo 24 Oct 2007 21:43:59 -0000
@@ -1,7 +1,10 @@
COMMENT(!MOD!zsh/curses
curses windowing commands
!MOD!)
-The tt(zsh/curses) module makes available one builtin command:
+The tt(zsh/curses) module makes available one builtin command and
+various parameters.
+
+subsect(Builtin)
startitem()
findex(zcurses)
@@ -15,7 +18,7 @@
xitem(tt(zcurses) tt(char) var(targetwin) var(character) )
xitem(tt(zcurses) tt(string) var(targetwin) var(string) )
xitem(tt(zcurses) tt(border) var(targetwin) var(border) )(
-item(tt(zcurses) tt(addwin) var(targetwin) var({+/-}attribute) [var({+/-}attribute)] [...])(
+item(tt(zcurses) tt(attr) var(targetwin) [ var({+/-}attribute) | var(fg_col)tt(/)var(bg_col) ] [...])(
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
@@ -26,7 +29,8 @@
var(begin_x) of the screen. var(targetwin) is a string and refers
to the name of a window that is not currently assigned.
-Use tt(delwin) to delete a window created with tt(addwin).
+Use tt(delwin) to delete a window created with tt(addwin). Note
+that tt(end) does em(not) implicitly delete windows.
The tt(refresh) command will refresh window var(targetwin); this is necessary to
make any pending changes (such as characters you have prepared for output
@@ -41,10 +45,49 @@
To draw a border around window var(targetwin), use tt(border).
-tt(addwin) will set var(targetwin)'s attributes for any successive character
-output. Each var(attribute) given on the line should be prepended by a
-tt(+) to set or a tt(-) to unset that attribute. The attributes supported
-are tt(blink), tt(bold), tt(dim), tt(reverse), tt(standout), and
-tt(underline).
+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) (to be read as
+`var(fg_col) on var(bg_col)') sets the foreground and background color
+for character output.
+)
+enditem()
+
+subsect(Parameters)
+
+startitem()
+vindex(ZCURSES_COLORS)
+item(tt(ZCURSES_COLORS))(
+Readonly integer. The maximum number of colors the terminal
+supports. This value is initialised by the curses library and is not
+available until the first time tt(zcurses init) is run.
+)
+vindex(ZCURSES_COLOR_PAIRS)
+item(tt(ZCURSES_COLOR_PAIRS))(
+Readonly integer. The maximum number of color pairs
+var(fg_col)tt(/)var(bg_col) that may be defined in `tt(zcurses attr)'
+commands; note this limit applies to all color pairs that have been
+used whether or not they are currently active. This value is initialised
+by the curses library and is not available until the first time tt(zcurses
+init) is run.
+)
+vindex(zcurses_attrs)
+item(tt(zcurses_attrs))(
+Readonly array. The attributes supported by tt(zsh/curses); available
+as soon as the module is loaded.
+)
+vindex(zcurses_colors)
+item(tt(zcurses_colors))(
+Readonly array. The colors supported by tt(zsh/curses); available
+as soon as the module is loaded.
+)
+vindex(zcurses_windows)
+item(tt(zcurses_windows))(
+Readonly array. The current list of windows, i.e. all windows that
+have been created with `tt(zcurses addwin)' and not removed with
+`tt(zcurses delwin)'.
)
enditem()
Index: Src/Modules/curses.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/Modules/curses.c,v
retrieving revision 1.20
diff -u -r1.20 curses.c
--- Src/Modules/curses.c 24 Oct 2007 08:47:45 -0000 1.20
+++ Src/Modules/curses.c 24 Oct 2007 21:43:59 -0000
@@ -94,6 +94,48 @@
static int zc_errno, zc_color_phase=0;
static short next_cp=0;
+static const struct zcurses_namenumberpair zcurses_attributes[] = {
+ {"blink", A_BLINK},
+ {"bold", A_BOLD},
+ {"dim", A_DIM},
+ {"reverse", A_REVERSE},
+ {"standout", A_STANDOUT},
+ {"underline", A_UNDERLINE},
+ {NULL, 0}
+};
+
+static const struct zcurses_namenumberpair zcurses_colors[] = {
+ {"black", COLOR_BLACK},
+ {"red", COLOR_RED},
+ {"green", COLOR_GREEN},
+ {"yellow", COLOR_YELLOW},
+ {"blue", COLOR_BLUE},
+ {"magenta", COLOR_MAGENTA},
+ {"cyan", COLOR_CYAN},
+ {"white", COLOR_WHITE},
+ {NULL, 0}
+};
+
+static char **
+zcurses_pairs_to_array(const struct zcurses_namenumberpair *nnps)
+{
+ char **arr, **arrptr;
+ int count;
+ const struct zcurses_namenumberpair *nnptr;
+
+ for (nnptr = nnps; nnptr->name; nnptr++)
+ ;
+ count = nnptr - nnps;
+
+ arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
+
+ for (nnptr = nnps; nnptr->name; nnptr++)
+ *arrptr++ = dupstring(nnptr->name);
+ *arrptr = NULL;
+
+ return arr;
+}
+
static const char *
zcurses_strerror(int err)
{
@@ -164,16 +206,6 @@
{
struct zcurses_namenumberpair *zca;
- static const struct zcurses_namenumberpair zcurses_attributes[] = {
- {"blink", A_BLINK},
- {"bold", A_BOLD},
- {"dim", A_DIM},
- {"reverse", A_REVERSE},
- {"standout", A_STANDOUT},
- {"underline", A_UNDERLINE},
- {NULL, 0}
- };
-
if (!attr)
return 1;
@@ -199,18 +231,6 @@
{
struct zcurses_namenumberpair *zc;
- static const struct zcurses_namenumberpair zcurses_colors[] = {
- {"black", COLOR_BLACK},
- {"red", COLOR_RED},
- {"green", COLOR_GREEN},
- {"yellow", COLOR_YELLOW},
- {"blue", COLOR_BLUE},
- {"magenta", COLOR_MAGENTA},
- {"cyan", COLOR_CYAN},
- {"white", COLOR_WHITE},
- {NULL, 0}
- };
-
for(zc=(struct zcurses_namenumberpair *)zcurses_colors;zc->name;zc++)
if (!strcmp(color, zc->name)) {
return (short)zc->number;
@@ -220,9 +240,9 @@
}
static int
-zcurses_colorset(WINDOW *w, char *colorpair)
+zcurses_colorset(const char *nam, WINDOW *w, char *colorpair)
{
- char *fg, *bg, *cp;
+ char *bg, *cp;
short f, b;
Colorpairnode cpn;
@@ -230,36 +250,43 @@
!(cpn = (Colorpairnode) gethashnode(zcurses_colorpairs, colorpair))) {
zc_color_phase = 2;
cp = ztrdup(colorpair);
- fg = strtok(cp, "/");
- bg = strtok(NULL, "/");
+ bg = strchr(cp, '/');
if (bg==NULL) {
zsfree(cp);
return 1;
}
-
- f = zcurses_color(fg);
- b = zcurses_color(bg);
- zsfree(cp);
-
- if (f==-1 || b==-1)
+ *bg = '\0';
+ f = zcurses_color(cp);
+ b = zcurses_color(bg+1);
+
+ if (f==-1 || b==-1) {
+ if (f == -1)
+ zwarnnam(nam, "foreground color `%s' not known", cp);
+ if (b == -1)
+ zwarnnam(nam, "background color `%s' not known", bg+1);
+ *bg = '/';
+ zsfree(cp);
return 1;
+ }
+ *bg = '/';
++next_cp;
- if (next_cp >= COLOR_PAIRS)
- return 1;
-
- if (init_pair(next_cp, f, b) == ERR)
+ if (next_cp >= COLOR_PAIRS || init_pair(next_cp, f, b) == ERR) {
+ zsfree(cp);
return 1;
+ }
cpn = (Colorpairnode)zalloc(sizeof(struct colorpairnode));
- if (!cpn)
+ if (!cpn) {
+ zsfree(cp);
return 1;
+ }
cpn->colorpair = next_cp;
- addhashnode(zcurses_colorpairs, ztrdup(colorpair), (void *)cpn);
+ addhashnode(zcurses_colorpairs, cp, (void *)cpn);
}
return (wcolor_set(w, cpn->colorpair, NULL) == ERR);
@@ -353,14 +380,14 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
w = (ZCWin)getdata(node);
if (w == NULL) {
- zwarnnam(nam, "record for window `%s' is corrupt", args[0], 0);
+ zwarnnam(nam, "record for window `%s' is corrupt", args[0]);
return 1;
}
if (delwin(w->win)!=OK)
@@ -408,7 +435,7 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -436,7 +463,7 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -475,7 +502,7 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -511,7 +538,7 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
@@ -555,52 +582,44 @@
node = zcurses_validate_window(args[0], ZCURSES_USED);
if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
+ zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0]);
return 1;
}
w = (ZCWin)getdata(node);
for(attrs = args+1; *attrs; attrs++) {
- switch(*attrs[0]) {
- case '-':
- if (zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTROFF))
+ if (strchr(*attrs, '/')) {
+ if (zcurses_colorset(nam, w->win, *attrs))
ret = 1;
- break;
- case '+':
- if (zcurses_attribute(w->win, (*attrs)+1, ZCURSES_ATTRON))
+ } else {
+ char *ptr;
+ int onoff;
+
+ 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 (zcurses_attribute(w->win, ptr, onoff)) {
+ zwarnnam(nam, "attribute `%s' not known", ptr);
ret = 1;
- break;
- default:
- /* maybe a bad idea to spew warnings here */
- break;
+ }
}
}
return ret;
}
-static int
-zccmd_color(const char *nam, char **args)
-{
- LinkNode node;
- ZCWin w;
-
- if (!args[0] || !args[1] || !zc_color_phase)
- return 1;
-
- node = zcurses_validate_window(args[0], ZCURSES_USED);
- if (node == NULL) {
- zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), args[0], 0);
- return 1;
- }
-
- w = (ZCWin)getdata(node);
-
- return zcurses_colorset(w->win, args[1]);
-}
-
-
/*********************
Main builtin handler
*********************/
@@ -624,7 +643,6 @@
{"border", zccmd_border, 1, 1},
{"end", zccmd_endwin, 0, 0},
{"attr", zccmd_attr, 2, -1},
- {"color", zccmd_color, 2, 2},
{NULL, (zccmd_t)0, 0, 0}
};
@@ -653,19 +671,103 @@
return zcsc->cmd(nam, args+1);
}
-/*
- * boot_ is executed when the module is loaded.
- */
static struct builtin bintab[] = {
BUILTIN("zcurses", 0, bin_zcurses, 1, 6, 0, "", NULL),
};
+
+/*******************
+ * Special variables
+ *******************/
+
+static char **
+zcurses_colorsarrgetfn(UNUSED(Param pm))
+{
+ return zcurses_pairs_to_array(zcurses_colors);
+}
+
+static const struct gsu_array zcurses_colorsarr_gsu =
+{ zcurses_colorsarrgetfn, arrsetfn, stdunsetfn };
+
+
+static char **
+zcurses_attrgetfn(UNUSED(Param pm))
+{
+ return zcurses_pairs_to_array(zcurses_attributes);
+}
+
+static const struct gsu_array zcurses_attrs_gsu =
+{ zcurses_attrgetfn, arrsetfn, stdunsetfn };
+
+
+static char **
+zcurses_windowsgetfn(UNUSED(Param pm))
+{
+ LinkNode node;
+ char **arr, **arrptr;
+ int count = countlinknodes(zcurses_windows);
+
+ arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
+
+ for (node = firstnode(zcurses_windows); node; incnode(node))
+ *arrptr++ = dupstring(((ZCWin)getdata(node))->name);
+ *arrptr = NULL;
+
+ return arr;
+}
+
+static const struct gsu_array zcurses_windows_gsu =
+{ zcurses_windowsgetfn, arrsetfn, stdunsetfn };
+
+
+static zlong
+zcurses_colorsintgetfn(UNUSED(Param pm))
+{
+ return COLORS;
+}
+
+static const struct gsu_integer zcurses_colorsint_gsu =
+{ zcurses_colorsintgetfn, nullintsetfn, stdunsetfn };
+
+
+static zlong
+zcurses_colorpairsintgetfn(UNUSED(Param pm))
+{
+ return COLOR_PAIRS;
+}
+
+static const struct gsu_integer zcurses_colorpairsint_gsu =
+{ zcurses_colorpairsintgetfn, nullintsetfn, stdunsetfn };
+
+
+static struct paramdef partab[] = {
+ SPECIALPMDEF("zcurses_colors", PM_ARRAY|PM_READONLY,
+ &zcurses_colorsarr_gsu, NULL, NULL),
+ SPECIALPMDEF("zcurses_attrs", PM_ARRAY|PM_READONLY,
+ &zcurses_attrs_gsu, NULL, NULL),
+ SPECIALPMDEF("zcurses_windows", PM_ARRAY|PM_READONLY,
+ &zcurses_windows_gsu, NULL, NULL),
+ SPECIALPMDEF("ZCURSES_COLORS", PM_INTEGER|PM_READONLY,
+ &zcurses_colorsint_gsu, NULL, NULL),
+ SPECIALPMDEF("ZCURSES_COLOR_PAIRS", PM_INTEGER|PM_READONLY,
+ &zcurses_colorpairsint_gsu, NULL, NULL)
+};
+
+/***************************
+ * Standard module interface
+ ***************************/
+
+
+/*
+ * boot_ is executed when the module is loaded.
+ */
+
static struct features module_features = {
bintab, sizeof(bintab)/sizeof(*bintab),
NULL, 0,
NULL, 0,
- NULL, 0,
+ partab, sizeof(partab)/sizeof(*partab),
0
};
--
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