home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_GEN
/
FACETV.ZIP
/
BOXTOOLS.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-04
|
13KB
|
465 lines
/************************************************************************
**
** @(#)boxtools.cpp 06/03/93 Chris Ahlstrom
**
** C++ version.
**
** Helpful functions for announce.cpp and other modules.
** These functions determine good box sizes and coordinates, and
** provide non-class implementations of some simple annunciators.
**
*************************************************************************/
#define BOXTOOLS_cpp // inform this module's header file
#include "boxtools.h" // generic box tools on a small budget
/************************************************************************
** banner_size()
**
** Scans a string to determine the width (in characters) and the
** height (in lines) of the string, then generating the appropriate
** height and width for a box that matches the strings "dimensions".
**
** This function doesn't try to handle tabs, but does ignore
** non-printing characters.
**
** If a SCROLL_END character [boxtools.h] is encountered, this
** signals the premature end of the template string. This is useful
** when you have a field too long to fit in a window, so you have to
** use a scrollable inputline that's much shorter than the string.
**
*************************************************************************/
TPoint
banner_size
(
char *message,
int xpadding, // width padding
int ypadding // height padding
)
{
TPoint box;
int x = 0, y = 0; // the maximum width and height
if (message == NULL || message[0] == '\0')
{
x = BOX_WIDTH;
y = BOX_HEIGHT;
}
else
{
int w = 0; // width of the current line
unsigned ch; // the current character
int scroll_end = 0; // time to stop counting
unsigned char *msg; // don't want sign to be important
msg = (unsigned char *) message;
while (((ch = (unsigned) *msg++) != '\0') && !scroll_end)
{
switch (ch)
{
case '\n': // newline ends current width
case '\r': // treat \r like a newline
if (w > x)
x = w; // log the new longest width
w = 0; // start counting the next width
y++; // increment the height counter
break;
case '\t': // tab is counted like one space
w++;
break;
case SCROLL_END: // effective limit of box
scroll_end = 1;
break;
case '~': // to emulate TV's cstrlen() function
break; // ignore Turbo Vision hot-key markers
default: // change all the rest to a space
if (isprint(ch)) // if it is printable
w++; // log it as a space
break;
}
}
if (w > x) // in case there's no newline at end
x = w; // log the last longest width
if (y == 0) // in case no newline ever provided
y++;
else if (y > MAX_HEIGHT)
y = MAX_HEIGHT;
if (x == 0) // maybe all were nonprinting
x = BOX_WIDTH;
else if (x > MAX_WIDTH)
x = MAX_WIDTH;
}
box.x = x + xpadding;
box.y = y + ypadding; // add for spacing
return box;
}
/************************************************************************
** banner_list_size
**
** Takes a list of strings, and counts the number of strings
** and the length of the maximum string. Returns both in a TPoint
** structure.
**
** Padding can be added. For example, Turbo Vision RadioButtons
** need to have a box 3 characters wider than the length of the widest
** string.
**
** The last string in the list *must* be a NULL pointer.
**
** Very similar to banner size, but simpler, and acts on array
** of (hopefully) one-line strings.
**
*************************************************************************/
TPoint
banner_list_size
(
char *string[],
int xpadding, // width padding
int ypadding // height padding
)
{
TPoint boxsize;
int length;
int count = 0;
int width = 0;
if (string != NULL)
{
while (*string != NULL)
{
length = cstrlen(*string); // Turbo Vision string length
if (length > width)
width = length;
count++;
string++;
}
boxsize.x = width + xpadding;
boxsize.y = count + ypadding;
}
return boxsize;
}
/************************************************************************
** banner_spec()
**
** Given the dimensions of a string of text (how many lines and
** columns is the rectangle that just holds the text), this function
** then adds padding appropriate for a dialog box with a border around
** it, and a row of buttons for responses.
**
** The box is centered on the screen.
**
*************************************************************************/
TRect
banner_spec
(
TPoint textbox // dimensions of the text string
)
{
TRect banner;
int x, y;
x = textbox.x + 2 * BOX_MARGIN; // dialog width
y = textbox.y + BOX_TOP + OK_THICK + OK_BOTTOM + 1; // dialog height
banner.a.x = (SCREENWIDTH - x) / 2; // upper left
banner.a.y = (SCREENHEIGHT - y) / 2; // upper left
banner.b.x = banner.a.x + x; // lower right
banner.b.y = banner.a.y + y; // lower right
return banner;
}
/************************************************************************
** banner_OK()
**
** Yields the rectangle that TurboVision needs for holding a single
** "OK" button, centered near the bottom of the box. This functions
** assumes there is only one button, an OK button.
**
*************************************************************************/
TRect
banner_OK
(
TRect banner // dimensions of the dialog box
)
{
TRect button;
int x, y;
x = banner.b.x - banner.a.x; // width of the dialog
y = banner.b.y - banner.a.y; // height of the dialog
button.a.x = (x - OK_SIZE) / 2 - 1; // center button horizontally
button.a.y = y - OK_THICK - OK_BOTTOM; // up a little from bottom
button.b.x = button.a.x + OK_SIZE + 2; // right end of OK bar
button.b.y = button.a.y + OK_THICK; // allow for thickness of bar
return button;
}
/************************************************************************
** banner_OK_Cancel()
**
** Yields the rectangle that TurboVision needs for holding the
** first of two buttons centered near the bottom of the box: an OK
** button and a Cancel button. This function returns the values
** needed for only the OK button.
**
*************************************************************************/
TRect
banner_OK_Cancel
(
TRect banner // dimensions of the dialog box
)
{
TRect button;
int x, y;
x = banner.b.x - banner.a.x; // width of the dialog
y = banner.b.y - banner.a.y; // height of the dialog
button.a.x = (x - OK_LENGTH) / 2 - 1; // center bars horizontally
button.a.y = y - OK_THICK - OK_BOTTOM; // up a little from bottom
button.b.x = button.a.x + OK_SIZE + 2; // right end of OK bar
button.b.y = button.a.y + OK_THICK; // allow for thickness of bar
return button;
}
/************************************************************************
** banner_Cancel()
**
** Yields the rectangle that TurboVision needs for holding the
** second of two buttons centered near the bottom of the box: an OK
** button and a Cancel button. This function returns the values
** needed for only the Cancel button.
**
*************************************************************************/
TRect
banner_Cancel
(
TRect banner // dimensions of the dialog box
)
{
TRect button;
int x, y;
x = banner.b.x - banner.a.x; // width of the dialog
y = banner.b.y - banner.a.y; // height of the dialog
button.a.x = (x - OK_LENGTH) / 2 - 1; // center bars horizontally
button.a.y = y - OK_THICK - OK_BOTTOM; // up a little from bottom
button.b.x = button.a.x + OK_SIZE + 2; // right end of OK bar
button.b.y = button.a.y + OK_THICK; // allow for thickness of bar
button.a.x += OK_SIZE + OK_ADJUST; // move to Cancel's spot
button.b.x += OK_SIZE + OK_ADJUST; // move to Cancel's spot
return button;
}
/************************************************************************
** flashHandler()
**
** Similar to UserMessages::bannerHandler, but doesn't provide
** any means for the user to take down the box. Instead, closeBox()
** must do that, via the TDialog pointer that flashHandler()
** returns.
**
** Also, the user provides a convenient label and the location
** of the upper-left corner of the box.
**
** Also removed a few error-checks.
**
*************************************************************************/
#define XPAD 0 // no extra spacing needed for width
#define YPAD 1 // one extra space for height
TDialog *
flashHandler
(
TDeskTop *desktop, // where to display the box
int location_x, // the desired row to display it at
int location_y, // the desired column to display it at
char *message, // the pre-formatted string to display
char *label // a short label for the dialog box
)
{
TPoint banner; // calculated size of text box
TRect box; // calculated size of dialog box
int x, y; // temps for sizes
banner = banner_size(message, XPAD, YPAD); // size of box
box.a.x = location_x; // upper left
box.a.y = location_y; // upper left
x = banner.x + 2 * (BOX_MARGIN+BOX_EXCESS); // width
y = banner.y + BOX_TOP + BOX_BOTTOM; // height
box.b.x = box.a.x + x; // lower right
box.b.y = box.a.y + y; // lower right
TDialog *pd = new TDialog(box, label);
if (pd) // did it work above?
{
TRect text; // location and extent of text
text.a.x = BOX_MARGIN+BOX_EXCESS; // move to text boundary
text.a.y = BOX_TOP; // move to text line
text.b.x = banner.x; // width of the text
text.b.y = banner.y; // heigth of the text
text.b += text.a; // lower right corner of text
TView *b = new TStaticText(text, message);
if (b)
{
pd->insert(b); // display the text
}
desktop->insert(pd); // show the box
}
return pd;
}
/************************************************************************
** closeBox()
**
** Call this routine to get rid of (non-manually), one of the
** boxes created by the routine below.
**
** Note the use of a C++-style optional parameter. If given,
** the closeBox() function can delay for a given number of milliseconds
** before closing the box.
**
*************************************************************************/
TDialog *
closeBox
(
TDialog *pd, // pointer to the dialog
unsigned delay_ms // optional delay in milliseconds
)
{
if (delay_ms > 0)
delay(delay_ms);
if (pd)
{
TObject::destroy(pd); // call this static member function
pd = (TDialog *) 0;
}
return pd;
}
/************************************************************************
** intBox()
**
** A very simple box to display one number, an integer, and
** leave the number up on screen until it is closed by a call to
** closeBox().
**
*************************************************************************/
static char intString[16]; // workspace
TDialog *
intBox
(
TDeskTop *desktop, // where to display the box
int location_x, // the desired row to display it at
int location_y, // the desired column to display it at
char *string, // a short label for the dialog box
int value // the value to display
)
{
sprintf(intString, "%6d", value);
return flashHandler
(
desktop, location_x, location_y, intString, string
);
}
/************************************************************************
** floatBox
**
** A very simple box to display one number, an double, and
** leave the number up on screen until it is closed by a call to
** closeBox().
**
*************************************************************************/
static char fltString[32]; // workspace
TDialog *
floatBox
(
TDeskTop *desktop, // where to display the box
int location_x, // the desired row to display it at
int location_y, // the desired column to display it at
char *string, // a short label for the dialog box
double value // the value to display
)
{
sprintf(fltString, "%8.3f", value);
return flashHandler
(
desktop, location_x, location_y, fltString, string
);
}
/************************************************************************
** stringBox
**
** A very simple box to display one string, and to leave the string
** up on screen until it is closed by a call to closeBox().
** The width of the box is dictated by the length of the string.
**
*************************************************************************/
TDialog *
stringBox
(
TDeskTop *desktop, // where to display the box
int location_x, // the desired row to display it at
int location_y, // the desired column to display it at
char *string, // a short label for the dialog box
char *value // the string value to display
)
{
return flashHandler
(
desktop, location_x, location_y, value, string
);
}