/*
* MENU.C
*
* Written on 10-Jul-94 by John Dennis and released to the public domain.
*
* Moving bar menu code for Msged.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "winsys.h"
#include "unused.h"
#include "menu.h"
#include "addr.h"
#include "nedit.h"
#include "msged.h"
#include "main.h"
#include "keys.h"
#include "strextra.h"
#include "areas.h"
#include "memextra.h"
void SelShowItem(char *text, int y, int len, int Attr, int indent)
{
char line[256];
memset(line, ' ', 40);
strcpy(line + indent, text);
WndPutsn(indent, y, len, Attr, line);
}
void SelShowPage(char **text, int top, int bot, int len, int pos, int Attr, int indent)
{
int i;
int y = top;
for (i = pos; text[i] != NULL; i++)
{
if (y > bot)
{
break;
}
SelShowItem(text[i], y++, len, Attr, indent);
}
if (y <= bot)
{
while (y <= bot)
{
SelShowItem(" ", y++, len, Attr, indent);
}
}
}
void CalcDef(int max, int cur, int *top, int miny, int maxy, int *y)
{
int dif = maxy - miny;
unused(cur);
if (max - 1 - *top < dif && max > dif)
{
*y = maxy;
*top = (max - 1) - dif;
}
}
int SelBox(char **Itms, int y1, int y2, int len, int def, WND * hPrev, WND * hWnd, int Sel, int Norm, int selbox_id, char *topMsg)
{
EVT e;
char find[30];
int itemCnt, Stuff, done, curY, Msg, currItem, Top, page, i;
itemCnt = 0;
Stuff = 0;
for (i = 0; Itms[i] != NULL; i++)
{
itemCnt++;
}
if (itemCnt < y2)
{
y2 = itemCnt;
}
currItem = def;
curY = y1;
page = y2 - y1;
Top = currItem;
if (currItem + y1 < y1)
{
curY = y1 + currItem;
Top = 0;
}
else
{
if (itemCnt - currItem <= y2 - y1)
{
Top -= ((y2 - y1 + 1) - (itemCnt - Top));
curY = y1 + def - Top;
if (Top < 0)
{
Top = 0;
curY--;
}
}
}
done = 0;
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
/* clear input queue */
TTClearQue();
memset(find, '\0', sizeof find);
while (!done)
{
if (*topMsg && selbox_id == SELBOX_REPLYOTH && !*find)
{
WndCurr(hPrev);
WndClear(strlen(topMsg) + 3, 0, maxx - 32, 0, cm[MN_NTXT]);
WndPrintf(0, 0, cm[MN_NTXT], ">>%s:", topMsg);
WndCurr(hWnd);
}
if (!Stuff)
{
Msg = MnuGetMsg(&e, hWnd->wid);
}
else
{
e.msgtype = WND_WM_CHAR;
Msg = Stuff;
Stuff = 0;
}
switch (e.msgtype)
{
case WND_WM_MOUSE:
switch (Msg)
{
case RMOU_CLCK:
case MOU_RBTUP:
return -1;
case LMOU_RPT:
case MOU_LBTDN:
case LMOU_CLCK:
{
int x, y;
WndGetRel(e.x, e.y, &x, &y);
if (y >= y1 && y <= y2) /* in window */
{
Stuff = 0;
if (x >= 0 && x < len)
{
if (y == curY)
{
if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
{
return currItem;
}
else
{
continue;
}
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
if (y > curY)
{
currItem += y - curY;
}
else
{
currItem -= curY - y;
}
curY = y;
SelShowItem(Itms[currItem], curY, len, Sel, 1);
if (Msg == LMOU_CLCK || Msg == MOU_LBTUP)
{
return currItem;
}
}
}
else
{
if (Msg != LMOU_CLCK)
{
if (y < y1)
{
Stuff = Key_Up;
}
else
{
Stuff = Key_Dwn;
}
}
}
}
memset(find, '\0', sizeof find);
break;
default:
break;
}
break;
case WND_WM_CHAR:
switch (Msg)
{
case Key_Home:
if (!currItem)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem = 0;
Top = 0;
curY = y1;
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_End:
if (currItem == itemCnt - 1)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem = itemCnt - 1;
while (currItem && currItem >= itemCnt - page)
{
currItem--;
}
Top = currItem;
currItem = itemCnt - 1;
curY = currItem - Top + y1;
CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_Dwn:
if (currItem == itemCnt - 1)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem++;
if (curY == y2)
{
WndScroll(1, y1, len, y2, 1);
Top++;
}
else
{
curY++;
}
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_Up:
if (!currItem)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem--;
if (curY == y1)
{
WndScroll(1, y1, len, y2, 0);
if (Top)
{
Top--;
}
}
else
{
curY--;
}
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_PgUp:
if (!currItem)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem -= page;
if (currItem < 0)
{
currItem = 0;
}
Top = currItem;
curY = y1;
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_PgDn:
if (currItem == itemCnt - 1)
{
break;
}
SelShowItem(Itms[currItem], curY, len, Norm, 1);
Top = currItem;
currItem += page;
if (currItem > itemCnt - 1)
{
currItem = itemCnt - 1;
}
curY = currItem - Top + y1;
CalcDef(itemCnt, currItem, &Top, y1, y2, &curY);
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
break;
case Key_Rgt:
case Key_Ent:
{
size_t i;
i = (size_t) strchr(Itms[currItem] + 1, ' ') - 1 -
(size_t) Itms[currItem];
if (i > 28)
{
i = 28;
}
strncpy(find, Itms[currItem] + 1, i);
*(find + i) = '\0';
strupr(find);
/* I did figure out that this code produces garbage on
screen. I did not figure out however, in
when situations it is necessary. So I
decided to comment it out and see what
happens ...
WndCurr(hPrev);
WndWriteStr(strlen(topMsg) + 4, 0, cm[MN_NTXT], find);
*/
WndCurr(hWnd);
return currItem;
}
case Key_A_X:
case Key_Esc:
return -1;
case '*':
case Key_A_S:
if (selbox_id == SELBOX_REPLYOTH)
{
arealist_area_scan(1);
for (i = 0; i < SW->areas; i++)
{
xfree(alist2[i]);
}
xfree(alist2);
BuildList(&alist2);
Itms = alist2;
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
memset(find, '\0', sizeof find);
CurArea.messages = MsgAreaOpen(&CurArea);
}
break;
default:
if (Msg > 32 && Msg < 127)
{
if (*topMsg && selbox_id == SELBOX_REPLYOTH)
{
if (strlen(find) >= 28)
{
break;
}
*(find + strlen(find)) = (char)toupper((char)Msg);
WndCurr(hPrev);
WndWriteStr(strlen(topMsg) + 4, 0, cm[MN_NTXT], find);
WndCurr(hWnd);
}
else
{
*find = (char)toupper((char)Msg);
}
i = currItem;
while (i < itemCnt)
{
if (selbox_id == SELBOX_REPLYOTH)
{
if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
{
break;
}
}
else
{
if (toupper(*Itms[i]) == *find)
{
if (selbox_id == SELBOX_MOVEMSG ||
selbox_id == SELBOX_WRTMODE ||
selbox_id == SELBOX_WRTOVER)
{
SelShowItem(Itms[currItem], curY, len, Norm, 1);
return i;
}
}
}
i++;
}
if (i == itemCnt)
{
for (i = 0; i < currItem; i++)
{
if (selbox_id == SELBOX_REPLYOTH)
{
if (stristr(Itms[i] + 1, find) == Itms[i] + 1)
{
break;
}
}
else
{
if (toupper(*Itms[i]) == *find)
{
if (selbox_id == SELBOX_MOVEMSG ||
selbox_id == SELBOX_WRTMODE ||
selbox_id == SELBOX_WRTOVER)
{
SelShowItem(Itms[currItem], curY, len, Norm, 1);
return i;
}
}
}
}
}
if (i != currItem)
{
SelShowItem(Itms[currItem], curY, len, Norm, 1);
currItem = i;
curY = y1;
Top = currItem;
/* Get the cursor position right... */
if (itemCnt - 1 - currItem < y2 - y1)
{
if (currItem > y2 - y1)
{
curY = y2;
Top = currItem - (y2 - y1);
}
else
{
curY = currItem + y1;
Top = 0;
}
}
SelShowPage(Itms, y1, y2, len, Top, Norm, 1);
SelShowItem(Itms[currItem], curY, len, Sel, 1);
}
}
else if (Msg == '\b' && *find)
{
if (*topMsg && selbox_id == SELBOX_REPLYOTH)
{
*(find + strlen(find) - 1) = '\0';
WndCurr(hPrev);
WndClear(strlen(topMsg) + 3 + strlen(find), 0, maxx - 32, 0, cm[MN_NTXT]);
WndCurr(hWnd);
}
}
else
{
memset(find, '\0', sizeof find);
}
break;
}
break;
}
}
return -1;
}
#ifndef NODOMENU
int DoMenu(int x1, int y1, int x2, int y2, char **Itms, int def, int selbox_id, char *topMsg)
{
WND *hCurr, *hWnd;
int ret;
hCurr = WndTop();
hWnd = WndOpen(x1 - 1, y1 - 1, x2 + 3, y2 + 1, DBDR | SHADOW, cm[MN_BTXT], cm[MN_NTXT]);
if (!hWnd)
{
return -1;
}
if (selbox_id >= SELBOX_CHARSET)
{
WndTitle(topMsg, cm[MN_TTXT]);
}
ret = SelBox(Itms, 0, y2 - y1, x2 - x1 + 2, def, hCurr, hWnd, cm[MN_STXT], cm[MN_NTXT], selbox_id, topMsg);
WndClose(hWnd);
WndCurr(hCurr);
return ret;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1