home *** CD-ROM | disk | FTP | other *** search
- //===============================================================
- // vcmdprnt.cxx - vCmdParent Class - Windows
- //
- // Copyright (C) 1995,1996,1997,1998 Bruce E. Wampler
- //
- // This file is part of the V C++ GUI Framework, and is covered
- // under the terms of the GNU Library General Public License,
- // Version 2. This library has NO WARRANTY. See the source file
- // vapp.cxx for more complete information about license terms.
- //===============================================================
- #include <v/vos2.h> // for OS/22 stuff
- #include <v/vapp.h> // need the codepage
- #include <v/vcmdprnt.h> // our include
- #include <v/vbtncmd.h> // ButtonCmd
- #include <v/vlabelc.h> // LabelCmd
- #include <v/vframec.h> // FrameCmd
- #include <v/vchkboxc.h> // CheckBoxCmd
- #include <v/vradioc.h> // RadioButtonCmd
- #include <v/vtextinc.h> // TextInCmd
- #include <v/vtextc.h> // TextCmd
- #include <v/vlistc.h> // ListCmd
- #include <v/vcomboc.h> // ComboBoxCmd
- #include <v/vspinc.h> // SpinnerCmd
- #include <v/vsliderc.h> // SliderCmd
- #include <v/vprogrsc.h> // ProgressCmd
- #include <v/vboxlblc.h> // BoxedLabel
-
- // ---------------------------------------------------------------------
- // Dynamic Dialog Building Support
- // ---------------------------------------------------------------------
-
- // this is an attempt to consolidate all the different margin
- // variables that are lying around, but alas all seem to be doing pretty
- // much the same thing. We will stick with StdMargin in vcmd.h as the
- // master margin variable.
- const int _CtrlSpacing = StdMargin;
-
- //======================>>> vCmdParent::vCmdParent <<<========================
- // In this tricky little function, the address of the pointer variable used
- // in the calling function to track the next free byte at the end of the
- // dialog template variable data region is accessed (*inp).
- // The function automatically increments this pointer so that after copying
- // the *src string to the end of the data region, the original pointer in
- // the calling function now points to the new end of the data region.
- static void CopyStringToDialog (PSZ *inp, PCSZ src)
- {
- char *in = (char * )(*inp); // in assigned the address of *inp
-
- do
- {
- *in++ = (char) *src;
- } while (*src++);
- *inp = (char *)in; // *inp reset to the new end of data
- }
-
- //======================>>> vCmdParent::vCmdParent <<<==========================
- vCmdParent::vCmdParent(PaneType pt)
- {
- _cmdList = 0;
- maxX = 0; // minimum size for a dialog
- maxY = 0;
- if (pt == P_Status)
- {
- maxX = 4; // give some room at left for drawing box
- maxY = 4;
- }
-
- _callbackID = -1; // no call back id
- _pt = pt;
- }
-
- //======================>>> vCmdParent::~vCmdParent <<<============================
- vCmdParent::~vCmdParent()
- {
- SysDebug(Destructor,"vCmdParent::~vCmdParent() destructor\n")
- // need to delete everything we added
- DlgCmdList* tmp;
- if (_hTemplate != 0)
- {
- DosFreeMem(_hTemplate);
-
- _hTemplate = 0;
- }
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; )
- {
- delete cc->cmdP; // delete the cmd object
- tmp = cc; // don't forget where we were
- cc = cc->nextDCL; // for next time
- delete tmp; // delete the list cell
- }
- }
-
- //======================>>> vCmdParent::AddCmd <<<============================
- vCmd* vCmdParent::AddCmd(CommandObject* cmd)
- {
- // Private method to add a single command to a dialog object.
- SysDebug2(Build,"vCmdParent::AddCmd() - %s(id:%d)\n",cmd->title,cmd->cmdId)
- vCmd* cmdPtr;
- switch (cmd->cmdType) // depends on type
- {
- case C_IconButton: // a command button Icon
- case C_ToggleButton: // a toggle icon button
- case C_ToggleIconButton: // a toggle icon button
- case C_Button: // Button
- case C_ColorButton: // ColorButton
- {
- cmdPtr = new vButtonCmd(this, cmd);
- break;
- }
- case C_CheckBox: // Checked Item
- {
- cmdPtr = new vCheckBoxCmd(this, cmd);
- break;
- }
- case C_ComboBox: // Popup combo list
- {
- cmdPtr = new vComboBoxCmd(this, cmd);
- break;
- }
- case C_Frame: // General purpose frame
- case C_ToggleFrame: // A toggle frame
- {
- cmdPtr = new vFrameCmd(this, cmd);
- break;
- }
- case C_Icon: // a static icon
- case C_Blank: // to help RightOfs, Belows work
- case C_Label: // Regular text label
- case C_ColorLabel: // Color text label
- {
- cmdPtr = new vLabelCmd(this, cmd);
- break;
- }
- case C_List: // List of items (scrollable)
- {
- cmdPtr = new vListCmd(this, cmd);
- break;
- }
- case C_ProgressBar: // Progress bar
- {
- cmdPtr = new vProgressCmd(this, cmd);
- break;
- }
- case C_RadioButton: // radio button
- {
- cmdPtr = new vRadioButtonCmd(this, cmd);
- break;
- }
- case C_Slider: // slider
- {
- cmdPtr = new vSliderCmd(this, cmd);
- break;
- }
- case C_BoxedLabel:
- {
- cmdPtr = new vBoxedLabelCmd(this, cmd);
- break;
- }
- case C_Text: // Text output field
- {
- cmdPtr = new vTextCmd(this, cmd);
- break;
- }
- case C_TextIn: // Text input field
- {
- cmdPtr = new vTextInCmd(this, cmd);
- break;
- }
- case C_Spinner: // Value Box list
- {
- cmdPtr = new vSpinnerCmd(this, cmd);
- break;
- }
- default: // unknown!
- {
- SysDebug2(BadVals,"vCmdParent::AddCmd(id:%d, title:%s) ** Unknown DialogCommand\n",
- cmd->cmdId,cmd->title);
- cmd->title = "?? Bad CommandObject ??";
- cmdPtr = new vLabelCmd(this, cmd);
- break;
- }
- }
- return cmdPtr;
- }
-
- //====================>>> vCmdParent::HasId <<<=========================
- int vCmdParent::HasId(ItemVal id) VCONST
- {
- // We need this one for panes to work correctly
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if (((cc->cmdP)->dlgCmd)->cmdId == id)
- {
- return 1;
- }
- }
- return 0;
- }
-
- //====================>>> vCmdParent::GetValue <<<=========================
- int vCmdParent::GetValue(ItemVal id) VCONST
- {
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if (((cc->cmdP)->dlgCmd)->cmdId == id)
- {
- return (cc->cmdP)->GetCmdValue(id); // return the value
- }
- }
- return 0;
- }
-
- //====================>>> vCmdParent::SetFrameChildren <<<======================
- void vCmdParent::SetFrameChildren(ItemVal frameId, int frameVal)
- {
- // Set all children of given frame to hidden or not hidden
- // Do this recursively to be sure to get them all.
- // Scan list, setting all children that use this frame
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL) // Find the frame
- {
- CommandObject* cop = (cc->cmdP)->dlgCmd;
- if (cop->cFrame == frameId) // A child of ours
- {
- // Hide control if not turning on (frameVal is opposite of Hidden)
- SetValue(cop->cmdId, !frameVal, Hidden);
- if (cop->cmdType == C_Frame || cop->cmdType == C_ToggleFrame)
- SetFrameChildren(cop->cmdId, frameVal); // Get other chilren
- }
- }
- }
-
- //====================>>> vCmdParent::GetTextIn <<<=========================
- int vCmdParent::GetTextIn(ItemVal id, char* strout, int maxlen)
- {
- // recover the string from TextIn id, up to maxlen
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if (((cc->cmdP)->dlgCmd)->cmdId == id)
- {
- // need to cast to a vTextInCmd so we can use getstr
- vTextInCmd* tip = (vTextInCmd*) cc->cmdP;
- return tip->GetTextIn(id, strout, maxlen); // return the value
- }
- }
- *strout = 0;
- return 0;
- }
-
- //====================>>> vCmdParent::getParent <<<=======================
- HWND vCmdParent::getParent(void) VCONST
- {
- // Return parent's HWND
- return _wDialog;
- }
-
- //==================>>> vCmdParent::getThisFromId <<<=======================
- vCmd* vCmdParent::getThisFromId(ItemVal find_id)
- {
- // search the list of cmds for id, return its this
- DlgCmdList* cc;
- // search the list
-
- for (cc = _cmdList; cc != NULL ; cc = cc->nextDCL)
- {
- if (cc->cmdP == NULL || (cc->cmdP)->dlgCmd == NULL)
- return 0;
-
- if (((cc->cmdP)->dlgCmd)->cmdId == find_id)
- {
- return cc->cmdP;
- }
- }
- return 0; // failed to find it
- }
-
- //====================>>> vCmdParent::SetPosition <<<=========================
- void vCmdParent::SetPosition(int& x, int& y, int w, int h, ItemVal frame,
- ItemVal rightOf, ItemVal below, int isSpinner)
- {
- // This method is responsible for controlling the layout of controls in
- // a dialog. All positions of controls are set relative to other controls,
- // which must have been previously defined (i.e., you start with the upper
- // left control and work to the lower right corner). It must dynamically
- // set the size of frames, and track the maximum x and y of the whole
- // dialog.
- //
- // note: As far as I can tell, the isSpinner variable is never used
- // and is always 0 so I deleted all the isSpinner code
-
- int margin = _CtrlSpacing; // spacing between controls
- int FrameMargin = _CtrlSpacing*2; // spacing between controls and frame edge
-
- vCmd* frameCmd = 0;
-
- x = y = margin; // start out with standard spacing
-
- if (frame != 0) // in a frame?
- {
- // refresher: DlgCmdList is a linked list of pointers to vCmd's
- // _cmdList is the list of vCmd's (controls) for this dialog
- // dlgCmd is a pointer to the vCmd static definition
- //
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
- continue;
-
- // search for the vCmd of our frame
- if (((cc->cmdP)->dlgCmd)->cmdId == frame)
- {
- frameCmd = cc->cmdP; // remember our frame
- if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
- FrameMargin = 0;
-
- // position the control relative to the frame based on the specified
- // position data
- if (rightOf == 0)
- {
- x = (cc->cmdP)->_x + FrameMargin; // add to right of frame
- if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
- ++x; // adjust for right side BEW 1.21
- }
-
- else
- x = FrameMargin;
-
- if (below == 0)
- {
- y = (cc->cmdP)->_y + FrameMargin;
- if ((frameCmd->dlgCmd)->attrs & CA_NoSpace)
- ++y; // adjust for bottom BEW 1.21
- }
-
- else
- y = FrameMargin;
- }
- }
- } // end of frame procedure
-
- // check if its a command bar and not in a frame
- if (_dialogType == aCmdBar && frame == 0)
- {
- x = maxX + margin; // put the control at the end of the bar + margin
- y = margin; // bars are linear in x (no y control allowed)
- }
-
- // check if its a status bar and not in a frame
- else if (_dialogType == aStatBar && frame == 0)
- {
- x = maxX + margin; // put the control at the end of the bar + margin
- // y = margin + 1; // adjust in y to center better
- y = margin; // bars are linear in x (no y control allowed)
- }
-
- // else, its a regular dialog with full 2d positioning
- else
- {
- // refresher: DlgCmdList is a linked list of pointers to vCmd's
- // _cmdList is the list of vCmd's (controls) for this dialog
- // dlgCmd is a pointer to the vCmd static definition
- //
- // cycle through all the controls in the dialog
-
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- // we skip the partially added current control
- if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
- continue;
- // set the control's x posn right of the 'rightof' control
- if (((cc->cmdP)->dlgCmd)->cmdId == rightOf)
- {
- x += ((cc->cmdP)->_x) + ((cc->cmdP)->_w); // position to right of the 'rightOf'
- }
- // set the control's y posn below the 'below' control
- if (((cc->cmdP)->dlgCmd)->cmdId == below)
- {
- y += ((cc->cmdP)->_y) + ((cc->cmdP)->_h); // position below the 'below'
- }
- }
- }
-
- // now we adjust the overall dialog size to enclose the
- // control we just added
- int cxr = x + w; // right x of control
- int cyb = y + h; // bottom y of control
-
- if (maxX < cxr) // track size of the dialog
- maxX = cxr;
-
- if (maxY < cyb)
- maxY = cyb;
-
- // if a frame was used, then we need to also adjust the
- // overall frame size to enclose the control we just added
- if (frameCmd) // need to fixup frame
- {
- FixFrame(cxr, cyb, FrameMargin, frameCmd); // fixup frames
- }
- }
-
- //====================>>> vCmdParent::FixFrame <<<=======================
- // After a vCmd (control) is added to a frame, we need to readjust the
- // overall frame size to make sure it encloses the control we just added
- //
- // cxr is the controls rightmost extent
- // cyb is the controls bottommost extent
- void vCmdParent::FixFrame(int cxr, int cyb, int FrameMargin, vCmd* frameCmd)
- {
- int fxr = frameCmd->_x + frameCmd->_w; // right x of frame
- int fyb = frameCmd->_y + frameCmd->_h; // bottom y of frame
-
- if (fxr < cxr + FrameMargin) // need to make frame wider
- {
- frameCmd->_w = (cxr + FrameMargin) - frameCmd->_x;
- if (FrameMargin == 0)
- ++(frameCmd->_w); // make nospace look right BEW 1.21
- }
-
- if (fyb < cyb + FrameMargin) // need to make frame taller
- {
- frameCmd->_h = (cyb + FrameMargin) - frameCmd->_y;
- if (FrameMargin == 0)
- ++(frameCmd->_h); // make nospace look right BEW 1.21
- }
-
- // Check if we need fixup the overall dialog size
- if (maxX < frameCmd->_x + frameCmd->_w)
- maxX = frameCmd->_x + frameCmd->_w;
- if (maxY < frameCmd->_y + frameCmd->_h)
- maxY = frameCmd->_y + frameCmd->_h;
-
- // Now fixup the dialog template
- // The dialog template item for the frame control is already created
- // We need to update the template item size parameters with the new
- // values for the frame size
- if (frameCmd->_CtrlOffset != 0)
- {
- ULONG *wNumBytes;
-
- PDLGTITEM pDlgTItem;
-
- // wNumBytes points to beginning of DLGTEMPLATE memory block.
- wNumBytes = (ULONG *) _hTemplate;
- // pDlgTItem points to start of new DLGTITEM.
- pDlgTItem = (PDLGTITEM) (((PSZ) wNumBytes) + frameCmd->_CtrlOffset);
-
- // Fix the width
- pDlgTItem->cx = frameCmd->_w;
- pDlgTItem->cy = frameCmd->_h;
- }
-
- // Now, fixup surrounding frames!
- int frame = (frameCmd->dlgCmd)->cFrame;
- if (frame != 0) // Have to fix frame's frame
- {
- // refresher: DlgCmdList is a linked list of pointers to vCmd's
- // _cmdList is the list of vCmd's (controls) for this dialog
- // dlgCmd is a pointer to the vCmd static definition
- //
- // cycle through all the controls in the dialog
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if ((cc->cmdP) == 0 || (cc->cmdP)->dlgCmd == 0) // not completely added yet!
- continue;
- if (((cc->cmdP)->dlgCmd)->cmdId == frame)
- {
- vCmd* fCmd = cc->cmdP; // remember frame's frame
- fxr = frameCmd->_x + frameCmd->_w; // right x of frame
- fyb = frameCmd->_y + frameCmd->_h; // bottom y of frame
- FixFrame(fxr, fyb, FrameMargin, fCmd);
- break;
- }
- }
- }
- }
-
- //====================>>> vCmdParent::SetValue <<<=======================
- void vCmdParent::SetValue(ItemVal id, ItemVal val, ItemSetType setType)
- {
- SysDebug2(Misc,"vCmdParent::SetValue(id:%d, val:%d)\n",id,val)
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if (((cc->cmdP)->dlgCmd)->cmdId == id)
- {
- (cc->cmdP)->SetCmdVal(val,setType); // return the value
- return;
- }
- }
- }
-
- //====================>>> vCmdParent::SetString <<<=======================
- void vCmdParent::SetString(ItemVal id, char* str) VCONST
- {
- char trunc[80];
- SysDebug2(Misc,"vCmdParent::SetString(id:%d, str:%s)\n",id, strncpy(trunc, str, 60) )
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- if (((cc->cmdP)->dlgCmd)->cmdId == id)
- {
- (cc->cmdP)->SetCmdStr(str); // return the value
- return;
- }
- }
- }
-
- //====================>>> vCmdParent::CreateDlgTemplate <<<==================
- // Creates a Dialog Template in memory. Avoids needing a resource file
- // to build up the dialog controls.
-
- int vCmdParent::CreateDlgTemplate(
- ULONG dtCtlData, // dialog control data (FCF_*, etc)
- ULONG dtStyle, // dialog style (WS_* and FS_*)
- SHORT dtX, // location, In dialog-box units
- SHORT dtY,
- SHORT dtCX, // size, in dialog-box units
- SHORT dtCY,
- SHORT dtID, // V doesn't assign an ID to the frame
- PSZ dtMenuName, // "" if no menu (not Implemented)
- PSZ dtClassName, // "" if standard dialog box class (not implemented)
- PSZ dtCaption, // caption text for dialog
- PPRESPARAMS pPP) // Presentation Parameters
- {
- ULONG wBlockLen;
- ULONG wBaseMem, wItemMem;
- ULONG wCaptionLen, PPLen;
- PSZ szDlgTemplate, szDlgTypeFace;
- PDLGTEMPLATE pDlgTemplate;
-
- // Calculate number of bytes required by following fields:
- // Block must be large enough to contain the following:
- // # bytes: fixed part DLGTEMPLATE and one DLGTITEM
- // # bytes: dialog box caption.
- // # bytes: presentation parameters.
-
- wCaptionLen = (1 + strlen(dtCaption));
- wBlockLen = sizeof(DLGTEMPLATE) + sizeof(dtCtlData) + wCaptionLen;
-
- if (pPP)
- {
- // Dialog box has Presentation Parameters
- // Calculate # of bytes required for PRESPARAM structure
- // cb gives the byte count of the aparam[] array, need to add
- // extra 4 bytes for pPP->cb count
- PPLen = pPP->cb + sizeof(ULONG);
- wBlockLen += PPLen; // # bytes for PRESPARAM value (font typeface)
- }
- else
- {
- // Dialog box uses the System font.
- // Block length does not change.
- PPLen = 0;
- }
-
- // Allocate global block of memory for Dialog template.
- DosAllocMem ((PPVOID) &_hTemplate, wBlockLen, fALLOC);
-
- if (_hTemplate == NULL)
- return 0; // memory alloc failed!
-
- // pDlgTemplate points to start of DLGTEMPLATE in block.
- pDlgTemplate = _hTemplate;
-
- // Set the members of the DLGTEMPLATE structure.
- pDlgTemplate->cbTemplate = wBlockLen;
- pDlgTemplate->type = 0; // not used
- pDlgTemplate->codepage = theApp->AppCP();
- wBaseMem = (ULONG) pDlgTemplate;
- wItemMem = (ULONG) pDlgTemplate->adlgti;
- pDlgTemplate->offadlgti = (SHORT) wItemMem - wBaseMem;
- pDlgTemplate->fsTemplateStatus = 1; // not used (docs say 0 but debug says 1)
- pDlgTemplate->iItemFocus = (USHORT) -1; // no focus specified
- pDlgTemplate->coffPresParams = 0; // never used!
-
- // Set the members of the frame DLGTITEM structure.
- // the first item is always the frame window class (WC_FRAME)
- pDlgTemplate->adlgti[0].fsItemStatus = 0; // not used
- // no controls yet, Incremented with calls to AddDlgControl.
- pDlgTemplate->adlgti[0].cChildren = 0;
- pDlgTemplate->adlgti[0].cchClassName = 0; // use PM classes
- pDlgTemplate->adlgti[0].offClassName = SHORT1FROMMP((MPARAM) WC_FRAME); // PM class
- pDlgTemplate->adlgti[0].cchText = wCaptionLen-1; // strip null from string
- pDlgTemplate->adlgti[0].flStyle = dtStyle;
- pDlgTemplate->adlgti[0].x = dtX;
- pDlgTemplate->adlgti[0].y = dtY;
- pDlgTemplate->adlgti[0].cx = dtCX;
- pDlgTemplate->adlgti[0].cy = dtCY;
- pDlgTemplate->adlgti[0].id = dtID; // V doesn't seem to need this
-
- // szDlgTemplate points to start of variable part of DLGTEMPLATE.
- szDlgTemplate = (PSZ) (pDlgTemplate + 1);
-
- // store variable length caption
- // we compute the offset from here to start of DLGTEMPLATE and save
- wItemMem = (ULONG) szDlgTemplate;
-
- pDlgTemplate->adlgti[0].offText = (SHORT) (wItemMem - wBaseMem);
- CopyStringToDialog(&szDlgTemplate, dtCaption);
-
- // store ULONG control data here
- wItemMem = (ULONG) szDlgTemplate;
- pDlgTemplate->adlgti[0].offCtlData = (SHORT) wItemMem - wBaseMem;
- memcpy(szDlgTemplate, &dtCtlData, 4);
- szDlgTemplate += 4;
-
- // add the PRESPARAMS info
- if (pPP)
- {
- wItemMem = (ULONG) szDlgTemplate;
- pDlgTemplate->adlgti[0].offPresParams = (SHORT) wItemMem - wBaseMem;
- memcpy(szDlgTemplate, pPP, PPLen);
- szDlgTemplate += PPLen;
- DosFreeMem (pPP); // destroy pPP structure after use
- }
- else // no PPs!
- pDlgTemplate->adlgti[0].offPresParams = (USHORT) -1;
-
- return 1; // success
- }
-
- //====================>>> vCmdParent::AddDlgControl <<<=====================
- int AddDlgControl (SHORT dtilX, SHORT dtilY, SHORT dtilCX, SHORT dtilCY,
- USHORT dtilID, ULONG dtilStyle, PCSZ dtilClass, PCSZ dtilText,
- PPRESPARAMS dtipPP, ULONG dtilCtlLen, PVOID dtilCtlData);
-
- int vCmdParent::AddDlgControl (
- SHORT dtilX, SHORT dtilY, // In dialog-box units.
- SHORT dtilCX, SHORT dtilCY, // In dialog-box units.
- USHORT dtilID,
- ULONG dtilStyle, // WS_* BS_* etc.
- PCSZ dtilClass, // Class name WC_*
- PCSZ dtilText, // label
- PPRESPARAMS dtipPP, // Pointer to presentation parameters
- ULONG dtilCtlLen, // Control Data length (bytes)
- PVOID dtilCtlData) // Pointer to control data
- {
- ULONG wBlockLen, wTextLen, wBaseMem, wItemMem;
- ULONG PPLen;
- USHORT *wCtlLen;
- PDLGTEMPLATE pOldDlgTemplate, pDlgTemplate;
- PDLGTITEM pDlgTItem;
-
- PSZ pszOldData, pszData;
-
- int i, numControls = 0; // number of controls in dialog
-
- // Calculate number of bytes required by following fields:
- wTextLen = (1 + strlen(dtilText)) * sizeof (char);
-
- // Block must be increased by the following amount:
- wBlockLen =
- sizeof(DLGTITEM) + // # bytes for fixed part of DLGTITEM.
- wTextLen + // # bytes for control text.
- dtilCtlLen; // # bytes for extra CTRL data.
-
- if (dtipPP)
- {
- // Dialog box has Presentation Parameters
- // Calculate # of bytes required for PRESPARAM structure
- // cb gives the byte count of the aparam[] array, need to add
- // extra (ULONG) bytes for dtipPP->cb member
- PPLen = dtipPP->cb + sizeof(ULONG);
-
- // Block must be large enough to include PP information.
- wBlockLen += PPLen; // # bytes for PRESPARAM value (font typeface)
- }
- else
- {
- // Dialog box uses the System font.
- // Block length does not change.
- PPLen = 0;
- }
-
- // Add to number of bytes currently in the memory block.
- wBlockLen += _hTemplate->cbTemplate;
-
- // pOldDlgTemplate points to start of old DLGTEMPLATE in block.
- pOldDlgTemplate = _hTemplate;
-
- // Allocate new larger global block of memory for Dialog template.
- // this is probably really inefficient but what else is there to do?
- DosAllocMem ((PPVOID) &pDlgTemplate, wBlockLen, fALLOC);
-
- if (pDlgTemplate == NULL)
- return 0; // memory alloc failed!
-
- _hTemplate = pDlgTemplate;
- wBaseMem = (ULONG) pDlgTemplate; // used for offset calcs
-
- // copy over the old template data to the new structure
- // we will fix up the offsets and variable data area later
- memcpy(pDlgTemplate, pOldDlgTemplate, pOldDlgTemplate->cbTemplate);
-
- // save the total size of the new template
- pDlgTemplate->cbTemplate = wBlockLen;
-
- // Increment the number of controls in the WC_FRAME template item.
- numControls = ++pDlgTemplate->adlgti[0].cChildren;
-
- // set pDlgTItem to point to the start of new DLGTITEM.
- // This is near the end of the memory block.
- pDlgTItem = &pDlgTemplate->adlgti[numControls];
-
- // Set the members of the DLGTITEM structure.
- pDlgTItem->fsItemStatus = 0; // not used
- pDlgTItem->cChildren = 0; // only WC_FRAME has children
- pDlgTItem->cchClassName = 0; // use PM classes
- pDlgTItem->offClassName = SHORT1FROMMP((MPARAM) dtilClass); // WC_*
- pDlgTItem->cchText = wTextLen-1; // label length (drop null at end)
- pDlgTItem->flStyle = dtilStyle; // WS_* BS_*, MLE_* etc.
- pDlgTItem->x = dtilX;
- pDlgTItem->y = dtilY;
- pDlgTItem->cx = dtilCX;
-
- // We have to handle comboboxes specially because the
- // height needed here is the combobox PLUS its list, while
- // the height we want to use internally is the height WITHOUT the list
- if (dtilClass == WC_COMBOBOX ) // Combo?
- pDlgTItem->cy = dtilCY + 8*6;
- else
- pDlgTItem->cy = dtilCY;
-
- pDlgTItem->id = dtilID;
- pDlgTItem->offPresParams = (USHORT) -1; // default
-
- // now we need to fix up the variable data area
- // pszData points to start of variable data part of the template
- pszData = (PSZ) (pDlgTItem + 1);
-
- for (i=0; i<numControls; i++)
- {
- // store text label and compute offset to start of DLGTEMPLATE
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offText = (USHORT) (wItemMem - wBaseMem);
-
- pszOldData = (PSZ) pOldDlgTemplate; // base of old template
- pszOldData += pOldDlgTemplate->adlgti[i].offText; // pointer to old text
- CopyStringToDialog(&pszData, pszOldData);
-
- // store PRESPARAMS and compute offset to start of DLGTEMPLATE
- // if offset = -1 then no data
- if (pOldDlgTemplate->adlgti[i].offPresParams == (USHORT) -1)
- pDlgTemplate->adlgti[i].offPresParams = (USHORT) -1;
-
- else // else copy over data
- {
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offPresParams = (USHORT) wItemMem - wBaseMem;
-
- pszOldData = (PSZ) pOldDlgTemplate; // base of old template
- pszOldData += pOldDlgTemplate->adlgti[i].offPresParams; // pointer to old CtlData
- // get the data length in bytes (first 4 bytes of data)
- PPLen = (ULONG) *pszOldData;
- memcpy(pszData, pszOldData, PPLen + sizeof(ULONG));
- pszData += PPLen + sizeof(ULONG);
- }
-
- // store CTLDATA and compute offset to start of DLGTEMPLATE
- // if offset = -1 then no data
- if (pOldDlgTemplate->adlgti[i].offCtlData == (USHORT) -1)
- pDlgTemplate->adlgti[i].offCtlData = (USHORT) -1;
-
- else // else copy over data
- {
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offCtlData = (USHORT) wItemMem - wBaseMem;
-
- pszOldData = (PSZ) pOldDlgTemplate; // base of old template
- pszOldData += pOldDlgTemplate->adlgti[i].offCtlData; // pointer to old CtlData
- // get the data length in bytes (first 4 bytes of data)
- // Note: WC_FRAME class is non-conforming. It expects a 4 byte
- // ULONG in the data area with no size info
- if ( pOldDlgTemplate->adlgti[i].offClassName == SHORT1FROMMP((MPARAM) WC_FRAME))
- {
- memcpy(pszData, pszOldData, 4); // non-conforming
- pszData += 4;
- }
- else
- {
- wCtlLen = (USHORT*) pszOldData; // conforming
- memcpy(pszData, pszOldData, *wCtlLen);
- pszData += *wCtlLen;
- }
- }
- }
-
- // now we finish off by storing the current control's data
- // store control label and compute offset to start of DLGTEMPLATE
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offText = (USHORT) (wItemMem - wBaseMem);
- CopyStringToDialog(&pszData, dtilText);
-
- // store PRESPARAMS and compute offset to start of DLGTEMPLATE
- if (dtipPP == 0) // if no data set offset to -1
- pDlgTemplate->adlgti[i].offPresParams = (USHORT) -1;
- else
- {
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offPresParams = (USHORT) wItemMem - wBaseMem;
- memcpy(pszData, dtipPP, dtipPP->cb + sizeof(ULONG));
- pszData += dtipPP->cb + sizeof(ULONG);
- DosFreeMem (dtipPP); // don't forget to clean up afterwards
- }
-
- // store CTLDATA and compute offset to start of DLGTEMPLATE
- if (dtilCtlLen == 0) // if no data set offset to -1
- pDlgTemplate->adlgti[i].offCtlData = (USHORT) -1;
- else
- {
- wItemMem = (ULONG) pszData;
- pDlgTemplate->adlgti[i].offCtlData = (USHORT) wItemMem - wBaseMem;
- memcpy(pszData, dtilCtlData, dtilCtlLen);
- pszData += dtilCtlLen;
- }
-
- // now destroy the old template
- DosFreeMem(pOldDlgTemplate);
-
- // offset to start of last control
- return (int) &pDlgTemplate->adlgti[i] - wBaseMem;
- }
-
-
- //==================>>> vCmdParent::DoneAddingControls <<<===================
- void vCmdParent::DoneAddingControls(void)
- {
- PDLGTEMPLATE pDlgTemplate;
-
- // set pDlgTemplate to start of DLGTEMPLATE in block.
- pDlgTemplate = _hTemplate;
-
- // Fixup size
- maxX = pDlgTemplate->adlgti[0].cx = maxX + _CtrlSpacing;
- maxY = pDlgTemplate->adlgti[0].cy = maxY + _CtrlSpacing;
-
- // we need to transform all control y-dimensions since V uses upper left as
- // origin and OS/2 assumes lower left
-
- ULONG *wNumBytes;
- PDLGTITEM pDlgTItem;
-
- // set wNumBytes to beginning of DLGTEMPLATE memory block.
- wNumBytes = (ULONG *) _hTemplate;
-
- for (DlgCmdList* cc = _cmdList ; cc != 0 ; cc = cc->nextDCL)
- {
- // transform the y coord in the dialog template
- if ( (cc->cmdP)->_CtrlOffset != 0)
- {
- // set pDlgTItem to start of current control DLGTITEM.
- pDlgTItem = (PDLGTITEM) (((PSZ) wNumBytes) + (cc->cmdP)->_CtrlOffset);
-
- // invert and shift y coord
- if ( (((cc->cmdP)->dlgCmd)->cmdType) == C_ComboBox ) // Combo?
- pDlgTItem->y = maxY - (cc->cmdP)->_y - (cc->cmdP)->_h - 8*6;
- else
- pDlgTItem->y = maxY - (cc->cmdP)->_y - (cc->cmdP)->_h;
- }
- }
- }
-
-
- //================>>> vCmdParent::ChangeDlgTButtonColor <<<=====================
- // routine to change the color button color in the dialog template
- // after the template is assembled in memory
- //
- void vCmdParent::ChangeDlgTButtonColor(int CtrlOffset, USHORT cmdId, ULONG newColor )
- {
- PDLGTITEM pDlgTItem;
-
- // set pDlgTItem to start of current control DLGTITEM.
- pDlgTItem = (PDLGTITEM) (((PSZ) _hTemplate) + CtrlOffset);
-
- // a sanity check
- if (pDlgTItem->id != cmdId)
- {
- // something's gone wrong, better punt!
- return;
- }
- // find the button color pres params word in the template...
- // this is a bit dangerous since we assume that the button
- // color pres param order is fixed, but since we create the template
- // we do have control over this so it shouldn't break later
- // and it makes life simpler this way
- ULONG *buttonColor;
- buttonColor = (ULONG *) (((PSZ) _hTemplate) + pDlgTItem->offPresParams);
-
- // button color is 3rd ULONG in from start of Pres Params
- buttonColor += 3;
- *buttonColor = newColor;
- }
-
- //====================>>> vCmdParent::AssyPresParams <<<=====================
- //----- routine to assemble an arbitrary size PP structure
- PPRESPARAMS vCmdParent::AssyPresParams(PPElement *PPel)
- {
- ULONG PPlen;
- int i;
- PPARAM ixPP;
- PPRESPARAMS pPP;
-
- // first compute necessary storage space for PPs
- PPlen = sizeof(ULONG); // pp.cb
- for (i=0; PPel[i].PPtype; i++)
- {
- if (PPel[i].PPtype == PP_FONTNAMESIZE)
- // its a font PP
- PPlen += sizeof(PARAM)-1 + strlen(PPel[i].PPval.font)+1;
- else
- // its a color PP
- PPlen += sizeof(PARAM)-1 + sizeof(ULONG);
- }
-
- // now we build up the PRESPARAM structure
- DosAllocMem ((PPVOID) &pPP, PPlen, fALLOC);
-
- // Danger: PRESPARAMS is so braindead that it is unworkable
- // as designed. It uses a PARAM as an indexed array
- // internally, but PARAM is variable length so that
- // the indexing fails after the first element!
- pPP->cb = PPlen - sizeof(ULONG);
- ixPP = pPP->aparam;
- for (i=0; PPel[i].PPtype; i++)
- {
- ixPP->id = PPel[i].PPtype;
- if (PPel[i].PPtype == PP_FONTNAMESIZE)
- { // its a font PP
- ixPP->cb = strlen(PPel[i].PPval.font)+1;
- strcpy(ixPP->ab, PPel[i].PPval.font);
- }
- else
- { // its a color PP
- ixPP->cb = sizeof(ULONG);
- memcpy(ixPP->ab, &PPel[i].PPval.color, sizeof(ULONG));
- }
- // now we set the index to the next PARAM element in the PRESPARAM structure
- // Here, we temporarily set ixPP to a PSZ so we can do byte size pointer
- // arithmetic
- ixPP = (PPARAM) (((PSZ) ixPP) + sizeof(PARAM)-1 + ixPP->cb);
- }
- return(pPP);
- }
-
- // ---------------------------------------------------------------------
-
-
-
-