summaryrefslogtreecommitdiff
path: root/Src/Modules/curses.c
diff options
context:
space:
mode:
authorSebastian Gniazdowski <psprint3@fastmail.com>2017-03-05 11:25:38 -0800
committerBarton E. Schaefer <schaefer@zsh.org>2017-03-05 11:25:38 -0800
commit23275fc8db671cecb5b6491a06455b27fbabd59b (patch)
tree181ca07d3819a151622d274bf25fc87396f1b269 /Src/Modules/curses.c
parent8522e996ecc88697344dcc4814367ec7e32e7deb (diff)
downloadzsh-23275fc8db671cecb5b6491a06455b27fbabd59b.tar.gz
zsh-23275fc8db671cecb5b6491a06455b27fbabd59b.zip
40726: add "zcurses resize" for sane terminal size change
Diffstat (limited to 'Src/Modules/curses.c')
-rw-r--r--Src/Modules/curses.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index d9c19bdb1..a60dfcbf8 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(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' 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", zccmd_resize, 2, 3},
{NULL, (zccmd_t)0, 0, 0}
};