Patch from Murali for windowing support and a much cleaner interface;
authorhpa <hpa>
Wed, 4 Feb 2004 23:36:07 +0000 (23:36 +0000)
committerhpa <hpa>
Wed, 4 Feb 2004 23:36:07 +0000 (23:36 +0000)
some minor formatting cleanups on my part

menu/biosio.c
menu/biosio.h
menu/complex.c
menu/menu.c
menu/menu.h
menu/simple.c

index d27f4f1..6c573fa 100644 (file)
@@ -18,8 +18,8 @@
 /* Print character and attribute at cursor */
 static inline void asm_cprint(char chr, char attr, int times, char disppage)
 {
-  asm volatile("movb $0x09,%%ah ; int $0x10"
-              : "+a" (chr) : "b" (attr + (disppage << 8)), "c" (times));
+    asm volatile("movb $0x09,%%ah ; int $0x10"
+                : "+a" (chr) : "b" (attr + (disppage << 8)), "c" (times));
 }
 
 void cprint(char chr,char attr,int times,char disppage)
@@ -29,8 +29,8 @@ void cprint(char chr,char attr,int times,char disppage)
 
 static inline void asm_setdisppage(char num)
 {
-  asm volatile("movb $0x05,%%ah ; int $0x10"
-              : "+a" (num));
+    asm volatile("movb $0x05,%%ah ; int $0x10"
+                : "+a" (num));
 }
 
 void setdisppage(char num) // Set the display page to specified number
@@ -41,12 +41,12 @@ void setdisppage(char num) // Set the display page to specified number
 
 static inline char asm_getdisppage(void)
 {
-  char page;
-
-  asm("movb $0x0f,%%ah ; "
-      "int $0x10 ; "
-      "movb %%bh,%0" : "=rm" (page) : : "eax", "ebp");
-  return page;
+    char page;
+    
+    asm("movb $0x0f,%%ah ; "
+       "int $0x10 ; "
+       "movb %%bh,%0" : "=rm" (page) : : "eax", "ebp");
+    return page;
 }
 
 char getdisppage() // Get current display page 
