Added new menu style O_RADIO which implements a radio button style

menu selection.  Thanks go to rtr(at)wasabisystems.com for doing
most of the work on this.
This commit is contained in:
blymn 2002-07-29 13:03:51 +00:00
parent eeeb970336
commit 09440e9036
9 changed files with 183 additions and 21 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: driver.c,v 1.7 2001/06/13 10:45:59 wiz Exp $ */
/* $NetBSD: driver.c,v 1.8 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -42,8 +42,10 @@
int
menu_driver(MENU *menu, int c)
{
int drv_top_row, drv_scroll, it, status = E_OK;
int drv_top_row, drv_scroll, i, it, status = E_OK;
ITEM *drv_new_item;
i = 0;
if (menu == NULL)
return E_BAD_ARGUMENT;
@ -167,8 +169,32 @@ menu_driver(MENU *menu, int c)
}
break;
case REQ_TOGGLE_ITEM:
if ((menu->opts & O_ONEVALUE) == O_ONEVALUE) {
return E_REQUEST_DENIED;
if ((menu->opts & (O_RADIO | O_ONEVALUE)) != 0) {
if ((menu->opts & O_RADIO) == O_RADIO) {
if ((drv_new_item->opts & O_SELECTABLE)
!= O_SELECTABLE)
return E_NOT_SELECTABLE;
/* don't deselect selected item */
if (drv_new_item->selected == 1)
return E_REQUEST_DENIED;
/* deselect all items */
for (i = 0; i < menu->item_count; i++) {
if ((menu->items[i]->selected) &&
(drv_new_item->index != i)) {
menu->items[i]->selected ^= 1;
_menui_draw_item(menu,
menu->items[i]->index);
}
}
/* turn on selected item */
drv_new_item->selected ^= 1;
_menui_draw_item(menu, drv_new_item->index);
} else {
return E_REQUEST_DENIED;
}
} else {
if ((drv_new_item->opts
& O_SELECTABLE) == O_SELECTABLE) {
@ -176,7 +202,7 @@ menu_driver(MENU *menu, int c)
drv_new_item->selected ^= 1;
/* update item in menu */
_menui_draw_item(menu,
drv_new_item->index);
drv_new_item->index);
} else {
return E_NOT_SELECTABLE;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: internals.c,v 1.9 2002/02/04 13:02:05 blymn Exp $ */
/* $NetBSD: internals.c,v 1.10 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -388,7 +388,7 @@ _menui_draw_item(MENU *menu, int item)
menu->items[item]->row - menu->top_row,
menu->items[item]->col * menu->col_width);
if ((menu->cur_item == item) || (menu->items[item]->selected == 1))
if (menu->cur_item == item)
wattrset(menu->scrwin, menu->fore);
if ((menu->items[item]->opts & O_SELECTABLE) != O_SELECTABLE)
wattron(menu->scrwin, menu->grey);

View File

@ -1,4 +1,4 @@
/* $NetBSD: item.c,v 1.7 2001/06/13 10:45:59 wiz Exp $ */
/* $NetBSD: item.c,v 1.8 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -142,6 +142,39 @@ item_term(MENU *menu)
return menu->item_term;
}
/*
* Returns the number of items that are selected.
* The index numbers of the items are placed in the dynamically allocated
* int array *sel.
*/
int
item_selected(MENU *menu, int **sel)
{
int i, j;
if (menu == NULL)
return E_BAD_ARGUMENT;
/* count selected */
for (i = 0, j = 0; i < menu->item_count; i++)
if (menu->items[i]->selected)
j++;
if (j == 0) {
*sel = NULL;
return 0;
}
if ( (*sel = malloc(sizeof(int) * j)) == NULL)
return E_SYSTEM_ERROR;
for (i = 0, j = 0; i < menu->item_count; i++)
if (menu->items[i]->selected)
(*sel)[j++] = i;
return j;
}
/*
* Set the item options. We keep a global copy of the current item options
* as subsequent new_item calls will use the updated options as their

View File

@ -1,4 +1,4 @@
/* $NetBSD: menu.c,v 1.11 2002/02/04 13:02:05 blymn Exp $ */
/* $NetBSD: menu.c,v 1.12 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -306,11 +306,34 @@ menu_opts(MENU *menu)
int
set_menu_opts(MENU *param_menu, OPTIONS opts)
{
int i, seen;
MENU *menu = (param_menu != NULL) ? param_menu : &_menui_default_menu;
OPTIONS old_opts = menu->opts;
menu->opts = opts;
/*
* If the radio option is selected then make sure only one
* item is actually selected in the items.
*/
if (((opts & O_RADIO) == O_RADIO) && (menu->items != NULL) &&
(menu->items[0] != NULL)) {
seen = 0;
for (i = 0; i < menu->item_count; i++) {
if (menu->items[i]->selected == 1) {
if (seen == 0) {
seen = 1;
} else {
menu->items[i]->selected = 0;
}
}
}
/* if none selected, select the first item */
if (seen == 0)
menu->items[0]->selected = 1;
}
if ((menu->opts & O_ROWMAJOR) != (old_opts & O_ROWMAJOR))
/* changed menu layout - need to recalc neighbours */
_menui_stitch_items(menu);
@ -324,11 +347,33 @@ set_menu_opts(MENU *param_menu, OPTIONS opts)
int
menu_opts_on(MENU *param_menu, OPTIONS opts)
{
int i, seen;
MENU *menu = (param_menu != NULL) ? param_menu : &_menui_default_menu;
OPTIONS old_opts = menu->opts;
menu->opts |= opts;
/*
* If the radio option is selected then make sure only one
* item is actually selected in the items.
*/
if (((opts & O_RADIO) == O_RADIO) && (menu->items != NULL) &&
(menu->items[0] != NULL)) {
seen = 0;
for (i = 0; i < menu->item_count; i++) {
if (menu->items[i]->selected == 1) {
if (seen == 0) {
seen = 1;
} else {
menu->items[i]->selected = 0;
}
}
}
/* if none selected then select the top item */
if (seen == 0)
menu->items[0]->selected = 1;
}
if ((menu->items != NULL) &&
(menu->opts & O_ROWMAJOR) != (old_opts & O_ROWMAJOR))
/* changed menu layout - need to recalc neighbours */
@ -485,7 +530,7 @@ int
set_menu_items(MENU *param_menu, ITEM **items)
{
MENU *menu = (param_menu != NULL) ? param_menu : &_menui_default_menu;
int i, new_count = 0;
int i, new_count = 0, sel_count = 0;
/* don't change if menu is posted */
if (menu->posted == 1)
@ -496,10 +541,19 @@ set_menu_items(MENU *param_menu, ITEM **items)
if ((items[new_count]->parent != NULL) &&
(items[new_count]->parent != menu))
return E_CONNECTED;
if (items[new_count]->selected == 1)
sel_count++;
new_count++;
}
/*
* don't allow multiple selected items if menu is radio
* button style.
*/
if (((menu->opts & O_RADIO) == O_RADIO) &&
(sel_count > 1))
return E_BAD_ARGUMENT;
/* if there were items connected then disconnect them. */
if (menu->items != NULL) {
for (i = 0; i < menu->item_count; i++) {
@ -525,6 +579,14 @@ set_menu_items(MENU *param_menu, ITEM **items)
menu->match_len = 0;
}
/*
* make sure at least one item is selected on a radio
* button style menu.
*/
if (((menu->opts & O_RADIO) == O_RADIO) && (sel_count == 0))
menu->items[0]->selected = 1;
_menui_stitch_items(menu); /* recalculate the item neighbours */
return E_OK;

View File

@ -1,4 +1,4 @@
/* $NetBSD: menu.h,v 1.11 2002/02/04 13:02:06 blymn Exp $ */
/* $NetBSD: menu.h,v 1.12 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -67,6 +67,7 @@ typedef unsigned int OPTIONS;
#define O_SHOWMATCH (0x10)
#define O_NONCYCLIC (0x20)
#define O_SELECTABLE (0x40)
#define O_RADIO (0x80)
typedef struct __menu_str {
char *string;
@ -190,6 +191,7 @@ char *item_name(ITEM *);
OPTIONS item_opts(ITEM *);
int item_opts_off(ITEM *, OPTIONS);
int item_opts_on(ITEM *, OPTIONS);
int item_selected(MENU *, int **); /* return the item index of selected */
Menu_Hook item_term(MENU *);
char *item_userptr(ITEM *);
int item_value(ITEM *);

View File

@ -1,4 +1,4 @@
.\" $NetBSD: menu_item_value.3,v 1.6 2002/02/20 11:47:56 wiz Exp $
.\" $NetBSD: menu_item_value.3,v 1.7 2002/07/29 13:03:51 blymn Exp $
.\"
.\" Copyright (c) 1999
.\" Brett Lymn - blymn@baea.com.au, brett_lymn@yahoo.com.au
@ -34,7 +34,8 @@
.Os
.Sh NAME
.Nm item_value ,
.Nm set_item_value
.Nm set_item_value ,
.Nm item_selected
.Nd get or set value for an item
.Sh LIBRARY
.Lb libmenu
@ -44,6 +45,8 @@
.Fn item_value "ITEM *item"
.Ft int
.Fn set_item_value "ITEM *item" "int flag"
.Ft int
.Fn item_selected "MENU *menu" "int **array"
.Sh DESCRIPTION
The
.Fn item_value
@ -52,6 +55,23 @@ then this value will be TRUE. The value can also be set by calling
.Fn set_item_value
to set the value to a defined state. Setting the value to a value
other than TRUE or FALSE will have undefined results.
The
.Fn item_selected
fucntion returns the number of items that are selected in the menu, that
is the number of items whose value is TRUE. The indexes of the selected
items will be returned in
.Fa array
which will be dynamically allocated to hold the number of indexes. It
is the reponsibility of the caller to release this storage by calling
.Xr free 3
when the storage is no longer required. If there are no elements selected
in the items array then
.Fn item_selected
will return 0 and
.Fa array
will be NULL. If an error occurs
.Fn item_selected
will return one of the below return values which are less than 0.
.Sh RETURN VALUES
The functions return one of the following error values:
.Pp
@ -62,6 +82,8 @@ The function was successful.
The item is not connected to a menu.
.It Er E_REQUEST_DENIED
The menu driver could not process the request.
.It Er E_SYSTEM_ERROR
A system error occurred whilst processing the request.
.El
.Sh SEE ALSO
.Xr curses 3 ,
@ -73,3 +95,10 @@ automatically includes both
.Pa \*[Lt]curses.h\*[Gt]
and
.Pa \*[Lt]eti.h\*[Gt] .
.Pp
The function
.Fn item_selected
is a
.Nx
extension and must not be used in portable code.

View File

@ -1,4 +1,4 @@
.\" $NetBSD: menus.3,v 1.10 2002/07/03 11:24:47 wiz Exp $
.\" $NetBSD: menus.3,v 1.11 2002/07/29 13:03:51 blymn Exp $
.\"
.\" Copyright (c) 1999
.\" Brett Lymn - blymn@baea.com.au, brett_lymn@yahoo.com.au
@ -98,6 +98,8 @@ manual page name
.Xr menu_item_opts 3
.It item_opts_on
.Xr menu_item_opts 3
.It item_selected
.Xr menu_item_value 3
.It item_term
.Xr menu_hook 3
.It item_userptr
@ -281,3 +283,9 @@ of it. Since the current item is displayed using the foreground
attribute it was deemed unnecessary to also display the mark string against
the current item.
.El
.Pp
The option O_RADIO and the function
.Fn item_selected
are
.Nx
extensions and must not be used in portable code.

View File

@ -1,4 +1,4 @@
/* $NetBSD: post.c,v 1.9 2002/02/04 13:02:06 blymn Exp $ */
/* $NetBSD: post.c,v 1.10 2002/07/29 13:03:51 blymn Exp $ */
/*-
* Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@yahoo.com.au)
@ -72,10 +72,12 @@ post_menu(MENU *menu)
if ((menu->cols * menu->max_item_width + menu->cols - 1) > maxx)
return E_NO_ROOM;
for (i = 0; i < menu->item_count; i++) {
menu->items[i]->selected = 0;
if ((menu->opts & O_RADIO) != O_RADIO) {
for (i = 0; i < menu->item_count; i++) {
menu->items[i]->selected = 0;
}
}
menu->posted = 1;
return _menui_draw_menu(menu);

View File

@ -1,5 +1,5 @@
# $NetBSD: shlib_version,v 1.8 2002/02/04 13:02:06 blymn Exp $
# $NetBSD: shlib_version,v 1.9 2002/07/29 13:03:51 blymn Exp $
# Remember to update distrib/sets/lists/base/shl.* when changing
#
major=4
minor=0
minor=1