home *** CD-ROM | disk | FTP | other *** search
- /************************************************************
- * Program: RMENU Menu Interpreter
- * Module: rmenu1.c
- * Main and Utility Functions
- * Written by: Leor Zolman, 7/91
- ************************************************************/
-
- #include "cmenu.h"
- #include "rcmenu.h"
-
- #if __STDC__
- # pragma hdrstop
- # include <stdarg.h>
- #else
- # include <varargs.h>
- #endif
-
- /********************** Global Data *************************/
-
- LEVELS LMenus[MAX_NEST];
- int nestlev; /* current nesting level */
- int echox, echoy; /* Location of item # echo area */
- int debug; /* true to display sys commands */
- char SysShell[80]; /* System command interpreter */
-
- /************************************************************
- * main():
- * Initialize the program and run
- * the master menu
- ************************************************************/
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- char *mname = "menu";
- int i, j;
-
- debug = 0; /* No debugging by default */
-
- /* Process command line options: */
- for (i = 1; i < argc; i++)
- if (argv[i][0] == '-')
- {
- switch (tolower(argv[i][1]))
- {
- case 'd': debug = TRUE;
- break;
-
- default: fprintf(stderr, "Unknown option: '%s'\n",
- argv[i]);
- exit(0);
- }
- for (j = i; j < argc - 1; j++) /* compress */
- argv[j] = argv[j + 1]; /* arg list */
- argc--;
- i--;
- }
-
- init_win(); /* initialize curses */
-
- if (argc == 2)
- mname = argv[1];
-
- nestlev = 0;
- do_menu("", mname);
- free_menus();
- close_win();
- return OK;
- }
-
-
- /************************************************************
- * do_menu():
- * Run a compiled menu file, supporting recursive
- * calls for nested external menus.
- * Default command/menu path is supplied as "path".
- ************************************************************/
-
- int do_menu(path, file)
- char *path, *file;
- {
- char pathname[MAX_PATH];
-
- strcpy(pathname, path);
- if (*path)
- strcat(pathname, "/");
- strcat(pathname, file);
- strcat(pathname, ".mnc");
-
- if (ld_menu(pathname) == ERROR)
- return EXITALL;
-
- return sub_menu(0, path); /* run main menu in file */
- }
-
-
- /************************************************************
- * ld_menu():
- * Load a compiled menu object file from disk,
- * into nesting level nestlev, allocating memory
- * as required.
- * For each menu in the menu file being loaded,
- * compute screen placement as per spacing/columns
- * specifications and the total number of items.
- ************************************************************/
-
- int ld_menu(path)
- char *path;
- {
- LEVELS *Levp = &LMenus[nestlev];
- MENU *Mp;
- ITEM *Ip;
- MENU2 *M2p;
-
- FILE *fp;
- int widest;
- int i, j, k, l;
-
- if ((fp = fopen(path, "rb")) == NULL)
- return fatal("Can't open %s", path);
-
- if (fread((Void *) &Levp->n_menus, sizeof (int), 1, fp)
- != 1)
- return fatal("Error reading menu count from %s", path);
-
- for (i = 0; i < Levp->n_menus; i++)
- {
- if (i < Levp -> max_menus)
- M2p = Levp -> Menus[i];
- else /* allocate memory for Menu */
- {
- M2p = Levp -> Menus[i] = (MENU2 *) malloc(sizeof(MENU2));
- if (M2p == NULL)
- return fatal("Out of memory loading %s", path);
- Levp -> max_menus++;
- M2p -> most_items = 0;
- }
-
- Mp = &M2p -> Menu;
-
- if (fread((Void *) Mp, sizeof(MENU), 1, fp) != 1)
- return fatal("Error reading Menu data from %s", path);
-
- /* Now determine screen placement strategy. */
-
- placement(Mp);
-
- M2p -> field_len = min(MAX_TXTWID,
- (SCREEN_COLS / Mp -> columns) - 5);
-
- /* Read in each item, and assign screen coordinate info */
- /* to each on-the-fly as per spacing/column parameters */
-
- for (j = 0; j < Mp -> nitems; j++)
- {
- if (j < M2p -> most_items)
- Ip = M2p -> Items[j];
- else
- {
- Ip = M2p -> Items[j] = (ITEM *) malloc(sizeof(ITEM));
- if (Ip == NULL)
- return fatal("Out of RAM in %s, menu #%d/item #%d",
- path, i,j);
- M2p -> most_items++;
- }
- if (fread((Void *) Ip, sizeof(ITEM), 1, fp) != 1)
- return fatal("Error reading %s", path);
-
- Ip -> text[M2p -> field_len - 1] = '\0'; /* truncate */
-
- if ((Ip -> acttyp == ACT_LMENU ||
- Ip -> acttyp == ACT_EMENU) &&
- strlen(Ip -> text) + 6 < M2p -> field_len)
- {
- int limit;
-
- limit = min (Mp -> widest + 2,
- M2p -> field_len - 7);
- for (k = strlen(Ip -> text);
- k < limit && k < (MAX_TXTWID - 6); k++)
- strcat(Ip -> text, " ");
- strcat(Ip -> text, "(MENU)");
- }
-
- M2p -> coords[j].ypos =
- HOME_Y + (j % (MAX_IROWS / Mp -> spacing))
- * Mp -> spacing;
-
- widest = Mp -> widest;
- M2p -> coords[j].xpos = HOME_X +
- (
- (Mp -> columns == 1)
- ?
- (
- (SCREEN_COLS - HOME_X -
- (widest + ((widest < 66) ? 14 : 6) )) / 2
- )
- :
- (j / (MAX_IROWS / Mp -> spacing) *
- (SCREEN_COLS / Mp -> columns))
- );
-
-
- M2p -> coords[j].spaces_needed =
- min(M2p -> field_len, Mp -> widest)
- - strlen(Ip -> text);
- }
- }
- fclose(fp);
- return OK;
- }
-
-
- /************************************************************
- * placement():
- * Calculate values for columns and spacing
- * for the given Menu:
- ************************************************************/
-
- Void placement(Mp)
- MENU *Mp;
- {
- int columns = Mp -> columns;
- int spacing = Mp -> spacing;
- int nitems = Mp -> nitems;
-
- /* Step 1: fill in real values if either */
- /* columns or spacing was not specified: */
-
- if (spacing == DEFAULT && columns == DEFAULT)
- {
- if (nitems <= (MAX_IROWS / 2))
- {
- Mp -> columns = 1;
- Mp -> spacing = 2;
- }
- else if (nitems <= MAX_IROWS)
- if ((Mp -> widest * 2 + 5) <= SCREEN_COLS)
- Mp -> columns = Mp -> spacing = 2;
- else
- Mp -> columns = Mp -> spacing = 1;
- else
- {
- Mp -> spacing = 1;
- Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
- }
- }
- else if (spacing == DEFAULT)
- Mp -> spacing =
- (nitems <= (MAX_IROWS / 2)) ? 2 : 1;
- else if (columns == DEFAULT)
- if (Mp -> spacing == 1)
- Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
- else
- Mp -> columns = (nitems - 1) / (MAX_IROWS / 2) + 1;
-
- /* Step 2: Adjust if out of range: */
-
- while (MAX_IROWS / Mp -> spacing * Mp -> columns < nitems)
- if (Mp -> spacing != 1)
- Mp -> spacing = 1;
- else
- Mp -> columns++;
- return;
- }
-
-
- /************************************************************
- * free_menus():
- * Free up memory allocated for ALL menu items:
- ************************************************************/
-
- Void free_menus()
- {
- int i, j, k;
- MENU2 *m2p;
-
- for (i = 0; i < MAX_NEST; i++)
- for (j = 0; j < LMenus[i].max_menus; j++)
- {
- m2p = LMenus[i].Menus[j];
- for (k = 0; k < m2p -> most_items; k++)
- free(m2p -> Items[k]);
- free(m2p);
- }
- }
-
-
- /************************************************************
- * fatal(): Complain and exit.
- ************************************************************/
-
- #if __STDC__ /* use ANSI variable-#-of-args method */
-
- int fatal (char *fmt, ...)
- {
- char ftext[80], ffmt[55];
- va_list arglist;
-
- va_start(arglist, fmt);
-
- #else /* or old varargs method: */
-
- int fatal(fmt, va_alist)
- char *fmt;
- va_dcl
- {
- char ftext[80], ffmt[55];
- va_list arglist;
-
- va_start(arglist);
- #endif
-
- vsprintf(ffmt, fmt, arglist);
- sprintf(ftext, "Fatal error in rmenu: %s", ffmt);
-
- put_msg(1, ftext);
-
- va_end(arglist);
- return ERROR;
- }
-
-
- /************************************************************
- * put_msg(): Display a message on the menu screen
- * Return the character typed to continue
- ************************************************************/
-
- #if __STDC__
- int put_msg (int bell, char *fmt, ...)
- {
- char ftext[80];
- va_list arglist;
- char c;
-
- va_start(arglist, fmt);
-
- #else
- int put_msg(bell, fmt, va_alist)
- int bell;
- char *fmt;
- va_dcl
- {
- char ftext[80];
- va_list arglist;
- char c;
-
- va_start(arglist);
- #endif
-
- move(ERR_ROW, 0);
- hlight_on();
-
- if (bell)
- beep();
-
- /* vwprintw(stdscr, fmt, arglist); */
- vsprintf(ftext, fmt, arglist);
- addstr(ftext);
- va_end(arglist);
- refresh();
-
- c = getch();
-
- move (ERR_ROW, 0);
- hlight_end();
- clrtoeol();
- refresh();
- return c;
- }
-