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

  1. /************************************************************************
  2. **
  3. ** @(#)dlg_box.cpp    11/11/93    Chris Ahlstrom
  4. **
  5. **  ------------------------
  6. **  73340.26!compuserve.com
  7. **  ------------------------
  8. **
  9. **    Defines the DialogBox class.  This class is similar to the
  10. ** TBox class, but it is meant to be a base class for a single
  11. ** dialog box, not for a whole application.  Furthermore, it is meant
  12. ** to isolate the dialog box from the user interface, so that either
  13. ** Windows or TurboVision (DOS) modes can be supported with almost
  14. ** equal ease.  Finally, if possible, I will simplify the class
  15. ** a bit.
  16. **
  17. **    It provides all of the functionality of the DialogBox class, plus
  18. ** it includes support for new dialog box functions.
  19. **
  20. **    The DialogBox class will become the primary dialog boxes for
  21. ** all my C++ programs.  Lets almost all important parameters be set.
  22. **
  23. **    1.  A function called "doDialog()", that can read any old
  24. **        MainBox structure (see tv_menu.h), link it with a
  25. **        GenParameters structure, and display it all as a dialog
  26. **        box.
  27. **
  28. **    2.  A "GenParameters" structure pointer; it points to any
  29. **        kind of structure that contains data for a dialog box.
  30. **
  31. *************************************************************************/
  32.  
  33. /************************************************************************
  34. **
  35. ** For information on the slightly strange method used for coordinates,
  36. ** see pp. 94-95 of the Turbo Vision manual.  Here's a quick summary:
  37. **
  38. **    The UL (upper left) coordinate of a rectangle is as normal
  39. ** (e.g. [0,0] is the upper-left-most you can go).  But the LR (lower
  40. ** right is one higher than normal, so that the LR corner of a unit-sized
  41. ** box as far up and left as possible is [1,1], not [0,0].
  42. **
  43. **    Thus, the LR coordinate is given by
  44. **
  45. **        LR = UL + box_size
  46. **
  47. ** instead of by LR = UL + box_size - [1,1]
  48. **
  49. **    However, for the databoxes, we must add 2 characters to the
  50. ** x-dimension of the box, to allow for the two exta spaces at the
  51. ** left and right of the databox.  Otherwise, when the menu first comes
  52. ** up, only part of each field's data can be seen.
  53. **
  54. **    The primary dialog boxes for C++\TV programs for general purposes.
  55. ** It is very similar to dialgbox.cpp, with the following exceptions:
  56. **
  57. **    0.  The relevant dialog box is converted to user format for
  58. **        display.
  59. **
  60. **    1.  Also supports , UnsignedByte, Checkbyte, and Radiobyte
  61. **        data types.
  62. **
  63. **    2.  The following values are retrieved from a special list,
  64. **        when the correct Extended type is provided:
  65. **
  66. **        a.  minimum and maximum values
  67. **        b.  conversions between user units and machine (internal) units
  68. **        c.  the kind of dialog field to use.
  69. **        d.  display sizes
  70. **
  71. **    3.  Once read, and altered, the dialog box data is copied to
  72. **        the specified place, being transformed to machine units
  73. **        along the way.
  74. **
  75. **    Defines a base class to provide a single function.
  76. **
  77. **    1.  A function called "doDialog()", that can read any old
  78. **        MainBox structure (see tv_menu.h), link it with a
  79. **        genParameters structure, and display it all as a dialog
  80. **        box.
  81. **
  82. **    2.  A "genParameters" structure pointer; it points to any
  83. **        kind of structure that contains data for a dialog box.
  84. **
  85. **    3.  As part of the class, just one array of ExtendedDescriptors
  86. **        that describe data that will have a linear mapping applied
  87. **        to it before displaying, and the inverse linear mapping
  88. **        applied after editing.  (See the TINPUT modules.)
  89. **
  90. *************************************************************************/
  91.  
  92.  
  93. #define DLG_BOX_cpp
  94.  
  95. #include <stdio.h>
  96.  
  97. #include "boxtools.h"    // string box sizing
  98. #include "dlg_box.h"    // declarations of this class
  99. #include "tv_menu.h"    // the C++ version
  100. #include "tinput.h"    // "Variations on TInputLine in C++", Op. 2.01
  101. #include "tinpmous.h"    // "Variations on TInputLine in C++", Op. 3.03
  102.  
  103.  
  104. static MouseMap defaultMouseMap =
  105. {
  106.     LINEAR,
  107.     1000,
  108.     100,
  109.     NULL
  110. };
  111.  
  112.  
  113. /************************************************************************
  114. ** DialogBox constructors
  115. **
  116. **    We only need two versions of the constructor to support
  117. ** using either the ExtendedDescriptor, the MappedFieldDescriptor,
  118. ** none, or both.
  119. **
  120. *************************************************************************/
  121.  
  122. DialogBox::DialogBox
  123. (
  124.     MainBox *d,            // points to nested structure (tv_menu.h)
  125.     GeneralDialogData dialog,    // pointer to general dialog structure
  126.     int size,            // number of bytes in the data
  127.     TDeskTop *desk,
  128.     ExtendedDescriptor *datamapping,
  129.     MappedFieldDescriptor *fieldmapping
  130. ) :
  131.     dialogWindow    (d),
  132.     dialogData        (dialog),
  133.     boxTop        (desk),
  134.     dataMap        (datamapping),
  135.     useDataMap        (datamapping != NULL),
  136.     fieldMap        (fieldmapping),
  137.     useFieldMap        (fieldmapping != NULL),
  138.     dataSize        (size)
  139. {
  140.     if (useFieldMap)
  141.     mappedWindow    = (MappedBox *) dialogWindow;
  142. }
  143.  
  144.  
  145. DialogBox::DialogBox
  146. (
  147.     MainBox *d,            // points to nested structure (tv_menu.h)
  148.     GeneralDialogData dialog,    // pointer to general dialog structure
  149.     int size,            // number of bytes in the data
  150.     TDeskTop *desk,
  151.     MappedFieldDescriptor *fieldmapping
  152. ) :
  153.     dialogWindow    (d),
  154.     dialogData        (dialog),
  155.     boxTop        (desk),
  156.     dataMap        (NULL),
  157.     useDataMap        (0),
  158.     fieldMap        (fieldmapping),
  159.     useFieldMap     (fieldmapping != NULL),
  160.     dataSize        (size)
  161. {
  162.     if (useFieldMap)
  163.     mappedWindow    = (MappedBox *) dialogWindow;
  164. }
  165.  
  166.  
  167. DialogBox::~DialogBox ()
  168. {
  169. }
  170.  
  171.  
  172.  
  173. /************************************************************************
  174. ** DialogBox::doDialog
  175. **
  176. **    Takes an relatively complex data structure that describes
  177. ** a dialog box, and makes the Turbo Vision tree for that box.
  178. **
  179. **    Adding the radio boxes:  First we set up a linked list of all
  180. ** the labels that are provided elsewhere.  Then we make a radio-box
  181. ** using this list.  We work backwards, to maintain the desired linear
  182. ** appearance.
  183. **
  184. **    Returns True if the user edited the box and accepted the edit.
  185. ** (Note that OK does not become the default unless the box is edited,
  186. ** or the user Tabs to the OK box).
  187. **
  188. *************************************************************************/
  189.  
  190. Boolean
  191. DialogBox::doDialog (void)
  192. {
  193.     Boolean err = False;
  194.     Boolean rcode = False;
  195.  
  196.     /*********************************************************************
  197.     ** Create the box part of the dialog.
  198.     **********************************************************************/
  199.  
  200.     TPoint ul = dialogWindow->box.location;    // location of dialog
  201.     TPoint lr = dialogWindow->box.size;        // size of dialog
  202.     lr += ul;                    // boundaries of dialog
  203.  
  204.     TDialog *pd = new TDialog(TRect(ul,lr), dialogWindow->box.title);
  205.  
  206.     /*********************************************************************
  207.     ** Add elements inside the box.  First, scan the list of data-items.
  208.     ** For each one, determine its type (e.g. numeric or Radiobox),
  209.     ** and insert it.  Then tack on the "OK/cancel" buttons.
  210.     **********************************************************************/
  211.  
  212.     if (pd)                    // did it work above?
  213.     {
  214.     MenuField *field = dialogWindow->fields; // point to first field
  215.     TView *b;                // general-purpose pointer
  216.  
  217.     for (int f = 0; f < dialogWindow->fieldcount; f++, field++)
  218.     {
  219.         TextLabel *lab = &field->label;    // label structure in field
  220.         TextData  *dat = &field->data;    // data structure in field
  221.  
  222.         DataType data_type    = dat->datatype;    // primary data type
  223.         char *dtmplate    = dat->dtmplate;    // string for template
  224.         char *format    = dat->format;        // format for display
  225.  
  226.         /************************************************************
  227.         ** Obtain the kind of "spec" to use, based on data type.
  228.         ** Note that the little group of declarations below provides
  229.         ** one declaration for each member of the TextDataSpec
  230.         ** union defined in tv_menu.h.
  231.         *************************************************************/
  232.  
  233.         char **strings    = NULL;
  234.         ExtendedField dtype    = BOGUS_EXTENDED_FIELD;
  235.         MouseMap *map    = NULL;
  236.  
  237.         if (isBox(data_type))
  238.         {
  239.         strings = dat->spec.strings;    // strings for display
  240.         }
  241.         else if (isControl(data_type))
  242.         {
  243.         map = dat->spec.ctrlmap;    // mouse/key mapping
  244.         }
  245.         else if (isExtended(data_type))
  246.         {
  247.         dtype = dat->spec.dtype;    // extension of int, etc?
  248.         }
  249.  
  250.         /************************************************************
  251.         ** If the data type is Extended, then we must get a little
  252.         ** more information from a ExtendedDescriptor list.
  253.         ** Right now, the only information we get is the fundamental
  254.         ** data type and the user's range.  If something is screwy,
  255.         ** we can only skip this field.
  256.         *************************************************************/
  257.  
  258.         Range user;
  259.         Range code;
  260.         int mapped;
  261.  
  262.         code.minimum = dat->code.minimum;
  263.         code.maximum = dat->code.maximum;
  264.         user     = code;            // in case of screwups
  265.  
  266.         if (isExtended(data_type))
  267.         {
  268.         if (useDataMap)
  269.         {
  270.             if (dataMap[dtype].type == dtype)    // consistent?
  271.             {
  272.             user        = dataMap[dtype].user;
  273.             data_type    = dataMap[dtype].datatype;
  274.             mapped        = TINPUT_EXTENDED;
  275.             }
  276.             else                // inconsistent!
  277.             break;                // don't bother
  278.         }
  279.         else
  280.             break;                // don't bother
  281.         }
  282.         else
  283.         {
  284.         mapped = TINPUT_NO_EXTENDED;
  285.         }
  286.  
  287.         /************************************************************
  288.         ** For data, use the length of the template string (or
  289.         ** strings, in the case of Box/Button items) provided,
  290.         ** plus 2 extra characters for the scroll arrows, if needed.
  291.         ** The length of the data-item must be exact, or weird
  292.         ** things happen in the bowels of TInputLine.
  293.         ** Selecting all these numbers became quite an art!!!
  294.         *************************************************************/
  295.  
  296.         TPoint dsz;                // adjusted entry-box size
  297.         int maxlength;            // maxLen for TInputLine(s)
  298.  
  299.         if (isBox(data_type))
  300.         {
  301.         dsz = banner_list_size        // templates of sorts
  302.         (
  303.             strings, RADIOBUTTON_PAD
  304.         );
  305.         maxlength = 0;            // unused for box data
  306.         }
  307.         else if (isString(data_type))
  308.         {
  309.         dsz = banner_size(dtmplate, SCROLLARROW_PAD);
  310.         maxlength = strlen(dtmplate) + SCROLLARROW_PAD - 1;
  311.         }
  312.         else if (isNumeric(data_type))
  313.         {
  314.         dsz = banner_size(dtmplate, SCROLLARROW_PAD);
  315.         maxlength = dsz.x;        // buffer size
  316.         }
  317.  
  318.         /************************************************************
  319.         ** Insert current data-item inside the dialog box,
  320.         ** relative to its label (we'll insert that later).
  321.         ** Obtain label's dimensions by inspection, to make
  322.         ** it easier on the poor programmer.
  323.         *************************************************************/
  324.  
  325.         TPoint lul = lab->location;        // label location
  326.         TPoint llr;                // size/corner of data label
  327.         TPoint dul = dat->location;        // data offset
  328.         TPoint dlr;                // adjusted data size
  329.  
  330.         llr = banner_size(lab->string, LABEL_PAD);    // size with padding
  331.         llr  += lul;                // lower-right corner
  332.  
  333.         dul  += lul;            // move it relative to label
  334.         dlr   = dsz + dul;            // get lower-right corner
  335.         dlr.x++;                // allow proper viewing
  336.  
  337.         b = makeField
  338.         (
  339.         data_type, strings, dul, dlr, maxlength,
  340.         code, format, mapped, user, *map
  341.         );
  342.  
  343.         if (b)
  344.         {
  345.         pd->insert(b);            // insert the databox
  346.  
  347.         if
  348.         (
  349.             lab->string != NULL &&    // no string given?
  350.             *lab->string != '\0'    // empty string given?
  351.         )
  352.         {
  353.             TView *c = new TLabel(TRect(lul, llr), lab->string, b);
  354.             if (c)
  355.             pd->insert(c);        // insert the label
  356.         }
  357.         }
  358.         else
  359.         {
  360.         err = True;
  361.         break;
  362.         }
  363.     }
  364.     if (err != True)
  365.     {
  366.         buttonsOKCancel            // insert OK/Cancel buttons
  367.         (
  368.         pd, dialogWindow->box.size
  369.         );
  370.  
  371.         if (dialogWindow->box.string != NULL)
  372.         {
  373.         ul = dialogWindow->box.labelloc;    // Insert main string
  374.         lr.x = strlen(dialogWindow->box.string) + 1;
  375.         lr.y = 1;
  376.         lr += ul;
  377.         TView *b = new TStaticText
  378.         (
  379.             TRect(ul, lr), dialogWindow->box.string
  380.         );
  381.         if (b)
  382.             pd->insert(b);
  383.         }
  384.  
  385.         /************************************************************
  386.         ** Save the dialog data and read it back when the dialog box
  387.         ** is successfully closed.  The setData() member of all
  388.         ** sub-objects gets called (deep inside Turbo Vision).
  389.         *************************************************************/
  390.  
  391.         pd->setData(dialogData);        // fill in data boxes
  392.         ushort control = boxTop->execView(pd);
  393.         if (control != cmCancel)
  394.         {
  395.         pd->getData(dialogData);    // obtain data from data boxes
  396.         rcode = True;
  397.         }
  398.     }
  399.     else
  400.     {
  401.         TView *b = new TStaticText(TRect(4,4,16,5), "DIALOG ERROR");
  402.         if (b)
  403.         pd->insert(b);
  404.         boxTop->execView(pd);
  405.     }
  406.     TObject::destroy(pd);                // remove the box now
  407.     }
  408.     return rcode;
  409. }
  410.  
  411.  
  412. /************************************************************************
  413. ** mappedDialog()
  414. **
  415. **    Takes an relatively complex data structure that describes
  416. ** a dialog box, and makes the Turbo Vision tree for that box.
  417. **
  418. **    Adding the radio boxes:  First we set up a linked list of all
  419. ** the labels that are provided elsewhere.  Then we make a radio-box
  420. ** using this list.  We work backwards, to maintain the desired linear
  421. ** appearance.
  422. **
  423. **    It's really the same as doDialog(), but gets the same information
  424. ** from different place (places!)
  425. **
  426. *************************************************************************/
  427.  
  428. Boolean
  429. DialogBox::mappedDialog ()
  430. {
  431.     Boolean err        = False;
  432.     Boolean rcode    = False;
  433.  
  434.     /*********************************************************************
  435.     ** Create the box part of the dialog.
  436.     **********************************************************************/
  437.  
  438.     TPoint ul = dialogWindow->box.location;    // location of dialog
  439.     TPoint lr = dialogWindow->box.size;        // size of dialog
  440.     lr += ul;                    // boundaries of dialog
  441.     TDialog *pd = new TDialog(TRect(ul,lr), dialogWindow->box.title);
  442.  
  443.     /*********************************************************************
  444.     ** Add elements inside the box.  First, scan the list of data-items.
  445.     ** For each one, determine its type (e.g. numeric or Radiobox),
  446.     ** and insert it.  Then tack on the "OK/cancel" buttons.
  447.     **********************************************************************/
  448.  
  449.     if (pd)                    // did it work above?
  450.     {
  451.     MappedField *field = mappedWindow->fields; // point to first field
  452.     TView *b;                // general-purpose pointer
  453.  
  454.     for (int f = 0; f < mappedWindow->fieldcount; f++, field++)
  455.     {
  456.         /************************************************************
  457.         ** Unlike for doDialog(), the data here is always mapped.
  458.         ** mappedDialog() always inspects the desired data-type to
  459.         ** get the information that describes the data field.
  460.         *************************************************************/
  461.  
  462.         int mapped = TINPUT_NO_EXTENDED;    // assume the worst at first
  463.         Range user;                // range of user-viewed units
  464.         Range code;                // range of internal units
  465.         DataType data_type;            // type of data (e.g. Integer)
  466.         char *dtmplate;            // data template string
  467.         char *format;            // data format for display
  468.         char **strings;            // list of items for boxes
  469.  
  470.         if (useFieldMap)
  471.         {
  472.         MappedFieldDescriptor *map;    // data-type description
  473.  
  474.         map = &fieldMap[field->dtype];
  475.         if (map->type == field->dtype)
  476.         {
  477.             mapped    = TINPUT_EXTENDED;
  478.             data_type    = map->datatype;
  479.             code    = map->code;
  480.             user    = map->user;
  481.             dtmplate    = map->dtmplate;
  482.             format    = map->format;
  483.             strings    = map->strings;
  484.         }
  485.         else                // disordered mapping-list
  486.             break;            // don't show the field
  487.         }
  488.         else                // no mapping-list provided
  489.         break;                // don't show the field
  490.  
  491.         /************************************************************
  492.         ** For data, use the length of the template string (or
  493.         ** strings, in the case of Box/Button items) provided,
  494.         ** plus 2 extra characters for the scroll arrows, if needed.
  495.         *************************************************************/
  496.  
  497.         TPoint dsz;                // adjusted entry-box size
  498.         int maxlength;            // maxLen for TInputLine(s)
  499.  
  500.         dsz.x = 1;                // bogus size in case of...
  501.         dsz.y = 1;                // ...problems
  502.         if (isBox(data_type))
  503.         {
  504.         if (strings != NULL)
  505.         {
  506.             dsz = banner_list_size    // templates of sorts
  507.             (
  508.             strings, RADIOBUTTON_PAD
  509.             );
  510.         }
  511.         maxlength = 0;                // unused for box data
  512.         }
  513.         else if (isString(data_type))
  514.         {
  515.         if (dtmplate != NULL)
  516.         {
  517.             dsz.x = strlen(dtmplate) + SCROLLARROW_PAD;
  518.             dsz.y = 1;                // strong assumption!
  519.             maxlength = dsz.x - 1;        // includes 1 null
  520.         }
  521.         else
  522.         {
  523.             maxlength = dsz.x;            // includes 1 null
  524.         }
  525.         }
  526.         else if (isNumeric(data_type))
  527.         {
  528.         if (dtmplate != NULL)
  529.         {
  530.             dsz.x = strlen(dtmplate) + SCROLLARROW_PAD;
  531.             dsz.y = 1;                // strong assumption!
  532.         }
  533.         maxlength = dsz.x;            // buffer size
  534.         }
  535.  
  536.         /************************************************************
  537.         ** Insert the current data-item inside the dialog box,
  538.         ** relative to its label (we'll insert that later).
  539.         ** Obtain the label's dimensions by inspection, to make
  540.         ** it easier on the poor programmer.
  541.         *************************************************************/
  542.  
  543.         TPoint lul = field->label_location;    // label location
  544.         TPoint llr;                // size of data label
  545.         TPoint dul = field->data_location;    // data offset
  546.         TPoint dlr;                // adjusted data size
  547.  
  548.         llr.x = (int) strlen(field->label_string) + LABEL_PAD;
  549.         llr.y = 1;
  550.         llr  += lul;            // lower-right corner
  551.  
  552.         dul  += lul;            // move it relative to label
  553.         dlr   = dsz + dul;            // get lower-right corner
  554.         dlr.x++;                // allow proper viewing
  555.  
  556.         b = makeField
  557.         (
  558.         data_type, strings, dul, dlr, maxlength,
  559.         code, format, mapped, user, defaultMouseMap
  560.         );
  561.  
  562.         if (b)
  563.         {
  564.         pd->insert(b);            // insert the databox
  565.  
  566.         if
  567.         (
  568.             field->label_string != NULL &&    // no string?
  569.             *field->label_string != '\0'    // empty string?
  570.         )
  571.         {
  572.             TView *c = new TLabel
  573.             (
  574.             TRect(lul, llr), field->label_string, b
  575.             );
  576.             if (c)
  577.             pd->insert(c);        // insert the label
  578.         }
  579.         }
  580.         else
  581.         {
  582.         err = True;
  583.         break;
  584.         }
  585.     }
  586.     if (err != True)
  587.     {
  588.         buttonsOKCancel            // insert OK/Cancel buttons
  589.         (
  590.         pd, mappedWindow->box.size
  591.         );
  592.  
  593.         if (mappedWindow->box.string != NULL)    // insert main string
  594.         {
  595.         ul = mappedWindow->box.labelloc;
  596.         lr.x = strlen(mappedWindow->box.string) + 1;
  597.         lr.y = 1;
  598.         lr += ul;
  599.         TView *b = new TStaticText
  600.         (
  601.             TRect(ul, lr), mappedWindow->box.string
  602.         );
  603.         if (b)
  604.             pd->insert(b);
  605.         }
  606.  
  607.         /************************************************************
  608.         ** Save the dialog data and read it back when the dialog box
  609.         ** is successfully closed.
  610.         *************************************************************/
  611.  
  612.         pd->setData(dialogData);
  613.         ushort control = boxTop->execView(pd);
  614.         if (control != cmCancel)
  615.         {
  616.         pd->getData(dialogData);
  617.         rcode = True;
  618.         }
  619.     }
  620.     else
  621.     {
  622.         TView *b = new TStaticText(TRect(4,4,16,5), "DIALOG ERROR");
  623.         if (b)
  624.         pd->insert(b);
  625.         boxTop->execView(pd);
  626.     }
  627.     TObject::destroy(pd);                // remove the box now
  628.     }
  629.     return rcode;
  630. }
  631.  
  632.  
  633. /************************************************************************
  634. ** DialogBox::makeField()
  635. **
  636. **    Determines the type of data-field display item to make, and
  637. ** makes it.  Returns a pointer to it.
  638. **
  639. *************************************************************************/
  640.  
  641. TView *
  642. DialogBox::makeField
  643. (
  644.     DataType data_type,    // exact type of data item
  645.     char **strings,    // pointer to list of button-strings
  646.     TPoint dul,        // upper-left corner of the box
  647.     TPoint dlr,        // lower-right corner of the box
  648.     int maxlength,    // for TInputLine(s)
  649.     Range& code,    // internal range of the units
  650.     char *format,    // format of the display
  651.     int mapped,        // non-zero if data mapping is to be employed
  652.     Range& user,    // user-viewable range of the units
  653.     MouseMap &map    // how the mouse and arrows will be mapped
  654. )
  655. {
  656.     TView *b;
  657.  
  658.     switch (data_type)            // create the databox
  659.     {
  660.     case Checkbox:
  661.     case Radiobox:
  662.     case Checkbyte:
  663.     case Radiobyte:
  664.  
  665.     b = makeButtons(data_type, strings, dul, dlr);
  666.     break;
  667.  
  668.     case UnsignedByte:
  669.  
  670.     b = new TInputByte
  671.     (
  672.         TRect(dul, dlr), maxlength, code, format, mapped, user
  673.     );
  674.     break;
  675.  
  676.     case SignedByte:
  677.  
  678.     b = new TInputSignedByte
  679.     (
  680.         TRect(dul, dlr), maxlength, code, format, mapped, user
  681.     );
  682.     break;
  683.  
  684.     case Integer:
  685.     case Hex:
  686.  
  687.     b = new TInputInteger
  688.     (
  689.         TRect(dul, dlr), maxlength, code, format, mapped, user
  690.     );
  691.     break;
  692.  
  693.     case LongInteger:
  694.     case HexAddress:
  695.  
  696.     b = new TInputLong
  697.     (
  698.         TRect(dul, dlr), maxlength, code, format, mapped, user
  699.     );
  700.     break;
  701.  
  702.     case Float:
  703.  
  704.     b = new TInputFloat
  705.     (
  706.         TRect(dul, dlr), maxlength, code, format, mapped, user
  707.     );
  708.     break;
  709.  
  710.     case FloatControl:
  711.  
  712.     b = new TInputFloatControl
  713.     (
  714.         TRect(dul, dlr), maxlength, code, format, mapped, user,
  715.         map.mapType, map.maxMickey, map.maxKey, map.ctrlFunction
  716.     );
  717.     break;
  718.  
  719.     case ByteString:
  720.  
  721.     b = new TByteString(TRect(dul, dlr), maxlength);
  722.     break;
  723.  
  724.     case TimeField:
  725.     case DateField:
  726.     case String:
  727.     case Money:
  728.     default:
  729.  
  730.     b = new TInputLine(TRect(dul, dlr), maxlength);
  731.     break;
  732.     }
  733.     return b;
  734. }
  735.  
  736.  
  737. /************************************************************************
  738. ** DialogBox::makeButtons()
  739. **
  740. **    Given that the list is pointing to a boxy data-item,
  741. ** this routine makes up a new box.
  742. **
  743. *************************************************************************/
  744.  
  745. TView *
  746. DialogBox::makeButtons
  747. (
  748.     DataType datatype,    // the exact type of boxy data item
  749.     char **list,    // pointer to list of button-strings
  750.     TPoint dul,        // upper-left corner of the box
  751.     TPoint dlr        // lower-right corner of the box
  752. )
  753. {
  754.     TView *b;                    // the pointer to make
  755.     int count;                    // count the entries
  756.     TSItem *next;                // last/next in box lists
  757.  
  758.     count = 0;                    // count the entries
  759.     next = 0;                    // last/next in box lists
  760.  
  761.     while (*list != NULL)            // stop at a NULL pointer
  762.     {
  763.     list++;                    // next entry in the list
  764.     count++;                // count it
  765.     }
  766.     list--;                    // ignore trailing NULL
  767.     for (; count > 0; count--, list--)        // build linked list
  768.     {
  769.     next = new TSItem(*list, next);
  770.     }
  771.     switch (datatype)
  772.     {
  773.     case Checkbox:
  774.  
  775.     b = new TCheckBoxes(TRect(dul, dlr), next);
  776.     break;
  777.  
  778.     case Radiobox:
  779.  
  780.     b = new TRadioButtons(TRect(dul, dlr), next);
  781.     break;
  782.  
  783.     case Checkbyte:
  784.  
  785.     b = new TByteCheckBoxes(TRect(dul, dlr), next);
  786.     break;
  787.  
  788.     case Radiobyte:
  789.  
  790.     b = new TByteRadioButtons(TRect(dul, dlr), next);
  791.     break;
  792.     }
  793.     return b;
  794. }
  795.  
  796.  
  797. /************************************************************************
  798. ** DialogBox::buttonsOKCancel
  799. **
  800. **    Simply inserts the OK and Cancel buttons at a good spot at
  801. ** the bottom of the box.
  802. **    
  803. *************************************************************************/
  804.  
  805. #define OK_SIZE    9            // size of each OK/Cancel bar
  806. #define OK_SPACE   4            // distance between each bar
  807. #define OK_THICK   2            // thickness of the bars
  808. #define OK_LENGTH 2*(OK_SIZE+OK_SPACE)    // total length of OK/Cancel bars
  809. #define OK_BOTTOM  1            // distance of bar from bottom
  810. #define OK_ADJUST  5            // another magic number
  811.  
  812. void
  813. DialogBox::buttonsOKCancel
  814. (
  815.     TDialog *pd,
  816.     TPoint lr
  817. )
  818. {
  819.     TPoint ul;                // location of dialog
  820.     TView *b;                // temporary pointer
  821.  
  822.     ul.x = (lr.x - OK_LENGTH) / 2;    // center bars horizontally
  823.     ul.y = lr.y - OK_THICK - OK_BOTTOM;    // up a little from bottom
  824.     lr.x = ul.x + OK_SIZE + 2;        // right end of OK bar
  825.     lr.y = ul.y + OK_THICK;        // allow for thickness of bar
  826.  
  827.     b = new TButton(TRect(ul,lr), "~O~K", cmOK, bfDefault);
  828.     if (b)
  829.     pd->insert(b);
  830.  
  831.     ul.x += OK_SIZE + OK_ADJUST;
  832.     lr.x += OK_SIZE + OK_ADJUST;
  833.  
  834.     b = new TButton(TRect(ul,lr), "~C~ancel", cmCancel, bfNormal);
  835.     if (b)
  836.     pd->insert(b);
  837. }
  838.  
  839.  
  840. /************************************************************************
  841. ** DialogBox::isBox()
  842. ** DialogBox::isString()
  843. ** DialogBox::isNumeric()
  844. ** DialogBox::isExtended()
  845. ** DialogBox::isControl()
  846. **
  847. **    Each returns a 1 if the DataType is one of the right kind of
  848. ** data item.
  849. **    
  850. *************************************************************************/
  851.  
  852. Boolean
  853. DialogBox::isBox
  854. (
  855.     DataType datatype
  856. )
  857. {
  858.     return (Boolean)
  859.     (
  860.     (datatype == Checkbox)  ||
  861.     (datatype == Radiobox)  ||
  862.     (datatype == Checkbyte) ||
  863.     (datatype == Radiobyte)
  864.     );
  865. }
  866.  
  867.  
  868. Boolean
  869. DialogBox::isNumeric
  870. (
  871.     DataType datatype
  872. )
  873. {
  874.     return (Boolean)
  875.     (
  876.     (datatype == Integer)        ||
  877.     (datatype == Hex)        ||
  878.     (datatype == UnsignedByte)    ||
  879.     (datatype == SignedByte)    ||
  880.     (datatype == LongInteger)        ||
  881.     (datatype == HexAddress)    ||
  882.     (datatype == Float)        ||
  883.     (datatype == FloatControl)
  884.     );
  885. }
  886.  
  887.  
  888. Boolean
  889. DialogBox::isString
  890. (
  891.     DataType datatype
  892. )
  893. {
  894.     return (Boolean)
  895.     (
  896.     (datatype == ByteString)    ||
  897.     (datatype == TimeField)        ||
  898.     (datatype == DateField)        ||
  899.     (datatype == String)        ||
  900.     (datatype == Money)
  901.     );
  902. }
  903.  
  904.  
  905. Boolean
  906. DialogBox::isControl
  907. (
  908.     DataType datatype
  909. )
  910. {
  911.     return (Boolean)
  912.     (
  913.     (datatype == FloatControl)
  914.     );
  915. }
  916.  
  917.  
  918. Boolean
  919. DialogBox::isExtended
  920. (
  921.     DataType datatype
  922. )
  923. {
  924.     return (Boolean)
  925.     (
  926.     (datatype == Extended)
  927.     );
  928. }
  929.  
  930.  
  931. /************************************************************************
  932. ** write()
  933. ** read()
  934. **
  935. **    Saves and restores all the dialog boxes; they amount to all
  936. ** the configuration we need.
  937. **
  938. **    I should learn to use streams on this stuff; later dude.
  939. **
  940. *************************************************************************/
  941.  
  942. #define ERR_NONE        0
  943. #define ERR_FILE_WRITE        1
  944. #define ERR_FILE_READ        2
  945. #define ERR_FILE_NOT_OPEN    3
  946.  
  947. int
  948. DialogBox::write
  949. (
  950.     FILE *fptr
  951. )
  952. {
  953.     size_t items;        // number of items successfully written
  954.     int errcode = ERR_NONE;
  955.  
  956.     if (fptr != NULL)
  957.     {
  958.     items = fwrite(dialogData, dataSize, 1, fptr);
  959.     if (items != dataSize)
  960.         errcode = ERR_FILE_WRITE;
  961.     }
  962.     else
  963.     {
  964.     errcode = ERR_FILE_NOT_OPEN;
  965.     }
  966.     return errcode;
  967. }
  968.  
  969.  
  970. int
  971. DialogBox::read
  972. (
  973.     FILE *fptr
  974. )
  975. {
  976.     size_t items;        // number of items successfully written
  977.     int errcode = ERR_NONE;
  978.  
  979.     if (fptr != NULL)
  980.     {
  981.     items = fread(dialogData, dataSize, 1, fptr);
  982.     if (items != dataSize)
  983.         errcode = ERR_FILE_READ;
  984.     }
  985.     else
  986.     {
  987.     errcode = ERR_FILE_NOT_OPEN;
  988.     }
  989.     return errcode;
  990. }
  991.