|
|
1.1 root 1: /****************************************************************************
2:
3: PROGRAM: lqh.c
4:
5: MODULE: lqhmenu.c
6:
7: FUNCTIONS:
8: Reference() - reference functions
9: ListMenu() - display list of categories
10: Options() - prior screen, mouse speed, other data base, half screen
11: Search() - search options
12: AddBar() - adds bar around menu name
13: DeleteBar() - deletes bar around menu name
14: Input() - wait for keypress or mouse button
15:
16: COMMENTS:
17: This module contains the functions that handle the various menu
18: options.
19:
20: ****************************************************************************/
21:
22: #include "lqh.h"
23:
24: /****************************************************************************
25:
26: FUNCTION:
27: Reference()
28:
29: PURPOSE: Displays the names of any references from the current topic
30:
31: ****************************************************************************/
32:
33: VOID Reference() {
34: QHBOX qhbBox;
35: SEL selBoxSave;
36: BOOL fLoop = TRUE;
37: USHORT usMenuPos;
38:
39: qhbBox.top = 1;
40: qhbBox.bottom = 2 + ((usRefCount) ? usRefCount : 1);
41: qhbBox.left = 0;
42: qhbBox.right = 1 + MAXNAMESIZE;
43: qhbBox.BorderAtt = bMenuAtt;
44: qhbBox.FillAtt = bMenuAtt;
45: qhbBox.BoxType = THIN;
46:
47: if (!(selBoxSave = BoxSave(&qhbBox)))
48: return;
49: BoxDraw(&qhbBox);
50: AddBar(0, 11);
51: if (usRefCount) {
52: for (usMenuPos = 2; usMenuPos < qhbBox.bottom; usMenuPos++)
53: VioWrtCharStr(npszRefTable[usMenuPos - 2],
54: strlen(npszRefTable[usMenuPos - 2]),
55: usMenuPos, qhbBox.left + 2, 0);
56: }
57: else
58: VioWrtCharStr("No References", 13, usMenuPos = 2, qhbBox.left + 2, 0);
59: usMenuPos = 2;
60:
61: for(;;) {
62: if (!MenuLoop(&qhbBox, &usMenuPos, FALSE, 11))
63: break;
64: if (kbdciKeyInfo.chScan == 28) {
65: BoxRestore(&qhbBox, selBoxSave);
66: DeleteBar(0, 11);
67: if (usRefCount)
68: if (HelpSearch(npszRefTable[usMenuPos - 2], TRUE, 0L))
69: Display();
70: return;
71: }
72: }
73: BoxRestore(&qhbBox, selBoxSave);
74: DeleteBar(0, 11);
75: }
76:
77: /****************************************************************************
78:
79: FUNCTION:
80: Options()
81:
82: PURPOSE: Handles the Options menu
83:
84: ****************************************************************************/
85:
86: #define NOPTIONS 5
87:
88: VOID Options() {
89: SCALEFACT Scaling;
90: QHBOX qhbOptSize;
91: SEL selOptionBox, selTmpBoxSave;
92: BOOL fLoop = TRUE;
93: USHORT usMenuPos, usSize, i;
94: USHORT MouReadType = 1; /* Waits for mouse event */
95: CHAR chOldName[80];
96: BOOL fFound = FALSE;
97: CHAR chBuf[80];
98: BOOL fShown; /* TRUE means the topic is being shown */
99:
100: qhbOptSize.top = 1;
101: qhbOptSize.bottom = NOPTIONS + 2;
102: qhbOptSize.left = 32;
103: qhbOptSize.right = 32 + 15;
104: qhbOptSize.BorderAtt = bMenuAtt;
105: qhbOptSize.FillAtt = bMenuAtt;
106: qhbOptSize.BoxType = THIN;
107:
108: if (!(selOptionBox = BoxSave(&qhbOptSize)))
109: return;
110: BoxDraw(&qhbOptSize);
111: AddBar(32, 39);
112: VioWrtCharStr("Prior screen", 12, qhbOptSize.top + 1,
113: qhbOptSize.left + 2, 0);
114: VioWrtCharStr("New database", 12, qhbOptSize.top + 2,
115: qhbOptSize.left + 2, 0);
116: VioWrtCharStr("Screen size", 11, qhbOptSize.top + 3,
117: qhbOptSize.left + 2, 0);
118: VioWrtCharStr("Slower mouse", 12, qhbOptSize.top + 4,
119: qhbOptSize.left + 2, 0);
120: VioWrtCharStr("Faster mouse", 12, qhbOptSize.top + 5,
121: qhbOptSize.left + 2, 0);
122: usMenuPos = 2;
123: while (fLoop) {
124: if (!MenuLoop(&qhbOptSize, &usMenuPos, TRUE, 39))
125: break;
126: if (kbdciKeyInfo.chScan != 28)
127: continue;
128: switch(usMenuPos) {
129:
130: /* Restores the screen and allows the user to make a
131: * selection using the mouse, on the screen they had prior
132: * to calling LQH.
133: */
134:
135: case 2: /* Prior screen */
136: if (!hmou) {
137: BoxMessage(" Requires a mouse ",
138: atWARNING, THIN, hmou, TRUE);
139: break;
140: }
141:
142: BoxRestore(&qhbOptSize, selOptionBox);
143: qhbBox.top--;
144: if (!(selTmpBoxSave = BoxSave(&qhbBox))) {
145: BoxMessage(" Can not allocate enough memory. ",
146: atWARNING, THIN, hmou, TRUE);
147: qhbBox.top++;
148: DeleteBar(32, 39);
149: return;
150: }
151: BoxRestore(&qhbBox, selBoxSave);
152: selBoxSave = BoxSave(&qhbBox);
153: Input();
154:
155: /* If the mouse button was pressed, wait for its
156: * release.
157: */
158:
159: if (fMouButton)
160: MouseRelease();
161: fMouButton = FALSE;
162: VioSetCurPos(mouevEvent.row, mouevEvent.col, 0);
163: fFound = ReadScreen(TRUE);
164: BoxRestore(&qhbBox, selTmpBoxSave);
165: qhbBox.top++;
166: DeleteBar(32, 39);
167: if (fFound)
168: Display();
169: return;
170:
171: case 3: /* New database */
172: Dstrcpy(chOldName, chHelpName);
173: if (BoxGetString("Enter name for new data base:",
174: chHelpName, 80, atMENU, hmou)) {
175: if (!Init()) {
176: Dstrcpy(chHelpName, chOldName);
177: Init();
178: }
179:
180: while (!fShown) {
181: if (!BoxGetString(" Enter topic to find:",
182: chBuf, 25, atMENU, hmou))
183: DosExit(EXIT_PROCESS, 1);
184: fShown = HelpSearch((NPSZ) chBuf, TRUE, 0L);
185: }
186: }
187: fLoop = FALSE;
188: break;
189:
190: case 4: /* Change screen size */
191: if (BoxGetString(" Enter new size:",
192: chBuf, 4, atMENU, hmou)) {
193: for (i = 0; chBuf[i] != 0; i++)
194: if (chBuf[i] > '0' && chBuf[i] <= '9')
195: break;
196: if (chBuf[i + 1] < '0')
197: usSize = chBuf[i] - '0';
198: else
199: usSize = ((chBuf[i] - '0') * 10) +
200: chBuf[i + 1] - '0';
201: usSize--; /* zero-based counting */
202: if (usSize < 7)
203: usSize = 7;
204: if (usSize >= vmiMode.row)
205: usSize = vmiMode.row - 1;
206: qhbBox.top--;
207: BoxRestore(&qhbBox, selBoxSave);
208: qhbBox.bottom = usSize;
209: selBoxSave = BoxSave(&qhbBox);
210: qhbBox.top++;
211: usInterior = qhbBox.bottom - (BOXTOP + 2);
212: BoxDraw(&qhbBox);
213: BoxScroll(&qhbBox, 100, 20, atBOX);
214: VioWrtCellStr(chMenu, 160, BOXTOP - 1, BOXLEFT, 0);
215: VioSetCurType(&viociCursor, 0);
216: if (selTable[usCurrent].usHighLight > usInterior)
217: selTable[usCurrent].usHighLight =
218: usInterior + 1;
219: Display();
220: return;
221: }
222: break;
223:
224: case 5: /* Slower mouse */
225: MouGetScaleFact(&Scaling, hmou);
226: Scaling.rowScale *= 2;
227: Scaling.colScale *= 2;
228: MouSetScaleFact(&Scaling, hmou);
229: fLoop = FALSE;
230: break;
231:
232: case 6: /* Faster mouse */
233: MouGetScaleFact(&Scaling, hmou);
234: Scaling.rowScale /= 2;
235: Scaling.colScale /= 2;
236: MouSetScaleFact(&Scaling, hmou);
237: fLoop = FALSE;
238: break;
239:
240: }
241: break;
242: }
243: BoxRestore(&qhbOptSize, selOptionBox);
244: DeleteBar(32, 39);
245: return;
246: }
247:
248: /****************************************************************************
249:
250: FUNCTION:
251: ListMenu()
252:
253: PURPOSE: Handles the Categories menu
254:
255: ****************************************************************************/
256:
257: VOID ListMenu() {
258: QHBOX qhbBox;
259: SEL selBoxSave;
260: BOOL fLoop = TRUE;
261: USHORT usMenuPos;
262:
263: qhbBox.top = 1;
264: qhbBox.bottom = 2 + ((usListPos) ? usListPos : 1);
265: qhbBox.left = 12;
266: qhbBox.right = 12 + MAXCATNAME;
267: qhbBox.BorderAtt = bMenuAtt;
268: qhbBox.FillAtt = bMenuAtt;
269: qhbBox.BoxType = THIN;
270:
271: if (!(selBoxSave = BoxSave(&qhbBox)))
272: return;
273: BoxDraw(&qhbBox);
274: AddBar(12, 23);
275:
276: if (usListPos) {
277: for (usMenuPos = 2; usMenuPos < qhbBox.bottom; usMenuPos++)
278: VioWrtCharStr((PCH) lstList[usMenuPos - 2].name,
279: Dstrlen((PCH) lstList[usMenuPos - 2].name),
280: usMenuPos, qhbBox.left + 2, 0);
281: }
282: else
283: VioWrtCharStr("No Categories", 13, usMenuPos = 2, qhbBox.left + 2, 0);
284:
285: for(;;) {
286: if (!MenuLoop(&qhbBox, &usSaveMenuPos, TRUE, 23)) {
287: BoxRestore(&qhbBox, selBoxSave);
288: DeleteBar(12, 23);
289: return;
290: }
291: if (kbdciKeyInfo.chScan != 28)
292: continue;
293: BoxRestore(&qhbBox, selBoxSave);
294: DeleteBar(12, 23);
295: if (usListPos)
296: if (HelpSearch((NPSZ) lstList[usSaveMenuPos - 2].name,
297: TRUE, 0L))
298: Display();
299: return;
300: }
301: }
302:
303: /****************************************************************************
304:
305: FUNCTION:
306: Search()
307:
308: PURPOSE: Handles the Search menu
309:
310: ****************************************************************************/
311:
312: #define NSEARCHES 3
313:
314: VOID Search() {
315: QHBOX qhbBox;
316: SEL selBoxSave;
317: BOOL fLoop = TRUE;
318: USHORT usMenuPos;
319: CHAR chBuf[80];
320:
321: qhbBox.top = 1;
322: qhbBox.bottom = NSEARCHES + 2;
323: qhbBox.left = 24;
324: qhbBox.right = 24 + 16;
325: qhbBox.BorderAtt = bMenuAtt;
326: qhbBox.FillAtt = bMenuAtt;
327: qhbBox.BoxType = THIN;
328:
329: if (!(selBoxSave = BoxSave(&qhbBox)))
330: return;
331: BoxDraw(&qhbBox);
332: AddBar(24, 31);
333: VioWrtCharStr("Search... S", 13, qhbBox.top + 1,
334: qhbBox.left + 2, 0);
335: VioWrtCharStr( "History I", 13, qhbBox.top + 2,
336: qhbBox.left + 2, 0);
337: VioWrtCharStr( "Next... N", 13, qhbBox.top + 3,
338: qhbBox.left + 2, 0);
339: usMenuPos = 2;
340: while (fLoop) {
341: if (!MenuLoop(&qhbBox, &usMenuPos, TRUE, 31))
342: break;
343: switch(kbdciKeyInfo.chScan) {
344: case 31: /* 's' */
345: kbdciKeyInfo.chScan = 28;
346: VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
347: usMenuPos, qhbBox.left + 1, 0);
348: usMenuPos = 2;
349: VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
350: usMenuPos, qhbBox.left + 1, 0);
351: break;
352:
353: case 23: /* 'i' */
354: kbdciKeyInfo.chScan = 28;
355: VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
356: usMenuPos, qhbBox.left + 1, 0);
357: usMenuPos = 3;
358: VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
359: usMenuPos, qhbBox.left + 1, 0);
360: break;
361:
362: case 49: /* 'n' */
363: kbdciKeyInfo.chScan = 28;
364: VioWrtNAttr(&bMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
365: usMenuPos, qhbBox.left + 1, 0);
366: usMenuPos = 4;
367: VioWrtNAttr(&bHiMenuAtt, (qhbBox.right) - (qhbBox.left + 1),
368: usMenuPos, qhbBox.left + 1, 0);
369: break;
370:
371: }
372: if (kbdciKeyInfo.chScan == 28)
373: switch(usMenuPos) {
374: case 2: /* Find */
375: if (BoxGetString(" Enter topic to find:",
376: chBuf, 25, atMENU, hmou))
377: if (HelpSearch((NPSZ) chBuf, TRUE, 0L)) {
378: BoxRestore(&qhbBox, selBoxSave);
379: DeleteBar(24, 31);
380: usBottomLine = usInterior +
381: selTable[usCurrent].usTopLine;
382: if (usBottomLine > usTotalLines)
383: usBottomLine = usTotalLines;
384: Display();
385: return;
386: }
387: break;
388:
389: case 3: /* Back */
390: fBack = TRUE;
391: if (HelpSearch("", FALSE, HelpNcBack())) {
392: BoxRestore(&qhbBox, selBoxSave);
393: DeleteBar(24, 31);
394: Display();
395: return;
396: }
397: else
398: BoxMessage(" No prior screen displayed ",
399: bMenuAtt, THIN, hmou, TRUE);
400: break;
401:
402: case 4: /* Next */
403: if (HelpSearch("", FALSE,
404: HelpNcNext(selTable[usCurrent].ncContext))) {
405: BoxRestore(&qhbBox, selBoxSave);
406: DeleteBar(24, 31);
407: Display();
408: return;
409: }
410: else
411: BoxMessage(" You are at the end of the database ",
412: bMenuAtt, THIN, hmou, TRUE);
413: break;
414: }
415: }
416: BoxRestore(&qhbBox, selBoxSave);
417: DeleteBar(24, 31);
418: return;
419: }
420:
421: /****************************************************************************
422:
423: FUNCTION: AddBar();
424:
425: PURPOSE: Adds vertical bars on both sides of the menu name.
426:
427: ****************************************************************************/
428:
429: VOID AddBar(usLeft, usRight)
430: USHORT usLeft, usRight;
431: {
432: CHAR chCell[2];
433: chCell[1] = bMenuAtt;
434: chCell[0] = (CHAR) 179; /* side scroll character */
435: VioWrtNCell(chCell, /* address of the cell */
436: 1, /* number of times to write the cell */
437: 0, /* starting row */
438: usLeft, /* starting column */
439: 0); /* Vio handle */
440: VioWrtNCell(chCell, 1, 0, usRight, 0);
441: chCell[0] = (CHAR) 195;
442: VioWrtNCell(chCell, 1, 1, usLeft, 0);
443: chCell[0] = (CHAR) 193;
444: VioWrtNCell(chCell, 1, 1, usRight, 0);
445: }
446:
447: /****************************************************************************
448:
449: FUNCTION: DeleteBar();
450:
451: PURPOSE: Deletes vertical bars on both sides of the menu name.
452:
453: ****************************************************************************/
454:
455: VOID DeleteBar(usLeft, usRight)
456: USHORT usLeft, usRight;
457: {
458: CHAR chCell[2];
459: chCell[1] = bMenuAtt;
460: chCell[0] = 32; /* space */
461: VioWrtNCell(chCell, 1, 0, usRight, 0);
462: VioWrtNCell(chCell, 1, 0, usLeft, 0);
463: MouFlushQue(hmou); /* Gets rid of additional mouse input */
464: }
465:
466: /****************************************************************************
467:
468: FUNCTION: Input();
469:
470: PURPOSE: Wait until there is input from either the keyboard or the mouse
471:
472: COMMENTS:
473: The mouse sets the attribute on the screen when it is drawn. In
474: order to prevent the attribute from being scrolled, the mouse
475: pointer is only displayed while waiting for input.
476:
477: ****************************************************************************/
478:
479: VOID Input() {
480:
481: /* If the user presses a horizontal cursor key while displaying a menu,
482: * the sDirection variable is set to indicate which direction the cursor
483: * is to move. This variable is checked, and if it is non-zero, the scan
484: * code for the next menu is taken from a table, and the function returns
485: * as if the user had pressed the first letter of the menu.
486: */
487:
488: if (sDirection) {
489: sMenuTablePos += sDirection;
490: sDirection = 0;
491: if (sMenuTablePos < 0)
492: sMenuTablePos = 3;
493: else if (sMenuTablePos > 3)
494: sMenuTablePos = 0;
495: kbdciKeyInfo.chScan = chMenuTable[sMenuTablePos];
496: return;
497: }
498:
499: /* Check to see if a key is waiting, and if so, return immediately. */
500:
501: KbdCharIn(&kbdciKeyInfo, /* buffer for data */
502: 1, /* Doesn't't wait */
503: 0); /* keyboard handle */
504: if (kbdciKeyInfo.fbStatus)
505: return;
506:
507: /* While waiting for input, let the the PreLoad thread run. The PreLoad
508: * thread preloads the file specified in the Reference list
509: */
510:
511: DosResumeThread(tidPreLoad);
512: MouFlushQue(hmou); /* Flushes the mouse queue */
513: MouDrawPtr(hmou); /* Displays the mouse */
514: do {
515: KbdCharIn(&kbdciKeyInfo, 1, 0);
516: MouReadEventQue(&mouevEvent, &MouReadType, hmou);
517: if (mouevEvent.fs & 0x06) { /* left button */
518: fMouButton = TRUE;
519: }
520:
521: /* If the right button is pressed, then the key scan code is set as
522: * if the B key was pressed on the keyboard.
523: */
524:
525: else if (mouevEvent.fs & 0x18) { /* right button */
526: kbdciKeyInfo.chScan = 48; /* 'b' */
527: kbdciKeyInfo.fbStatus = TRUE;
528: }
529: }
530: while (!kbdciKeyInfo.fbStatus && !fMouButton);
531:
532: /* Now that input has been received, suspend the PreLoad thread so that
533: * the response to the input will be as rapid as possible.
534: */
535:
536: DosSuspendThread(tidPreLoad);
537: MouRemovePtr(&mourtRect, hmou); /* Hides the mouse */
538: }
539:
540: /****************************************************************************
541:
542: FUNCTION:
543: MenuLoop()
544:
545: PURPOSE: Handles the mouse and keyboard interface for the menus
546:
547: ****************************************************************************/
548:
549: BOOL MenuLoop(qhbBox, npMenuPos, fAccelerate, usRight)
550: QHBOX *qhbBox;
551: USHORT *npMenuPos;
552: BOOL fAccelerate;
553: USHORT usRight; /* right side of menu name */
554: {
555: int i;
556: PTRLOC plMouPos;
557: BOOL fUpButton = FALSE;
558: USHORT usMouNoWait = 0; /* don't wait for mouse event */
559:
560: for(;;) {
561: VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
562: *npMenuPos, qhbBox->left + 1, 0);
563:
564: InputLoop:
565: MouDrawPtr(hmou); /* display the mouse */
566: for(;;) {
567: KbdCharIn(&kbdciKeyInfo, IO_NOWAIT, 0);
568: if (kbdciKeyInfo.fbStatus) {
569: fUpButton = fMouButton = FALSE;
570: break;
571: }
572: MouReadEventQue(&mouevEvent, &usMouNoWait, hmou);
573: if (mouevEvent.Time) {
574: if (mouevEvent.fs == 0 || (mouevEvent.fs == 1 && fMouButton)) {
575: fUpButton = TRUE;
576: fMouButton = FALSE;
577: break;
578: }
579: else if (mouevEvent.fs > 1) {
580: fMouButton = TRUE;
581: fUpButton = FALSE;
582: break;
583: }
584: }
585: }
586: MouRemovePtr(&mourtRect, hmou); /* hide the mouse */
587:
588: if (fUpButton) {
589: fMouButton = FALSE;
590: if (mouevEvent.col >= qhbBox->right ||
591: mouevEvent.col <= qhbBox->left ||
592: mouevEvent.row >= qhbBox->bottom ||
593: (mouevEvent.row == 0 && mouevEvent.col > usRight)) {
594: kbdciKeyInfo.chScan = 1; /* ESCAPE */
595: }
596: else if (mouevEvent.row <= BOXTOP)
597: goto InputLoop;
598: else {
599: kbdciKeyInfo.chScan = 28;
600: *npMenuPos = mouevEvent.row;
601: }
602: }
603: else if (fMouButton) {
604: if (mouevEvent.row == 0) {
605: if (mouevEvent.col > usRight || mouevEvent.col < qhbBox->left) {
606: fMouButton = FALSE;
607: return FALSE;
608: }
609: else
610: goto InputLoop;
611: }
612:
613: if (mouevEvent.row > qhbBox->top &&
614: mouevEvent.row < qhbBox->bottom &&
615: mouevEvent.col > qhbBox->left &&
616: mouevEvent.col < qhbBox->right) {
617: VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
618: *npMenuPos, qhbBox->left + 1, 0);
619: *npMenuPos = mouevEvent.row;
620: VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
621: *npMenuPos, qhbBox->left + 1, 0);
622: }
623: goto InputLoop;
624: }
625:
626: switch(kbdciKeyInfo.chScan) {
627: case 1: /* ESCAPE */
628: return FALSE;
629:
630: case 28:
631: return TRUE;
632:
633: case 80: /* cursor down */
634: VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
635: *npMenuPos, qhbBox->left + 1, 0);
636: *npMenuPos = (*npMenuPos > (qhbBox->bottom - 2)) ?
637: qhbBox->top + 1 : *npMenuPos + 1;
638: VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
639: *npMenuPos, qhbBox->left + 1, 0);
640: continue;
641:
642: case 72: /* cursor up */
643: VioWrtNAttr(&bMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
644: *npMenuPos, qhbBox->left + 1, 0);
645: *npMenuPos = (*npMenuPos < (qhbBox->top + 2)) ?
646: qhbBox->bottom - 1 : *npMenuPos - 1;
647: VioWrtNAttr(&bHiMenuAtt, (qhbBox->right) - (qhbBox->left + 1),
648: *npMenuPos, qhbBox->left + 1, 0);
649: continue;
650:
651: case 77:
652: sDirection = 1;
653: return FALSE;
654:
655: case 75:
656: sDirection = -1;
657: return FALSE;
658: }
659: return TRUE;
660: }
661: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.