home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 10 / c_colu / menu.c < prev    next >
Text File  |  1988-08-30  |  4KB  |  202 lines

  1. /* ------------ menu.c ------------ */
  2.  
  3. #include <stdio.h>
  4. #include <conio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <ctype.h>
  8. #include <alloc.h>
  9. #include "window.h"
  10. #include "menu.h"
  11.  
  12. #define ON 1
  13. #define OFF 0
  14.  
  15. static int getvmn(void);
  16. static void haccent(int);
  17. static void dimension(char **,int *,int *);
  18. static void light(int);
  19. static int vlook(int,int);
  20.  
  21. int hsel = 1;        /* horizontal selection */
  22. MENU *mn;            /* active menu            */
  23.  
  24. /* ------------- display & process a menu ----------- */
  25. void menu_select(MENU *mnn, int sel)
  26. {
  27.     int hs, sx, sy, vsel, holdhsel, frtn = FALSE;
  28.     char *mb;
  29.  
  30.     if (sel)
  31.         hsel = sel;
  32.     mn = mnn;
  33.     sx = wherex();
  34.     sy = wherey();
  35.     mb = display_menubar(mn);
  36.     light(ON);
  37.     while (!frtn && ((vsel = getvmn()) != 0))    {
  38.         light(OFF);
  39.         holdhsel = hsel;
  40.         hs = hsel;
  41.         hsel = 1;
  42.         frtn = (*(mn+hs-1)->func [vsel-1]) ?
  43.                (*(mn+hs-1)->func [vsel-1])(hs,vsel) : FALSE;
  44.         hsel = holdhsel;
  45.         mn = mnn;
  46.         light(ON);
  47.     }
  48.     mn = NULL;
  49.     light(OFF);
  50.     gotoxy(sx, sy);
  51.     restore_menubar(mb);
  52. }
  53.  
  54. /* ----------- display the menu bar with no selections chosen ------- */
  55. char *display_menubar(MENU *mn)
  56. {
  57.     int i = 0;
  58.     char *mb;
  59.  
  60.     if ((mb = malloc(160)) != NULL)
  61.         gettext(1,1,80,1,mb);
  62.     window(1,1,80,25);
  63.     gotoxy(1,1);
  64.     textcolor(MENUFG);
  65.     textbackground(MENUBG);
  66.     cprintf("    ");
  67.     while ((mn+i)->mname)
  68.         cprintf(" %-10.10s ", (mn+i++)->mname);
  69.     while (i++ < 6)
  70.         cprintf("            ");
  71.     cprintf("    ");
  72.     hidecursor();
  73.     return mb;
  74. }
  75.  
  76. /* ------------ restore the menu bar line --------------- */
  77. void restore_menubar(char *mb)
  78. {
  79.     if (mb)    {
  80.         puttext(1,1,80,1,mb);
  81.         free(mb);
  82.     }
  83. }
  84.  
  85. /* ---------pop down a vertical menu --------- */
  86. static int getvmn()
  87. {
  88.     int ht, wd, vx, sel;
  89.  
  90.     while (TRUE)    {
  91.         dimension((mn+hsel-1)->mselcs, &ht, &wd);
  92.         if (!(mn+hsel-1)->lastvsel)
  93.             (mn+hsel-1)->lastvsel = 1;
  94.         if (ht > 0)    {
  95.             vx = 5+(hsel-1)*12;
  96.             establish_window(vx, 2, vx+wd+1, ht+3, MENUFG, MENUBG,TRUE);
  97.             text_window((mn+hsel-1)->mselcs, 1);
  98.             sel = select_window((mn+hsel-1)->lastvsel, SELECTFG, SELECTBG, vlook);
  99.             delete_window();
  100.             if (sel == FWD || sel == BS)
  101.                 haccent(sel);
  102.             else
  103.                 return ((mn+hsel-1)->lastvsel = sel);
  104.         }
  105.         else    {
  106.             if ((sel = getkey()) == *(mn+hsel-1)->mskeys)
  107.                 return 1;
  108.             switch (sel)    {
  109.                 case FWD:
  110.                 case BS:    haccent(sel);
  111.                             break;
  112.                 case '\r':    return 1;
  113.                 case ESC:    return 0;
  114.                 default:    putch(BELL);
  115.                             break;
  116.             }
  117.         }
  118.     }
  119. }
  120.  
  121. /* ---- if vertical menu user types FWD, BS, or a menu key, return it ---- */
  122. static int vlook(ch, sel)
  123. {
  124.     char *cs, *ks;
  125.  
  126.     if (ch == FWD || ch == BS)    {
  127.         (mn+hsel-1)->lastvsel = sel;
  128.         return ch;
  129.     }
  130.     ks = (mn+hsel-1)->mskeys;
  131.     if ((cs = memchr(ks, tolower(ch), strlen(ks))) == NULL)
  132.         return ERROR;
  133.     return ((mn+hsel-1)->lastvsel = cs-ks+1);
  134. }
  135.  
  136. /* ----- manage the horizontal menu selection accent ----- */
  137. static void haccent(int sel)
  138. {
  139.     switch (sel)    {
  140.         case FWD:
  141.             light(OFF);
  142.             if ((mn+hsel)->mname)
  143.                 hsel++;
  144.             else
  145.                 hsel = 1;
  146.             light(ON);
  147.             break;
  148.         case BS:
  149.             light(OFF);
  150.             if (hsel == 1)
  151.                 while ((mn+hsel)->mname)
  152.                     hsel++;
  153.             else
  154.                 --hsel;
  155.             light(ON);
  156.             break;
  157.         default:
  158.             break;
  159.     }
  160. }
  161.  
  162. /* ---------- compute a menu's height & width --------- */
  163. static void dimension(char *sl[], int *ht, int *wd)
  164. {
  165.     *ht = *wd = 0;
  166.  
  167.     while (sl && sl [*ht])    {
  168.         *wd = max(*wd, (unsigned) strlen(sl [*ht]));
  169.         (*ht)++;
  170.     }
  171. }
  172.  
  173. /* --------- accent a horizontal menu selection ---------- */
  174. static void light(int onoff)
  175. {
  176.     extern struct wn wkw;
  177.     extern char spaces[];
  178.     int ln;
  179.  
  180.     window(1,1,80,25);
  181.      textcolor(onoff ? SELECTFG : MENUFG);
  182.      textbackground(onoff ? SELECTBG : MENUBG);
  183.      gotoxy((hsel-1)*12+6, 1);
  184.     cprintf((mn+hsel-1)->mname);
  185.     textcolor(TEXTFG);
  186.     textbackground(TEXTBG);
  187.     if ((mn+hsel-1)->mhlpmsg)    {
  188.         if (onoff)    {
  189.             ln = strlen((mn+hsel-1)->mhlpmsg);
  190.             gotoxy((80-ln)/2,25);
  191.             cprintf((mn+hsel-1)->mhlpmsg);
  192.         }
  193.         else    {
  194.             gotoxy(1,25);
  195.             cprintf(spaces);
  196.         }
  197.     }
  198.     current_window();
  199.     hidecursor();
  200. }
  201.  
  202.