Annotation of qemu/roms/seabios/tools/kconfig/lxdialog/menubox.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  menubox.c -- implements the menu box
                      3:  *
                      4:  *  ORIGINAL AUTHOR: Savio Lam ([email protected])
                      5:  *  MODIFIED FOR LINUX KERNEL CONFIG BY: William Roadcap ([email protected])
                      6:  *
                      7:  *  This program is free software; you can redistribute it and/or
                      8:  *  modify it under the terms of the GNU General Public License
                      9:  *  as published by the Free Software Foundation; either version 2
                     10:  *  of the License, or (at your option) any later version.
                     11:  *
                     12:  *  This program is distributed in the hope that it will be useful,
                     13:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  *  GNU General Public License for more details.
                     16:  *
                     17:  *  You should have received a copy of the GNU General Public License
                     18:  *  along with this program; if not, write to the Free Software
                     19:  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     20:  */
                     21: 
                     22: /*
                     23:  *  Changes by Clifford Wolf ([email protected])
                     24:  *
                     25:  *  [ 1998-06-13 ]
                     26:  *
                     27:  *    *)  A bugfix for the Page-Down problem
                     28:  *
                     29:  *    *)  Formerly when I used Page Down and Page Up, the cursor would be set 
                     30:  *        to the first position in the menu box.  Now lxdialog is a bit
                     31:  *        smarter and works more like other menu systems (just have a look at
                     32:  *        it).
                     33:  *
                     34:  *    *)  Formerly if I selected something my scrolling would be broken because
                     35:  *        lxdialog is re-invoked by the Menuconfig shell script, can't
                     36:  *        remember the last scrolling position, and just sets it so that the
                     37:  *        cursor is at the bottom of the box.  Now it writes the temporary file
                     38:  *        lxdialog.scrltmp which contains this information. The file is
                     39:  *        deleted by lxdialog if the user leaves a submenu or enters a new
                     40:  *        one, but it would be nice if Menuconfig could make another "rm -f"
                     41:  *        just to be sure.  Just try it out - you will recognise a difference!
                     42:  *
                     43:  *  [ 1998-06-14 ]
                     44:  *
                     45:  *    *)  Now lxdialog is crash-safe against broken "lxdialog.scrltmp" files
                     46:  *        and menus change their size on the fly.
                     47:  *
                     48:  *    *)  If for some reason the last scrolling position is not saved by
                     49:  *        lxdialog, it sets the scrolling so that the selected item is in the
                     50:  *        middle of the menu box, not at the bottom.
                     51:  *
                     52:  * 02 January 1999, Michael Elizabeth Chastain ([email protected])
                     53:  * Reset 'scroll' to 0 if the value from lxdialog.scrltmp is bogus.
                     54:  * This fixes a bug in Menuconfig where using ' ' to descend into menus
                     55:  * would leave mis-synchronized lxdialog.scrltmp files lying around,
                     56:  * fscanf would read in 'scroll', and eventually that value would get used.
                     57:  */
                     58: 
                     59: #include "dialog.h"
                     60: 
                     61: static int menu_width, item_x;
                     62: 
                     63: /*
                     64:  * Print menu item
                     65:  */
                     66: static void do_print_item(WINDOW * win, const char *item, int line_y,
                     67:                           int selected, int hotkey)
                     68: {
                     69:        int j;
                     70:        char *menu_item = malloc(menu_width + 1);
                     71: 
                     72:        strncpy(menu_item, item, menu_width - item_x);
                     73:        menu_item[menu_width - item_x] = '\0';
                     74:        j = first_alpha(menu_item, "YyNnMmHh");
                     75: 
                     76:        /* Clear 'residue' of last item */
                     77:        wattrset(win, dlg.menubox.atr);
                     78:        wmove(win, line_y, 0);
                     79: #if OLD_NCURSES
                     80:        {
                     81:                int i;
                     82:                for (i = 0; i < menu_width; i++)
                     83:                        waddch(win, ' ');
                     84:        }
                     85: #else
                     86:        wclrtoeol(win);
                     87: #endif
                     88:        wattrset(win, selected ? dlg.item_selected.atr : dlg.item.atr);
                     89:        mvwaddstr(win, line_y, item_x, menu_item);
                     90:        if (hotkey) {
                     91:                wattrset(win, selected ? dlg.tag_key_selected.atr
                     92:                         : dlg.tag_key.atr);
                     93:                mvwaddch(win, line_y, item_x + j, menu_item[j]);
                     94:        }
                     95:        if (selected) {
                     96:                wmove(win, line_y, item_x + 1);
                     97:        }
                     98:        free(menu_item);
                     99:        wrefresh(win);
                    100: }
                    101: 
                    102: #define print_item(index, choice, selected)                            \
                    103: do {                                                                   \
                    104:        item_set(index);                                                \
                    105:        do_print_item(menu, item_str(), choice, selected, !item_is_tag(':')); \
                    106: } while (0)
                    107: 
                    108: /*
                    109:  * Print the scroll indicators.
                    110:  */
                    111: static void print_arrows(WINDOW * win, int item_no, int scroll, int y, int x,
                    112:                         int height)
                    113: {
                    114:        int cur_y, cur_x;
                    115: 
                    116:        getyx(win, cur_y, cur_x);
                    117: 
                    118:        wmove(win, y, x);
                    119: 
                    120:        if (scroll > 0) {
                    121:                wattrset(win, dlg.uarrow.atr);
                    122:                waddch(win, ACS_UARROW);
                    123:                waddstr(win, "(-)");
                    124:        } else {
                    125:                wattrset(win, dlg.menubox.atr);
                    126:                waddch(win, ACS_HLINE);
                    127:                waddch(win, ACS_HLINE);
                    128:                waddch(win, ACS_HLINE);
                    129:                waddch(win, ACS_HLINE);
                    130:        }
                    131: 
                    132:        y = y + height + 1;
                    133:        wmove(win, y, x);
                    134:        wrefresh(win);
                    135: 
                    136:        if ((height < item_no) && (scroll + height < item_no)) {
                    137:                wattrset(win, dlg.darrow.atr);
                    138:                waddch(win, ACS_DARROW);
                    139:                waddstr(win, "(+)");
                    140:        } else {
                    141:                wattrset(win, dlg.menubox_border.atr);
                    142:                waddch(win, ACS_HLINE);
                    143:                waddch(win, ACS_HLINE);
                    144:                waddch(win, ACS_HLINE);
                    145:                waddch(win, ACS_HLINE);
                    146:        }
                    147: 
                    148:        wmove(win, cur_y, cur_x);
                    149:        wrefresh(win);
                    150: }
                    151: 
                    152: /*
                    153:  * Display the termination buttons.
                    154:  */
                    155: static void print_buttons(WINDOW * win, int height, int width, int selected)
                    156: {
                    157:        int x = width / 2 - 16;
                    158:        int y = height - 2;
                    159: 
                    160:        print_button(win, gettext("Select"), y, x, selected == 0);
                    161:        print_button(win, gettext(" Exit "), y, x + 12, selected == 1);
                    162:        print_button(win, gettext(" Help "), y, x + 24, selected == 2);
                    163: 
                    164:        wmove(win, y, x + 1 + 12 * selected);
                    165:        wrefresh(win);
                    166: }
                    167: 
                    168: /* scroll up n lines (n may be negative) */
                    169: static void do_scroll(WINDOW *win, int *scroll, int n)
                    170: {
                    171:        /* Scroll menu up */
                    172:        scrollok(win, TRUE);
                    173:        wscrl(win, n);
                    174:        scrollok(win, FALSE);
                    175:        *scroll = *scroll + n;
                    176:        wrefresh(win);
                    177: }
                    178: 
                    179: /*
                    180:  * Display a menu for choosing among a number of options
                    181:  */
                    182: int dialog_menu(const char *title, const char *prompt,
                    183:                 const void *selected, int *s_scroll)
                    184: {
                    185:        int i, j, x, y, box_x, box_y;
                    186:        int height, width, menu_height;
                    187:        int key = 0, button = 0, scroll = 0, choice = 0;
                    188:        int first_item =  0, max_choice;
                    189:        WINDOW *dialog, *menu;
                    190: 
                    191: do_resize:
                    192:        height = getmaxy(stdscr);
                    193:        width = getmaxx(stdscr);
                    194:        if (height < 15 || width < 65)
                    195:                return -ERRDISPLAYTOOSMALL;
                    196: 
                    197:        height -= 4;
                    198:        width  -= 5;
                    199:        menu_height = height - 10;
                    200: 
                    201:        max_choice = MIN(menu_height, item_count());
                    202: 
                    203:        /* center dialog box on screen */
                    204:        x = (COLS - width) / 2;
                    205:        y = (LINES - height) / 2;
                    206: 
                    207:        draw_shadow(stdscr, y, x, height, width);
                    208: 
                    209:        dialog = newwin(height, width, y, x);
                    210:        keypad(dialog, TRUE);
                    211: 
                    212:        draw_box(dialog, 0, 0, height, width,
                    213:                 dlg.dialog.atr, dlg.border.atr);
                    214:        wattrset(dialog, dlg.border.atr);
                    215:        mvwaddch(dialog, height - 3, 0, ACS_LTEE);
                    216:        for (i = 0; i < width - 2; i++)
                    217:                waddch(dialog, ACS_HLINE);
                    218:        wattrset(dialog, dlg.dialog.atr);
                    219:        wbkgdset(dialog, dlg.dialog.atr & A_COLOR);
                    220:        waddch(dialog, ACS_RTEE);
                    221: 
                    222:        print_title(dialog, title, width);
                    223: 
                    224:        wattrset(dialog, dlg.dialog.atr);
                    225:        print_autowrap(dialog, prompt, width - 2, 1, 3);
                    226: 
                    227:        menu_width = width - 6;
                    228:        box_y = height - menu_height - 5;
                    229:        box_x = (width - menu_width) / 2 - 1;
                    230: 
                    231:        /* create new window for the menu */
                    232:        menu = subwin(dialog, menu_height, menu_width,
                    233:                      y + box_y + 1, x + box_x + 1);
                    234:        keypad(menu, TRUE);
                    235: 
                    236:        /* draw a box around the menu items */
                    237:        draw_box(dialog, box_y, box_x, menu_height + 2, menu_width + 2,
                    238:                 dlg.menubox_border.atr, dlg.menubox.atr);
                    239: 
                    240:        if (menu_width >= 80)
                    241:                item_x = (menu_width - 70) / 2;
                    242:        else
                    243:                item_x = 4;
                    244: 
                    245:        /* Set choice to default item */
                    246:        item_foreach()
                    247:                if (selected && (selected == item_data()))
                    248:                        choice = item_n();
                    249:        /* get the saved scroll info */
                    250:        scroll = *s_scroll;
                    251:        if ((scroll <= choice) && (scroll + max_choice > choice) &&
                    252:           (scroll >= 0) && (scroll + max_choice <= item_count())) {
                    253:                first_item = scroll;
                    254:                choice = choice - scroll;
                    255:        } else {
                    256:                scroll = 0;
                    257:        }
                    258:        if ((choice >= max_choice)) {
                    259:                if (choice >= item_count() - max_choice / 2)
                    260:                        scroll = first_item = item_count() - max_choice;
                    261:                else
                    262:                        scroll = first_item = choice - max_choice / 2;
                    263:                choice = choice - scroll;
                    264:        }
                    265: 
                    266:        /* Print the menu */
                    267:        for (i = 0; i < max_choice; i++) {
                    268:                print_item(first_item + i, i, i == choice);
                    269:        }
                    270: 
                    271:        wnoutrefresh(menu);
                    272: 
                    273:        print_arrows(dialog, item_count(), scroll,
                    274:                     box_y, box_x + item_x + 1, menu_height);
                    275: 
                    276:        print_buttons(dialog, height, width, 0);
                    277:        wmove(menu, choice, item_x + 1);
                    278:        wrefresh(menu);
                    279: 
                    280:        while (key != KEY_ESC) {
                    281:                key = wgetch(menu);
                    282: 
                    283:                if (key < 256 && isalpha(key))
                    284:                        key = tolower(key);
                    285: 
                    286:                if (strchr("ynmh", key))
                    287:                        i = max_choice;
                    288:                else {
                    289:                        for (i = choice + 1; i < max_choice; i++) {
                    290:                                item_set(scroll + i);
                    291:                                j = first_alpha(item_str(), "YyNnMmHh");
                    292:                                if (key == tolower(item_str()[j]))
                    293:                                        break;
                    294:                        }
                    295:                        if (i == max_choice)
                    296:                                for (i = 0; i < max_choice; i++) {
                    297:                                        item_set(scroll + i);
                    298:                                        j = first_alpha(item_str(), "YyNnMmHh");
                    299:                                        if (key == tolower(item_str()[j]))
                    300:                                                break;
                    301:                                }
                    302:                }
                    303: 
                    304:                if (i < max_choice ||
                    305:                    key == KEY_UP || key == KEY_DOWN ||
                    306:                    key == '-' || key == '+' ||
                    307:                    key == KEY_PPAGE || key == KEY_NPAGE) {
                    308:                        /* Remove highligt of current item */
                    309:                        print_item(scroll + choice, choice, FALSE);
                    310: 
                    311:                        if (key == KEY_UP || key == '-') {
                    312:                                if (choice < 2 && scroll) {
                    313:                                        /* Scroll menu down */
                    314:                                        do_scroll(menu, &scroll, -1);
                    315: 
                    316:                                        print_item(scroll, 0, FALSE);
                    317:                                } else
                    318:                                        choice = MAX(choice - 1, 0);
                    319: 
                    320:                        } else if (key == KEY_DOWN || key == '+') {
                    321:                                print_item(scroll+choice, choice, FALSE);
                    322: 
                    323:                                if ((choice > max_choice - 3) &&
                    324:                                    (scroll + max_choice < item_count())) {
                    325:                                        /* Scroll menu up */
                    326:                                        do_scroll(menu, &scroll, 1);
                    327: 
                    328:                                        print_item(scroll+max_choice - 1,
                    329:                                                   max_choice - 1, FALSE);
                    330:                                } else
                    331:                                        choice = MIN(choice + 1, max_choice - 1);
                    332: 
                    333:                        } else if (key == KEY_PPAGE) {
                    334:                                scrollok(menu, TRUE);
                    335:                                for (i = 0; (i < max_choice); i++) {
                    336:                                        if (scroll > 0) {
                    337:                                                do_scroll(menu, &scroll, -1);
                    338:                                                print_item(scroll, 0, FALSE);
                    339:                                        } else {
                    340:                                                if (choice > 0)
                    341:                                                        choice--;
                    342:                                        }
                    343:                                }
                    344: 
                    345:                        } else if (key == KEY_NPAGE) {
                    346:                                for (i = 0; (i < max_choice); i++) {
                    347:                                        if (scroll + max_choice < item_count()) {
                    348:                                                do_scroll(menu, &scroll, 1);
                    349:                                                print_item(scroll+max_choice-1,
                    350:                                                           max_choice - 1, FALSE);
                    351:                                        } else {
                    352:                                                if (choice + 1 < max_choice)
                    353:                                                        choice++;
                    354:                                        }
                    355:                                }
                    356:                        } else
                    357:                                choice = i;
                    358: 
                    359:                        print_item(scroll + choice, choice, TRUE);
                    360: 
                    361:                        print_arrows(dialog, item_count(), scroll,
                    362:                                     box_y, box_x + item_x + 1, menu_height);
                    363: 
                    364:                        wnoutrefresh(dialog);
                    365:                        wrefresh(menu);
                    366: 
                    367:                        continue;       /* wait for another key press */
                    368:                }
                    369: 
                    370:                switch (key) {
                    371:                case KEY_LEFT:
                    372:                case TAB:
                    373:                case KEY_RIGHT:
                    374:                        button = ((key == KEY_LEFT ? --button : ++button) < 0)
                    375:                            ? 2 : (button > 2 ? 0 : button);
                    376: 
                    377:                        print_buttons(dialog, height, width, button);
                    378:                        wrefresh(menu);
                    379:                        break;
                    380:                case ' ':
                    381:                case 's':
                    382:                case 'y':
                    383:                case 'n':
                    384:                case 'm':
                    385:                case '/':
                    386:                case 'h':
                    387:                case '?':
                    388:                case 'z':
                    389:                case '\n':
                    390:                        /* save scroll info */
                    391:                        *s_scroll = scroll;
                    392:                        delwin(menu);
                    393:                        delwin(dialog);
                    394:                        item_set(scroll + choice);
                    395:                        item_set_selected(1);
                    396:                        switch (key) {
                    397:                        case 'h':
                    398:                        case '?':
                    399:                                return 2;
                    400:                        case 's':
                    401:                        case 'y':
                    402:                                return 3;
                    403:                        case 'n':
                    404:                                return 4;
                    405:                        case 'm':
                    406:                                return 5;
                    407:                        case ' ':
                    408:                                return 6;
                    409:                        case '/':
                    410:                                return 7;
                    411:                        case 'z':
                    412:                                return 8;
                    413:                        case '\n':
                    414:                                return button;
                    415:                        }
                    416:                        return 0;
                    417:                case 'e':
                    418:                case 'x':
                    419:                        key = KEY_ESC;
                    420:                        break;
                    421:                case KEY_ESC:
                    422:                        key = on_key_esc(menu);
                    423:                        break;
                    424:                case KEY_RESIZE:
                    425:                        on_key_resize();
                    426:                        delwin(menu);
                    427:                        delwin(dialog);
                    428:                        goto do_resize;
                    429:                }
                    430:        }
                    431:        delwin(menu);
                    432:        delwin(dialog);
                    433:        return key;             /* ESC pressed */
                    434: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.