]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
cfdisk: supports also vertical menus
authorKarel Zak <kzak@redhat.com>
Mon, 24 Feb 2014 12:57:08 +0000 (13:57 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 11 Mar 2014 10:35:14 +0000 (11:35 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
fdisks/cfdisk.c

index 1d93d8d53935dd40586a80a053f206aeee0b73cd..b5029eef144ed91c36465a38e97c832a594f2892 100644 (file)
@@ -93,6 +93,7 @@ struct cfdisk_menudesc {
 };
 
 struct cfdisk_menu {
+       char                    *title;
        struct cfdisk_menudesc  *desc;
        char                    *ignore;
        size_t                  id;
@@ -102,6 +103,8 @@ struct cfdisk_menu {
        menu_callback_t         *callback;
 
        struct cfdisk_menu      *prev;
+
+       unsigned int            vertical : 1;
 };
 
 static struct cfdisk_menudesc menu_main[] = {
@@ -658,12 +661,27 @@ static struct cfdisk_menu *menu_pop(struct cfdisk *cf)
        if (cf->menu) {
                m = cf->menu->prev;
                free(cf->menu->ignore);
+               free(cf->menu->title);
                free(cf->menu);
        }
        cf->menu = m;
        return cf->menu;
 }
 
+static void menu_set_title(struct cfdisk_menu *m, const char *title)
+{
+       char *str = NULL;
+
+       if (title) {
+               size_t len =  mbs_safe_width(title);
+               if (len + 3 > m->width)
+                       m->width = len + 3;
+               str = xstrdup(title);
+       }
+       m->title = str;
+}
+
+
 /* returns: error: < 0, success: 0, quit: 1 */
 static int menu_cb_main(struct cfdisk *cf, int key)
 {
@@ -789,25 +807,41 @@ static int ui_init(struct cfdisk *cf __attribute__((__unused__)))
 
 static size_t menuitem_get_line(struct cfdisk *cf, size_t idx)
 {
-       size_t len = cf->menu->width + 4 + MENU_PADDING;        /* item width */
-       size_t items = COLS / len;                              /* items per line */
+       if (cf->menu->vertical) {
+               size_t ni = (cf->menu->nitems + 1) / 2;
+               size_t l = LINES / 2;
 
-       return MENU_START_LINE + ((idx / items));
+               ni = ni > l ? l - 1 : ni;
+               return l - ni + idx;
+       } else {
+               size_t len = cf->menu->width + 4 + MENU_PADDING;        /* item width */
+               size_t items = COLS / len;                              /* items per line */
+
+               return MENU_START_LINE + ((idx / items));
+       }
 }
 
 static int menuitem_get_column(struct cfdisk *cf, size_t idx)
 {
-       size_t len = cf->menu->width + 4 + MENU_PADDING;        /* item width */
-       size_t items = COLS / len;                              /* items per line */
-       size_t extra = items < cf->menu->nitems ?               /* extra space on line */
-                       COLS % len :                            /* - multi-line menu */
-                       COLS - (cf->menu->nitems * len);        /* - one line menu */
+       if (cf->menu->vertical) {
+               size_t nc = cf->menu->width + MENU_PADDING;
+               size_t c = COLS / 2;
 
-       extra += MENU_PADDING;          /* add padding after last item to extra */
+               nc = nc > c ? c - 1 : nc;
+               return c - nc;
+       } else {
+               size_t len = cf->menu->width + 4 + MENU_PADDING;        /* item width */
+               size_t items = COLS / len;                              /* items per line */
+               size_t extra = items < cf->menu->nitems ?               /* extra space on line */
+                               COLS % len :                            /* - multi-line menu */
+                               COLS - (cf->menu->nitems * len);        /* - one line menu */
+
+               extra += MENU_PADDING;          /* add padding after last item to extra */
 
-       if (idx < items)
-               return (idx * len) + (extra / 2);
-       return ((idx % items) * len) + (extra / 2);
+               if (idx < items)
+                       return (idx * len) + (extra / 2);
+               return ((idx % items) * len) + (extra / 2);
+       }
 }
 
 static struct cfdisk_menudesc *menu_get_menuitem(struct cfdisk *cf, size_t idx)
@@ -848,10 +882,12 @@ static void ui_draw_menuitem(struct cfdisk *cf,
        char buf[80 * MB_CUR_MAX];
        const char *name;
        size_t width = cf->menu->width + 2;     /* 2 = blank around string */
-       int ln, cl;
+       int ln, cl, vert = cf->menu->vertical;
 
        name = _(d->name);
-       mbsalign(name, buf, sizeof(buf), &width, MBS_ALIGN_CENTER, 0);
+       mbsalign(name, buf, sizeof(buf), &width,
+                       vert ? MBS_ALIGN_LEFT : MBS_ALIGN_CENTER,
+                       0);
 
        ln = menuitem_get_line(cf, idx);
        cl = menuitem_get_column(cf, idx);
@@ -859,19 +895,25 @@ static void ui_draw_menuitem(struct cfdisk *cf,
        DBG(FRONTEND, dbgprint("ui: menuitem: cl=%d, ln=%d, item='%s'",
                        cl, ln, buf));
 
+       if (vert) {
+               mvaddch(ln, cl - 1, ACS_VLINE);
+               mvaddch(ln, cl + cf->menu->width + 4, ACS_VLINE);
+       }
+
        if (cf->menu_idx == idx) {
                standout();
-               mvprintw(ln, cl, "[%s]", buf);
+               mvprintw(ln, cl, vert ? " %s " : "[%s]", buf);
                standend();
                if (d->desc)
                        ui_hint(d->desc);
        } else
-               mvprintw(ln, cl, "[%s]", buf);
+               mvprintw(ln, cl, vert ? " %s " : "[%s]", buf);
 }
 
 static void ui_draw_menu(struct cfdisk *cf)
 {
        struct cfdisk_menudesc *d;
+       struct cfdisk_menu *m;
        size_t i = 0;
 
        assert(cf);
@@ -879,6 +921,8 @@ static void ui_draw_menu(struct cfdisk *cf)
 
        DBG(FRONTEND, dbgprint("ui: menu: draw start"));
 
+       m = cf->menu;
+
        for (i = MENU_START_LINE; i < (size_t) LINES - 1; i++) {
                move(i, 0);
                clrtoeol();
@@ -890,6 +934,29 @@ static void ui_draw_menu(struct cfdisk *cf)
        while ((d = menu_get_menuitem(cf, i)))
                ui_draw_menuitem(cf, d, i++);
 
+       if (m->vertical) {
+               size_t ln = menuitem_get_line(cf, 0);
+               size_t cl = menuitem_get_column(cf, 0);
+               size_t nlines = i;
+
+               mvaddch(ln - 1, cl - 1, ACS_ULCORNER);
+               mvaddch(ln + nlines, cl - 1, ACS_LLCORNER);
+
+               for (i = 0; i < m->width + 4; i++) {
+                       mvaddch(ln - 1, cl + i, ACS_HLINE);
+                       mvaddch(ln + nlines, cl + i, ACS_HLINE);
+               }
+               mvaddch(ln - 1, cl + i, ACS_URCORNER);
+               mvaddch(ln + nlines, cl + i, ACS_LRCORNER);
+
+               if (m->title) {
+                       attron(A_BOLD);
+                       mvprintw(ln - 1, cl, " %s ", m->title);
+                       attroff(A_BOLD);
+               }
+
+       }
+
        DBG(FRONTEND, dbgprint("ui: menu: draw end."));
 }