From a22c4aff0e5649fa22bbb4b7fda9433d7a8c44de Mon Sep 17 00:00:00 2001 From: Murali Krishnan Ganapathy Date: Fri, 16 Dec 2005 16:25:49 -0600 Subject: [PATCH] advanced menu patch Python code to generate C code from ini-like file format and changes to libmenu to accomodate a one pass parser. Diff is against 3.20-pre3 - Murali --- menu/CHANGES | 8 ++++++ menu/MANUAL | 41 ++++++++++++++++++++++--------- menu/Makefile | 11 +++++++-- menu/README | 8 ++++-- menu/libmenu/menu.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++ menu/libmenu/menu.h | 28 +++++++++------------ menu/simple.c | 23 +++++++++--------- 7 files changed, 146 insertions(+), 43 deletions(-) diff --git a/menu/CHANGES b/menu/CHANGES index 3998f1b..da7fc90 100644 --- a/menu/CHANGES +++ b/menu/CHANGES @@ -1,3 +1,11 @@ +Changes in v1.2 +--------------- +* Allowed menu's to have names. Submenu's can be referred to by names instead + of their index in the menu system. This allows user to refer to submenus + which are not yet part of the menusystem. +* menugen.py: Python script for converting menu's specified in a given format + to corresponding C source code + Changes in v1.1 --------------- * Additional handler type: Keys handler diff --git a/menu/MANUAL b/menu/MANUAL index 50652fb..df8a4db 100644 --- a/menu/MANUAL +++ b/menu/MANUAL @@ -65,13 +65,10 @@ should appear in the menu. An example is given below. CHECKED = 1; add_item("option1","Status 1",OPT_RUN,"kernel1 arg1=val1",0); add_item("selfloop","Status 2",OPT_SUBMENU,NULL,MAINMENU); + add_item("othermenu","Status 3",OPT_SUBMENU,"menuname",0); add_sep(); add_item("checkbox,"Checkbox Info",OPT_CHECKBOX,NULL,CHECKED); add_item("Exit ","Status String",OPT_EXITMENU,NULL,0); - // "any string" not used by the menu system, useful for storing kernel names - // NUM = index of submenu if OPT_SUBMENU, - // 0/1 default checked state if OPT_CHECKBOX - // unused otherwise. The call to add_menu has two arguments, the first being the title of @@ -79,8 +76,17 @@ the menu and the second an upper bound on the number of items in the menu. Putting a -1, will use the default (see MENUSIZE in menu.h). If you try to add more items than specified, the extra items will not appear in the menu. The accuracy of this number affects the memory required -to run the system. Currently the code compiles to a .COM file which -has a 64K limit on memory used. +to run the system. + +If you do not want to keep track of the return values, you can also use +the following variant of add_menu + + +add_named_menu("main"," Menu Title ",-1) + + +This creates a new menu as before and gives it a name "main". When using named +menus, you get an alternate way for adding submenu's. See below for details. The call to add_item has five arguments. The first argument is the text which appears in the menu itself. @@ -100,16 +106,28 @@ the following * OPT_INACTIVE : A disabled item (user cannot select this) * OPT_INVISIBLE: This item will not be displayed. -The fourth argument is the value of the data field. This pointer is just -stored. In case of a radiomenu this points to the menuitem chosen (Dont -forget to typecase this pointer to (t_menuitem *) when reading this info). +The fourth argument is the value of the data field always a string. +Usually this string is just copied and nothing is done with it. Two +cases, where it is used. + +In case of a radiomenu the input string is ignored and the "data" field +points to the menuitem chosen (Dont forget to typecast this pointer to +(t_menuitem *) when reading this info). + +In case of a submenu, this string if non-trivial is interpreted as the +name of the submenu which should be linked there. This interpretation +happens when the menu is first run and not when the menu system is being +created. This allows the user to create the menusystem in an arbitrary +order. + The fifth argument is a number whose meaning depends on the type of the item. For a CHECKBOX it should be 0/1 setting the initial state of the checkbox. For a SUBMENU it should be the index of the menu which should -be displayed if this option is chosen. For a RADIOMENU it should be the +be displayed if this option is chosen. Incase the data field is non-trivial, +this number is ignored and computed later. For a RADIOMENU it should be the index of the menu which contains all the options (All items in that menu -should not of type RADIOITEM are ignored). For all other types, this +not of type RADIOITEM are ignored). For all other types, this argument has no meaning at all. A call to add_sep is a convenient shorthand for calling add_item @@ -123,6 +141,7 @@ item which was selected by the user. choice = showmenus(MAIN); // Initial menu is the one with index MAIN + // or choice = showmenus(find_menu_num("main")); // Initial menu is the one named "main" 1.4 Processing the result diff --git a/menu/Makefile b/menu/Makefile index ea75350..102b7af 100644 --- a/menu/Makefile +++ b/menu/Makefile @@ -39,9 +39,16 @@ LIBS = libmenu/libmenu.a $(LUDIR)/libutil_com.a $(LDIR)/libcom32.a $(LIBGCC) LIBMENU = libmenu/syslnx.o libmenu/com32io.o libmenu/tui.o \ libmenu/menu.o libmenu/passwords.o libmenu/des.o libmenu/help.o -MENUS = $(patsubst %.c,%.c32,$(wildcard *.c)) +CMENUS = $(patsubst %.c,%.c32,$(wildcard *.c)) +IMENUS = $(patsubst %.menu,%.c32,$(wildcard *.menu)) -.SUFFIXES: .S .c .o .elf .c32 +MENUS = $(CMENUS) $(IMENUS) + +.SUFFIXES: .S .c .o .elf .c32 .menu + +.PRECIOUS: %.c +%.c: %.menu + python menugen.py $< $@ .PRECIOUS: %.o %.o: %.S diff --git a/menu/README b/menu/README index 66116e9..aa979ed 100644 --- a/menu/README +++ b/menu/README @@ -8,8 +8,12 @@ original author. To configure the menus, you need to set up a menu configuration file to have the menu items you desire, then build the menu system using make. You can use either simple.c or complex.c as a starting point -for your own menu configuration file; then add the name with a .c32 -extension to the MENUS list in the Makefile. +for your own menu configuration file; If your menu system is only going +to have entries corresponding to things which can be executed directly, +then you can create a file in ".menu" format instead of the C code. + +NOTE: ".menu" files can only describe the very basic type of menus +See MENU_FORMAT for the syntax of .menu files The resulting code is a 32-bit COMBOOT code, and hence can be executed only under syslinux. You can use tools like bochs to help debug your diff --git a/menu/libmenu/menu.c b/menu/libmenu/menu.c index 7d7e76d..75a8d72 100644 --- a/menu/libmenu/menu.c +++ b/menu/libmenu/menu.c @@ -652,6 +652,44 @@ pt_menuitem runmenusystem(uchar top, uchar left, pt_menu cmenu, uchar startopt, } } +// Finds the indexof the menu with given name +uchar find_menu_num(const char *name) +{ + int i; + pt_menu m; + + if (name == NULL) return (uchar)(-1); + for (i=0; i < ms->nummenus; i++) + { + m = ms->menus[i]; + if ((m->name) && (strcmp(m->name,name)==0)) return i; + } + return (uchar)(-1); +} + +// Run through all items and if they are submenus +// with a non-trivial "action" and trivial submenunum +// replace submenunum with the menu with name "action" +void fix_submenus() +{ + int i,j; + pt_menu m; + pt_menuitem mi; + + i = 0; + for (i=0; i < ms->nummenus; i++) + { + m = ms->menus[i]; + for (j=0; j < m->numitems; j++) + { + mi = m->items[j]; + // if submenu with non-trivial data string + if ( (mi->action == OPT_SUBMENU) && (mi->data) ) + mi->itemdata.submenunum = find_menu_num (mi->data); + } + } +} + /* User Callable functions */ pt_menuitem showmenus(uchar startmenu) @@ -659,6 +697,8 @@ pt_menuitem showmenus(uchar startmenu) pt_menuitem rv; uchar oldpage,tpos; + fix_submenus(); // Fix submenu numbers incase nick names were used + // Setup screen for menusystem oldpage = getdisppage(); setdisppage(ms->menupage); @@ -673,6 +713,7 @@ pt_menuitem showmenus(uchar startmenu) cursoroff(); // Doesn't seem to work? + // Go, main menu cannot be a radio menu rv = runmenusystem(ms->minrow+MENUROW, ms->mincol+MENUCOL, ms->menus[(unsigned int)startmenu], 0, NORMALMENU); @@ -983,6 +1024,7 @@ uchar add_menu(const char *title, int maxmenusize) if (m == NULL) return -1; ms->menus[num] = m; m->numitems = 0; + m->name = NULL; m->row = 0xFF; m->col = 0xFF; if (maxmenusize < 1) @@ -1004,6 +1046,32 @@ uchar add_menu(const char *title, int maxmenusize) return ms->nummenus - 1; } +void set_menu_name(const char *name) // Set the "name" of this menu +{ + pt_menu m; + + m = ms->menus[ms->nummenus-1]; + if (m->name) // Free up previous name + { + free(m->name); + m -> name = NULL; + } + + if (name) + { + m->name = (char *)malloc(strlen(name)+1); + strcpy(m->name,name); + } +} + +// Create a new named menu and return its position +uchar add_named_menu(const char * name, const char *title, int maxmenusize) +{ + add_menu(title,maxmenusize); + set_menu_name(name); + return ms->nummenus - 1; +} + void set_menu_pos(uchar row,uchar col) // Set the position of this menu. { pt_menu m; @@ -1118,6 +1186,7 @@ pt_menuitem add_item(const char *item, const char *status, t_action action, break; case OPT_RADIOMENU: mi->itemdata.radiomenunum = itemdata; + if (mi->data) free(mi->data); mi->data = NULL; // No selection made break; default: // to keep the compiler happy @@ -1146,3 +1215,4 @@ void set_item_options(uchar shortcut,int helpid) void close_menusystem(void) { } + diff --git a/menu/libmenu/menu.h b/menu/libmenu/menu.h index 1e0a619..a6fae5d 100644 --- a/menu/libmenu/menu.h +++ b/menu/libmenu/menu.h @@ -155,6 +155,7 @@ typedef struct s_menuitem { char *status; char *data; // string containing kernel to run.. but... // for radio menu's this is a pointer to the item selected or NULL (initially) + // for submenu's this string could be name of menu void * extra_data; // Any other data user can point to t_item_handler handler; // Pointer to function of type menufn t_action action; @@ -169,7 +170,8 @@ typedef t_menuitem *pt_menuitem; // Pointer to type menuitem typedef struct s_menu { pt_menuitem *items; // pointer to array of pointer to menuitems - char *title; + char *title; // Title string for menu + char *name; // menu can be referred to by this string int maxmenusize; // the size of array allocated uchar numitems; // how many items do we actually have uchar menuwidth; @@ -215,25 +217,10 @@ typedef struct s_menusystem { typedef t_menusystem *pt_menusystem; // Pointer to type menusystem -/************************************************************************ - * IMPORTANT INFORMATION - * - * All functions which take a string as argument store the pointer - * for later use. So if you have alloc'ed a space for the string - * and are passing it to any of these functions, DO NOT deallocate it. - * - * If they are constant strings, you may receive warning from the compiler - * about "converting from char const * to char *". Ignore these errors. - * - * This hack/trick of storing these pointers will help in reducing the size - * of the internal structures by a lot. - * - *************************************************************************** - */ - pt_menuitem showmenus(uchar startmenu); pt_menusystem init_menusystem(const char *title); + void close_menusystem(); // Deallocate memory used void set_normal_attr(uchar normal, uchar selected, uchar inactivenormal, uchar inactiveselected); @@ -261,9 +248,16 @@ void reg_ontimeout(t_timeout_handler, unsigned int numsteps, unsigned int stepsi // So stepsize=0 means numsteps is measured in centiseconds. void unreg_ontimeout(); +// Find the number of the menu given the name +// Returns -1 if not found +uchar find_menu_num(const char *name); + // Create a new menu and return its position uchar add_menu(const char *title, int maxmenusize); +// Create a named menu and return its position +uchar add_named_menu(const char *name, const char *title, int maxmenusize); + void set_menu_pos(uchar row,uchar col); // Set the position of this menu. // Add item to the "current" menu diff --git a/menu/simple.c b/menu/simple.c index 2458909..8277c5e 100644 --- a/menu/simple.c +++ b/menu/simple.c @@ -22,8 +22,6 @@ int main(void) { t_menuitem * curr; - char TESTING,RESCUE,MAIN; /* The menus we're going to declare */ - // Change the video mode here // setvideomode(0) @@ -38,32 +36,35 @@ int main(void) //set_title_info (-1,-1); //set_misc_info(-1,-1,-1,-1); - // menuindex = add_menu(" Menu Title ",-1); + // menuindex = add_named_menu("name"," Menu Title ",-1); // add_item("Item string","Status String",TYPE,"any string",NUM) // TYPE = OPT_RUN | OPT_EXITMENU | OPT_SUBMENU | OPT_CHECKBOX | OPT_INACTIVE - // "any string" not used by the menu system, useful for storing kernel names + // "any string" useful for storing kernel names + // In case of OPT_SUBMENU, "any string" can be set to "name" of menu to be linked + // in which case value NUM is ignored // NUM = index of submenu if OPT_SUBMENU, // 0/1 default checked state if OPT_CHECKBOX // unused otherwise. - TESTING = add_menu(" Testing ",-1); - add_item("Self Loop","Go to testing",OPT_SUBMENU,NULL,TESTING); + add_named_menu("testing"," Testing ",-1); + add_item("Self Loop","Go to testing",OPT_SUBMENU,"testing",0); add_item("Memory Test","Perform extensive memory testing",OPT_RUN, "memtest",0); add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0); - RESCUE = add_menu(" Rescue Options ",-1); + add_named_menu("rescue"," Rescue Options ",-1); add_item("Linux Rescue","linresc",OPT_RUN,"linresc",0); add_item("Dos Rescue","dosresc",OPT_RUN,"dosresc",0); add_item("Windows Rescue","winresc",OPT_RUN,"winresc",0); add_item("Exit this menu","Go one level up",OPT_EXITMENU,"exit",0); - MAIN = add_menu(" Main Menu ",-1); + add_named_menu("main"," Main Menu ",-1); add_item("Prepare","prep",OPT_RUN,"prep",0); - add_item("Rescue options...","Troubleshoot a system",OPT_SUBMENU,NULL,RESCUE); - add_item("Testing...","Options to test hardware",OPT_SUBMENU,NULL,TESTING); + add_item("Rescue options...","Troubleshoot a system",OPT_SUBMENU,"rescue",0); + add_item("Testing...","Options to test hardware",OPT_SUBMENU,"testing",0); add_item("Exit to prompt", "Exit the menu system", OPT_EXITMENU, "exit", 0); - curr = showmenus(MAIN); // Initial menu is the one with index MAIN + curr = showmenus(find_menu_num("main")); // Initial menu is the one called "main" + if (curr) { if (curr->action == OPT_RUN) -- 2.7.4