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.
This commit is contained in:
Jordan K. Hubbard 1995-12-23 01:10:20 +00:00
parent 49f8ea7107
commit fa8dc2c075
8 changed files with 1028 additions and 358 deletions

View File

@ -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 \

View File

@ -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);

381
gnu/lib/libdialog/dialog.3 Normal file
View File

@ -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!

View File

@ -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 */

View File

@ -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);

View File

@ -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() */

View File

@ -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 */
}

View File

@ -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);