Category : Files from Magazines
Archive   : DDJSRC.ZIP
Filename : MENU.C

 
Output of file : MENU.C contained in archive : DDJSRC.ZIP

/* ------------ menu.c ------------ */

#include
#include
#include
#include
#include
#include "window.h"
#include "menu.h"

#define ON 1
#define OFF 0

static int getvmn(void);
static void haccent(int);
static void dimension(char **,int *,int *);
static void light(int);
static int vlook(int,int);

int hsel = 1; /* horizontal selection */
MENU *mn; /* active menu */

/* ------------- display & process a menu ----------- */
void menu_select(MENU *mnn, int sel)
{
int hs, sx, sy, vsel, holdhsel, frtn = FALSE;
char *mb;

if (sel)
hsel = sel;
mn = mnn;
sx = wherex();
sy = wherey();
mb = display_menubar(mn);
light(ON);
while (!frtn && ((vsel = getvmn()) != 0)) {
light(OFF);
holdhsel = hsel;
hs = hsel;
hsel = 1;
frtn = (*(mn+hs-1)->func [vsel-1]) ?
(*(mn+hs-1)->func [vsel-1])(hs,vsel) : FALSE;
hsel = holdhsel;
mn = mnn;
light(ON);
}
light(OFF);
gotoxy(sx, sy);
restore_menubar(mb);
}

/* --- display the menu bar with no selections chosen ---- */
char *display_menubar(MENU *mn)
{
int i = 0;
char *mb;

if ((mb = malloc(160)) != NULL)
gettext(1,1,80,1,mb);
window(1,1,80,25);
gotoxy(1,1);
textcolor(MENUFG);
textbackground(MENUBG);
cprintf(" ");
while ((mn+i)->mname)
cprintf(" %-10.10s ", (mn+i++)->mname);
while (i++ < 6)
cprintf(" ");
cprintf(" ");
hidecursor();
return mb;
}

/* ------------ restore the menu bar line --------------- */
void restore_menubar(char *mb)
{
if (mb) {
puttext(1,1,80,1,mb);
free(mb);
}
}

/* ---------pop down a vertical menu --------- */
static int getvmn()
{
int ht, wd, vx, sel;

while (TRUE) {
dimension((mn+hsel-1)->mselcs, &ht, &wd);
if (!(mn+hsel-1)->lastvsel)
(mn+hsel-1)->lastvsel = 1;
if (ht > 0) {
vx = 5+(hsel-1)*12;
establish_window(vx, 2, vx+wd+1, ht+3,
MENUFG, MENUBG,TRUE);
text_window((mn+hsel-1)->mselcs, 1);
sel = select_window((mn+hsel-1)->lastvsel,
SELECTFG, SELECTBG, vlook);
delete_window();
if (sel == FWD || sel == BS)
haccent(sel);
else
return ((mn+hsel-1)->lastvsel = sel);
}
else {
if ((sel = getkey()) == *(mn+hsel-1)->mskeys)
return 1;
switch (sel) {
case FWD:
case BS: haccent(sel);
break;
case '\r': return 1;
case ESC: return 0;
default: putch(BELL);
break;
}
}
}
}

/* ---- if vertical menu user types FWD, BS,
or a menu key, return it ---- */
static int vlook(ch, sel)
{
char *cs, *ks;

if (ch == FWD || ch == BS) {
(mn+hsel-1)->lastvsel = sel;
return ch;
}
ks = (mn+hsel-1)->mskeys;
if ((cs = memchr(ks, tolower(ch), strlen(ks))) == NULL)
return ERROR;
return ((mn+hsel-1)->lastvsel = cs-ks+1);
}

/* ----- manage the horizontal menu selection accent ----- */
static void haccent(int sel)
{
switch (sel) {
case FWD:
light(OFF);
if ((mn+hsel)->mname)
hsel++;
else
hsel = 1;
light(ON);
break;
case BS:
light(OFF);
if (hsel == 1)
while ((mn+hsel)->mname)
hsel++;
else
--hsel;
light(ON);
break;
default:
break;
}
}

/* ---------- compute a menu's height & width --------- */
static void dimension(char *sl[], int *ht, int *wd)
{
*ht = *wd = 0;

while (sl && sl [*ht]) {
*wd = max(*wd, (unsigned) strlen(sl [*ht]));
(*ht)++;
}
}

/* --------- accent a horizontal menu selection ---------- */
static void light(int onoff)
{
extern struct wn wkw;
extern char spaces[];
int ln;

window(1,1,80,25);
textcolor(onoff ? SELECTFG : MENUFG);
textbackground(onoff ? SELECTBG : MENUBG);
gotoxy((hsel-1)*12+6, 1);
cprintf((mn+hsel-1)->mname);
textcolor(TEXTFG);
textbackground(TEXTBG);
if ((mn+hsel-1)->mhlpmsg) {
if (onoff) {
ln = strlen((mn+hsel-1)->mhlpmsg);
gotoxy((80-ln)/2,25);
cprintf((mn+hsel-1)->mhlpmsg);
}
else {
gotoxy(1,25);
cprintf(spaces);
}
}
current_window();
hidecursor();
}