File:  [OS/2 SDKs] / os2sdk / demos / apps / lqh / box.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: Box.c

    PURPOSE: Dynamic Link Library for drawing boxes on the screen

    FUNCTIONS:
        BoxSave() - Saves a rectangular area of the screen
        BoxRestore() - Restores a rectangular area of the screen
        BoxDraw() - Draws a box on the screen
        BoxMessage() - Displays a message within a temporary box
        BoxGetString() - Displays a box with a prompt, retrieves a string
        BoxScroll() - Displays a vertical scroll bar

    COMMENTS:
        This group of functions provides an easy method for saving and
        restoring a rectangular area of the screen. An application calls
        BoxSave() to save the requested portion of the screen along with
        the current cursor position and cursor type. It calls BoxDraw() to
        create a border around the area that is saved and to clear the
        interior and optionally change the attributes of the interior.
        When that application completes display to the box, it calls
        BoxRestore() to restore the screen, cursor position, and cursor
        type. These functions may be called as many times as there is
        memory to store the screen.

****************************************************************************/
#define INCL_BASE                  /* Includes all of the OS/2 base */

#include <os2.h>                               /* OS/2 include file */
#include "lqhdll.h"

INT _acrtused = 0;                             /* no C startup      */

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

    FUNCTION: BoxSave(QHBOX FAR *);

    PURPOSE: Saves a rectangular box on the screen

    COMMENTS:

        This function allocates enough memory to save the specified
        rectangle of screen memory, the current cursor position, and the
        currrent cursor type. It returns the selector to that memory, or
        zero if it was unable to allocate the memory. The screen memory,
        cursor position, and cursor type may be restored with a call to
        BoxRestore().

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

SEL FAR PASCAL BoxSave(qhbBox)
QHBOX FAR *qhbBox;
{
    PCH pchBoxSave;                   /* pointer to memory          */
    SEL selBoxSave;                   /* selector to memory         */
    USHORT usRow;                     /* current row                */
    USHORT usLen;                     /* length of each row         */

    if (DosAllocSeg((((qhbBox->bottom + 1) - qhbBox->top) *
            ((qhbBox->right + 1) - qhbBox->left)) * 2 + 12,
            (PSEL) &selBoxSave, 0))
        return (0L);
    pchBoxSave = MAKEP(selBoxSave, 0);

    /* Save the current cursor position and cursor type */

    VioGetCurType((PVIOCURSORINFO) pchBoxSave, 0);
    VioGetCurPos(MAKEP(selBoxSave, 8), MAKEP(selBoxSave, 10), 0);
    pchBoxSave += 12;

    /* Save the screen by copying the screen cells into memory */

    usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
    for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
        VioReadCellStr(pchBoxSave,         /* address of the buffer */
            &usLen,                        /* length of the buffer  */
            usRow,                         /* starting row          */
            qhbBox->left,                  /* starting column       */
            0);                            /* Vio handle            */
        pchBoxSave += usLen;
    }
    return (selBoxSave); /* Returns selector to the saved screen data */
}

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

    FUNCTION: BoxRestore(QHBOX FAR *, SEL);

    PURPOSE: Restores a rectangular area of the screen

    COMMENTS:

        This function restores the cursor position, the cursor typye, and
        the area of the screen that was previously saved with a call to the
        BoxSave() function. After the data is restored, it frees the
        allocated memory.

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

