home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_06 / cmenu13.exe / RMENU2.C < prev    next >
C/C++ Source or Header  |  1992-05-22  |  8KB  |  388 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu2.c
  4.  *    Top-level menu processing
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #include "cmenu.h"
  9. #include "rcmenu.h"
  10.  
  11. #if __STDC
  12. #pragma hdrstop
  13. #endif
  14.  
  15. #include <ctype.h>
  16.  
  17.  
  18. /************************************************************
  19.  * sub_menu(): 
  20.  *    Run a local menu at the given nesting level
  21.  *    Default command/menu path is supplied via "path".
  22.  ************************************************************/
  23.  
  24. int sub_menu(mnum, path)
  25. int mnum;
  26. char *path;
  27. {
  28.     MENU2 *M2p = LMenus[nestlev].Menus[mnum];
  29.     MENU *Mp = &M2p -> Menu;
  30.     char newpath[MAX_PATH];
  31.     
  32.     int cur_item = 0;
  33.     int sel_val = 0;
  34.     int factor;
  35.     
  36.     draw_menu(M2p, cur_item);        /* display the menu        */
  37.  
  38.     strcpy(newpath, make_path(path, Mp -> path));
  39.  
  40.     while (1)
  41.     {
  42.         switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
  43.         {
  44.             case  KEY_UP:
  45.                 draw_item(M2p, cur_item, NORMAL, NO);
  46.                 cur_item = cur_item ? cur_item - 1 :
  47.                         Mp -> nitems - 1;
  48.                 draw_item(M2p, cur_item, STANDOUT, YES);
  49.                 break;
  50.                 
  51.             case KEY_DOWN:
  52.                 draw_item(M2p, cur_item, NORMAL, NO);
  53.                 cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
  54.                         cur_item + 1;
  55.                 draw_item(M2p, cur_item, STANDOUT, YES);
  56.                 break;
  57.  
  58.             case KEY_RIGHT:
  59.                 if (Mp -> columns == 1)
  60.                     break;
  61.  
  62.                 draw_item(M2p, cur_item, NORMAL, NO);
  63.  
  64.                 factor = MAX_IROWS / Mp -> spacing;
  65.                 if (cur_item + factor < Mp -> nitems)
  66.                     cur_item += factor;
  67.                 else
  68.                     cur_item %= factor;
  69.  
  70.                 draw_item(M2p, cur_item, STANDOUT, YES);
  71.                 break;
  72.                 
  73.             case KEY_LEFT:
  74.                 if (Mp -> columns == 1)
  75.                     break;
  76.                 draw_item(M2p, cur_item, NORMAL, NO);
  77.  
  78.                 factor = MAX_IROWS / Mp -> spacing;
  79.                 if (cur_item >= factor)
  80.                     cur_item -= factor;
  81.                 else
  82.                     while (cur_item + factor < Mp -> nitems)
  83.                         cur_item += factor;
  84.  
  85.                 draw_item(M2p, cur_item, STANDOUT, YES);
  86.                 break;
  87.                 
  88.             case KEY_SHOW:
  89.                 if (show_item(M2p, cur_item, newpath) == EXITALL)
  90.                     return EXITALL;
  91.                 break;
  92.                 
  93.             case KEY_RUN:
  94.                 if (M2p -> Items[cur_item] -> acttyp == ACT_EXIT)
  95.                     return OK;
  96.                 if (do_item(M2p, cur_item, newpath) == EXITALL)
  97.                     return EXITALL;
  98.  
  99.                 switch(M2p -> Items[cur_item] -> nextcode)
  100.                 {
  101.                     case NXT_FIRST:
  102.                         cur_item = 0;
  103.                         break;
  104.                         
  105.                     case NXT_LAST:
  106.                         cur_item = M2p -> Menu.nitems - 1;
  107.                         break;
  108.                     
  109.                     case NXT_NEXT:
  110.                         if (cur_item < M2p -> Menu.nitems - 1)
  111.                             cur_item++;
  112.                         break;
  113.                         
  114.                     case NXT_DIRECT:
  115.                         cur_item = M2p -> Items[cur_item] -> nextitem;
  116.                         break;
  117.                 }
  118.  
  119.                 draw_menu(M2p, cur_item);   /* redisplay menu */
  120.                 break;
  121.                 
  122.             case K_DIRECT:
  123.                 if ((sel_val - 1) != cur_item)
  124.                 {
  125.                     draw_item(M2p, cur_item, NORMAL, NO);
  126.                     cur_item = sel_val - 1;
  127.                     draw_item(M2p, cur_item, STANDOUT, YES);
  128.                 }
  129.                 break;
  130.  
  131.             case K_SHELL:
  132.                 if (M2p -> Menu.escape == YES ||
  133.                   (M2p -> Menu.escape == DEFAULT && DEF_ESCAPE == YES))
  134.                 {
  135. #if SHELL_PROMPT
  136.                     if (put_msg(0, SH_PROMPT_STR) == ESC)
  137.                         break;
  138. #else
  139.                     move(ERR_ROW, 0);
  140.                     hlight_on();
  141.                     addstr("Invoking shell. . .");
  142.                     hlight_end();
  143. #endif
  144.  
  145.                     pre_shell();        /* set up for shell call    */
  146.                     system(SysShell);    /* run a shell                */
  147.                     post_shell();        /* restore everything        */
  148.  
  149.                     draw_menu(M2p, cur_item);
  150.                 }
  151.                 else
  152.                   put_msg(1, "Sorry, shell escapes are disabled.");
  153.                 break;
  154.  
  155.             case K_EXIT:
  156.                 return OK;
  157.  
  158.             case K_EXITALL:
  159.                 return EXITALL;
  160.  
  161.             case K_VERSION:
  162.                 put_msg(0, " RMENU Menu Interpreter v%s ",
  163.                              VERSION);
  164.                 break;
  165.  
  166.             case K_UNKNOWN:
  167.                 beep();
  168.         }
  169.         refresh();
  170.     }
  171. }
  172.  
  173.  
  174. /************************************************************
  175.  * draw_menu(): 
  176.  *    Display the entire menu, including all prompts,
  177.  *    and titles and help text (if any) for current item
  178.  *    on the screen.
  179.  ************************************************************/
  180.  
  181. Void draw_menu(M2p, curr)
  182. MENU2 *M2p;
  183. int curr;
  184. {
  185.     MENU *Mp = &M2p -> Menu;
  186.     int title_len = strlen(Mp -> title);
  187.     int i, j; 
  188.     
  189.     clear();
  190.  
  191.     move(TITLE_ROW, (SCREEN_COLS - title_len)/2);
  192.     addstr(Mp -> title);    /* Put up menu title */
  193.  
  194.     for (i = 0; i < Mp -> nitems; i++)
  195.         if (i != curr)
  196.             draw_item(M2p, i, NORMAL, NO);
  197.  
  198.     draw_item(M2p, curr, STANDOUT, YES);
  199.  
  200.     move(PROMPT_ROW, 0);
  201.     addstr(MENU_OPTS);
  202.     if (Mp -> escape == YES ||
  203.             (Mp -> escape == DEFAULT && DEF_ESCAPE == YES))
  204.         addstr(MENU_SHELL);
  205.     addstr(MENU_PROMPT);
  206.     getyx(stdscr, echoy, echox);    /* save coords of item # echo area */
  207.         
  208.     refresh();    /* display the window */
  209.  
  210. }
  211.  
  212.  
  213. /************************************************************
  214.  * draw_item():
  215.  *    Display a single item (the current item) of the
  216.  *    specified menu, using the specified video mode.
  217.  *    Display assiciated help text only if "dohelp"
  218.  *    is TRUE.
  219.  ************************************************************/
  220.  
  221. Void draw_item(M2p, item, vid_mode, dohelp)
  222. MENU2 *M2p;
  223. int item, vid_mode, dohelp;
  224. {
  225.     ITEM *Ip = M2p -> Items[item];
  226.     COORDS *Cp = &M2p -> coords[item];
  227.     int j;
  228.     int help_len;
  229.  
  230.     move (Cp->ypos, Cp->xpos);
  231.     printw("%2d.", item + 1);
  232.  
  233.     if (vid_mode == STANDOUT)
  234.         hlight_on();
  235.  
  236.     printw(" %s", Ip -> text);
  237.  
  238.     for (j = 0; j < Cp -> spaces_needed; j++)
  239.             addch(' ');
  240.  
  241.     if (vid_mode == STANDOUT)
  242.         hlight_end();
  243.  
  244.  
  245.     if (dohelp == YES)
  246.     {
  247.         move(HELP_ROW0, HELP_COL0);
  248.         if (*Ip -> help)
  249.         {
  250.             addstr(" HELP: ");    /* display "HELP:" text    */
  251.  
  252.             move (HELP_ROW, 0);    /* Erase preivous help text (if any) */
  253.             clrtoeol();
  254.  
  255.             help_len = strlen(Ip -> help);
  256.             if (help_len > (SCREEN_COLS - 6))
  257.                 move (HELP_ROW, (80 - strlen(Ip -> help))/2);
  258.             else
  259.                 move (HELP_ROW, (80 - help_len)/2 - 2);
  260.  
  261.             hlight_on();
  262.             if (help_len <= (SCREEN_COLS - 6))
  263.                 addstr(" ");
  264.             addstr(Ip -> help);
  265.             if (help_len <= (SCREEN_COLS - 6))
  266.                 addstr(" ");
  267.             hlight_end();
  268.             clrtoeol();
  269.         }
  270.         else
  271.         {
  272.             addstr("       ");    /* clear help text area    */
  273.             move(HELP_ROW, 0);
  274.         }
  275.         clrtoeol();
  276.     }
  277. }
  278.  
  279.  
  280. /************************************************************
  281.  * get_cmd()
  282.  *    Get a command from the user.
  283.  *    Arrow keys or space returns the appropriate K_ code.
  284.  *    Pressing Enter returns the K_RUN code.
  285.  *    Pressing ! returns the K_SHELL code.
  286.  *    Entering a direct number returns K_DIRECT,
  287.  *    and the sel_val is set (indirectly) to selection number
  288.  *  (1-based).
  289.  ************************************************************/
  290.  
  291. int get_cmd(nitems, curr, sel_val)
  292. int nitems;
  293. int curr;
  294. int *sel_val;
  295. {
  296.     int ch;
  297.     int newval;
  298.     int savy, savx;
  299.  
  300.     static int digits = FALSE;    /* true if digits being entered */
  301.     
  302.     move(echoy, echox);    /* move to prompt location */
  303.     printw("%d", curr + 1);
  304.     getyx(stdscr, savy, savx);
  305.     clrtoeol();
  306.     move(savy, savx);
  307.     refresh();
  308.     
  309.     while (1)
  310.     {
  311.         ch = getch();
  312.         if (!isdigit(ch))
  313.             digits = FALSE;
  314.         switch (ch)
  315.         {
  316.             case KEY_UP:
  317.             case '\b':        /* WYSE 60s send this for left arrow */
  318.                 clrtoeol();
  319.                 return KEY_UP;
  320.  
  321.             case ' ':
  322.             case KEY_DOWN:
  323. #if UNIX || XENIX
  324.             case '\n':        /* WYSE 60s send this for down arrow */
  325. #endif
  326.                 clrtoeol();
  327.                 return KEY_DOWN;
  328.  
  329.             case KEY_RIGHT:
  330.             case KEY_LEFT:
  331.             case KEY_RUN:
  332.             case KEY_SHOW:
  333.                 return ch;
  334.  
  335.             case 'e':
  336.             case 'E':
  337.                 return K_EXIT;
  338.  
  339.             case 'x':
  340.             case 'X':
  341.                 return K_EXITALL;
  342.                 
  343.             case 'v':
  344.             case 'V':
  345.                 return K_VERSION;
  346.  
  347.             case '!':
  348.                 return K_SHELL;
  349.  
  350.             case ESC:        /* clear digits area */
  351.                 digits = FALSE;
  352.                 move(echoy, echox);    
  353.                 clrtoeol();
  354.                 refresh();
  355.                 break;
  356.                 
  357.             default:        /* handle digits */
  358.                 if (!isdigit(ch))
  359.                     return K_UNKNOWN;
  360.  
  361.                 if (digits && 
  362.                     (newval = *sel_val * 10 + (ch - '0')) <= nitems
  363.                         && newval > 0)
  364.                 {
  365.                     addch(ch);
  366.                     refresh();
  367.                     *sel_val = newval;
  368.                     return K_DIRECT;
  369.                 }
  370.                 else if ( (newval = ch - '0') && newval <= nitems)
  371.                 {
  372.                     digits = TRUE;
  373.                     move(echoy, echox);    
  374.                     addch(ch);
  375.                     clrtoeol();
  376.                     refresh();
  377.                     *sel_val = newval;
  378.                     return K_DIRECT;
  379.                 }
  380.                 else
  381.                 {
  382.                     digits = FALSE;
  383.                     beep();
  384.                 }
  385.         }
  386.     }
  387. }
  388.