Annotation of os2sdk/demos/apps/lqh/box.c, revision 1.1.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.