BOOL FAR PASCAL BoxRestore(qhbBox, selBoxSave)
QHBOX far *qhbBox;
SEL selBoxSave;
{
    PCH pchBoxSave;                   /* pointer to memory          */
    USHORT usRow;                     /* current row                */
    USHORT usLen;                     /* length of each row         */
    PUSHORT pusCur;

    pchBoxSave = MAKEP(selBoxSave, 0);
    pusCur = MAKEP(selBoxSave, 8);

    /* Restore the current cursor position and cursor type */

    VioSetCurType((PVIOCURSORINFO) pchBoxSave, 0);
    VioSetCurPos(*pusCur, *(pusCur + 1), 0);
    pchBoxSave += 12;

    /* Restore the screen */

    usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
    for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
        VioWrtCellStr(pchBoxSave,          /* address of the buffer */
            usLen,                         /* length of the buffer  */
            usRow,                         /* starting row          */
            qhbBox->left,                  /* starting column       */
            0);                            /* Vio handle            */
        pchBoxSave += usLen;
    }
    DosFreeSeg(selBoxSave);                      /* free the memory */
}

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

    FUNCTION: BoxDraw(QHBOX FAR *);

    PURPOSE: Draws a rectangular box on the screen

    COMMENTS:

        This function is used to draw a box on the screen. All the
        information that is needed to draw the box is placed in a QHBOX
        structure, and the pointer to that structure is passed as the
        parameter to this function. The QHBOX structure is defined as:

        typedef struct _QHBOX {
            USHORT top;
            USHORT left;
            USHORT bottom;
            USHORT right;
            INT FillAtt;
            BYTE BorderAtt;
            BYTE BoxType;
        } QHBOX;

        The qhbBox.FillAtt contains an attribute that will be combined with
        a space to clear the interior of the box. If the attribute is -1,
        the interior of the box is not cleared.

        The attributes of the border are set by using the qhbBox.BorderAtt
        parameter.

        The type of border is specified in the qhbBox.BoxType parameter.
        The value is in the range between 0 to 2.

            0 - no border
            1 - thin border
            2 - thick border

        Before calling BoxDraw(), an application should call BoxSave() if
        it intends to restore the screen written to by the BoxDraw()
        function.

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

VOID FAR PASCAL BoxDraw(qhbBox)
QHBOX FAR *qhbBox;                            /* box dimensions     */
{
    INT i;
    CHAR chCell[2], chBox[6];
    switch(qhbBox->BoxType) {
        case 1:                               /* thin border        */
            chBox[0] = 218;                   /* upper-left corner  */
            chBox[1] = 192;                   /* lower-left corner  */
            chBox[2] = 217;                   /* lower-right corner */
            chBox[3] = 191;                   /* upper-right corner */
            chBox[4] = 196;                   /* horizontal line    */
            chBox[5] = 179;                   /* vertical line      */
            break;

        case 2:                               /* thick border       */
            chBox[0] = 201;
            chBox[1] = 200;
            chBox[2] = 188;
            chBox[3] = 187;
            chBox[4] = 205;
            chBox[5] = 186;
            break;

        default:                                       /* no border */
            chBox[0] = chBox[1] = chBox[2] = chBox[3] =
                chBox[4] = chBox[5] = ' ';
            break;
    }

    chCell[1] = qhbBox->BorderAtt;   /* Sets the border attribute   */
    chCell[0] = chBox[0];            /* Upper-left corner character */

    /* display the four corners of the box */

    VioWrtNCell(chCell,        /* address of the cell               */
        1,                     /* number of times to write the cell */
        qhbBox->top,           /* starting row                      */
        qhbBox->left,          /* starting column                   */
        0);                    /* Vio handle                        */
    chCell[0] = chBox[1];      /* lower-left corner character       */
    VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->left, 0);
    chCell[0] = chBox[2];      /* lower-right corner character      */
    VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->right, 0);
    chCell[0] = chBox[3];      /* upper-right corner character      */
    VioWrtNCell(chCell, 1, qhbBox->top, qhbBox->right, 0);

    /* display the horizontal and vertical sides of the box */

    chCell[0] = chBox[4];              /* horizontal-line character */
    VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->top,
        qhbBox->left + 1, 0);
    VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->bottom,
        qhbBox->left + 1, 0);
    chCell[0] = chBox[5];                /* vertical-line character */
    for (i = qhbBox->top + 1; i < qhbBox->bottom; i++) {
        VioWrtNCell(chCell, 1, i, qhbBox->left, 0);
        VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
    }

    /* Clear the inside of the box by using spaces combined with the
     * specified attribute.
     */

    if (qhbBox->FillAtt != -1) {     /* Does not clear if minus one */
        chCell[1] = qhbBox->FillAtt;
        chCell[0] = ' ';
        VioScrollUp(qhbBox->top + 1,            /* top row          */
            qhbBox->left + 1,                   /* left column      */
            qhbBox->bottom - 1,                 /* bottom row       */
            qhbBox->right - 1,                  /* right column     */
            (qhbBox->bottom - qhbBox->top) - 1, /* number of lines  */
            chCell,                     /* character-attribute cell */
            0);                         /* Vio handle               */
    }
}


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

    FUNCTION: BoxMessage(PSZ, BYTE, BYTE, HMOU, BOOL);

    PURPOSE: Displays an alert box with the PSZ message inside

    COMMENTS:
        This automatically saves the area of the screen that will be used
        for the message box, creates the message box in the center of the
        screen (with the message centered within the box), optionally
        beeps, and waits for a key or mouse button to be pressed, and then
        restores the portion of the screen used for the box.

        A zero may be passed instead of the handle to the mouse device.

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

