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

[PATCH] Zcurses sub-command "resize_term"



Hello,
thought I need that, turned out it isn't exactly needed. "zcurses end;
zcurses refresh;" accomplishes the same goal. More, 5 system
configurations confirmed that endwin() before resize_term(); is needed,
otherwise moves start to be inaccurate (randomly ignore x position). I
think it's a bug in ncurses. Tested OS X ncurses 5.4, Homebrew ncursesw
6.0-2, Arch Linux ncursesw 6.0, Ubuntu 14.04 ncurses 5.9, FreeBSD
ncursesw.so.8.

So why a new sub-command? For versatility. Some edge situations, future
ncurses versions, PDCurses, etc. The sub-command will secure edge cases
and new situations.

If it has "endwin" third param, it does the needed endwin() and refresh.
If "nosave" is used, curses terminal state will not be re-read into
internal variable. I can imagine some edge case for that.
"endwin_nosave" can be used for both effects.

To test resize_term extension availability, 0 for height and width can
be given, $? == 0 or $? == 2 are possible results.

-- 
  Sebastian Gniazdowski
  psprint3@xxxxxxxxxxxx
diff --git a/Doc/Zsh/mod_curses.yo b/Doc/Zsh/mod_curses.yo
index 72dc409..82103e4 100644
--- a/Doc/Zsh/mod_curses.yo
+++ b/Doc/Zsh/mod_curses.yo
@@ -27,7 +27,8 @@ xitem(tt(zcurses) tt(scroll) var(targetwin) [ tt(on) | tt(off) | [tt(+)|tt(-)]va
 xitem(tt(zcurses) tt(input) var(targetwin) [ var(param) [ var(kparam) [ var(mparam) ] ] ])
 xitem(tt(zcurses) tt(mouse) [ tt(delay) var(num) | [tt(+)|tt(-)]tt(motion) ])
 xitem(tt(zcurses) tt(timeout) var(targetwin) var(intval))
-item(tt(zcurses) tt(querychar) var(targetwin) [ var(param) ])(
+xitem(tt(zcurses) tt(querychar) var(targetwin) [ var(param) ])
+item(tt(zcurses) tt(resize_term) var(height) var(width) [ tt(endwin) | tt(nosave) | tt(endwin_nosave) ])(
 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
@@ -211,6 +212,21 @@ second is the color pair in the usual var(fg_col)tt(/)var(bg_col)
 notation, or tt(0) if color is not supported.  Any attributes other than
 color that apply to the character, as set with the subcommand tt(attr),
 appear as additional elements.
+
+The subcommand tt(resize_term) resizes tt(stdscr) and all windows to
+given dimensions (windows that stick out from the new dimensions are
+resized down). The underlying curses extension (tt(resize_term call))
+can be unavailable. To verify, zeroes can be used for var(height) and
+var(width). If the result of the subcommand is tt(0), resize_term is
+available (tt(2) otherwise). Tests show that resizing can be normally
+accomplished by calling tt(zcurses end) and tt(zcurses refresh). The
+tt(resize_term) subcommand is provided for versatility. Multiple
+system configurations have been checked and tt(zcurses end) and
+tt(zcurses refresh) are still needed for correct terminal state after
+resize. To invoke them with tt(resize_term), use var(endwin) argument.
+Using var(nosave) argument will cause new terminal state to not be
+saved internally by tt(zcurses). This is also provided for versatility
+and should normally be not needed.
 )
 enditem()
 
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index d9c19bd..dcb7ed2 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -1490,6 +1490,74 @@ zccmd_touch(const char *nam, char **args)
     return ret;
 }
 
+static int
+zccmd_resize_term(const char *nam, char **args)
+{
+#ifdef HAVE_RESIZE_TERM
+    int y, x, do_endwin=0, do_save=1;
+    LinkNode stdscr_win = zcurses_getwindowbyname("stdscr");
+
+    if (stdscr_win) {
+        y = atoi(args[0]);
+        x = atoi(args[1]);
+        if (args[2]) {
+            if (0 == strcmp(args[2], "endwin")) {
+                do_endwin=1;
+            } else if (0 == strcmp(args[2], "endwin_nosave")) {
+                do_endwin=1;
+                do_save=0;
+            } else if (0 == strcmp(args[2], "nosave")) {
+                do_save=0;
+            } else {
+                zwarnnam(nam, "`resize_term' expects `endwin', `nosave' or `endwin_nosave' for third argument, if given");
+            }
+        }
+
+        if (y == 0 && x == 0 && args[2] == NULL) {
+            // Special case to just test that curses has resize_term. #ifdef
+            // HAVE_RESIZE_TERM will result in return value 2 if resize_term
+            // is not available.
+            return 0;
+        } else {
+            // Without this call some window moves are innacurate. Tested on
+            // OS X ncurses 5.4, Homebrew ncursesw 6.0-2, Arch Linux ncursesw
+            // 6.0, Ubuntu 14.04 ncurses 5.9, FreeBSD ncursesw.so.8
+            //
+            // On the other hand, the whole resize goal can be (from tests)
+            // accomplished by calling endwin and refresh. But to secure any
+            // future problems, resize_term is provided, and it is featured
+            // with endwin, so that users have multiple options.
+            if (do_endwin) {
+                endwin();
+            }
+
+            if( resize_term( y, x ) == OK ) {
+                // Things work without this, but we need to get out from
+                // endwin (i.e. call refresh), and in theory store new
+                // curses state (the resize might have changed it), which
+                // should be presented to terminal only after refresh.
+                if (do_endwin || do_save) {
+                    ZCWin w;
+                    w = (ZCWin)getdata(stdscr_win);
+                    wnoutrefresh(w->win);
+                    doupdate();
+                }
+
+                if (do_save) {
+                    gettyinfo(&curses_tty_state);
+                }
+                return 0;
+            } else {
+                return 1;
+            }
+        }
+    } else {
+        return 1;
+    }
+#else
+    return 2;
+#endif
+}
 
 /*********************
   Main builtin handler
@@ -1523,6 +1591,7 @@ bin_zcurses(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
 	{"mouse", zccmd_mouse, 0, -1},
 	{"querychar", zccmd_querychar, 1, 2},
 	{"touch", zccmd_touch, 1, -1},
+	{"resize_term", zccmd_resize_term, 2, 3},
 	{NULL, (zccmd_t)0, 0, 0}
     };
 
diff --git a/configure.ac b/configure.ac
index 0551a69..911cc45 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1309,7 +1309,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
 	       putenv getenv setenv unsetenv xw\
 	       brk sbrk \
 	       pathconf sysconf \
-	       tgetent tigetflag tigetnum tigetstr setupterm initscr \
+	       tgetent tigetflag tigetnum tigetstr setupterm initscr resize_term \
 	       getcchar setcchar waddwstr wget_wch win_wch use_default_colors \
 	       pcre_compile pcre_study pcre_exec \
 	       nl_langinfo \


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