home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_06 / 1006102a < prev    next >
Text File  |  1992-04-17  |  10KB  |  388 lines

  1.  
  2. /************************************************************
  3.  * Program: RMENU Menu Interpreter
  4.  *  Module: rmenu2.c
  5.  * Top-level menu processing
  6.  * Written by: Leor Zolman, 7/91
  7.  ************************************************************/
  8.  
  9. #include "cmenu.h"
  10. #include "rcmenu.h"
  11.  
  12. #if __STDC
  13. #pragma hdrstop
  14. #endif
  15.  
  16. #include <ctype.h>
  17.  
  18.  
  19. /************************************************************
  20.  * sub_menu(): 
  21.  * Run a local menu at the given nesting level
  22.  * Default command/menu path is supplied via "path".
  23.  ************************************************************/
  24.  
  25. int sub_menu(mnum, path)
  26. int mnum;
  27. char *path;
  28. {
  29.    MENU2 *M2p = LMenus[nestlev].Menus[mnum];
  30.    MENU *Mp = &M2p -> Menu;
  31.    char newpath[MAX_PATH];
  32.    
  33.    int cur_item = 0;
  34.    int sel_val = 0;
  35.    int factor;
  36.    
  37.    draw_menu(M2p, cur_item);               /* display the menu     */
  38.  
  39.    strcpy(newpath, make_path(path, Mp -> path));
  40.  
  41.    while (1)
  42.    {
  43.       switch (get_cmd(Mp -> nitems, cur_item, &sel_val))
  44.       {
  45.          case  KEY_UP:
  46.             draw_item(M2p, cur_item, NORMAL, NO);
  47.             cur_item = cur_item ? cur_item - 1 :
  48.                   Mp -> nitems - 1;
  49.             draw_item(M2p, cur_item, STANDOUT, YES);
  50.             break;
  51.             
  52.          case KEY_DOWN:
  53.             draw_item(M2p, cur_item, NORMAL, NO);
  54.             cur_item = (cur_item == Mp -> nitems - 1) ? 0 :
  55.                   cur_item + 1;
  56.             draw_item(M2p, cur_item, STANDOUT, YES);
  57.             break;
  58.  
  59.          case KEY_RIGHT:
  60.             if (Mp -> columns == 1)
  61.                break;
  62.  
  63.             draw_item(M2p, cur_item, NORMAL, NO);
  64.  
  65.             factor = MAX_IROWS / Mp -> spacing;
  66.             if (cur_item + factor < Mp -> nitems)
  67.                cur_item += factor;
  68.             else
  69.                cur_item %= factor;
  70.  
  71.             draw_item(M2p, cur_item, STANDOUT, YES);
  72.             break;
  73.             
  74.          case KEY_LEFT:
  75.             if (Mp -> columns == 1)
  76.                break;
  77.             draw_item(M2p, cur_item, NORMAL, NO);
  78.  
  79.             factor = MAX_IROWS / Mp -> spacing;
  80.             if (cur_item >= factor)
  81.                cur_item -= factor;
  82.             else
  83.                while (cur_item + factor < Mp -> nitems)
  84.                   cur_item += factor;
  85.  
  86.             draw_item(M2p, cur_item, STANDOUT, YES);
  87.             break;
  88.             
  89.          case KEY_SHOW:
  90.             show_item(M2p, cur_item, newpath);
  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.