@@ -66,7 +66,7 @@ static inline void asm_putchar(char x, char page)
 void csprint(const char *str)
 {
     char page = asm_getdisppage();
-
+    
     while ( *str ) {
        asm_putchar(*str, page);
        str++;
@@ -85,18 +85,19 @@ void clearwindow(char top, char left, char bot, char right, char page, char fill
 
 void cls(void)
 {
-    asm_cprint(' ',0x07,25*80,getdisppage());    
+    gotoxy(0,0,getdisppage());
+    asm_cprint(' ',0x07,getnumrows()*getnumcols(),getdisppage());    
 }
 
 static inline void asm_gotoxy(char row,char col, char page)
 {
-  asm volatile("movb %1,%%bh ; "
-              "movb $0x02,%%ah ; "
-              "int $0x10"
-              : : "d" ((row << 8) + col), "g" (page)
-              : "eax", "ebx");
+    asm volatile("movb %1,%%bh ; "
+                "movb $0x02,%%ah ; "
+                "int $0x10"
+                : : "d" ((row << 8) + col), "g" (page)
+                : "eax", "ebx");
 }
-   
+
 void gotoxy(char row,char col, char page)
 {
     asm_gotoxy(row,col,page);
@@ -104,16 +105,16 @@ void gotoxy(char row,char col, char page)
 
 static inline void asm_getpos(char *row, char *col, char page)
 {
-  asm("movb %2,%%bh ; "
-      "movb $0x03,%%ah ; "
-      "int $0x10 ; "
-      "movb %%dh,%0 ; "
-      "movb %%dl,%1"
-      : "=m" (*row), "=m" (*col)
-      : "g" (page)
-      : "eax", "ebx", "ecx", "edx");
+    asm("movb %2,%%bh ; "
+       "movb $0x03,%%ah ; "
+       "int $0x10 ; "
+       "movb %%dh,%0 ; "
+       "movb %%dl,%1"
+       : "=m" (*row), "=m" (*col)
+       : "g" (page)
+       : "eax", "ebx", "ecx", "edx");
 }
-   
+
 void getpos(char * row, char * col, char page)
 {
     asm_getpos(row,col,page);
@@ -128,8 +129,8 @@ char asm_inputc(char *scancode)
               : "=a" (ax));
   
   if (scancode)
-    *scancode = (ax >> 8);
-
+      *scancode = (ax >> 8);
+  
   return (char)ax;
 }
    
@@ -140,8 +141,8 @@ char inputc(char * scancode)
 
 static inline void asm_cursorshape(char start, char end)
 {
-  asm volatile("movb $0x01,%%ah ; int $0x10"
-              : : "c" ((start << 8) + end) : "eax");
+    asm volatile("movb $0x01,%%ah ; int $0x10"
+                : : "c" ((start << 8) + end) : "eax");
 }
    
 void cursoroff(void)
@@ -159,46 +160,59 @@ char eolstr[] = "\n$";
 
 static inline char asm_getchar(void)
 {
-  char v;
-
-  /* Get key without echo */
-  asm("movb $0x08,%%ah ; int $0x21" : "=a" (v));
-
-  return v;
+    char v;
+    
+    /* Get key without echo */
+    asm("movb $0x08,%%ah ; int $0x21" : "=a" (v));
+    
+    return v;
 }
 
-void getstring(char *str, unsigned int size)
 // Reads a line of input from stdin. Replace CR with NUL byte
+void getstring(char *str, unsigned int size)
 {
-  char c;
-  char *p = str;
-  char page = asm_getdisppage();
-
-  while ( (c = asm_getchar()) != '\r' ) {
-    switch (c) {
-    case '\0':                 /* Extended char prefix */
-      asm_getchar();           /* Drop */
-      break;
-    case '\b':
-      if ( p > str ) {
-       p--;
-       csprint("\b \b");
-      }
-      break;
-    case '\x15':               /* Ctrl-U: kill input */
-      while ( p > str ) {
-       p--;
-       csprint("\b \b");
-      }
-      break;
-    default:
-      if ( c >= ' ' && (unsigned int)(p-str) < size-1 ) {
-       *p++ = c;
-       asm_putchar(c, page);
-      }
-      break;
+    char c;
+    char *p = str;
+    char page = asm_getdisppage();
+    
+    while ( (c = asm_getchar()) != '\r' ) {
+       switch (c) {
+       case '\0':              /* Extended char prefix */
+           asm_getchar();      /* Drop */
+           break;
+       case '\b':
+           if ( p > str ) {
+               p--;
+               csprint("\b \b");
+           }
+           break;
+       case '\x15':            /* Ctrl-U: kill input */
+           while ( p > str ) {
+               p--;
+               csprint("\b \b");
+           }
+           break;
+       default:
+           if ( c >= ' ' && (unsigned int)(p-str) < size-1 ) {
+               *p++ = c;
+               asm_putchar(c, page);
+           }
+           break;
+       }
     }
-  }
-  *p = '\0';
-  csprint("\r\n");
+    *p = '\0';
+    csprint("\r\n");
+}
+
+static inline void asm_setvideomode(char mode)
+{
+    /* This BIOS function is notoriously register-dirty,
+       so push/pop around it */
+    asm volatile("pushal ; xorb %%ah,%%ah ; int $0x10 ; popal"
+                : : "a" (mode) );
+}
+
+void setvideomode(char mode)
+{
+    asm_setvideomode(mode);
 }
index 719a8e1..c4ba0c6 100644 (file)
@@ -49,4 +49,26 @@ void cursoron(void);         /* Turns off cursor */
 
 void getstring(char *str, unsigned int size);
 
+static inline unsigned char readbiosb(unsigned short addr)
+{
+    unsigned char v;
+
+    asm("movw %2,%%fs ; "
+       "movb %%fs:%1,%0"
+       : "=r" (v)
+       : "m" (*(unsigned char *)(unsigned int)addr),
+       "r" ((unsigned short)0));
+    return v;
+}
+static inline char getnumrows()
+{
+    return readbiosb(0x484);
+}
+static inline char getnumcols(void)
+{
+    return readbiosb(0x44a);
+}
+void setvideomode(char mode); // Set the video mode.
+
 #endif
index 47cf373..8498618 100644 (file)
@@ -46,7 +46,7 @@ void msys_handler(t_menusystem *ms, t_menuitem *mi)
         return;
     }
     strcpy (infoline," ");
-    if (flags.baseurl) strcat(infoline,"baseurl=http://128.135.11.139/gui ");
+    if (flags.baseurl) strcat(infoline,"baseurl=http://192.168.11.12/gui ");
     if (flags.mountcd) strcat(infoline,"mountcd=yes ");
     if (!flags.network)
        strcat(infoline,"network=no ");
@@ -118,8 +118,12 @@ int menumain(char *cmdline)
 
   (void)cmdline;               /* Not used */
 
+  // Switch video mode here
+  // setvideomode(0x18); // or whatever mode you want
+
   // Choose the default title and setup default values for all attributes....
   init_menusystem(NULL);
+  set_window_size(1,1,23,79); // Leave one row/col all around
   
   // Choose the default values for all attributes and char's
   // -1 means choose defaults (Actually the next 4 lines are not needed)
@@ -182,7 +186,7 @@ int menumain(char *cmdline)
                 {
                     csprint("Enter IP address (last two octets only): ");
                     getstring(ip, sizeof ip);
-                    strcat(cmd,"ipaddr=128.135.");
+                    strcat(cmd,"ipaddr=192.168.");
                     strcat(cmd,ip);
                 }
             }
index e786b92..5a865a2 100644 (file)
- /* -*- c -*- ------------------------------------------------------------- *
-  *
-  *   Copyright 2004 Murali Krishnan Ganapathy - All Rights Reserved
-  *
-  *   This program is free software; you can redistribute it and/or modify
-  *   it under the terms of the GNU General Public License as published by
-  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
-  *   Bostom MA 02111-1307, USA; either version 2 of the License, or
-  *   (at your option) any later version; incorporated herein by reference.
-  *
-  * ----------------------------------------------------------------------- */
-
- #include "biosio.h"
- #include "string.h"
- #include "menu.h"
-
- // Structures
-
- // Declare a menusystem here
- static t_menusystem menusystem;
-
- /* Basic Menu routines */
-
- void drawbox(char top, char left, char bot, char right,char attr, char page)
- {
-     char x;
-
-     // Top border
-     gotoxy(top,left,page);
-     cprint(TOPLEFT,attr,1,page);
-     gotoxy(top,left+1,page);
-     cprint(TOP,attr,right-left,page);
-     gotoxy(top,right,page);
-     cprint(TOPRIGHT,attr,1,page);
-     // Bottom border
-     gotoxy(bot,left,page);
-     cprint(BOTLEFT,attr,1,page);
-     gotoxy(bot,left+1,page);
-     cprint(BOT,attr,right-left,page);
-     gotoxy(bot,right,page);
-     cprint(BOTRIGHT,attr,1,page);
-     // Left & right borders
-     for (x=top+1; x < bot; x++)
-     {
-        gotoxy(x,left,page);
-        cprint(LEFT,attr,1,page);
-        gotoxy(x,right,page);
-        cprint(RIGHT,attr,1,page);
-     }
- }
-
- void printmenu(t_menu * menu, int curr, char top, char left)
- {
-     int x;
-     int numitems,menuwidth;
-     t_menusystem *ms;
-     char attr;
-
-     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);
-     // 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)
-        {
-            attr = (x==curr? ms->revinactattr : ms->inactattr);
-        } else {
-            attr = (x==curr ? ms->reverseattr : ms->normalattr);
-        }
-        cprint(ms->spacechar,attr,menuwidth+1,ms->menupage);        
-        gotoxy(top+x,left,ms->menupage);
-        csprint(menu->items[x].item);
-        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;
-        }
-     }
-     if (menusystem.handler) menusystem.handler(&menusystem,menu->items+curr);
- }
-
- 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
- }
-
- /* Handle one menu */
- t_menuitem * getmenuoption( t_menu *menu, char top, char left, char startopt)
- // Return item chosen or NULL if ESC was hit.
- {
-     int curr;
-     char asc,scan;
-     char numitems;
-     t_menusystem *ms;
-     t_menuitem *ci; // Current item
-
-     ms = & menusystem;
-     numitems = menu->numitems;
-     // Setup status line
-     gotoxy(ms->statline,0,ms->menupage);
-     cprint(ms->spacechar,ms->reverseattr,80,ms->menupage);
-
-     // Initialise current menu item    
-     curr = startopt;
-     gotoxy(ms->statline,0,ms->menupage);
-     cprint(ms->spacechar,ms->statusattr,80,1);
-     gotoxy(ms->statline,0,ms->menupage);
-     csprint(menu->items[curr].status);
-     while (1) // Forever
-     {
-        printmenu(menu,curr,top,left);
-        ci = &(menu->items[curr]);
-        asc = inputc(&scan);
-        switch (scan)
-        {
-            case HOMEKEY:
-                  curr = 0;
-                  break;
-            case ENDKEY:
-                  curr = numitems -1;
-                  break;
-            case PAGEDN:
-                  curr += 5;
-                  break; 
-            case PAGEUP:
-                  curr -= 5;
-                  break; 
-            case UPARROW:
-                  curr --;
-                  break;
-            case DNARROW:
-                  curr++;
-                  break;
-            case LTARROW:
-            case ESCAPE:
-                  return NULL;
-                  break;
-            case ENTERA:
-            case RTARROW:
-            case ENTERB:
-                  if (ci->action == OPT_INACTIVE) break;
-                  if (ci->action == OPT_CHECKBOX) break;
-                  if (ci->action == OPT_EXITMENU) return NULL; // As if we hit Esc
-                  return ci;
-                  break;
-            case SPACEKEY:
-                  if (ci->action != OPT_CHECKBOX) break;
-                  ci->itemdata.checked = !ci->itemdata.checked;
-                  // Call handler to see it anything needs to be done
-                  if (ci->handler != NULL) ci->handler(&menusystem,ci); 
-                  break;
-        }
-        // Adjust within range
-        if (curr < 0) curr=0;
-        if (curr >= numitems) curr = numitems -1;
-        // Update status line
-        gotoxy(ms->statline,0,ms->menupage);
-        cprint(ms->spacechar,ms->statusattr,80,ms->menupage);
-        csprint(menu->items[curr].status);
-     }
-     return NULL; // Should never come here
- }
-
- /* Handle the entire system of menu's. */
- t_menuitem * runmenusystem(char top, char left, int currmenu)
- /*
-  * currmenu
-  *    Which menu should be currently displayed
-  * top,left
-  *    What is the position of the top,left corner of the menu
-  *
-  * Return Value:
-  *    Returns a pointer to the final item chosen, or NULL if nothing chosen.
-  */
- {
-     t_menu *cmenu;
-     t_menusystem *ms = &menusystem;
-     t_menuitem *opt,*choice;
-     int numitems;
-     char startopt;
-
-     startopt = 0;
- startover:
-     cmenu = (menusystem.menus+currmenu);
-     numitems = menusystem.menus[currmenu].numitems;
-     opt = getmenuoption(cmenu,top,left,startopt);
-     if (opt == NULL)
-     {
-        // User hit Esc
-        cleanupmenu(cmenu,top,left);
-        return NULL;
-     }
-     if (opt->action != OPT_SUBMENU) // We are done with the menu system
-     {
-        cleanupmenu(cmenu,top,left);
-        return opt; // parent cleanup other menus
-     }
-     if (opt->itemdata.submenunum >= menusystem.nummenus) // This is Bad....
-     {
-        gotoxy(12,12,ms->menupage); // Middle of screen
-        csprint("Invalid submenu requested. Ask administrator to correct this.");
-        cleanupmenu(cmenu,top,left);
-        return NULL; // Pretend user hit esc
-     }
-     // Call recursively for submenu
-     // Position the submenu below the current item,
-     // covering half the current window (horizontally)
-     choice = runmenusystem(top+opt->index+2, left+3+(cmenu->menuwidth >> 1), opt->itemdata.submenunum);
-     if (choice==NULL) // User hit Esc in submenu
-     {
-       // Startover
-       startopt = opt->index;
-       goto startover;
-     }
-     else
-     {
-        cleanupmenu(cmenu,top,left);
-        return choice;
-     }
- }
-
- /* User Callable functions */
-
- t_menuitem * showmenus(char startmenu)
- {
-     t_menuitem *rv;
-     t_menusystem *ms;
-     char oldpage, tpos;
-     char oldrow, oldcol;
-
-     ms = & menusystem;
-     // Setup screen for menusystem
-     oldpage = getdisppage();
-     getpos(&oldrow, &oldcol, oldpage);
-     setdisppage(ms->menupage);
-     clearwindow(0,0,24,79,ms->menupage,ms->fillchar,ms->fillattr);
-     tpos = (80 - strlen(menusystem.title) - 1) >> 1; // To center it on line    
-     gotoxy(0,0,ms->menupage);
-     cprint(ms->tfillchar,ms->titleattr,80,ms->menupage);
-     gotoxy(0,tpos,ms->menupage);
-     csprint(menusystem.title);
-
-     cursoroff(); // Doesn't seem to work?
-
-     // Go
-     rv = runmenusystem(MENUROW, MENUCOL, startmenu);
-
-     // Hide the garbage we left on the screen
-     cursoron();
-     if (oldpage == ms->menupage) {
-        cls();
-     } else {
-        setdisppage(oldpage);
-        gotoxy(oldrow, oldcol, oldpage);
+/* -*- c -*- ------------------------------------------------------------- *
+ *
+ *   Copyright 2004 Murali Krishnan Ganapathy - All Rights Reserved
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
+ *   Bostom MA 02111-1307, USA; either version 2 of the License, or
+ *   (at your option) any later version; incorporated herein by reference.
+ *
+ * ----------------------------------------------------------------------- */
+
+/* This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt getargs.c
+ */
+
+#include "biosio.h"
+#include "string.h"
+#include "menu.h"
+
+// Structures
+
+// Declare a menusystem here
+static t_menusystem menusystem;
+
+/* Basic Menu routines */
+
+void drawbox(char top, char left, char bot, char right,char attr, char page)
+{
+    char x;
+    
+    // Top border
+    gotoxy(top,left,page);
+    cprint(TOPLEFT,attr,1,page);
+    gotoxy(top,left+1,page);
+    cprint(TOP,attr,right-left,page);
+    gotoxy(top,right,page);
+    cprint(TOPRIGHT,attr,1,page);
+    // Bottom border
+    gotoxy(bot,left,page);
+    cprint(BOTLEFT,attr,1,page);
+    gotoxy(bot,left+1,page);
+    cprint(BOT,attr,right-left,page);
+    gotoxy(bot,right,page);
+    cprint(BOTRIGHT,attr,1,page);
+    // Left & right borders
+    for (x=top+1; x < bot; x++)
+    {
+        gotoxy(x,left,page);
+        cprint(LEFT,attr,1,page);
+        gotoxy(x,right,page);
+        cprint(RIGHT,attr,1,page);
+    }
+}
+
+void printmenu(t_menu * menu, int curr, char top, char left)
+{
+    int x;
+    int numitems,menuwidth;
+    t_menusystem *ms;
+    char attr;
+
+    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);
+    // 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)
+        {
+            attr = (x==curr? ms->revinactattr : ms->inactattr);
+        } else {
+            attr = (x==curr ? ms->reverseattr : ms->normalattr);
+        }
+        cprint(ms->spacechar,attr,menuwidth+1,ms->menupage);        
+        gotoxy(top+x,left,ms->menupage);
+        csprint(menu->items[x].item);
+        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;
+        }
+    }
+    if (menusystem.handler) menusystem.handler(&menusystem,menu->items+curr);
+}
+
+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
+}
+
+/* Handle one menu */
+t_menuitem * getmenuoption( t_menu *menu, char top, char left, char startopt)
+// Return item chosen or NULL if ESC was hit.
+{
+    int curr;
+    char asc,scan;
+    char numitems;
+    t_menusystem *ms;
+    t_menuitem *ci; // Current item
+    
+    ms = & menusystem;
+    numitems = menu->numitems;
+    // Setup status line
+    gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage);
+    cprint(ms->spacechar,ms->reverseattr,ms->numcols,ms->menupage);
+
+    // Initialise current menu item    
+    curr = startopt;
+    gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage);
+    cprint(ms->spacechar,ms->statusattr,ms->numcols,1);
+    gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage);
+    csprint(menu->items[curr].status);
+    while (1) // Forever
+    {
+        printmenu(menu,curr,top,left);
+        ci = &(menu->items[curr]);
+        asc = inputc(&scan);
+        switch (scan)
+        {
+            case HOMEKEY:
+                  curr = 0;
+                  break;
+            case ENDKEY:
+                  curr = numitems -1;
+                  break;
+            case PAGEDN:
+                  curr += 5;
+                  break; 
+            case PAGEUP:
+                  curr -= 5;
+                  break; 
+            case UPARROW:
+                  curr --;
+                  break;
+            case DNARROW:
+                  curr++;
+                  break;
+            case LTARROW:
+            case ESCAPE:
+                  return NULL;
+                  break;
+            case ENTERA:
+            case RTARROW:
+            case ENTERB:
+                  if (ci->action == OPT_INACTIVE) break;
+                  if (ci->action == OPT_CHECKBOX) break;
+                  if (ci->action == OPT_EXITMENU) return NULL; // As if we hit Esc
+                  return ci;
+                  break;
+            case SPACEKEY:
+                  if (ci->action != OPT_CHECKBOX) break;
+                  ci->itemdata.checked = !ci->itemdata.checked;
+                  // Call handler to see it anything needs to be done
+                  if (ci->handler != NULL) ci->handler(&menusystem,ci); 
+                  break;
+        }
+        // Adjust within range
+        if (curr < 0) curr=0;
+        if (curr >= numitems) curr = numitems -1;
+        // Update status line
+        gotoxy(ms->minrow+ms->statline,ms->mincol,ms->menupage);
+        cprint(ms->spacechar,ms->statusattr,ms->numcols,ms->menupage);
+        csprint(menu->items[curr].status);
+    }
+    return NULL; // Should never come here
+}
+
+/* Handle the entire system of menu's. */
+t_menuitem * runmenusystem(char top, char left, int currmenu)
+/*
+ * currmenu
+ *    Which menu should be currently displayed
+ * top,left
+ *    What is the position of the top,left corner of the menu
+ *
+ * Return Value:
+ *    Returns a pointer to the final item chosen, or NULL if nothing chosen.
+ */
+{
+    t_menu *cmenu;
+    t_menusystem *ms = &menusystem;
+    t_menuitem *opt,*choice;
+    int numitems;
+    char startopt;
+
+    startopt = 0;
+startover:
+    cmenu = (menusystem.menus+currmenu);
+    numitems = menusystem.menus[currmenu].numitems;
+    opt = getmenuoption(cmenu,top,left,startopt);
+    if (opt == NULL)
+    {
+        // User hit Esc
+        cleanupmenu(cmenu,top,left);
+        return NULL;
+    }
+    if (opt->action != OPT_SUBMENU) // We are done with the menu system
+    {
+        cleanupmenu(cmenu,top,left);
+        return opt; // parent cleanup other menus
     }
+    if (opt->itemdata.submenunum >= menusystem.nummenus) // This is Bad....
+    {
+        gotoxy(12,12,ms->menupage); // Middle of screen
+        csprint("Invalid submenu requested. Ask administrator to correct this.");
+        cleanupmenu(cmenu,top,left);
+        return NULL; // Pretend user hit esc
+    }
+    // Call recursively for submenu
+    // Position the submenu below the current item,
+    // covering half the current window (horizontally)
+    choice = runmenusystem(top+opt->index+2, left+3+(cmenu->menuwidth >> 1), opt->itemdata.submenunum);
+    if (choice==NULL) // User hit Esc in submenu
+    {
+       // Startover
+       startopt = opt->index;
+       goto startover;
+    }
+    else
+    {
+        cleanupmenu(cmenu,top,left);
+        return choice;
+    }
+}
+
+/* User Callable functions */
+
+t_menuitem * showmenus(char startmenu)
+{
+    t_menuitem *rv;
+    t_menusystem *ms;
+    char oldpage,tpos;
+
+    ms = & menusystem;
+    // Setup screen for menusystem
+    oldpage = getdisppage();
+    setdisppage(ms->menupage);
+    cls();
+    clearwindow(ms->minrow,ms->mincol,ms->maxrow,ms->maxcol,ms->menupage,ms->fillchar,ms->fillattr);
+    tpos = (ms->numcols - strlen(menusystem.title) - 1) >> 1; // To center it on line    
+    gotoxy(ms->minrow,ms->mincol,ms->menupage);
+    cprint(ms->tfillchar,ms->titleattr,ms->numcols,ms->menupage);
+    gotoxy(ms->minrow,ms->mincol+tpos,ms->menupage);
+    csprint(menusystem.title);
+    
+    cursoroff(); // Doesn't seem to work?
+
+    // Go
+    rv = runmenusystem(ms->minrow+MENUROW, ms->mincol+MENUCOL, startmenu);
+
+    // Hide the garbage we left on the screen
+    cursoron();
+    if (oldpage == ms->menupage) cls(); else setdisppage(oldpage);
 
     // Return user choice
     return rv;
@@ -296,6 +296,14 @@ void init_menusystem(const char *title)
 
     menusystem.menupage = MENUPAGE; // Usually no need to change this at all
     menusystem.handler = NULL; // No handler function
+
+    // Figure out the size of the screen we are in now.
+    // By default we use the whole screen for our menu
+    menusystem.minrow = menusystem.mincol = 0;
+    menusystem.numcols = getnumcols();
+    menusystem.numrows = getnumrows();
+    menusystem.maxcol = menusystem.numcols - 1;
+    menusystem.maxrow = menusystem.numrows - 1;
 }
 
 void set_normal_attr(char normal, char selected, char inactivenormal, char inactiveselected)
