|
|
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.