diff options
author | jkh <jkh@FreeBSD.org> | 1995-12-23 01:10:20 +0000 |
---|---|---|
committer | jkh <jkh@FreeBSD.org> | 1995-12-23 01:10:20 +0000 |
commit | 09146e9c1750da0657ec2e041746780122965368 (patch) | |
tree | 1f083fecc7699ff2bdf6524e7e1c82763c466a1e /gnu | |
parent | e7d9236adaebb9ec46c615b1bcee2a0674c5e7e7 (diff) | |
download | FreeBSD-src-09146e9c1750da0657ec2e041746780122965368.zip FreeBSD-src-09146e9c1750da0657ec2e041746780122965368.tar.gz |
Add changes to:
o Support a new, fully backwards-compatible API for controling
individual items in dialog menus.
o Write a man page.
o Add some test code.
Diffstat (limited to 'gnu')
-rw-r--r-- | gnu/lib/libdialog/Makefile | 4 | ||||
-rw-r--r-- | gnu/lib/libdialog/checklist.c | 399 | ||||
-rw-r--r-- | gnu/lib/libdialog/dialog.3 | 381 | ||||
-rw-r--r-- | gnu/lib/libdialog/dialog.h | 41 | ||||
-rw-r--r-- | gnu/lib/libdialog/dialog.priv.h | 9 | ||||
-rw-r--r-- | gnu/lib/libdialog/kernel.c | 4 | ||||
-rw-r--r-- | gnu/lib/libdialog/menubox.c | 181 | ||||
-rw-r--r-- | gnu/lib/libdialog/radiolist.c | 367 |
8 files changed, 1028 insertions, 358 deletions
diff --git a/gnu/lib/libdialog/Makefile b/gnu/lib/libdialog/Makefile index ade82d2..a8190eb 100644 --- a/gnu/lib/libdialog/Makefile +++ b/gnu/lib/libdialog/Makefile @@ -1,7 +1,9 @@ # Makefile for libdialog -# $Id: Makefile,v 1.12 1995/05/04 09:45:29 ache Exp $ +# $Id: Makefile,v 1.13 1995/08/06 12:22:47 bde Exp $ LIB= dialog +MAN3= dialog.3 + SHLIB_MAJOR= 3 SHLIB_MINOR= 0 SRCS= kernel.c rc.c checklist.c inputbox.c menubox.c msgbox.c \ diff --git a/gnu/lib/libdialog/checklist.c b/gnu/lib/libdialog/checklist.c index 0890c00..66f0c8f 100644 --- a/gnu/lib/libdialog/checklist.c +++ b/gnu/lib/libdialog/checklist.c @@ -3,6 +3,8 @@ * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -23,8 +25,10 @@ #include "dialog.priv.h" -static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected); +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, + dialogMenuItem *me); +#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL) static int list_width, check_x, item_x; @@ -32,23 +36,46 @@ static int list_width, check_x, item_x; /* * Display a dialog box with a list of options that can be turned on or off */ -int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result) +int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, + int list_height, int item_no, void *it, unsigned char *result) { int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, - l, k, scroll = 0, max_choice, *status; + l, k, scroll = 0, max_choice, *status; int redraw_menu = FALSE; + char okButton, cancelButton; WINDOW *dialog, *list; + unsigned char **items; + dialogMenuItem *ditems; /* Allocate space for storing item on/off status */ - if ((status = malloc(sizeof(int)*item_no)) == NULL) { + if ((status = alloca(sizeof(int) * abs(item_no))) == NULL) { endwin(); fprintf(stderr, "\nCan't allocate memory in dialog_checklist().\n"); exit(-1); } - /* Initializes status */ - for (i = 0; i < item_no; i++) - status[i] = !strcasecmp(items[i*3 + 2], "on"); + /* Previous calling syntax, e.g. just a list of strings? */ + if (item_no >= 0) { + items = it; + ditems = NULL; + /* Initializes status */ + for (i = 0; i < item_no; i++) + status[i] = !strcasecmp(items[i*3 + 2], "on"); + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(item_no); + ditems = it; + items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *)); + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = ditems[i].checked ? (*ditems[i].checked)(&ditems[i]) : FALSE; + items[i*3] = ditems[i].prompt; + items[i*3 + 1] = ditems[i].title; + items[i*3 + 2] = status[i] ? "on" : "off"; + } + } max_choice = MIN(list_height, item_no); check_x = 0; @@ -63,23 +90,23 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in item_x = MAX(item_x, l); } if (height < 0) - height = strheight(prompt)+list_height+4+2; + height = strheight(prompt)+list_height+4+2; if (width < 0) { - i = strwidth(prompt); - j = ((title != NULL) ? strwidth(title) : 0); - width = MAX(i,j); - width = MAX(width,check_x+4)+4; + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j); + width = MAX(width,check_x+4)+4; } width = MAX(width,24); if (width > COLS) - width = COLS; + width = COLS; if (height > LINES) - height = LINES; + height = LINES; /* center dialog box on screen */ x = (COLS - width)/2; y = (LINES - height)/2; - + #ifdef HAVE_NCURSES if (use_shadow) draw_shadow(stdscr, y, x, height, width); @@ -87,11 +114,11 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in dialog = newwin(height, width, y, x); if (dialog == NULL) { endwin(); - fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); - exit(1); + fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width, y, x); + return -1; } keypad(dialog, TRUE); - + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); wattrset(dialog, border_attr); wmove(dialog, height-3, 0); @@ -113,31 +140,32 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in } wattrset(dialog, dialog_attr); wmove(dialog, 1, 2); - print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); + print_autowrap(dialog, prompt, height - 1, width - 2, width, 1, 2, TRUE, FALSE); - list_width = width-6; + list_width = width - 6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; - box_x = (width - list_width)/2 - 1; + box_x = (width - list_width) / 2 - 1; /* create new window for the list */ list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1); if (list == NULL) { endwin(); - fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height,list_width,y+box_y+1,x+box_x+1); - exit(1); + fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height, list_width, + y + box_y + 1, x + box_x + 1); + return -1; } keypad(list, TRUE); /* draw a box around the list items */ - draw_box(dialog, box_y, box_x, list_height+2, list_width+2, menubox_border_attr, menubox_attr); + draw_box(dialog, box_y, box_x, list_height + 2, list_width + 2, menubox_border_attr, menubox_attr); check_x = (list_width - check_x) / 2; item_x = check_x + item_x + 6; /* Print the list */ for (i = 0; i < max_choice; i++) - print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice); + print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice, DREF(ditems, i)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); @@ -145,49 +173,83 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in x = width/2-11; y = height-2; - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); + /* Is this a fancy new style argument string where we get to override + * the buttons, or an old style one where they're fixed? + */ + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } wrefresh(dialog); while (key != ESC) { key = wgetch(dialog); + + /* Shortcut to OK? */ + if (toupper(key) == okButton) { + if (ditems && result && ditems[OK_BUTTON].fire) { + if ((*ditems[OK_BUTTON].fire)(&ditems[OK_BUTTON]) == DITEM_FAILURE) + continue; + else + delwin(dialog); + } + else { + delwin(dialog); + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcat(result, items[i*3]); + strcat(result, "\n"); + } + } + } + return 0; + } + /* Shortcut to cancel? */ + else if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + if ((*ditems[CANCEL_BUTTON].fire)(&ditems[CANCEL_BUTTON]) == DITEM_FAILURE) + continue; + } + delwin(dialog); + return 1; + } + /* Check if key pressed matches first character of any item tag in list */ for (i = 0; i < max_choice; i++) if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*3][0])) break; - if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || - key == KEY_UP || key == KEY_DOWN || key == ' ' || - key == '+' || key == '-' ) { + if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || key == KEY_UP || + key == KEY_DOWN || key == ' ' || key == '+' || key == '-' ) { + if (key >= '1' && key <= MIN('9', '0'+max_choice)) i = key - '1'; + else if (key == KEY_UP || key == '-') { if (!choice) { if (scroll) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll--; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint list to scroll down */ - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - -#else - /* Scroll list down */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (list_height > 1) { /* De-highlight current first item before scrolling down */ - print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE); + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE, DREF(ditems, scroll)); scrollok(list, TRUE); wscrl(list, -1); scrollok(list, FALSE); } scroll--; - print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE); -#endif + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE, DREF(ditems, scroll)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); wrefresh(dialog); @@ -200,30 +262,17 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in else if (key == KEY_DOWN || key == '+') { if (choice == max_choice - 1) { if (scroll+choice < item_no-1) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll++; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint list to scroll up */ - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - -#else - /* Scroll list up */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (list_height > 1) { /* De-highlight current last item before scrolling up */ - print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, FALSE); + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, FALSE, DREF(ditems, scroll + max_choice - 1)); scrollok(list, TRUE); scroll(list); scrollok(list, FALSE); } scroll++; - print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, TRUE); -#endif + print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, TRUE, DREF(ditems, scroll + max_choice - 1)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); wrefresh(dialog); @@ -234,11 +283,49 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in i = choice + 1; } else if (key == ' ') { /* Toggle item status */ - status[scroll+choice] = !status[scroll+choice]; + char lbra = 0, rbra = 0, mark = 0; + + if (ditems) { + if (ditems[scroll+choice].fire) { + int st = (*ditems[scroll+choice].fire)(&ditems[scroll+choice]); + + if (st == DITEM_LEAVE_MENU) { + /* Allow a fire action to take us out of the menu */ + key = ESC; + break; + } + else if (st == DITEM_FAILURE) + continue; + else if (st == DITEM_REDRAW) { + for (i = 0; i < max_choice; i++) { + status[scroll + i] = ditems[scroll + i].checked ? + (*ditems[scroll + i].checked)(&ditems[scroll + i]) : FALSE; + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice, + DREF(ditems, scroll + i)); + } + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wrefresh(dialog); + } + } + status[scroll+choice] = ditems[scroll+choice].checked ? + (*ditems[scroll+choice].checked)(&ditems[scroll+choice]) : FALSE; + lbra = ditems[scroll+choice].lbra; + rbra = ditems[scroll+choice].rbra; + mark = ditems[scroll+choice].mark; + } + else + status[scroll+choice] = !status[scroll+choice]; getyx(dialog, cur_y, cur_x); /* Save cursor position */ wmove(list, choice, check_x); wattrset(list, check_selected_attr); - wprintw(list, "[%c]", status[scroll+choice] ? 'X' : ' '); + if (!lbra) + lbra = '['; + if (!rbra) + rbra = ']'; + if (!mark) + mark = 'X'; + wprintw(list, "%c%c%c", lbra, status[scroll+choice] ? mark : ' ', rbra); wnoutrefresh(list); wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ wrefresh(dialog); @@ -248,11 +335,13 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in if (i != choice) { /* De-highlight current item */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ - print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, FALSE); + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, FALSE, + DREF(ditems, scroll + choice)); /* Highlight new item */ choice = i; - print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE); + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE, + DREF(ditems, scroll + choice)); wnoutrefresh(list); wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ wrefresh(dialog); @@ -261,99 +350,118 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in } switch (key) { - case KEY_PPAGE: - if (scroll > height-4) { /* can we go up? */ - scroll -= (height-4); - } else { - scroll = 0; - } - redraw_menu = TRUE; - break; - case KEY_NPAGE: - if (scroll + list_height >= item_no-1 - list_height) { /* can we go down a full page? */ - scroll = item_no - list_height; - if (scroll < 0) scroll = 0; - } else { - scroll += list_height; - } - redraw_menu = TRUE; - break; - case KEY_HOME: + case KEY_PPAGE: /* can we go up? */ + if (scroll > height - 4) + scroll -= (height-4); + else scroll = 0; - choice = 0; - redraw_menu = TRUE; - break; - case KEY_END: + redraw_menu = TRUE; + break; + + case KEY_NPAGE: /* can we go down a full page? */ + if (scroll + list_height >= item_no-1 - list_height) { scroll = item_no - list_height; - if (scroll < 0) scroll = 0; - choice = max_choice - 1; - redraw_menu = TRUE; - break; - case 'O': - case 'o': - delwin(dialog); - *result = '\0'; - for (i = 0; i < item_no; i++) - if (status[i]) { - strcat(result, items[i*3]); - strcat(result, "\n"); - } - free(status); - return 0; - case 'C': - case 'c': - delwin(dialog); - free(status); - return 1; - case TAB: - case KEY_BTAB: - case KEY_LEFT: - case KEY_RIGHT: - if (!button) { - button = 1; /* Indicates "Cancel" button is selected */ - print_button(dialog, " OK ", y, x, FALSE); - print_button(dialog, "Cancel", y, x+14, TRUE); - } - else { - button = 0; /* Indicates "OK" button is selected */ - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); - } - wrefresh(dialog); - break; - case ' ': - case '\n': - case '\r': - delwin(dialog); - if (!button) { + if (scroll < 0) + scroll = 0; + } + else + scroll += list_height; + redraw_menu = TRUE; + break; + + case KEY_HOME: /* go to the top */ + scroll = 0; + choice = 0; + redraw_menu = TRUE; + break; + + case KEY_END: /* Go to the bottom */ + scroll = item_no - list_height; + if (scroll < 0) + scroll = 0; + choice = max_choice - 1; + redraw_menu = TRUE; + break; + + /* swap the selection of OK/Cancel buttons */ + case TAB: + case KEY_BTAB: + case KEY_LEFT: + case KEY_RIGHT: + button = !button; + if (ditems && result) { + if (button) { + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + } + else { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + } + } + else { + if (button) { + print_button(dialog, " OK ", y, x, !button); + print_button(dialog, "Cancel", y, x + 14, button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + } + wrefresh(dialog); + break; + + /* Select either the OK or Cancel button */ + case '\n': + case '\r': + if (!button && result) { + if (ditems && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) { + if ((*ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire)(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]) == + DITEM_FAILURE) + continue; + } + else { *result = '\0'; - for (i = 0; i < item_no; i++) + for (i = 0; i < item_no; i++) { if (status[i]) { strcat(result, items[i*3]); strcat(result, "\n"); } + } } - free(status); - return button; - case ESC: - break; + } + delwin(dialog); + return button; + break; + + /* Let me outta here! */ + case ESC: + break; + + /* Help! */ case KEY_F(1): case '?': - display_helpfile(); - break; + display_helpfile(); + break; } + if (redraw_menu) { - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - wnoutrefresh(list); - print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); - wrefresh(dialog); - redraw_menu = FALSE; + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice, + DREF(ditems, scroll + i)); + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wrefresh(dialog); + redraw_menu = FALSE; } } - + delwin(dialog); - free(status); return -1; /* ESC pressed */ } /* End of dialog_checklist() */ @@ -362,7 +470,8 @@ int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, in /* * Print list item */ -static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected) +static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int status, int choice, int selected, + dialogMenuItem *me) { int i; @@ -373,7 +482,9 @@ static void print_item(WINDOW *win, unsigned char *tag, unsigned char *item, int waddch(win, ' '); wmove(win, choice, check_x); wattrset(win, selected ? check_selected_attr : check_attr); - wprintw(win, "[%c]", status ? 'X' : ' '); + wprintw(win, "%c%c%c", me && me->lbra ? me->lbra : '[', + status ? me && me->mark ? me->mark : 'X' : ' ', + me && me->rbra ? me->rbra : ']'); wattrset(win, menubox_attr); waddch(win, ' '); wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); diff --git a/gnu/lib/libdialog/dialog.3 b/gnu/lib/libdialog/dialog.3 new file mode 100644 index 0000000..35f4ea1 --- /dev/null +++ b/gnu/lib/libdialog/dialog.3 @@ -0,0 +1,381 @@ +.\" +.\" Copyright (c) 1995, Jordan Hubbard +.\" +.\" All rights reserved. +.\" +.\" This manual page may be used, modified, copied, distributed, and +.\" sold, in both source and binary form provided that the above +.\" copyright and these terms are retained, verbatim, as the first +.\" lines of this file. Under no circumstances is the author +.\" responsible for the proper functioning of the software described herein +.\" nor does the author assume any responsibility for damages incurred with +.\" its use. +.\" +.\" $Id$ +.\" +.Dd December 18, 1995 +.Dt dialog 3 +.Os FreeBSD 2 +.Sh NAME +.Nm draw_shadow , +.Nm draw_box , +.Nm line_edit , +.Nm strheight , +.Nm strwidth , +.Nm dialog_create_rc, +.Nm dialog_yesno , +.Nm dialog_prgbox , +.Nm dialog_msgbox , +.Nm dialog_textbox , +.Nm dialog_menu , +.Nm dialog_checklist , +.Nm dialog_radiolist , +.Nm dialog_inputbox , +.Nm dialog_clear_norefresh , +.Nm dialog_clear , +.Nm dialog_update , +.Nm dialog_fselect , +.Nm dialog_notify , +.Nm dialog_mesgbox , +.Nm dialog_gauge , +.Nm init_dialog , +.Nm end_dialog , +.Nm use_helpfile , +.Nm use_helpline , +.Nm get_helpline , +.Nm restore_helpline . +.Nd Provide a simple ncurses-based "GUI" interface. +.Sh DESCRIPTION +The dialog library attempts to provide a fairly simplistic set of +fixed-presentation menus, input boxes, gauges, file requestors and +other general purpose "GUI" (a bit of a stretch, since it uses +ncurses) objects. Since the library also had its roots in a +shell-script writer's utility (see the \fBdialog(1)\fR command), the +early API was somewhat primitively based on strings being passed in or +out and parsed. This API was later extended to take either the +original arguments or arrays of \fBdialogMenuItem\fR structures, +giving the user much more control over the internal behavior of each +control. The \fBdialogMenuItem\fR structure internals are public: + +.nf +typedef struct _dmenu_item { + char *\fBprompt\fR; + char *\fBtitle\fR; + int (*\fBchecked\fR)(struct _dmenu_item *self); + int (*\fBfire\fR)(struct _dmenu_item *self); + void *\fBdata\fR; + char \fBlbra\fR, \fBmark\fR, \fBrbra\fR; +} \fBdialogMenuItem\fR; +.fi + +The \fBprompt\fR and \fBtitle\fR strings are pretty much self-explanatory, +and the \fBchecked\fR and \fBfire\fR function pointers provide optional +display and action hooks (the \fBdata\fR variable being available for +the convenience of those hooks) when more tightly coupled feedback between +a menu object and user code is required. A number of clever tricks for +simulating various kinds of item types can also be done by adjusting the +values of \fBlbra\fR (default: '['), \fB\mark\fR (default: '*' for radio +menus, 'X' for check menus) and \fBrbra\fR (default: ']') and declaring +a reasonable \fBchecked\fR hook, which should return TRUE for the `marked' state +and FALSE for `unmarked.' If an item has a \fBfire\fR hook associated +with it, it will also be called whenever the item is "toggled" in some way +and should return one of the following codes: +.nf + +#define DITEM_SUCCESS 0 /* Successful completion */ +#define DITEM_FAILURE -1 /* Failed to "fire" */ +#define DITEM_LEAVE_MENU -2 /* Treat selection as "Ok" */ +#define DITEM_REDRAW -3 /* Menu has changed, redraw it */ +.fi + +.Sh SYNOPSIS +.Fd #include <dialog.h> +.Ft "void" +.Fn draw_shadow "WINDOW *win" "int y" "int x" "int height" "int width" + +Draws a shadow in curses window \fBwin\fR using the dimensions +of \fBx, y, width\fR and \fBheight\fR. Returns 0 on success, -1 on failure. + +.Ft "void" +.Fn draw_box "WINDOW *win" "int y" "int x" "int height" "int width" "chtype box" "chtype border" + +Draws a bordered box using the dimensions of \fBx, y, width\fR and +\fBheight\fR. The attributes from \fBbox\fR and \fBborder\fR are +used, if specified, while painting the box and border regions of the +object. + +.Ft "int" +.Fn line_edit "WINDOW *dialog" "int box_y" "int box_x" "int flen" "int box_width" "chtype attrs" "int first" "u_char *result" + +Invoke a simple line editor with an edit box of dimensions \fBbox_x, +box_y\fR and \fBbox_width\fR. The field length is constrained by +\fBflen\fR, starting at the \fBfirst\fR character specified and +optionally displayed with character attributes \fBattrs\fR. The +string being edited is stored in \fBresult\fR. + +Returns 0 on success, -1 on failure. + +.Ft "int" +.Fn strheight "const char *p" + +Returns the height of string in \fBp\fR, counting newlines. + +.Ft "int" +.Fn strwidth "const char *p" + +Returns the width of string in \fBp\fR, counting newlines. + +.Ft "void" +.Fn dialog_create_rc "u_char *filename" + +Dump dialog library settings into \fBfilename\fR for later retreival +as defaults. Returns 0 on success, -1 on failure. + +.Ft "int" +.Fn dialog_yesno "u_char *title" "u_char *prompt" "int height" "int width" + +Display a text box using \fBtitle\fR and \fBprompt\fR strings of dimensions +\fBheight\fR and \fBwidth\fR. Also paint a pair of \fBYes\fR and \fBNo\fR +buttons at the bottom. If the \fBYes\fR button is chosen, return FALSE. +If \fBNo\fR, return TRUE. + +.Ft "int" +.Fn dialog_prgbox "u_char *title" "u_char *line" "int height" "int width" "int pause" "int use_shell" + +Display a text box of dimensions \fBheight\fR and \fBwidth\fR +containing the output of command \fBline\fR. If \fBuse_shell\fR is +TRUE, \fBline\fR is passed as an argument to \fBsh(1)\fR, otherwise it +is simply passed to \fBexec(3)\fR. If \fBpause\fR is TRUE, a final +confirmation requestor will be put up when execution terminates. + +Returns 0 on success, -1 on failure. + +.Ft "int" +.Fn dialog_textbox "u_char *title" "u_char *prompt" "int height" "int width" + +Display a text box containing the contents of string \fBprompt\fR of dimensions +\fBheight\fR and \fBwidth\fR. + +Returns 0 on success, -1 on failure. + +.Ft "int" +.Fn dialog_menu "u_char *title" "u_char *prompt" "int height" "int width" "int menu_height" "int item_no" "void *itptr" "u_char *result, int *ch, int *sc" + +Display a menu of dimensions \fBheight\fR and \fBwidth\fR with an +optional internal menu height of \fBmenu_height\fR. The \fBitem_no\fR +and \fBitptr\fR arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. To use the +older and traditional interface, \fBitem_no\fR should be a positive +integer representing the number of string pointer pairs to find in +\fBitptr\fR (which should be of type \fBchar **\fR), the strings are +expected to be in prompt and title order for each item and the +\fBresult\fR parameter is expected to point to an array where the +prompt string of the item selected will be copied. To use the newer +interface, \fBitem_no\fR should be a \fInegative\fR integer +representing the number of \fBdialogMenuItem\fR structures pointed to +by \fBitptr\fR (which should be of type \fBdialogMenuItem *\fR), one +structure per item. In the new interface, the \fBresult\fR variable +is used as a simple boolean (not a pointer) and should be NULL if +\fBitptr\fR only points to menu items and the default \fBOK\fR and +\fBCancel\fR buttons are desired. If \fBresult\fR is non-NULL, then +\fBitptr\fR is actually expected to point 2 locations \fBpast\fR the +start of the menu item list. \fBitptr\fR[-1] is then expected to +point to an item representing the \fBCancel\fR button, from which the +\fBprompt\fR and \fBfire\fR actions are used to override the default +behavior, and \fBitptr\fR[-2] to the same for the \fBOK\fR button. + +Using either API behavior, the \fBch\fR and \fBsc\fR values may be passed in to preserve current +item selection and scroll position values across calls. + +Returns 0 on success, 1 on Cancel and -1 on failure or ESC. + +.Ft "int" +.Fn dialog_checklist "u_char *title" "u_char *prompt" "int height" "int width" "int m_height" "int item_no" "void *itptr" "u_char *result" + +Display a menu of dimensions \fBheight\fR and \fBwidth\fR with an +optional internal menu height of \fBmenu_height\fR. The \fBitem_no\fR +and \fBitptr\fR arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. To use the +older and traditional interface, \fBitem_no\fR should be a positive +integer representing the number of string pointer tuples to find in +\fBitptr\fR (which should be of type \fBchar **\fR), the strings are +expected to be in prompt, title and state ("on" or "off") order for +each item and the \fBresult\fR parameter is expected to point to an +array where the prompt string of the item(s) selected will be +copied. To use the newer interface, \fBitem_no\fR should be a +\fInegative\fR integer representing the number of \fBdialogMenuItem\fR +structures pointed to by \fBitptr\fR (which should be of type +\fBdialogMenuItem *\fR), one structure per item. In the new interface, +the \fBresult\fR variable is used as a simple boolean (not a pointer) +and should be NULL if \fBitptr\fR only points to menu items and the +default \fBOK\fR and \fBCancel\fR buttons are desired. If +\fBresult\fR is non-NULL, then \fBitptr\fR is actually expected to +point 2 locations \fBpast\fR the start of the menu item list. +\fBitptr\fR[-1] is then expected to point to an item representing the +\fBCancel\fR button, from which the \fBprompt\fR and \fBfire\fR +actions are used to override the default behavior, and \fBitptr\fR[-2] +to the same for the \fBOK\fR button. + +In the standard API model, the menu supports the selection of multiple items, +each of which is marked with an `X' character to denote selection. When +the OK button is selected, the prompt values for all items selected are +concatenated into the \fBresult\fR string. + +In the new API model, it is not actually necessary to preserve +"checklist" semantics at all since practically everything about how +each item is displayed or marked as "selected" is fully configurable. +You could have a single checklist menu that actually contained a group +of items with "radio" behavior, "checklist" behavior and standard menu +item behavior. The only reason to call \fBdialog_checklist\fR over +\fBdialog_radiolist\fR in the new API model is to inherit the base +behavior, you're no longer constrained by it. + +Returns 0 on success, 1 on Cancel and -1 on failure or ESC. + +.Ft "int" +.Fn dialog_radiolist "u_char *title" "u_char *prompt" "int height" "int width" "int m_height" "int item_no" "void *it" "u_char *result" + +Display a menu of dimensions \fBheight\fR and \fBwidth\fR with an +optional internal menu height of \fBmenu_height\fR. The \fBitem_no\fR +and \fBitptr\fR arguments are of particular importance since they, +together, determine which of the 2 available APIs to use. To use the +older and traditional interface, \fBitem_no\fR should be a positive +integer representing the number of string pointer tuples to find in +\fBitptr\fR (which should be of type \fBchar **\fR), the strings are +expected to be in prompt, title and state ("on" or "off") order for +each item and the \fBresult\fR parameter is expected to point to an +array where the prompt string of the item(s) selected will be +copied. To use the newer interface, \fBitem_no\fR should be a +\fInegative\fR integer representing the number of \fBdialogMenuItem\fR +structures pointed to by \fBitptr\fR (which should be of type +\fBdialogMenuItem *\fR), one structure per item. In the new interface, +the \fBresult\fR variable is used as a simple boolean (not a pointer) +and should be NULL if \fBitptr\fR only points to menu items and the +default \fBOK\fR and \fBCancel\fR buttons are desired. If +\fBresult\fR is non-NULL, then \fBitptr\fR is actually expected to +point 2 locations \fBpast\fR the start of the menu item list. +\fBitptr\fR[-1] is then expected to point to an item representing the +\fBCancel\fR button, from which the \fBprompt\fR and \fBfire\fR +actions are used to override the default behavior, and \fBitptr\fR[-2] +does the same for the traditional \fBOK\fR button. + +In the standard API model, the menu supports the selection of only one +of multiple items, the currently active item marked with an `*' +character to denote selection. When the OK button is selected, the +prompt value for this item is copied into the \fBresult\fR string. + +In the new API model, it is not actually necessary to preserve +"radio button" semantics at all since practically everything about how +each item is displayed or marked as "selected" is fully configurable. +You could have a single radio menu that actually contained a group +of items with "checklist" behavior, "radio" behavior and standard menu +item behavior. The only reason to call \fBdialog_radiolist\fR over +\fBdialog_checklistlist\fR in the new API model is to inherit the base +behavior. + +Returns 0 on success, 1 on Cancel and -1 on failure or ESC. + +.Ft "int" +.Fn dialog_inputbox "u_char *title" "u_char *prompt" "int height" "int width" "u_char *result" + +Displays a single-line text input field in a box displaying \fBtitle\fR and \fBprompt\fR +of dimensions \fBheight\fR and \fBwidth\fR. The field entered is stored in \fBresult\fR. + +Returns 0 on success, -1 on failure or ESC. + +.Ft "char *" +.Fn dialog_fselect "char *dir" "char *fmask" + +Brings up a file selector dialog starting at \fBdir\fR and showing only those file names +matching \fBfmask\fR. + +Returns filename selected or NULL. + +.Ft "int" +.Fn dialog_dselect "char *dir" "char *fmask" + +Brings up a directory selector dialog starting at \fBdir\fR and showing only those directory names +matching \fBfmask\fR. + +Returns directory name selected or NULL. + +.Ft "void" +.Fn dialog_notify "char *msg" + +Bring up a generic "hey, you!" notifier dialog containing \fBmsg\fR. + +.Ft "int" +.Fn dialog_mesgbox "u_char *title" "u_char *prompt" "int height" "int width" + +Like a notifier dialog, but with more control over \fBtitle\fR, \fBprompt\fR, \fBwidth\fR and +\fBheight\fR. This object will also wait for user confirmation, unlike \fBdialog_notify\fR. + +Returns 0 on success, -1 on failure. + +.Ft "void" +.Fn dialog_gauge "u_char *title" "u_char *prompt" "int y" "int x" "int height" "int width" "int perc" + +Display a horizontal bar-graph style gauge. A value of \fB100\fR for \fBperc\fR constitutes +a full gauge, a value of \fB0\fR an empty one. + +.Ft "void" +.Fn use_helpfile "char *helpfile" + +For any menu supporting context sensitive help, invoke the text box +object on this file whenever the \fBF1\fR key is pressed. + + +.Ft "void" +.Fn use_helpline "char *helpline" + +Display this line of helpful text below any menu being displayed. + +.Ft "char *" +.Fn get_helpline "void" + +Get the current value of the helpful text line. + +.Ft "void" +.Fn dialog_clear_norefresh "void" + +Clear the screen back to the dialog background color, but don't refresh the contents +just yet. + +.Ft "void" +.Fn dialog_clear "void" + +Clear the screen back to the dialog background color immediately. + +.Ft "void" +.Fn dialog_update "void" + +Do any pending screen refreshes now. + +.Ft "void" +.Fn init_dialog "void" + +Initialize the dialog library (call this routine before any other dialog API calls). + +.Ft "void" +.Fn end_dialog "void" + +Shut down the dialog library (call this if you need to get back to sanity). + +.Sh SEE ALSO +.Xr dialog 1 , +.Xr ncurses 3 + +.Sh AUTHORS +The primary author would appear to be Savio Lam <lam836@cs.cuhk.hk> with contributions over +the years by Stuart Herbert <S.Herbert@sheffield.ac.uk>, Marc van Kempen <wmbfmk@urc.tue.nl>, +Andrey Chernov <ache@freebsd.org> and Jordan Hubbard <jkh@freebsd.org>. + +.Sh HISTORY +These functions appeared in +.Em FreeBSD-2.0 +as the \fBdialog(1)\fR command and were soon split into library +and command by Andrey Chernov. Marc van Kempen implemented most of the +extra controls and objects and Jordan Hubbard added the dialogMenuItem +renovations and this man page. +.Sh BUGS +Sure! diff --git a/gnu/lib/libdialog/dialog.h b/gnu/lib/libdialog/dialog.h index 6500ef8..afca1db 100644 --- a/gnu/lib/libdialog/dialog.h +++ b/gnu/lib/libdialog/dialog.h @@ -1,8 +1,13 @@ +#ifndef _DIALOG_H_INCLUDE +#define _DIALOG_H_INCLUDE + /* * dialog.h -- common declarations for all dialog modules * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -33,6 +38,26 @@ #endif +/* special return codes for `fire' actions */ +#define DITEM_SUCCESS 0 +#define DITEM_FAILURE -1 +#define DITEM_LEAVE_MENU -2 +#define DITEM_REDRAW -3 + +/* negative offsets for buttons in item lists, if specified */ +#define OK_BUTTON -2 +#define CANCEL_BUTTON -1 + +/* for use in describing more exotic behaviors */ +typedef struct _dmenu_item { + char *prompt; + char *title; + int (*checked)(struct _dmenu_item *self); + int (*fire)(struct _dmenu_item *self); + void *data; + char lbra, mark, rbra; +} dialogMenuItem; + #define VERSION "0.4" #define MAX_LEN 2048 @@ -87,7 +112,7 @@ extern bool use_shadow; void draw_shadow(WINDOW *win, int y, int x, int height, int width); #endif void draw_box(WINDOW *win, int y, int x, int height, int width, chtype box, chtype border); -int line_edit(WINDOW* dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result); +int line_edit(WINDOW *dialog, int box_y, int box_x, int flen, int box_width, chtype attrs, int first, unsigned char *result); int strheight(const char *p); int strwidth(const char *p); @@ -96,9 +121,12 @@ int dialog_yesno(unsigned char *title, unsigned char *prompt, int height, int wi int dialog_prgbox(unsigned char *title, const unsigned char *line, int height, int width, int pause, int use_shell); int dialog_msgbox(unsigned char *title, unsigned char *prompt, int height, int width, int pause); int dialog_textbox(unsigned char *title, unsigned char *file, int height, int width); -int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result, int *ch, int *sc); -int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result); -int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result); +int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, + int item_no, void *itptr, unsigned char *result, int *ch, int *sc); +int dialog_checklist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int item_no, void *itptr, unsigned char *result); +int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int item_no, void *itptr, unsigned char *result); int dialog_inputbox(unsigned char *title, unsigned char *prompt, int height, int width, unsigned char *result); void dialog_clear_norefresh(void); void dialog_clear(void); @@ -115,5 +143,6 @@ void use_helpfile(char *helpfile); void use_helpline(char *helpline); char *get_helpline(void); void restore_helpline(char *helpline); -void dialog_gauge(char *title, char *prompt, int y, int x, - int height, int width, int perc); +void dialog_gauge(char *title, char *prompt, int y, int x, int height, int width, int perc); + +#endif /* _DIALOG_H_INCLUDE */ diff --git a/gnu/lib/libdialog/dialog.priv.h b/gnu/lib/libdialog/dialog.priv.h index d84dc39..9d32f65 100644 --- a/gnu/lib/libdialog/dialog.priv.h +++ b/gnu/lib/libdialog/dialog.priv.h @@ -30,6 +30,7 @@ #include <locale.h> #endif + /* * Change these if you want */ @@ -163,13 +164,15 @@ extern int parse_rc(void); #ifdef HAVE_NCURSES void color_setup(void); #endif + void attr_clear(WINDOW *win, int height, int width, chtype attr); -void print_autowrap(WINDOW *win, unsigned char *prompt, int height, int width, int maxwidth, int y, int x, int center, int rawmode); +void print_autowrap(WINDOW *win, unsigned char *prompt, int height, int width, int maxwidth, + int y, int x, int center, int rawmode); void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected); FILE *raw_popen(const char *program, char * const *argv, const char *type); int raw_pclose(FILE *iop); void display_helpfile(void); void display_helpline(WINDOW *w, int y, int width); -void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no, - int box_x, int box_y, int tag_x, int cur_x, int cur_y); +void print_arrows(WINDOW *dialog, int scroll, int menu_height, int item_no, int box_x, + int box_y, int tag_x, int cur_x, int cur_y); diff --git a/gnu/lib/libdialog/kernel.c b/gnu/lib/libdialog/kernel.c index e9d23b2..1c38fa5 100644 --- a/gnu/lib/libdialog/kernel.c +++ b/gnu/lib/libdialog/kernel.c @@ -319,7 +319,7 @@ void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected) wmove(win, y, x); wattrset(win, selected ? button_active_attr : button_inactive_attr); - waddstr(win, "<"); + waddstr(win, selected ? "[" : " "); temp = strspn(label, " "); label += temp; wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr); @@ -330,7 +330,7 @@ void print_button(WINDOW *win, unsigned char *label, int y, int x, int selected) wattrset(win, selected ? button_label_active_attr : button_label_inactive_attr); waddstr(win, label+1); wattrset(win, selected ? button_active_attr : button_inactive_attr); - waddstr(win, ">"); + waddstr(win, selected ? "]" : " "); wmove(win, y, x+temp+1); } /* End of print_button() */ diff --git a/gnu/lib/libdialog/menubox.c b/gnu/lib/libdialog/menubox.c index b5aed1f..6961d07 100644 --- a/gnu/lib/libdialog/menubox.c +++ b/gnu/lib/libdialog/menubox.c @@ -3,6 +3,8 @@ * * AUTHOR: Savio Lam (lam836@cs.cuhk.hk) * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -30,17 +32,38 @@ static int menu_width, tag_x, item_x; /* * Display a menu for choosing among a number of options */ -int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, int item_no, unsigned char **items, unsigned char *result, int *ch, int *sc) +int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int width, int menu_height, + int item_no, void *it, unsigned char *result, int *ch, int *sc) { int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, l, k, scroll = 0, max_choice, redraw_menu = FALSE; + char okButton, cancelButton; WINDOW *dialog, *menu; + unsigned char **items; + dialogMenuItem *ditems; if (ch) /* restore menu item info */ choice = *ch; if (sc) scroll = *sc; + /* If item_no is a positive integer, use old item specification format */ + if (item_no >= 0) { + items = it; + ditems = NULL; + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(item_no); + ditems = it; + items = (unsigned char **)alloca((item_no * 2) * sizeof(unsigned char *)); + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + items[i*2] = ditems[i].prompt; + items[i*2 + 1] = ditems[i].title; + } + } max_choice = MIN(menu_height, item_no); tag_x = 0; @@ -55,19 +78,19 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid item_x = MAX(item_x, l); } if (height < 0) - height = strheight(prompt)+menu_height+4+2; + height = strheight(prompt)+menu_height+4+2; if (width < 0) { - i = strwidth(prompt); - j = ((title != NULL) ? strwidth(title) : 0); - width = MAX(i,j); - width = MAX(width,tag_x+4)+4; + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j); + width = MAX(width,tag_x+4)+4; } width = MAX(width,24); if (width > COLS) - width = COLS; + width = COLS; if (height > LINES) - height = LINES; + height = LINES; /* center dialog box on screen */ x = (COLS - width)/2; y = (LINES - height)/2; @@ -80,7 +103,7 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid if (dialog == NULL) { endwin(); fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); - exit(1); + return -1; } keypad(dialog, TRUE); @@ -117,7 +140,7 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid if (menu == NULL) { endwin(); fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", menu_height,menu_width,y+box_y+1,x+box_x+1); - exit(1); + return -1; } keypad(menu, TRUE); @@ -137,13 +160,51 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid x = width/2-11; y = height-2; - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); + + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } wrefresh(dialog); while (key != ESC) { key = wgetch(dialog); + + /* Shortcut to OK? */ + if (toupper(key) == okButton) { + if (ditems && result && ditems[OK_BUTTON].fire) { + if ((*ditems[OK_BUTTON].fire)(&ditems[OK_BUTTON]) == DITEM_FAILURE) + continue; + else + delwin(dialog); + } + else { + delwin(dialog); + strcpy(result, items[(scroll+choice)*2]); + } + return 0; + } + /* Shortcut to cancel? */ + else if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + if ((*ditems[CANCEL_BUTTON].fire)(&ditems[CANCEL_BUTTON]) == DITEM_FAILURE) + continue; + } + delwin(dialog); + return 1; + } + /* Check if key pressed matches first character of any item tag in menu */ for (i = 0; i < max_choice; i++) if (key < 0x100 && toupper(key) == toupper(items[(scroll+i)*2][0])) @@ -156,18 +217,6 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid else if (key == KEY_UP || key == '-') { if (!choice) { if (scroll) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll--; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint menu to scroll down */ - for (i = 0; i < max_choice; i++) - print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice); - -#else - /* Scroll menu down */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (menu_height > 1) { @@ -179,7 +228,6 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid } scroll--; print_item(menu, items[scroll*2], items[scroll*2 + 1], 0, TRUE); -#endif wnoutrefresh(menu); print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); wrefresh(dialog); @@ -192,18 +240,6 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid else if (key == KEY_DOWN || key == '+') if (choice == max_choice - 1) { if (scroll+choice < item_no-1) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll++; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint menu to scroll up */ - for (i = 0; i < max_choice; i++) - print_item(menu, items[(scroll+i)*2], items[(scroll+i)*2 + 1], i, i == choice); - -#else - /* Scroll menu up */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (menu_height > 1) { @@ -215,7 +251,6 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid } scroll++; print_item(menu, items[(scroll+max_choice-1)*2], items[(scroll+max_choice-1)*2 + 1], max_choice-1, TRUE); -#endif wnoutrefresh(menu); print_arrows(dialog, scroll, menu_height, item_no, box_x, box_y, tag_x, cur_x, cur_y); wrefresh(dialog); @@ -255,6 +290,7 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid } redraw_menu = TRUE; break; + case KEY_NPAGE: if (scroll + menu_height >= item_no-1 - menu_height) { /* can we go down a full page? */ scroll = item_no - menu_height; @@ -264,56 +300,75 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid } redraw_menu = TRUE; break; + case KEY_HOME: scroll = 0; choice = 0; redraw_menu = TRUE; break; + case KEY_END: scroll = item_no - menu_height; if (scroll < 0) scroll = 0; choice = max_choice - 1; redraw_menu = TRUE; break; - case 'O': - case 'o': - delwin(dialog); - strcpy(result, items[(scroll+choice)*2]); - return 0; - case 'C': - case 'c': - delwin(dialog); - return 1; + case KEY_BTAB: case TAB: case KEY_LEFT: case KEY_RIGHT: - if (!button) { - button = 1; /* Indicates "Cancel" button is selected */ - print_button(dialog, " OK ", y, x, FALSE); - print_button(dialog, "Cancel", y, x+14, TRUE); - } - else { - button = 0; /* Indicates "OK" button is selected */ - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); - } - wrefresh(dialog); - break; + button = !button; + if (ditems && result) { + if (button) { + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + } + else { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + } + } + else { + if (button) { + print_button(dialog, " OK ", y, x, !button); + print_button(dialog, "Cancel", y, x + 14, button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + } + wrefresh(dialog); + break; + case ' ': case '\r': case '\n': - delwin(dialog); - if (!button) + if (!button) { + if (ditems && ditems[scroll + choice].fire) { + if ((*ditems[scroll + choice].fire)(&ditems[scroll + choice]) == DITEM_FAILURE) + continue; + } + else if (result) strcpy(result, items[(scroll+choice)*2]); - return button; + } + delwin(dialog); + return button; + case ESC: break; + case KEY_F(1): case '?': display_helpfile(); break; } + if (redraw_menu) { for (i = 0; i < max_choice; i++) { print_item(menu, items[(scroll+i)*2], @@ -325,7 +380,7 @@ int dialog_menu(unsigned char *title, unsigned char *prompt, int height, int wid redraw_menu = FALSE; } } - + delwin(dialog); return -1; /* ESC pressed */ } diff --git a/gnu/lib/libdialog/radiolist.c b/gnu/lib/libdialog/radiolist.c index fefcb53..a23a82e 100644 --- a/gnu/lib/libdialog/radiolist.c +++ b/gnu/lib/libdialog/radiolist.c @@ -4,6 +4,8 @@ * AUTHOR: Stuart Herbert - S.Herbert@sheffield.ac.uk * (from checklist.c by Savio Lam (lam836@cs.cuhk.hk)) * + * Substantial rennovation: 12/18/95, Jordan K. Hubbard + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 @@ -24,8 +26,10 @@ #include "dialog.priv.h" -static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected); +static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, + dialogMenuItem *me); +#define DREF(di, item) ((di) ? &((di)[(item)]) : NULL) static int list_width, check_x, item_x; @@ -33,32 +37,61 @@ static int list_width, check_x, item_x; /* * Display a dialog box with a list of options that can be turned on or off */ -int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, int item_no, unsigned char **items, unsigned char *result) +int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, int width, int list_height, + int item_no, void *it, unsigned char *result) { int i, j, x, y, cur_x, cur_y, box_x, box_y, key = 0, button = 0, choice = 0, l, k, scroll = 0, max_choice, *status, was_on = 0; int redraw_menu = FALSE; + char okButton, cancelButton; WINDOW *dialog, *list; + unsigned char **items; + dialogMenuItem *ditems; /* Allocate space for storing item on/off status */ - if ((status = malloc(sizeof(int)*item_no)) == NULL) { + if ((status = alloca(sizeof(int)*item_no)) == NULL) { endwin(); fprintf(stderr, "\nCan't allocate memory in dialog_radiolist().\n"); exit(-1); } - /* Initializes status */ - for (i = 0; i < item_no; i++) { - status[i] = !strcasecmp(items[i*3 + 2], "on"); - if (status[i]) - if (was_on) { - endwin(); - fprintf(stderr, "\nOnly one status can be ON in dialog_radiolist().\n"); - exit(-1); - } else - was_on = 1; + + /* Previous calling syntax, e.g. just a list of strings? */ + if (item_no >= 0) { + items = it; + ditems = NULL; + + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = !strcasecmp(items[i*3 + 2], "on"); + if (status[i]) { + if (was_on) + status[i] = FALSE; + else + was_on = 1; + } + } + } + /* It's the new specification format - fake the rest of the code out */ + else { + item_no = abs(item_no); + ditems = it; + items = (unsigned char **)alloca((item_no * 3) * sizeof(unsigned char *)); + /* Initializes status */ + for (i = 0; i < item_no; i++) { + status[i] = ditems[i].checked ? (*ditems[i].checked)(&ditems[i]) : FALSE; + if (status[i]) { + if (was_on) + status[i] = FALSE; + else + was_on = 1; + } + items[i*3] = ditems[i].prompt; + items[i*3 + 1] = ditems[i].title; + items[i*3 + 2] = status[i] ? "on" : "off"; + } } max_choice = MIN(list_height, item_no); - + check_x = 0; item_x = 0; /* Find length of longest item in order to center radiolist */ @@ -71,23 +104,23 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in item_x = MAX(item_x, l); } if (height < 0) - height = strheight(prompt)+list_height+4+2; + height = strheight(prompt)+list_height+4+2; if (width < 0) { - i = strwidth(prompt); - j = ((title != NULL) ? strwidth(title) : 0); - width = MAX(i,j); - width = MAX(width,check_x+4)+4; + i = strwidth(prompt); + j = ((title != NULL) ? strwidth(title) : 0); + width = MAX(i,j); + width = MAX(width,check_x+4)+4; } width = MAX(width,24); - + if (width > COLS) - width = COLS; + width = COLS; if (height > LINES) - height = LINES; + height = LINES; /* center dialog box on screen */ x = (COLS - width)/2; y = (LINES - height)/2; - + #ifdef HAVE_NCURSES if (use_shadow) draw_shadow(stdscr, y, x, height, width); @@ -96,10 +129,10 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in if (dialog == NULL) { endwin(); fprintf(stderr, "\nnewwin(%d,%d,%d,%d) failed, maybe wrong dims\n", height,width,y,x); - exit(1); + return -1; } keypad(dialog, TRUE); - + draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); wattrset(dialog, border_attr); wmove(dialog, height-3, 0); @@ -122,21 +155,21 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in wattrset(dialog, dialog_attr); wmove(dialog, 1, 2); print_autowrap(dialog, prompt, height-1, width-2, width, 1, 2, TRUE, FALSE); - + list_width = width-6; getyx(dialog, cur_y, cur_x); box_y = cur_y + 1; box_x = (width - list_width)/2 - 1; - + /* create new window for the list */ list = subwin(dialog, list_height, list_width, y + box_y + 1, x + box_x + 1); if (list == NULL) { endwin(); fprintf(stderr, "\nsubwin(dialog,%d,%d,%d,%d) failed, maybe wrong dims\n", list_height,list_width,y+box_y+1,x+box_x+1); - exit(1); + return -1; } keypad(list, TRUE); - + /* draw a box around the list items */ draw_box(dialog, box_y, box_x, list_height+2, list_width+2, menubox_border_attr, menubox_attr); @@ -145,7 +178,7 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in /* Print the list */ for (i = 0; i < max_choice; i++) - print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice); + print_item(list, items[i*3], items[i*3 + 1], status[i], i, i == choice, DREF(ditems, i)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); @@ -153,49 +186,78 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in x = width/2-11; y = height-2; - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); + if (ditems && result) { + cancelButton = toupper(ditems[CANCEL_BUTTON].prompt[0]); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : FALSE); + okButton = toupper(ditems[OK_BUTTON].prompt[0]); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : TRUE); + } + else { + cancelButton = 'C'; + print_button(dialog, "Cancel", y, x + 14, FALSE); + okButton = 'O'; + print_button(dialog, " OK ", y, x, TRUE); + } wrefresh(dialog); - + while (key != ESC) { key = wgetch(dialog); + + /* See if its the short-cut to "OK" */ + if (toupper(key) == okButton) { + if (ditems && result && ditems[OK_BUTTON].fire) { + if ((*ditems[OK_BUTTON].fire)(&ditems[OK_BUTTON]) == DITEM_FAILURE) + continue; + else + delwin(dialog); + } + else { + delwin(dialog); + *result = '\0'; + for (i = 0; i < item_no; i++) { + if (status[i]) { + strcat(result, items[i*3]); + break; + } + } + } + return 0; + } + /* Shortcut to cancel */ + else if (toupper(key) == cancelButton) { + if (ditems && result && ditems[CANCEL_BUTTON].fire) { + if ((*ditems[CANCEL_BUTTON].fire)(&ditems[CANCEL_BUTTON]) == DITEM_FAILURE) + continue; + } + delwin(dialog); + return 1; + } + /* Check if key pressed matches first character of any item tag in list */ for (i = 0; i < max_choice; i++) if (toupper(key) == toupper(items[(scroll+i)*3][0])) break; - if (i < max_choice || (key >= '1' && key <= MIN('9', '0'+max_choice)) || - key == KEY_UP || key == KEY_DOWN || key == ' ' || - key == '+' || key == '-' ) { - if (key >= '1' && key <= MIN('9', '0'+max_choice)) + if (i < max_choice || (key >= '1' && key <= MIN('9', '0' + max_choice)) || + key == KEY_UP || key == KEY_DOWN || key == ' ' || key == '+' || key == '-' ) { + if (key >= '1' && key <= MIN('9', '0' + max_choice)) i = key - '1'; else if (key == KEY_UP || key == '-') { if (!choice) { if (scroll) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll--; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint list to scroll down */ - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - -#else - /* Scroll list down */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (list_height > 1) { /* De-highlight current first item before scrolling down */ - print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE); + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, FALSE, DREF(ditems, scroll)); scrollok(list, TRUE); wscrl(list, -1); scrollok(list, FALSE); } scroll--; - print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE); -#endif + print_item(list, items[scroll*3], items[scroll*3 + 1], status[scroll], 0, TRUE, DREF(ditems, scroll)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); wrefresh(dialog); @@ -208,30 +270,19 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in else if (key == KEY_DOWN || key == '+') { if (choice == max_choice - 1) { if (scroll+choice < item_no-1) { -#ifdef BROKEN_WSCRL - /* wscrl() in ncurses 1.8.1 seems to be broken, causing a segmentation - violation when scrolling windows of height = 4, so scrolling is not - used for now */ - scroll++; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - /* Reprint list to scroll up */ - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - -#else - /* Scroll list up */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ if (list_height > 1) { /* De-highlight current last item before scrolling up */ - print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, FALSE); + print_item(list, items[(scroll + max_choice - 1) * 3], items[(scroll + max_choice - 1) * 3 + 1], + status[scroll + max_choice - 1], max_choice - 1, FALSE, DREF(ditems, scroll + max_choice - 1)); scrollok(list, TRUE); scroll(list); scrollok(list, FALSE); } scroll++; - print_item(list, items[(scroll+max_choice-1)*3], items[(scroll+max_choice-1)*3 + 1], status[scroll+max_choice-1], max_choice-1, TRUE); -#endif + print_item(list, items[(scroll + max_choice - 1) * 3], items[(scroll + max_choice - 1) * 3 + 1], + status[scroll + max_choice - 1], max_choice - 1, TRUE, DREF(ditems, scroll + max_choice - 1)); wnoutrefresh(list); print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); wrefresh(dialog); @@ -242,28 +293,47 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in i = choice + 1; } else if (key == ' ') { /* Toggle item status */ - if (!status[scroll+choice]) - { - for (i=0; i<item_no; i++) - status[i]=0; - status[scroll+choice]=1; - getyx(dialog, cur_y, cur_x); /* Save cursor position */ - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - wnoutrefresh(list); - wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ - wrefresh(dialog); + if (status[scroll + choice]) + continue; + else if (ditems) { + if (ditems[scroll + choice].fire) { + int st = (*ditems[scroll + choice].fire)(&ditems[scroll + choice]); + + if (st == DITEM_LEAVE_MENU) { + /* Allow a fire action to take us out of the menu */ + key = ESC; + break; + } + else if (st == DITEM_FAILURE) + continue; + } + for (i = 0; i < item_no; i++) + status[i] = ditems[i].checked ? (*ditems[i].checked)(&ditems[i]) : FALSE; + } + else { + for (i = 0; i < item_no; i++) + status[i] = 0; + status[scroll + choice] = TRUE; } + getyx(dialog, cur_y, cur_x); /* Save cursor position */ + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice, + DREF(ditems, scroll + i)); + wnoutrefresh(list); + wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ + wrefresh(dialog); continue; /* wait for another key press */ } if (i != choice) { /* De-highlight current item */ getyx(dialog, cur_y, cur_x); /* Save cursor position */ - print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 +1], status[scroll+choice], choice, FALSE); + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 +1], status[scroll+choice], choice, FALSE, + DREF(ditems, scroll + choice)); /* Highlight new item */ choice = i; - print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE); + print_item(list, items[(scroll+choice)*3], items[(scroll+choice)*3 + 1], status[scroll+choice], choice, TRUE, + DREF(ditems, scroll + choice)); wnoutrefresh(list); wmove(dialog, cur_y, cur_x); /* Restore cursor to previous position */ wrefresh(dialog); @@ -273,93 +343,109 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in switch (key) { case KEY_PPAGE: - if (scroll > height-4) { /* can we go up? */ + if (scroll > height-4) /* can we go up? */ scroll -= (height-4); - } else { + else scroll = 0; - } redraw_menu = TRUE; break; + case KEY_NPAGE: if (scroll + list_height >= item_no-1 - list_height) { /* can we go down a full page? */ scroll = item_no - list_height; - if (scroll < 0) scroll = 0; - } else { - scroll += list_height; + if (scroll < 0) + scroll = 0; } + else + scroll += list_height; redraw_menu = TRUE; break; + case KEY_HOME: scroll = 0; choice = 0; redraw_menu = TRUE; break; + case KEY_END: scroll = item_no - list_height; - if (scroll < 0) scroll = 0; + if (scroll < 0) + scroll = 0; choice = max_choice - 1; redraw_menu = TRUE; break; - case 'O': - case 'o': - delwin(dialog); - *result = '\0'; - for (i = 0; i < item_no; i++) - if (status[i]) { - strcpy(result, items[i*3]); - break; - } - free(status); - return 0; - case 'C': - case 'c': - delwin(dialog); - free(status); - return 1; - case KEY_BTAB: - case TAB: - case KEY_LEFT: - case KEY_RIGHT: - if (!button) { - button = 1; /* Indicates "Cancel" button is selected */ - print_button(dialog, " OK ", y, x, FALSE); - print_button(dialog, "Cancel", y, x+14, TRUE); - } - else { - button = 0; /* Indicates "OK" button is selected */ - print_button(dialog, "Cancel", y, x+14, FALSE); - print_button(dialog, " OK ", y, x, TRUE); - } - wrefresh(dialog); - break; - case ' ': - case '\r': - case '\n': - delwin(dialog); - if (!button) { + + case KEY_BTAB: + case TAB: + case KEY_LEFT: + case KEY_RIGHT: + button = !button; + if (ditems && result) { + if (button) { + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + } + else { + print_button(dialog, ditems[CANCEL_BUTTON].prompt, y, x + strlen(ditems[OK_BUTTON].prompt) + 5, + ditems[CANCEL_BUTTON].checked ? (*ditems[CANCEL_BUTTON].checked)(&ditems[CANCEL_BUTTON]) : button); + print_button(dialog, ditems[OK_BUTTON].prompt, y, x, + ditems[OK_BUTTON].checked ? (*ditems[OK_BUTTON].checked)(&ditems[OK_BUTTON]) : !button); + } + } + else { + if (button) { + print_button(dialog, " OK ", y, x, !button); + print_button(dialog, "Cancel", y, x + 14, button); + } + else { + print_button(dialog, "Cancel", y, x + 14, button); + print_button(dialog, " OK ", y, x, !button); + } + } + wrefresh(dialog); + break; + + case ' ': + case '\r': + case '\n': + if (!button && result) { + if (ditems && ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire) { + if ((*ditems[button ? CANCEL_BUTTON : OK_BUTTON].fire)(&ditems[button ? CANCEL_BUTTON : OK_BUTTON]) == DITEM_FAILURE) + continue; + } + else { *result = '\0'; - for (i = 0; i < item_no; i++) + for (i = 0; i < item_no; i++) { if (status[i]) { strcpy(result, items[i*3]); break; } + } } - free(status); - return button; - case ESC: - break; + } + delwin(dialog); + return button; + break; + + case ESC: + break; + case KEY_F(1): case '?': - display_helpfile(); - break; + display_helpfile(); + break; } + if (redraw_menu) { - for (i = 0; i < max_choice; i++) - print_item(list, items[(scroll+i)*3], items[(scroll+i)*3 + 1], status[scroll+i], i, i == choice); - wnoutrefresh(list); - print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); - wrefresh(dialog); - redraw_menu = FALSE; + for (i = 0; i < max_choice; i++) + print_item(list, items[(scroll + i) * 3], items[(scroll + i) * 3 + 1], status[scroll + i], i, i == choice, + DREF(ditems, scroll + i)); + wnoutrefresh(list); + print_arrows(dialog, scroll, list_height, item_no, box_x, box_y, check_x + 4, cur_x, cur_y); + wrefresh(dialog); + redraw_menu = FALSE; } } @@ -373,7 +459,8 @@ int dialog_radiolist(unsigned char *title, unsigned char *prompt, int height, in /* * Print list item */ -static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected) +static void print_item(WINDOW *win, char *tag, char *item, int status, int choice, int selected, + dialogMenuItem *me) { int i; @@ -384,7 +471,9 @@ static void print_item(WINDOW *win, char *tag, char *item, int status, int choic waddch(win, ' '); wmove(win, choice, check_x); wattrset(win, selected ? check_selected_attr : check_attr); - wprintw(win, "(%c)", status ? '*' : ' '); + wprintw(win, "%c%c%c", me && me->lbra ? me->lbra : '(', + status ? me && me->mark ? me->mark : '*' : ' ', + me && me->rbra ? me->rbra : ')'); wattrset(win, menubox_attr); waddch(win, ' '); wattrset(win, selected ? tag_key_selected_attr : tag_key_attr); |