v18i080: menubar - C Menubar function, Part01/01
J.E. King
jek5036 at ultb.isc.rit.edu
Tue Apr 23 11:35:41 AEST 1991
Submitted-by: J.E. King <jek5036 at 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 at 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 at 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 at ultb.isc.rit.edu (Jim King)
If above address fails (and it won't)
try pulsar%lsrhs.uucp at 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 at 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 at 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 at 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list