Annotation of os2sdk/demos/apps/lqh/box.c, revision 1.1

1.1     ! root        1: /****************************************************************************
        !             2: 
        !             3:     PROGRAM: Box.c
        !             4: 
        !             5:     PURPOSE: Dynamic Link Library for drawing boxes on the screen
        !             6: 
        !             7:     FUNCTIONS:
        !             8:         BoxSave() - Saves a rectangular area of the screen
        !             9:         BoxRestore() - Restores a rectangular area of the screen
        !            10:         BoxDraw() - Draws a box on the screen
        !            11:         BoxMessage() - Displays a message within a temporary box
        !            12:         BoxGetString() - Displays a box with a prompt, retrieves a string
        !            13:         BoxScroll() - Displays a vertical scroll bar
        !            14: 
        !            15:     COMMENTS:
        !            16:         This group of functions provides an easy method for saving and
        !            17:         restoring a rectangular area of the screen. An application calls
        !            18:         BoxSave() to save the requested portion of the screen along with
        !            19:         the current cursor position and cursor type. It calls BoxDraw() to
        !            20:         create a border around the area that is saved and to clear the
        !            21:         interior and optionally change the attributes of the interior.
        !            22:         When that application completes display to the box, it calls
        !            23:         BoxRestore() to restore the screen, cursor position, and cursor
        !            24:         type. These functions may be called as many times as there is
        !            25:         memory to store the screen.
        !            26: 
        !            27: ****************************************************************************/
        !            28: #define INCL_BASE                  /* Includes all of the OS/2 base */
        !            29: 
        !            30: #include <os2.h>                               /* OS/2 include file */
        !            31: #include "lqhdll.h"
        !            32: 
        !            33: INT _acrtused = 0;                             /* no C startup      */
        !            34: 
        !            35: /****************************************************************************
        !            36: 
        !            37:     FUNCTION: BoxSave(QHBOX FAR *);
        !            38: 
        !            39:     PURPOSE: Saves a rectangular box on the screen
        !            40: 
        !            41:     COMMENTS:
        !            42: 
        !            43:         This function allocates enough memory to save the specified
        !            44:         rectangle of screen memory, the current cursor position, and the
        !            45:         currrent cursor type. It returns the selector to that memory, or
        !            46:         zero if it was unable to allocate the memory. The screen memory,
        !            47:         cursor position, and cursor type may be restored with a call to
        !            48:         BoxRestore().
        !            49: 
        !            50: ****************************************************************************/
        !            51: 
        !            52: SEL FAR PASCAL BoxSave(qhbBox)
        !            53: QHBOX FAR *qhbBox;
        !            54: {
        !            55:     PCH pchBoxSave;                   /* pointer to memory          */
        !            56:     SEL selBoxSave;                   /* selector to memory         */
        !            57:     USHORT usRow;                     /* current row                */
        !            58:     USHORT usLen;                     /* length of each row         */
        !            59: 
        !            60:     if (DosAllocSeg((((qhbBox->bottom + 1) - qhbBox->top) *
        !            61:             ((qhbBox->right + 1) - qhbBox->left)) * 2 + 12,
        !            62:             (PSEL) &selBoxSave, 0))
        !            63:         return (0L);
        !            64:     pchBoxSave = MAKEP(selBoxSave, 0);
        !            65: 
        !            66:     /* Save the current cursor position and cursor type */
        !            67: 
        !            68:     VioGetCurType((PVIOCURSORINFO) pchBoxSave, 0);
        !            69:     VioGetCurPos(MAKEP(selBoxSave, 8), MAKEP(selBoxSave, 10), 0);
        !            70:     pchBoxSave += 12;
        !            71: 
        !            72:     /* Save the screen by copying the screen cells into memory */
        !            73: 
        !            74:     usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
        !            75:     for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
        !            76:         VioReadCellStr(pchBoxSave,         /* address of the buffer */
        !            77:             &usLen,                        /* length of the buffer  */
        !            78:             usRow,                         /* starting row          */
        !            79:             qhbBox->left,                  /* starting column       */
        !            80:             0);                            /* Vio handle            */
        !            81:         pchBoxSave += usLen;
        !            82:     }
        !            83:     return (selBoxSave); /* Returns selector to the saved screen data */
        !            84: }
        !            85: 
        !            86: /****************************************************************************
        !            87: 
        !            88:     FUNCTION: BoxRestore(QHBOX FAR *, SEL);
        !            89: 
        !            90:     PURPOSE: Restores a rectangular area of the screen
        !            91: 
        !            92:     COMMENTS:
        !            93: 
        !            94:         This function restores the cursor position, the cursor typye, and
        !            95:         the area of the screen that was previously saved with a call to the
        !            96:         BoxSave() function. After the data is restored, it frees the
        !            97:         allocated memory.
        !            98: 
        !            99: ****************************************************************************/
        !           100: 
        !           101: BOOL FAR PASCAL BoxRestore(qhbBox, selBoxSave)
        !           102: QHBOX far *qhbBox;
        !           103: SEL selBoxSave;
        !           104: {
        !           105:     PCH pchBoxSave;                   /* pointer to memory          */
        !           106:     USHORT usRow;                     /* current row                */
        !           107:     USHORT usLen;                     /* length of each row         */
        !           108:     PUSHORT pusCur;
        !           109: 
        !           110:     pchBoxSave = MAKEP(selBoxSave, 0);
        !           111:     pusCur = MAKEP(selBoxSave, 8);
        !           112: 
        !           113:     /* Restore the current cursor position and cursor type */
        !           114: 
        !           115:     VioSetCurType((PVIOCURSORINFO) pchBoxSave, 0);
        !           116:     VioSetCurPos(*pusCur, *(pusCur + 1), 0);
        !           117:     pchBoxSave += 12;
        !           118: 
        !           119:     /* Restore the screen */
        !           120: 
        !           121:     usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
        !           122:     for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
        !           123:         VioWrtCellStr(pchBoxSave,          /* address of the buffer */
        !           124:             usLen,                         /* length of the buffer  */
        !           125:             usRow,                         /* starting row          */
        !           126:             qhbBox->left,                  /* starting column       */
        !           127:             0);                            /* Vio handle            */
        !           128:         pchBoxSave += usLen;
        !           129:     }
        !           130:     DosFreeSeg(selBoxSave);                      /* free the memory */
        !           131: }
        !           132: 
        !           133: /****************************************************************************
        !           134: 
        !           135:     FUNCTION: BoxDraw(QHBOX FAR *);
        !           136: 
        !           137:     PURPOSE: Draws a rectangular box on the screen
        !           138: 
        !           139:     COMMENTS:
        !           140: 
        !           141:         This function is used to draw a box on the screen. All the
        !           142:         information that is needed to draw the box is placed in a QHBOX
        !           143:         structure, and the pointer to that structure is passed as the
        !           144:         parameter to this function. The QHBOX structure is defined as:
        !           145: 
        !           146:         typedef struct _QHBOX {
        !           147:             USHORT top;
        !           148:             USHORT left;
        !           149:             USHORT bottom;
        !           150:             USHORT right;
        !           151:             INT FillAtt;
        !           152:             BYTE BorderAtt;
        !           153:             BYTE BoxType;
        !           154:         } QHBOX;
        !           155: 
        !           156:         The qhbBox.FillAtt contains an attribute that will be combined with
        !           157:         a space to clear the interior of the box. If the attribute is -1,
        !           158:         the interior of the box is not cleared.
        !           159: 
        !           160:         The attributes of the border are set by using the qhbBox.BorderAtt
        !           161:         parameter.
        !           162: 
        !           163:         The type of border is specified in the qhbBox.BoxType parameter.
        !           164:         The value is in the range between 0 to 2.
        !           165: 
        !           166:             0 - no border
        !           167:             1 - thin border
        !           168:             2 - thick border
        !           169: 
        !           170:         Before calling BoxDraw(), an application should call BoxSave() if
        !           171:         it intends to restore the screen written to by the BoxDraw()
        !           172:         function.
        !           173: 
        !           174: ****************************************************************************/
        !           175: 
        !           176: VOID FAR PASCAL BoxDraw(qhbBox)
        !           177: QHBOX FAR *qhbBox;                            /* box dimensions     */
        !           178: {
        !           179:     INT i;
        !           180:     CHAR chCell[2], chBox[6];
        !           181:     switch(qhbBox->BoxType) {
        !           182:         case 1:                               /* thin border        */
        !           183:             chBox[0] = 218;                   /* upper-left corner  */
        !           184:             chBox[1] = 192;                   /* lower-left corner  */
        !           185:             chBox[2] = 217;                   /* lower-right corner */
        !           186:             chBox[3] = 191;                   /* upper-right corner */
        !           187:             chBox[4] = 196;                   /* horizontal line    */
        !           188:             chBox[5] = 179;                   /* vertical line      */
        !           189:             break;
        !           190: 
        !           191:         case 2:                               /* thick border       */
        !           192:             chBox[0] = 201;
        !           193:             chBox[1] = 200;
        !           194:             chBox[2] = 188;
        !           195:             chBox[3] = 187;
        !           196:             chBox[4] = 205;
        !           197:             chBox[5] = 186;
        !           198:             break;
        !           199: 
        !           200:         default:                                       /* no border */
        !           201:             chBox[0] = chBox[1] = chBox[2] = chBox[3] =
        !           202:                 chBox[4] = chBox[5] = ' ';
        !           203:             break;
        !           204:     }
        !           205: 
        !           206:     chCell[1] = qhbBox->BorderAtt;   /* Sets the border attribute   */
        !           207:     chCell[0] = chBox[0];            /* Upper-left corner character */
        !           208: 
        !           209:     /* display the four corners of the box */
        !           210: 
        !           211:     VioWrtNCell(chCell,        /* address of the cell               */
        !           212:         1,                     /* number of times to write the cell */
        !           213:         qhbBox->top,           /* starting row                      */
        !           214:         qhbBox->left,          /* starting column                   */
        !           215:         0);                    /* Vio handle                        */
        !           216:     chCell[0] = chBox[1];      /* lower-left corner character       */
        !           217:     VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->left, 0);
        !           218:     chCell[0] = chBox[2];      /* lower-right corner character      */
        !           219:     VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->right, 0);
        !           220:     chCell[0] = chBox[3];      /* upper-right corner character      */
        !           221:     VioWrtNCell(chCell, 1, qhbBox->top, qhbBox->right, 0);
        !           222: 
        !           223:     /* display the horizontal and vertical sides of the box */
        !           224: 
        !           225:     chCell[0] = chBox[4];              /* horizontal-line character */
        !           226:     VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->top,
        !           227:         qhbBox->left + 1, 0);
        !           228:     VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->bottom,
        !           229:         qhbBox->left + 1, 0);
        !           230:     chCell[0] = chBox[5];                /* vertical-line character */
        !           231:     for (i = qhbBox->top + 1; i < qhbBox->bottom; i++) {
        !           232:         VioWrtNCell(chCell, 1, i, qhbBox->left, 0);
        !           233:         VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
        !           234:     }
        !           235: 
        !           236:     /* Clear the inside of the box by using spaces combined with the
        !           237:      * specified attribute.
        !           238:      */
        !           239: 
        !           240:     if (qhbBox->FillAtt != -1) {     /* Does not clear if minus one */
        !           241:         chCell[1] = qhbBox->FillAtt;
        !           242:         chCell[0] = ' ';
        !           243:         VioScrollUp(qhbBox->top + 1,            /* top row          */
        !           244:             qhbBox->left + 1,                   /* left column      */
        !           245:             qhbBox->bottom - 1,                 /* bottom row       */
        !           246:             qhbBox->right - 1,                  /* right column     */
        !           247:             (qhbBox->bottom - qhbBox->top) - 1, /* number of lines  */
        !           248:             chCell,                     /* character-attribute cell */
        !           249:             0);                         /* Vio handle               */
        !           250:     }
        !           251: }
        !           252: 
        !           253: 
        !           254: /****************************************************************************
        !           255: 
        !           256:     FUNCTION: BoxMessage(PSZ, BYTE, BYTE, HMOU, BOOL);
        !           257: 
        !           258:     PURPOSE: Displays an alert box with the PSZ message inside
        !           259: 
        !           260:     COMMENTS:
        !           261:         This automatically saves the area of the screen that will be used
        !           262:         for the message box, creates the message box in the center of the
        !           263:         screen (with the message centered within the box), optionally
        !           264:         beeps, and waits for a key or mouse button to be pressed, and then
        !           265:         restores the portion of the screen used for the box.
        !           266: 
        !           267:         A zero may be passed instead of the handle to the mouse device.
        !           268: 
        !           269: ****************************************************************************/
        !           270: 
        !           271: VOID FAR PASCAL BoxMessage(pszMessage, bBorder, bType, hmou, bBell)
        !           272: PSZ pszMessage;                  /* message to display             */
        !           273: BYTE bBorder;                    /* border and interior attribute  */
        !           274: BYTE bType;                      /* box line type                  */
        !           275: HMOU hmou;                       /* handle to the current mouse    */
        !           276: BOOL bBell;                      /* TRUE to sound a warning tone   */
        !           277: {
        !           278:     KBDKEYINFO KbdKeyInfo;    /* structure for key data             */
        !           279:     MOUEVENTINFO MouInfo;     /* mouse event packet structure       */
        !           280:     QHBOX qhbBox;             /* box dimensions                     */
        !           281:     SEL selBoxSave;           /* selector to memory for screen save */
        !           282:     USHORT usMouNoWait = 0;   /* Do not wait for mouse event        */
        !           283: 
        !           284:     if (Dstrlen(pszMessage) > 77)
        !           285:         pszMessage[77] = 0;
        !           286: 
        !           287:     /* Set up the qhbBox structure */
        !           288: 
        !           289:     qhbBox.top = 11;
        !           290:     qhbBox.bottom = 13;
        !           291:     qhbBox.left = (79 - Dstrlen(pszMessage)) / 2;
        !           292:     qhbBox.right = (79 - qhbBox.left) + 1;
        !           293:     qhbBox.BorderAtt = bBorder;
        !           294:     qhbBox.FillAtt = (int) bBorder;
        !           295:     qhbBox.BoxType = bType;
        !           296: 
        !           297:     if (!(selBoxSave = BoxSave(&qhbBox)))     /* Saves the screen   */
        !           298:         return;
        !           299:     BoxDraw(&qhbBox);                         /* Draws the box      */
        !           300:     VioWrtCharStr(pszMessage, Dstrlen(pszMessage), qhbBox.top + 1,
        !           301:         qhbBox.left + 1, 0);                  /* Writes the message */
        !           302:     if (bBell)
        !           303:         DosBeep(800, 200);                    /* Generates a beep   */
        !           304:     do {
        !           305:         KbdCharIn(&KbdKeyInfo,                /* buffer for data    */
        !           306:             1,                                /* Does not wait      */
        !           307:             0);                               /* keyboard handle    */
        !           308:         if (hmou) {
        !           309:             MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
        !           310:             if (MouInfo.fs < 1 && MouInfo.Time) /* button release  */
        !           311:                 break;
        !           312:         }
        !           313:     }
        !           314:     while (!KbdKeyInfo.fbStatus);
        !           315:     BoxRestore(&qhbBox, selBoxSave);         /* Restores the screen */
        !           316: }
        !           317: 
        !           318: /****************************************************************************
        !           319: 
        !           320:     FUNCTION: BoxGetString(PSZ, PSZ, USHORT, BYTE);
        !           321: 
        !           322:     PURPOSE: Retrieves a string from the user
        !           323: 
        !           324:     COMMENTS:
        !           325: 
        !           326:         This function is used to retrieve a string from the user. It
        !           327:         displays a box wide enough to contain the prompt string and the
        !           328:         maximum size of the string buffer to retrieve. If the total exceeds
        !           329:         78 characters, then the interior of the box will contain two lines.
        !           330:         The first line contains the prompt string, and the second line is
        !           331:         used for the input string.
        !           332: 
        !           333: ****************************************************************************/
        !           334: 
        !           335: BOOL FAR PASCAL BoxGetString(pszPrompt, pszDest, usMax, bAttrib, hmou)
        !           336: PSZ pszPrompt;                        /* prompt string              */
        !           337: PSZ pszDest;                          /* destination buffer         */
        !           338: USHORT usMax;                         /* maximum string to retrieve */
        !           339: BYTE bAttrib;                         /* box's attribute            */
        !           340: HMOU hmou;                            /* mouse handle               */
        !           341: {
        !           342:     KBDKEYINFO KbdKeyInfo;          /* structure for key data       */
        !           343:     MOUEVENTINFO MouInfo;           /* mouse event packet structure */
        !           344:     VIOCURSORINFO CData;            /* cursor data                  */
        !           345:     SEL selBoxSave;
        !           346:     QHBOX qhbBox;                   /* box dimensions               */
        !           347:     USHORT usLine, usCol, usRow, usPos;
        !           348:     BOOL fLoop;
        !           349:     USHORT cbTotal, cbOutside, cbPrompt;
        !           350:     USHORT usMouNoWait = 0;         /* Do not wait for mouse event  */
        !           351: 
        !           352:     cbPrompt = Dstrlen(pszPrompt);
        !           353:     cbTotal = cbPrompt + usMax;
        !           354:     cbOutside = (cbTotal < 78) ? (79 - (cbTotal + 2)) / 2 : 0;
        !           355:     usRow = (cbTotal < 78) ? 1 : 2;
        !           356:     if (usMax > 78)
        !           357:         usMax = 78;
        !           358: 
        !           359:     qhbBox.top = 11;
        !           360:     qhbBox.bottom = qhbBox.top + usRow + 1;
        !           361:     qhbBox.left = cbOutside;
        !           362:     qhbBox.right = 79 - cbOutside;
        !           363:     qhbBox.BorderAtt = bAttrib;
        !           364:     qhbBox.FillAtt = bAttrib;
        !           365:     qhbBox.BoxType = 1;
        !           366: 
        !           367:     if (!(selBoxSave = BoxSave(&qhbBox)))
        !           368:         return 0L;
        !           369:     BoxDraw(&qhbBox);
        !           370:     VioGetCurType(&CData, 0);        /* Gets current cursor data */
        !           371:     CData.attr = 0x00;               /* Sets attribute to normal */
        !           372:     VioSetCurType(&CData, 0);
        !           373:     VioWrtCharStr(pszPrompt, cbPrompt, qhbBox.top + 1,
        !           374:         qhbBox.left + 1, 0);
        !           375:     usCol = (usRow > 1) ? 0 : qhbBox.left + cbPrompt + 1;
        !           376:     usPos = 0;
        !           377: 
        !           378:     for (fLoop = TRUE; fLoop;) {
        !           379:         VioSetCurPos(qhbBox.top + usRow, usCol + usPos + 1, 0);
        !           380:         do {
        !           381:             KbdCharIn(&KbdKeyInfo, /* address of buffer for keystroke */
        !           382:                 IO_NOWAIT,               /* wait/no-wait flag       */
        !           383:                 0);                      /* logical keyboard handle */
        !           384:             if (hmou) {
        !           385:                 MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
        !           386:                 if (MouInfo.fs < 1 && MouInfo.Time) {
        !           387:                     KbdKeyInfo.chChar = 27;
        !           388:                     break;
        !           389:                 }
        !           390:             }
        !           391:         }
        !           392:         while (!KbdKeyInfo.fbStatus);
        !           393: 
        !           394:         switch(KbdKeyInfo.chChar) {
        !           395:             case 27:                             /* ESCAPE key      */
        !           396:                 BoxRestore(&qhbBox, selBoxSave);
        !           397:                 return FALSE;
        !           398: 
        !           399:             case '\r':                           /* ENTER key       */
        !           400:                 fLoop = FALSE;
        !           401:                 pszDest[usPos] = 0;
        !           402:                 if (!usPos) {                    /* nothing entered */
        !           403:                     BoxRestore(&qhbBox, selBoxSave);
        !           404:                     return FALSE;
        !           405:                 }
        !           406:                 break;
        !           407: 
        !           408:             case 8:                              /* BACKSPACE key   */
        !           409:                 if (usPos) {
        !           410:                     VioWrtNChar(" ",        /* character            */
        !           411:                         1,                  /* number of characters */
        !           412:                         qhbBox.top + usRow, /* row                  */
        !           413:                         usCol + usPos,      /* column               */
        !           414:                         0);                 /* Vio handle           */
        !           415:                     --usPos;
        !           416:                 }
        !           417:                 break;
        !           418: 
        !           419:             default:
        !           420:                 if (usPos >= usMax)
        !           421:                     DosBeep(800, 200);
        !           422:                 else {
        !           423:                     pszDest[usPos++] = KbdKeyInfo.chChar;
        !           424:                     VioWrtNChar(&KbdKeyInfo.chChar, 1, qhbBox.top + usRow,
        !           425:                         usCol + usPos, 0);
        !           426:                 }
        !           427:                 break;
        !           428:         }
        !           429:     }
        !           430: 
        !           431:     BoxRestore(&qhbBox, selBoxSave);         /* Restores the screen */
        !           432:     return TRUE;
        !           433: }
        !           434: 
        !           435: /****************************************************************************
        !           436: 
        !           437:     FUNCTION: BoxScroll(QHBOX FAR *, USHORT, USHORT, BYTE);
        !           438: 
        !           439:     PURPOSE: Displays scroll bar and current position
        !           440: 
        !           441:     COMMENTS:
        !           442: 
        !           443:         This function draws a scroll bar on the right side of the box
        !           444:         displayed by the BoxDraw() function. It places a marker within the
        !           445:         scroll bar to indicate the relative position of the text within the
        !           446:         box.
        !           447: 
        !           448: ****************************************************************************/
        !           449: 
        !           450: VOID FAR PASCAL BoxScroll(qhbBox, usTotalLines, usCurLine, bAttib)
        !           451: QHBOX FAR *qhbBox;
        !           452: USHORT usTotalLines, usCurLine;
        !           453: BYTE bAttib;
        !           454: {
        !           455:     INT i;
        !           456:     USHORT usCount;
        !           457:     CHAR chCell[2];
        !           458:     USHORT cbBar;
        !           459: 
        !           460:     chCell[1] = bAttib;
        !           461:     chCell[0] = 176;                       /* side-scroll character */
        !           462: 
        !           463:     /* draw the side scroll bar */
        !           464: 
        !           465:     for (i = qhbBox->top + 2; i < qhbBox->bottom - 1; i++) {
        !           466:         VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
        !           467:     }
        !           468: 
        !           469:     /* place arrows at the top and bottom */
        !           470: 
        !           471:     chCell[0] = 24;                                 /* upward arrow */
        !           472:     VioWrtNCell(chCell, 1, qhbBox->top + 1, qhbBox->right, 0);
        !           473:     chCell[0] = 25;                               /* downward arrow */
        !           474:     VioWrtNCell(chCell, 1, qhbBox->bottom - 1, qhbBox->right, 0);
        !           475: 
        !           476:     /* Position the marker that indicates where the current line is
        !           477:      * relative to the total number of lines of text.
        !           478:      */
        !           479: 
        !           480:     chCell[0] = 178;
        !           481:     if (usCurLine > (usTotalLines - (qhbBox->bottom - qhbBox->top)) ||
        !           482:             usTotalLines < qhbBox->bottom)
        !           483:         usCount = qhbBox->bottom - 2;
        !           484:     else if (usCurLine == 1)
        !           485:         usCount = qhbBox->top + 2;
        !           486:     else {
        !           487:         cbBar = (qhbBox->bottom - qhbBox->top) - 3;
        !           488:         usCount = qhbBox->top + 2 +
        !           489:             ((usCurLine * cbBar) / (usTotalLines - cbBar));
        !           490:     }
        !           491: 
        !           492:     VioWrtNCell(chCell, 1, usCount, qhbBox->right, 0);
        !           493: }

unix.superglobalmegacorp.com

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