File:  [OS/2 SDKs] / os2sdk / demos / apps / lqh / lqhmain.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 12:26:06 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: os2sdk-1988, HEAD
Microsoft OS/2 SDK 03-01-1988

/****************************************************************************

    PROGRAM: lqh.c

    MODULE: lqhmain.c

    PURPOSE: Displays on-line information

    FUNCTIONS:
        main()
        ReadScreen()    Checks if cursor is over a function name
        ScrollDown()    Scroll screen down
        ScrollUp()      Scroll screen up
        Abort()         Called upon program termination
        MouseRelease()  Waits until mouse button is released
        isalpha()       Returns TRUE if character is alphabetic


    COMMENTS:
        This program provides a subset of the capabilities of the Microsoft
        QuickHelp program. It is provided as an example application using
        MS OS/2.

****************************************************************************/

#include "lqh.h"

CHAR chMenu[] = { /* Top menu defined as character-attribute string */
    ' ', atMENU,
    'R', atLEAD,                                              /* #1 */
    'e', atMENU,
    'f', atMENU,
    'e', atMENU,
    'r', atMENU,
    'e', atMENU,
    'n', atMENU,
    'c', atMENU,
    'e', atMENU,
    's', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    'C', atLEAD,                                             /* #13 */
    'a', atMENU,
    't', atMENU,
    'e', atMENU,
    'g', atMENU,
    'o', atMENU,
    'r', atMENU,
    'i', atMENU,
    'e', atMENU,
    's', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    'V', atLEAD,                                             /* #25 */
    'i', atMENU,
    'e', atMENU,
    'w', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    'O', atLEAD,                                             /* #33 */
    'p', atMENU,
    't', atMENU,
    'i', atMENU,
    'o', atMENU,
    'n', atMENU,
    's', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    ' ', atMENU,
    0xB3, atMENU,
    ' ', atMENU,
    'F', atMENU,
    '1', atMENU,
    '=', atMENU,
    'H', atLEAD,
    'e', atMENU,
    'l', atMENU,
    'p', atMENU,
    ' ', atMENU,
    };

VIOCURSORINFO viociCursor;    /* cursor data                        */
KBDKEYINFO kbdciKeyInfo;      /* structure for key data             */
QHBOX qhbBox;                 /*  box dimensions                    */

CHAR achBlank[2];             /* used to clear the screen           */
BYTE bHoldString[160];        /* Holds string prior to highlighting */
USHORT cbHoldLength = ((BOXRIGHT - 1) - (BOXLEFT + 1)) * 2;

CHAR chReference[MAXLIST * MAXNAMESIZE]; /* Stores reference names  */
NPSZ npszRefTable[MAXLIST];       /* table of reference functions   */
STRTABLE strTable[2000];          /* Maintains address of each line */
USHORT usRefCount;                /* number of reference functions  */
LIST lstList[MAXLIST];            /* list of category names         */
USHORT usListPos;                 /* position in tables             */
USHORT usCurListPos;              /* position in tables             */

USHORT hmou;                      /* handle to the mouse            */
MOUEVENTINFO mouevEvent;          /* mouse event packet structure   */
NOPTRRECT mourtRect;              /* structure for hiding the mouse */
BOOL fMouButton = FALSE;          /* TRUE if button it clicked      */
USHORT MouReadType = 0;           /* don't wait for mouse event     */

BYTE bNormalAtt = atNORMAL;       /* default attributes             */
BYTE bHiAtt = atHILITE;
BYTE bBoldAtt = atBOLD;
BYTE bItalicAtt = atITALIC;
BYTE bMenuAtt = atMENU;
BYTE bHiMenuAtt = atNORMAL;

SEL selBoxSave;              /* selector to memory for screen save  */
SEL selStringTable;          /* selector for char-attribute strings */

