|
|
Microsoft OS/2 SDK 03-01-1988
/****************************************************************************
PROGRAM: lqh.c
MODULE: lqhmenu.c
FUNCTIONS:
Reference() - reference functions
ListMenu() - display list of categories
Options() - prior screen, mouse speed, other data base, half screen
Search() - search options
AddBar() - adds bar around menu name
DeleteBar() - deletes bar around menu name
Input() - wait for keypress or mouse button
COMMENTS:
This module contains the functions that handle the various menu
options.
****************************************************************************/
#include "lqh.h"
/****************************************************************************
FUNCTION:
Reference()
PURPOSE: Displays the names of any references from the current topic
****************************************************************************/
VOID Reference() {
QHBOX qhbBox;
SEL selBoxSave;
BOOL fLoop = TRUE;
USHORT usMenuPos;
qhbBox.top = 1;
qhbBox.bottom = 2 + ((usRefCount) ? usRefCount : 1);
qhbBox.left = 0;
qhbBox.right = 1 + MAXNAMESIZE;
qhbBox.BorderAtt = bMenuAtt;
qhbBox.FillAtt = bMenuAtt;
qhbBox.BoxType = THIN;
if (!(selBoxSave = BoxSave(&qhbBox)))
return;
BoxDraw(&qhbBox);
AddBar(0, 11);
if (usRefCount) {
for (usMenuPos = 2; usMenuPos < qhbBox.bottom; usMenuPos++)
VioWrtCharStr(npszRefTable[usMenuPos - 2],
strlen(npszRefTable[usMenuPos - 2]),
usMenuPos, qhbBox.left + 2, 0);
}
else
VioWrtCharStr("No References", 13, usMenuPos = 2, qhbBox.left + 2, 0);
usMenuPos = 2;
for(;;) {
if (!MenuLoop(&qhbBox, &usMenuPos, FALSE, 11))
break;
if (kbdciKeyInfo.chScan == 28) {
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(0, 11);
if (usRefCount)
if (HelpSearch(npszRefTable[usMenuPos - 2], TRUE, 0L))
Display();
return;
}
}
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(0, 11);
}
/****************************************************************************
FUNCTION:
Options()
PURPOSE: Handles the Options menu
****************************************************************************/
#define NOPTIONS 5
VOID Options() {
SCALEFACT Scaling;
QHBOX qhbOptSize;
SEL selOptionBox, selTmpBoxSave;
BOOL fLoop = TRUE;
USHORT usMenuPos, usSize, i;
USHORT MouReadType = 1; /* Waits for mouse event */
CHAR chOldName[80];
BOOL fFound = FALSE;
CHAR chBuf[80];
BOOL fShown; /* TRUE means the topic is being shown */
qhbOptSize.top = 1;
qhbOptSize.bottom = NOPTIONS + 2;
qhbOptSize.left = 32;
qhbOptSize.right = 32 + 15;
qhbOptSize.BorderAtt = bMenuAtt;
qhbOptSize.FillAtt = bMenuAtt;
qhbOptSize.BoxType = THIN;
if (!(selOptionBox = BoxSave(&qhbOptSize)))
return;
BoxDraw(&qhbOptSize);
AddBar(32, 39);
VioWrtCharStr("Prior screen", 12, qhbOptSize.top + 1,
qhbOptSize.left + 2, 0);
VioWrtCharStr("New database", 12, qhbOptSize.top + 2,
qhbOptSize.left + 2, 0);
VioWrtCharStr("Screen size", 11, qhbOptSize.top + 3,
qhbOptSize.left + 2, 0);
VioWrtCharStr("Slower mouse", 12, qhbOptSize.top + 4,
qhbOptSize.left + 2, 0);
VioWrtCharStr("Faster mouse", 12, qhbOptSize.top + 5,
qhbOptSize.left + 2, 0);
usMenuPos = 2;
while (fLoop) {
if (!MenuLoop(&qhbOptSize, &usMenuPos, TRUE, 39))
break;
if (kbdciKeyInfo.chScan != 28)
continue;
switch(usMenuPos) {
/* Restores the screen and allows the user to make a
* selection using the mouse, on the screen they had prior
* to calling LQH.
*/
case 2: /* Prior screen */
if (!hmou) {
BoxMessage(" Requires a mouse ",
atWARNING, THIN, hmou, TRUE);
break;
}
BoxRestore(&qhbOptSize, selOptionBox);
qhbBox.top--;
if (!(selTmpBoxSave = BoxSave(&qhbBox))) {
BoxMessage(" Can not allocate enough memory. ",
atWARNING, THIN, hmou, TRUE);
qhbBox.top++;
DeleteBar(32, 39);
return;
}
BoxRestore(&qhbBox, selBoxSave);
selBoxSave = BoxSave(&qhbBox);
Input();
/* If the mouse button was pressed, wait for its
* release.
*/
if (fMouButton)
MouseRelease();
fMouButton = FALSE;
VioSetCurPos(mouevEvent.row, mouevEvent.col, 0);
fFound = ReadScreen(TRUE);
BoxRestore(&qhbBox, selTmpBoxSave);
qhbBox.top++;
DeleteBar(32, 39);
if (fFound)
Display();
return;
case 3: /* New database */
Dstrcpy(chOldName, chHelpName);
if (BoxGetString("Enter name for new data base:",
chHelpName, 80, atMENU, hmou)) {
if (!Init()) {
Dstrcpy(chHelpName, chOldName);
Init();
}
while (!fShown) {
if (!BoxGetString(" Enter topic to find:",
chBuf, 25, atMENU, hmou))
DosExit(EXIT_PROCESS, 1);
fShown = HelpSearch((NPSZ) chBuf, TRUE, 0L);
}
}
fLoop = FALSE;
break;
case 4: /* Change screen size */
if (BoxGetString(" Enter new size:",
chBuf, 4, atMENU, hmou)) {
for (i = 0; chBuf[i] != 0; i++)
if (chBuf[i] > '0' && chBuf[i] <= '9')
break;
if (chBuf[i + 1] < '0')
usSize = chBuf[i] - '0';
else
usSize = ((chBuf[i] - '0') * 10) +
chBuf[i + 1] - '0';
usSize--; /* zero-based counting */
if (usSize < 7)
usSize = 7;
if (usSize >= vmiMode.row)
usSize = vmiMode.row - 1;
qhbBox.top--;
BoxRestore(&qhbBox, selBoxSave);
qhbBox.bottom = usSize;
selBoxSave = BoxSave(&qhbBox);
qhbBox.top++;
usInterior = qhbBox.bottom - (BOXTOP + 2);
BoxDraw(&qhbBox);
BoxScroll(&qhbBox, 100, 20, atBOX);
VioWrtCellStr(chMenu, 160, BOXTOP - 1, BOXLEFT, 0);
VioSetCurType(&viociCursor, 0);
if (selTable[usCurrent].usHighLight > usInterior)
selTable[usCurrent].usHighLight =
usInterior + 1;
Display();
return;
}
break;
case 5: /* Slower mouse */
MouGetScaleFact(&Scaling, hmou);
Scaling.rowScale *= 2;
Scaling.colScale *= 2;
MouSetScaleFact(&Scaling, hmou);
fLoop = FALSE;
break;
case 6: /* Faster mouse */
MouGetScaleFact(&Scaling, hmou);
Scaling.rowScale /= 2;
Scaling.colScale /= 2;
MouSetScaleFact(&Scaling, hmou);
fLoop = FALSE;
break;
}
break;
}
BoxRestore(&qhbOptSize, selOptionBox);
DeleteBar(32, 39);
return;
}
/****************************************************************************
FUNCTION:
ListMenu()
PURPOSE: Handles the Categories menu
****************************************************************************/
VOID ListMenu() {
QHBOX qhbBox;
SEL selBoxSave;
BOOL fLoop = TRUE;
USHORT usMenuPos;
qhbBox.top = 1;
qhbBox.bottom = 2 + ((usListPos) ? usListPos : 1);
qhbBox.left = 12;
qhbBox.right = 12 + MAXCATNAME;
qhbBox.BorderAtt = bMenuAtt;
qhbBox.FillAtt = bMenuAtt;
qhbBox.BoxType = THIN;
if (!(selBoxSave = BoxSave(&qhbBox)))
return;
BoxDraw(&qhbBox);
AddBar(12, 23);
if (usListPos) {
for (usMenuPos = 2; usMenuPos < qhbBox.bottom; usMenuPos++)
VioWrtCharStr((PCH) lstList[usMenuPos - 2].name,
Dstrlen((PCH) lstList[usMenuPos - 2].name),
usMenuPos, qhbBox.left + 2, 0);
}
else
VioWrtCharStr("No Categories", 13, usMenuPos = 2, qhbBox.left + 2, 0);
for(;;) {
if (!MenuLoop(&qhbBox, &usSaveMenuPos, TRUE, 23)) {
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(12, 23);
return;
}
if (kbdciKeyInfo.chScan != 28)
continue;
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(12, 23);
if (usListPos)
if (HelpSearch((NPSZ) lstList[usSaveMenuPos - 2].name,
TRUE, 0L))
Display();
return;
}
}
/****************************************************************************
FUNCTION:
Search()
PURPOSE: Handles the Search menu
****************************************************************************/
#define NSEARCHES 3
VOID Search() {
QHBOX qhbBox;
SEL selBoxSave;
BOOL fLoop = TRUE;
USHORT usMenuPos;
CHAR chBuf[80];
qhbBox.top = 1;
qhbBox.bottom = NSEARCHES + 2;
qhbBox.left = 24;
qhbBox.right = 24 + 16;
qhbBox.BorderAtt = bMenuAtt;
qhbBox.FillAtt = bMenuAtt;
qhbBox.BoxType = THIN;
if (!(selBoxSave = BoxSave(&qhbBox)))
return;
BoxDraw(&qhbBox);
AddBar(24, 31);
VioWrtCharStr("Search... S", 13, qhbBox.top + 1,
qhbBox.left + 2, 0);
VioWrtCharStr( "History I", 13, qhbBox.top + 2,
qhbBox.left + 2, 0);
VioWrtCharStr( "Next... N", 13, qhbBox.top + 3,
qhbBox.left + 2, 0);
usMenuPos = 2;
while (fLoop) {
if (!MenuLoop(&qhbBox, &usMenuPos, TRUE, 31))
break;
switch(kbdciKeyInfo.chScan) {
case 31: /* 's' */
kbdciKeyInfo.chScan = 28;
VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
usMenuPos = 2;
VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
break;
case 23: /* 'i' */
kbdciKeyInfo.chScan = 28;
VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
usMenuPos = 3;
VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
break;
case 49: /* 'n' */
kbdciKeyInfo.chScan = 28;
VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
usMenuPos = 4;
VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
usMenuPos, qhbBox.left + 1, 0);
break;
}
if (kbdciKeyInfo.chScan == 28)
switch(usMenuPos) {
case 2: /* Find */
if (BoxGetString(" Enter topic to find:",
chBuf, 25, atMENU, hmou))
if (HelpSearch((NPSZ) chBuf, TRUE, 0L)) {
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(24, 31);
usBottomLine = usInterior +
selTable[usCurrent].usTopLine;
if (usBottomLine > usTotalLines)
usBottomLine = usTotalLines;
Display();
return;
}
break;
case 3: /* Back */
fBack = TRUE;
if (HelpSearch("", FALSE, HelpNcBack())) {
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(24, 31);
Display();
return;
}
else
BoxMessage(" No prior screen displayed ",
bMenuAtt, THIN, hmou, TRUE);
break;
case 4: /* Next */
if (HelpSearch("", FALSE,
HelpNcNext(selTable[usCurrent].ncContext))) {
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(24, 31);
Display();
return;
}
else
BoxMessage(" You are at the end of the database ",
bMenuAtt, THIN, hmou, TRUE);
break;
}
}
BoxRestore(&qhbBox, selBoxSave);
DeleteBar(24, 31);
return;
}
/****************************************************************************
FUNCTION: AddBar();
PURPOSE: Adds vertical bars on both sides of the menu name.
****************************************************************************/
VOID AddBar(usLeft, usRight)
USHORT usLeft, usRight;
{
CHAR chCell[2];
chCell[1] = bMenuAtt;
chCell[0] = (CHAR) 179; /* side scroll character */
VioWrtNCell(chCell, /* address of the cell */
1, /* number of times to write the cell */
0, /* starting row */
usLeft, /* starting column */
0); /* Vio handle */
VioWrtNCell(chCell, 1, 0, usRight, 0);
chCell[0] = (CHAR) 195;
VioWrtNCell(chCell, 1, 1, usLeft, 0);
chCell[0] = (CHAR) 193;
VioWrtNCell(chCell, 1, 1, usRight, 0);
}
/****************************************************************************
FUNCTION: DeleteBar();
PURPOSE: Deletes vertical bars on both sides of the menu name.
****************************************************************************/
VOID DeleteBar(usLeft, usRight)
USHORT usLeft, usRight;
{
CHAR chCell[2];
chCell[1] = bMenuAtt;
chCell[0] = 32; /* space */
VioWrtNCell(chCell, 1, 0, usRight, 0);
VioWrtNCell(chCell, 1, 0, usLeft, 0);
MouFlushQue(hmou); /* Gets rid of additional mouse input */
}
/****************************************************************************
FUNCTION: Input();
PURPOSE: Wait until there is input from either the keyboard or the mouse
COMMENTS:
The mouse sets the attribute on the screen when it is drawn. In
order to prevent the attribute from being scrolled, the mouse
pointer is only displayed while waiting for input.
****************************************************************************/
VOID Input() {
/* If the user presses a horizontal cursor key while displaying a menu,
* the sDirection variable is set to indicate which direction the cursor
* is to move. This variable is checked, and if it is non-zero, the scan
* code for the next menu is taken from a table, and the function returns
* as if the user had pressed the first letter of the menu.
*/
if (sDirection) {
sMenuTablePos += sDirection;
sDirection = 0;
if (sMenuTablePos < 0)
sMenuTablePos = 3;
else if (sMenuTablePos > 3)
sMenuTablePos = 0;
kbdciKeyInfo.chScan = chMenuTable[sMenuTablePos];
return;
}
/* Check to see if a key is waiting, and if so, return immediately. */
KbdCharIn(&kbdciKeyInfo, /* buffer for data */
1, /* Doesn't't wait */
0); /* keyboard handle */
if (kbdciKeyInfo.fbStatus)
return;
/* While waiting for input, let the the PreLoad thread run. The PreLoad
* thread preloads the file specified in the Reference list
*/
DosResumeThread(tidPreLoad);
MouFlushQue(hmou); /* Flushes the mouse queue */
MouDrawPtr(hmou); /* Displays the mouse */
do {
KbdCharIn(&kbdciKeyInfo, 1, 0);
MouReadEventQue(&mouevEvent, &MouReadType, hmou);
if (mouevEvent.fs & 0x06) { /* left button */
fMouButton = TRUE;
}
/* If the right button is pressed, then the key scan code is set as
* if the B key was pressed on the keyboard.
*/
else if (mouevEvent.fs & 0x18) { /* right button */
kbdciKeyInfo.chScan = 48; /* 'b' */
kbdciKeyInfo.fbStatus = TRUE;
}
}
while (!kbdciKeyInfo.fbStatus && !fMouButton);
/* Now that input has been received, suspend the PreLoad thread so that
* the response to the input will be as rapid as possible.
*/
DosSuspendThread(tidPreLoad);
MouRemovePtr(&mourtRect, hmou); /* Hides the mouse */
}
/****************************************************************************
FUNCTION:
MenuLoop()
PURPOSE: Handles the mouse and keyboard interface for the menus
****************************************************************************/
BOOL MenuLoop(qhbBox, npMenuPos, fAccelerate, usRight)
QHBOX *qhbBox;
USHORT *npMenuPos;
BOOL fAccelerate;
USHORT usRight; /* right side of menu name */
{
int i;
PTRLOC plMouPos;
BOOL fUpButton = FALSE;
USHORT usMouNoWait = 0; /* don't wait for mouse event */
for(;;) {
VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
InputLoop:
MouDrawPtr(hmou); /* display the mouse */
for(;;) {
KbdCharIn(&kbdciKeyInfo, IO_NOWAIT, 0);
if (kbdciKeyInfo.fbStatus) {
fUpButton = fMouButton = FALSE;
break;
}
MouReadEventQue(&mouevEvent, &usMouNoWait, hmou);
if (mouevEvent.Time) {
if (mouevEvent.fs == 0 || (mouevEvent.fs == 1 && fMouButton)) {
fUpButton = TRUE;
fMouButton = FALSE;
break;
}
else if (mouevEvent.fs > 1) {
fMouButton = TRUE;
fUpButton = FALSE;
break;
}
}
}
MouRemovePtr(&mourtRect, hmou); /* hide the mouse */
if (fUpButton) {
fMouButton = FALSE;
if (mouevEvent.col >= qhbBox->right ||
mouevEvent.col <= qhbBox->left ||
mouevEvent.row >= qhbBox->bottom ||
(mouevEvent.row == 0 && mouevEvent.col > usRight)) {
kbdciKeyInfo.chScan = 1; /* ESCAPE */
}
else if (mouevEvent.row <= BOXTOP)
goto InputLoop;
else {
kbdciKeyInfo.chScan = 28;
*npMenuPos = mouevEvent.row;
}
}
else if (fMouButton) {
if (mouevEvent.row == 0) {
if (mouevEvent.col > usRight || mouevEvent.col < qhbBox->left) {
fMouButton = FALSE;
return FALSE;
}
else
goto InputLoop;
}
if (mouevEvent.row > qhbBox->top &&
mouevEvent.row < qhbBox->bottom &&
mouevEvent.col > qhbBox->left &&
mouevEvent.col < qhbBox->right) {
VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
*npMenuPos = mouevEvent.row;
VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
}
goto InputLoop;
}
switch(kbdciKeyInfo.chScan) {
case 1: /* ESCAPE */
return FALSE;
case 28:
return TRUE;
case 80: /* cursor down */
VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
*npMenuPos = (*npMenuPos > (qhbBox->bottom - 2)) ?
qhbBox->top + 1 : *npMenuPos + 1;
VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
continue;
case 72: /* cursor up */
VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
*npMenuPos = (*npMenuPos < (qhbBox->top + 2)) ?
qhbBox->bottom - 1 : *npMenuPos - 1;
VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
*npMenuPos, qhbBox->left + 1, 0);
continue;
case 77:
sDirection = 1;
return FALSE;
case 75:
sDirection = -1;
return FALSE;
}
return TRUE;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.