home *** CD-ROM | disk | FTP | other *** search
- /*
- ** menu.c
- **
- ** Pictor, Version 1.51, Copyright (c) 1992-94 SoftCircuits
- ** Redistributed by permission.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include "pictor.h"
-
-
- #define STATE_WAIT 0x1000
- #define STATE_HILITE 0x1001
- #define STATE_RUN 0x1002
- #define STATE_CANCEL 0x1003
- #define STATE_LEFT 0x2000
- #define STATE_RIGHT 0x2001
- #define STATE_RUNCOMMAND 0x3000
-
-
- static int mainselect,subselect;
- static int num_menus,num_items,width;
-
- int _PL_menurow = 1;
-
- /*
- ** Returns the starting column for the given main menu item.
- */
- static int getmenucol(MAINMENU *menu,int item)
- {
- int i,col = 3;
-
- for(i = 0;i < item;i++)
- col += (hstrlen(menu[i].item) + 2);
-
- return(col);
-
- } /* getmenucol */
-
- /*
- ** Paints a hilite bar on the current submenu selection. Note that
- ** if the specified colors are the non-hilite colors, then the effect
- ** is that of removing the hilite bar.
- */
- static void hilite_submenu(SUBMENU *menu,int color,int hcolor,int col)
- {
- setvpos(subselect + 2 + _PL_menurow,col - 1);
- vrepa(color,width + 2);
-
- vcolor(color);
- setvpos(subselect + 2 + _PL_menurow,col);
- hputs(menu[subselect].item,hcolor);
-
- } /* hilite_submenu */
-
- /*
- ** Runs the specified submenu.
- */
- static int submenu(SUBMENU *menu,COLORSTRUCT *colors,int col)
- {
- int state,state_value;
- int i,key,alt_released = FALSE;
-
- /* get menu dimensions */
- for(width = 0,num_items = 0;menu[num_items].item != NULL;num_items++) {
- if(menu[num_items].item != (char *)-1) {
- if(hstrlen(menu[num_items].item) > width)
- width = hstrlen(menu[num_items].item);
- }
- }
- if(width == 0) /* empty menu */
- return STATE_WAIT;
-
- /* paint submenu */
- wopen(_PL_menurow + 1,col - 2,num_items + 2,width + 4,colors->normal,
- WO_STATICMEM | WO_SHADOW);
- vcolor(colors->normal);
- for(i = 0;menu[i].item != NULL;i++) {
- if(menu[i].item != (char *)-1) {
- setvpos(i + _PL_menurow + 2,col);
- hputs(menu[i].item,colors->boldnormal);
- }
- else { /* menu divider */
- setvpos(i + _PL_menurow + 2,col - 2);
- vputc('\xC7');
- vrepc('\xC4',width + 2);
- vputc('\xB6');
- }
- }
-
- state = STATE_HILITE;
- subselect = state_value = 0;
-
- while(state != STATE_CANCEL) {
- switch(state) {
- case STATE_WAIT:
- if(kbdshift() & 0x08) {
- while((kbdshift() & 0x08) && !kbdready())
- ;
-
- if(!kbdready() && alt_released) {
- state = STATE_CANCEL;
- state_value = STATE_WAIT;
- }
- }
- alt_released = TRUE;
-
- if(kbdready()) {
- switch(key = kbdread()) {
- case DOWN_KEY:
- case SPACE_BAR:
- state = STATE_HILITE;
- state_value = subselect;
- do {
- if(++state_value >= num_items)
- state_value = 0;
- } while(menu[state_value].item == (char *)-1);
- break;
- case UP_KEY:
- state = STATE_HILITE;
- state_value = subselect;
- do {
- if(--state_value < 0)
- state_value = (num_items - 1);
- } while(menu[state_value].item == (char *)-1);
- break;
- case RIGHT_KEY:
- state = STATE_CANCEL;
- state_value = STATE_RIGHT;
- break;
- case LEFT_KEY:
- state = STATE_CANCEL;
- state_value = STATE_LEFT;
- break;
- case ENTER_KEY:
- state = STATE_CANCEL;
- state_value = STATE_RUNCOMMAND;
- break;
- case ESCAPE_KEY:
- state = STATE_CANCEL;
- state_value = STATE_CANCEL;
- break;
- case F1_KEY:
- if(_PL_helpfunc != NULL)
- _PL_helpfunc(menu[subselect].helptopic);
- else beep();
- break;
- default:
- /* test for hotkey */
- if(isalnum(key = tolower(key & 0xFF))) {
- for(i = 0;i < num_items;i++) {
- if(key == tolower(gethotkey(menu[i].item))) {
- state = STATE_CANCEL;
- state_value = STATE_RUNCOMMAND;
- subselect = i;
- break;
- }
- }
- }
- if(state == STATE_WAIT) beep();
- break;
- }
- }
- break;
- case STATE_HILITE:
- hilite_submenu(menu,colors->normal,colors->boldnormal,col);
- subselect = state_value;
- hilite_submenu(menu,colors->select,colors->boldselect,col);
- if(menu[subselect].description != NULL)
- statusbar(menu[subselect].description);
- state = STATE_WAIT;
- break;
- }
- }
- wclose();
-
- return(state_value);
-
- } /* submenu */
-
- /*
- ** Displays the mainmenu across the top of the screen. Hotkeys
- ** are displayed bold if hilite is TRUE.
- */
- void showmenu(MAINMENU *menu,COLORSTRUCT *colors,int hilite)
- {
- int i;
-
- setvpos(_PL_menurow,1);
- vcolor(colors->normal);
- vrepc(' ',_PL_columns);
-
- for(i = 0;menu[i].item != NULL;i++) {
- setvpos(_PL_menurow,getmenucol(menu,i));
- hputs(menu[i].item,(hilite) ? colors->boldnormal : colors->normal);
- }
-
- } /* showmenu */
-
- /*
- ** Puts a hilite bar on the current main menu selection. Note that
- ** if normal attributes are passed, the effect is that of removing
- ** the hilite bar.
- */
- static void hilite_menu(MAINMENU *menu,int color,int hcolor)
- {
- int col;
-
- col = getmenucol(menu,mainselect);
-
- setvpos(_PL_menurow,col - 1);
- vrepa(color,hstrlen(menu[mainselect].item) + 2);
-
- if(hcolor != color) {
- vcolor(color);
- setvpos(_PL_menurow,col);
- hputs(menu[mainselect].item,hcolor);
- }
-
- } /* hilite_menu */
-
- /*
- ** Runs the specified main menu.
- */
- static int mainmenu(MAINMENU *menu,COLORSTRUCT *colors,
- COLORSTRUCT *subcolors,int index)
- {
- int i,key,state,state_value;
-
- if(index == -1) {
- state = STATE_HILITE;
- mainselect = state_value = 0;
- showmenu(menu,colors,TRUE);
- }
- else {
- state = STATE_RUN;
- mainselect = state_value = index;
- }
-
- /* count number of submenus */
- for(num_menus = 0;menu[num_menus].item != NULL;num_menus++)
- ;
-
- pushstatus();
- pushcurs();
- setcurs(_PL_rows + 1,1);
-
- while(state != STATE_CANCEL) {
- switch(state) {
- case STATE_WAIT:
- if(kbdshift() & 0x08) {
- state = STATE_CANCEL;
- state_value = STATE_WAIT;
- }
- else if(kbdready()) {
- switch(key = kbdread()) {
- case RIGHT_KEY:
- case SPACE_BAR:
- state_value = mainselect;
- if(++state_value >= num_menus)
- state_value = 0;
- state = STATE_HILITE;
- break;
- case LEFT_KEY:
- state_value = mainselect;
- if(--state_value < 0)
- state_value = (num_menus-1);
- state = STATE_HILITE;
- break;
- case ENTER_KEY:
- case DOWN_KEY:
- case UP_KEY:
- state_value = mainselect;
- state = STATE_RUN;
- break;
- case ESCAPE_KEY:
- state = STATE_CANCEL;
- state_value = STATE_CANCEL;
- break;
- case F1_KEY:
- if(_PL_helpfunc != NULL)
- _PL_helpfunc(menu[mainselect].helptopic);
- else beep();
- break;
- default:
- /* test for hotkey */
- if(isalnum(key = tolower(key & 0xFF))) {
- for(i = 0;i < num_menus;i++) {
- if(key == tolower(gethotkey(menu[i].item))) {
- state_value = i;
- state = STATE_RUN;
- break;
- }
- }
- }
- if(state == STATE_WAIT) beep();
- break;
- }
- }
- break;
- case STATE_HILITE:
- hilite_menu(menu,colors->normal,colors->boldnormal);
- mainselect = state_value;
- hilite_menu(menu,colors->select,colors->boldselect);
- if(menu[mainselect].description != NULL)
- statusbar(menu[mainselect].description);
- state = STATE_WAIT;
- break;
-
- case STATE_RUN:
- while(state == STATE_RUN) {
-
- /* remove bold hotkeys */
- showmenu(menu,colors,FALSE);
-
- mainselect = state_value;
- hilite_menu(menu,colors->select,colors->select);
-
- i = submenu(menu[mainselect].submenu,subcolors,
- getmenucol(menu,mainselect));
-
- switch(i) {
- case STATE_RIGHT:
- if(++state_value >= num_menus)
- state_value = 0;
- break;
- case STATE_LEFT:
- if(--state_value < 0)
- state_value = (num_menus-1);
- break;
- case STATE_WAIT:
- showmenu(menu,colors,TRUE);
- state = STATE_HILITE;
- state_value = mainselect;
- break;
- default:
- state = STATE_CANCEL;
- state_value = i;
-
- }
- }
- break;
- }
- }
- popcurs();
- popstatus();
- if(state_value == STATE_RUNCOMMAND) {
- menu[mainselect].submenu[subselect].function();
- state_value = STATE_CANCEL;
- }
- showmenu(menu,colors,FALSE);
-
- return(state_value);
-
- } /* mainmenu */
-
- /*
- ** Waits for the next key press. If the key is used by the menu
- ** routines, it is handled appropriately. Otherwise this function
- ** returns the value of the key.
- **
- ** If a menu command is selected, the corresponding function is
- ** called from within the menu routines after which this routine
- ** will return 0.
- */
- int runmenu(MAINMENU *menu,COLORSTRUCT *colors,COLORSTRUCT *colors2)
- {
- int i,state = STATE_WAIT,state_value = 0;
- int alt_released = FALSE;
-
- while(state != STATE_CANCEL) {
- switch(state) {
- case STATE_WAIT:
- if(kbdshift() & 0x08) {
- showmenu(menu,colors,TRUE);
- while((kbdshift() & 0x08) && !kbdready())
- ;
- showmenu(menu,colors,FALSE);
-
- if(alt_released) {
- state = STATE_CANCEL;
- state_value = 0;
- }
- else {
- state = STATE_RUN; /* assume no key pressed */
- state_value = -1;
- }
- }
- if(kbdready()) {
- state = STATE_CANCEL;
- state_value = kbdread();
- for(i = 0;menu[i].item != NULL;i++) {
- if(getaltkey(gethotkey(menu[i].item)) == state_value) {
- state = STATE_RUN;
- state_value = i;
- break;
- }
- }
- }
- break;
- case STATE_RUN:
- state = mainmenu(menu,colors,colors2,state_value);
- alt_released = TRUE;
- state_value = 0;
- break;
- }
- }
- return(state_value);
-
- } /* runmenu */
-