USHORT usBottomLine;         /* current bottom-line number          */
USHORT usInterior;           /* maximum number of displayed lines   */
USHORT usTotalLines;         /* total number of lines               */
USHORT usStructLine;         /* starting line of structure section  */
BOOL fListDisplay;      /* TRUE if function list is being displayed */
BOOL fBack = FALSE;     /* TRUE if HelpNcBack() was called          */
USHORT usSaveMenuPos = 2;    /* current List menu position          */

/* The selTable contains a list of preloaded topics. Whenever a request is
 * made for a topic, this table is checked to see if the topic is in memory.
 */

SELTABLE selTable[MAXPRELOAD];  /* table of preloaded topics        */
USHORT usCurrent = 0;           /* current index in selTable        */

ULONG FAR hsemNewRef = 0;      /* RAM semaphore used by PreLoad()   */
TID tidPreLoad;                /* identifier for the PreLoad thread */
BYTE bThreadStack[512];        /* stack for the thread              */

/* The chMenuTable contains the scan codes of the first letter of each
 * menu. When a horizontal cursor key is pressed, the scan code for that menu
 * is taken from this table and processed as if the user had pressed the
 * key.
 */

CHAR chMenuTable[] = { 19, 46, 47, 24 };
SHORT sMenuTablePos;        /* position in the scan code table      */
SHORT sDirection = 0;       /* direction to move in scan code table */

NC ncHelp;                  /* handle to the help data file         */

/* The help engine uses an array of attributes to determine the colors of
 * normal, bold, and italic text.
 */

BYTE bAttr[5] = { atNORMAL, atBOLD, atITALIC, atBOX, atMENU };
CHAR chHelpName[80];             /*  data file name                 */
VIOMODEINFO vmiMode;             /* video-mode structure            */

