home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_100
/
198_02
/
menu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-23
|
12KB
|
520 lines
/* Menu: Menu processor
*/
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
#if MENUS
/* screen area (taken from display.c, should be moved to a header file) */
typedef struct VIDEOTAG {
int v_flag; /* Flags */
#if COLOR
int v_fcolor; /* current forground color */
int v_bcolor; /* current background color */
int v_rfcolor; /* requested forground color */
int v_rbcolor; /* requested background color */
#endif
char v_text[1]; /* Screen data. */
} VIDEO;
#define VFCHG 0x0001 /* Changed flag */
#define VFEXT 0x0002 /* extended (beyond column 80) */
#define VFREV 0x0004 /* reverse video status */
#define VFREQ 0x0008 /* reverse video request */
#define VFCOL 0x0010 /* color change requested */
extern VIDEO **vscreen; /* Virtual screen. */
/* menu codes return by getmkey() */
#define MENUMERR 0 /* unrecognized command */
#define MENUMUP 1 /* go up */
#define MENUMDOWN 2 /* go down */
#define MENUMLEFT 3 /* go left */
#define MENUMRIGHT 4 /* go right */
#define MENUMENTER 5 /* CR */
/* box drawing characters */
#if IBMPC
#define BOXUR 218
#define BOXUL 191
#define BOXLR 192
#define BOXLL 217
#define BOXH 196
#define BOXV 179
#else
#define BOXUR '.'
#define BOXUL '.'
#define BOXLR '\''
#define BOXLL '\''
#define BOXH '-'
#define BOXV '|'
#endif
extern int fileread(), filesave(), filewrite(), insfile();
extern int spawncli(), spawn(), quit();
extern int forwsearch(), forwhunt(), nullproc(), sreplace();
extern int forwline(), backline(), forwchar(), backchar();
extern int newline(), openline(), indent(), tab(), insspace();
#if DECEDT
extern int scupwind(), scdnwind();
#endif
#define FPNULL 0
typedef struct {
char *m_text;
int m_up;
int m_down;
int m_left;
int m_right;
int (*m_func)();
} MENUTABLE;
MENUTABLE menudata[] = {
/* 0 */ { "", 0, 1, 0, 0, FPNULL },
/* 1 */ { "File", 0, 2, 0, 9, FPNULL }, /* File option */
/* 2 */ { "New", 1, 0, 0, 3, fileread }, /* create new file */
/* 3 */ { "Open", 1, 0, 2, 4, fileread }, /* read old file */
/* 4 */ { "Insert", 1, 0, 3, 5, insfile }, /* insert file */
/* 5 */ { "Save", 1, 0, 4, 6, filesave }, /* save current file */
/* 6 */ { "save As", 1, 0, 5, 7, filewrite }, /* write a file */
/* 7 */ { "Dos", 1, 0, 6, 8, spawncli }, /* do a DOS command */
/* 8 */ { "Exit", 1, 0, 7, 0, quit }, /* exit */
/* 9 */ { "Edit", 0, 10, 1, 13, FPNULL },
/* 10 */ { "Search", 9, 0, 0, 11, forwsearch }, /* search */
/* 11 */ { "Last search", 9, 0, 10, 12, forwhunt }, /* hunt */
/* 12 */ { "Replace", 9, 0, 11, 0, sreplace }, /* replace */
/* 13 */ { "Compile", 0, 0, 9, 0, spawn }
};
int menutwid; /* width of entries on top line */
int menulast; /* last option on main menu */
menuinit() /* create menu line */
{
LINE *lalloc();
int i, j, num, wid, m, len;
if (menuflag) {
menulast = 1;
if (menuline != NULL) free(menuline);
menuline = lalloc(term.t_ncol);
if (menuline == NULL) {
mlwrite("[Can not create menu line]");
menuflag = 0;
return;
}
menuline->l_fp = NULL;
menuline->l_bp = NULL;
menuline->l_used = term.t_ncol;
num = menucount(0);
menutwid = llength(menuline) / num;
wid = menutwid - 1;
for (i = 0; i < llength(menuline); i++)
lputc(menuline, i, ' ');
j = 0;
for (m = 1; m != 0; m = menudata[m].m_right) {
for (i = 0; menudata[m].m_text[i] && i < wid; i++)
lputc(menuline, i+j, menudata[m].m_text[i]);
j += menutwid;
}
}
}
/* find number of options beneath m */
int menucount(m)
int m;
{
int c;
c = 0;
for(m = menudata[m].m_down; m != 0; m = menudata[m].m_right)
c++;
return(c);
}
/* find length of longest string under m */
int menulen(m)
int m;
{
int i, len;
len = 0;
for(m = menudata[m].m_down; m != 0; m = menudata[m].m_right) {
i = strlen( menudata[m].m_text );
if (i > len) len = i;
}
return(len);
}
int menukey; /* current key pressed */
getmkey() /* read a menu movement command */
{
int c, cmd;
int (*f)(), (*getbind())();
#if C86
int (*fbackline)(), (*fforwline)();
int (*fbackchar)(), (*fforwchar)(), (*findent)(), (*ftab)();
int (*finsspace)(), (*fnewline)(), (*fopenline)();
#if DECEDT
int (*fscupwind)(), (*fscdnwind)();
fscupwind = scupwind;
fscdnwind = scdnwind;
#endif
fbackline = backline;
fforwline = forwline;
fbackchar = backchar;
fforwchar = forwchar;
findent = indent;
ftab = tab;
finsspace = insspace;
fnewline = newline;
fopenline = openline;
#else
#if DECEDT
#define fscupwind scupwind
#define fscdnwind scdnwind
#endif
#define fbackline backline
#define fforwline forwline
#define fbackchar backchar
#define fforwchar forwchar
#define findent indent
#define ftab tab
#define finsspace insspace
#define fnewline newline
#define fopenline openline
#endif
TTflush();
c = getcmd();
menukey = c & 0x7F;
if (menukey >= 'a' && menukey <= 'z') menukey += 'A' - 'a';
f = getbind(c);
if (f == fbackline) cmd = MENUMUP;
else if (f == fforwline) cmd = MENUMDOWN;
#if DECEDT
else if (f == fscupwind) cmd = MENUMUP;
else if (f == fscdnwind) cmd = MENUMDOWN;
#endif
else if (f == fbackchar) cmd = MENUMLEFT;
else if (f == fforwchar || f == findent || f == ftab ||
f == finsspace) cmd = MENUMRIGHT;
else if (f == fnewline || f == fopenline) cmd = MENUMENTER;
else if (c == ' ') cmd = MENUMRIGHT;
else if (c == '\n') cmd = MENUMENTER;
else cmd = MENUMERR;
return(cmd);
}
int menumatch(m) /* check if menukey is in menu item m */
int m;
{
char *cp;
if (menukey >= 'A' && menukey <= 'Z')
for(cp = menudata[m].m_text; *cp != '\0'; cp++)
if (*cp == menukey) return(1);
return(0);
}
menudo(r, c, m) /* execute a menu enter command */
int r, c, m;
{
int status;
status = HOOK;
if (menudata[m].m_down != 0)
status = menupull(r, c, m);
if (menudata[m].m_func != FPNULL)
status = (*menudata[m].m_func)(FALSE, 1);
return(status);
}
menuput(row, col, len, normal) /* display a string */
int row, col, len, normal;
{
char *str;
str = &(vscreen[row]->v_text[col]);
if (row > 0) normal = 1 - normal;
TTrev(normal);
movecursor(row, col);
if (normal) {
#if COLOR
TTforg(gbcolor);
TTbacg(gfcolor);
#endif
#if IBMPC
menuwrite(row, col, str, len, gbcolor, gfcolor);
#endif
}
else {
#if COLOR
TTforg(gfcolor);
TTbacg(gbcolor);
#endif
#if IBMPC
menuwrite(row, col, str, len, gfcolor, gbcolor);
#endif
}
ttcol += len;
#if IBMPC
#else
while(len-- > 0) TTputc(*str++);
TTrev(0);
#endif
}
int menupull(row, col, men) /* pull down a menu */
int row, col, men;
{
int nrows, ncols;
int c, r, m, curmrow, status, tmprow, tmpm;
char *save, *sp, *tp;
register VIDEO *vp;
/* initialize */
++row;
nrows = menucount(men) + 2;
if (nrows > term.t_nrow) nrows = term.t_nrow;
if (row + nrows > term.t_nrow) row = term.t_nrow - nrows;
ncols = menulen(men) + 2;
if (ncols > term.t_ncol) ncols = term.t_ncol;
if (col + ncols > term.t_ncol) col = term.t_ncol - ncols;
save = malloc(nrows * ncols);
status = HOOK;
if (save == NULL) {
mlwrite("[No memory to pull down menu]");
return(status);
}
/* pull down the menu */
m = menudata[men].m_down;
sp = save;
for(r = row; r < row + nrows; r++) {
/* save old line */
tp = &(vscreen[r]->v_text[col]);
for(c = 0; c < ncols; c++) *sp++ = *tp++;
/* create new line */
tp = &(vscreen[r]->v_text[col]);
if (r == row) {
*tp++ = BOXUR;
for(c = 0; c < ncols-2; c++) *tp++ = BOXH;
*tp = BOXUL;
}
else if (r == row + nrows - 1) {
*tp++ = BOXLR;
for(c = 0; c < ncols-2; c++) *tp++ = BOXH;
*tp = BOXLL;
}
else {
*tp++ = BOXV;
for(c = 0; c < ncols-2 && menudata[m].m_text[c]; c++)
*tp++ = menudata[m].m_text[c];
for(; c < ncols-2; c++)
*tp++ = ' ';
*tp = BOXV;
m = menudata[m].m_right;
}
/* display new line */
menuput(r, col, ncols, 1);
}
/* process keys */
m = menudata[men].m_down;
curmrow = row + 1;
menuput(curmrow, col, ncols, 0);
do {
movecursor(curmrow, col);
c = getmkey();
if (c == MENUMLEFT)
m = 0;
else if (c == MENUMRIGHT || c == MENUMENTER)
status = menudo(row+nrows-1, col, m);
else if (c == MENUMUP) {
if (menudata[m].m_left != 0) {
menuput(curmrow, col, ncols, 1);
m = menudata[m].m_left; --curmrow;
menuput(curmrow, col, ncols, 0);
}
}
else if (c == MENUMDOWN) {
if (menudata[m].m_right != 0 &&
curmrow < row + nrows - 2) {
menuput(curmrow, col, ncols, 1);
m = menudata[m].m_right; curmrow++;
menuput(curmrow, col, ncols, 0);
}
}
else {
tmprow = row + 1;
tmpm = menudata[men].m_down;
while (tmpm != 0 && (!menumatch(tmpm)) &&
tmprow < row + nrows - 2) {
tmpm = menudata[tmpm].m_right;
++tmprow;
}
if (tmpm != 0) {
menuput(curmrow, col, ncols, 1);
m = tmpm;
curmrow = tmprow;
menuput(curmrow, col, ncols, 0);
status = menudo(curmrow, col, m);
}
else
TTbeep();
}
} while (m != 0 && status == HOOK);
/* restore the screen */
sp = save;
for(r = row; r < row + nrows; r++) {
movecursor(r, col);
if (vscreen[r]->v_flag & VFREQ) TTrev(1); else TTrev(0);
#if COLOR
TTforg(vscreen[r]->v_rfcolor);
TTbacg(vscreen[r]->v_rbcolor);
#endif
#if IBMPC
menuwrite(r, col, sp, ncols,
vscreen[r]->v_rfcolor, vscreen[r]->v_rbcolor);
#endif
tp = &(vscreen[r]->v_text[col]);
for(c = 0; c < ncols; c++) {
#if IBMPC
#else
TTputc(*sp);
#endif
*tp++ = *sp++;
}
ttcol += ncols;
}
free(save);
/* return */
return(status);
}
menutput(col, m, normal) /* display a string on top line */
int col, m, normal;
{
int len;
len = strlen(menudata[m].m_text);
if (len >= menutwid) len = menutwid - 1;
menuput(0, col, len, normal);
}
int menu(f, n) /* actual menu command */
{
int i, m, c, curmcol, wid, status, tmpcol, tmpm;
if (!menuflag) return(TRUE);
status = HOOK;
m = 1;
curmcol = 0;
if (f == TRUE)
while (--n > 0 && menudata[m].m_right != 0) {
m = menudata[m].m_right;
curmcol += menutwid;
}
else
while (m != menulast && menudata[m].m_right != 0) {
m = menudata[m].m_right;
curmcol += menutwid;
}
menutput(curmcol, m, 0);
do {
movecursor(0, curmcol);
c = getmkey();
if (c == MENUMLEFT) {
menutput(curmcol, m, 1);
if (menudata[m].m_left != 0)
{m = menudata[m].m_left; curmcol -= menutwid;}
else
while(menudata[m].m_right != 0) {
m = menudata[m].m_right;
curmcol += menutwid;
}
menutput(curmcol, m, 0);
}
else if (c == MENUMRIGHT) {
menutput(curmcol, m, 1);
if (menudata[m].m_right != 0)
{m = menudata[m].m_right; curmcol += menutwid;}
else
{m = 1; curmcol = 0;}
menutput(curmcol, m, 0);
}
else if (c == MENUMUP)
status = TRUE;
else if (c == MENUMDOWN || c == MENUMENTER)
status = menudo(0, curmcol, m);
else {
tmpcol = 0;
tmpm = menudata[0].m_down;
while (tmpm != 0 && !menumatch(tmpm)) {
tmpm = menudata[tmpm].m_right;
tmpcol += menutwid;
}
if (tmpm != 0) {
menutput(curmcol, m, 1);
m = tmpm;
curmcol = tmpcol;
status = menudo(0, curmcol, m);
menutput(curmcol, m, 0);
}
else
TTbeep();
}
} while (status == HOOK);
menutput(curmcol, m, 1);
menulast = m;
return(status);
}
#endif