home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / menubar / part01 next >
Internet Message Format  |  1991-03-21  |  9KB

  1. From: jek5036@ultb.isc.rit.edu (J.E. King)
  2. Newsgroups: comp.sources.misc
  3. Subject: v17i062:  menubar - C Menubar function, Part01/01
  4. Message-ID: <1991Mar21.210826.12086@sparky.IMD.Sterling.COM>
  5. Date: 21 Mar 91 21:08:26 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: 061bd438 cbe7e308 d69ed5dc 45037598
  8.  
  9. Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu>
  10. Posting-number: Volume 17, Issue 62
  11. Archive-name: menubar/part01
  12.  
  13. Since I rely on curses heavily for my programs, I have began to write 
  14. some functions for my programs.  I found this one so useful that I 
  15. decided to put it up on comp.sources.misc.  It is a menu routine, 
  16. which will adjust to the size of a 2d char array and will draw a nice 
  17. box around the menu which is either numerically driven or arrow-key 
  18. driven.  I hope someone finds it useful.
  19.  
  20. Jim King <jek5036@ultb.isc.rit.edu>
  21.  
  22. -- cut here -- cut here -- cut here -- cut here -- cut here -- cut here --
  23. #!/bin/sh
  24. # to extract, remove the header and type "sh filename"
  25. if `test ! -s ./Makefile`
  26. then
  27. echo "writing ./Makefile"
  28. cat > ./Makefile << '\End\Of\Shar\'
  29. CFLAGS = -O
  30.  
  31. all: test
  32.  
  33. test: menubar.o test.o
  34.     cc test.o menubar.o -o test -g -lcurses -ltermcap
  35.  
  36. test.o: test.c
  37. menubar.o: menubar.c
  38. \End\Of\Shar\
  39. else
  40.   echo "will not over write ./Makefile"
  41. fi
  42. if `test ! -s ./README`
  43. then
  44. echo "writing ./README"
  45. cat > ./README << '\End\Of\Shar\'
  46. Hi!
  47.  
  48.     MenuBar is something I cooked up whilst bored at work.  You can
  49. use it for just about any program which prompts the user for menu choices.
  50. I am planning on installing it in my next version of Chemtab, the
  51. chemistry database released on comp.sources.unix not too long ago.  Here's
  52. how you would go about using menubar():
  53.  
  54. 1) Set up a 2d array of char in your program, such as:
  55.  
  56. char    *first_menu[] = {
  57.     "This is menu option number 1",
  58.     "This is menu option number 2",
  59.     "This will return a three",
  60.     "Exit the program",
  61.     0
  62. };
  63.  
  64. 2) Call the function like this:
  65.  
  66.     menubar(y, x, first_menu, boxflag, title);
  67.  
  68. where:
  69.     y = the y position on the screen - upper left hand corner
  70.     x = the x position on the screen - upper left hand corner
  71.     first_menu = the char 2d array like above
  72.     boxflag = (1, 0) if 1, will put an ascii box around the menu
  73.     title = char string - centered in the first line of the menu
  74.             if you don't want a title, use NULL
  75. 3) The fuctions will return the number of the option, for example in the
  76. above menu if I pressed return on "This will return a three" I would get
  77. back a three because it was the third choice.. Have fun with it.
  78.  
  79. \End\Of\Shar\
  80. else
  81.   echo "will not over write ./README"
  82. fi
  83. if `test ! -s ./menubar.c`
  84. then
  85. echo "writing ./menubar.c"
  86. cat > ./menubar.c << '\End\Of\Shar\'
  87. /*
  88.  * Menubar - curses driven menu bar display
  89.  *           menubar will run a menu-bar display on screen for you.
  90.  *           This type of package is useful for databases, etc..
  91.  */
  92.  
  93. /* Menubar V1.0 by Jim King (jek5036@ultb.isc.rit.edu) */
  94.  
  95. #include <stdio.h>
  96. #include <curses.h>
  97. #include <signal.h>
  98.  
  99. #ifdef    SYSV
  100. # include    <string.h>
  101. #else
  102. # include    <strings.h>
  103. #endif
  104.  
  105. #define    MAXNAMELEN    70
  106. #define    UP        'A'
  107. #define    DN        'B'
  108. #define    LT        'C'
  109. #define RT        'D'
  110. #define    ESC        '\033'
  111. #define    RET        '\015'
  112. #define LF        '\012'
  113.  
  114. struct mbar    {
  115.     char    menu_choice[MAXNAMELEN];
  116.     int    menu_number;
  117.     struct    mbar    *next;
  118. } *m;
  119.  
  120. WINDOW    *MENU;
  121.  
  122. #define    NEW(XXX)    (struct XXX *)malloc(sizeof(struct XXX))
  123.  
  124. int    Stopflag = 0;    /* interrupt flag */
  125.  
  126. void    (*oldsig)();    /* old signal catch */
  127.  
  128. /*
  129.  * signal calls this on an interrupt like ^C
  130.  */
  131.  
  132. menuclean()
  133. {
  134.     wclear(MENU); wrefresh(MENU); delwin(MENU); refresh();
  135.     printf("<<< Press return to continue >>>"); fflush(stdout);
  136.     signal(SIGINT, oldsig);        /* reset signal handler */
  137.     ++Stopflag;
  138.     return(-1);            /* return to loop */
  139. }
  140.  
  141. /*
  142.  * converts information in menu to a linked-list
  143.  */
  144.  
  145. mkmenubar(num, menu)
  146. int    *num;
  147. char    *menu[];
  148. {
  149.     int    i = 0;            /* counter for num */
  150.     struct    mbar    *tmp;        /* tmp pointer to list */
  151.  
  152.     m = NEW(mbar);            /* initialize menubar */
  153.     tmp = m;            /* set tmp to head */
  154.  
  155.     do {
  156.         strcpy(tmp->menu_choice, menu[i]);
  157.         tmp->menu_number = i+1;    /* move values into tmp */
  158.         tmp->next = NEW(mbar);
  159.         tmp = tmp->next;    /* set up next link */
  160.         ++i;
  161.     } while (menu[i] != NULL);
  162.  
  163.     *num = i;            /* 'return' the maxnum of choices */
  164.     tmp = NULL;            /* lop off the end */
  165. }
  166.  
  167. /*
  168.  * determine optimal size for menu bar.
  169.  */
  170.  
  171. sizemenubar(len, wid, title)
  172. int    *len, *wid;
  173. char    *title;
  174. {
  175.     int    sz = 0, i = 0;        /* tmp counter */
  176.     struct    mbar    *tmp;        /* tmp placeholder */
  177.  
  178.     *len = 0;  *wid = 0;
  179.  
  180.     tmp = m;
  181.  
  182.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  183.         ++i;
  184.         sz = strlen(tmp->menu_choice);
  185.         if (sz > *wid)        /* as wide as longest line */
  186.             *wid = sz;
  187.     }
  188.     if (title != NULL)
  189.         if (strlen(title) > *wid)
  190.             *wid = strlen(title);
  191.  
  192.     *wid += 8;            /* extras like #] and . */
  193.     *len = i+1;
  194. }
  195.  
  196. /*
  197.  * sets up the menu on MENU window
  198.  */
  199.  
  200. dispmenu(boxflag, title, width, length)
  201. int    boxflag, width, length;
  202. char    *title;
  203. {
  204.     struct    mbar    *tmp;
  205.  
  206.     if (boxflag) {
  207.         box(MENU, '|', '-');
  208.         mvwaddch(MENU, 0, 0, '/');
  209.         mvwaddch(MENU, 0, width-1, '\\');
  210.         mvwaddch(MENU, length-1, 0, '\\');
  211.         mvwaddch(MENU, length-1, width-1, '/');
  212.     }
  213.  
  214.     if (title != NULL) {
  215.         wstandout(MENU);
  216.         mvwaddstr(MENU, 0, (width / 2) - (strlen(title) / 2), title);
  217.         wstandend(MENU);
  218.     }
  219.  
  220.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  221.         if (tmp->menu_number == 0) continue;
  222.         wmove(MENU, tmp->menu_number, 1);
  223.         wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice);
  224.     }
  225.     wrefresh(MENU);
  226. }
  227.  
  228. /*
  229.  * un-hilight old selection at num
  230.  */
  231.  
  232. delight(num)
  233. int    num;
  234. {
  235.     struct mbar    *tmp;
  236.  
  237.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  238.         if (num == tmp->menu_number) {
  239.             wmove(MENU, tmp->menu_number, 1);
  240.             wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice);
  241.         }
  242.     }
  243.     wrefresh(MENU);
  244. }
  245.  
  246. /*
  247.  * hilight selection at num
  248.  */
  249.  
  250. hilight(num)
  251. int    num;
  252. {
  253.     struct    mbar    *tmp;
  254.  
  255.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  256.         if (num == tmp->menu_number) {
  257.             wstandout(MENU);    /* highlight */
  258.             wmove(MENU, tmp->menu_number, 1);
  259.             wprintw(MENU, "%d> %s. ", tmp->menu_number, tmp->menu_choice);
  260.             wstandend(MENU);
  261.         }
  262.     }
  263.     wrefresh(MENU);
  264. }
  265.  
  266. /*
  267.  * main function call
  268.  * menubar(y, x, menu) where
  269.  * y = starting line of menu
  270.  * x = starting column of menu
  271.  * menu is of type *menu[] in which are stored the items for be chosen
  272.  */
  273.  
  274. menubar(y, x, menu, boxflag, title)
  275. int    y, x, boxflag;
  276. char    *menu[], *title;
  277. {
  278.     int    cur = 1, old = 1, l, w, num;
  279.     char    c;
  280.     
  281.     mkmenubar(&num, menu);
  282.     sizemenubar(&l, &w, title);
  283.  
  284.     initscr();
  285.     MENU = newwin(l, w, y, x);    /* start (x, y) to (x+w, y+l) */
  286.  
  287.     dispmenu(boxflag, title, w, l);
  288.  
  289.     oldsig = signal(SIGINT, menuclean);
  290.     noecho(); crmode();
  291.     for (;;) {
  292.         delight(old);
  293.         hilight(cur);
  294.  
  295.         if (Stopflag) { cur = -1; goto end; }
  296.         c = wgetch(MENU);
  297.         switch(c) {
  298.             case ESC:
  299.                 wgetch(MENU);
  300.                 switch(wgetch(MENU)) {
  301.                     case UP:
  302.                     case RT: old = cur--;
  303.                          if (Stopflag) { cur = -1; goto end; }
  304.                         break;
  305.                     case DN:
  306.                     case LT: old = cur++;
  307.                          if (Stopflag) { cur = -1; goto end; }                        break;
  308.                     default:
  309.                          if (Stopflag) { cur = -1; goto end; }
  310.                          break;
  311.                 }
  312.                 break;
  313.             case LF:
  314.             case RET:
  315.                 if (Stopflag) { cur = -1; goto end; }
  316. end:                wclear(MENU); wrefresh(MENU); delwin(MENU);
  317.                 refresh(); echo(); crmode();
  318.                 return(cur); break;
  319.             default:
  320.                 if (Stopflag) { cur = -1; goto end; }
  321.                 if (c > '0' || c <= '9') {
  322.                     old = cur;
  323.                     cur = c - '0';
  324.                     if (cur > num) cur = num;
  325.                     if (cur < 1) cur = 1;
  326.                 }
  327.                 break;
  328.         }
  329.         if (cur > num) cur = 1;
  330.         if (cur < 1) cur = num;
  331.     }
  332.     
  333. }
  334. \End\Of\Shar\
  335. else
  336.   echo "will not over write ./menubar.c"
  337. fi
  338. if `test ! -s ./test.c`
  339. then
  340. echo "writing ./test.c"
  341. cat > ./test.c << '\End\Of\Shar\'
  342. #include <stdio.h>
  343.  
  344. /*
  345.  * declare your menus like this:
  346.  */
  347.  
  348. char    *menu[40] = {
  349.     "This is menu option 1",
  350.     "This is menu option 2",
  351.     "This is menu option 3",
  352.     "This is menu option 4",
  353.     0
  354. };
  355.  
  356. char    title[80] = "THIS IS THE MenuBar";
  357.  
  358. /*
  359.  * don't forget this
  360.  */
  361.  
  362. extern int    menubar();
  363.  
  364. main()
  365. {
  366. /*
  367.  * call menubar like this
  368.  * it returns the number of choice (good to use as a switch statement)
  369.  * or a -1 if the person hit return
  370.  */
  371.     printf("\n\nAnd the number is: %d\n", menubar(5, 20, menu, 1, title));
  372.     exit(1);
  373. }
  374. \End\Of\Shar\
  375. else
  376.   echo "will not over write ./test.c"
  377. fi
  378. echo "Finished archive 1 of 1"
  379. exit
  380.  
  381. exit 0 # Just in case...
  382. -- 
  383. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  384. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  385. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  386. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  387.