VOID cdecl main(argc, argv)
INT argc;
CHAR *argv[];
{
    USHORT usTmp, i, y;          /* temporary variables             */
    BOOL fNewPage = FALSE;       /* TRUE draws a new page           */
    BOOL fFound;                 /* TRUE means topic has been found */
    PTRLOC mouplInit;            /* initial mouse position          */
    PSZ pszDefaults;             /* LQH defaults from environment   */
    PCH pchPtr;                  /* temporary pointer               */
    CHAR chBuf[80];              /* temporary buffer                */

    /* The hsemNewRef variable is set to indicate that there are no new
     * reference topics to preload. This prevents the thread from starting
     * when it is created. The HelpSearch() function clears the semaphore
     * whenever a new function is loaded.
     */

    DosSemSet((HSEM) &hsemNewRef);
    DosCreateThread(PreLoadThread, /* address of the thread         */
        &tidPreLoad,               /* address of the thread ID      */
        bThreadStack + 512);       /* address of the thread's stack */

    /* The thread is allowed to run only while waiting for input. The
     * Input() function resumes execution of the thread when it is called, and
     * suspends execution before it returns. This maximizes response time to a
     * keystroke or mouse event while allowing the thread to preload topics
     * when the user is reading the current topic and not pressing keys or
     * pressing the mouse button.
     */

    DosSuspendThread(tidPreLoad);

    achBlank[0] = 0x20;                /* used for clearing the box */
    achBlank[1] = bNormalAtt;

    MouOpen(0L, (PHMOU) &hmou);        /* Opens the mouse device    */

    /* The selStringTable selector is set to a 64-K block of memory that is
     * used to store the character-attribute strings. The strTable[] structure
     * contains a list of pointers to each character-attribute string within
     * this table and its length.
     */

    if (DosAllocSeg(0, &selStringTable, 0)) {
        BoxMessage(" Insufficient memory ", /* message              */
            atWARNING,                /* attribute                  */
            THIN,                     /* box line type              */
            hmou,                     /* handle to the mouse        */
            TRUE);                    /* TRUE sounds a warning tone */
        DosExit(EXIT_PROCESS, 1);
    }

    /* Get the current screen mode */

    vmiMode.cb = sizeof(vmiMode);
    VioGetMode(&vmiMode, 0);

    /* If the display is monochrome, then all the character attributes need
     * to be changed.
     */

    if (vmiMode.fbType == 0) {
        bAttr[2] = bItalicAtt = 1;
        bHiAtt = bHiMenuAtt = 0x78;
        chMenu[3] = chMenu[27] = chMenu[51] = chMenu[67] =
            chMenu[81] = chMenu[99] = chMenu[149] = 1;
    }

    /* All the dimensions for the box are set except the bottom. The bottom
     * of the box is determined after examining the environment for a LQH
     * variable and checking the size of the current display.
     */

    mourtRect.row = qhbBox.top = 0;
    mourtRect.col = qhbBox.left = BOXLEFT;
    mourtRect.cCol = qhbBox.right = BOXRIGHT;
    qhbBox.BorderAtt = atBOX;
    qhbBox.FillAtt = atBOX;
    qhbBox.BoxType = THIN;

    Dstrcpy((PCH) chHelpName, "qh.hlp");              /*  data file */

    /* Scan the environment for a LQH variable. If LQH is found, process it
     * to get the default data file and the window size.
     */

    if (!DosScanEnv("LQH", &pszDefaults)) {
        pchPtr = pszDefaults;

        /* If the first letter is not numeric, convert it into a filename,
         * and use that filename as the database.
         */

        if (*pchPtr != ',' && *pchPtr > '9') {
            Dstrcpy((PCH) chHelpName, pszDefaults);
            for (pchPtr = chHelpName; *pchPtr && *pchPtr != ',';
                pchPtr++);
            if (*pchPtr == ',')
                *pchPtr++ = 0;
        }

        /* If the character is numeric, convert it into the window size. */

        for (i = 0; pchPtr[i] != 0; i++)
            if (pchPtr[i] > '0' && pchPtr[i] <= '9')
                break;
        if (pchPtr[i + 1] < '0')
            usTmp = pchPtr[i] - '0';
        else
            usTmp = ((pchPtr[i] - '0') * 10) + pchPtr[i + 1] - '0';
        if (usTmp < 5)
            usTmp = 5;
        else
            usTmp++;                            /* First line is #0 */
        vmiMode.cb = sizeof(vmiMode);
        VioGetMode(&vmiMode, 0);
        if (usTmp >= vmiMode.row)
            usTmp = vmiMode.row - 1;
    }
    else
        usTmp = vmiMode.row - 1;
    mourtRect.cRow = qhbBox.bottom = usTmp;

    if (argc > 2)
        Dstrcpy((PCH) chHelpName, argv[2]);

    /* Call Init() to open the data file and initialize the various tables */

    if (!Init())
        DosExit(EXIT_PROCESS, 1);

    /* If nothing was passed via the command line, then try to get a function
     * name from whatever the cursor is over when LQH is called.
     */

    if (argc < 2)
        fFound = ReadScreen(TRUE);
    else
        fFound = HelpSearch((NPSZ) argv[1], TRUE, 0L);

    /* Save the portion of the screen the box will be in */

    if (!(selBoxSave = BoxSave(&qhbBox)))
        DosExit(EXIT_PROCESS, 1);

    /* Now that the screen area for the box and the menu is saved, increase
     * the top of the box to leave room for the menu. The top will be decreased
     * by one before the screen area is restored.
     */

    qhbBox.top++;

    /* DosExit list is called so that when the program is terminated, the
     * cursor and screen will be restored to their original state.
     */

    DosExitList(EXLST_ADD, Abort);

    VioGetCurType(&viociCursor, 0);       /* Gets the current cursor data */
    viociCursor.attr = 0xFFFF;            /* Sets the attribute to hidden */
    VioSetCurType(&viociCursor, 0);

    /* Set the initial mouse position */

    mouplInit.row = 4;
    mouplInit.col = 11;
    MouSetPtrPos(&mouplInit, hmou);

    BoxDraw(&qhbBox);                              /* Draws the box */
    VioWrtCellStr(chMenu, 160, BOXTOP - 1, BOXLEFT, 0); /* Adds menu */

    if (!fFound)
        fFound = HelpSearch("QuickHelp", FALSE, 0L);

    /* If a topic hasn't been found, try to load the first list of topics
     * from the List menu.
     */

    if (!fFound && usListPos)
        fFound = HelpSearch((NPSZ) lstList[0].name, FALSE, 0L);

    /* If all else fails, prompt the user for a topic. */

    while (!fFound) {
        if (!BoxGetString(" Enter topic to find:", chBuf, 25, atMENU, hmou))
            DosExitList(EXLST_ADD, Abort);
        fFound = HelpSearch(chBuf, TRUE, 0L);
    }

    usInterior = qhbBox.bottom - (BOXTOP + 2);
    Display();                      /* Displays the current topic   */

    for (;; ) {                     /* infinite loop                */
        Input();                    /* Waits for key or mouse input */
        if (!kbdciKeyInfo.fbStatus) {   /* If not a keystroke       */
            fMouButton = FALSE;         /* Resets mouse button flag */
            if (mouevEvent.row == BOXTOP - 1) { /* If over a menu   */
                if (mouevEvent.col < 12)
                    kbdciKeyInfo.chScan = 19;                /* 'r' */
                else if (mouevEvent.col < 24)
                    kbdciKeyInfo.chScan = 46;                /* 'c' */
                else if (mouevEvent.col < 32)
                    kbdciKeyInfo.chScan = 47;                /* 'v' */
                else if (mouevEvent.col < 41)
                    kbdciKeyInfo.chScan = 24;                /* 'o' */
                else if (mouevEvent.col > 71)
                    kbdciKeyInfo.chScan = 35;                /* 'h' */
                else
                    continue;
            }

            /* Scroll the text if the mouse button is pressed when the
             * mouse pointer is on the scroll bar.
             */

            else if(mouevEvent.col == BOXRIGHT) {
                if (mouevEvent.row > usInterior / 2 &&
                        mouevEvent.row < qhbBox.bottom) {
                    do {
                        ScrollDown();
                        MouReadEventQue(&mouevEvent, &MouReadType, hmou);
                    }
                    while (!mouevEvent.Time);
                }
                else if (mouevEvent.row < qhbBox.bottom) {
                    do {
                        ScrollUp();
                        MouReadEventQue(&mouevEvent, &MouReadType, hmou);
                    }
                    while (!mouevEvent.Time);
                }
                continue;
            }

            /* If the mouse pointer wasn't over a menu or the scroll bar,
             * try to find whatever topic is under the mouse.
             */

            else {
                if (fListDisplay && mouevEvent.row < qhbBox.bottom) {

                    /* Set the cursor position to the mouse position */

                    VioSetCurPos(mouevEvent.row, 2, 0);
                    MouseRelease();   /* Waits for a button release */
                    if (ReadScreen(FALSE))
                        Display();

                    /* If a word on the screen couldn't be found, try
                     * the entire line.
                     */

                    else {
                        y = 40;                    /* largest topic */
                        VioReadCharStr(chBuf, &y, mouevEvent.row, 2, 0);
                        y = Dstrlen(chBuf) - 1;
                        while (y && chBuf[y] == ' ')
                            chBuf[y--] = 0;
                        if (HelpSearch(chBuf, TRUE, 0L))
                            Display();
                    }
                }
                else {
                    VioSetCurPos(mouevEvent.row, mouevEvent.col, 0);
                    MouseRelease();     /* Waits for button release */
                    if (ReadScreen(TRUE))
                        Display();
                }
                continue;
            }
        }

        /* The key scan code is processed instead of the character so that
         * alternate, shift, and control key combinations are all accepted.
         */

        switch(kbdciKeyInfo.chScan) {
            case 45:                                         /* 'x' */

                /* Calling DosExit will invoke the DosExitList function
                 * Abort(), which will restore the cursor and the screen.
                 */

                DosExit(EXIT_PROCESS, 0);

            case 28:                                       /* ENTER */

                /* If a list of topics is being displayed, then set the
                 * cursor to the second column and call the ReadScreen()
                 * function to search for the topic name at that position.
                 */

                if (fListDisplay) {
                    VioSetCurPos(selTable[usCurrent].usHighLight + 1, 2, 0);
                    if (ReadScreen(FALSE))
                        Display();
                    else {
                        y = 40;
                        VioReadCharStr(chBuf, &y,
                            selTable[usCurrent].usHighLight + 1 , 2, 0);                                 /* Vio handle           */
                        y = Dstrlen(chBuf) - 1;
                        while (y && chBuf[y] == ' ')
                            chBuf[y--] = 0;
                        if (HelpSearch(chBuf, TRUE, 0L))
                            Display();
                    }
                }
                break;

            case 23:                                       /* 'i' */
                fBack = TRUE;
                if (HelpSearch("", FALSE, HelpNcBack()))
                    Display();
                else
                    BoxMessage(" No prior screen displayed ",
                        bMenuAtt, THIN, hmou, TRUE);
                break;

            case 49:                                         /* 'n' */
                if (HelpSearch("", FALSE,
                        HelpNcNext(selTable[usCurrent].ncContext)))
                    Display();
                else
                    BoxMessage(" You are at the end of the database ",
                        bMenuAtt, THIN, hmou, TRUE);
                break;

            case 31:                                         /* 's' */
                if (BoxGetString(" Enter topic to find:", chBuf, 25,
                        atMENU, hmou))
                    if (HelpSearch(chBuf, TRUE, 0L))
                        Display();
                break;

            case 47:                                         /* 'v' */
                sMenuTablePos = 2;
                Search();
                break;

            case 24:                                         /* 'o' */
                sMenuTablePos = 3;
                Options();
                break;

            case 19:                                         /* 'r' */
                sMenuTablePos = 0;
                Reference();
                break;

            case 46:                                          /* 'c */
                sMenuTablePos = 1;
                ListMenu();
                break;

            case 59:                                          /* F1 */
            case 35:                                         /* 'h' */
                if (HelpSearch("QuickHelp", TRUE, 0L))
                    Display();
                break;

            case 72:                                   /* cursor up */
                ScrollUp();
                break;

            case 80:                                 /* cursor down */
                ScrollDown();
                break;

            case 81:                                   /* PAGE DOWN */
                if (usTotalLines <= usInterior)
                    break;
                if (usBottomLine != usTotalLines) {
                    usBottomLine += usInterior;
                    if (usBottomLine > usTotalLines)
                        usBottomLine = usTotalLines;
                    fNewPage = TRUE;           /* Requests new page */
                }
                break;

            case 73:                                     /* PAGE UP */
                if (usTotalLines <= usInterior ||
                        selTable[usCurrent].usTopLine == 1)
                    break;
                if (selTable[usCurrent].usTopLine > usInterior + 1)
                    usBottomLine -= usInterior;
                else {
                    usBottomLine = usInterior + 1;
                }
                fNewPage = TRUE;             /* Requests a new page */
                break;

            case 71:                                        /* HOME */
                usBottomLine = usInterior + 1;
                if (usBottomLine > usTotalLines)
                    usBottomLine = usTotalLines;
                fNewPage = TRUE;             /* Requests a new page */
                break;

            case 79:                                         /* END */
                if (usTotalLines <= usInterior)
                    break;
                if (usBottomLine != usTotalLines) {
                    usBottomLine = usTotalLines;
                    fNewPage = TRUE;
                }
                break;

            default:
                break;
        }

        if (fNewPage) {
            selTable[usCurrent].usTopLine = usBottomLine - usInterior;
            Display();
            fNewPage = FALSE;
        }
    }
}

