|
|
1.1 root 1: /****************************************************************************
2:
3: PROGRAM: lqh.c
4:
5: MODULE: lqhmain.c
6:
7: PURPOSE: Displays on-line information
8:
9: FUNCTIONS:
10: main()
11: ReadScreen() Checks if cursor is over a function name
12: ScrollDown() Scroll screen down
13: ScrollUp() Scroll screen up
14: Abort() Called upon program termination
15: MouseRelease() Waits until mouse button is released
16: isalpha() Returns TRUE if character is alphabetic
17:
18:
19: COMMENTS:
20: This program provides a subset of the capabilities of the Microsoft
21: QuickHelp program. It is provided as an example application using
22: MS OS/2.
23:
24: ****************************************************************************/
25:
26: #include "lqh.h"
27:
28: CHAR chMenu[] = { /* Top menu defined as character-attribute string */
29: ' ', atMENU,
30: 'R', atLEAD, /* #1 */
31: 'e', atMENU,
32: 'f', atMENU,
33: 'e', atMENU,
34: 'r', atMENU,
35: 'e', atMENU,
36: 'n', atMENU,
37: 'c', atMENU,
38: 'e', atMENU,
39: 's', atMENU,
40: ' ', atMENU,
41: ' ', atMENU,
42: 'C', atLEAD, /* #13 */
43: 'a', atMENU,
44: 't', atMENU,
45: 'e', atMENU,
46: 'g', atMENU,
47: 'o', atMENU,
48: 'r', atMENU,
49: 'i', atMENU,
50: 'e', atMENU,
51: 's', atMENU,
52: ' ', atMENU,
53: ' ', atMENU,
54: 'V', atLEAD, /* #25 */
55: 'i', atMENU,
56: 'e', atMENU,
57: 'w', atMENU,
58: ' ', atMENU,
59: ' ', atMENU,
60: ' ', atMENU,
61: ' ', atMENU,
62: 'O', atLEAD, /* #33 */
63: 'p', atMENU,
64: 't', atMENU,
65: 'i', atMENU,
66: 'o', atMENU,
67: 'n', atMENU,
68: 's', atMENU,
69: ' ', atMENU,
70: ' ', atMENU,
71: ' ', atMENU,
72: ' ', atMENU,
73: ' ', atMENU,
74: ' ', atMENU,
75: ' ', atMENU,
76: ' ', atMENU,
77: ' ', atMENU,
78: ' ', atMENU,
79: ' ', atMENU,
80: ' ', atMENU,
81: ' ', atMENU,
82: ' ', atMENU,
83: ' ', atMENU,
84: ' ', atMENU,
85: ' ', atMENU,
86: ' ', atMENU,
87: ' ', atMENU,
88: ' ', atMENU,
89: ' ', atMENU,
90: ' ', atMENU,
91: ' ', atMENU,
92: ' ', atMENU,
93: ' ', atMENU,
94: ' ', atMENU,
95: ' ', atMENU,
96: ' ', atMENU,
97: ' ', atMENU,
98: ' ', atMENU,
99: 0xB3, atMENU,
100: ' ', atMENU,
101: 'F', atMENU,
102: '1', atMENU,
103: '=', atMENU,
104: 'H', atLEAD,
105: 'e', atMENU,
106: 'l', atMENU,
107: 'p', atMENU,
108: ' ', atMENU,
109: };
110:
111: VIOCURSORINFO viociCursor; /* cursor data */
112: KBDKEYINFO kbdciKeyInfo; /* structure for key data */
113: QHBOX qhbBox; /* box dimensions */
114:
115: CHAR achBlank[2]; /* used to clear the screen */
116: BYTE bHoldString[160]; /* Holds string prior to highlighting */
117: USHORT cbHoldLength = ((BOXRIGHT - 1) - (BOXLEFT + 1)) * 2;
118:
119: CHAR chReference[MAXLIST * MAXNAMESIZE]; /* Stores reference names */
120: NPSZ npszRefTable[MAXLIST]; /* table of reference functions */
121: STRTABLE strTable[2000]; /* Maintains address of each line */
122: USHORT usRefCount; /* number of reference functions */
123: LIST lstList[MAXLIST]; /* list of category names */
124: USHORT usListPos; /* position in tables */
125: USHORT usCurListPos; /* position in tables */
126:
127: USHORT hmou; /* handle to the mouse */
128: MOUEVENTINFO mouevEvent; /* mouse event packet structure */
129: NOPTRRECT mourtRect; /* structure for hiding the mouse */
130: BOOL fMouButton = FALSE; /* TRUE if button it clicked */
131: USHORT MouReadType = 0; /* don't wait for mouse event */
132:
133: BYTE bNormalAtt = atNORMAL; /* default attributes */
134: BYTE bHiAtt = atHILITE;
135: BYTE bBoldAtt = atBOLD;
136: BYTE bItalicAtt = atITALIC;
137: BYTE bMenuAtt = atMENU;
138: BYTE bHiMenuAtt = atNORMAL;
139:
140: SEL selBoxSave; /* selector to memory for screen save */
141: SEL selStringTable; /* selector for char-attribute strings */
142:
143: USHORT usBottomLine; /* current bottom-line number */
144: USHORT usInterior; /* maximum number of displayed lines */
145: USHORT usTotalLines; /* total number of lines */
146: USHORT usStructLine; /* starting line of structure section */
147: BOOL fListDisplay; /* TRUE if function list is being displayed */
148: BOOL fBack = FALSE; /* TRUE if HelpNcBack() was called */
149: USHORT usSaveMenuPos = 2; /* current List menu position */
150:
151: /* The selTable contains a list of preloaded topics. Whenever a request is
152: * made for a topic, this table is checked to see if the topic is in memory.
153: */
154:
155: SELTABLE selTable[MAXPRELOAD]; /* table of preloaded topics */
156: USHORT usCurrent = 0; /* current index in selTable */
157:
158: ULONG FAR hsemNewRef = 0; /* RAM semaphore used by PreLoad() */
159: TID tidPreLoad; /* identifier for the PreLoad thread */
160: BYTE bThreadStack[512]; /* stack for the thread */
161:
162: /* The chMenuTable contains the scan codes of the first letter of each
163: * menu. When a horizontal cursor key is pressed, the scan code for that menu
164: * is taken from this table and processed as if the user had pressed the
165: * key.
166: */
167:
168: CHAR chMenuTable[] = { 19, 46, 47, 24 };
169: SHORT sMenuTablePos; /* position in the scan code table */
170: SHORT sDirection = 0; /* direction to move in scan code table */
171:
172: NC ncHelp; /* handle to the help data file */
173:
174: /* The help engine uses an array of attributes to determine the colors of
175: * normal, bold, and italic text.
176: */
177:
178: BYTE bAttr[5] = { atNORMAL, atBOLD, atITALIC, atBOX, atMENU };
179: CHAR chHelpName[80]; /* data file name */
180: VIOMODEINFO vmiMode; /* video-mode structure */
181:
182: VOID cdecl main(argc, argv)
183: INT argc;
184: CHAR *argv[];
185: {
186: USHORT usTmp, i, y; /* temporary variables */
187: BOOL fNewPage = FALSE; /* TRUE draws a new page */
188: BOOL fFound; /* TRUE means topic has been found */
189: PTRLOC mouplInit; /* initial mouse position */
190: PSZ pszDefaults; /* LQH defaults from environment */
191: PCH pchPtr; /* temporary pointer */
192: CHAR chBuf[80]; /* temporary buffer */
193:
194: /* The hsemNewRef variable is set to indicate that there are no new
195: * reference topics to preload. This prevents the thread from starting
196: * when it is created. The HelpSearch() function clears the semaphore
197: * whenever a new function is loaded.
198: */
199:
200: DosSemSet((HSEM) &hsemNewRef);
201: DosCreateThread(PreLoadThread, /* address of the thread */
202: &tidPreLoad, /* address of the thread ID */
203: bThreadStack + 512); /* address of the thread's stack */
204:
205: /* The thread is allowed to run only while waiting for input. The
206: * Input() function resumes execution of the thread when it is called, and
207: * suspends execution before it returns. This maximizes response time to a
208: * keystroke or mouse event while allowing the thread to preload topics
209: * when the user is reading the current topic and not pressing keys or
210: * pressing the mouse button.
211: */
212:
213: DosSuspendThread(tidPreLoad);
214:
215: achBlank[0] = 0x20; /* used for clearing the box */
216: achBlank[1] = bNormalAtt;
217:
218: MouOpen(0L, (PHMOU) &hmou); /* Opens the mouse device */
219:
220: /* The selStringTable selector is set to a 64-K block of memory that is
221: * used to store the character-attribute strings. The strTable[] structure
222: * contains a list of pointers to each character-attribute string within
223: * this table and its length.
224: */
225:
226: if (DosAllocSeg(0, &selStringTable, 0)) {
227: BoxMessage(" Insufficient memory ", /* message */
228: atWARNING, /* attribute */
229: THIN, /* box line type */
230: hmou, /* handle to the mouse */
231: TRUE); /* TRUE sounds a warning tone */
232: DosExit(EXIT_PROCESS, 1);
233: }
234:
235: /* Get the current screen mode */
236:
237: vmiMode.cb = sizeof(vmiMode);
238: VioGetMode(&vmiMode, 0);
239:
240: /* If the display is monochrome, then all the character attributes need
241: * to be changed.
242: */
243:
244: if (vmiMode.fbType == 0) {
245: bAttr[2] = bItalicAtt = 1;
246: bHiAtt = bHiMenuAtt = 0x78;
247: chMenu[3] = chMenu[27] = chMenu[51] = chMenu[67] =
248: chMenu[81] = chMenu[99] = chMenu[149] = 1;
249: }
250:
251: /* All the dimensions for the box are set except the bottom. The bottom
252: * of the box is determined after examining the environment for a LQH
253: * variable and checking the size of the current display.
254: */
255:
256: mourtRect.row = qhbBox.top = 0;
257: mourtRect.col = qhbBox.left = BOXLEFT;
258: mourtRect.cCol = qhbBox.right = BOXRIGHT;
259: qhbBox.BorderAtt = atBOX;
260: qhbBox.FillAtt = atBOX;
261: qhbBox.BoxType = THIN;
262:
263: Dstrcpy((PCH) chHelpName, "qh.hlp"); /* data file */
264:
265: /* Scan the environment for a LQH variable. If LQH is found, process it
266: * to get the default data file and the window size.
267: */
268:
269: if (!DosScanEnv("LQH", &pszDefaults)) {
270: pchPtr = pszDefaults;
271:
272: /* If the first letter is not numeric, convert it into a filename,
273: * and use that filename as the database.
274: */
275:
276: if (*pchPtr != ',' && *pchPtr > '9') {
277: Dstrcpy((PCH) chHelpName, pszDefaults);
278: for (pchPtr = chHelpName; *pchPtr && *pchPtr != ',';
279: pchPtr++);
280: if (*pchPtr == ',')
281: *pchPtr++ = 0;
282: }
283:
284: /* If the character is numeric, convert it into the window size. */
285:
286: for (i = 0; pchPtr[i] != 0; i++)
287: if (pchPtr[i] > '0' && pchPtr[i] <= '9')
288: break;
289: if (pchPtr[i + 1] < '0')
290: usTmp = pchPtr[i] - '0';
291: else
292: usTmp = ((pchPtr[i] - '0') * 10) + pchPtr[i + 1] - '0';
293: if (usTmp < 5)
294: usTmp = 5;
295: else
296: usTmp++; /* First line is #0 */
297: vmiMode.cb = sizeof(vmiMode);
298: VioGetMode(&vmiMode, 0);
299: if (usTmp >= vmiMode.row)
300: usTmp = vmiMode.row - 1;
301: }
302: else
303: usTmp = vmiMode.row - 1;
304: mourtRect.cRow = qhbBox.bottom = usTmp;
305:
306: if (argc > 2)
307: Dstrcpy((PCH) chHelpName, argv[2]);
308:
309: /* Call Init() to open the data file and initialize the various tables */
310:
311: if (!Init())
312: DosExit(EXIT_PROCESS, 1);
313:
314: /* If nothing was passed via the command line, then try to get a function
315: * name from whatever the cursor is over when LQH is called.
316: */
317:
318: if (argc < 2)
319: fFound = ReadScreen(TRUE);
320: else
321: fFound = HelpSearch((NPSZ) argv[1], TRUE, 0L);
322:
323: /* Save the portion of the screen the box will be in */
324:
325: if (!(selBoxSave = BoxSave(&qhbBox)))
326: DosExit(EXIT_PROCESS, 1);
327:
328: /* Now that the screen area for the box and the menu is saved, increase
329: * the top of the box to leave room for the menu. The top will be decreased
330: * by one before the screen area is restored.
331: */
332:
333: qhbBox.top++;
334:
335: /* DosExit list is called so that when the program is terminated, the
336: * cursor and screen will be restored to their original state.
337: */
338:
339: DosExitList(EXLST_ADD, Abort);
340:
341: VioGetCurType(&viociCursor, 0); /* Gets the current cursor data */
342: viociCursor.attr = 0xFFFF; /* Sets the attribute to hidden */
343: VioSetCurType(&viociCursor, 0);
344:
345: /* Set the initial mouse position */
346:
347: mouplInit.row = 4;
348: mouplInit.col = 11;
349: MouSetPtrPos(&mouplInit, hmou);
350:
351: BoxDraw(&qhbBox); /* Draws the box */
352: VioWrtCellStr(chMenu, 160, BOXTOP - 1, BOXLEFT, 0); /* Adds menu */
353:
354: if (!fFound)
355: fFound = HelpSearch("QuickHelp", FALSE, 0L);
356:
357: /* If a topic hasn't been found, try to load the first list of topics
358: * from the List menu.
359: */
360:
361: if (!fFound && usListPos)
362: fFound = HelpSearch((NPSZ) lstList[0].name, FALSE, 0L);
363:
364: /* If all else fails, prompt the user for a topic. */
365:
366: while (!fFound) {
367: if (!BoxGetString(" Enter topic to find:", chBuf, 25, atMENU, hmou))
368: DosExitList(EXLST_ADD, Abort);
369: fFound = HelpSearch(chBuf, TRUE, 0L);
370: }
371:
372: usInterior = qhbBox.bottom - (BOXTOP + 2);
373: Display(); /* Displays the current topic */
374:
375: for (;; ) { /* infinite loop */
376: Input(); /* Waits for key or mouse input */
377: if (!kbdciKeyInfo.fbStatus) { /* If not a keystroke */
378: fMouButton = FALSE; /* Resets mouse button flag */
379: if (mouevEvent.row == BOXTOP - 1) { /* If over a menu */
380: if (mouevEvent.col < 12)
381: kbdciKeyInfo.chScan = 19; /* 'r' */
382: else if (mouevEvent.col < 24)
383: kbdciKeyInfo.chScan = 46; /* 'c' */
384: else if (mouevEvent.col < 32)
385: kbdciKeyInfo.chScan = 47; /* 'v' */
386: else if (mouevEvent.col < 41)
387: kbdciKeyInfo.chScan = 24; /* 'o' */
388: else if (mouevEvent.col > 71)
389: kbdciKeyInfo.chScan = 35; /* 'h' */
390: else
391: continue;
392: }
393:
394: /* Scroll the text if the mouse button is pressed when the
395: * mouse pointer is on the scroll bar.
396: */
397:
398: else if(mouevEvent.col == BOXRIGHT) {
399: if (mouevEvent.row > usInterior / 2 &&
400: mouevEvent.row < qhbBox.bottom) {
401: do {
402: ScrollDown();
403: MouReadEventQue(&mouevEvent, &MouReadType, hmou);
404: }
405: while (!mouevEvent.Time);
406: }
407: else if (mouevEvent.row < qhbBox.bottom) {
408: do {
409: ScrollUp();
410: MouReadEventQue(&mouevEvent, &MouReadType, hmou);
411: }
412: while (!mouevEvent.Time);
413: }
414: continue;
415: }
416:
417: /* If the mouse pointer wasn't over a menu or the scroll bar,
418: * try to find whatever topic is under the mouse.
419: */
420:
421: else {
422: if (fListDisplay && mouevEvent.row < qhbBox.bottom) {
423:
424: /* Set the cursor position to the mouse position */
425:
426: VioSetCurPos(mouevEvent.row, 2, 0);
427: MouseRelease(); /* Waits for a button release */
428: if (ReadScreen(FALSE))
429: Display();
430:
431: /* If a word on the screen couldn't be found, try
432: * the entire line.
433: */
434:
435: else {
436: y = 40; /* largest topic */
437: VioReadCharStr(chBuf, &y, mouevEvent.row, 2, 0);
438: y = Dstrlen(chBuf) - 1;
439: while (y && chBuf[y] == ' ')
440: chBuf[y--] = 0;
441: if (HelpSearch(chBuf, TRUE, 0L))
442: Display();
443: }
444: }
445: else {
446: VioSetCurPos(mouevEvent.row, mouevEvent.col, 0);
447: MouseRelease(); /* Waits for button release */
448: if (ReadScreen(TRUE))
449: Display();
450: }
451: continue;
452: }
453: }
454:
455: /* The key scan code is processed instead of the character so that
456: * alternate, shift, and control key combinations are all accepted.
457: */
458:
459: switch(kbdciKeyInfo.chScan) {
460: case 45: /* 'x' */
461:
462: /* Calling DosExit will invoke the DosExitList function
463: * Abort(), which will restore the cursor and the screen.
464: */
465:
466: DosExit(EXIT_PROCESS, 0);
467:
468: case 28: /* ENTER */
469:
470: /* If a list of topics is being displayed, then set the
471: * cursor to the second column and call the ReadScreen()
472: * function to search for the topic name at that position.
473: */
474:
475: if (fListDisplay) {
476: VioSetCurPos(selTable[usCurrent].usHighLight + 1, 2, 0);
477: if (ReadScreen(FALSE))
478: Display();
479: else {
480: y = 40;
481: VioReadCharStr(chBuf, &y,
482: selTable[usCurrent].usHighLight + 1 , 2, 0); /* Vio handle */
483: y = Dstrlen(chBuf) - 1;
484: while (y && chBuf[y] == ' ')
485: chBuf[y--] = 0;
486: if (HelpSearch(chBuf, TRUE, 0L))
487: Display();
488: }
489: }
490: break;
491:
492: case 23: /* 'i' */
493: fBack = TRUE;
494: if (HelpSearch("", FALSE, HelpNcBack()))
495: Display();
496: else
497: BoxMessage(" No prior screen displayed ",
498: bMenuAtt, THIN, hmou, TRUE);
499: break;
500:
501: case 49: /* 'n' */
502: if (HelpSearch("", FALSE,
503: HelpNcNext(selTable[usCurrent].ncContext)))
504: Display();
505: else
506: BoxMessage(" You are at the end of the database ",
507: bMenuAtt, THIN, hmou, TRUE);
508: break;
509:
510: case 31: /* 's' */
511: if (BoxGetString(" Enter topic to find:", chBuf, 25,
512: atMENU, hmou))
513: if (HelpSearch(chBuf, TRUE, 0L))
514: Display();
515: break;
516:
517: case 47: /* 'v' */
518: sMenuTablePos = 2;
519: Search();
520: break;
521:
522: case 24: /* 'o' */
523: sMenuTablePos = 3;
524: Options();
525: break;
526:
527: case 19: /* 'r' */
528: sMenuTablePos = 0;
529: Reference();
530: break;
531:
532: case 46: /* 'c */
533: sMenuTablePos = 1;
534: ListMenu();
535: break;
536:
537: case 59: /* F1 */
538: case 35: /* 'h' */
539: if (HelpSearch("QuickHelp", TRUE, 0L))
540: Display();
541: break;
542:
543: case 72: /* cursor up */
544: ScrollUp();
545: break;
546:
547: case 80: /* cursor down */
548: ScrollDown();
549: break;
550:
551: case 81: /* PAGE DOWN */
552: if (usTotalLines <= usInterior)
553: break;
554: if (usBottomLine != usTotalLines) {
555: usBottomLine += usInterior;
556: if (usBottomLine > usTotalLines)
557: usBottomLine = usTotalLines;
558: fNewPage = TRUE; /* Requests new page */
559: }
560: break;
561:
562: case 73: /* PAGE UP */
563: if (usTotalLines <= usInterior ||
564: selTable[usCurrent].usTopLine == 1)
565: break;
566: if (selTable[usCurrent].usTopLine > usInterior + 1)
567: usBottomLine -= usInterior;
568: else {
569: usBottomLine = usInterior + 1;
570: }
571: fNewPage = TRUE; /* Requests a new page */
572: break;
573:
574: case 71: /* HOME */
575: usBottomLine = usInterior + 1;
576: if (usBottomLine > usTotalLines)
577: usBottomLine = usTotalLines;
578: fNewPage = TRUE; /* Requests a new page */
579: break;
580:
581: case 79: /* END */
582: if (usTotalLines <= usInterior)
583: break;
584: if (usBottomLine != usTotalLines) {
585: usBottomLine = usTotalLines;
586: fNewPage = TRUE;
587: }
588: break;
589:
590: default:
591: break;
592: }
593:
594: if (fNewPage) {
595: selTable[usCurrent].usTopLine = usBottomLine - usInterior;
596: Display();
597: fNewPage = FALSE;
598: }
599: }
600: }
601:
602: /****************************************************************************
603:
604: FUNCTION: Abort();
605:
606: PURPOSE: Restore the cursor, and clean up memory
607:
608: COMMENTS:
609: This function is called when the program is aborted to restore the
610: cursor type, cursor position, and the screen.
611:
612: ****************************************************************************/
613:
614: VOID FAR Abort() {
615: qhbBox.top--; /* Restores the menu as well as the box */
616: BoxRestore(&qhbBox, selBoxSave); /* Restores the screen */
617: DosExitList(EXLST_EXIT, 0L); /* termination completed */
618: }
619:
620: /****************************************************************************
621:
622: FUNCTION: ReadScreen();
623:
624: PURPOSE: If the cursor is over a topic name, retrieve the topic
625:
626: COMMENTS:
627: This function takes the current cursor position on the screen,
628: backs up to the first non-alphabetic character or the beginning of
629: the line, and then forms a search string by copying all characters
630: up until the first non-alphabetic character. It then calls the
631: HelpSearch() function to retrieve the topic matching the search
632: string.
633:
634: ****************************************************************************/
635:
636: BOOL ReadScreen(fFlag)
637: BOOL fFlag;
638: {
639: USHORT usRow, usCol, usLen = 80;
640: INT i, j;
641: CHAR chPatBuf[80];
642:
643: VioGetCurPos(&usRow, &usCol, 0); /* get cursor position */
644: j = usCol; /* save cursor column */
645: VioReadCharStr(chPatBuf, /* buffer for string */
646: &usLen, /* length of the buffer */
647: usRow, /* starting row */
648: 0, /* starting column */
649: 0); /* Vio handle */
650:
651: if (usCol && !isalpha(chPatBuf[usCol]))
652: usCol--;
653:
654: /* Back up the cursor to the first non-letter, or beginning of the line */
655:
656: for (i = usCol; isalpha(chPatBuf[i]) && i >= 0; i--);
657: i++; /* Backs up to the first letter of the word */
658:
659: /* Copy everything up to the first non-letter into the first part of
660: * the pattern buffer.
661: */
662:
663: for (j = 0; isalpha(chPatBuf[i]) && i < 80; i++, j++)
664: chPatBuf[j] = chPatBuf[i];
665: if (i < 80 && j > 2) {
666: chPatBuf[j] = 0;
667: return (HelpSearch(chPatBuf, fFlag, 0L));
668: }
669: return FALSE;
670: }
671:
672: /****************************************************************************
673:
674: FUNCTION: ScrollUp()
675:
676: PURPOSE: Scroll the text up one line
677:
678: COMMENTS:
679: This function is called to scroll up either a highlighted line or
680: the text.
681:
682: ****************************************************************************/
683:
684: VOID ScrollUp() {
685: if (selTable[usCurrent].usTopLine == 1 &&
686: selTable[usCurrent].usHighLight == BOXTOP)
687: return;
688: if (fListDisplay)
689: VioWrtCellStr(bHoldString, cbHoldLength,
690: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
691:
692: if (fListDisplay && selTable[usCurrent].usHighLight > 1) {
693: selTable[usCurrent].usHighLight--;
694: }
695:
696: else if (selTable[usCurrent].usTopLine > 1) {
697: VioScrollDn(qhbBox.top + 1, /* top row */
698: BOXLEFT + 2, /* left column */
699: qhbBox.bottom - 1, /* bottom row */
700: BOXRIGHT - 1, /* right column */
701: 1, /* lines to scroll */
702: achBlank,
703: 0);
704: selTable[usCurrent].usTopLine--;
705: usBottomLine--;
706: VioWrtCellStr(strTable[selTable[usCurrent].usTopLine].addr,
707: strTable[selTable[usCurrent].usTopLine].cb,
708: BOXTOP + 1, BOXLEFT + 2, 0);
709: }
710: if (fListDisplay) { /* Turns on highlighting */
711: VioReadCellStr(bHoldString, &cbHoldLength,
712: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
713: VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
714: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
715: }
716: BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
717: }
718:
719: /****************************************************************************
720:
721: FUNCTION: ScrollUp()
722:
723: PURPOSE: Scroll the text up one line
724:
725: COMMENTS:
726: This function is called to scroll down either a highlighted line or
727: the text.
728:
729: ****************************************************************************/
730:
731: VOID ScrollDown() {
732: if (usBottomLine == usTotalLines &&
733: selTable[usCurrent].usHighLight == usBottomLine)
734: return;
735: if (fListDisplay)
736: VioWrtCellStr(bHoldString, cbHoldLength,
737: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
738:
739: if (fListDisplay && selTable[usCurrent].usHighLight <= usInterior)
740: selTable[usCurrent].usHighLight++;
741: else if (usBottomLine < usTotalLines) {
742: VioScrollUp(qhbBox.top + 1, /* top row */
743: BOXLEFT + 2, /* left column */
744: qhbBox.bottom - 1, /* bottom row */
745: BOXRIGHT - 1, /* right column */
746: 1, /* lines to scroll */
747: achBlank,
748: 0);
749: selTable[usCurrent].usTopLine++;
750: usBottomLine++;
751: VioWrtCellStr(strTable[usBottomLine].addr, strTable[usBottomLine].cb,
752: qhbBox.bottom - 1, BOXLEFT + 2, 0);
753: }
754: if (fListDisplay) { /* Turns on highlighting */
755: VioReadCellStr(bHoldString, &cbHoldLength,
756: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
757: VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
758: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
759: }
760: BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
761: }
762:
763: /****************************************************************************
764:
765: FUNCTION: Display();
766:
767: PURPOSE: Display a page from the current topic
768:
769: COMMENTS:
770: This function first clears the interior of the box by scrolling
771: spaces with a normal attribute into the box. It then retrieves the
772: top-line number from the selTable structure and uses the global
773: usBottomLine variable to determine how many lines to display. It
774: then checks the usHighLight member of the selTable strucutre to
775: determine if one of the lines is to be highlighted. The final
776: action is to call BoxScroll to position the inverse block on the
777: right side of the box border to indicate where the current line is
778: in the text.
779:
780: ****************************************************************************/
781:
782: VOID Display() {
783: USHORT usLine, i;
784:
785: usBottomLine = usInterior + selTable[usCurrent].usTopLine;
786: if (usBottomLine > usTotalLines)
787: usBottomLine = usTotalLines;
788:
789: VioScrollDn(BOXTOP + 1, BOXLEFT + 1, qhbBox.bottom - 1,
790: BOXRIGHT - 1, usInterior + 1, achBlank, 0);
791: for (i = 1, usLine = selTable[usCurrent].usTopLine;
792: usLine <= usBottomLine; usLine++, i++)
793: VioWrtCellStr(strTable[usLine].addr, strTable[usLine].cb,
794: BOXTOP + i, BOXLEFT + 2, 0);
795: if (selTable[usCurrent].usHighLight) {
796:
797: /* Before highlighting a line, read the entire line into a buffer
798: * so that when the user is scrolling, the line can be restored with
799: * the previous attributes.
800: */
801:
802: VioReadCellStr(bHoldString, &cbHoldLength,
803: selTable[usCurrent].usHighLight + 1,BOXLEFT + 1, 0);
804: VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
805: selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
806: }
807: BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
808: }
809:
810: /****************************************************************************
811:
812: FUNCTION:
813: MouseRelease();
814:
815: PURPOSE: Waits for the release of the mouse button
816:
817: ****************************************************************************/
818:
819: VOID MouseRelease() {
820: USHORT usMouWait = 1; /* Waits for a mouse event */
821:
822: do {
823: MouReadEventQue(&mouevEvent, &usMouWait, hmou);
824: }
825: while (mouevEvent.fs > 1); /* while a mouse button is pressed */
826: }
827:
828: /****************************************************************************
829:
830: FUNCTION:
831: isalpha(PCH, PCH, USHORT);
832:
833: PURPOSE: Returns TRUE if character is alphabetic
834:
835: COMMENTS:
836: This function is defined here to avoid bringing in the C runtime.
837:
838: ****************************************************************************/
839:
840: BOOL isalpha(chVal)
841: CHAR chVal;
842: {
843: return ((chVal >= 'A' && chVal <= 'Z') ||
844: (chVal >= 'a' && chVal <= 'z'));
845: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.