jek5036@ultb.isc.rit.edu (J.E. King) (04/23/91)
Submitted-by: J.E. King <jek5036@ultb.isc.rit.edu> Posting-number: Volume 18, Issue 80 Archive-name: menubar/part01 Supersedes: menubar: Volume 17, Issue 62 This is a demonstration package on how to use two new curses routines: menubar - sets up a menu on the screen using a menu-bar format, curgets - get a string using curses in a box on the screen, termlock - a terminal lock program complete with compile definable timeout, and an option to logout at timeout (safelock). Jim King <jek5036@ultb.isc.rit.edu> -- cut here -- cut here -- cut here -- cut here -- cut here -- cut here -- #!/bin/sh # to extract, remove the header and type "sh filename" if `test ! -s ./Makefile` then echo "writing ./Makefile" cat > ./Makefile << '\End\Of\Shar\' # # Makefile for termlock, curses implemented # by Jim King (jek5036@ultb.isc.rit.edu) # # Define TIMELOCK is you want the program to timeout # Timeout means if the terminal is idle (nobody touches it) for so many # seconds, the program will quit.. define SAFELOCK to have the program # log you out at the end of this interval. Useful for computer rooms # where terminals are fought over.. # # If you define TIMELOCK or SAFELOCK, make sure you define DEFTIME. # DEFTIME is the amount of idle seconds the terminal can sit before timeout. # # CHECKAT is the amount of seconds the program will 'sleep' before # checking if timeout time has occured. # # Define SYSV for a SYSV make # # CFLAGS = -O -DSAFELOCK -DCHECKAT=30 -DDEFTIME=600 -DSYSV CFLAGS = -O -DTIMELOCK -DCHECKAT=15 -DDEFTIME=300 # 5 minutes all: termlock termlock: menubar.o termlock.o curgets.o cc termlock.o menubar.o curgets.o -o termlock -O -lcurses -ltermcap termlock.o: termlock.c /usr/include/curses.h /usr/include/signal.h menubar.o: menubar.c /usr/include/curses.h curgets.o: curgets.c /usr/include/curses.h \End\Of\Shar\ else echo "will not over write ./Makefile" fi if [ `wc -c ./Makefile | awk '{printf $1}'` -ne 1083 ] then echo `wc -c ./Makefile | awk '{print "Got " $1 ", Expected " 1083}'` fi if `test ! -s ./README` then echo "writing ./README" cat > ./README << '\End\Of\Shar\' This is a demonstration package on how to use two new curses routines: menubar - sets up a menu on the screen using a menu-bar format curgets - get a string using curses in a box on the screen termlock itself is a terminal lock program complete with compile definable timeout, and an option to logout at timeout (safelock). Problems to jek5036@ultb.isc.rit.edu (Jim King) If above address fails (and it won't) try pulsar%lsrhs.uucp@xait.xerox.com (same person) \End\Of\Shar\ else echo "will not over write ./README" fi if [ `wc -c ./README | awk '{printf $1}'` -ne 466 ] then echo `wc -c ./README | awk '{print "Got " $1 ", Expected " 466}'` fi if `test ! -s ./curgets.c` then echo "writing ./curgets.c" cat > ./curgets.c << '\End\Of\Shar\' /* * Curses getstring in a box * by Jim King (jek5036@ultb.isc.rit.edu) */ #include <curses.h> /* curses include file */ /* * curgets is a void type because it does not return anything. * curgets arguments: * * str: address of a character array, passed in like &string * this will contain the string which the user inputs * len: the maximum amount of characters to read in (defines box size) * y, x: (x, y) coordinates on the screen of the box's upper left-hand corner * title: same as str, but it is the title for the box */ void curgets(str, len, y, x, title, hide) char *str, *title; int len, y, x, hide; { WINDOW *strwin; char c, input[80]; int pos, curx; strwin = newwin(3, len+2, y, x); box(strwin, '|', '-'); mvwaddch(strwin, 0, 0, '/'); mvwaddch(strwin, 2, 0, '\\'); mvwaddch(strwin, 0, len+1, '\\'); mvwaddch(strwin, 2, len+1, '/'); wstandout(strwin); mvwaddstr(strwin, 0, (len / 2) - (strlen(title) / 2), title); wstandend(strwin); ers: curx = 1; for (pos = 1; pos < len; pos++) mvwaddch(strwin, 1, pos, '_'); for (;;) { wmove(strwin, 1, curx); wrefresh(strwin); noecho(); crmode(); c = wgetch(strwin); switch(c) { case '\177': /* DELETE */ if (curx == 1) break; mvwaddch(strwin, 1, --curx, '_'); input[curx-1] = '\0'; break; case '\025': /* ^U, line kill */ goto ers; break; case '\015': case '\012': /* RETURN, LF */ input[curx-1] = '\0'; wclear(strwin); wrefresh(strwin); delwin(strwin); strcpy(str, input); return; default: if (curx == len) break; if (c < 033) break; /* no control chars */ wstandout(strwin); if (!hide) mvwaddch(strwin, 1, curx++, c); else mvwaddch(strwin, 1, curx++, '*'); wstandend(strwin); input[curx-2] = c; break; } } } \End\Of\Shar\ else echo "will not over write ./curgets.c" fi if [ `wc -c ./curgets.c | awk '{printf $1}'` -ne 1811 ] then echo `wc -c ./curgets.c | awk '{print "Got " $1 ", Expected " 1811}'` fi if `test ! -s ./menubar.c` then echo "writing ./menubar.c" cat > ./menubar.c << '\End\Of\Shar\' /* * Menubar - curses driven menu bar display * menubar will run a menu-bar display on screen for you. * This type of package is useful for databases, etc.. */ /* Menubar V1.0 by Jim King (jek5036@ultb.isc.rit.edu) - Original source */ /* V1.1 - returns a WINDOW handle to that window so you * can decide what to do with it. Your choice * is handled as a pointer and set by the function * * Modification by Jim King (jek5036@ultb.isc.rit.edu) */ #include <stdio.h> #include <curses.h> #include <signal.h> #ifdef SYSV # include <string.h> #else # include <strings.h> #endif #define MAXNAMELEN 70 #define UP 'A' #define DN 'B' #define LT 'C' #define RT 'D' #define ESC '\033' #define RET '\015' #define LF '\012' struct mbar { char menu_choice[MAXNAMELEN]; int menu_number; struct mbar *next; } *m; WINDOW *MENU; #define NEW(XXX) (struct XXX *)malloc(sizeof(struct XXX)) int Stopflag = 0; /* interrupt flag */ /* * converts information in menu to a linked-list */ mkmenubar(num, menu) int *num; char *menu[]; { int i = 0; /* counter for num */ struct mbar *tmp; /* tmp pointer to list */ m = NEW(mbar); /* initialize menubar */ tmp = m; /* set tmp to head */ do { strcpy(tmp->menu_choice, menu[i]); tmp->menu_number = i+1; /* move values into tmp */ tmp->next = NEW(mbar); tmp = tmp->next; /* set up next link */ ++i; } while (menu[i] != NULL); *num = i; /* 'return' the maxnum of choices */ tmp = NULL; /* lop off the end */ } /* * determine optimal size for menu bar. */ sizemenubar(len, wid, title) int *len, *wid; char *title; { int sz = 0, i = 0; /* tmp counter */ struct mbar *tmp; /* tmp placeholder */ *len = 0; *wid = 0; tmp = m; for (tmp = m; tmp != NULL; tmp = tmp->next) { ++i; sz = strlen(tmp->menu_choice); if (sz > *wid) /* as wide as longest line */ *wid = sz; } if (title != NULL) if (strlen(title) > *wid) *wid = strlen(title); *wid += 8; /* extras like #] and . */ *len = i+1; } /* * sets up the menu on MENU window */ dispmenu(boxflag, title, width, length) int boxflag, width, length; char *title; { struct mbar *tmp; if (boxflag) { box(MENU, '|', '-'); mvwaddch(MENU, 0, 0, '/'); mvwaddch(MENU, 0, width-1, '\\'); mvwaddch(MENU, length-1, 0, '\\'); mvwaddch(MENU, length-1, width-1, '/'); } if (title != NULL) { wstandout(MENU); mvwaddstr(MENU, 0, (width / 2) - (strlen(title) / 2), title); wstandend(MENU); } for (tmp = m; tmp != NULL; tmp = tmp->next) { if (tmp->menu_number == 0) continue; wmove(MENU, tmp->menu_number, 1); wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice); } wrefresh(MENU); } /* * un-hilight old selection at num */ delight(num) int num; { struct mbar *tmp; for (tmp = m; tmp != NULL; tmp = tmp->next) { if (num == tmp->menu_number) { wmove(MENU, tmp->menu_number, 1); wprintw(MENU, "%d] %s. ", tmp->menu_number, tmp->menu_choice); } } wrefresh(MENU); } /* * hilight selection at num */ hilight(num) int num; { struct mbar *tmp; for (tmp = m; tmp != NULL; tmp = tmp->next) { if (num == tmp->menu_number) { wstandout(MENU); /* highlight */ wmove(MENU, tmp->menu_number, 1); wprintw(MENU, "%d> %s. ", tmp->menu_number, tmp->menu_choice); wstandend(MENU); } } wrefresh(MENU); } /* * main function call * menubar(y, x, menu) where * y = starting line of menu * x = starting column of menu * menu is of type *menu[] in which are stored the items for be chosen * boxflag = boolean if !0, draw box around border of menu * title = address to char array for title of menu * win = returns a handle to the menu so you can delete it when you want */ int menubar(y, x, menu, boxflag, title, win) int y, x, boxflag; char *menu[], *title; WINDOW *win; { int cur = 1, old = 1, l, w, num; char c; mkmenubar(&num, menu); sizemenubar(&l, &w, title); /* Menubar ASSUMES that the calling procedure initialized curses already */ MENU = newwin(l, w, y, x); /* start (x, y) to (x+w, y+l) */ dispmenu(boxflag, title, w, l); noecho(); crmode(); for (;;) { delight(old); hilight(cur); if (Stopflag) { cur = -1; goto end; } c = wgetch(MENU); switch(c) { case ESC: wgetch(MENU); switch(wgetch(MENU)) { case UP: case RT: old = cur--; if (Stopflag) { cur = -1; goto end; } break; case DN: case LT: old = cur++; if (Stopflag) { cur = -1; goto end; } break; default: if (Stopflag) { cur = -1; goto end; } break; } break; case LF: case RET: if (Stopflag) { cur = -1; goto end; } end: win = MENU; return(cur); break; default: if (Stopflag) { cur = -1; goto end; } if (c > '0' || c <= '9') { old = cur; cur = c - '0'; if (cur > num) cur = num; if (cur < 1) cur = 1; } break; } if (cur > num) cur = 1; if (cur < 1) cur = num; } } \End\Of\Shar\ else echo "will not over write ./menubar.c" fi if [ `wc -c ./menubar.c | awk '{printf $1}'` -ne 4977 ] then echo `wc -c ./menubar.c | awk '{print "Got " $1 ", Expected " 4977}'` fi if `test ! -s ./termlock.c` then echo "writing ./termlock.c" cat > ./termlock.c << '\End\Of\Shar\' /* * termlock - a menu-driven terminal lock */ #include <signal.h> #include <curses.h> #ifdef SAFELOCK #ifndef TIMELOCK #define TIMELOCK #endif #endif char *mainmenu[] = { "Lock terminal", "Unlock terminal", "Quit", 0 }; #ifdef TIMELOCK long first; #endif char notdone[80] = "Terminal is NOT LOCKED."; char done[80] = "Terminal is LOCKED."; char mainmenutitle[80] = "TermLock V1.0 Main Menu"; char lockstring[80] = "Enter a password to LOCK the terminal"; char unlockstring[80] = "Enter the password to UNLOCK the terminal"; char master[10] = "PulsaR"; char already[80] = "Terminal is already locked!"; char notlong[80] = "Password not long enough."; char notlocked[80] = "Terminal isn't locked!"; char nope[80] = "Password mismatch. Go away."; char butlocked[80] = "But wait! It's locked."; char enteragain[80] = "Enter password again for verification."; char mismatch[80] = "Passwords do not match. Terminal not locked."; #ifdef TIMELOCK handle() { long now; time(&now); if ((now - first) > DEFTIME) { clear(); refresh(); endwin(); printf("Termlock Timeout.\n\n"); #ifdef SAFELOCK if (getuid() == 0) /* don't want to kill the system */ exit(1); kill(getppid(), 9); #endif exit(1); } else { move(0, 75); printw("%d", DEFTIME - (now - first)); refresh(); signal(SIGALRM, handle); alarm(CHECKAT); return; } } #endif TIMELOCK clr() { move(20, 0); clrtoeol(); refresh(); } main() { char lock[40], unlock[40], check[40]; WINDOW *menu; int choice, locked = 0; signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); signal(SIGTERM, SIG_IGN); #ifndef SYSV signal(SIGTSTP, SIG_IGN); signal(SIGSTOP, SIG_IGN); #endif /* SYSV */ #ifdef TIMELOCK signal(SIGALRM, handle); alarm(CHECKAT); #endif initscr(); mvaddstr(5, 36, getenv("USER")); mvaddstr(22, (40 - strlen(notdone) / 2), notdone); for (;;) { time(&first); refresh(); choice = menubar(8, 25, mainmenu, 1, mainmenutitle, &menu); clr(); switch(choice) { case 1: if (locked) { mvaddstr(20, (40 - strlen(already) / 2), already); break; } curgets(lock, 60, 15, 10, lockstring, 1); if (!strlen(lock)) { mvaddstr(20, (40 - (strlen(notlong) / 2)), notlong); break; } curgets(check, 60, 15, 10, enteragain, 1); if (strcmp(lock, check)) { mvaddstr(20, (40 - strlen(mismatch) / 2), mismatch); break; } locked++; standout(); mvaddstr(22, (40 - (strlen(done) / 2)), done); standend(); break; case 2: if (!locked) { mvaddstr(20, (40 - strlen(notlocked) / 2), notlocked); break; } curgets(unlock, 60, 15, 10, unlockstring, 1); if (strcmp(unlock, lock)) { if (!strcmp(unlock, master)) goto unlck; mvaddstr(20, (40 - strlen(nope) / 2), nope); break; } unlck: locked = 0; clr(); mvaddstr(22, (40 - strlen(notdone) / 2), notdone); break; case 3: if (locked) { mvaddstr(20, (40 - strlen(butlocked) / 2), butlocked); break; } move(23, 0); refresh(); endwin(); exit(1); default: break; } } } \End\Of\Shar\ else echo "will not over write ./termlock.c" fi if [ `wc -c ./termlock.c | awk '{printf $1}'` -ne 3116 ] then echo `wc -c ./termlock.c | awk '{print "Got " $1 ", Expected " 3116}'` fi echo "Finished archive 1 of 1" exit exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.