2 * Copyright Droids Corporation, Microb Technology, Eirbot (2005)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Revision : $Id: menu.c,v 1.3.4.2 2007-05-23 17:18:15 zer0 Exp $
22 /* Olivier MATZ, Droids-corp 2004 - 2006
23 * Implementation of a static menu
33 /** return name of a menu, if the type is correct */
34 char * menu_get_name(struct menu * m) {
38 if ( m->type == MENU_TYPE_MENU ||
39 m->type == MENU_TYPE_ROOT ||
40 m->type == MENU_TYPE_FCT_HDR )
41 return (char *)m->data;
46 /** return type of a menu */
47 uint8_t menu_get_type(struct menu * m) {
49 return MENU_TYPE_UNKNOWN;
54 static uint8_t menu_is_a_submenu(struct menu * m)
59 return ( m->type == MENU_TYPE_MENU || m->type == MENU_TYPE_ROOT );
63 /** call the function described by the menu, and return 0 on success */
64 uint8_t menu_call_fct(struct menu * m) {
70 if ( m->type != MENU_TYPE_FCT_HDR )
73 f = (void (*)(void *) )(m+1)->data;
75 if ( (m+1)->type != MENU_TYPE_FCT_PTR || f == NULL )
78 if ( (m+2)->type != MENU_TYPE_FCT_DATA )
86 /** get previous menu on same level, return NULL if no one */
87 struct menu * menu_get_previous(struct menu * m) {
93 if(m->type == MENU_TYPE_ROOT)
97 while ( level >= 0 ) {
99 if ( m->type == MENU_TYPE_ROOT ) {
102 if ( m->type == MENU_TYPE_END ) {
105 if ( m->type == MENU_TYPE_MENU ) {
109 if ( m->type == MENU_TYPE_FCT_HDR ||
110 m->type == MENU_TYPE_MENU ) {
119 /** get next menu on same level, return NULL if no one */
120 struct menu * menu_get_next(struct menu * m) {
126 if(m->type == MENU_TYPE_ROOT)
129 if ( m->type == MENU_TYPE_MENU ) {
134 while ( level >= 0 ) {
137 if ( m->type == MENU_TYPE_FCT_HDR ||
138 m->type == MENU_TYPE_MENU ) {
142 if ( m->type == MENU_TYPE_END ) {
145 if ( m->type == MENU_TYPE_MENU ) {
153 /** get the parent of the menu - return NULL if no parent */
154 struct menu * menu_get_parent(struct menu * m)
161 /* return null if root */
162 if(m->type == MENU_TYPE_ROOT)
167 } while ( (m=menu_get_previous(ret)) ) ;
169 /* get the previous one and return it if it is a submenu, else return NULL */
171 if ( menu_is_a_submenu(ret) )
177 /** return first son or NULL if there is no son */
178 struct menu * menu_get_first_son(struct menu * m)
183 if (menu_is_a_submenu(m)) {
189 /** get the submenu 'num' -> can return NULL if does not exist */
190 struct menu * menu_get_sub(struct menu * m, uint8_t num) {
194 m = menu_get_first_son(m);
197 m = menu_get_next(m);
202 /** return number of submenus in a menu */
203 uint8_t menu_get_sub_howmany(struct menu * m) {
209 m = menu_get_first_son(m);
212 m = menu_get_next(m);
218 /** get the parent of the menu - never return NULL except if m is null */
219 struct menu * menu_left(struct menu * m)
226 if ( (ret = menu_get_parent(m)) )
232 /** get the son number 'num' or self if it does not exist,
233 try to call the function if it exists, does not return null
234 except if m is null */
235 struct menu * menu_right(struct menu * m)
241 if ( (ret=menu_get_first_son(m)) )
249 /** return the next menu on same level (if it is the last, go back to beginning */
250 struct menu * menu_up(struct menu * m)
257 /* if there is a menu before, return it */
258 if ( (ret=menu_get_previous(m)) )
261 /* if there is no before and no next, return self */
262 if ( ! (ret = menu_get_next(m) ) )
265 /* return the next, next, next, ... until the end of menu */
268 } while ( (m=menu_get_next(ret)) ) ;
273 /** return the next menu on same level (if it is the first, go back to the end */
274 struct menu * menu_down(struct menu * m)
281 /* if there is a menu after, return it */
282 if ( (ret=menu_get_next(m)) )
285 /* if there is no before and no next, return self */
286 if ( ! (ret = menu_get_previous(m) ) )
289 /* return the previous, previous, previous, ... until the end of menu */
292 } while ( (m=menu_get_previous(ret)) ) ;
298 /** move in the menu, depending on the action */
299 struct menu * menu_default_update(struct menu * m, char c)
309 return menu_right(m);
313 if(c >= '0' && c <= '9') {
314 if ( m->type == MENU_TYPE_ROOT && c == '0' ) {
318 else if ( (ret = menu_right(menu_get_sub(menu_get_parent(m), c-'0'))) ) {
327 /** default function to display a menu, you can reimplement it */
328 void menu_default_display(struct menu * m)
330 struct menu * parent = menu_get_parent(m);
338 printf("%s\r\n", menu_get_name(parent));
340 for (i=0 ; i<menu_get_sub_howmany(parent) ; i++) {
341 son = menu_get_sub(parent, i);
343 printf("> %d: %s", i, menu_get_name(son));
345 printf(" %d: %s", i, menu_get_name(son));
346 if(menu_is_a_submenu(son))
352 printf("| 0: %s -->", menu_get_name(m));