|
|
Microsoft OS/2 SDK 03-01-1988
/****************************************************************************
PROGRAM: Box.c
PURPOSE: Dynamic Link Library for drawing boxes on the screen
FUNCTIONS:
BoxSave() - Saves a rectangular area of the screen
BoxRestore() - Restores a rectangular area of the screen
BoxDraw() - Draws a box on the screen
BoxMessage() - Displays a message within a temporary box
BoxGetString() - Displays a box with a prompt, retrieves a string
BoxScroll() - Displays a vertical scroll bar
COMMENTS:
This group of functions provides an easy method for saving and
restoring a rectangular area of the screen. An application calls
BoxSave() to save the requested portion of the screen along with
the current cursor position and cursor type. It calls BoxDraw() to
create a border around the area that is saved and to clear the
interior and optionally change the attributes of the interior.
When that application completes display to the box, it calls
BoxRestore() to restore the screen, cursor position, and cursor
type. These functions may be called as many times as there is
memory to store the screen.
****************************************************************************/
#define INCL_BASE /* Includes all of the OS/2 base */
#include <os2.h> /* OS/2 include file */
#include "lqhdll.h"
INT _acrtused = 0; /* no C startup */
/****************************************************************************
FUNCTION: BoxSave(QHBOX FAR *);
PURPOSE: Saves a rectangular box on the screen
COMMENTS:
This function allocates enough memory to save the specified
rectangle of screen memory, the current cursor position, and the
currrent cursor type. It returns the selector to that memory, or
zero if it was unable to allocate the memory. The screen memory,
cursor position, and cursor type may be restored with a call to
BoxRestore().
****************************************************************************/
SEL FAR PASCAL BoxSave(qhbBox)
QHBOX FAR *qhbBox;
{
PCH pchBoxSave; /* pointer to memory */
SEL selBoxSave; /* selector to memory */
USHORT usRow; /* current row */
USHORT usLen; /* length of each row */
if (DosAllocSeg((((qhbBox->bottom + 1) - qhbBox->top) *
((qhbBox->right + 1) - qhbBox->left)) * 2 + 12,
(PSEL) &selBoxSave, 0))
return (0L);
pchBoxSave = MAKEP(selBoxSave, 0);
/* Save the current cursor position and cursor type */
VioGetCurType((PVIOCURSORINFO) pchBoxSave, 0);
VioGetCurPos(MAKEP(selBoxSave, 8), MAKEP(selBoxSave, 10), 0);
pchBoxSave += 12;
/* Save the screen by copying the screen cells into memory */
usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
VioReadCellStr(pchBoxSave, /* address of the buffer */
&usLen, /* length of the buffer */
usRow, /* starting row */
qhbBox->left, /* starting column */
0); /* Vio handle */
pchBoxSave += usLen;
}
return (selBoxSave); /* Returns selector to the saved screen data */
}
/****************************************************************************
FUNCTION: BoxRestore(QHBOX FAR *, SEL);
PURPOSE: Restores a rectangular area of the screen
COMMENTS:
This function restores the cursor position, the cursor typye, and
the area of the screen that was previously saved with a call to the
BoxSave() function. After the data is restored, it frees the
allocated memory.
****************************************************************************/
BOOL FAR PASCAL BoxRestore(qhbBox, selBoxSave)
QHBOX far *qhbBox;
SEL selBoxSave;
{
PCH pchBoxSave; /* pointer to memory */
USHORT usRow; /* current row */
USHORT usLen; /* length of each row */
PUSHORT pusCur;
pchBoxSave = MAKEP(selBoxSave, 0);
pusCur = MAKEP(selBoxSave, 8);
/* Restore the current cursor position and cursor type */
VioSetCurType((PVIOCURSORINFO) pchBoxSave, 0);
VioSetCurPos(*pusCur, *(pusCur + 1), 0);
pchBoxSave += 12;
/* Restore the screen */
usLen = ((qhbBox->right + 1) - qhbBox->left) * 2;
for (usRow = qhbBox->top; usRow <= qhbBox->bottom; usRow++) {
VioWrtCellStr(pchBoxSave, /* address of the buffer */
usLen, /* length of the buffer */
usRow, /* starting row */
qhbBox->left, /* starting column */
0); /* Vio handle */
pchBoxSave += usLen;
}
DosFreeSeg(selBoxSave); /* free the memory */
}
/****************************************************************************
FUNCTION: BoxDraw(QHBOX FAR *);
PURPOSE: Draws a rectangular box on the screen
COMMENTS:
This function is used to draw a box on the screen. All the
information that is needed to draw the box is placed in a QHBOX
structure, and the pointer to that structure is passed as the
parameter to this function. The QHBOX structure is defined as:
typedef struct _QHBOX {
USHORT top;
USHORT left;
USHORT bottom;
USHORT right;
INT FillAtt;
BYTE BorderAtt;
BYTE BoxType;
} QHBOX;
The qhbBox.FillAtt contains an attribute that will be combined with
a space to clear the interior of the box. If the attribute is -1,
the interior of the box is not cleared.
The attributes of the border are set by using the qhbBox.BorderAtt
parameter.
The type of border is specified in the qhbBox.BoxType parameter.
The value is in the range between 0 to 2.
0 - no border
1 - thin border
2 - thick border
Before calling BoxDraw(), an application should call BoxSave() if
it intends to restore the screen written to by the BoxDraw()
function.
****************************************************************************/
VOID FAR PASCAL BoxDraw(qhbBox)
QHBOX FAR *qhbBox; /* box dimensions */
{
INT i;
CHAR chCell[2], chBox[6];
switch(qhbBox->BoxType) {
case 1: /* thin border */
chBox[0] = 218; /* upper-left corner */
chBox[1] = 192; /* lower-left corner */
chBox[2] = 217; /* lower-right corner */
chBox[3] = 191; /* upper-right corner */
chBox[4] = 196; /* horizontal line */
chBox[5] = 179; /* vertical line */
break;
case 2: /* thick border */
chBox[0] = 201;
chBox[1] = 200;
chBox[2] = 188;
chBox[3] = 187;
chBox[4] = 205;
chBox[5] = 186;
break;
default: /* no border */
chBox[0] = chBox[1] = chBox[2] = chBox[3] =
chBox[4] = chBox[5] = ' ';
break;
}
chCell[1] = qhbBox->BorderAtt; /* Sets the border attribute */
chCell[0] = chBox[0]; /* Upper-left corner character */
/* display the four corners of the box */
VioWrtNCell(chCell, /* address of the cell */
1, /* number of times to write the cell */
qhbBox->top, /* starting row */
qhbBox->left, /* starting column */
0); /* Vio handle */
chCell[0] = chBox[1]; /* lower-left corner character */
VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->left, 0);
chCell[0] = chBox[2]; /* lower-right corner character */
VioWrtNCell(chCell, 1, qhbBox->bottom, qhbBox->right, 0);
chCell[0] = chBox[3]; /* upper-right corner character */
VioWrtNCell(chCell, 1, qhbBox->top, qhbBox->right, 0);
/* display the horizontal and vertical sides of the box */
chCell[0] = chBox[4]; /* horizontal-line character */
VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->top,
qhbBox->left + 1, 0);
VioWrtNCell(chCell, (qhbBox->right - qhbBox->left) - 1, qhbBox->bottom,
qhbBox->left + 1, 0);
chCell[0] = chBox[5]; /* vertical-line character */
for (i = qhbBox->top + 1; i < qhbBox->bottom; i++) {
VioWrtNCell(chCell, 1, i, qhbBox->left, 0);
VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
}
/* Clear the inside of the box by using spaces combined with the
* specified attribute.
*/
if (qhbBox->FillAtt != -1) { /* Does not clear if minus one */
chCell[1] = qhbBox->FillAtt;
chCell[0] = ' ';
VioScrollUp(qhbBox->top + 1, /* top row */
qhbBox->left + 1, /* left column */
qhbBox->bottom - 1, /* bottom row */
qhbBox->right - 1, /* right column */
(qhbBox->bottom - qhbBox->top) - 1, /* number of lines */
chCell, /* character-attribute cell */
0); /* Vio handle */
}
}
/****************************************************************************
FUNCTION: BoxMessage(PSZ, BYTE, BYTE, HMOU, BOOL);
PURPOSE: Displays an alert box with the PSZ message inside
COMMENTS:
This automatically saves the area of the screen that will be used
for the message box, creates the message box in the center of the
screen (with the message centered within the box), optionally
beeps, and waits for a key or mouse button to be pressed, and then
restores the portion of the screen used for the box.
A zero may be passed instead of the handle to the mouse device.
****************************************************************************/
VOID FAR PASCAL BoxMessage(pszMessage, bBorder, bType, hmou, bBell)
PSZ pszMessage; /* message to display */
BYTE bBorder; /* border and interior attribute */
BYTE bType; /* box line type */
HMOU hmou; /* handle to the current mouse */
BOOL bBell; /* TRUE to sound a warning tone */
{
KBDKEYINFO KbdKeyInfo; /* structure for key data */
MOUEVENTINFO MouInfo; /* mouse event packet structure */
QHBOX qhbBox; /* box dimensions */
SEL selBoxSave; /* selector to memory for screen save */
USHORT usMouNoWait = 0; /* Do not wait for mouse event */
if (Dstrlen(pszMessage) > 77)
pszMessage[77] = 0;
/* Set up the qhbBox structure */
qhbBox.top = 11;
qhbBox.bottom = 13;
qhbBox.left = (79 - Dstrlen(pszMessage)) / 2;
qhbBox.right = (79 - qhbBox.left) + 1;
qhbBox.BorderAtt = bBorder;
qhbBox.FillAtt = (int) bBorder;
qhbBox.BoxType = bType;
if (!(selBoxSave = BoxSave(&qhbBox))) /* Saves the screen */
return;
BoxDraw(&qhbBox); /* Draws the box */
VioWrtCharStr(pszMessage, Dstrlen(pszMessage), qhbBox.top + 1,
qhbBox.left + 1, 0); /* Writes the message */
if (bBell)
DosBeep(800, 200); /* Generates a beep */
do {
KbdCharIn(&KbdKeyInfo, /* buffer for data */
1, /* Does not wait */
0); /* keyboard handle */
if (hmou) {
MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
if (MouInfo.fs < 1 && MouInfo.Time) /* button release */
break;
}
}
while (!KbdKeyInfo.fbStatus);
BoxRestore(&qhbBox, selBoxSave); /* Restores the screen */
}
/****************************************************************************
FUNCTION: BoxGetString(PSZ, PSZ, USHORT, BYTE);
PURPOSE: Retrieves a string from the user
COMMENTS:
This function is used to retrieve a string from the user. It
displays a box wide enough to contain the prompt string and the
maximum size of the string buffer to retrieve. If the total exceeds
78 characters, then the interior of the box will contain two lines.
The first line contains the prompt string, and the second line is
used for the input string.
****************************************************************************/
BOOL FAR PASCAL BoxGetString(pszPrompt, pszDest, usMax, bAttrib, hmou)
PSZ pszPrompt; /* prompt string */
PSZ pszDest; /* destination buffer */
USHORT usMax; /* maximum string to retrieve */
BYTE bAttrib; /* box's attribute */
HMOU hmou; /* mouse handle */
{
KBDKEYINFO KbdKeyInfo; /* structure for key data */
MOUEVENTINFO MouInfo; /* mouse event packet structure */
VIOCURSORINFO CData; /* cursor data */
SEL selBoxSave;
QHBOX qhbBox; /* box dimensions */
USHORT usLine, usCol, usRow, usPos;
BOOL fLoop;
USHORT cbTotal, cbOutside, cbPrompt;
USHORT usMouNoWait = 0; /* Do not wait for mouse event */
cbPrompt = Dstrlen(pszPrompt);
cbTotal = cbPrompt + usMax;
cbOutside = (cbTotal < 78) ? (79 - (cbTotal + 2)) / 2 : 0;
usRow = (cbTotal < 78) ? 1 : 2;
if (usMax > 78)
usMax = 78;
qhbBox.top = 11;
qhbBox.bottom = qhbBox.top + usRow + 1;
qhbBox.left = cbOutside;
qhbBox.right = 79 - cbOutside;
qhbBox.BorderAtt = bAttrib;
qhbBox.FillAtt = bAttrib;
qhbBox.BoxType = 1;
if (!(selBoxSave = BoxSave(&qhbBox)))
return 0L;
BoxDraw(&qhbBox);
VioGetCurType(&CData, 0); /* Gets current cursor data */
CData.attr = 0x00; /* Sets attribute to normal */
VioSetCurType(&CData, 0);
VioWrtCharStr(pszPrompt, cbPrompt, qhbBox.top + 1,
qhbBox.left + 1, 0);
usCol = (usRow > 1) ? 0 : qhbBox.left + cbPrompt + 1;
usPos = 0;
for (fLoop = TRUE; fLoop;) {
VioSetCurPos(qhbBox.top + usRow, usCol + usPos + 1, 0);
do {
KbdCharIn(&KbdKeyInfo, /* address of buffer for keystroke */
IO_NOWAIT, /* wait/no-wait flag */
0); /* logical keyboard handle */
if (hmou) {
MouReadEventQue(&MouInfo, &usMouNoWait, hmou);
if (MouInfo.fs < 1 && MouInfo.Time) {
KbdKeyInfo.chChar = 27;
break;
}
}
}
while (!KbdKeyInfo.fbStatus);
switch(KbdKeyInfo.chChar) {
case 27: /* ESCAPE key */
BoxRestore(&qhbBox, selBoxSave);
return FALSE;
case '\r': /* ENTER key */
fLoop = FALSE;
pszDest[usPos] = 0;
if (!usPos) { /* nothing entered */
BoxRestore(&qhbBox, selBoxSave);
return FALSE;
}
break;
case 8: /* BACKSPACE key */
if (usPos) {
VioWrtNChar(" ", /* character */
1, /* number of characters */
qhbBox.top + usRow, /* row */
usCol + usPos, /* column */
0); /* Vio handle */
--usPos;
}
break;
default:
if (usPos >= usMax)
DosBeep(800, 200);
else {
pszDest[usPos++] = KbdKeyInfo.chChar;
VioWrtNChar(&KbdKeyInfo.chChar, 1, qhbBox.top + usRow,
usCol + usPos, 0);
}
break;
}
}
BoxRestore(&qhbBox, selBoxSave); /* Restores the screen */
return TRUE;
}
/****************************************************************************
FUNCTION: BoxScroll(QHBOX FAR *, USHORT, USHORT, BYTE);
PURPOSE: Displays scroll bar and current position
COMMENTS:
This function draws a scroll bar on the right side of the box
displayed by the BoxDraw() function. It places a marker within the
scroll bar to indicate the relative position of the text within the
box.
****************************************************************************/
VOID FAR PASCAL BoxScroll(qhbBox, usTotalLines, usCurLine, bAttib)
QHBOX FAR *qhbBox;
USHORT usTotalLines, usCurLine;
BYTE bAttib;
{
INT i;
USHORT usCount;
CHAR chCell[2];
USHORT cbBar;
chCell[1] = bAttib;
chCell[0] = 176; /* side-scroll character */
/* draw the side scroll bar */
for (i = qhbBox->top + 2; i < qhbBox->bottom - 1; i++) {
VioWrtNCell(chCell, 1, i, qhbBox->right, 0);
}
/* place arrows at the top and bottom */
chCell[0] = 24; /* upward arrow */
VioWrtNCell(chCell, 1, qhbBox->top + 1, qhbBox->right, 0);
chCell[0] = 25; /* downward arrow */
VioWrtNCell(chCell, 1, qhbBox->bottom - 1, qhbBox->right, 0);
/* Position the marker that indicates where the current line is
* relative to the total number of lines of text.
*/
chCell[0] = 178;
if (usCurLine > (usTotalLines - (qhbBox->bottom - qhbBox->top)) ||
usTotalLines < qhbBox->bottom)
usCount = qhbBox->bottom - 2;
else if (usCurLine == 1)
usCount = qhbBox->top + 2;
else {
cbBar = (qhbBox->bottom - qhbBox->top) - 3;
usCount = qhbBox->top + 2 +
((usCurLine * cbBar) / (usTotalLines - cbBar));
}
VioWrtNCell(chCell, 1, usCount, qhbBox->right, 0);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.