/****************************************************************************

    FUNCTION: Abort();

    PURPOSE: Restore the cursor, and clean up memory

    COMMENTS:
        This function is called when the program is aborted to restore the
        cursor type, cursor position, and the screen.

****************************************************************************/

VOID FAR Abort() {
    qhbBox.top--;           /* Restores the menu as well as the box */
    BoxRestore(&qhbBox, selBoxSave); /* Restores the screen         */
    DosExitList(EXLST_EXIT, 0L);     /* termination completed       */
}

/****************************************************************************

    FUNCTION: ReadScreen();

    PURPOSE: If the cursor is over a topic name, retrieve the topic

    COMMENTS:
        This function takes the current cursor position on the screen,
        backs up to the first non-alphabetic character or the beginning of
        the line, and then forms a search string by copying all characters
        up until the first non-alphabetic character. It then calls the
        HelpSearch() function to retrieve the topic matching the search
        string.

****************************************************************************/

BOOL ReadScreen(fFlag)
BOOL fFlag;
{
    USHORT usRow, usCol, usLen = 80;
    INT i, j;
    CHAR chPatBuf[80];

    VioGetCurPos(&usRow, &usCol, 0);        /* get cursor position  */
    j = usCol;                              /* save cursor column   */
    VioReadCharStr(chPatBuf,                /* buffer for string    */
        &usLen,                             /* length of the buffer */
        usRow,                              /* starting row         */
        0,                                  /* starting column      */
        0);                                 /* Vio handle           */

    if (usCol && !isalpha(chPatBuf[usCol]))
        usCol--;

    /* Back up the cursor to the first non-letter, or beginning of the line */

    for (i = usCol; isalpha(chPatBuf[i]) && i >= 0; i--);
    i++;                /* Backs up to the first letter of the word */

    /* Copy everything up to the first non-letter into the first part of
     * the pattern buffer.
     */

    for (j = 0; isalpha(chPatBuf[i]) && i < 80; i++, j++)
        chPatBuf[j] = chPatBuf[i];
    if (i < 80 && j > 2) {
        chPatBuf[j] = 0;
        return (HelpSearch(chPatBuf, fFlag, 0L));
    }
    return FALSE;
}

