]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
cfdisk: resize UI on SIGWINCH
authorKarel Zak <kzak@redhat.com>
Thu, 5 Jun 2014 12:32:51 +0000 (14:32 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 5 Jun 2014 12:32:51 +0000 (14:32 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
configure.ac
disk-utils/cfdisk.c

index e7c6a144d70be57db84fb52db33fadcbb10936cc..107184bf9d1ccb79ae18e7aef45732abad877727 100644 (file)
@@ -706,7 +706,11 @@ AM_CONDITIONAL([HAVE_SLANG], [test "x$have_slang" = xyes])
 AS_IF([test "x$have_slang" = xyes -o "x$have_ncurses" = xyes], [
        AC_CHECK_LIB([$CURSES_LIB_NAME], use_default_colors, [
                     AC_DEFINE(HAVE_USE_DEFAULT_COLORS, 1,
-                              [Define if curses library has the use_default_colors command.])
+                              [Define if curses library has the use_default_colors().])
+       ])
+       AC_CHECK_LIB([$CURSES_LIB_NAME], resizeterm, [
+                    AC_DEFINE(HAVE_RESIZETERM, 1,
+                              [Define if curses library has the resizeterm().])
        ])
 ])
 
index 6d3e6eb8dad6fd646c4f5470080bee3fa1d67220..b0185092a2cc2432514181ada4d69bd0d2b9f61e 100644 (file)
@@ -5,6 +5,7 @@
 #include <ctype.h>
 #include <getopt.h>
 #include <libsmartcols.h>
+#include <sys/ioctl.h>
 
 #ifdef HAVE_SLANG_H
 # include <slang.h>
@@ -76,6 +77,7 @@ static struct cfdisk_menuitem *menu_get_menuitem(struct cfdisk *cf, size_t idx);
 static struct cfdisk_menuitem *menu_get_menuitem_by_key(struct cfdisk *cf, int key, size_t *idx);
 static struct cfdisk_menu *menu_push(struct cfdisk *cf, struct cfdisk_menuitem *item);
 static struct cfdisk_menu *menu_pop(struct cfdisk *cf);
+static void menu_refresh_size(struct cfdisk *cf);
 
 static int ui_refresh(struct cfdisk *cf);
 static void ui_warnx(const char *fmt, ...);
@@ -83,11 +85,13 @@ static void ui_warn(const char *fmt, ...);
 static void ui_info(const char *fmt, ...);
 static void ui_draw_menu(struct cfdisk *cf);
 static int ui_menu_move(struct cfdisk *cf, int key);
+static void ui_menu_resize(struct cfdisk *cf);
 
 static int ui_get_size(struct cfdisk *cf, const char *prompt, uintmax_t *res,
                       uintmax_t low, uintmax_t up);
 
 static int ui_enabled;
+static int ui_resize;
 
 /* menu item */
 struct cfdisk_menuitem {
@@ -161,6 +165,25 @@ static int cols_init(struct cfdisk *cf)
        return fdisk_get_columns(cf->cxt, 0, &cf->cols, &cf->ncols);
 }
 
+static void resize(void)
+{
+       struct winsize ws;
+
+       if (ioctl(fileno(stdout), TIOCGWINSZ, &ws) != -1
+           && ws.ws_row && ws.ws_col) {
+               LINES = ws.ws_row;
+               COLS = ws.ws_col;
+#if HAVE_RESIZETERM
+               resizeterm(ws.ws_row, ws.ws_col);
+#endif
+               clearok(stdscr, TRUE);
+       }
+       touchwin(stdscr);
+
+       DBG(FRONTEND, ul_debug("ui: resize refresh COLS=%d, LINES=%d", COLS, LINES));
+       ui_resize = 0;
+}
+
 /* Reads partition in tree-like order from scols
  */
 static int partition_from_scols(struct fdisk_table *tb,
@@ -408,6 +431,8 @@ static int ask_menu(struct fdisk_ask *ask, struct cfdisk *cf)
        do {
                int key = getch();
 
+               if (ui_resize)
+                       ui_menu_resize(cf);
                if (ui_menu_move(cf, key) == 0)
                        continue;
 
@@ -601,6 +626,18 @@ static void die_on_signal(int dummy __attribute__((__unused__)))
        exit(EXIT_FAILURE);
 }
 
+static void resize_on_signal(int dummy __attribute__((__unused__)))
+{
+       DBG(FRONTEND, ul_debug("resize on signal."));
+       ui_resize = 1;
+}
+
+static void menu_refresh_size(struct cfdisk *cf)
+{
+       if (cf->menu && cf->menu->nitems)
+               cf->menu->page_sz = cf->menu->nitems / (LINES - 4) ? LINES - 4 : 0;
+}
+
 static void menu_update_ignore(struct cfdisk *cf)
 {
        char ignore[128] = { 0 };
@@ -643,7 +680,7 @@ static void menu_update_ignore(struct cfdisk *cf)
        else
                m->idx = 0;
 
-       m->page_sz = m->nitems / (LINES - 4) ? LINES - 4 : 0;
+       menu_refresh_size(cf);
 }
 
 static struct cfdisk_menu *menu_push(
@@ -669,7 +706,7 @@ static struct cfdisk_menu *menu_push(
        }
 
        cf->menu = m;
-       m->page_sz = m->nitems / (LINES - 4) ? LINES - 4 : 0;
+       menu_refresh_size(cf);
        return m;
 }
 
@@ -718,6 +755,9 @@ static int ui_init(struct cfdisk *cf __attribute__((__unused__)))
        sigaction(SIGINT, &sa, NULL);
        sigaction(SIGTERM, &sa, NULL);
 
+       sa.sa_handler = resize_on_signal;
+       sigaction(SIGWINCH, &sa, NULL);
+
        ui_enabled = 1;
        initscr();
 
@@ -859,6 +899,29 @@ static void ui_draw_menuitem(struct cfdisk *cf,
                mvprintw(ln, cl, vert ? " %s " : "[%s]", buf);
 }
 
+static void ui_clean_menu(struct cfdisk *cf)
+{
+       size_t i;
+       size_t nlines;
+       struct cfdisk_menu *m = cf->menu;
+       size_t ln = menuitem_get_line(cf, 0);
+
+       if (m->vertical)
+               nlines = m->page_sz ? m->page_sz : m->nitems;
+       else
+               nlines = menuitem_get_line(cf, m->nitems);
+
+       for (i = ln; i <= ln + nlines; i++) {
+               move(i, 0);
+               clrtoeol();
+       }
+       if (m->vertical) {
+               move(ln - 1, 0);
+               clrtoeol();
+       }
+       ui_clean_hint();
+}
+
 static void ui_draw_menu(struct cfdisk *cf)
 {
        struct cfdisk_menuitem *d;
@@ -872,6 +935,7 @@ static void ui_draw_menu(struct cfdisk *cf)
 
        DBG(FRONTEND, ul_debug("ui: menu: draw start"));
 
+       ui_clean_menu(cf);
        m = cf->menu;
 
        if (m->vertical)
@@ -879,11 +943,6 @@ static void ui_draw_menu(struct cfdisk *cf)
        else
                nlines = menuitem_get_line(cf, m->nitems);
 
-       for (i = ln; i <= ln + nlines; i++) {
-               move(i, 0);
-               clrtoeol();
-       }
-
        if (m->ignore_cb)
                menu_update_ignore(cf);
        i = 0;
@@ -973,6 +1032,9 @@ static int ui_menu_move(struct cfdisk *cf, int key)
        assert(cf);
        assert(cf->menu);
 
+       if (key == ERR)
+               return 0;       /* ignore errors */
+
        m = cf->menu;
 
        DBG(FRONTEND, ul_debug("ui: menu move key >%c<.", key));
@@ -1025,6 +1087,16 @@ static int ui_menu_move(struct cfdisk *cf, int key)
        return 1;       /* key irrelevant for menu move */
 }
 
+/* but don't call me from ui_run(), this is for pop-up menus only */
+static void ui_menu_resize(struct cfdisk *cf)
+{
+       resize();
+       ui_clean_menu(cf);
+       menu_refresh_size(cf);
+       ui_draw_menu(cf);
+       refresh();
+}
+
 static int partition_on_page(struct cfdisk *cf, size_t i)
 {
        if (cf->page_sz == 0 ||
@@ -1221,6 +1293,10 @@ static ssize_t ui_get_string(struct cfdisk *cf, const char *prompt,
                int c;
                if ((c = getch()) == ERR) {
 #endif
+                       if (ui_resize) {
+                               resize();
+                               continue;
+                       }
                        if (!isatty(STDIN_FILENO))
                                exit(2);
                        else
@@ -1406,6 +1482,8 @@ static struct fdisk_parttype *ui_get_parttype(struct cfdisk *cf,
        do {
                int key = getch();
 
+               if (ui_resize)
+                       ui_menu_resize(cf);
                if (ui_menu_move(cf, key) == 0)
                        continue;
 
@@ -1472,6 +1550,9 @@ static int ui_create_label(struct cfdisk *cf)
 
        do {
                int key = getch();
+
+               if (ui_resize)
+                       ui_menu_resize(cf);
                if (ui_menu_move(cf, key) == 0)
                        continue;
                switch (key) {
@@ -1538,6 +1619,7 @@ static int ui_help(void)
                mvaddstr(i, 1, _(help[i]));
 
        ui_info(_("Press a key to continue."));
+
        getch();
        return 0;
 }
@@ -1738,6 +1820,14 @@ static int main_menu_action(struct cfdisk *cf, int key)
        return 0;
 }
 
+static void ui_resize_refresh(struct cfdisk *cf)
+{
+       resize();
+       menu_refresh_size(cf);
+       lines_refresh(cf);
+       ui_refresh(cf);
+}
+
 static int ui_run(struct cfdisk *cf)
 {
        int rc = 0;
@@ -1771,6 +1861,12 @@ static int ui_run(struct cfdisk *cf)
        do {
                int rc = 0, key = getch();
 
+               if (ui_resize)
+                       /* Note that ncurses getch() returns ERR when interrupted
+                        * by signal, but SLang does not interrupt at all. */
+                       ui_resize_refresh(cf);
+               if (key == ERR)
+                       continue;
                if (ui_menu_move(cf, key) == 0)
                        continue;