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 / RMENU1.C < prev    next >
C/C++ Source or Header  |  1992-05-22  |  9KB  |  378 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu1.c
  4.  *        Main and Utility Functions
  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. #    include <stdarg.h>
  14. #else
  15. #    include <varargs.h>
  16. #endif
  17.  
  18. /********************** Global Data *************************/
  19.  
  20. LEVELS LMenus[MAX_NEST];
  21. int    nestlev;                /* current nesting level        */
  22. int    echox, echoy;            /* Location of item # echo area */
  23. int    debug;                    /* true to display sys commands    */
  24. char SysShell[80];            /* System command interpreter    */
  25. char sav_cmd[80];            /* Saved system command            */
  26.  
  27. /************************************************************
  28.  * main():
  29.  *    Initialize the program and run
  30.  *    the master menu
  31.  ************************************************************/
  32.  
  33. main(argc, argv)
  34. int argc;
  35. char **argv;
  36. {
  37.     char *mname = "menu";
  38.     int i, j;
  39.  
  40.     debug = 0;                    /* No debugging by default        */
  41.     *sav_cmd = '\0';            /* No saved system command yet    */
  42.  
  43.                                 /* Process command line options: */
  44.     for (i = 1; i < argc; i++)
  45.         if (argv[i][0] == '-')
  46.         {
  47.             switch (tolower(argv[i][1]))
  48.             {
  49.                 case 'd':    debug = TRUE;
  50.                             break;
  51.  
  52.                 default:    fprintf(stderr, "Unknown option: '%s'\n",
  53.                                         argv[i]);
  54.                             exit(0);
  55.             }
  56.             for (j = i; j < argc - 1; j++)    /* compress */
  57.                 argv[j] = argv[j + 1];        /* arg list */
  58.             argc--;
  59.             i--;
  60.         }
  61.  
  62.     init_win();        /* initialize curses */
  63.  
  64.     if (argc == 2)
  65.         mname = argv[1];
  66.  
  67.     nestlev = 0;
  68.     do_menu("", mname);
  69.     free_menus();
  70.     close_win();
  71.                     /* If user pressed "x" while viewing an    */
  72.     if (*sav_cmd)    /* action command, show it upon exit:    */
  73.         printf("The viewed action command was:\n\t%s\n", sav_cmd);
  74.  
  75.     return OK;
  76. }
  77.  
  78.  
  79. /************************************************************
  80.  * do_menu(): 
  81.  *    Run a compiled menu file, supporting recursive
  82.  *    calls for nested external menus.
  83.  *    Default command/menu path is supplied as "path".
  84.  ************************************************************/
  85.  
  86. int do_menu(path, file)
  87. char *path, *file;
  88. {
  89.     char pathname[MAX_PATH];
  90.     
  91.     strcpy(pathname, path);
  92.     if (*path) 
  93.         strcat(pathname, "/");
  94.     strcat(pathname, file);
  95.     strcat(pathname, ".mnc");
  96.  
  97.     if (ld_menu(pathname) == ERROR)
  98.         return EXITALL;
  99.  
  100.     return sub_menu(0, path);    /* run main menu in file */ 
  101. }
  102.  
  103.         
  104. /************************************************************
  105.  * ld_menu():
  106.  *    Load a compiled menu object file from disk,
  107.  *    into nesting level nestlev, allocating memory
  108.  *    as required.
  109.  *    For each menu in the menu file being loaded,
  110.  *    compute screen placement as per spacing/columns
  111.  *    specifications and the total number of items.
  112.  ************************************************************/
  113.  
  114. int ld_menu(path)
  115. char *path;
  116. {
  117.     LEVELS *Levp = &LMenus[nestlev];
  118.     MENU *Mp;
  119.     ITEM *Ip;
  120.     MENU2 *M2p;
  121.  
  122.     FILE *fp;
  123.     int widest;
  124.     int i, j, k, l;
  125.     
  126.     if ((fp = fopen(path, "rb")) == NULL)
  127.         return fatal("Can't open %s", path);
  128.     
  129.     if (fread((Void *) &Levp->n_menus, sizeof (int), 1, fp)
  130.                     != 1)
  131.         return fatal("Error reading menu count from %s", path);
  132.     
  133.     for (i = 0; i < Levp->n_menus; i++)
  134.     {
  135.         if (i < Levp -> max_menus)
  136.             M2p = Levp -> Menus[i];
  137.         else                        /* allocate memory for Menu    */
  138.         {
  139.             M2p = Levp -> Menus[i] = (MENU2 *) malloc(sizeof(MENU2));
  140.             if (M2p == NULL)
  141.                 return fatal("Out of memory loading %s", path);
  142.             Levp -> max_menus++;
  143.             M2p -> most_items = 0;
  144.         }
  145.  
  146.         Mp = &M2p -> Menu;
  147.         
  148.         if (fread((Void *) Mp, sizeof(MENU), 1, fp) != 1)
  149.             return fatal("Error reading Menu data from %s", path);
  150.         
  151.     /* Now determine screen placement strategy. */
  152.  
  153.         placement(Mp);
  154.  
  155.         M2p -> field_len = min(MAX_TXTWID, 
  156.                     (SCREEN_COLS / Mp -> columns) - 5);
  157.  
  158.     /* Read in each item, and assign screen coordinate info */
  159.     /* to each on-the-fly as per spacing/column parameters    */
  160.         
  161.         for (j = 0; j < Mp -> nitems; j++)
  162.         {
  163.             if (j < M2p -> most_items)
  164.                 Ip = M2p -> Items[j];
  165.             else
  166.             {
  167.                 Ip = M2p -> Items[j] = (ITEM *) malloc(sizeof(ITEM));
  168.                 if (Ip == NULL)
  169.                    return fatal("Out of memory loading %s, menu #%d/item #%d",
  170.                         path, i,j);
  171.                 M2p -> most_items++;
  172.             }
  173.             if (fread((Void *) Ip, sizeof(ITEM), 1, fp) != 1)
  174.                 return fatal("Error reading %s", path);
  175.  
  176.             Ip -> text[M2p -> field_len - 1] = '\0'; /* truncate */
  177.  
  178.             if ((Ip -> acttyp == ACT_LMENU ||
  179.                  Ip -> acttyp == ACT_EMENU) &&
  180.                 strlen(Ip -> text) + 6 < M2p -> field_len)
  181.             {
  182.                 int limit;
  183.                 
  184.                 limit = min (Mp -> widest + 2,
  185.                         M2p -> field_len - 7);
  186.                 for (k = strlen(Ip -> text);
  187.                         k < limit && k < (MAX_TXTWID - 6); k++)
  188.                     strcat(Ip -> text, " ");
  189.                 strcat(Ip -> text, "(MENU)");
  190.             }
  191.  
  192.             M2p -> coords[j].ypos = 
  193.                     HOME_Y + (j % (MAX_IROWS / Mp -> spacing))
  194.                                 * Mp -> spacing;
  195.  
  196.             widest = Mp -> widest;
  197.             M2p -> coords[j].xpos = HOME_X + 
  198.                     (
  199.                       (Mp -> columns == 1)
  200.                               ? 
  201.                       (
  202.                           (SCREEN_COLS - HOME_X -
  203.                          (widest + ((widest < 66) ? 14 : 6) )) / 2
  204.                       )
  205.                             :
  206.                       (j / (MAX_IROWS / Mp -> spacing) *
  207.                            (SCREEN_COLS / Mp -> columns))
  208.                     );
  209.  
  210.  
  211.             M2p -> coords[j].spaces_needed = 
  212.                     min(M2p -> field_len, Mp -> widest)
  213.                             - strlen(Ip -> text);
  214.         }
  215.     }
  216.     fclose(fp);
  217.     return OK;
  218. }
  219.  
  220.  
  221. /************************************************************
  222.  * placement():
  223.  *    Calculate values for columns and spacing 
  224.  *    for the given Menu:
  225.  ************************************************************/
  226.  
  227. Void placement(Mp)
  228. MENU *Mp;
  229. {
  230.     int columns = Mp -> columns;
  231.     int spacing = Mp -> spacing;
  232.     int nitems = Mp -> nitems;
  233.  
  234.     /* Step 1: fill in real values if either    */
  235.     /*    columns or spacing was not specified:    */
  236.  
  237.     if (spacing == DEFAULT && columns == DEFAULT)
  238.     {
  239.         if (nitems <= (MAX_IROWS / 2))
  240.         {
  241.             Mp -> columns = 1;
  242.             Mp -> spacing = 2;
  243.         }
  244.         else if (nitems <= MAX_IROWS)
  245.             if ((Mp -> widest * 2 + 5) <= SCREEN_COLS)
  246.                 Mp -> columns = Mp -> spacing = 2;
  247.             else
  248.                 Mp -> columns = Mp -> spacing = 1;
  249.         else
  250.         {
  251.             Mp -> spacing = 1;
  252.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  253.         }
  254.     }
  255.     else if (spacing == DEFAULT)
  256.         Mp -> spacing =
  257.                 (nitems <= (MAX_IROWS / 2)) ? 2 : 1;
  258.     else if (columns == DEFAULT)
  259.         if (Mp -> spacing == 1)
  260.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  261.         else
  262.             Mp -> columns = (nitems - 1) / (MAX_IROWS / 2) + 1;
  263.         
  264.     /* Step 2: Adjust if out of range: */
  265.             
  266.     while (MAX_IROWS / Mp -> spacing * Mp -> columns < nitems)
  267.         if (Mp -> spacing != 1)
  268.             Mp -> spacing = 1;
  269.         else
  270.             Mp -> columns++;
  271.     return;
  272. }
  273.  
  274.  
  275. /************************************************************
  276.  * free_menus():
  277.  *    Free up memory allocated for ALL menu items:
  278.  ************************************************************/
  279.  
  280. Void free_menus()
  281. {
  282.     int i, j, k;
  283.     MENU2 *m2p;
  284.     
  285.     for (i = 0; i < MAX_NEST; i++)
  286.         for (j = 0; j < LMenus[i].max_menus; j++)
  287.         {
  288.             m2p = LMenus[i].Menus[j];
  289.             for (k = 0; k < m2p -> most_items; k++)
  290.                 free(m2p -> Items[k]);
  291.             free(m2p);
  292.         }
  293. }
  294.  
  295.  
  296. /************************************************************
  297.  * fatal(): Complain and exit.
  298.  ************************************************************/
  299.  
  300. #if __STDC__                 /* use ANSI variable-#-of-args method    */
  301.  
  302. int fatal (char *fmt, ...)
  303. {
  304.     char ftext[80], ffmt[55];
  305.     va_list arglist;
  306.     
  307.     va_start(arglist, fmt);
  308.  
  309. #else                        /* or old varargs method:                */
  310.  
  311. int fatal(fmt, va_alist)
  312. char *fmt;
  313. va_dcl
  314. {
  315.     char ftext[80], ffmt[55];
  316.     va_list arglist;
  317.     
  318.     va_start(arglist);
  319. #endif
  320.  
  321.     vsprintf(ffmt, fmt, arglist);
  322.     sprintf(ftext, "Fatal error in rmenu: %s", ffmt);
  323.  
  324.     put_msg(1, ftext);
  325.  
  326.     va_end(arglist);
  327.     return ERROR;
  328. }
  329.  
  330.  
  331. /************************************************************
  332.  * put_msg(): Display a message on the menu screen
  333.  *    Return the character typed to continue
  334.  ************************************************************/
  335.  
  336. #if __STDC__
  337. int put_msg (int bell, char *fmt, ...)
  338. {
  339.     char ftext[80];
  340.     va_list arglist;
  341.     char c;
  342.     
  343.     va_start(arglist, fmt);
  344.     
  345. #else
  346. int put_msg(bell, fmt, va_alist)
  347. int bell;
  348. char *fmt;
  349. va_dcl
  350. {
  351.     char ftext[80];
  352.     va_list arglist;
  353.     char c;
  354.     
  355.     va_start(arglist);
  356. #endif
  357.     
  358.     move(ERR_ROW, 0);
  359.     hlight_on();
  360.  
  361.     if (bell)
  362.         beep();
  363.  
  364. /*    vwprintw(stdscr, fmt, arglist); */
  365.     vsprintf(ftext, fmt, arglist);
  366.     addstr(ftext);
  367.     va_end(arglist);
  368.     refresh();
  369.  
  370.     c = getch();
  371.  
  372.     move (ERR_ROW, 0);
  373.     hlight_end();
  374.     clrtoeol();
  375.     refresh();
  376.     return c;
  377. }
  378.