diff --git a/server/menu.c b/server/menu.c index 3f194e5..c4f13da 100644 --- a/server/menu.c +++ b/server/menu.c @@ -43,12 +43,15 @@ menu_create (char *id, MenuEventFunc(*event_func), { Menu *new_menu; - debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", association=%p )", __FUNCTION__, id, event_func, text, association); + debug (RPT_DEBUG, "%s( id=\"%s\", event_func=%p, text=\"%s\", association=%p )", + __FUNCTION__, id, event_func, text, association); new_menu = menuitem_create (MENUITEM_MENU, id, event_func, text); - new_menu->data.menu.contents = LL_new(); - new_menu->data.menu.association = association; + if (new_menu != NULL) { + new_menu->data.menu.contents = LL_new(); + new_menu->data.menu.association = association; + } return new_menu; } @@ -56,6 +59,9 @@ menu_create (char *id, MenuEventFunc(*event_func), void menu_destroy (Menu *menu) { + if (menu == NULL) + return; + debug (RPT_DEBUG, "%s( menu=[%s] )", __FUNCTION__, menu->id); menu_destroy_all_items (menu); @@ -68,9 +74,10 @@ menu_destroy (Menu *menu) void menu_add_item (Menu *menu, MenuItem *item) { - debug (RPT_DEBUG, "%s( menu=[%s], item=[%s] )", __FUNCTION__, menu->id, item->id); + if ((menu == NULL) || (item == NULL)) + return; - if (!menu) return; + debug (RPT_DEBUG, "%s( menu=[%s], item=[%s] )", __FUNCTION__, menu->id, item->id); /* Add the item to the menu */ LL_Push (menu->data.menu.contents, item); @@ -83,15 +90,18 @@ menu_remove_item (Menu *menu, MenuItem *item) int i; MenuItem * item2; + if ((menu == NULL) || (item == NULL)) + return + debug (RPT_DEBUG, "%s( menu=[%s], item=[%s] )", __FUNCTION__, menu->id, item->id); /* Find the item */ - for (item2=LL_GetFirst(menu->data.menu.contents), i=0; - item2; - item2=LL_GetNext(menu->data.menu.contents), i++ ) { - if (item==item2) { + for (item2 = LL_GetFirst(menu->data.menu.contents), i=0; + item2 != NULL; + item2 = LL_GetNext(menu->data.menu.contents), i++ ) { + if (item == item2) { LL_DeleteNode (menu->data.menu.contents); - if (menu->data.menu.selector_pos>=i) { + if (menu->data.menu.selector_pos >= i) { menu->data.menu.selector_pos--; if (menu->data.menu.scroll > 0) menu->data.menu.scroll--; @@ -106,9 +116,12 @@ menu_destroy_all_items (Menu *menu) { MenuItem * item; + if (menu == NULL) + return; + debug (RPT_DEBUG, "%s( menu=[%s] )", __FUNCTION__, menu->id); - for( item = menu_getfirst_item(menu); item; item = menu_getfirst_item(menu) ) { + for( item = menu_getfirst_item(menu); item != NULL; item = menu_getfirst_item(menu) ) { menuitem_destroy (item); LL_Remove (menu->data.menu.contents, item); } @@ -118,9 +131,12 @@ MenuItem *menu_find_item (Menu *menu, char *id, bool recursive) { MenuItem * item; + if ((menu == NULL) || (id == NULL)) + return NULL; + debug (RPT_DEBUG, "%s( menu=[%s], id=\"%s\", recursive=%d )", __FUNCTION__, menu->id, id, recursive); - for( item = menu_getfirst_item(menu); item; item = menu_getnext_item(menu) ) { + for( item = menu_getfirst_item(menu); item != NULL; item = menu_getnext_item(menu) ) { if ( strcmp(item->id, id) == 0 ) { return item; } @@ -137,6 +153,9 @@ MenuItem *menu_find_item (Menu *menu, char *id, bool recursive) void menu_reset (Menu *menu) { + if (menu == NULL) + return; + debug (RPT_DEBUG, "%s( menu=[%s] )", __FUNCTION__, menu->id); menu->data.menu.selector_pos = 0; @@ -149,6 +168,9 @@ void menu_build_screen (MenuItem *menu, Screen *s) MenuItem * subitem; int itemnr; + if ((menu == NULL) || (s == NULL)) + return; + debug (RPT_DEBUG, "%s( menu=[%s], screen=[%s] )", __FUNCTION__, menu->id, s->id); /* TODO: Put menu in a frame to do easy scrolling */ @@ -156,13 +178,15 @@ void menu_build_screen (MenuItem *menu, Screen *s) /* Create menu title widget */ w = widget_create ("title", WID_TITLE, s); - screen_add_widget (s, w); - w->text = strdup(menu->text); - w->x = 1; + if (w != NULL) { + screen_add_widget (s, w); + w->text = strdup(menu->text); + w->x = 1; + } /* Create widgets for each subitem in the menu */ for (subitem = LL_GetFirst (menu->data.menu.contents), itemnr = 0; - subitem; + subitem != NULL; subitem = LL_GetNext (menu->data.menu.contents), itemnr ++ ) { char buf[10]; @@ -171,72 +195,80 @@ void menu_build_screen (MenuItem *menu, Screen *s) buf[sizeof(buf)-1] = 0; w = widget_create (buf, WID_STRING, s); /* (buf will be copied) */ - screen_add_widget (s, w); - w->x = 2; - - switch (subitem->type) { - case MENUITEM_CHECKBOX: - - /* Limit string length */ - w->text = strdup (subitem->text); - if (strlen(subitem->text) >= display_props->width-2) { - (w->text)[display_props->width-2] = 0; - } - - /* Add icon for checkbox */ - snprintf (buf, sizeof(buf)-1, "icon%d", itemnr); - buf[sizeof(buf)-1] = 0; - w = widget_create (buf, WID_ICON, s); - /* (buf will be copied) */ + if (w != NULL) { screen_add_widget (s, w); - w->x = display_props->width - 1; - w->length = ICON_CHECKBOX_OFF; - break; - case MENUITEM_RING: - /* Create string for text + ringtext */ - w->text = malloc (display_props->width); - break; - case MENUITEM_MENU: - /* Limit string length */ - w->text = malloc( strlen(subitem->text) + 4 ); - strcpy( w->text, subitem->text ); - strcat( w->text, " >" ); - if (strlen(subitem->text) >= display_props->width-1) { - (w->text)[display_props->width-1] = 0; + w->x = 2; + + switch (subitem->type) { + case MENUITEM_CHECKBOX: + + /* Limit string length */ + w->text = strdup (subitem->text); + if (strlen(subitem->text) >= display_props->width-2) { + (w->text)[display_props->width-2] = 0; + } + + /* Add icon for checkbox */ + snprintf (buf, sizeof(buf)-1, "icon%d", itemnr); + buf[sizeof(buf)-1] = 0; + w = widget_create (buf, WID_ICON, s); + /* (buf will be copied) */ + screen_add_widget (s, w); + w->x = display_props->width - 1; + w->length = ICON_CHECKBOX_OFF; + break; + case MENUITEM_RING: + /* Create string for text + ringtext */ + w->text = malloc (display_props->width); + break; + case MENUITEM_MENU: + /* Limit string length */ + w->text = malloc( strlen(subitem->text) + 4 ); + strcpy( w->text, subitem->text ); + strcat( w->text, " >" ); + if (strlen(subitem->text) >= display_props->width-1) { + (w->text)[display_props->width-1] = '\0'; + } + break; + case MENUITEM_ACTION: + case MENUITEM_SLIDER: + case MENUITEM_NUMERIC: + case MENUITEM_ALPHA: + /* Limit string length */ + w->text = strdup (subitem->text); + if (strlen(subitem->text) >= display_props->width-1) { + (w->text)[display_props->width-1] = '\0'; + } + break; } - break; - case MENUITEM_ACTION: - case MENUITEM_SLIDER: - case MENUITEM_NUMERIC: - case MENUITEM_ALPHA: - /* Limit string length */ - w->text = strdup (subitem->text); - if (strlen(subitem->text) >= display_props->width-1) { - (w->text)[display_props->width-1] = 0; - } - break; } } /* Add arrow for selection on the left */ w = widget_create ("selector", WID_ICON, s); - screen_add_widget (s, w); - w->length = ICON_SELECTOR_AT_LEFT; - w->x = 1; + if (w != NULL) { + screen_add_widget (s, w); + w->length = ICON_SELECTOR_AT_LEFT; + w->x = 1; + } /* Add scrollers on the right side on top and bottom */ /* TODO: when menu is in a frame, these can be removed */ w = widget_create ("upscroller", WID_ICON, s); - screen_add_widget (s, w); - w->length = ICON_ARROW_UP; - w->x = display_props->width; - w->y = 1; + if (w != NULL) { + screen_add_widget (s, w); + w->length = ICON_ARROW_UP; + w->x = display_props->width; + w->y = 1; + } w = widget_create ("downscroller", WID_ICON, s); - screen_add_widget (s, w); - w->length = ICON_ARROW_DOWN; - w->x = display_props->width; - w->y = display_props->height; + if (w != NULL) { + screen_add_widget (s, w); + w->length = ICON_ARROW_DOWN; + w->x = display_props->width; + w->y = display_props->height; + } } @@ -246,6 +278,9 @@ void menu_update_screen (MenuItem *menu, Screen *s) MenuItem * subitem; int itemnr; + if ((menu == NULL) || (s == NULL)) + return; + debug (RPT_DEBUG, "%s( menu=[%s], screen=[%s] )", __FUNCTION__, menu->id, s->id); /* Update widgets for the title */ @@ -358,6 +393,9 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key) { MenuItem *subitem; + if (menu == NULL) + return MENURESULT_ERROR; + debug (RPT_DEBUG, "%s( menu=[%s], token=%d, key=\"%s\" )", __FUNCTION__, menu->id, token, key); switch (token) { @@ -371,7 +409,8 @@ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key) case MENUITEM_ACTION: if (subitem->event_func) subitem->event_func (subitem, MENUEVENT_SELECT); - return subitem->data.action.menu_result; return MENURESULT_QUIT; + return subitem->data.action.menu_result; + //return MENURESULT_QUIT; case MENUITEM_CHECKBOX: if (subitem->data.checkbox.allow_gray) { subitem->data.checkbox.value = (subitem->data.checkbox.value + 1) % 3; diff --git a/server/menu.h b/server/menu.h index f50abaa..43b2952 100644 --- a/server/menu.h +++ b/server/menu.h @@ -64,7 +64,9 @@ static inline MenuItem *menu_getfirst_item (Menu *menu) * Retrieves the first item from the list of items in the menu. */ { - return (MenuItem*) LL_GetFirst( menu->data.menu.contents ); + return (MenuItem*) ((menu != NULL) + ? LL_GetFirst(menu->data.menu.contents) + : NULL); } static inline MenuItem *menu_getnext_item (Menu *menu) @@ -74,15 +76,18 @@ static inline MenuItem *menu_getnext_item (Menu *menu) * this function, to keep the list-cursor where it is. */ { - return (MenuItem*) LL_GetNext( menu->data.menu.contents ); + return (MenuItem*) ((menu != NULL) + ? LL_GetNext(menu->data.menu.contents) + : NULL); } static inline MenuItem *menu_get_current_item (Menu *menu) /* Retrieves the current item from the list of items in the menu. */ { - return LL_GetByIndex( - menu->data.menu.contents, - menu->data.menu.selector_pos); + return (MenuItem*) ((menu != NULL) + ? LL_GetByIndex(menu->data.menu.contents, + menu->data.menu.selector_pos) + : NULL); } MenuItem *menu_find_item (Menu *menu, char *id, bool recursive); @@ -90,23 +95,23 @@ MenuItem *menu_find_item (Menu *menu, char *id, bool recursive); void menu_reset (Menu *menu); /* Resets it to initial state. - * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! + * DO NOT CALL THIS FUNCTION, CALL menuitem_reset_screen INSTEAD ! */ void menu_build_screen (Menu *menu, Screen *s); /* Builds the selected menuitem on screen using widgets. - * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! + * DO NOT CALL THIS FUNCTION, CALL menuitem_rebuild_screen INSTEAD ! */ void menu_update_screen (Menu *menu, Screen *s); /* Updates the widgets of the selected menuitem - * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! + * DO NOT CALL THIS FUNCTION, CALL menuitem_update_screen INSTEAD ! */ MenuResult menu_process_input (Menu *menu, MenuToken token, char * key); /* Does something with the given input. * key is only used if token is MENUTOKEN_OTHER. - * DO NOT CALL THIS FUNCTION, CALL menuitem_build_screen INSTEAD ! + * DO NOT CALL THIS FUNCTION, CALL menuitem_process_input INSTEAD ! */ #endif diff --git a/server/menuitem.c b/server/menuitem.c index 07c1be8..15fdc48 100644 --- a/server/menuitem.c +++ b/server/menuitem.c @@ -115,6 +115,11 @@ MenuItem *menuitem_create (MenuItemType type, char *id, MenuEventFunc(*event_fun debug (RPT_DEBUG, "%s( type=%d, id=\"%s\", event_func=%p, text=\"%s\" )", __FUNCTION__, type, id, event_func, text); + if ((id == NULL) || (text == NULL)) { + // report (RPT_ERR, "%s: illegal id or text", __FUNCTION__); + return NULL; + } + /* Allocate space and fill struct */ new_item = malloc (sizeof(MenuItem)); if (!new_item) { @@ -150,7 +155,8 @@ MenuItem *menuitem_create_action (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, menu_result); new_item = menuitem_create (MENUITEM_ACTION, id, event_func, text); - new_item->data.action.menu_result = menu_result; + if (new_item != NULL) + new_item->data.action.menu_result = menu_result; return new_item; } @@ -164,8 +170,10 @@ MenuItem *menuitem_create_checkbox (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, allow_gray, value); new_item = menuitem_create (MENUITEM_CHECKBOX, id, event_func, text); - new_item->data.checkbox.allow_gray = allow_gray; - new_item->data.checkbox.value = value; + if (new_item != NULL) { + new_item->data.checkbox.allow_gray = allow_gray; + new_item->data.checkbox.value = value; + } return new_item; } @@ -179,8 +187,10 @@ MenuItem *menuitem_create_ring (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, strings, value); new_item = menuitem_create (MENUITEM_RING, id, event_func, text); - new_item->data.ring.strings = tablist2linkedlist (strings); - new_item->data.ring.value = value; + if (new_item != NULL) { + new_item->data.ring.strings = tablist2linkedlist (strings); + new_item->data.ring.value = value; + } return new_item; } @@ -195,12 +205,14 @@ MenuItem *menuitem_create_slider (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, mintext, maxtext, minvalue, maxvalue, stepsize, value); new_item = menuitem_create (MENUITEM_SLIDER, id, event_func, text); - new_item->data.slider.mintext = strdup (mintext); - new_item->data.slider.maxtext = strdup (maxtext); - new_item->data.slider.minvalue = minvalue; - new_item->data.slider.maxvalue = maxvalue; - new_item->data.slider.stepsize = stepsize; - new_item->data.slider.value = value; + if (new_item != NULL) { + new_item->data.slider.mintext = strdup (mintext); + new_item->data.slider.maxtext = strdup (maxtext); + new_item->data.slider.minvalue = minvalue; + new_item->data.slider.maxvalue = maxvalue; + new_item->data.slider.stepsize = stepsize; + new_item->data.slider.value = value; + } return new_item; } @@ -214,10 +226,12 @@ MenuItem *menuitem_create_numeric (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, minvalue, minvalue, value); new_item = menuitem_create (MENUITEM_NUMERIC, id, event_func, text); - new_item->data.numeric.maxvalue = maxvalue; - new_item->data.numeric.minvalue = minvalue; - new_item->data.numeric.edit_str = malloc (MAX_NUMERIC_LEN); - new_item->data.numeric.value = value; + if (new_item != NULL) { + new_item->data.numeric.maxvalue = maxvalue; + new_item->data.numeric.minvalue = minvalue; + new_item->data.numeric.edit_str = malloc (MAX_NUMERIC_LEN); + new_item->data.numeric.value = value; + } return new_item; } @@ -233,20 +247,22 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func), __FUNCTION__, id, event_func, text, password_char, maxlength, value); new_item = menuitem_create (MENUITEM_ALPHA, id, event_func, text); - new_item->data.alpha.password_char = password_char; - new_item->data.alpha.minlength = minlength; - new_item->data.alpha.maxlength = maxlength; + if (new_item != NULL) { + new_item->data.alpha.password_char = password_char; + new_item->data.alpha.minlength = minlength; + new_item->data.alpha.maxlength = maxlength; - new_item->data.alpha.allow_caps = allow_caps; - new_item->data.alpha.allow_noncaps = allow_noncaps; - new_item->data.alpha.allow_numbers = allow_numbers; - new_item->data.alpha.allowed_extra = strdup (allowed_extra); + new_item->data.alpha.allow_caps = allow_caps; + new_item->data.alpha.allow_noncaps = allow_noncaps; + new_item->data.alpha.allow_numbers = allow_numbers; + new_item->data.alpha.allowed_extra = strdup (allowed_extra); - new_item->data.alpha.value = malloc (maxlength + 1); - strncpy (new_item->data.alpha.value, value, maxlength); - new_item->data.alpha.value[maxlength] = 0; + new_item->data.alpha.value = malloc (maxlength + 1); + strncpy (new_item->data.alpha.value, value, maxlength); + new_item->data.alpha.value[maxlength] = 0; - new_item->data.alpha.edit_str = malloc (maxlength + 1); + new_item->data.alpha.edit_str = malloc (maxlength + 1); + } return new_item; } @@ -254,98 +270,126 @@ MenuItem *menuitem_create_alpha (char *id, MenuEventFunc(*event_func), void menuitem_destroy (MenuItem *item) { - void (*destructor) (MenuItem *); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + if (item != NULL) { + void (*destructor) (MenuItem *); - /* First destroy type specific data */ - destructor = destructor_table[item->type]; - if (destructor) - destructor (item); + /* First destroy type specific data */ + destructor = destructor_table[item->type]; + if (destructor) + destructor (item); - /* Following strings should always be allocated */ - free (item->text); - free (item->id); + /* Following strings should always be allocated */ + free (item->text); + free (item->id); - /* And finally...*/ - free (item); + /* And finally...*/ + free (item); + } } void menuitem_destroy_ring (MenuItem *item) { + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); + + if (item != NULL) { char * s; - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); - - /* deallocate the strings */ - for (s = LL_GetFirst(item->data.ring.strings); s; s = LL_GetNext(item->data.ring.strings)) { - free (s); - } - /* and the list */ - LL_Destroy (item->data.ring.strings); + /* deallocate the strings */ + for (s = LL_GetFirst(item->data.ring.strings); + s != NULL; + s = LL_GetNext(item->data.ring.strings)) { + free (s); + } + /* and the list */ + LL_Destroy (item->data.ring.strings); + } } void menuitem_destroy_slider (MenuItem *item) { - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - /* These strings should always be allocated */ - free (item->data.slider.mintext); - free (item->data.slider.maxtext); + if (item != NULL) { + /* These strings should always be allocated */ + free (item->data.slider.mintext); + free (item->data.slider.maxtext); + } } void menuitem_destroy_numeric (MenuItem *item) { - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - /* This string should always be allocated */ - free (item->data.alpha.edit_str); + if (item != NULL) { + /* This string should always be allocated */ + free (item->data.numeric.edit_str); + } } void menuitem_destroy_alpha (MenuItem *item) { - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - /* These strings should always be allocated */ - free (item->data.alpha.allowed_extra); - free (item->data.alpha.value); - free (item->data.alpha.edit_str); + if (item != NULL) { + /* These strings should always be allocated */ + free (item->data.alpha.allowed_extra); + free (item->data.alpha.value); + free (item->data.alpha.edit_str); + } } /******** MENU ITEM RESET FUNCTIONS ********/ void menuitem_reset (MenuItem *item) { - void (*func) (MenuItem *); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + if (item != NULL) { + void (*func) (MenuItem *); - /* First destroy type specific data */ - func = reset_table[item->type]; - if (func) - func (item); + /* First destroy type specific data */ + func = reset_table[item->type]; + if (func) + func (item); + } } void menuitem_reset_numeric (MenuItem *item) { - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - item->data.numeric.edit_pos = 0; - memset ( item->data.numeric.edit_str, 0, MAX_NUMERIC_LEN); - if (item->data.numeric.minvalue < 0) { - snprintf (item->data.numeric.edit_str, MAX_NUMERIC_LEN, "%+d", item->data.numeric.value); - } else { - snprintf (item->data.numeric.edit_str, MAX_NUMERIC_LEN, "%d", item->data.numeric.value); + if (item != NULL) { + item->data.numeric.edit_pos = 0; + memset ( item->data.numeric.edit_str, 0, MAX_NUMERIC_LEN); + if (item->data.numeric.minvalue < 0) { + snprintf (item->data.numeric.edit_str, MAX_NUMERIC_LEN, + "%+d", item->data.numeric.value); + } else { + snprintf (item->data.numeric.edit_str, MAX_NUMERIC_LEN, + "%d", item->data.numeric.value); + } } } void menuitem_reset_alpha (MenuItem *item) { - debug (RPT_DEBUG, "%s( item=[%s] )", __FUNCTION__, item->id); + debug (RPT_DEBUG, "%s( item=[%s] )", + __FUNCTION__, ((item != NULL) ? item->id : "(null)")); - item->data.alpha.edit_pos = 0; - memset (item->data.alpha.edit_str, 0, item->data.alpha.maxlength+1); - strcpy (item->data.alpha.edit_str, item->data.alpha.value); + if (item != NULL) { + item->data.alpha.edit_pos = 0; + memset (item->data.alpha.edit_str, 0, item->data.alpha.maxlength+1); + strcpy (item->data.alpha.edit_str, item->data.alpha.value); + } } @@ -356,7 +400,9 @@ void menuitem_rebuild_screen (MenuItem *item, Screen *s) Widget * w; void (*build_screen) (MenuItem *item, Screen *s); - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); if (!display_props) { /* Nothing to build if no display size is known */ @@ -364,33 +410,39 @@ void menuitem_rebuild_screen (MenuItem *item, Screen *s) return; } - /* First remove all widgets from the screen */ - while ( (w = screen_getfirst_widget(s)) ) { - /* We know these widgets don't have subwidgets, so we can - * easily remove them - */ - screen_remove_widget (s, w); - widget_destroy (w); - } + if (s != NULL) { + /* First remove all widgets from the screen */ + while ( (w = screen_getfirst_widget(s)) != NULL) { + /* We know these widgets don't have subwidgets, so we can + * easily remove them + */ + screen_remove_widget (s, w); + widget_destroy (w); + } - /* Call type specific screen building function */ - build_screen = build_screen_table [item->type]; - if (build_screen) { - build_screen (item, s); - } else { - report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__); - return; - } + if (item != NULL) { + /* Call type specific screen building function */ + build_screen = build_screen_table [item->type]; + if (build_screen) { + build_screen (item, s); + } else { + report (RPT_ERR, "%s: given menuitem cannot be active", __FUNCTION__); + return; + } - /* Also always call update_screen */ - menuitem_update_screen (item, s); + /* Also always call update_screen */ + menuitem_update_screen (item, s); + } + } } void menuitem_rebuild_screen_slider (MenuItem *item, Screen *s) { Widget * w; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); if (display_props->height >= 2 ) { /* Only add a title if enough space... */ @@ -438,7 +490,9 @@ void menuitem_rebuild_screen_numeric (MenuItem *item, Screen *s) { Widget * w; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); if (display_props->height >= 2 ) { /* Only add a title if enough space... */ @@ -469,7 +523,9 @@ void menuitem_rebuild_screen_alpha (MenuItem *item, Screen *s) { Widget * w; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); if (display_props->height >= 2 ) { /* Only add a title if enough space... */ @@ -502,8 +558,13 @@ void menuitem_update_screen (MenuItem *item, Screen *s) { void (*update_screen) (MenuItem *item, Screen *s); - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); + if ((item == NULL) || (s == NULL)) + return; + /* Disable the cursor by default */ s->cursor = CURSOR_OFF; @@ -522,8 +583,13 @@ void menuitem_update_screen_slider (MenuItem *item, Screen *s) Widget * w; int min_len, max_len; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); + if ((item == NULL) || (s == NULL)) + return; + /* Calculate the bar position and length by filling buffers */ min_len = strlen (item->data.slider.mintext); max_len = strlen (item->data.slider.maxtext); @@ -559,8 +625,13 @@ void menuitem_update_screen_numeric (MenuItem *item, Screen *s) { Widget * w; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); + if ((item == NULL) || (s == NULL)) + return; + w = screen_find_widget (s, "value"); strcpy (w->text, item->data.numeric.edit_str); @@ -580,8 +651,13 @@ void menuitem_update_screen_alpha (MenuItem *item, Screen *s) { Widget * w; - debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, item->id, s->id); + debug (RPT_DEBUG, "%s( item=[%s], screen=[%s] )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), + ((s != NULL) ? s->id : "(null)")); + if ((item == NULL) || (s == NULL)) + return; + w = screen_find_widget (s, "value"); if (item->data.alpha.password_char == 0) { strcpy (w->text, item->data.alpha.edit_str); @@ -608,7 +684,11 @@ MenuResult menuitem_process_input (MenuItem *item, MenuToken token, char * key) { MenuResult (*process_input) (MenuItem *item, MenuToken token, char * key); - debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); + debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), token, key); + + if (item == NULL) + return MENURESULT_ERROR; /* Call type specific screen building function */ process_input = process_input_table [item->type]; @@ -622,7 +702,11 @@ MenuResult menuitem_process_input (MenuItem *item, MenuToken token, char * key) MenuResult menuitem_process_input_slider (MenuItem *item, MenuToken token, char * key) { - debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); + debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), token, key); + + if (item == NULL) + return MENURESULT_ERROR; switch (token) { case MENUTOKEN_MENU: @@ -653,133 +737,131 @@ MenuResult menuitem_process_input_numeric (MenuItem *item, MenuToken token, char char buf1[MAX_NUMERIC_LEN]; char buf2[MAX_NUMERIC_LEN]; - char *format_str; int max_len; - /* To make life easy... */ - char *str = item->data.numeric.edit_str; - int pos = item->data.numeric.edit_pos; - int allow_signed = (item->data.numeric.minvalue < 0); + debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), token, key); - debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); + if (item != NULL) { + /* To make life easy... */ + char *str = item->data.numeric.edit_str; + int pos = item->data.numeric.edit_pos; + int allow_signed = (item->data.numeric.minvalue < 0); + char *format_str = (allow_signed) ? "%+d" : "%d"; - if (allow_signed) { - format_str = "%+d"; - } else { - format_str = "%d"; - } - snprintf (buf1, MAX_NUMERIC_LEN, format_str, item->data.numeric.minvalue); - snprintf (buf2, MAX_NUMERIC_LEN, format_str, item->data.numeric.maxvalue); + snprintf (buf1, MAX_NUMERIC_LEN, format_str, item->data.numeric.minvalue); + snprintf (buf2, MAX_NUMERIC_LEN, format_str, item->data.numeric.maxvalue); - max_len = max (strlen(buf1), strlen(buf2)); + max_len = max (strlen(buf1), strlen(buf2)); - /* Clear the error */ - item->data.numeric.error_code = 0; + /* Clear the error */ + item->data.numeric.error_code = 0; - switch (token) { - case MENUTOKEN_MENU: - if (pos == 0) { - return MENURESULT_CLOSE; - } - else { - /* Reset data */ - item->data.numeric.edit_pos = 0; - memset (str, 0, MAX_NUMERIC_LEN); - snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value); - } - return MENURESULT_NONE; - case MENUTOKEN_ENTER: - if (str[pos] == 0) { - int value; - /* The user completed his input */ - - /* ...scan it */ - if (sscanf (str, "%d", &value) != 1) { - return MENURESULT_ERROR; + switch (token) { + case MENUTOKEN_MENU: + if (pos == 0) { + return MENURESULT_CLOSE; } - /* Test the value */ - if (value < item->data.numeric.minvalue - || value > item->data.numeric.maxvalue) { - /* Out of range ! - * We can't exit this screen now - */ - item->data.numeric.error_code = 1; + else { + /* Reset data */ + item->data.numeric.edit_pos = 0; + memset (str, 0, MAX_NUMERIC_LEN); + snprintf (str, MAX_NUMERIC_LEN, format_str, item->data.numeric.value); + } + return MENURESULT_NONE; + case MENUTOKEN_ENTER: + if (str[pos] == '\0') { + int value; + /* The user completed his input */ + + /* ...scan it */ + if (sscanf (str, "%d", &value) != 1) { + return MENURESULT_ERROR; + } + /* Test the value */ + if (value < item->data.numeric.minvalue + || value > item->data.numeric.maxvalue) { + /* Out of range ! + * We can't exit this screen now + */ + item->data.numeric.error_code = 1; + item->data.numeric.edit_pos = 0; + return MENURESULT_NONE; + } + + /* OK, store value */ + item->data.numeric.value = value; + + /* Inform client */ + if (item->event_func) + item->event_func (item, MENUEVENT_UPDATE); + + return MENURESULT_CLOSE; + } + else { + /* The user wants to go to next digit */ + if (pos < max_len) { + item->data.numeric.edit_pos ++; + } + } + return MENURESULT_NONE; + case MENUTOKEN_UP: + if (pos >= max_len) { + /* We're not allowed to add anything anymore */ + item->data.numeric.error_code = 2; item->data.numeric.edit_pos = 0; return MENURESULT_NONE; } - - /* OK, store value */ - item->data.numeric.value = value; - - /* Inform client */ - if (item->event_func) - item->event_func (item, MENUEVENT_UPDATE); - - return MENURESULT_CLOSE; - } - else { - /* The user wants to go to next digit */ - if (pos < max_len) { + if (allow_signed && pos == 0) { + /* make negative */ + str[0] = (str[0] == '-') ? '+' : '-'; + } + else { + if (str[pos] >= '0' && str[pos] < '9') { + str[pos] ++; + } else if (str[pos] == '9') { + str[pos] = 0; + } else if (str[pos] == 0) { + str[pos] = '0'; + } + } + return MENURESULT_NONE; + case MENUTOKEN_DOWN: + if (pos >= max_len) { + /* We're not allowed to add anything anymore */ + item->data.numeric.error_code = 2; + item->data.numeric.edit_pos = 0; + return MENURESULT_NONE; + } + if (allow_signed && pos == 0) { + /* make negative */ + str[0] = (str[0] == '-') ? '+' : '-'; + } + else { + if (str[pos] > '0' && str[pos] <= '9') { + str[pos] --; + } else if (str[pos] == '0') { + str[pos] = 0; + } else if (str[pos] == 0) { + str[pos] = '9'; + } + } + return MENURESULT_NONE; + case MENUTOKEN_OTHER: + if (pos >= max_len) { + /* We're not allowed to add anything anymore */ + item->data.numeric.error_code = 2; + item->data.numeric.edit_pos = 0; + return MENURESULT_NONE; + } + /* process numeric keys */ + if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') { + str[pos] = key[0]; item->data.numeric.edit_pos ++; } - } - return MENURESULT_NONE; - case MENUTOKEN_UP: - if (pos >= max_len) { - /* We're not allowed to add anything anymore */ - item->data.numeric.error_code = 2; - item->data.numeric.edit_pos = 0; return MENURESULT_NONE; } - if (allow_signed && pos == 0) { - /* make negative */ - str[0] = (str[0] == '-') ? '+' : '-'; - } - else { - if (str[pos] >= '0' && str[pos] < '9') { - str[pos] ++; - } else if (str[pos] == '9') { - str[pos] = 0; - } else if (str[pos] == 0) { - str[pos] = '0'; - } - } - return MENURESULT_NONE; - case MENUTOKEN_DOWN: - if (pos >= max_len) { - /* We're not allowed to add anything anymore */ - item->data.numeric.error_code = 2; - item->data.numeric.edit_pos = 0; - return MENURESULT_NONE; - } - if (allow_signed && pos == 0) { - /* make negative */ - str[0] = (str[0] == '-') ? '+' : '-'; - } - else { - if (str[pos] > '0' && str[pos] <= '9') { - str[pos] --; - } else if (str[pos] == '0') { - str[pos] = 0; - } else if (str[pos] == 0) { - str[pos] = '9'; - } - } - return MENURESULT_NONE; - case MENUTOKEN_OTHER: - if (pos >= max_len) { - /* We're not allowed to add anything anymore */ - item->data.numeric.error_code = 2; - item->data.numeric.edit_pos = 0; - return MENURESULT_NONE; - } - /* proces numeric keys */ - if ( strlen(key) == 1 && key[0] >= '0' && key[0] <= '9') { - str[pos] = key[0]; - item->data.numeric.edit_pos ++; - } - return MENURESULT_NONE; - } + } return MENURESULT_ERROR; } @@ -788,161 +870,170 @@ MenuResult menuitem_process_input_alpha (MenuItem *item, MenuToken token, char * char * p; static char * chars = NULL; - /* To make life easy... */ - char *str = item->data.alpha.edit_str; - int pos = item->data.alpha.edit_pos; + debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, + ((item != NULL) ? item->id : "(null)"), token, key); - debug (RPT_DEBUG, "%s( item=[%s], token=%d, key=\"%s\" )", __FUNCTION__, item->id, token, key); + if (item != NULL) { + /* To make life easy... */ + char *str = item->data.alpha.edit_str; + int pos = item->data.alpha.edit_pos; - /* Create list of allowed chars */ - chars = realloc (chars, 26 + 26 + 10 + strlen(item->data.alpha.allowed_extra) + 1); - chars[0] = 0; /* clear string */ - if (item->data.alpha.allow_caps) - strcat (chars, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - if (item->data.alpha.allow_noncaps) - strcat (chars, "abcdefghijklmnopqrstuvwxyz"); - if (item->data.alpha.allow_numbers) - strcat (chars, "0123456789"); - strcat (chars, item->data.alpha.allowed_extra); + /* Create list of allowed chars */ + chars = realloc (chars, 26 + 26 + 10 + strlen(item->data.alpha.allowed_extra) + 1); + chars[0] = 0; /* clear string */ + if (item->data.alpha.allow_caps) + strcat (chars, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (item->data.alpha.allow_noncaps) + strcat (chars, "abcdefghijklmnopqrstuvwxyz"); + if (item->data.alpha.allow_numbers) + strcat (chars, "0123456789"); + strcat (chars, item->data.alpha.allowed_extra); - /* Clear the error */ - item->data.alpha.error_code = 0; + /* Clear the error */ + item->data.alpha.error_code = 0; - switch (token) { - case MENUTOKEN_MENU: - if (pos == 0) { - return MENURESULT_CLOSE; - } - else { - /* Reset data */ - item->data.alpha.edit_pos = 0; - memset (str, 0, item->data.alpha.maxlength+1); - strcpy (str, item->data.alpha.value); - } - return MENURESULT_NONE; - case MENUTOKEN_ENTER: - if (str[item->data.alpha.edit_pos] == 0) { - /* The user completed his input */ + switch (token) { + case MENUTOKEN_MENU: + if (pos == 0) { + return MENURESULT_CLOSE; + } + else { + /* Reset data */ + item->data.alpha.edit_pos = 0; + memset (str, 0, item->data.alpha.maxlength+1); + strcpy (str, item->data.alpha.value); + } + return MENURESULT_NONE; + case MENUTOKEN_ENTER: + if (str[item->data.alpha.edit_pos] == 0) { + /* The user completed his input */ - /* It's not too short ? */ - if (strlen (item->data.alpha.edit_str) < item->data.alpha.minlength) { - item->data.alpha.error_code = 3; + /* It's not too short ? */ + if (strlen (item->data.alpha.edit_str) < item->data.alpha.minlength) { + item->data.alpha.error_code = 3; + return MENURESULT_NONE; + } + + /* Store value */ + strcpy (item->data.alpha.value, item->data.alpha.edit_str); + + /* Inform client */ + if (item->event_func) + item->event_func (item, MENUEVENT_UPDATE); + + return MENURESULT_CLOSE; + } + else { + /* The user wants to go to next digit */ + if (pos < item->data.alpha.maxlength) { + item->data.alpha.edit_pos ++; + } + } + return MENURESULT_NONE; + case MENUTOKEN_UP: + if (pos >= item->data.alpha.maxlength) { + /* We're not allowed to add anything anymore */ + item->data.alpha.error_code = 2; + item->data.numeric.edit_pos = 0; return MENURESULT_NONE; } - - /* Store value */ - strcpy (item->data.alpha.value, item->data.alpha.edit_str); - - /* Inform client */ - if (item->event_func) - item->event_func (item, MENUEVENT_UPDATE); - - return MENURESULT_CLOSE; - } - else { - /* The user wants to go to next digit */ - if (pos < item->data.alpha.maxlength) { + if (str[pos] == 0) { + /* User goes past EOL */ + str[pos] = chars[0]; + } else { + /* We should have a symbol from our list */ + p = strchr (chars, str[pos]); + if (p != NULL) { + str[pos] = * (++p); /* next symbol on list */ + /* Might be 0 now */ + } else { + str[pos] = 0; + } + } + return MENURESULT_NONE; + case MENUTOKEN_DOWN: + if (pos >= item->data.alpha.maxlength) { + /* We're not allowed to add anything anymore */ + item->data.alpha.error_code = 2; + item->data.numeric.edit_pos = 0; + return MENURESULT_NONE; + } + if (str[pos] == 0) { + /* User goes past EOL */ + str[pos] = chars[strlen(chars)-1]; + } else { + /* We should have a symbol from our list */ + p = strchr (chars, str[pos]); + if (p != NULL) { + if (p == chars) { + str[pos] = 0; /* Go to EOL */ + } else { + str[pos] = * (--p); /* next symbol on list */ + } + } else { + str[pos] = 0; + } + } + return MENURESULT_NONE; + case MENUTOKEN_OTHER: + if (pos >= item->data.alpha.maxlength) { + /* We're not allowed to add anything anymore */ + item->data.alpha.error_code = 2; + item->data.numeric.edit_pos = 0; + return MENURESULT_NONE; + } + /* proces other keys */ + if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') { + str[pos] = key[0]; item->data.alpha.edit_pos ++; } - } - return MENURESULT_NONE; - case MENUTOKEN_UP: - if (pos >= item->data.alpha.maxlength) { - /* We're not allowed to add anything anymore */ - item->data.alpha.error_code = 2; - item->data.numeric.edit_pos = 0; return MENURESULT_NONE; - } - if (str[pos] == 0) { - /* User goes past EOL */ - str[pos] = chars[0]; - } else { - /* We should have a symbol from our list */ - p = strchr (chars, str[pos]); - if (p != NULL) { - str[pos] = * (++p); /* next symbol on list */ - /* Might be 0 now */ - } else { - str[pos] = 0; - } - } - return MENURESULT_NONE; - case MENUTOKEN_DOWN: - if (pos >= item->data.alpha.maxlength) { - /* We're not allowed to add anything anymore */ - item->data.alpha.error_code = 2; - item->data.numeric.edit_pos = 0; - return MENURESULT_NONE; - } - if (str[pos] == 0) { - /* User goes past EOL */ - str[pos] = chars[strlen(chars)-1]; - } else { - /* We should have a symbol from our list */ - p = strchr (chars, str[pos]); - if (p != NULL) { - if (p == chars) { - str[pos] = 0; /* Go to EOL */ - } else { - str[pos] = * (--p); /* next symbol on list */ - } - } else { - str[pos] = 0; - } - } - return MENURESULT_NONE; - case MENUTOKEN_OTHER: - if (pos >= item->data.alpha.maxlength) { - /* We're not allowed to add anything anymore */ - item->data.alpha.error_code = 2; - item->data.numeric.edit_pos = 0; - return MENURESULT_NONE; - } - /* proces other keys */ - if ( strlen(key) == 1 && key[0] >= ' ' && key[0] <= 'Z') { - str[pos] = key[0]; - item->data.alpha.edit_pos ++; - } - return MENURESULT_NONE; + } } return MENURESULT_ERROR; } LinkedList * tablist2linkedlist (char *strings) { - char *tabptr, *p, *new_s; LinkedList * list; list = LL_new(); /* Parse strings */ - p = strings; - while ((tabptr = strchr(p, '\t')) != NULL) { - int len = (int)(tabptr - p); + if (strings != NULL) { + char *p = strings; + char *tabptr, *new_s; + + while ((tabptr = strchr(p, '\t')) != NULL) { + int len = (int)(tabptr - p); - /* Alloc and copy substring */ - new_s = malloc (len + 1); - strncpy (new_s, p, len); - new_s[len] = 0; + /* Alloc and copy substring */ + new_s = malloc (len + 1); + strncpy (new_s, p, len); + new_s[len] = 0; + LL_Push (list, new_s); + + /* Go to next string */ + p = tabptr + 1; + } + /* Add last string */ + new_s = strdup (p); LL_Push (list, new_s); - - /* Go to next string */ - p = tabptr + 1; - } - /* Add last string */ - new_s = strdup (p); - LL_Push (list, new_s); + } return list; } MenuItemType menuitem_typename_to_type (char *name) { - MenuItemType type; - for (type = 0; type < NUM_ITEMTYPES; type ++) { - if (strcmp (menuitemtypenames[type], name) == 0) { - return type; + if (name != NULL) { + MenuItemType type; + + for (type = 0; type < NUM_ITEMTYPES; type ++) { + if (strcmp (menuitemtypenames[type], name) == 0) { + return type; + } } } return -1; @@ -950,20 +1041,20 @@ MenuItemType menuitem_typename_to_type (char *name) char *menuitem_type_to_typename (MenuItemType type) { - if (type >= 0 && type < NUM_ITEMTYPES) { - return menuitemtypenames[type]; - } - else { - return NULL; - } + return ((type >= 0 && type < NUM_ITEMTYPES) + ? menuitemtypenames[type] + : NULL); } MenuEventType menuitem_eventtypename_to_eventtype (char *name) { - MenuEventType type; - for (type = 0; type < NUM_EVENTTYPES; type ++) { - if (strcmp (menueventtypenames[type], name) == 0) { - return type; + if (name != NULL) { + MenuEventType type; + + for (type = 0; type < NUM_EVENTTYPES; type ++) { + if (strcmp (menueventtypenames[type], name) == 0) { + return type; + } } } return -1; @@ -971,11 +1062,8 @@ MenuEventType menuitem_eventtypename_to_eventtype (char *name) char *menuitem_eventtype_to_eventtypename (MenuEventType type) { - if (type >= 0 && type < NUM_EVENTTYPES) { - return menueventtypenames[type]; - } - else { - return NULL; - } + return ((type >= 0 && type < NUM_EVENTTYPES) + ? menueventtypenames[type] + : NULL); } diff --git a/server/screen.h b/server/screen.h index fcf4849..8fef2c9 100644 --- a/server/screen.h +++ b/server/screen.h @@ -65,12 +65,16 @@ int screen_remove_widget (Screen * s, Widget * w); /* List functions */ static inline Widget * screen_getfirst_widget (Screen * s) { - return LL_GetFirst(s->widgetlist); + return (Widget *) ((s != NULL) + ? LL_GetFirst(s->widgetlist) + : NULL); } static inline Widget * screen_getnext_widget (Screen * s) { - return LL_GetNext(s->widgetlist); + return (Widget *) ((s != NULL) + ? LL_GetNext(s->widgetlist) + : NULL); }