/*
* MNU.C
*
* Written on 10-Jul-94 by John Dennis and released to the public domain.
*
* Routines to display horizontal and vertical menus with full drag/browse
* mouse support.
*/
#include <string.h>
#include <stdlib.h>
#include "winsys.h"
#include "keys.h"
#include "menu.h"
int PullDown = 0;
int ExitType = 0;
static int bc = WHITE | _CYAN;
static int nc = BLACK | _CYAN;
static int sc = WHITE | _BLACK;
static int GetFocus(cmd * cmdtab, int num, int id)
{
int i;
for (i = 0; i < num; i++)
{
if (cmdtab[i].id == id)
{
return i;
}
}
return -1;
}
static void DispItem(cmd * c, unsigned char attr, int indent, int slen, int type)
{
char text[255];
int len;
if (!c || !c->itmtxt)
{
return;
}
len = strlen(c->itmtxt);
memset(text, ' ', slen + 2);
strncpy(text + indent, c->itmtxt, len);
*(text + slen) = '\0';
if (type == CMD_VER)
{
WndPutsn(0, c->row, slen, attr, text);
}
else
{
WndPutsn(c->col, c->row, slen, attr, text);
}
}
static int NextItem(int num, int cur)
{
cur++;
if (cur == num)
{
cur = 0;
}
return cur;
}
static int PrevItem(int num, int cur)
{
cur--;
if (cur < 0)
{
cur = num - 1;
}
return cur;
}
/*
* Displays a horizontal menu in a window, according to the info in
* the passed MC structure.
*
* The current mouse position is passed to the function to pinpoint
* the item where the mouse hit before calling this function.
*/
int ProcessMenu(MC * m, EVT * event, int show)
{
HotGroup Hot;
WND *hCurr, *hWnd = NULL;
cmd *cmdtab = m->cmdtab;
int num = m->num;
int Focus = m->cur;
int mnu = m->mode;
int len = m->len;
int OldFoc;
int done = 0;
int select = 0;
int Msg; /* Msg is used unitialised here. I did not yet
investigate it. FIXME! */
int NewFoc;
int i, j;
if (m->btype & INSBDR)
{
m->btype = SBDR;
}
hCurr = WndTop();
if (!show && !(m->mode & CMD_PRT))
{
hWnd = WndOpen(m->x1, m->y1, m->x2, m->y2, m->btype, bc, nc);
if (hWnd == NULL)
{
WndCurr(hCurr);
return WND_ERROR;
}
}
if (m->btype & NBDR)
{
j = 0;
}
else
{
j = 1;
}
for (i = 0; i < num; i++)
{
Hot.harr[i].id = cmdtab[i].id;
Hot.harr[i].x1 = m->x1 + j + cmdtab[i].col;
Hot.harr[i].x2 = m->x1 + j + cmdtab[i].col + len;
Hot.harr[i].y1 = m->y1 + j + cmdtab[i].row;
Hot.harr[i].y2 = m->y1 + j + cmdtab[i].row;
DispItem(&cmdtab[i], (unsigned char)nc, m->indent, m->len, mnu);
}
if (show)
{
return 0;
}
Hot.num = num;
Hot.wid = WND_WN_MENU;
PushHotGroup(&Hot);
if (event->msg)
{
if (event->msgtype == WND_WM_COMMAND)
{
Focus = GetFocus(cmdtab, m->num, event->id);
}
else
{
if (event->msgtype == WND_WM_MOUSE)
{
Focus = LocateHotItem(event->x, event->y, WND_WN_MENU);
if (Focus)
{
Focus = GetFocus(cmdtab, m->num, Focus);
}
}
}
if (Focus == -1)
{
Focus = 0;
}
}
DispItem(&cmdtab[Focus], (unsigned char)sc, m->indent, m->len, mnu);
while (!done)
{
if (select)
{
if (cmdtab[Focus].m_sub)
{
ProcessMenu(cmdtab[Focus].m_sub, event, 0);
}
else
{
if (cmdtab[Focus].flags & CMD_EXIT)
{
done = TRUE;
continue;
}
else
{
if (cmdtab[Focus].itmfunc != NULL)
{
(*cmdtab[Focus].itmfunc) ();
}
done = TRUE; /* should we exit here? */
continue;
}
}
select = 0;
}
else
{
Msg = MnuGetMsg(event, WND_WN_MENU);
}
OldFoc = Focus;
switch (event->msgtype)
{
case WND_WM_COMMAND:
NewFoc = GetFocus(cmdtab, m->num, event->id);
if (NewFoc != -1)
{
switch (Msg)
{
case MOU_LBTUP:
case LMOU_CLCK:
Focus = NewFoc;
select = TRUE;
break;
case MOU_LBTDN:
case LMOU_RPT:
case MOUSE_EVT:
Focus = NewFoc;
if (cmdtab[Focus].m_sub)
{
select = TRUE;
}
break;
default:
break;
}
}
else
{
if (mnu == CMD_VER && event->msg != m->parent)
{
done = TRUE;
}
}
break;
case WND_WM_MOUSE:
switch (Msg)
{
case LMOU_CLCK:
case MOU_LBTUP:
done = TRUE;
break;
default:
break;
}
break;
case WND_WM_CHAR:
switch (Msg)
{
case Key_Up:
if (mnu == CMD_VER)
{
Focus = PrevItem(m->num, Focus);
}
break;
case Key_Dwn:
if (cmdtab[Focus].m_sub)
{
select = TRUE;
}
if (mnu == CMD_VER)
{
Focus = NextItem(m->num, Focus);
}
break;
case Key_Lft:
if (mnu == CMD_HOR)
{
Focus = PrevItem(m->num, Focus);
}
else
{
done = TRUE;
}
break;
case Key_Rgt:
if (mnu == CMD_HOR)
{
Focus = NextItem(m->num, Focus);
}
else
{
done = TRUE;
}
break;
case Key_Esc:
done = TRUE;
break;
case Key_Ent:
select = TRUE;
break;
default:
break;
}
break;
default:
break;
}
if (Focus != OldFoc)
{
DispItem(&cmdtab[OldFoc], (unsigned char)nc, m->indent, m->len, mnu);
DispItem(&cmdtab[Focus], (unsigned char)sc, m->indent, m->len, mnu);
}
}
DispItem(&cmdtab[Focus], (unsigned char)nc, m->indent, m->len, mnu);
PopHotGroup();
if (!(m->mode & CMD_PRT))
{
WndClose(hWnd);
WndCurr(hCurr);
}
if (cmdtab[Focus].flags & CMD_EXIT && select)
{
/* then return the ID of ret item */
event->msgtype = WND_WM_CHAR;
event->msg = 0;
return cmdtab[Focus].id;
}
else
{
return 0;
}
}
void MnuSetColours(int nbc, int nnc, int nsc)
{
bc = nbc;
nc = nnc;
sc = nsc;
}
syntax highlighted by Code2HTML, v. 0.9.1