|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.