Home | History | Annotate | Line # | Download | only in libmenu
item.c revision 1.9
      1 /*	$NetBSD: item.c,v 1.9 2003/03/09 01:08:48 lukem Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998-1999 Brett Lymn (blymn (at) baea.com.au, brett_lymn (at) yahoo.com.au)
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. The name of the author may not be used to endorse or promote products
     13  *    derived from this software without specific prior written permission
     14  *
     15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  *
     26  *
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __RCSID("$NetBSD: item.c,v 1.9 2003/03/09 01:08:48 lukem Exp $");
     31 
     32 #include <menu.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 
     36 /* the following is defined in menu.c - it is the default menu struct */
     37 extern MENU _menui_default_menu;
     38 
     39 /* keep default item options for setting in new_item */
     40 ITEM _menui_default_item = {
     41 	{NULL, 0}, /* item name struct */
     42 	{NULL, 0}, /* item description struct */
     43 	NULL, /* user pointer */
     44 	0, /* is item visible? */
     45 	0, /* is item selected? */
     46 	0, /* row item is on */
     47 	0, /* column item is on */
     48 	O_SELECTABLE, /* item options */
     49 	NULL, /* parent menu item is bound to */
     50 	-1, /* index number if item attached to a menu */
     51 	NULL, /* left neighbour */
     52 	NULL, /* right neighbour */
     53 	NULL, /* up neighbour */
     54 	NULL /* down neighbour */
     55 };
     56 
     57 /*
     58  * Return the item visibility flag
     59  */
     60 int
     61 item_visible(ITEM *item)
     62 {
     63 	if (item == NULL)
     64 		return E_BAD_ARGUMENT;
     65 	if (item->parent == NULL)
     66 		return E_NOT_CONNECTED;
     67 
     68         return item->visible;
     69 }
     70 
     71 /*
     72  * Return the pointer to the item name
     73  */
     74 char *
     75 item_name(ITEM *item)
     76 {
     77 	if (item == NULL)
     78 		return NULL;
     79 
     80         return item->name.string;
     81 }
     82 
     83 /*
     84  * Return the pointer to the item description
     85  */
     86 char *
     87 item_description(ITEM *item)
     88 {
     89 	if (item == NULL)
     90 		return NULL;
     91 
     92         return item->description.string;
     93 }
     94 
     95 /*
     96  * Set the application defined function called when the menu is posted or
     97  * just after the current item changes.
     98  */
     99 int
    100 set_item_init(MENU *menu, Menu_Hook func)
    101 {
    102 	if (menu == NULL)
    103 		_menui_default_menu.item_init = func;
    104 	else
    105 		menu->item_init = func;
    106         return E_OK;
    107 }
    108 
    109 
    110 /*
    111  * Return a pointer to the item initialisation routine.
    112  */
    113 Menu_Hook
    114 item_init(MENU *menu)
    115 {
    116 	if (menu == NULL)
    117 		return _menui_default_menu.item_init;
    118 	else
    119 		return menu->item_init;
    120 }
    121 
    122 /*
    123  * Set the user defined function to be called when menu is unposted or just
    124  * before the current item changes.
    125  */
    126 int
    127 set_item_term(MENU *menu, Menu_Hook func)
    128 {
    129 	if (menu == NULL)
    130 		_menui_default_menu.item_term = func;
    131 	else
    132 		menu->item_term = func;
    133         return E_OK;
    134 }
    135 
    136 /*
    137  * Return a pointer to the termination function
    138  */
    139 Menu_Hook
    140 item_term(MENU *menu)
    141 {
    142 	if (menu == NULL)
    143 		return _menui_default_menu.item_term;
    144 	else
    145 		return menu->item_term;
    146 }
    147 
    148 /*
    149  * Returns the number of items that are selected.
    150  * The index numbers of the items are placed in the dynamically allocated
    151  * int array *sel.
    152  */
    153 int
    154 item_selected(MENU *menu, int **sel)
    155 {
    156 	int i, j;
    157 
    158 	if (menu == NULL)
    159 		return E_BAD_ARGUMENT;
    160 
    161 	/* count selected */
    162 	for (i = 0, j = 0; i < menu->item_count; i++)
    163 		if (menu->items[i]->selected)
    164 			j++;
    165 
    166 	if (j == 0) {
    167 		*sel = NULL;
    168 		return 0;
    169 	}
    170 
    171 	if ( (*sel = malloc(sizeof(int) * j)) == NULL)
    172 		return E_SYSTEM_ERROR;
    173 
    174 	for (i = 0, j = 0; i < menu->item_count; i++)
    175 		if (menu->items[i]->selected)
    176 			(*sel)[j++] = i;
    177 
    178 	return j;
    179 }
    180 
    181 /*
    182  * Set the item options.  We keep a global copy of the current item options
    183  * as subsequent new_item calls will use the updated options as their
    184  * defaults.
    185  */
    186 int
    187 set_item_opts(item, opts)
    188         ITEM *item;
    189         OPTIONS opts;
    190 {
    191           /* selectable seems to be the only allowable item opt! */
    192         if (opts != O_SELECTABLE)
    193                 return E_SYSTEM_ERROR;
    194 
    195 	if (item == NULL)
    196 		_menui_default_item.opts = opts;
    197 	else
    198 		item->opts = opts;
    199         return E_OK;
    200 }
    201 
    202 /*
    203  * Set item options on.
    204  */
    205 int
    206 item_opts_on(ITEM *item, OPTIONS opts)
    207 {
    208         if (opts != O_SELECTABLE)
    209                 return E_SYSTEM_ERROR;
    210 
    211         if (item == NULL)
    212 		_menui_default_item.opts |= opts;
    213 	else
    214 		item->opts |= opts;
    215         return E_OK;
    216 }
    217 
    218 /*
    219  * Turn off the named options.
    220  */
    221 int
    222 item_opts_off(ITEM *item, OPTIONS opts)
    223 {
    224         if (opts != O_SELECTABLE)
    225                 return E_SYSTEM_ERROR;
    226 
    227 	if (item == NULL)
    228 		_menui_default_item.opts &= ~(opts);
    229 	else
    230 		item->opts &= ~(opts);
    231         return E_OK;
    232 }
    233 
    234 /*
    235  * Return the current options set in item.
    236  */
    237 OPTIONS
    238 item_opts(ITEM *item)
    239 {
    240 	if (item == NULL)
    241 		return _menui_default_item.opts;
    242 	else
    243 		return item->opts;
    244 }
    245 
    246 /*
    247  * Set the selected flag of the item iff the menu options allow it.
    248  */
    249 int
    250 set_item_value(ITEM *param_item, int flag)
    251 {
    252 	ITEM *item = (param_item != NULL) ? param_item : &_menui_default_item;
    253 
    254           /* not bound to a menu */
    255         if (item->parent == NULL)
    256                 return E_NOT_CONNECTED;
    257 
    258           /* menu options do not allow multi-selection */
    259         if ((item->parent->opts & O_ONEVALUE) == O_ONEVALUE)
    260                 return E_REQUEST_DENIED;
    261 
    262         item->selected = flag;
    263         return E_OK;
    264 }
    265 
    266 /*
    267  * Return the item value of the item.
    268  */
    269 int
    270 item_value(ITEM *item)
    271 {
    272 	if (item == NULL)
    273 		return _menui_default_item.selected;
    274 	else
    275 		return item->selected;
    276 }
    277 
    278 /*
    279  * Allocate a new item and return the pointer to the newly allocated
    280  * structure.
    281  */
    282 ITEM *
    283 new_item(char *name, char *description)
    284 {
    285         ITEM *new_one;
    286 
    287 	  /* allocate a new item structure for ourselves */
    288         if ((new_one = (ITEM *)malloc(sizeof(ITEM))) == NULL)
    289                 return NULL;
    290 
    291 	  /* copy in the defaults for the item */
    292 	(void)memcpy(new_one, &_menui_default_item, sizeof(ITEM));
    293 
    294 	  /* fill in the name structure - first the length and then
    295 	     allocate room for the string & copy that. */
    296 	new_one->name.length = strlen(name);
    297         if ((new_one->name.string = (char *)
    298              malloc(sizeof(char) * new_one->name.length + 1)) == NULL) {
    299 		  /* uh oh malloc failed - clean up & exit */
    300 		free(new_one);
    301                 return NULL;
    302         }
    303 
    304         strcpy(new_one->name.string, name);
    305 
    306 	  /* fill in the description structure, stash the length then
    307 	     allocate room for description string and copy it in */
    308         new_one->description.length = strlen(description);
    309         if ((new_one->description.string = (char *)
    310              malloc(sizeof(char) * new_one->description.length + 1)) == NULL) {
    311 		  /* malloc has failed - free up allocated memory and return */
    312 		free(new_one->name.string);
    313 		free(new_one);
    314 		return NULL;
    315 	}
    316 
    317 	strcpy(new_one->description.string, description);
    318 
    319 	return new_one;
    320 }
    321 
    322 /*
    323  * Free the allocated storage associated with item.
    324  */
    325 int
    326 free_item(ITEM *item)
    327 {
    328 	if (item == NULL)
    329 		return E_BAD_ARGUMENT;
    330 
    331 	  /* check for connection to menu */
    332 	if (item->parent != NULL)
    333 		return E_CONNECTED;
    334 
    335 	  /* no connections, so free storage starting with the strings */
    336 	free(item->name.string);
    337 	free(item->description.string);
    338 	free(item);
    339 	return E_OK;
    340 }
    341 
    342 /*
    343  * Set the menu's current item to the one given.
    344  */
    345 int
    346 set_current_item(MENU *param_menu, ITEM *item)
    347 {
    348 	MENU *menu = (param_menu != NULL) ? param_menu : &_menui_default_menu;
    349 	int i = 0;
    350 
    351 	  /* check if we have been called from an init type function */
    352 	if (menu->in_init == 1)
    353 		return E_BAD_STATE;
    354 
    355 	  /* check we have items in the menu */
    356 	if (menu->items == NULL)
    357 		return E_NOT_CONNECTED;
    358 
    359 	if ((i = item_index(item)) < 0)
    360 		  /* item must not be a part of this menu */
    361 		return E_BAD_ARGUMENT;
    362 
    363 	menu->cur_item = i;
    364 	return E_OK;
    365 }
    366 
    367 /*
    368  * Return a pointer to the current item for the menu
    369  */
    370 ITEM *
    371 current_item(MENU *menu)
    372 {
    373 	if (menu == NULL)
    374 		return NULL;
    375 
    376 	if (menu->items == NULL)
    377 		return NULL;
    378 
    379 	return menu->items[menu->cur_item];
    380 }
    381 
    382 /*
    383  * Return the index into the item array that matches item.
    384  */
    385 int
    386 item_index(ITEM *item)
    387 {
    388 	if (item == NULL)
    389 		return _menui_default_item.index;
    390 	else
    391 		return item->index;
    392 }
    393