/* Example menu program * Liam R. Quin, July 1989 * * $Header: /usr/home/liam/src/lq-text1.17/src/menu/RCS/example.c,v 1.3 2001/05/31 03:50:13 liam Exp $ * * $Log: example.c,v $ * Revision 1.3 2001/05/31 03:50:13 liam * for release 1.17 * * Revision 1.2 94/02/26 14:56:12 lee * API change * * Revision 1.1 90/08/29 21:49:59 lee * Initial revision * * Revision 2.1 89/08/07 13:49:41 lee * First fully working (V.3.2 only) release; * this is the baseline for future development. * * Revision 1.2 89/08/04 17:59:18 lee * Fully working with Basic Functionality. * Scrolling menubar, scrolling menus, moveable Info windows. * * Revision 1.1 89/07/27 11:39:58 lee * Initial revision * * */ #ifdef HAVE_STDLIB_H # include #else # include #endif #ifdef HAVE_UNISTD_H #ifdef ultrix # include #else # include #endif /* * #ifndef CURSESX * # include "oldcurses.h" * #endif */ #include "menu.h" #include "internal.h" #include "error.h" extern void exit(); char *cmdname; char *progname; /* some functions for use from the command line */ int MF_System(Menu, Selection) t_Menu *Menu; int Selection; { /* FIXME -- * Should restore terminal modes, clear screen, etc. * Also, should check to ensure that the child gets the appropriate * file descriptors and signals. * NOTDONE */ if (Menu->Items[Selection].LongText) { clearok(stdscr, TRUE); clear(); refresh(); noraw(); echo(); nl(); system("stty opost icanon onlcr icrnl echo"); system(Menu->Items[Selection].LongText); raw(); noecho(); nonl(); clearok(stdscr, TRUE); } return Selection; } int MF_ShowInfo(Menu, Selection) t_Menu *Menu; int Selection; { (void) wmove(stdscr, Menu->MenuId + 5, 1); (void) ShowInfo(Menu->Items[Menu->SelectedLine].LongText, (WINDOW *) 0, Menu->MenuId + 5, Menu->SelectedLine); return Selection; } int MF_NonFatalError(Menu, Selection) t_Menu *Menu; int Selection; { error(0, Menu->Items[Menu->SelectedLine].LongText); return Selection; } int MF_FatalError(Menu, Selection) t_Menu *Menu; int Selection; { error(ERR_FATAL, Menu->Items[Menu->SelectedLine].LongText); return Selection; } int MF_SayWhatIChose(Menu, Selection) t_Menu *Menu; int Selection; { (void) wmove(stdscr, Menu->MenuId + 5, 1); (void) wclrtoeol(stdscr); (void) mvwprintw(stdscr, Menu->MenuId + 5, 1, "You have selected %s from the %s menu.", Menu->Items[Selection].Name, Menu->Name); return Selection; } /*ARGSUSED*/ int MF_Flash(Menu, Selection) t_Menu *Menu; int Selection; { (void) flash(); return -1; } /*ARGSUSED*/ MF_Quit(Menu, Selection) t_Menu *Menu; int Selection; { (void) endwin(); exit(0); } /* A table of Functions... */ typedef int (*t_fptr)(); typedef struct { t_fptr Function; char *Name; } t_ftable; t_ftable FunctionList[] = { { MF_SayWhatIChose, "SayWhatIChose" }, { MF_Flash, "Flash" }, { MF_System, "System" }, { MF_System, "Shell" }, { MF_Quit, "Quit" }, { MF_NonFatalError, "NonFatalError" }, { MF_FatalError, "FatalError" }, { MF_FatalError, "Error" }, { MF_ShowInfo, "ShowInfo" }, { 0, "Null" }, /* So you can restore the default */ { 0, 0 } }; /* After the user has chosen, this program exits. * It communicates with the outside world by one of the following methods: * wtr_printint -- print the number of the selection to stderr. * In other words, if the user selects item 3, do fprintf(stderr, "3\n"); * wtr_printstring -- print the actual menu item * wtr_exitcode -- like printint, but use an exit code. */ enum e_what { wtr_printint, wtr_printstring, wtr_exitcode } WhatToReturn = wtr_printint; int MenuUsed = -1; /* -1 for none */ main(argc, argv) int argc; char *argv[]; { int retval; t_MenuItem *ItemList = 0; t_Menu *M; static t_MenuBar MenuBar; int ItemsSeen = 0; t_fptr FunctionListPointer = 0; char *Description = 0; char *LongText = 0; extern char *getenv(); extern char *strrchr(); /* Make progname point to the last component of argv[0] */ progname = strrchr(argv[0], '/'); if (progname) { if (*++progname == '\0') { --progname; /* No Unix filename can do this! */ } } else { progname = argv[0]; } /* cmdname lets you say CMDNAME=`basename $0` in a shell script * for better error reporting */ cmdname = getenv("CMDNAME"); argv++; argc--; if (STREQ(argv[0], "-s")) { WhatToReturn = wtr_printstring; argv++; argc--; } else if (STREQ(argv[0], "-e")) { WhatToReturn = wtr_exitcode; argv++; argc--; } /* Get some memory (actually a little too much sometimes) */ if ((ItemList = (t_MenuItem *)malloc(sizeof(t_MenuItem) * (argc-1))) == (t_MenuItem *) 0) { error(ERR_FATAL|ERR_MEMORY,"Not enough momory for %d menu items\n", argc); } /* Add arguments to the menu, one at a time */ while (argc-- > 0) { if (STREQ(*argv, "-m")) { /* new menu */ argc--; argv++; /* skip over the -m */ /* Check that there's a menu name */ if (argc <= 0) { error(ERR_FATAL, "-m option must be followed by menu_name [item ...]"); } /* check there are not too many menus */ if (MenuBar.HowManyMenus > MENUMAXINBAR) { error(ERR_FATAL, "Attempt to define more than %d menus", MENUMAXINBAR); } /* get memory for the new menu */ if ((M = (t_Menu *) malloc(sizeof(t_Menu))) == (t_Menu *) 0) { error(ERR_FATAL|ERR_MEMORY, "Couldn't get memory to store menu %s", *argv); } MenuBar.Menus[MenuBar.HowManyMenus] = M; MenuBar.HowManyMenus++; /* Set up new Menu structure */ M->HowManyItems = 0; M->Items = &ItemList[ItemsSeen]; M->MenuStyle = 0; M->IsSelected = 0; M->SelectedLine = 0; M->TopLineOnScreen = 0; /* Vertical Scrolling */ M->MenuId = 0; /* Oh for C++ */ M->Description = Description; M->NameLength = strlen(*argv); M->Name = *(argv++); } else if (STREQ(argv[0], "-d")) { argc--; argv++; if (argc <= 0) { error(ERR_FATAL, "-d must be followed by an item-description"); } Description = *(argv++); } else if (STREQ(argv[0], "-c")) { argc--; argv++; if (argc <= 0) { error(ERR_FATAL, "-c must be followed by a string"); } LongText = *(argv++); } else if (STREQ(argv[0], "-f")) { t_ftable *flp; argc--; argv++; /* skip over the -f */ /* Check that there's a function name */ if (argc <= 0) { error(ERR_FATAL, "-f option must be followed by a functionname"); } for (flp = FunctionList; flp->Name != (char *) 0; flp++) { if (STREQ(flp->Name, *argv)) { break; } } if (flp->Function == 0) { error(ERR_FATAL, "Unknown function name %s", *argv); } FunctionListPointer = flp->Function; argv++; } else { if (!M) { error(ERR_FATAL, "each list of menu items must start with a -m menu_name"); } ItemList[ItemsSeen].Function = FunctionListPointer; ItemList[ItemsSeen].Name = *(argv++); ItemList[ItemsSeen].NameLength = 0; ItemList[ItemsSeen].Description = Description; ItemList[ItemsSeen].LongText = LongText; ItemsSeen++; M->HowManyItems++; } } (void) initscr(); InCurses = 1; (void) cbreak(); (void) noecho(); (void) nonl(); (void) keypad(stdscr, TRUE); /* This string is printed onto the screen to show that the pull-down * menus don't affect the contents of stdscr below line 1 -- that is * to say, they overwrite the top two lines, but are careful to restore * the rest of the screen to how it was. The cursor position may be * lost, however. */ (void) mvwaddstr(stdscr, 2, 0, "This is a demonstration-only version of Liam Quin's Menu program, July 1989"); while ((retval = UseMenuBar(&MenuBar)) != -2) { /*NULLBODY*/ ; } clear(); (void) refresh(); InCurses = 0; (void) endwin(); switch (WhatToReturn) { case wtr_printstring: if (retval >= 0) { if (MenuUsed >= MenuBar.HowManyMenus || MenuUsed < 0) { error(ERR_FATAL|ERR_INTERNAL, "internal error: selected menu %d, max was %d!", MenuUsed, MenuBar.HowManyMenus); } /* Need to find the right string... */ (void) fprintf(stderr, "%s\n", MenuBar.Menus[MenuUsed]->Items[retval].Name); exit(0); } break; case wtr_printint: if (retval >=0 ) { (void) fprintf(stderr, "%d\n", retval); exit(0); } break; } exit(retval); /*NOTREACHED*/ }