VOID FAR PASCAL BoxMessage(pszMessage, bBorder, bType, hmou, bBell)
PSZ pszMessage;                  /* message to display             */
BYTE bBorder;                    /* border and interior attribute  */
BYTE bType;                      /* box line type                  */
HMOU hmou;                       /* handle to the current mouse    */
BOOL bBell;                      /* TRUE to sound a warning tone   */
{
    KBDKEYINFO KbdKeyInfo;    /* structure for key data             */
    MOUEVENTINFO MouInfo;     /* mouse event packet structure       */
    QHBOX qhbBox;             /* box dimensions                     */
    SEL selBoxSave;           /* selector to memory for screen save */
    USHORT usMouNoWait = 0;   /* Do not wait for mouse event        */

    if (Dstrlen(pszMessage) > 77)
        pszMessage[77] = 0;

    /* Set up the qhbBox structure */

    qhbBox.top = 11;
    qhbBox.bottom = 13;
    qhbBox.left = (79 - Dstrlen(pszMessage)) / 2;
    qhbBox.right = (79 - qhbBox.left) + 1;
    qhbBox.BorderAtt = bBorder;
    qhbBox.FillAtt = (int) bBorder;
    qhbBox.BoxType = bType;

    if (!(selBoxSave = BoxSave(&qhbBox)))     /* Saves the screen   */
        return;
    BoxDraw(&qhbBox);                         /* Draws the box      */
    VioWrtCharStr(pszMessage, Dstrlen(pszMessage), qhbBox.top + 1,
        qhbBox.left + 1, 0);                  /* Writes the message */
    if (bBell)
        DosBeep(800, 200);                    /* Generates a beep   */
    do {
        KbdCharIn(&KbdKeyInfo,                /* buffer for data    */
            1,                                /* Does not wait      */
            0);                               /* keyboard handle    */
        if (hmou) {
            MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
            if (MouInfo.fs < 1 && MouInfo.Time) /* button release  */
                break;
        }
    }
    while (!KbdKeyInfo.fbStatus);
    BoxRestore(&qhbBox, selBoxSave);         /* Restores the screen */
}

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

    FUNCTION: BoxGetString(PSZ, PSZ, USHORT, BYTE);

    PURPOSE: Retrieves a string from the user

    COMMENTS:

        This function is used to retrieve a string from the user. It
        displays a box wide enough to contain the prompt string and the
        maximum size of the string buffer to retrieve. If the total exceeds
        78 characters, then the interior of the box will contain two lines.
        The first line contains the prompt string, and the second line is
        used for the input string.

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

