home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol7n10.zip / MENU.C < prev    next >
C/C++ Source or Header  |  1988-05-31  |  11KB  |  312 lines

  1. /* menu.c */
  2.  
  3. #include<stdio.h>
  4. #include<bios.h>
  5. #include<string.h>
  6. #include"PcMag.h"
  7.  
  8. /* screen colors:
  9.  *  NORMAL_VID value for ordinary characters,
  10.  *  HIGHLITE for reverse
  11.  */
  12.  
  13. #define NORMAL_VID      0x1700      /* white text, blue field    */
  14. #define HIGHLITE_VID    0x7000      /* black text, white field   */
  15.  
  16. /* Ascii key definitions */
  17.  
  18. #define ENTER       13
  19. #define SPACE       32
  20. #define ESC         27
  21.  
  22. /* Scan key redefinitions */
  23.  
  24. #define RIGHT_ARROW 77+'z'
  25. #define LEFT_ARROW  75+'z'
  26.  
  27. /* limitations: */
  28.  
  29. #define MAXMENUITEMS    25          /* number of menu items      */
  30. #define NAME_ROW        2           /* row number of item name   */
  31. #define NAME_COL        1           /* column number for name    */
  32. #define DESCRIPTION_ROW 3           /* description row number    */
  33. #define DESCRIPTION_COL 2           /* description column        */
  34.  
  35. /* macros to make the code more readable, don't touch these */
  36.  
  37. #define     SCREEN_SIZE         2000        /* screen size @ 2000 words  */
  38. #define     ring_bell()         putch(7)    /* bell-ringing macro        */
  39. #define     VIDEO_INT           0x10        /* Bios video interrupt      */
  40. #define     SET_CURSOR_SIZE     0x01        /* Int 10 function 1         */
  41. #define     GET_CURSOR_POS      0x02        /* Int 10 function 2         */
  42. #define     READ_CURSOR         0x03        /* Int 10 function 3         */
  43. #define     GET_VID_MODE        0x0f        /* Int 10 function F         */
  44. #define     MONO_MODE           7           /* monochrome video mode #   */
  45. #define     MONO_SCREEN         0xb0000000  /* address of mono screen    */
  46. #define     COLOR_SCREEN        0xb8000000  /* address of color screen   */
  47. #define     CURSOR_SAVE         0           /* macro for cursor save     */
  48. #define     CURSOR_RESTORE      1           /* macro for cursor store    */
  49.  
  50. /* global objects: */
  51.  
  52. int far *screen;                            /* pointer to screen buffer  */
  53. int old_screen[SCREEN_SIZE];                /* store old screen here     */
  54.  
  55. /* list of function declarations for cue_function */
  56.  
  57. int    addf(), subf(), mulf(), divf(), exitf();
  58.  
  59. /* array of structures with names, descriptions and function pointers */
  60.  
  61. struct _cue
  62. {
  63.     char    *cue_name;                     /* name to be displayed     */
  64.     char    *cue_description;              /* description              */
  65.     int     (*cue_function)();             /* function to be called    */
  66. }
  67. cue[MAXMENUITEMS] =
  68. {
  69. /* --1234567890--------1234567890123456789012-----for alignment */
  70.  
  71.     " Add ",          "Explain addition      ",     addf,
  72.     " Subtract ",     "Discuss subtraction   ",     subf,
  73.     " Multiply ",     "Portray multiplication",     mulf,
  74.     " Divide ",       "Characterize division ",     divf,
  75.     " Exit ",         "Exit to system        ",     exitf,
  76.  
  77.         /* you can add more items here in the same fashion - 
  78.          * up to MAXMENUITEMS total
  79.          */
  80.     NULL,NULL,NULL
  81. };
  82.  
  83.  
  84. /* functions */
  85.  
  86. /* cls()
  87.  * clears the screen by writing blanks to screen buffer
  88.  */
  89. cls()
  90. {
  91.     int pos=0;
  92.     
  93.     while(pos < SCREEN_SIZE)                    /* for each word in screen  */
  94.         *(screen + pos++) = NORMAL_VID;         /* set it to NORMAL_VID     */
  95. }
  96.  
  97. /* print()
  98.  * prints a null-terminated string at row,col with attributes
  99.  * returns next available column
  100.  */
  101. print(str, row, col, att)               
  102. char *str;                             
  103. int row, col, att;                                                  
  104. {
  105.     while(*str) 
  106.         *(screen+row*80+col++) = att + *str++;
  107.         return (col);
  108. }
  109.  
  110. /* four test functions */
  111. addf()          
  112. {
  113.     cls();
  114.     print("In Add, press a key for menu",2,1,HIGHLITE_VID);
  115.     getch();
  116. }
  117.  
  118. subf()
  119. {
  120.     cls(); 
  121.     print("In Subtract, press a key for menu",2,1,HIGHLITE_VID);
  122.     getch();
  123. }
  124.  
  125. mulf()                                     
  126. {
  127.     cls(); 
  128.     print("In Multiply, press a key for menu",2,1,HIGHLITE_VID); 
  129.     getch();
  130. }
  131.  
  132. divf()
  133. {
  134.     cls(); 
  135.     print("In Divide, press a key for menu",2,1,HIGHLITE_VID); 
  136.     getch();
  137. }
  138.  
  139. exitf() 
  140. {
  141.     int    i;
  142.                                             
  143.     for( i = 0; i < SCREEN_SIZE; i++)          /* restore original screen */
  144.         *(screen+i) = old_screen[i];
  145.  
  146.     cursor(CURSOR_RESTORE);                    /* reset cursor size/posit.*/
  147. }
  148.  
  149.  
  150. /* Run()
  151.  * runs the appropriate test function at cue[itemnumber].cue_function.
  152.  * This could be modified to use spawn() to run other programs.
  153.  */
  154. Run(itemnumber)
  155. int        itemnumber;
  156. {
  157.     return (cue[itemnumber].cue_function)();
  158. }
  159.  
  160. /* cursor() * cursor operations: saves the current cursor size and position in
  161.  * the statics, or restores the cursor size and position previously
  162.  * saved.
  163.  */
  164. cursor(op)
  165. {
  166.     union REGS r;
  167.     static int oldcurrow,oldcurcol,oldcurstart,oldcurend;
  168.  
  169.     if(op)                                 /* restore cursor           */
  170.     {
  171.         r.h.ah = SET_CURSOR_POS;           /* cursor position function */
  172.         r.h.dh = oldcurrow;                /* set the row              */
  173.         r.h.dl = oldcurcol;                /* set the column           */
  174.         r.h.bh = 0;                        /* for video page 0         */
  175.         int86(VIDEO_INT,&r,&r);            /* call the bios            */
  176.  
  177.         r.h.ah = SET_CURSOR_SIZE;          /* cursor size function     */
  178.         r.h.ch = oldcurstart;              /* set the start            */
  179.         r.h.cl = oldcurend;                /* set the end              */
  180.         r.h.bh = 0;                        /* for video page 0         */
  181.         int86(VIDEO_INT,&r,&r);            /* call the bios            */
  182.     }
  183.     else                                   /* save the cursor          */
  184.     {
  185.         r.h.ah = READ_CURSOR;              /* cursor read function     */
  186.         r.h.bh = 0;                        /* page 0                   */
  187.         int86(VIDEO_INT,&r,&r);            /* call the bios            */
  188.         oldcurrow = r.h.dh;                /* save the cursor row      */
  189.         oldcurcol = r.h.dl = 0;            /* save the cursor column   */
  190.         oldcurstart = r.h.ch;              /* save the cursor start    */
  191.         oldcurend = r.h.cl;                /* save the cursor end      */
  192.         r.h.ah = SET_CURSOR_SIZE;          /* cursor size function     */
  193.         r.h.ch = 0x20;                     /* set bit 5 to hide cursor */
  194.         int86(VIDEO_INT,&r,&r);            /* call the bios            */
  195.     }
  196. }
  197.  
  198. /* initialize()
  199.  * initializes the initials array, sets number of choices found, and
  200.  * saves the screen buffer in the old_screen array
  201.  */
  202. initialize(choices,initials)
  203. int     *choices;
  204. char        *initials;
  205. {
  206.     int        i;
  207.     get_screen_mode();                      /* set screen pointer   */
  208.  
  209.                                             /* initialize the initials */
  210.     for( i = 0; cue[i].cue_name && i < MAXMENUITEMS; i++)
  211.         initials[i] = tolower(cue[i].cue_name[1]);
  212.     initials[i] = NULL;
  213.     *choices = i;
  214.                                                 /* save old screen */
  215.     for( i = 0; i < SCREEN_SIZE; i++)
  216.         old_screen[i] = *(screen+i);
  217. }
  218.  
  219. /* get_screen_mode()
  220.  * returns the current screen mode in AL, and sets the screen pointer
  221.  * to the appropriate video buffer address.
  222.  */
  223. get_screen_mode()
  224. {
  225.     union REGS r;
  226.  
  227.     r.h.ah = GET_VID_MODE;                  /* get video mode function  */
  228.     int86(VIDEO_INT,&r,&r);                 /* call the bios            */
  229.                                             /* set screen pointer       */
  230.     screen = (int far *)((r.h.al == MONO_MODE) ? MONO_SCREEN : COLOR_SCREEN);
  231. }
  232.  
  233. /* menu()
  234.  * main menu creation function, callable from anywhere in a program.
  235.  *  Performs the following tasks:
  236.  *      1. saves the current screen and cursor
  237.  *         2. clears the screen
  238.  *         3. loops until the exit function is called through the following:
  239.  *          1. prints the menu items (highlights current selection)
  240.  *             2. prints the description of the highlighted selection
  241.  *             3. gets a key from the user (adjusts for non-ascii keys)
  242.  *             4. takes the appropriate actions for <ENTER>, <SPACE>,
  243.  *                 <LEFT-ARROW>, <RIGHT-ARROW>, <ESC>, or the first
  244.  *                 letter of the menu item.
  245.  *     Assumes last item is exit item and returns when that is executed.
  246.  */
  247. menu()
  248.     static int mark = 0; 
  249.     int col, i, key, choices;
  250.     char *match, initials[MAXMENUITEMS];
  251.  
  252.     initialize(&choices,initials);         /* initialize & save screen */
  253.  
  254.     cursor(CURSOR_SAVE);                   /* save the cursor          */
  255.     cls();                                 /* clear the screen         */
  256.  
  257.     while(TRUE)                            /* main loop                */
  258.     {   
  259.         col = NAME_COL;
  260.  
  261. /* print the names and highlight the current selection        */
  262.  
  263.         for( i = 0; i < choices; i++)
  264.             col =   print(cue[i].cue_name, NAME_ROW, col,
  265.                     (mark == i) ? HIGHLITE_VID : NORMAL_VID);        
  266.                                            /* print description        */
  267.  
  268. print(cue[mark].cue_description, DESCRIPTION_ROW, DESCRIPTION_COL, NORMAL_VID); 
  269.  
  270.         if(!(key = tolower(getch())))      /* get key, and lowercase   */ 
  271.             key = (getch() + 'z');         /* Not Ascii? get scan code */
  272.  
  273.         switch(key)                        /* which key was pressed?   */
  274.         {
  275.             case ENTER:                    /* if ENTER                 */
  276.                 Run(mark);                 /* run function at mark     */
  277.                 break;
  278.  
  279.             case RIGHT_ARROW:              /* if RIGHT_ARROW/SPACE bar */
  280.             case SPACE:
  281.                 mark = ((mark+1) % choices); /* move to next choice    */
  282.                 break;
  283.  
  284.             case LEFT_ARROW:               /* if LEFT_ARROW            */
  285.                                            /* move to previous choice  */
  286.                 mark = ((mark+choices-1) % choices);
  287.                  break;
  288.  
  289.             case ESC:                      /* if ESC                   */
  290.                 return Run(choices-1);     /* select last choice (exit)*/
  291.                 break;
  292.             
  293.             default:                       /* if initials match        */
  294.                 if(match = strchr(initials,key))
  295.                 {
  296.                     mark = (match-initials);
  297.                     Run(match-initials);
  298.                 }
  299.                 else
  300.                     ring_bell();           /* bad choice, ring the bell*/
  301.                 break;
  302.         }
  303.     }
  304. }
  305.  
  306. main()                                     /* main program             */
  307. {
  308.     menu();                                /* called as needed         */
  309. }
  310.  
  311. /* End of Menu.c */