@@ -309,7 +317,9 @@ void set_normal_attr(char normal, char selected, char inactivenormal, char inact
 void set_status_info(char statusattr, char statline)
 {
     if (statusattr != 0xFF) menusystem.statusattr = statusattr;
-    if (statline   != 0xFF) menusystem.statline   = statline;
+    // statline is relative to minrow
+    if (statline >= menusystem.numrows) statline = menusystem.numrows - 1;
+    menusystem.statline = statline; // relative to ms->minrow, 0 based
 }
 
 void set_title_info(char tfillchar, char titleattr)
@@ -326,6 +336,26 @@ void set_misc_info(char fillchar, char fillattr,char spacechar, char shadowattr)
     if (shadowattr!= 0xFF) menusystem.shadowattr= shadowattr;
 }
 
+void set_window_size(char top, char left, char bot, char right) // Set the window which menusystem should use
+{
+    t_menusystem *ms;
+    
+    char nr,nc;
+    if ((top > bot) || (left > right)) return; // Sorry no change will happen here
+    nr = getnumrows();
+    nc = getnumcols();
+    if (bot >= nr) bot = nr-1;
+    if (right >= nc) right = nc-1;
+    ms = &menusystem;
+    ms->minrow = top;
+    ms->mincol = left;
+    ms->maxrow = bot;
+    ms->maxcol = right;
+    ms->numcols = right - left + 1;
+    ms->numrows = bot - top + 1;
+    if (ms->statline >= ms->numrows) ms->statline = ms->numrows - 1; // Clip statline if need be
+}
+
 void reg_handler( t_menusystem_handler handler)
 {
     menusystem.handler = handler;
@@ -338,36 +368,32 @@ void unreg_handler()
 
 int add_menu(const char *title) // Create a new menu and return its position
 {
-    t_menu *m;
-
-    if (menusystem.nummenus >= MAXMENUS)
-       return -1;
-
-    m = &menusystem.menus[(unsigned int)menusystem.nummenus];
-
-    m->numitems = 0;
-    if (title) {
-        if (strlen(title) > MENULEN - 2) {
-           strcpy(m->title," TITLE TOO LONG ");          
-        } else {
-           strcpy(m->title,title);
-        }
-    } else {
-        strcpy(m->title,"");
-    }
-
-    m->menuwidth = strlen(m->title);
-
-    return menusystem.nummenus++;
+   char num = menusystem.nummenus;
+   t_menu *m;
+
+   if (num >= MAXMENUS) return -1;
+   m = &(menusystem.menus[(int)num]);
+   m->numitems = 0;
+   if (title)
+   {
+       if (strlen(title) > MENULEN - 2)
+             strcpy(m->title," TITLE TOO LONG ");
+       else strcpy(m->title,title);
+   }
+   else strcpy(m->title,"");
+   m ->menuwidth = strlen(m->title);
+   menusystem.nummenus += 1;
+   return 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[m->numitems]);
+    mi = &(m->items[(int)m->numitems]);
     mi->handler = NULL; // No handler
     if (item) {
       if (strlen(item) > MENULEN - 2) {
index cf41173..1de36ec 100644 (file)
  *
  * ----------------------------------------------------------------------- */
 
+/* This program can be compiled for DOS with the OpenWatcom compiler
+ * (http://www.openwatcom.org/):
+ *
+ * wcl -3 -osx -mt <filename>.c
+ */
+
 #ifndef __MENU_H__
 #define __MENU_H__
 
 #define SPACEKEY 57 // Scan code for SPACE
 
 // Attributes
-#if 0
-/* Original black/white with blink */
-
-#define NORMALATTR   0x70
-#define REVERSEATTR  0x87
-#define INACTATTR    0x74
-#define REVINACTATTR 0x87
-#define STATUSATTR   0xF0
-#define FILLCHAR     178
-#define FILLATTR     0x07
-#define SHADOWATTR   0x08
-#define SPACECHAR    ' '
-
-#define TFILLCHAR    ' '
-#define TITLEATTR    0x70
-
-#else
-/* Alternate color scheme */
-
 #define NORMALATTR   0x17
 #define REVERSEATTR  0x70
 #define INACTATTR    0x18
@@ -64,8 +51,6 @@
 #define TFILLCHAR    ' '
 #define TITLEATTR    0x70
 
-#endif
-
 #define TITLESTR  "COMBOOT Menu System for SYSLINUX developed by Murali Krishnan Ganapathy"
 
 // Single line Box drawing Chars
@@ -79,7 +64,6 @@
 #define LEFT     179
 #define RIGHT    179
 
-
 // Double line Box Drawing Chars
 /*
 #define TOPLEFT  201
 #define MENUROW       3  // Row where menu is displayed
 #define MENUCOL       4  // Col where menu is displayed
 #define MENUPAGE      1  // show in display page 1
-#define STATLINE      24 // Line number where status line starts
+#define STATLINE      23 // Line number where status line starts
 
 // Other Chars
 #define SUBMENUCHAR  175 // This is >> symbol, << is 174
-#define CHECKED      251 // Checkmark
+#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;
@@ -128,21 +112,21 @@ 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];
+    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
     t_action action;
-    char data[ACTIONLEN+2];
     t_itemdata itemdata; // Data depends on action value
     char index; // Index within the menu array
     char parindex; // Index of the menu in which this item appears. 
-    void * extra_data; // Any other data user can point to
-    t_item_handler handler; // Pointer to function of type menufn
 } t_menuitem;
 
 typedef struct s_menu {
+    t_menuitem items[MAXMENUSIZE];
+    char title[MENULEN+2];
     char numitems;
     char menuwidth;
-    char title[MENULEN+2];
-    t_menuitem items[MAXMENUSIZE];
 } t_menu;
 
 typedef struct s_menusystem {
@@ -163,6 +147,8 @@ 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
 } t_menusystem;
 
 // User callable Functions
@@ -179,6 +165,8 @@ void set_title_info(char tfillchar, char titleattr);
 
 void set_misc_info(char fillchar, char fillattr,char spacechar, char shadowattr);
 
+void set_window_size(char top, char left, char bot, char right); // Set the window which menusystem should use
+
 void reg_handler( t_menusystem_handler handler); // Register handler
 
 void unreg_handler(); 
index 2d26af8..aeaa6b7 100644 (file)
@@ -26,8 +26,12 @@ int menumain(char *cmdline)
   char TESTING,RESCUE,MAIN;    /* The menus we're going to declare */
   (void)cmdline;               /* Not used */
 
+  // Change the video mode here
+  // setvideomode(0)
+
   // Choose the default title and setup default values for all attributes....
   init_menusystem(NULL);
+  set_window_size(1,1,23,78); // Leave one row/col border all around
   
   // Choose the default values for all attributes and char's
   // -1 means choose defaults (Actually the next 4 lines are not needed)