home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / FACETV.ZIP / BOXTOOLS.CPP < prev    next >
C/C++ Source or Header  |  1994-01-04  |  13KB  |  465 lines

  1. /************************************************************************
  2. **
  3. ** @(#)boxtools.cpp        06/03/93    Chris Ahlstrom
  4. **
  5. **    C++ version.
  6. **
  7. **    Helpful functions for announce.cpp and other modules.
  8. ** These functions determine good box sizes and coordinates, and
  9. ** provide non-class implementations of some simple annunciators.
  10. **
  11. *************************************************************************/
  12.  
  13. #define BOXTOOLS_cpp        // inform this module's header file
  14.  
  15. #include "boxtools.h"        // generic box tools on a small budget
  16.  
  17.  
  18. /************************************************************************
  19. ** banner_size()
  20. **
  21. **    Scans a string to determine the width (in characters) and the
  22. ** height (in lines) of the string, then generating the appropriate
  23. ** height and width for a box that matches the strings "dimensions".
  24. **
  25. **    This function doesn't try to handle tabs, but does ignore
  26. ** non-printing characters.
  27. **
  28. **    If a SCROLL_END character [boxtools.h] is encountered, this
  29. ** signals the premature end of the template string.  This is useful
  30. ** when you have a field too long to fit in a window, so you have to
  31. ** use a scrollable inputline that's much shorter than the string.
  32. **
  33. *************************************************************************/
  34.  
  35. TPoint
  36. banner_size
  37. (
  38.     char *message,
  39.     int xpadding,            // width padding
  40.     int ypadding            // height padding
  41. )
  42. {
  43.     TPoint box;
  44.     int x = 0, y = 0;            // the maximum width and height
  45.  
  46.     if (message == NULL || message[0] == '\0')
  47.     {
  48.     x = BOX_WIDTH;
  49.     y = BOX_HEIGHT;
  50.     }
  51.     else
  52.     {
  53.     int w = 0;            // width of the current line
  54.     unsigned ch;            // the current character
  55.     int scroll_end = 0;        // time to stop counting
  56.     unsigned char *msg;        // don't want sign to be important
  57.  
  58.     msg = (unsigned char *) message;
  59.     while (((ch = (unsigned) *msg++) != '\0') && !scroll_end)
  60.     {
  61.         switch (ch)
  62.         {
  63.         case '\n':            // newline ends current width
  64.         case '\r':            // treat \r like a newline
  65.     
  66.         if (w > x)
  67.             x = w;        // log the new longest width
  68.         w = 0;            // start counting the next width
  69.         y++;            // increment the height counter
  70.         break;
  71.     
  72.         case '\t':            // tab is counted like one space
  73.  
  74.         w++;
  75.         break;
  76.  
  77.         case SCROLL_END:        // effective limit of box
  78.  
  79.         scroll_end = 1;
  80.         break;
  81.  
  82.         case '~':            // to emulate TV's cstrlen() function
  83.  
  84.         break;            // ignore Turbo Vision hot-key markers
  85.  
  86.         default:            // change all the rest to a space
  87.  
  88.         if (isprint(ch))    // if it is printable
  89.             w++;        // log it as a space
  90.         break;
  91.         }
  92.     }
  93.     if (w > x)            // in case there's no newline at end
  94.         x = w;            // log the last longest width
  95.     if (y == 0)            // in case no newline ever provided
  96.         y++;
  97.     else if (y > MAX_HEIGHT)
  98.         y = MAX_HEIGHT;
  99.     if (x == 0)            // maybe all were nonprinting
  100.         x = BOX_WIDTH;
  101.     else if (x > MAX_WIDTH)
  102.         x = MAX_WIDTH;
  103.     }
  104.     box.x = x + xpadding;
  105.     box.y = y + ypadding;        // add for spacing
  106.  
  107.     return box;
  108. }
  109.  
  110.  
  111. /************************************************************************
  112. ** banner_list_size
  113. **
  114. **    Takes a list of strings, and counts the number of strings
  115. ** and the length of the maximum string.  Returns both in a TPoint
  116. ** structure.
  117. **
  118. **    Padding can be added.  For example, Turbo Vision RadioButtons
  119. ** need to have a box 3 characters wider than the length of the widest
  120. ** string.
  121. **
  122. **    The last string in the list *must* be a NULL pointer.
  123. **
  124. **    Very similar to banner size, but simpler, and acts on array
  125. ** of (hopefully) one-line strings.
  126. **
  127. *************************************************************************/
  128.  
  129. TPoint
  130. banner_list_size
  131. (
  132.     char *string[],
  133.     int xpadding,            // width padding
  134.     int ypadding            // height padding
  135. )
  136. {
  137.     TPoint boxsize;
  138.     int length;
  139.     int count = 0;
  140.     int width = 0;
  141.  
  142.     if (string != NULL)
  143.     {
  144.     while (*string != NULL)
  145.     {
  146.         length = cstrlen(*string);    // Turbo Vision string length
  147.         if (length > width)
  148.         width = length;
  149.         count++;
  150.         string++;
  151.     }
  152.     boxsize.x = width + xpadding;
  153.     boxsize.y = count + ypadding;
  154.     }
  155.  
  156.     return boxsize;
  157. }
  158.  
  159.  
  160. /************************************************************************
  161. ** banner_spec()
  162. **
  163. **    Given the dimensions of a string of text (how many lines and
  164. ** columns is the rectangle that just holds the text), this function
  165. ** then adds padding appropriate for a dialog box with a border around
  166. ** it, and a row of buttons for responses.
  167. **
  168. **    The box is centered on the screen.
  169. **
  170. *************************************************************************/
  171.  
  172. TRect
  173. banner_spec
  174. (
  175.     TPoint textbox            // dimensions of the text string
  176. )
  177. {
  178.     TRect banner;
  179.     int x, y;
  180.  
  181.     x = textbox.x + 2 * BOX_MARGIN;            // dialog width
  182.     y = textbox.y + BOX_TOP + OK_THICK + OK_BOTTOM + 1;    // dialog height
  183.  
  184.     banner.a.x = (SCREENWIDTH  - x) / 2;        // upper left
  185.     banner.a.y = (SCREENHEIGHT - y) / 2;        // upper left
  186.  
  187.     banner.b.x = banner.a.x + x;            // lower right
  188.     banner.b.y = banner.a.y + y;            // lower right
  189.  
  190.     return banner;
  191. }
  192.  
  193.  
  194. /************************************************************************
  195. ** banner_OK()
  196. **
  197. **    Yields the rectangle that TurboVision needs for holding a single
  198. ** "OK" button, centered near the bottom of the box.  This functions
  199. ** assumes there is only one button, an OK button.
  200. **
  201. *************************************************************************/
  202.  
  203. TRect
  204. banner_OK
  205. (
  206.     TRect banner            // dimensions of the dialog box
  207. )
  208. {
  209.     TRect button;
  210.     int x, y;
  211.  
  212.     x = banner.b.x - banner.a.x;        // width of the dialog
  213.     y = banner.b.y - banner.a.y;        // height of the dialog
  214.     button.a.x = (x - OK_SIZE) / 2 - 1;        // center button horizontally
  215.     button.a.y = y - OK_THICK - OK_BOTTOM;    // up a little from bottom
  216.     button.b.x = button.a.x + OK_SIZE + 2;    // right end of OK bar
  217.     button.b.y = button.a.y + OK_THICK;        // allow for thickness of bar
  218.  
  219.     return button;
  220. }
  221.  
  222.  
  223. /************************************************************************
  224. ** banner_OK_Cancel()
  225. **
  226. **    Yields the rectangle that TurboVision needs for holding the
  227. ** first of two buttons centered near the bottom of the box: an OK
  228. ** button and a Cancel button.  This function returns the values
  229. ** needed for only the OK button.
  230. **
  231. *************************************************************************/
  232.  
  233. TRect
  234. banner_OK_Cancel
  235. (
  236.     TRect banner            // dimensions of the dialog box
  237. )
  238. {
  239.     TRect button;
  240.     int x, y;
  241.  
  242.     x = banner.b.x - banner.a.x;        // width of the dialog
  243.     y = banner.b.y - banner.a.y;        // height of the dialog
  244.     button.a.x = (x - OK_LENGTH) / 2 - 1;    // center bars horizontally
  245.     button.a.y = y - OK_THICK - OK_BOTTOM;    // up a little from bottom
  246.     button.b.x = button.a.x + OK_SIZE + 2;    // right end of OK bar
  247.     button.b.y = button.a.y + OK_THICK;        // allow for thickness of bar
  248.  
  249.     return button;
  250. }
  251.  
  252.  
  253. /************************************************************************
  254. ** banner_Cancel()
  255. **
  256. **    Yields the rectangle that TurboVision needs for holding the
  257. ** second of two buttons centered near the bottom of the box: an OK
  258. ** button and a Cancel button.  This function returns the values
  259. ** needed for only the Cancel button.
  260. **
  261. *************************************************************************/
  262.  
  263. TRect
  264. banner_Cancel
  265. (
  266.     TRect banner            // dimensions of the dialog box
  267. )
  268. {
  269.     TRect button;
  270.     int x, y;
  271.  
  272.     x = banner.b.x - banner.a.x;        // width of the dialog
  273.     y = banner.b.y - banner.a.y;        // height of the dialog
  274.     button.a.x = (x - OK_LENGTH) / 2 - 1;    // center bars horizontally
  275.     button.a.y = y - OK_THICK - OK_BOTTOM;    // up a little from bottom
  276.     button.b.x = button.a.x + OK_SIZE + 2;    // right end of OK bar
  277.     button.b.y = button.a.y + OK_THICK;        // allow for thickness of bar
  278.  
  279.     button.a.x += OK_SIZE + OK_ADJUST;        // move to Cancel's spot
  280.     button.b.x += OK_SIZE + OK_ADJUST;        // move to Cancel's spot
  281.  
  282.     return button;
  283. }
  284.  
  285.  
  286. /************************************************************************
  287. ** flashHandler()
  288. **
  289. **    Similar to UserMessages::bannerHandler, but doesn't provide
  290. ** any means for the user to take down the box.  Instead, closeBox()
  291. ** must do that, via the TDialog pointer that flashHandler()
  292. ** returns.
  293. **
  294. **    Also, the user provides a convenient label and the location
  295. ** of the upper-left corner of the box.
  296. **
  297. **    Also removed a few error-checks.
  298. **
  299. *************************************************************************/
  300.  
  301. #define XPAD    0        // no extra spacing needed for width
  302. #define YPAD    1        // one extra space for height
  303.  
  304.  
  305. TDialog *
  306. flashHandler
  307. (
  308.     TDeskTop *desktop,        // where to display the box
  309.     int location_x,        // the desired row to display it at
  310.     int location_y,        // the desired column to display it at
  311.     char *message,        // the pre-formatted string to display
  312.     char *label            // a short label for the dialog box
  313. )
  314. {
  315.     TPoint banner;        // calculated size of text box
  316.     TRect box;            // calculated size of dialog box
  317.     int x, y;            // temps for sizes
  318.  
  319.     banner    = banner_size(message, XPAD, YPAD);        // size of box
  320.  
  321.     box.a.x    = location_x;                    // upper left
  322.     box.a.y    = location_y;                    // upper left
  323.     x        = banner.x + 2 * (BOX_MARGIN+BOX_EXCESS);    // width
  324.     y        = banner.y + BOX_TOP + BOX_BOTTOM;        // height
  325.     box.b.x    = box.a.x + x;                    // lower right
  326.     box.b.y    = box.a.y + y;                    // lower right
  327.  
  328.     TDialog *pd = new TDialog(box, label);
  329.  
  330.     if (pd)                    // did it work above?
  331.     {
  332.     TRect text;                // location and extent of text
  333.  
  334.     text.a.x = BOX_MARGIN+BOX_EXCESS;    // move to text boundary
  335.     text.a.y = BOX_TOP;            // move to text line
  336.     text.b.x = banner.x;            // width of the text
  337.     text.b.y = banner.y;            // heigth of the text
  338.     text.b  += text.a;            // lower right corner of text
  339.  
  340.     TView *b = new TStaticText(text, message);
  341.     if (b)
  342.     {
  343.         pd->insert(b);            // display the text
  344.     }
  345.     desktop->insert(pd);            // show the box
  346.     }
  347.     return pd;
  348. }
  349.  
  350.  
  351. /************************************************************************
  352. ** closeBox()
  353. **
  354. **    Call this routine to get rid of (non-manually), one of the
  355. ** boxes created by the routine below.
  356. **
  357. **    Note the use of a C++-style optional parameter.  If given,
  358. ** the closeBox() function can delay for a given number of milliseconds
  359. ** before closing the box.
  360. **
  361. *************************************************************************/
  362.  
  363. TDialog *
  364. closeBox
  365. (
  366.     TDialog *pd,            // pointer to the dialog
  367.     unsigned delay_ms            // optional delay in milliseconds
  368. )
  369. {
  370.     if (delay_ms > 0)
  371.     delay(delay_ms);
  372.  
  373.     if (pd)
  374.     {
  375.     TObject::destroy(pd);        // call this static member function
  376.     pd = (TDialog *) 0;
  377.     }
  378.     return pd;
  379. }
  380.  
  381.  
  382. /************************************************************************
  383. ** intBox()
  384. **
  385. **    A very simple box to display one number, an integer, and
  386. ** leave the number up on screen until it is closed by a call to
  387. ** closeBox().
  388. **
  389. *************************************************************************/
  390.  
  391. static char intString[16];            // workspace
  392.  
  393. TDialog *
  394. intBox
  395. (
  396.     TDeskTop *desktop,        // where to display the box
  397.     int location_x,        // the desired row to display it at
  398.     int location_y,        // the desired column to display it at
  399.     char *string,        // a short label for the dialog box
  400.     int value            // the value to display
  401. )
  402. {
  403.     sprintf(intString, "%6d", value);
  404.     return flashHandler
  405.     (
  406.     desktop, location_x, location_y, intString, string
  407.     );
  408. }
  409.  
  410. /************************************************************************
  411. ** floatBox
  412. **
  413. **    A very simple box to display one number, an double, and
  414. ** leave the number up on screen until it is closed by a call to
  415. ** closeBox().
  416. **
  417. *************************************************************************/
  418.  
  419. static char fltString[32];            // workspace
  420.  
  421. TDialog *
  422. floatBox
  423. (
  424.     TDeskTop *desktop,        // where to display the box
  425.     int location_x,        // the desired row to display it at
  426.     int location_y,        // the desired column to display it at
  427.     char *string,        // a short label for the dialog box
  428.     double value        // the value to display
  429. )
  430. {
  431.     sprintf(fltString, "%8.3f", value);
  432.     return flashHandler
  433.     (
  434.     desktop, location_x, location_y, fltString, string
  435.     );
  436. }
  437.  
  438.  
  439. /************************************************************************
  440. ** stringBox
  441. **
  442. **    A very simple box to display one string, and to leave the string
  443. ** up on screen until it is closed by a call to closeBox().
  444. ** The width of the box is dictated by the length of the string.
  445. **
  446. *************************************************************************/
  447.  
  448. TDialog *
  449. stringBox
  450. (
  451.     TDeskTop *desktop,        // where to display the box
  452.     int location_x,        // the desired row to display it at
  453.     int location_y,        // the desired column to display it at
  454.     char *string,        // a short label for the dialog box
  455.     char *value            // the string value to display
  456. )
  457. {
  458.     return flashHandler
  459.     (
  460.     desktop, location_x, location_y, value, string
  461.     );
  462. }
  463.  
  464.  
  465.