xref: /netbsd/lib/libmenu/item.c (revision bf9ec67e)
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