1 /* $NetBSD: item.c,v 1.7 2001/06/13 10:45:59 wiz Exp $ */ 2 3 /*- 4 * Copyright (c) 1998-1999 Brett Lymn (blymn@baea.com.au, brett_lymn@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 <menu.h> 30 #include <stdlib.h> 31 #include <string.h> 32 33 /* the following is defined in menu.c - it is the default menu struct */ 34 extern MENU _menui_default_menu; 35 36 /* keep default item options for setting in new_item */ 37 ITEM _menui_default_item = { 38 {NULL, 0}, /* item name struct */ 39 {NULL, 0}, /* item description struct */ 40 NULL, /* user pointer */ 41 0, /* is item visible? */ 42 0, /* is item selected? */ 43 0, /* row item is on */ 44 0, /* column item is on */ 45 O_SELECTABLE, /* item options */ 46 NULL, /* parent menu item is bound to */ 47 -1, /* index number if item attached to a menu */ 48 NULL, /* left neighbour */ 49 NULL, /* right neighbour */ 50 NULL, /* up neighbour */ 51 NULL /* down neighbour */ 52 }; 53 54 /* 55 * Return the item visibility flag 56 */ 57 int 58 item_visible(ITEM *item) 59 { 60 if (item == NULL) 61 return E_BAD_ARGUMENT; 62 if (item->parent == NULL) 63 return E_NOT_CONNECTED; 64 65 return item->visible; 66 } 67 68 /* 69 * Return the pointer to the item name 70 */ 71 char * 72 item_name(ITEM *item) 73 { 74 if (item == NULL) 75 return NULL; 76 77 return item->name.string; 78 } 79 80 /* 81 * Return the pointer to the item description 82 */ 83 char * 84 item_description(ITEM *item) 85 { 86 if (item == NULL) 87 return NULL; 88 89 return item->description.string; 90 } 91 92 /* 93 * Set the application defined function called when the menu is posted or 94 * just after the current item changes. 95 */ 96 int 97 set_item_init(MENU *menu, Menu_Hook func) 98 { 99 if (menu == NULL) 100 _menui_default_menu.item_init = func; 101 else 102 menu->item_init = func; 103 return E_OK; 104 } 105 106 107 /* 108 * Return a pointer to the item initialisation routine. 109 */ 110 Menu_Hook 111 item_init(MENU *menu) 112 { 113 if (menu == NULL) 114 return _menui_default_menu.item_init; 115 else 116 return menu->item_init; 117 } 118 119 /* 120 * Set the user defined function to be called when menu is unposted or just 121 * before the current item changes. 122 */ 123 int 124 set_item_term(MENU *menu, Menu_Hook func) 125 { 126 if (menu == NULL) 127 _menui_default_menu.item_term = func; 128 else 129 menu->item_term = func; 130 return E_OK; 131 } 132 133 /* 134 * Return a pointer to the termination function 135 */ 136 Menu_Hook 137 item_term(MENU *menu) 138 { 139 if (menu == NULL) 140 return _menui_default_menu.item_term; 141 else 142 return menu->item_term; 143 } 144 145 /* 146 * Set the item options. We keep a global copy of the current item options 147 * as subsequent new_item calls will use the updated options as their 148 * defaults. 149 */ 150 int 151 set_item_opts(item, opts) 152 ITEM *item; 153 OPTIONS opts; 154 { 155 /* selectable seems to be the only allowable item opt! */ 156 if (opts != O_SELECTABLE) 157 return E_SYSTEM_ERROR; 158 159 if (item == NULL) 160 _menui_default_item.opts = opts; 161 else 162 item->opts = opts; 163 return E_OK; 164 } 165 166 /* 167 * Set item options on. 168 */ 169 int 170 item_opts_on(ITEM *item, OPTIONS opts) 171 { 172 if (opts != O_SELECTABLE) 173 return E_SYSTEM_ERROR; 174 175 if (item == NULL) 176 _menui_default_item.opts |= opts; 177 else 178 item->opts |= opts; 179 return E_OK; 180 } 181 182 /* 183 * Turn off the named options. 184 */ 185 int 186 item_opts_off(ITEM *item, OPTIONS opts) 187 { 188 if (opts != O_SELECTABLE) 189 return E_SYSTEM_ERROR; 190 191 if (item == NULL) 192 _menui_default_item.opts &= ~(opts); 193 else 194 item->opts &= ~(opts); 195 return E_OK; 196 } 197 198 /* 199 * Return the current options set in item. 200 */ 201 OPTIONS 202 item_opts(ITEM *item) 203 { 204 if (item == NULL) 205 return _menui_default_item.opts; 206 else 207 return item->opts; 208 } 209 210 /* 211 * Set the selected flag of the item iff the menu options allow it. 212 */ 213 int 214 set_item_value(ITEM *param_item, int flag) 215 { 216 ITEM *item = (param_item != NULL) ? param_item : &_menui_default_item; 217 218 /* not bound to a menu */ 219 if (item->parent == NULL) 220 return E_NOT_CONNECTED; 221 222 /* menu options do not allow multi-selection */ 223 if ((item->parent->opts & O_ONEVALUE) == O_ONEVALUE) 224 return E_REQUEST_DENIED; 225 226 item->selected = flag; 227 return E_OK; 228 } 229 230 /* 231 * Return the item value of the item. 232 */ 233 int 234 item_value(ITEM *item) 235 { 236 if (item == NULL) 237 return _menui_default_item.selected; 238 else 239 return item->selected; 240 } 241 242 /* 243 * Allocate a new item and return the pointer to the newly allocated 244 * structure. 245 */ 246 ITEM * 247 new_item(char *name, char *description) 248 { 249 ITEM *new_one; 250 251 /* allocate a new item structure for ourselves */ 252 if ((new_one = (ITEM *)malloc(sizeof(ITEM))) == NULL) 253 return NULL; 254 255 /* copy in the defaults for the item */ 256 (void)memcpy(new_one, &_menui_default_item, sizeof(ITEM)); 257 258 /* fill in the name structure - first the length and then 259 allocate room for the string & copy that. */ 260 new_one->name.length = strlen(name); 261 if ((new_one->name.string = (char *) 262 malloc(sizeof(char) * new_one->name.length + 1)) == NULL) { 263 /* uh oh malloc failed - clean up & exit */ 264 free(new_one); 265 return NULL; 266 } 267 268 strcpy(new_one->name.string, name); 269 270 /* fill in the description structure, stash the length then 271 allocate room for description string and copy it in */ 272 new_one->description.length = strlen(description); 273 if ((new_one->description.string = (char *) 274 malloc(sizeof(char) * new_one->description.length + 1)) == NULL) { 275 /* malloc has failed - free up allocated memory and return */ 276 free(new_one->name.string); 277 free(new_one); 278 return NULL; 279 } 280 281 strcpy(new_one->description.string, description); 282 283 return new_one; 284 } 285 286 /* 287 * Free the allocated storage associated with item. 288 */ 289 int 290 free_item(ITEM *item) 291 { 292 if (item == NULL) 293 return E_BAD_ARGUMENT; 294 295 /* check for connection to menu */ 296 if (item->parent != NULL) 297 return E_CONNECTED; 298 299 /* no connections, so free storage starting with the strings */ 300 free(item->name.string); 301 free(item->description.string); 302 free(item); 303 return E_OK; 304 } 305 306 /* 307 * Set the menu's current item to the one given. 308 */ 309 int 310 set_current_item(MENU *param_menu, ITEM *item) 311 { 312 MENU *menu = (param_menu != NULL) ? param_menu : &_menui_default_menu; 313 int i = 0; 314 315 /* check if we have been called from an init type function */ 316 if (menu->in_init == 1) 317 return E_BAD_STATE; 318 319 /* check we have items in the menu */ 320 if (menu->items == NULL) 321 return E_NOT_CONNECTED; 322 323 if ((i = item_index(item)) < 0) 324 /* item must not be a part of this menu */ 325 return E_BAD_ARGUMENT; 326 327 menu->cur_item = i; 328 return E_OK; 329 } 330 331 /* 332 * Return a pointer to the current item for the menu 333 */ 334 ITEM * 335 current_item(MENU *menu) 336 { 337 if (menu == NULL) 338 return NULL; 339 340 if (menu->items == NULL) 341 return NULL; 342 343 return menu->items[menu->cur_item]; 344 } 345 346 /* 347 * Return the index into the item array that matches item. 348 */ 349 int 350 item_index(ITEM *item) 351 { 352 if (item == NULL) 353 return _menui_default_item.index; 354 else 355 return item->index; 356 } 357