BOOL FAR PASCAL BoxGetString(pszPrompt, pszDest, usMax, bAttrib, hmou)
PSZ pszPrompt;                        /* prompt string              */
PSZ pszDest;                          /* destination buffer         */
USHORT usMax;                         /* maximum string to retrieve */
BYTE bAttrib;                         /* box's attribute            */
HMOU hmou;                            /* mouse handle               */
{
    KBDKEYINFO KbdKeyInfo;          /* structure for key data       */
    MOUEVENTINFO MouInfo;           /* mouse event packet structure */
    VIOCURSORINFO CData;            /* cursor data                  */
    SEL selBoxSave;
    QHBOX qhbBox;                   /* box dimensions               */
    USHORT usLine, usCol, usRow, usPos;
    BOOL fLoop;
    USHORT cbTotal, cbOutside, cbPrompt;
    USHORT usMouNoWait = 0;         /* Do not wait for mouse event  */

    cbPrompt = Dstrlen(pszPrompt);
    cbTotal = cbPrompt + usMax;
    cbOutside = (cbTotal < 78) ? (79 - (cbTotal + 2)) / 2 : 0;
    usRow = (cbTotal < 78) ? 1 : 2;
    if (usMax > 78)
        usMax = 78;

    qhbBox.top = 11;
    qhbBox.bottom = qhbBox.top + usRow + 1;
    qhbBox.left = cbOutside;
    qhbBox.right = 79 - cbOutside;
    qhbBox.BorderAtt = bAttrib;
    qhbBox.FillAtt = bAttrib;
    qhbBox.BoxType = 1;

    if (!(selBoxSave = BoxSave(&qhbBox)))
        return 0L;
    BoxDraw(&qhbBox);
    VioGetCurType(&CData, 0);        /* Gets current cursor data */
    CData.attr = 0x00;               /* Sets attribute to normal */
    VioSetCurType(&CData, 0);
    VioWrtCharStr(pszPrompt, cbPrompt, qhbBox.top + 1,
        qhbBox.left + 1, 0);
    usCol = (usRow > 1) ? 0 : qhbBox.left + cbPrompt + 1;
    usPos = 0;

    for (fLoop = TRUE; fLoop;) {
        VioSetCurPos(qhbBox.top + usRow, usCol + usPos + 1, 0);
        do {
            KbdCharIn(&KbdKeyInfo, /* address of buffer for keystroke */
                IO_NOWAIT,               /* wait/no-wait flag       */
                0);                      /* logical keyboard handle */
            if (hmou) {
                MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
                if (MouInfo.fs < 1 && MouInfo.Time) {
                    KbdKeyInfo.chChar = 27;
                    break;
                }
            }
        }
        while (!KbdKeyInfo.fbStatus);

        switch(KbdKeyInfo.chChar) {
            case 27:                             /* ESCAPE key      */
                BoxRestore(&qhbBox, selBoxSave);
                return FALSE;

            case '\r':                           /* ENTER key       */
                fLoop = FALSE;
                pszDest[usPos] = 0;
                if (!usPos) {                    /* nothing entered */
                    BoxRestore(&qhbBox, selBoxSave);
                    return FALSE;
                }
                break;

            case 8:                              /* BACKSPACE key   */
                if (usPos) {
                    VioWrtNChar(" ",        /* character            */
                        1,                  /* number of characters */
                        qhbBox.top + usRow, /* row                  */
                        usCol + usPos,      /* column               */
                        0);                 /* Vio handle           */
                    --usPos;
                }
                break;

            default:
                if (usPos >= usMax)
                    DosBeep(800, 200);
                else {
                    pszDest[usPos++] = KbdKeyInfo.chChar;
                    VioWrtNChar(&KbdKeyInfo.chChar, 1, qhbBox.top + usRow,
                        usCol + usPos, 0);
                }
                break;
        }
    }

    BoxRestore(&qhbBox, selBoxSave);         /* Restores the screen */
    return TRUE;
}

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

    FUNCTION: BoxScroll(QHBOX FAR *, USHORT, USHORT, BYTE);

    PURPOSE: Displays scroll bar and current position

    COMMENTS:

        This function draws a scroll bar on the right side of the box
        displayed by the BoxDraw() function. It places a marker within the
        scroll bar to indicate the relative position of the text within the
        box.

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

VOID FAR PASCAL BoxScroll(qhbBox, usTotalLines, usCurLine, bAttib)
QHBOX FAR *qhbBox;
USHORT usTotalLines, usCurLine;
BYTE bAttib;
{
    INT i;
    USHORT usCount;
    CHAR chCell[2];
    USHORT cbBar;

    chCell[1] = bAttib;
    chCell[0] = 176;                       /* side-scroll character */

    /* draw the side scroll bar */

    for (i = qhbBox->top + 2; i < qhbBox->bottom - 1; i++) {
        VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
    }

    /* place arrows at the top and bottom */

    chCell[0] = 24;                                 /* upward arrow */
    VioWrtNCell(chCell, 1, qhbBox->top + 1, qhbBox->right, 0);
    chCell[0] = 25;                               /* downward arrow */
    VioWrtNCell(chCell, 1, qhbBox->bottom - 1, qhbBox->right, 0);

    /* Position the marker that indicates where the current line is
     * relative to the total number of lines of text.
     */

    chCell[0] = 178;
    if (usCurLine > (usTotalLines - (qhbBox->bottom - qhbBox->top)) ||
            usTotalLines < qhbBox->bottom)
        usCount = qhbBox->bottom - 2;
    else if (usCurLine == 1)
        usCount = qhbBox->top + 2;
    else {
        cbBar = (qhbBox->bottom - qhbBox->top) - 3;
        usCount = qhbBox->top + 2 +
            ((usCurLine * cbBar) / (usTotalLines - cbBar));
    }

    VioWrtNCell(chCell, 1, usCount, qhbBox->right, 0);
}

unix.superglobalmegacorp.com

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