home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume18 / menubar / part01 next >
Internet Message Format  |  1991-04-23  |  14KB

  1. From: jek5036@ultb.isc.rit.edu (J.E. King)
  2. Newsgroups: comp.sources.misc
  3. Subject: v18i080:  menubar - C Menubar function, Part01/01
  4. Message-ID: <1991Apr23.013541.7930@sparky.IMD.Sterling.COM>
  5. Date: 23 Apr 91 01:35:41 GMT
  6. Approved: kent@sparky.imd.sterling.com
  7. X-Checksum-Snefru: fe964db2 a8cad109 6a2ee76d d9d37c83
  8.  
  9. Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu>
  10. Posting-number: Volume 18, Issue 80
  11. Archive-name: menubar/part01
  12. Supersedes: menubar: Volume 17, Issue 62
  13.  
  14. This is a demonstration package on how to use two new curses routines:
  15.  
  16. menubar  - sets up a menu on the screen using a menu-bar format,
  17. curgets  - get a string using curses in a box on the screen,
  18. termlock - a terminal lock program complete with compile
  19.            definable timeout, and an option to logout at 
  20.            timeout (safelock).
  21.  
  22. Jim King <jek5036@ultb.isc.rit.edu>
  23.  
  24. -- cut here -- cut here -- cut here -- cut here -- cut here -- cut here --
  25. #!/bin/sh
  26. # to extract, remove the header and type "sh filename"
  27. if `test ! -s ./Makefile`
  28. then
  29. echo "writing ./Makefile"
  30. cat > ./Makefile << '\End\Of\Shar\'
  31. #
  32. # Makefile for termlock, curses implemented
  33. # by Jim King (jek5036@ultb.isc.rit.edu)
  34. #
  35. # Define TIMELOCK is you want the program to timeout
  36. # Timeout means if the terminal is idle (nobody touches it) for so many
  37. # seconds, the program will quit.. define SAFELOCK to have the program
  38. # log you out at the end of this interval.  Useful for computer rooms
  39. # where terminals are fought over..
  40. #
  41. # If you define TIMELOCK or SAFELOCK, make sure you define DEFTIME.
  42. # DEFTIME is the amount of idle seconds the terminal can sit before timeout.
  43. #
  44. # CHECKAT is the amount of seconds the program will 'sleep' before
  45. # checking if timeout time has occured.
  46. #
  47. # Define SYSV for a SYSV make
  48. #
  49. # CFLAGS = -O -DSAFELOCK -DCHECKAT=30 -DDEFTIME=600 -DSYSV
  50.  
  51. CFLAGS = -O -DTIMELOCK -DCHECKAT=15 -DDEFTIME=300 # 5 minutes
  52.  
  53. all: termlock
  54.  
  55. termlock: menubar.o termlock.o curgets.o
  56.     cc termlock.o menubar.o curgets.o -o termlock -O -lcurses -ltermcap
  57.  
  58. termlock.o: termlock.c /usr/include/curses.h /usr/include/signal.h
  59. menubar.o: menubar.c /usr/include/curses.h
  60. curgets.o: curgets.c /usr/include/curses.h
  61. \End\Of\Shar\
  62. else
  63.   echo "will not over write ./Makefile"
  64. fi
  65. if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 1083 ]
  66. then
  67. echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 1083}'`
  68. fi
  69. if `test ! -s ./README`
  70. then
  71. echo "writing ./README"
  72. cat > ./README << '\End\Of\Shar\'
  73. This is a demonstration package on how to use two new curses routines:
  74.  
  75. menubar - sets up a menu on the screen using a menu-bar format
  76. curgets - get a string using curses in a box on the screen
  77.  
  78. termlock itself is a terminal lock program complete with compile
  79. definable timeout, and an option to logout at timeout (safelock).
  80.  
  81. Problems to jek5036@ultb.isc.rit.edu (Jim King)
  82. If above address fails (and it won't)
  83.     try pulsar%lsrhs.uucp@xait.xerox.com (same person)
  84.  
  85. \End\Of\Shar\
  86. else
  87.   echo "will not over write ./README"
  88. fi
  89. if [ `wc -c ./README | awk '{printf $1}'` -ne 466 ]
  90. then
  91. echo `wc -c ./README | awk '{print "Got " $1 ", Expected " 466}'`
  92. fi
  93. if `test ! -s ./curgets.c`
  94. then
  95. echo "writing ./curgets.c"
  96. cat > ./curgets.c << '\End\Of\Shar\'
  97. /*
  98.  * Curses getstring in a box
  99.  * by Jim King (jek5036@ultb.isc.rit.edu)
  100.  */
  101.  
  102. #include <curses.h>            /* curses include file */
  103.  
  104. /*
  105.  * curgets is a void type because it does not return anything.
  106.  * curgets arguments:
  107.  *
  108.  * str: address of a character array, passed in like &string
  109.  *      this will contain the string which the user inputs
  110.  * len: the maximum amount of characters to read in (defines box size)
  111.  * y, x: (x, y) coordinates on the screen of the box's upper left-hand corner
  112.  * title: same as str, but it is the title for the box
  113.  */
  114.  
  115. void curgets(str, len, y, x, title, hide)
  116. char    *str, *title;
  117. int    len, y, x, hide;
  118. {
  119.     WINDOW    *strwin;
  120.     char    c, input[80];
  121.     int    pos, curx;
  122.  
  123.     strwin = newwin(3, len+2, y, x);
  124.     box(strwin, '|', '-');
  125.     mvwaddch(strwin, 0, 0, '/');
  126.     mvwaddch(strwin, 2, 0, '\\');
  127.     mvwaddch(strwin, 0, len+1, '\\');
  128.     mvwaddch(strwin, 2, len+1, '/');
  129.     wstandout(strwin);
  130.     mvwaddstr(strwin, 0, (len / 2) - (strlen(title) / 2), title);
  131.     wstandend(strwin);
  132. ers:    curx = 1;
  133.     for (pos = 1; pos < len; pos++)
  134.         mvwaddch(strwin, 1, pos, '_');
  135.  
  136.     for (;;) {
  137.         wmove(strwin, 1, curx);
  138.         wrefresh(strwin);
  139.         noecho(); crmode();
  140.         c = wgetch(strwin);
  141.         switch(c) {
  142.             case '\177':    /* DELETE */
  143.                 if (curx == 1) break;
  144.                 mvwaddch(strwin, 1, --curx, '_');
  145.                 input[curx-1] = '\0';
  146.                 break;
  147.             case '\025':    /* ^U, line kill */
  148.                 goto ers; break;
  149.             case '\015':
  150.             case '\012':    /* RETURN, LF */
  151.                 input[curx-1] = '\0';
  152.                 wclear(strwin);
  153.                 wrefresh(strwin);
  154.                 delwin(strwin);
  155.                 strcpy(str, input);
  156.                 return;
  157.             default:
  158.                 if (curx == len) break;
  159.                 if (c < 033) break;    /* no control chars */
  160.                 wstandout(strwin);
  161.                 if (!hide)
  162.                     mvwaddch(strwin, 1, curx++, c);
  163.                 else
  164.                     mvwaddch(strwin, 1, curx++, '*');
  165.                 wstandend(strwin);
  166.                 input[curx-2] = c;
  167.                 break;
  168.         }
  169.     }
  170. }
  171. \End\Of\Shar\
  172. else
  173.   echo "will not over write ./curgets.c"
  174. fi
  175. if [ `wc -c ./curgets.c | awk '{printf $1}'` -ne 1811 ]
  176. then
  177. echo `wc -c ./curgets.c | awk '{print "Got " $1 ", Expected " 1811}'`
  178. fi
  179. if `test ! -s ./menubar.c`
  180. then
  181. echo "writing ./menubar.c"
  182. cat > ./menubar.c << '\End\Of\Shar\'
  183. /*
  184.  * Menubar - curses driven menu bar display
  185.  *           menubar will run a menu-bar display on screen for you.
  186.  *           This type of package is useful for databases, etc..
  187.  */
  188.  
  189. /* Menubar V1.0 by Jim King (jek5036@ultb.isc.rit.edu) - Original source */
  190.  
  191. /*         V1.1 - returns a WINDOW handle to that window so you
  192.  *                can decide what to do with it.  Your choice
  193.  *                is handled as a pointer and set by the function
  194.  *
  195.  * Modification by Jim King (jek5036@ultb.isc.rit.edu)
  196.  */
  197.  
  198. #include <stdio.h>
  199. #include <curses.h>
  200. #include <signal.h>
  201.  
  202. #ifdef    SYSV
  203. # include    <string.h>
  204. #else
  205. # include    <strings.h>
  206. #endif
  207.  
  208. #define    MAXNAMELEN    70
  209. #define    UP        'A'
  210. #define    DN        'B'
  211. #define    LT        'C'
  212. #define RT        'D'
  213. #define    ESC        '\033'
  214. #define    RET        '\015'
  215. #define LF        '\012'
  216.  
  217. struct mbar    {
  218.     char    menu_choice[MAXNAMELEN];
  219.     int    menu_number;
  220.     struct    mbar    *next;
  221. } *m;
  222.  
  223. WINDOW    *MENU;
  224.  
  225. #define    NEW(XXX)    (struct XXX *)malloc(sizeof(struct XXX))
  226.  
  227. int    Stopflag = 0;    /* interrupt flag */
  228.  
  229. /*
  230.  * converts information in menu to a linked-list
  231.  */
  232.  
  233. mkmenubar(num, menu)
  234. int    *num;
  235. char    *menu[];
  236. {
  237.     int    i = 0;            /* counter for num */
  238.     struct    mbar    *tmp;        /* tmp pointer to list */
  239.  
  240.     m = NEW(mbar);            /* initialize menubar */
  241.     tmp = m;            /* set tmp to head */
  242.  
  243.     do {
  244.         strcpy(tmp->menu_choice, menu[i]);
  245.         tmp->menu_number = i+1;    /* move values into tmp */
  246.         tmp->next = NEW(mbar);
  247.         tmp = tmp->next;    /* set up next link */
  248.         ++i;
  249.     } while (menu[i] != NULL);
  250.  
  251.     *num = i;            /* 'return' the maxnum of choices */
  252.     tmp = NULL;            /* lop off the end */
  253. }
  254.  
  255. /*
  256.  * determine optimal size for menu bar.
  257.  */
  258.  
  259. sizemenubar(len, wid, title)
  260. int    *len, *wid;
  261. char    *title;
  262. {
  263.     int    sz = 0, i = 0;        /* tmp counter */
  264.     struct    mbar    *tmp;        /* tmp placeholder */
  265.  
  266.     *len = 0;  *wid = 0;
  267.  
  268.     tmp = m;
  269.  
  270.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  271.         ++i;
  272.         sz = strlen(tmp->menu_choice);
  273.         if (sz > *wid)        /* as wide as longest line */
  274.             *wid = sz;
  275.     }
  276.     if (title != NULL)
  277.         if (strlen(title) > *wid)
  278.             *wid = strlen(title);
  279.  
  280.     *wid += 8;            /* extras like #] and . */
  281.     *len = i+1;
  282. }
  283.  
  284. /*
  285.  * sets up the menu on MENU window
  286.  */
  287.  
  288. dispmenu(boxflag, title, width, length)
  289. int    boxflag, width, length;
  290. char    *title;
  291. {
  292.     struct    mbar    *tmp;
  293.  
  294.     if (boxflag) {
  295.         box(MENU, '|', '-');
  296.         mvwaddch(MENU, 0, 0, '/');
  297.         mvwaddch(MENU, 0, width-1, '\\');
  298.         mvwaddch(MENU, length-1, 0, '\\');
  299.         mvwaddch(MENU, length-1, width-1, '/');
  300.     }
  301.  
  302.     if (title != NULL) {
  303.         wstandout(MENU);
  304.         mvwaddstr(MENU, 0, (width / 2) - (strlen(title) / 2), title);
  305.         wstandend(MENU);
  306.     }
  307.  
  308.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  309.         if (tmp->menu_number == 0) continue;
  310.         wmove(MENU, tmp->menu_number, 1);
  311.         wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice);
  312.     }
  313.     wrefresh(MENU);
  314. }
  315.  
  316. /*
  317.  * un-hilight old selection at num
  318.  */
  319.  
  320. delight(num)
  321. int    num;
  322. {
  323.     struct mbar    *tmp;
  324.  
  325.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  326.         if (num == tmp->menu_number) {
  327.             wmove(MENU, tmp->menu_number, 1);
  328.             wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice);
  329.         }
  330.     }
  331.     wrefresh(MENU);
  332. }
  333.  
  334. /*
  335.  * hilight selection at num
  336.  */
  337.  
  338. hilight(num)
  339. int    num;
  340. {
  341.     struct    mbar    *tmp;
  342.  
  343.     for (tmp = m; tmp != NULL; tmp = tmp->next) {
  344.         if (num == tmp->menu_number) {
  345.             wstandout(MENU);    /* highlight */
  346.             wmove(MENU, tmp->menu_number, 1);
  347.             wprintw(MENU, "%d> %s. ", tmp->menu_number, tmp->menu_choice);
  348.             wstandend(MENU);
  349.         }
  350.     }
  351.     wrefresh(MENU);
  352. }
  353.  
  354. /*
  355.  * main function call
  356.  * menubar(y, x, menu) where
  357.  * y = starting line of menu
  358.  * x = starting column of menu
  359.  * menu is of type *menu[] in which are stored the items for be chosen
  360.  * boxflag = boolean if !0, draw box around border of menu
  361.  * title = address to char array for title of menu
  362.  * win = returns a handle to the menu so you can delete it when you want
  363.  */
  364.  
  365. int menubar(y, x, menu, boxflag, title, win)
  366. int    y, x, boxflag;
  367. char    *menu[], *title;
  368. WINDOW    *win;
  369. {
  370.     int    cur = 1, old = 1, l, w, num;
  371.     char    c;
  372.     
  373.     mkmenubar(&num, menu);
  374.     sizemenubar(&l, &w, title);
  375.  
  376. /* Menubar ASSUMES that the calling procedure initialized curses already */
  377.  
  378.     MENU = newwin(l, w, y, x);    /* start (x, y) to (x+w, y+l) */
  379.  
  380.     dispmenu(boxflag, title, w, l);
  381.  
  382.     noecho(); crmode();
  383.     for (;;) {
  384.         delight(old);
  385.         hilight(cur);
  386.  
  387.         if (Stopflag) { cur = -1; goto end; }
  388.         c = wgetch(MENU);
  389.         switch(c) {
  390.             case ESC:
  391.                 wgetch(MENU);
  392.                 switch(wgetch(MENU)) {
  393.                     case UP:
  394.                     case RT: old = cur--;
  395.                          if (Stopflag) { cur = -1; goto end; }
  396.                         break;
  397.                     case DN:
  398.                     case LT: old = cur++;
  399.                          if (Stopflag) { cur = -1; goto end; }                        break;
  400.                     default:
  401.                          if (Stopflag) { cur = -1; goto end; }
  402.                          break;
  403.                 }
  404.                 break;
  405.             case LF:
  406.             case RET:
  407.                 if (Stopflag) { cur = -1; goto end; }
  408. end:                win = MENU;
  409.                 return(cur);
  410.                 break;
  411.             default:
  412.                 if (Stopflag) { cur = -1; goto end; }
  413.                 if (c > '0' || c <= '9') {
  414.                     old = cur;
  415.                     cur = c - '0';
  416.                     if (cur > num) cur = num;
  417.                     if (cur < 1) cur = 1;
  418.                 }
  419.                 break;
  420.         }
  421.         if (cur > num) cur = 1;
  422.         if (cur < 1) cur = num;
  423.     }
  424.     
  425. }
  426. \End\Of\Shar\
  427. else
  428.   echo "will not over write ./menubar.c"
  429. fi
  430. if [ `wc -c ./menubar.c | awk '{printf $1}'` -ne 4977 ]
  431. then
  432. echo `wc -c ./menubar.c | awk '{print "Got " $1 ", Expected " 4977}'`
  433. fi
  434. if `test ! -s ./termlock.c`
  435. then
  436. echo "writing ./termlock.c"
  437. cat > ./termlock.c << '\End\Of\Shar\'
  438. /*
  439.  * termlock - a menu-driven terminal lock
  440.  */
  441.  
  442. #include <signal.h>
  443. #include <curses.h>
  444.  
  445. #ifdef    SAFELOCK
  446. #ifndef    TIMELOCK
  447. #define    TIMELOCK
  448. #endif
  449. #endif
  450.  
  451. char    *mainmenu[] = {
  452.     "Lock terminal",
  453.     "Unlock terminal",
  454.     "Quit",
  455.     0
  456. };
  457.  
  458. #ifdef    TIMELOCK
  459.     long    first;
  460. #endif
  461.  
  462. char    notdone[80] = "Terminal is NOT LOCKED.";
  463. char    done[80] = "Terminal is     LOCKED.";
  464. char    mainmenutitle[80] = "TermLock V1.0 Main Menu";
  465. char    lockstring[80] = "Enter a password to LOCK the terminal";
  466. char    unlockstring[80] = "Enter the password to UNLOCK the terminal";
  467. char    master[10] = "PulsaR";
  468. char    already[80] = "Terminal is already locked!";
  469. char    notlong[80] = "Password not long enough.";
  470. char    notlocked[80] = "Terminal isn't locked!";
  471. char    nope[80] = "Password mismatch.  Go away.";
  472. char    butlocked[80] = "But wait!  It's locked.";
  473. char    enteragain[80] = "Enter password again for verification.";
  474. char    mismatch[80] = "Passwords do not match.  Terminal not locked.";
  475.  
  476. #ifdef    TIMELOCK
  477. handle()
  478. {
  479.     long    now;
  480.     
  481.     time(&now);
  482.     if ((now - first) > DEFTIME) {
  483.         clear(); refresh(); endwin(); printf("Termlock Timeout.\n\n");
  484. #ifdef    SAFELOCK
  485.         if (getuid() == 0) /* don't want to kill the system */
  486.             exit(1);
  487.         kill(getppid(), 9);
  488. #endif
  489.         exit(1);
  490.     } else {
  491.         move(0, 75);
  492.         printw("%d", DEFTIME - (now - first));
  493.         refresh();
  494.         signal(SIGALRM, handle);
  495.         alarm(CHECKAT);
  496.         return;
  497.     }
  498. }
  499. #endif    TIMELOCK
  500.  
  501. clr()
  502. {
  503.     move(20, 0);
  504.     clrtoeol();
  505.     refresh();
  506. }
  507.  
  508. main()
  509. {
  510.     char    lock[40], unlock[40], check[40];
  511.     WINDOW    *menu;
  512.     int    choice, locked = 0;
  513.  
  514.     signal(SIGQUIT, SIG_IGN);
  515.     signal(SIGINT, SIG_IGN);
  516.     signal(SIGHUP, SIG_IGN);
  517.     signal(SIGTERM, SIG_IGN);
  518. #ifndef    SYSV
  519.     signal(SIGTSTP, SIG_IGN);
  520.     signal(SIGSTOP, SIG_IGN);
  521. #endif    /* SYSV */
  522. #ifdef    TIMELOCK
  523.     signal(SIGALRM, handle);
  524.     alarm(CHECKAT);
  525. #endif
  526.  
  527.     initscr();
  528.  
  529.     mvaddstr(5, 36, getenv("USER"));
  530.     mvaddstr(22, (40 - strlen(notdone) / 2), notdone);
  531.  
  532.     for (;;) {
  533.         time(&first);
  534.         refresh();
  535.         choice = menubar(8, 25, mainmenu, 1, mainmenutitle, &menu);
  536.         clr();
  537.         switch(choice) {
  538.             case 1:
  539.                 if (locked) {
  540.                     mvaddstr(20, (40 - strlen(already) / 2), already);
  541.                     break;
  542.                 }
  543.                 curgets(lock, 60, 15, 10, lockstring, 1);
  544.                 if (!strlen(lock)) {
  545.                     mvaddstr(20, (40 - (strlen(notlong) / 2)), notlong);
  546.                     break;
  547.                 }
  548.                 curgets(check, 60, 15, 10, enteragain, 1);
  549.                 if (strcmp(lock, check)) {
  550.                     mvaddstr(20, (40 - strlen(mismatch) / 2), mismatch);
  551.                     break;
  552.                 }
  553.                 locked++;
  554.                 standout();
  555.                 mvaddstr(22, (40 - (strlen(done) / 2)), done);
  556.                 standend();
  557.                 break;
  558.             case 2:
  559.                 if (!locked) {
  560.                     mvaddstr(20, (40 - strlen(notlocked) / 2), notlocked);
  561.                     break;
  562.                 }
  563.                 curgets(unlock, 60, 15, 10, unlockstring, 1);
  564.                 if (strcmp(unlock, lock)) {
  565.                     if (!strcmp(unlock, master)) goto unlck;
  566.                     mvaddstr(20, (40 - strlen(nope) / 2), nope);
  567.                     break;
  568.                 }
  569. unlck:                locked = 0;
  570.                 clr();
  571.                 mvaddstr(22, (40 - strlen(notdone) / 2), notdone);
  572.                 break;
  573.             case 3:
  574.                 if (locked) {
  575.                     mvaddstr(20, (40 - strlen(butlocked) / 2), butlocked);
  576.                     break;
  577.                 }
  578.                 move(23, 0);
  579.                 refresh();
  580.                 endwin();
  581.                 exit(1);
  582.             default:
  583.                 break;
  584.         }
  585.     }
  586. }
  587. \End\Of\Shar\
  588. else
  589.   echo "will not over write ./termlock.c"
  590. fi
  591. if [ `wc -c ./termlock.c | awk '{printf $1}'` -ne 3116 ]
  592. then
  593. echo `wc -c ./termlock.c | awk '{print "Got " $1 ", Expected " 3116}'`
  594. fi
  595. echo "Finished archive 1 of 1"
  596. exit
  597.  
  598. exit 0 # Just in case...
  599. -- 
  600. Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
  601. Sterling Software, IMD           UUCP:     uunet!sparky!kent
  602. Phone:    (402) 291-8300         FAX:      (402) 291-4362
  603. Please send comp.sources.misc-related mail to kent@uunet.uu.net.
  604.