home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1988
/
10
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-05-30
|
11KB
|
312 lines
/* menu.c */
#include<stdio.h>
#include<bios.h>
#include<string.h>
#include"PcMag.h"
/* screen colors:
* NORMAL_VID value for ordinary characters,
* HIGHLITE for reverse
*/
#define NORMAL_VID 0x1700 /* white text, blue field */
#define HIGHLITE_VID 0x7000 /* black text, white field */
/* Ascii key definitions */
#define ENTER 13
#define SPACE 32
#define ESC 27
/* Scan key redefinitions */
#define RIGHT_ARROW 77+'z'
#define LEFT_ARROW 75+'z'
/* limitations: */
#define MAXMENUITEMS 25 /* number of menu items */
#define NAME_ROW 2 /* row number of item name */
#define NAME_COL 1 /* column number for name */
#define DESCRIPTION_ROW 3 /* description row number */
#define DESCRIPTION_COL 2 /* description column */
/* macros to make the code more readable, don't touch these */
#define SCREEN_SIZE 2000 /* screen size @ 2000 words */
#define ring_bell() putch(7) /* bell-ringing macro */
#define VIDEO_INT 0x10 /* Bios video interrupt */
#define SET_CURSOR_SIZE 0x01 /* Int 10 function 1 */
#define GET_CURSOR_POS 0x02 /* Int 10 function 2 */
#define READ_CURSOR 0x03 /* Int 10 function 3 */
#define GET_VID_MODE 0x0f /* Int 10 function F */
#define MONO_MODE 7 /* monochrome video mode # */
#define MONO_SCREEN 0xb0000000 /* address of mono screen */
#define COLOR_SCREEN 0xb8000000 /* address of color screen */
#define CURSOR_SAVE 0 /* macro for cursor save */
#define CURSOR_RESTORE 1 /* macro for cursor store */
/* global objects: */
int far *screen; /* pointer to screen buffer */
int old_screen[SCREEN_SIZE]; /* store old screen here */
/* list of function declarations for cue_function */
int addf(), subf(), mulf(), divf(), exitf();
/* array of structures with names, descriptions and function pointers */
struct _cue
{
char *cue_name; /* name to be displayed */
char *cue_description; /* description */
int (*cue_function)(); /* function to be called */
}
cue[MAXMENUITEMS] =
{
/* --1234567890--------1234567890123456789012-----for alignment */
" Add ", "Explain addition ", addf,
" Subtract ", "Discuss subtraction ", subf,
" Multiply ", "Portray multiplication", mulf,
" Divide ", "Characterize division ", divf,
" Exit ", "Exit to system ", exitf,
/* you can add more items here in the same fashion -
* up to MAXMENUITEMS total
*/
NULL,NULL,NULL
};
/* functions */
/* cls()
* clears the screen by writing blanks to screen buffer
*/
cls()
{
int pos=0;
while(pos < SCREEN_SIZE) /* for each word in screen */
*(screen + pos++) = NORMAL_VID; /* set it to NORMAL_VID */
}
/* print()
* prints a null-terminated string at row,col with attributes
* returns next available column
*/
print(str, row, col, att)
char *str;
int row, col, att;
{
while(*str)
*(screen+row*80+col++) = att + *str++;
return (col);
}
/* four test functions */
addf()
{
cls();
print("In Add, press a key for menu",2,1,HIGHLITE_VID);
getch();
}
subf()
{
cls();
print("In Subtract, press a key for menu",2,1,HIGHLITE_VID);
getch();
}
mulf()
{
cls();
print("In Multiply, press a key for menu",2,1,HIGHLITE_VID);
getch();
}
divf()
{
cls();
print("In Divide, press a key for menu",2,1,HIGHLITE_VID);
getch();
}
exitf()
{
int i;
for( i = 0; i < SCREEN_SIZE; i++) /* restore original screen */
*(screen+i) = old_screen[i];
cursor(CURSOR_RESTORE); /* reset cursor size/posit.*/
}
/* Run()
* runs the appropriate test function at cue[itemnumber].cue_function.
* This could be modified to use spawn() to run other programs.
*/
Run(itemnumber)
int itemnumber;
{
return (cue[itemnumber].cue_function)();
}
/* cursor() * cursor operations: saves the current cursor size and position in
* the statics, or restores the cursor size and position previously
* saved.
*/
cursor(op)
{
union REGS r;
static int oldcurrow,oldcurcol,oldcurstart,oldcurend;
if(op) /* restore cursor */
{
r.h.ah = SET_CURSOR_POS; /* cursor position function */
r.h.dh = oldcurrow; /* set the row */
r.h.dl = oldcurcol; /* set the column */
r.h.bh = 0; /* for video page 0 */
int86(VIDEO_INT,&r,&r); /* call the bios */
r.h.ah = SET_CURSOR_SIZE; /* cursor size function */
r.h.ch = oldcurstart; /* set the start */
r.h.cl = oldcurend; /* set the end */
r.h.bh = 0; /* for video page 0 */
int86(VIDEO_INT,&r,&r); /* call the bios */
}
else /* save the cursor */
{
r.h.ah = READ_CURSOR; /* cursor read function */
r.h.bh = 0; /* page 0 */
int86(VIDEO_INT,&r,&r); /* call the bios */
oldcurrow = r.h.dh; /* save the cursor row */
oldcurcol = r.h.dl = 0; /* save the cursor column */
oldcurstart = r.h.ch; /* save the cursor start */
oldcurend = r.h.cl; /* save the cursor end */
r.h.ah = SET_CURSOR_SIZE; /* cursor size function */
r.h.ch = 0x20; /* set bit 5 to hide cursor */
int86(VIDEO_INT,&r,&r); /* call the bios */
}
}
/* initialize()
* initializes the initials array, sets number of choices found, and
* saves the screen buffer in the old_screen array
*/
initialize(choices,initials)
int *choices;
char *initials;
{
int i;
get_screen_mode(); /* set screen pointer */
/* initialize the initials */
for( i = 0; cue[i].cue_name && i < MAXMENUITEMS; i++)
initials[i] = tolower(cue[i].cue_name[1]);
initials[i] = NULL;
*choices = i;
/* save old screen */
for( i = 0; i < SCREEN_SIZE; i++)
old_screen[i] = *(screen+i);
}
/* get_screen_mode()
* returns the current screen mode in AL, and sets the screen pointer
* to the appropriate video buffer address.
*/
get_screen_mode()
{
union REGS r;
r.h.ah = GET_VID_MODE; /* get video mode function */
int86(VIDEO_INT,&r,&r); /* call the bios */
/* set screen pointer */
screen = (int far *)((r.h.al == MONO_MODE) ? MONO_SCREEN : COLOR_SCREEN);
}
/* menu()
* main menu creation function, callable from anywhere in a program.
* Performs the following tasks:
* 1. saves the current screen and cursor
* 2. clears the screen
* 3. loops until the exit function is called through the following:
* 1. prints the menu items (highlights current selection)
* 2. prints the description of the highlighted selection
* 3. gets a key from the user (adjusts for non-ascii keys)
* 4. takes the appropriate actions for <ENTER>, <SPACE>,
* <LEFT-ARROW>, <RIGHT-ARROW>, <ESC>, or the first
* letter of the menu item.
* Assumes last item is exit item and returns when that is executed.
*/
menu()
{
static int mark = 0;
int col, i, key, choices;
char *match, initials[MAXMENUITEMS];
initialize(&choices,initials); /* initialize & save screen */
cursor(CURSOR_SAVE); /* save the cursor */
cls(); /* clear the screen */
while(TRUE) /* main loop */
{
col = NAME_COL;
/* print the names and highlight the current selection */
for( i = 0; i < choices; i++)
col = print(cue[i].cue_name, NAME_ROW, col,
(mark == i) ? HIGHLITE_VID : NORMAL_VID);
/* print description */
print(cue[mark].cue_description, DESCRIPTION_ROW, DESCRIPTION_COL, NORMAL_VID);
if(!(key = tolower(getch()))) /* get key, and lowercase */
key = (getch() + 'z'); /* Not Ascii? get scan code */
switch(key) /* which key was pressed? */
{
case ENTER: /* if ENTER */
Run(mark); /* run function at mark */
break;
case RIGHT_ARROW: /* if RIGHT_ARROW/SPACE bar */
case SPACE:
mark = ((mark+1) % choices); /* move to next choice */
break;
case LEFT_ARROW: /* if LEFT_ARROW */
/* move to previous choice */
mark = ((mark+choices-1) % choices);
break;
case ESC: /* if ESC */
return Run(choices-1); /* select last choice (exit)*/
break;
default: /* if initials match */
if(match = strchr(initials,key))
{
mark = (match-initials);
Run(match-initials);
}
else
ring_bell(); /* bad choice, ring the bell*/
break;
}
}
}
main() /* main program */
{
menu(); /* called as needed */
}
/* End of Menu.c */