|
|
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.