about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--Doc/Zsh/mod_curses.yo14
-rw-r--r--Src/Modules/curses.c65
3 files changed, 69 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 0f87e6378..354025af4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-10-17  Peter Stephenson  <pws@csr.com>
+
+	* 23970 (slightly modified): Doc/Zsh/mod_curses.yo,
+	Src/Modules/curses.c: fix up deletion of curses windows and add
+	zcurses -i/-e for initialisation and end to retain terminal
+	sanity; make "zcurses -r" do a global refresh.
+
+	* Vin Shelton: 23968: Doc/Zsh/mod_curses.yo: overabundance of
+	enditem().
+
 2007-10-15  Clint Adams  <clint@zsh.org>
 
 	* 23965: Completion/Unix/Command/_git: add missing bracket in
diff --git a/Doc/Zsh/mod_curses.yo b/Doc/Zsh/mod_curses.yo
index 386074cd9..f2b442e98 100644
--- a/Doc/Zsh/mod_curses.yo
+++ b/Doc/Zsh/mod_curses.yo
@@ -6,14 +6,19 @@ The tt(zsh/curses) module makes available one builtin command:
 startitem()
 findex(zcurses)
 cindex(windows, curses)
+xitem(tt(zcurses) tt(-i))
+xitem(tt(zcurses) tt(-e))
 xitem(tt(zcurses) tt(-a) var(targetwin) var(nlines) var(ncols) var(begin_y) var(begin_x) )
 xitem(tt(zcurses) tt(-d) var(targetwin) )
-xitem(tt(zcurses) tt(-r) var(targetwin) )
+xitem(tt(zcurses) tt(-r) [ var(targetwin) ] )
 xitem(tt(zcurses) tt(-m) var(targetwin) var(new_y) var(new_x) )
 xitem(tt(zcurses) tt(-c) var(targetwin) var(character) )
 xitem(tt(zcurses) tt(-s) var(targetwin) var(string) )
 item(tt(zcurses) tt(-b) var(targetwin) var(border) )(
-Manipulate curses windows.
+Manipulate curses windows.  All uses of this command should be
+bracketed by `tt(zcurses -i)' to initialise use of curses, and
+`tt(zcurses -e)' to end it; omitting `tt(zcurses -e)' can cause
+the terminal to be in an unwanted state.
 
 With tt(-a), 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
@@ -24,7 +29,8 @@ Use tt(-d) to delete a window created with tt(-a).
 
 The tt(-r) command will refresh window var(targetwin); this is necessary to
 make any pending changes (such as characters you have prepared for output
-with tt(-c)) visible on the screen.
+with tt(-c)) visible on the screen.  If no argument is given,
+all windows are refreshed; this is necessary after deleting a window.
 
 tt(-m) moves the cursor position in var(targetwin) to new coordinates
 var(new_y) and var(new_x).
@@ -35,5 +41,3 @@ respectively.
 To draw a border around window var(targetwin), use tt(-b).
 )
 enditem()
-
-enditem()
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index fa1ea8b3b..3edd23c22 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -44,8 +44,10 @@ typedef struct zc_win {
     char *name;
 } *ZCWin;
 
-WINDOW *win_zero;
-LinkList zcurses_windows;
+static WINDOW *win_zero;
+static struct ttyinfo saved_tty_state;
+static struct ttyinfo curses_tty_state;
+static LinkList zcurses_windows;
 
 #define ZCURSES_ERANGE 1
 #define ZCURSES_EDEFINED 2
@@ -125,6 +127,18 @@ zcurses_free_window(ZCWin w)
 static int
 bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
 {
+    /* Initialise curses */
+    if (OPT_ISSET(ops,'i')) {
+	if (!win_zero) {
+	    gettyinfo(&saved_tty_state);
+	    win_zero = initscr();
+	    gettyinfo(&curses_tty_state);
+	} else {
+	    settyinfo(&curses_tty_state);
+	}
+	return 0;
+    }
+
     if (OPT_ISSET(ops,'a')) {
 	int nlines, ncols, begin_y, begin_x;
         ZCWin w;
@@ -179,24 +193,31 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
 	if (w->name)
 	    zsfree(w->name);
 
-        remnode(zcurses_windows, node);
+        zfree((ZCWin)remnode(zcurses_windows, node), sizeof(struct zc_win));
 
 	return 0;
     }
 
     if (OPT_ISSET(ops,'r')) {
-	LinkNode node;
-	ZCWin w;
+	if (args[0]) {
+	    LinkNode node;
+	    ZCWin w;
 
-	node = zcurses_validate_window(OPT_ARG(ops,'r'), ZCURSES_USED);
-	if (node == NULL) {
-	    zwarnnam(nam, "%s: %s", zcurses_strerror(zc_errno), OPT_ARG(ops,'r'), 0);
-	    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);
+	    w = (ZCWin)getdata(node);
 
-	return (wrefresh(w->win)!=OK) ? 1 : 0;
+	    return (wrefresh(w->win)!=OK) ? 1 : 0;
+	}
+	else
+	{
+	    return (refresh() != OK) ? 1 : 0;
+	}
     }
 
     if (OPT_ISSET(ops,'m')) {
@@ -325,6 +346,22 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
 	return 0;
     }
 
+    /* Finish using curses */
+    if (OPT_ISSET(ops,'e')) {
+	if (win_zero) {
+	    endwin();
+	    /* Restore TTY as it was before zcurses -i */
+	    settyinfo(&saved_tty_state);
+	    /*
+	     * TODO: should I need the following?  Without it
+	     * the screen stays messed up.  Presumably we are
+	     * doing stuff with shttyinfo when we shouldn't really be.
+	     */
+	    gettyinfo(&shttyinfo);
+	}
+	return 0;
+    }
+
     return 0;
 }
 
@@ -333,7 +370,7 @@ bin_zcurses(char *nam, char **args, Options ops, UNUSED(int func))
  */
 
 static struct builtin bintab[] = {
-    BUILTIN("zcurses", 0, bin_zcurses, 0, 5, 0, "ab:cd:mr:rs", NULL),
+    BUILTIN("zcurses", 0, bin_zcurses, 0, 5, 0, "ab:cd:eimrs", NULL),
 };
 
 static struct features module_features = {
@@ -371,7 +408,6 @@ int
 boot_(Module m)
 {
     zcurses_windows = znewlinklist();
-    win_zero=initscr();
 
     return 0;
 }
@@ -380,7 +416,6 @@ boot_(Module m)
 int
 cleanup_(Module m)
 {
-    endwin();
     freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
     return setfeatureenables(m, &module_features, NULL);
 }