/****************************************************************************

    FUNCTION: ScrollUp()

    PURPOSE: Scroll the text up one line

    COMMENTS:
        This function is called to scroll up either a highlighted line or
        the text.

****************************************************************************/

VOID ScrollUp() {
    if (selTable[usCurrent].usTopLine == 1 &&
            selTable[usCurrent].usHighLight == BOXTOP)
        return;
    if (fListDisplay)
        VioWrtCellStr(bHoldString, cbHoldLength,
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);

    if (fListDisplay && selTable[usCurrent].usHighLight > 1) {
        selTable[usCurrent].usHighLight--;
    }

    else if (selTable[usCurrent].usTopLine > 1) {
        VioScrollDn(qhbBox.top + 1,              /* top row         */
            BOXLEFT + 2,                         /* left column     */
            qhbBox.bottom - 1,                   /* bottom row      */
            BOXRIGHT - 1,                        /* right column    */
            1,                                   /* lines to scroll */
            achBlank,
            0);
        selTable[usCurrent].usTopLine--;
        usBottomLine--;
        VioWrtCellStr(strTable[selTable[usCurrent].usTopLine].addr,
            strTable[selTable[usCurrent].usTopLine].cb,
            BOXTOP + 1, BOXLEFT + 2, 0);
    }
    if (fListDisplay) {                    /* Turns on highlighting */
        VioReadCellStr(bHoldString, &cbHoldLength,
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
        VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
    }
    BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
}

/****************************************************************************

    FUNCTION: ScrollUp()

    PURPOSE: Scroll the text up one line

    COMMENTS:
        This function is called to scroll down either a highlighted line or
        the text.

****************************************************************************/

VOID ScrollDown() {
    if (usBottomLine == usTotalLines &&
            selTable[usCurrent].usHighLight == usBottomLine)
        return;
    if (fListDisplay)
        VioWrtCellStr(bHoldString, cbHoldLength,
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);

    if (fListDisplay && selTable[usCurrent].usHighLight <= usInterior)
        selTable[usCurrent].usHighLight++;
    else if (usBottomLine < usTotalLines) {
        VioScrollUp(qhbBox.top + 1,              /* top row         */
            BOXLEFT + 2,                         /* left column     */
            qhbBox.bottom - 1,                   /* bottom row      */
            BOXRIGHT - 1,                        /* right column    */
            1,                                   /* lines to scroll */
            achBlank,
            0);
        selTable[usCurrent].usTopLine++;
        usBottomLine++;
        VioWrtCellStr(strTable[usBottomLine].addr, strTable[usBottomLine].cb,
            qhbBox.bottom - 1, BOXLEFT + 2, 0);
    }
    if (fListDisplay) {                    /* Turns on highlighting */
        VioReadCellStr(bHoldString, &cbHoldLength,
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
        VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
    }
    BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
}

/****************************************************************************

    FUNCTION: Display();

    PURPOSE: Display a page from the current topic

    COMMENTS:
        This function first clears the interior of the box by scrolling
        spaces with a normal attribute into the box. It then retrieves the
        top-line number from the selTable structure and uses the global
        usBottomLine variable to determine how many lines to display. It
        then checks the usHighLight member of the selTable strucutre to
        determine if one of the lines is to be highlighted. The final
        action is to call BoxScroll to position the inverse block on the
        right side of the box border to indicate where the current line is
        in the text.

****************************************************************************/

VOID Display() {
    USHORT usLine, i;

    usBottomLine = usInterior + selTable[usCurrent].usTopLine;
    if (usBottomLine > usTotalLines)
        usBottomLine = usTotalLines;

    VioScrollDn(BOXTOP + 1, BOXLEFT + 1, qhbBox.bottom - 1,
        BOXRIGHT - 1, usInterior + 1, achBlank, 0);
    for (i = 1, usLine = selTable[usCurrent].usTopLine;
            usLine <= usBottomLine; usLine++, i++)
        VioWrtCellStr(strTable[usLine].addr, strTable[usLine].cb,
            BOXTOP + i, BOXLEFT + 2, 0);
    if (selTable[usCurrent].usHighLight) {

        /* Before highlighting a line, read the entire line into a buffer
         * so that when the user is scrolling, the line can be restored with
         * the previous attributes.
         */

        VioReadCellStr(bHoldString, &cbHoldLength,
            selTable[usCurrent].usHighLight + 1,BOXLEFT + 1, 0);
        VioWrtNAttr(&bHiAtt, (BOXRIGHT - 1) - (BOXLEFT + 1),
            selTable[usCurrent].usHighLight + 1, BOXLEFT + 1, 0);
    }
    BoxScroll(&qhbBox, usTotalLines, selTable[usCurrent].usTopLine, atBOX);
}

/****************************************************************************

    FUNCTION:
        MouseRelease();

    PURPOSE: Waits for the release of the mouse button

****************************************************************************/

VOID MouseRelease() {
    USHORT usMouWait = 1;                /* Waits for a mouse event */

    do {
        MouReadEventQue(&mouevEvent, &usMouWait, hmou);
    }
    while (mouevEvent.fs > 1);   /* while a mouse button is pressed */
}

/****************************************************************************

    FUNCTION:
        isalpha(PCH, PCH, USHORT);

    PURPOSE: Returns TRUE if character is alphabetic

    COMMENTS:
        This function is defined here to avoid bringing in the C runtime.

****************************************************************************/

BOOL isalpha(chVal)
CHAR chVal;
{
    return ((chVal >= 'A' && chVal <= 'Z') ||
        (chVal >= 'a' && chVal <= 'z'));
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.