From 3f1dc4d44e2edd814eb98b229683ef12c59a0589 Mon Sep 17 00:00:00 2001 From: hpa Date: Wed, 4 Feb 2004 23:36:07 +0000 Subject: [PATCH] Patch from Murali for windowing support and a much cleaner interface; some minor formatting cleanups on my part --- menu/biosio.c | 150 +++++++------- menu/biosio.h | 22 +++ menu/complex.c | 8 +- menu/menu.c | 608 ++++++++++++++++++++++++++++++--------------------------- menu/menu.h | 46 ++--- menu/simple.c | 4 + 6 files changed, 448 insertions(+), 390 deletions(-) diff --git a/menu/biosio.c b/menu/biosio.c index d27f4f1..6c573fa 100644 --- a/menu/biosio.c +++ b/menu/biosio.c @@ -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); } diff --git a/menu/biosio.h b/menu/biosio.h index 719a8e1..c4ba0c6 100644 --- a/menu/biosio.h +++ b/menu/biosio.h @@ -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 diff --git a/menu/complex.c b/menu/complex.c index 47cf373..8498618 100644 --- a/menu/complex.c +++ b/menu/complex.c @@ -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); } } diff --git a/menu/menu.c b/menu/menu.c index e786b92..5a865a2 100644 --- a/menu/menu.c +++ b/menu/menu.c @@ -1,272 +1,272 @@ - /* -*- 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) { diff --git a/menu/menu.h b/menu/menu.h index cf41173..1de36ec 100644 --- a/menu/menu.h +++ b/menu/menu.h @@ -10,6 +10,12 @@ * * ----------------------------------------------------------------------- */ +/* This program can be compiled for DOS with the OpenWatcom compiler + * (http://www.openwatcom.org/): + * + * wcl -3 -osx -mt .c + */ + #ifndef __MENU_H__ #define __MENU_H__ @@ -32,25 +38,6 @@ #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 @@ -103,11 +87,11 @@ #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(); diff --git a/menu/simple.c b/menu/simple.c index 2d26af8..aeaa6b7 100644 --- a/menu/simple.c +++ b/menu/simple.c @@ -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) -- 2.7.4