From adaeace414f19e610fa8b9bfa43a28046c60f8ec Mon Sep 17 00:00:00 2001 From: hpa Date: Fri, 6 Feb 2004 04:39:12 +0000 Subject: [PATCH] Menu upgrades from Murali. --- menu/complex.c | 4 ++ menu/menu.c | 133 +++++++++++++++++++++++++++++++++++++-------------------- menu/menu.h | 76 ++++++++++++++++++++++----------- 3 files changed, 142 insertions(+), 71 deletions(-) diff --git a/menu/complex.c b/menu/complex.c index fd2ef1c..9496347 100644 --- a/menu/complex.c +++ b/menu/complex.c @@ -152,11 +152,15 @@ int menumain(char *cmdline) PREP = add_menu(" Prep options "); baseurl = add_item("baseurl by IP?","Specify gui baseurl by IP address",OPT_CHECKBOX,"baseurl",0); mountcd = add_item("mountcd?","Mount the cdrom drive?",OPT_CHECKBOX,"mountcd",0); + add_sep(); network = add_item("network?","Try to initialise network device?",OPT_CHECKBOX,"network",1); dhcp = add_item("dhcp?","Use dhcp to get ipaddr?",OPT_CHECKBOX,"dhcp",1); + add_sep(); winrep = add_item("Reinstall windows","Re-install the windows side of a dual boot setup",OPT_CHECKBOX,"winrepair",0); linrep = add_item("Reinstall linux","Re-install the linux side of a dual boot setup",OPT_CHECKBOX,"linrepair",0); + add_sep(); runprep = add_item("Run prep now","Execute prep with the above options",OPT_RUN,"prep",0); + add_item("Exit this menu","Go up one level",OPT_EXITMENU,"exitmenu",0); baseurl->handler = &checkbox_handler; mountcd->handler = &checkbox_handler; network->handler = &checkbox_handler; diff --git a/menu/menu.c b/menu/menu.c index 5a865a2..763ae93 100644 --- a/menu/menu.c +++ b/menu/menu.c @@ -20,10 +20,14 @@ #include "string.h" #include "menu.h" -// Structures - -// Declare a menusystem here +// Local Variables static t_menusystem menusystem; +static char TITLESTR[] = "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy"; +static char TITLELONG[] = " TITLE too long "; +static char ITEMLONG[] = " ITEM too long "; +static char ACTIONLONG[] = " ACTION too long "; +static char STATUSLONG[] = " STATUS too long "; +static char EMPTYSTR[] = ""; /* Basic Menu routines */ @@ -60,39 +64,58 @@ void printmenu(t_menu * menu, int curr, char top, char left) int x; int numitems,menuwidth; t_menusystem *ms; - char attr; + char fchar[5],lchar[5]; // The first and last char in for each entry + const char *str; // and inbetween the item or a seperator is printed + char attr; // all in the attribute attr + char sep[MENULEN];// and inbetween the item or a seperator is printed ms = & menusystem; numitems = menu->numitems; - menuwidth = menu->menuwidth+2; - clearwindow(top,left-1,top+numitems+1,left+menuwidth+1,ms->menupage,ms->fillchar,ms->shadowattr); - drawbox(top-1,left-2,top+numitems,left+menuwidth,ms->normalattr,ms->menupage); + menuwidth = menu->menuwidth+3; + clearwindow(top,left-2,top+numitems+1,left+menuwidth+1,ms->menupage,ms->fillchar,ms->shadowattr); + drawbox(top-1,left-3,top+numitems,left+menuwidth,ms->normalattr,ms->menupage); + memset(sep,HORIZ,menuwidth); // String containing the seperator string + sep[menuwidth-1] = 0; // Menu title x = (menuwidth - strlen(menu->title) - 1) >> 1; gotoxy(top-1,left+x,ms->menupage); csprint(menu->title); for (x=0; x < numitems; x++) { - gotoxy(top+x,left-1,ms->menupage); - if (menu->items[x].action == OPT_INACTIVE) + // Setup the defaults now + lchar[0] = fchar[0] = ' '; + lchar[1] = fchar[1] = '\0'; // fchar and lchar are just spaces + str = menu->items[x].item; // Pointer to item string + attr = (x==curr ? ms->reverseattr : ms->normalattr); // Normal attributes + switch (menu->items[x].action) // set up attr,str,fchar,lchar for everything { - attr = (x==curr? ms->revinactattr : ms->inactattr); - } else { - attr = (x==curr ? ms->reverseattr : ms->normalattr); + case OPT_INACTIVE: + attr = (x==curr? ms->revinactattr : ms->inactattr); + break; + case OPT_SUBMENU: + lchar[0] = SUBMENUCHAR; lchar[1] = 0; + break; + case OPT_CHECKBOX: + lchar[0] = (menu->items[x].itemdata.checked ? CHECKED : UNCHECKED); + lchar[1] = 0; + break; + case OPT_SEP: + fchar[0] = '\b'; fchar[1] = LTRT; fchar[2] = HORIZ; fchar[3] = HORIZ; fchar[4] = 0; + lchar[0] = HORIZ; lchar[1] = RTLT; lchar[3] = 0; + str = sep; + break; + case OPT_EXITMENU: + fchar[0] = EXITMENUCHAR; fchar[1] = 0; + //default: } - cprint(ms->spacechar,attr,menuwidth+1,ms->menupage); + gotoxy(top+x,left-2,ms->menupage); + cprint(ms->spacechar,attr,menuwidth+2,ms->menupage); // Wipe area with spaces + gotoxy(top+x,left-2,ms->menupage); + csprint(fchar); // Print first part gotoxy(top+x,left,ms->menupage); - csprint(menu->items[x].item); + csprint(str); // Print main part gotoxy(top+x,left+menuwidth-1,ms->menupage); // Last char if any - switch (menu->items[x].action) - { - case OPT_SUBMENU: - cprint(SUBMENUCHAR,attr,1,ms->menupage); - break; - case OPT_CHECKBOX: - cprint( (menu->items[x].itemdata.checked ? CHECKED : UNCHECKED),attr,1,ms->menupage); - break; - } + csprint(lchar); // Print last part } if (menusystem.handler) menusystem.handler(&menusystem,menu->items+curr); } @@ -100,8 +123,8 @@ void printmenu(t_menu * menu, int curr, char top, char left) void cleanupmenu(t_menu *menu, char top,char left) { t_menusystem *ms = &menusystem; - clearwindow(top,left-1,top+menu->numitems+1,left+menu->menuwidth+3,ms->menupage,ms->fillchar,ms->fillattr); // Clear the shadow - clearwindow(top-1,left-2,top+menu->numitems,left+menu->menuwidth+2,ms->menupage,ms->fillchar,ms->fillattr); // clear the main window + clearwindow(top,left-2,top+menu->numitems+1,left+menu->menuwidth+4,ms->menupage,ms->fillchar,ms->fillattr); // Clear the shadow + clearwindow(top-1,left-3,top+menu->numitems,left+menu->menuwidth+3,ms->menupage,ms->fillchar,ms->fillattr); // clear the main window } /* Handle one menu */ @@ -141,25 +164,27 @@ t_menuitem * getmenuoption( t_menu *menu, char top, char left, char startopt) break; case PAGEDN: curr += 5; - break; + break; case PAGEUP: curr -= 5; - break; + break; case UPARROW: - curr --; + while((curr > 0) && (menu->items[--curr].action == OPT_SEP)) ; break; case DNARROW: - curr++; + while((curr < numitems-1) && (menu->items[++curr].action == OPT_SEP)) ; + //curr++; break; case LTARROW: case ESCAPE: return NULL; break; - case ENTERA: case RTARROW: + case ENTERA: case ENTERB: if (ci->action == OPT_INACTIVE) break; if (ci->action == OPT_CHECKBOX) break; + if (ci->action == OPT_SEP) break; if (ci->action == OPT_EXITMENU) return NULL; // As if we hit Esc return ci; break; @@ -276,8 +301,8 @@ void init_menusystem(const char *title) { menusystem.nummenus = 0; if (title == NULL) - strcpy(menusystem.title,TITLESTR); - else strcpy(menusystem.title,title); + menusystem.title = TITLESTR; // Copy pointers + else menusystem.title = title; menusystem.normalattr = NORMALATTR; menusystem.reverseattr= REVERSEATTR; @@ -366,61 +391,75 @@ void unreg_handler() menusystem.handler = NULL; } -int add_menu(const char *title) // Create a new menu and return its position +char add_menu(const char *title) // Create a new menu and return its position { char num = menusystem.nummenus; t_menu *m; if (num >= MAXMENUS) return -1; - m = &(menusystem.menus[(int)num]); + m = &(menusystem.menus[num]); m->numitems = 0; if (title) { if (strlen(title) > MENULEN - 2) - strcpy(m->title," TITLE TOO LONG "); - else strcpy(m->title,title); + m->title = TITLELONG; //strcpy(m->title," TITLE TOO LONG "); + else m->title = title; //strcpy(m->title,title); } - else strcpy(m->title,""); + else m->title = EMPTYSTR; //strcpy(m->title,""); m ->menuwidth = strlen(m->title); menusystem.nummenus += 1; return menusystem.nummenus - 1; } +void add_sep() // Add a separator to current menu +{ + t_menuitem *mi; + t_menu *m; + + m = &(menusystem.menus[menusystem.nummenus-1]); + mi = &(m->items[m->numitems]); + mi->handler = NULL; // No handler + mi->item = mi->status = mi->data = EMPTYSTR; + mi->action = OPT_SEP; + mi->index = m->numitems++; + mi->parindex = menusystem.nummenus-1; +} + t_menuitem * add_item(const char *item, const char *status, t_action action, const char *data, char itemdata) // Add item to the "current" menu { t_menuitem *mi; t_menu *m; m = &(menusystem.menus[menusystem.nummenus-1]); - mi = &(m->items[(int)m->numitems]); + mi = &(m->items[m->numitems]); mi->handler = NULL; // No handler if (item) { if (strlen(item) > MENULEN - 2) { - strcpy(mi->item,"ITEM TOO LONG"); + mi->item = ITEMLONG; //strcpy(mi->item,"ITEM TOO LONG"); } else { - strcpy(mi->item,item); + mi->item = item; //strcpy(mi->item,item); if (strlen(item) > m->menuwidth) m->menuwidth = strlen(item); } - } else strcpy(mi->item,""); + } else mi->item = EMPTYSTR; //strcpy(mi->item,""); if (status) { if (strlen(status) > STATLEN - 2) { - strcpy(mi->status,"STATUS STRING TOO LONG"); + mi->status = STATUSLONG; //strcpy(mi->status,"STATUS STRING TOO LONG"); } else { - strcpy(mi->status,status); + mi->status = status; //strcpy(mi->status,status); } - } else strcpy(mi->status,""); + } else mi->status = EMPTYSTR; //strcpy(mi->status,""); mi->action = action; if (data) { if (strlen(data) > ACTIONLEN - 2) { - strcpy(mi->data,"ACTION STRING LONG"); + mi->data = ACTIONLONG; //strcpy(mi->data,"ACTION STRING LONG"); } else { - strcpy(mi->data,data); // This is only null terminated + mi->data = data; //strcpy(mi->data,data); // This is only null terminated } - } else strcpy(mi->data,""); + } else mi->data = EMPTYSTR; //strcpy(mi->data,""); switch (action) { diff --git a/menu/menu.h b/menu/menu.h index 1de36ec..c6b2cf3 100644 --- a/menu/menu.h +++ b/menu/menu.h @@ -51,8 +51,6 @@ #define TFILLCHAR ' ' #define TITLEATTR 0x70 -#define TITLESTR "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy" - // Single line Box drawing Chars #define TOPLEFT 218 @@ -63,6 +61,9 @@ #define BOT 196 #define LEFT 179 #define RIGHT 179 +#define HORIZ 196 +#define LTRT 195 // The |- char +#define RTLT 180 // The -| char // Double line Box Drawing Chars /* @@ -74,27 +75,37 @@ #define BOT 205 #define LEFT 186 #define RIGHT 186 +#define HORIZ 205 +#define LTRT 199 // The ||- char +#define RTLT 182 // The -|| char */ // Attributes of the menu system -#define MAXMENUS 10 // Maximum number of menu's allowed -#define MAXMENUSIZE 10 // Maximum number of entries in each menu -#define MENULEN 30 // Each menu entry is atmost MENULEN chars including the terminating $ -#define STATLEN 70 // Maximum length of status string +#define MAXMENUS 8 // Maximum number of menu's allowed +#define MAXMENUSIZE 12 // Maximum number of entries in each menu + +// Upper bounds on lengths +// Now that the onus of allocating space is with the user, these numbers +// are only for sanity checks. You may increase these values without +// affecting the memory footprint of this program +#define MENULEN 30 // Each menu entry is atmost MENULEN chars +#define STATLEN 80 // Maximum length of status string #define ACTIONLEN 80 // Maximum length of an action string // Layout of menu -#define MENUROW 3 // Row where menu is displayed -#define MENUCOL 4 // Col where menu is displayed +#define MENUROW 3 // Row where menu is displayed (relative to window) +#define MENUCOL 4 // Col where menu is displayed (relative to window) #define MENUPAGE 1 // show in display page 1 -#define STATLINE 23 // Line number where status line starts +#define STATLINE 23 // Line number where status line starts (relative to window) // Other Chars -#define SUBMENUCHAR 175 // This is >> symbol, << is 174 +#define SUBMENUCHAR 175 // This is >> symbol +#define EXITMENUCHAR 174 // This is << symbol #define CHECKED 251 // Check mark #define UNCHECKED 250 // Light bullet -typedef enum {OPT_INACTIVE, OPT_SUBMENU, OPT_RUN, OPT_EXITMENU, OPT_CHECKBOX, OPT_RADIOBTN, OPT_EXIT} t_action; +typedef enum {OPT_INACTIVE, OPT_SUBMENU, OPT_RUN, OPT_EXITMENU, OPT_CHECKBOX, + OPT_RADIOBTN, OPT_EXIT, OPT_SEP} t_action; typedef union { char submenunum; @@ -110,9 +121,9 @@ typedef void (*t_item_handler)(struct s_menusystem *, struct s_menuitem *); typedef void (*t_menusystem_handler)(struct s_menusystem *, struct s_menuitem *); typedef struct s_menuitem { - char item[MENULEN+2]; - char status[STATLEN+2]; - char data[ACTIONLEN+2]; + const char *item; //char item[MENULEN+2]; + const char *status; //char status[STATLEN+2]; + const char *data; //char data[ACTIONLEN+2]; void * extra_data; // Any other data user can point to t_item_handler handler; // Pointer to function of type menufn char active; // Is this item active or not @@ -124,14 +135,14 @@ typedef struct s_menuitem { typedef struct s_menu { t_menuitem items[MAXMENUSIZE]; - char title[MENULEN+2]; + const char *title; //char title[MENULEN+2]; char numitems; char menuwidth; } t_menu; typedef struct s_menusystem { - t_menu menus[MAXMENUS]; - char title[80]; // Maximum title length + t_menu menus[MAXMENUS]; + const char *title; //char title[80]; // Maximum title length t_menusystem_handler handler; // Handler function called every time a menu is re-printed. char nummenus; char normalattr; @@ -147,15 +158,29 @@ typedef struct s_menusystem { char shadowattr; char statline; char menupage; - char maxrow,minrow,numrows; // Number of rows in the current text mode - char maxcol,mincol,numcols; // Number of columns in the current text mode + char maxrow,minrow,numrows; // Number of rows in the window + char maxcol,mincol,numcols; // Number of columns in the window } t_menusystem; -// User callable Functions +/************************************************************************ + * 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. + * + *************************************************************************** + */ t_menuitem * showmenus(char startmenu); -void init_menusystem(const char *title); +void init_menusystem(const char *title); // This pointer value is stored internally void set_normal_attr(char normal, char selected, char inactivenormal, char inactiveselected); @@ -172,10 +197,13 @@ void reg_handler( t_menusystem_handler handler); // Register handler void unreg_handler(); // Create a new menu and return its position -int add_menu(const char *title); +char add_menu(const char *title); // This pointer value is stored internally + +// Add item to the "current" menu // pointer values are stored internally +t_menuitem * add_item(const char *item, const char *status, t_action action, const char *data, char itemdata); -// Add item to the "current" menu -t_menuitem * add_item(const char *item, const char *status, t_action action, const char *data, char itemdata); +// Add a separator to the "current" menu +void add_sep(); // Main function for the user's config file int menumain(char *cmdline); -- 2.7.4