home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / UFormElementFactory.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  54.7 KB  |  1,912 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. //    UFormElementFactory.cp
  20.  
  21. #include "UFormElementFactory.h"
  22.  
  23. // PowerPlant
  24. #include <LPane.h>
  25. #include <LCommander.h>
  26. #include <UReanimator.h>
  27. #include <UMemoryMgr.h>
  28. //#include <LEventHandler.h>
  29. //#include <LStyleSet.h>
  30. //#include <VStyleSet.h>
  31.  
  32. // MacFE
  33. #include "CHTMLView.h"
  34. #include "CNSContext.h"
  35. #include "resgui.h"
  36. #include "uprefd.h"
  37. #include "mforms.h"
  38. #include "CConfigActiveScroller.h"
  39. #include "macgui.h"
  40. #include "macutil.h"
  41. #include "ufilemgr.h"
  42. #include "uintl.h"
  43. #include "CAutoPtr.h"
  44.  
  45. // Backend
  46. #include "lo_ele.h"    // for struct def'n
  47. #include "xlate.h"
  48. #include "fe_proto.h"
  49. #include "prefapi.h"
  50.  
  51. // macros
  52. #define FEDATAPANE    ((FormFEData *)formElem->element_data->ele_minimal.FE_Data)->fPane    
  53. #define FEDATAHOST     ((FormFEData *)formElem->element_data->ele_minimal.FE_Data)->fHost
  54. // These defines add extra spacing to the controls.
  55. // The spacing is needed because the layout puts them too close otherwise
  56. #define buttonTopExtra 1
  57. #define buttomLeftExtra 1
  58. #define buttonRightExtra 1
  59. #define buttonBottomExtra 1
  60.  
  61. #define textTopExtra 1
  62. #define textLeftExtra 1
  63. #define textRightExtra 1
  64. #define textBottomExtra 1
  65.  
  66. void FE_FreeFormElement(
  67.     MWContext*                 /* inContext */,
  68.     LO_FormElementData *    inFormData)
  69. {
  70.     UFormElementFactory::FreeFormElement(inFormData);
  71. }
  72.  
  73. // prototypes
  74. Boolean SetFE_Data(LO_FormElementStruct *formElem, LPane * pane, LFormElement *host, LCommander *commander);
  75. Boolean HasFormWidget(LO_FormElementStruct *formElem);
  76.  
  77. // utilities
  78. inline  FormFEData *GetFEData(LO_FormElementStruct *formElem) { return ((FormFEData *)formElem->element_data->ele_minimal.FE_Data); }
  79. inline    LPane *GetFEDataPane( LO_FormElementStruct *formElem) { return FEDATAPANE; } 
  80.  
  81. // Sets the value of FE_Data structure in form element
  82. // Returns true if form is being created from scratch
  83. Boolean SetFE_Data(
  84.     LO_FormElementStruct* formElem,
  85.     LPane* pane,
  86.     LFormElement *host,
  87.     LCommander *commander)
  88. {
  89.     if (!formElem->element_data)
  90.         return false;
  91.     FormFEData *feData;
  92.     Boolean noFEData = ( formElem->element_data->ele_minimal.FE_Data == NULL );
  93.     
  94.     if ( noFEData )
  95.     {
  96.         FormFEData* feData = new FormFEData;
  97.         ThrowIfNil_( feData );
  98.         formElem->element_data->ele_minimal.FE_Data = feData;
  99.     }
  100.  
  101.     feData = (FormFEData *)formElem->element_data->ele_minimal.FE_Data;    
  102.     feData->fPane = pane;
  103.     feData->fHost = host;
  104.     feData->fCommander = commander;
  105.     
  106.     Assert_(host);
  107.     if (host)
  108.         host->SetFEData(feData);
  109.     return noFEData;
  110. }
  111.  
  112. Boolean HasFormWidget(
  113.     LO_FormElementStruct *formElem)
  114. {
  115.     return ((formElem->element_data->ele_minimal.FE_Data != NULL) &&
  116.             (FEDATAPANE != NULL));
  117. }
  118.  
  119. /******************************************************************************
  120.  *    CWhiteScroller 
  121.  * White background instead of gray 'wscr'
  122.  ******************************************************************************/
  123. class CWhiteScroller: public CConfigActiveScroller
  124. {
  125. public:
  126.     friend class CHyperView;
  127.     
  128.                     enum { class_ID = 'wscr' };
  129.  
  130.                     CWhiteScroller( LStream* inStream );    
  131.     virtual Boolean    FocusDraw(LPane* inSubPane = nil);
  132.     virtual void    DrawSelf();
  133. };
  134.  
  135. CWhiteScroller::CWhiteScroller(LStream *inStream)
  136.     :    CConfigActiveScroller(inStream)
  137. {
  138. }
  139.  
  140. // The only real routine. Sets background to white
  141. Boolean CWhiteScroller::FocusDraw(LPane* /*inSubPane*/)
  142. {
  143.     if (LScroller::FocusDraw())
  144.     {
  145.         UGraphics::SetBack(CPrefs::White);
  146.         return TRUE;
  147.     }
  148.     else
  149.     {
  150.         return FALSE;
  151.     }
  152. }
  153.  
  154. void CWhiteScroller::DrawSelf()
  155. {
  156.     Rect    frame;
  157.     if (CalcLocalFrameRect(frame) && IsVisible() && 
  158.         mUpdateRgnH && ((*mUpdateRgnH)->rgnBBox.top != (*mUpdateRgnH)->rgnBBox.bottom))    // Only erase on update
  159.         ::EraseRect(&frame);
  160.         
  161. //    if ((mVerticalBar && mVerticalBar->IsVisible()) || (mHorizontalBar && mHorizontalBar->IsVisible()))
  162. //        ::EraseRect(&frame);
  163.  
  164.     LScroller::DrawSelf();    
  165. }
  166.  
  167. /*********************************************************************
  168.  * StModifyPPob
  169.  * Modifying PPob for dynamic change of the text resource ID when loading
  170.  * Constructor modifies the resource by sticking a resID at the appropriate
  171.  * offset.
  172.  * Destructor restores it.
  173.  * Offsets are generated by looking them up in Resourcerer
  174.  *********************************************************************/
  175. class StModifyPPob {
  176.     Int16 fResID;
  177.     Int16 fOffset;
  178.     Int16 fOldTextR;
  179. public:
  180.     StModifyPPob(Int16 resID, // Resource of the PPob to be modified
  181.                 Int16 offset, // Offset into the resource
  182.                 Int16 csid,        // Charset of the current doc
  183.                 Boolean button);    // Which TxtR are we looking for (TRUE = button, FALSE = text)
  184.     ~StModifyPPob();
  185. };
  186.  
  187. StModifyPPob::StModifyPPob(Int16 resID, Int16 offset, Int16 csid, Boolean button)
  188. {
  189.     fResID = resID;
  190.     fOffset = offset;
  191.  
  192.     Int16 newTextR;
  193.     if (button)
  194.         newTextR = CPrefs::GetButtonFontTextResIDs(csid);
  195.     else 
  196.         newTextR = CPrefs::GetTextFieldTextResIDs(csid);
  197.     
  198.     Handle r = ::GetResource('PPob', fResID);
  199.     ThrowIfNil_(r);
  200.     HNoPurge(r);
  201.     // Modify the resource
  202.     StHandleLocker lock(r);
  203.     Int16 * myPointer = (Int16*)(*r + fOffset);
  204.     fOldTextR = *myPointer;
  205.     *myPointer = newTextR;
  206. }
  207.  
  208. StModifyPPob::~StModifyPPob()
  209. {
  210.     Handle r = ::GetResource('PPob', fResID);
  211.     StHandleLocker lock(r);
  212.     Int16 * myPointer = (Int16*)(*r + fOffset);;
  213.     *myPointer = fOldTextR;
  214.     HPurge(r);
  215. }
  216.  
  217. void UFormElementFactory::RegisterFormTypes()
  218. {
  219.     RegisterClass_( CFormButton);
  220.     RegisterClass_( CGAFormPushButton);
  221.     RegisterClass_( CFormList);
  222.     RegisterClass_( CFormLittleText);
  223.     RegisterClass_( CFormBigText);
  224.     RegisterClass_( CFormRadio);
  225.     RegisterClass_( CGAFormRadio);
  226.     RegisterClass_( CFormCheckbox);
  227.     RegisterClass_( CGAFormCheckbox);
  228.     RegisterClass_( CFormFile);
  229.     RegisterClass_( CFormFileEditField);
  230.     RegisterClass_( CWhiteScroller);
  231. }
  232.  
  233. //
  234. // Figures out what kind of form element we're dealing with and dispatches *that*
  235. //
  236. void UFormElementFactory::MakeFormElem(
  237.     CHTMLView* inHTMLView,
  238.     CNSContext*    inNSContext,
  239.     LO_FormElementStruct* formElem)
  240. {
  241.     if (!formElem->element_data)
  242.         return;
  243.     Try_    {
  244.     Int32        width;
  245.     Int32        height;
  246.     Int32        baseline;
  247.  
  248.     switch ( formElem->element_data->type )
  249.     {
  250.         case FORM_TYPE_TEXT:
  251.         case FORM_TYPE_PASSWORD:
  252.         case FORM_TYPE_ISINDEX:
  253.             MakeTextFormElem(inHTMLView, inNSContext, width, height, baseline, formElem);
  254.             break;
  255.         case FORM_TYPE_READONLY:
  256.             MakeReadOnlyFormElem(inHTMLView, inNSContext, width, height, baseline, formElem);
  257.             break;
  258.         
  259.         case FORM_TYPE_TEXTAREA:
  260.             MakeTextArea(inHTMLView, inNSContext, width, height, baseline, formElem);
  261.             break;
  262.         
  263.         case FORM_TYPE_RADIO:
  264.         case FORM_TYPE_CHECKBOX:
  265.             MakeToggle(inHTMLView, inNSContext, width, height, baseline, formElem);
  266.             break;
  267.         
  268.         case FORM_TYPE_HIDDEN:
  269.         case FORM_TYPE_KEYGEN:
  270.         case FORM_TYPE_OBJECT:
  271.             width = height = baseline = 0;
  272.             break;
  273.         
  274.         case FORM_TYPE_SUBMIT:
  275.         case FORM_TYPE_RESET:
  276.         case FORM_TYPE_BUTTON:
  277.             MakeButton(inHTMLView, inNSContext, width, height, baseline, formElem);
  278.             break;
  279.  
  280.         case FORM_TYPE_FILE:
  281.             MakeFilePicker(inHTMLView, inNSContext, width, height, baseline, formElem);
  282.             break;
  283.  
  284.         case FORM_TYPE_SELECT_ONE:
  285.             MakePopup(inHTMLView, inNSContext, width, height, baseline,formElem);
  286.             break;
  287.         
  288.         case FORM_TYPE_SELECT_MULT:
  289.             MakeList(inHTMLView, inNSContext, width, height, baseline, formElem);
  290.         break;
  291.         
  292.         case FORM_TYPE_IMAGE:
  293.         case FORM_TYPE_JOT:
  294.         default:
  295.             Assert_(FALSE);
  296.         break;
  297.     };
  298.     
  299.     formElem->width = width;
  300.     formElem->height = height;
  301.     formElem->baseline = baseline;
  302.     }
  303.     Catch_(inErr)
  304.     {
  305.         Assert_(FALSE);
  306.     }
  307.     EndCatch_
  308. }
  309.  
  310. // Creates a simple edit text field
  311. // textData->size is the number of characters
  312. // textData->max_size is the maximum number of characters
  313. // textData->default_text is the default text
  314. LPane*    UFormElementFactory::MakeTextFormElem(
  315.     CHTMLView* inHTMLView,
  316.     CNSContext*    inNSContext,
  317.     Int32 &width, Int32 &height, Int32& baseline,
  318.     LO_FormElementStruct *formElem)
  319. {
  320.     if (!formElem->element_data)
  321.         return nil;
  322.     CFormLittleText * editField;
  323.     if (!HasFormWidget(formElem))
  324.     {
  325.     // If we did not have a control, create one
  326.         lo_FormElementTextData * textData = (lo_FormElementTextData *) formElem->element_data;
  327.         LCommander::SetDefaultCommander(inHTMLView);    // For tabbing
  328.         LPane::SetDefaultView(inHTMLView);
  329.         switch (textData->type)    {
  330.             case FORM_TYPE_TEXT:
  331.             case FORM_TYPE_ISINDEX:
  332.             {
  333.                 StModifyPPob modifier(formTextField, 0x3F, inNSContext->GetWinCSID(), false);
  334.                 editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formTextField);
  335.             }
  336.                 break;
  337.             case FORM_TYPE_PASSWORD:
  338.                 editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formPasswordField);
  339.                 break;
  340.             default:
  341.                 Throw_(0);
  342.         }
  343.         ThrowIfNil_(editField);
  344.     
  345.         editField->InitFormElement(*inNSContext, formElem);
  346.  
  347.         editField->FinishCreate();
  348.         editField->AddListener(inHTMLView);
  349.         if (textData->max_size < 0)
  350.             textData->max_size = 32000;
  351.         editField->SetMaxChars(textData->max_size);
  352.         editField->SetVisibleChars(textData->size);
  353.         editField->SetLayoutForm(formElem);
  354.  
  355.     // Reset the value
  356.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,editField,editField, editField));
  357.  
  358.     // Secure fields are disabled
  359.     }
  360.     else
  361.     {
  362.         //
  363.         // We've already created a widget for the
  364.         // form element, but layout has gone and
  365.         // reallocated the form element, so we must
  366.         // update our reference to it.
  367.         //
  368.         editField = (CFormLittleText *)FEDATAPANE;
  369.         if (!editField)
  370.             return NULL;
  371.         editField->SetLayoutForm(formElem);        // CWhiteEdit field only (never uses it...)
  372.         editField->SetLayoutElement(formElem);    // mocha mix-in needs to know too...
  373.     }
  374.     
  375. // Figure out dimensions
  376.     SDimension16 size;
  377.     editField->GetFrameSize(size);
  378.     width = size.width + textLeftExtra + textRightExtra;
  379.     height = size.height + textTopExtra + textBottomExtra;;
  380.     TEHandle textH = editField->GetMacTEH();
  381.     baseline = (*textH)->fontAscent + 2 + textTopExtra;
  382.     return editField;
  383. }
  384.  
  385. // Very similar to MakeTextFormElem, for now
  386. LPane * UFormElementFactory::MakeReadOnlyFormElem(
  387.     CHTMLView* inHTMLView,
  388.     CNSContext*    inNSContext,
  389.     Int32 &width,
  390.     Int32 &height,
  391.     Int32& baseline,
  392.     LO_FormElementStruct *formElem)
  393. {
  394.     if (!formElem->element_data)
  395.         return nil;
  396.     CFormLittleText * editField;
  397.     if (!HasFormWidget(formElem))
  398.     {
  399.     // If we did not have a control, create one
  400.         lo_FormElementMinimalData * readData = (lo_FormElementMinimalData *) formElem->element_data;
  401.         LCommander::SetDefaultCommander(inHTMLView);    // For tabbing
  402.         LPane::SetDefaultView(inHTMLView);
  403.         StModifyPPob modifier(formTextField, 0x3F, inNSContext->GetWinCSID(), false);
  404.         editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formTextField);
  405.         ThrowIfNil_(editField);
  406.  
  407.         editField->InitFormElement(*inNSContext, formElem);
  408.         editField->FinishCreate();
  409.         editField->SetLayoutForm(formElem);
  410.         editField->Disable();
  411.  
  412.     // Reset the value
  413.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,editField,editField, editField));
  414.         char * newText;
  415.         PA_LOCK(newText, char* , readData->value);
  416.         editField->SetDescriptor(CStr255(newText));
  417.         editField->SetVisibleChars(newText ? XP_STRLEN(newText) : 10);
  418.         PA_UNLOCK(readData->value);
  419.  
  420.     }
  421.     else
  422.     {
  423.         //
  424.         // We've already created a widget for the
  425.         // form element, but layout has gone and
  426.         // reallocated the form element, so we must
  427.         // update our reference to it.
  428.         //
  429.  
  430.         editField = (CFormLittleText *)FEDATAPANE;
  431.         if (!editField)
  432.             return NULL;
  433.         editField->SetLayoutForm(formElem);
  434.         editField->SetLayoutElement(formElem);
  435.     }
  436.     
  437.     
  438.     
  439. // Figure out dimensions
  440.     SDimension16 size;
  441.     editField->GetFrameSize(size);
  442.     width = size.width + textLeftExtra + textRightExtra;
  443.     height = size.height + textTopExtra + textBottomExtra;;
  444.     TEHandle textH = editField->GetMacTEH();
  445.     baseline = (*textH)->fontAscent + 2 + textTopExtra;
  446.     return editField;
  447. }
  448.  
  449. #define BigTextLeftIndent 5    // same constants are in the forms.r
  450. #define BigTextRightIndent 1
  451. #define BigTextTopIndent 1
  452. #define BigTextBottomIndent 1
  453. // Creates a text area
  454. //    textAreaData->default_text;
  455. //    textAreaData->rows;
  456. //    textAreaData->cols;
  457. LPane* UFormElementFactory::MakeTextArea(
  458.     CHTMLView* inHTMLView,
  459.     CNSContext*    inNSContext,
  460.     Int32 &width,
  461.     Int32 &height,
  462.     Int32& baseline,
  463.     LO_FormElementStruct *formElem)
  464. {
  465.     if (!formElem->element_data)
  466.         return nil;
  467.     CWhiteScroller * theScroller = NULL;
  468.     CFormBigText * theTextView = NULL;
  469.     FontInfo fontInfo;
  470.     if (!HasFormWidget(formElem))                // If there is no form, create it
  471.         {    
  472.         lo_FormElementTextareaData * textAreaData = (lo_FormElementTextareaData *) formElem->element_data;
  473.     
  474.         // Create the view
  475.         LCommander::SetDefaultCommander(inHTMLView);
  476.         LView::SetDefaultView(inHTMLView);
  477.     
  478.         // since I can't find an API to switch the word wrap property after the element
  479.         // has been initialized, we need to create two separate PPob's. Read in the
  480.         // appropriate one depending on if the text area requires wrapping or not.
  481.         ResIDT elementToRead = 0;
  482.         switch(textAreaData->auto_wrap) {
  483.             case TEXTAREA_WRAP_SOFT:
  484.             case TEXTAREA_WRAP_HARD:
  485.                 elementToRead = formBigText;
  486.                 break;
  487.                 
  488.             case TEXTAREA_WRAP_OFF:
  489.                 elementToRead = formBigTextScroll;
  490.                 break;
  491.                 
  492.         } // case of wrap property
  493.                 
  494.         theScroller = (CWhiteScroller *)UReanimator::ReadObjects('PPob', elementToRead);
  495.         ThrowIfNil_(theScroller);
  496.         theScroller->FinishCreate();
  497.         theScroller->PutInside(inHTMLView);
  498.     
  499.         theTextView = (CFormBigText*)theScroller->FindPaneByID(formBigTextID);
  500.         Assert_(theTextView != NULL);
  501.  
  502.         LModelObject* theSuper = inHTMLView->GetFormElemBaseModel();
  503.         theTextView->InitFormElement(*inNSContext, formElem);
  504.  
  505.         // Add the undoer for text actions.  This will be on a per-text field basis
  506.         LUndoer* theUndoer = new LUndoer;
  507.         theTextView->AddAttachment(theUndoer);
  508.         
  509.         // Resize to proper size
  510.         theTextView->FocusDraw();
  511.         ::GetFontInfo(&fontInfo);
  512.         short wantedWidth = textAreaData->cols * fontInfo.widMax + 8;
  513.         short wantedHeight = textAreaData->rows * (fontInfo.ascent + fontInfo.descent + fontInfo.leading) + 8;
  514.         
  515.         // make the image big so there is something to scroll, if necessary....
  516.         if ( textAreaData->auto_wrap == TEXTAREA_WRAP_OFF )
  517.             theTextView->ResizeImageTo(2000, 0, false);
  518.         
  519.         theScroller->ResizeFrameTo(wantedWidth + 16 + BigTextLeftIndent + BigTextRightIndent,
  520.                                    wantedHeight + 16 + BigTextTopIndent + BigTextBottomIndent,
  521.                                    FALSE);
  522.                                    
  523.     // Set the default values.
  524.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem, theScroller, theTextView, theTextView));
  525.  
  526.         theScroller->Show();
  527.         }
  528.     else
  529.         {
  530.         theScroller = (CWhiteScroller*)FEDATAPANE;
  531.         if (!theScroller)
  532.             return NULL;
  533.         theTextView = (CFormBigText*)theScroller->FindPaneByID(formBigTextID);
  534.         theTextView->FocusDraw();
  535.         
  536.         //
  537.         // We've already created a widget for the
  538.         // form element, but layout has gone and
  539.         // reallocated the form element, so we must
  540.         // update our reference to it.
  541.         //
  542.         theTextView->SetLayoutElement(formElem);
  543.         ::GetFontInfo(&fontInfo);
  544.         }        
  545.     
  546.     SDimension16 size;
  547.     theScroller->GetFrameSize(size);
  548.     width = size.width + textLeftExtra + textRightExtra;;
  549.     height = size.height + textTopExtra + textBottomExtra;;
  550.     baseline = fontInfo.ascent + 2;
  551.     
  552.     return theScroller;
  553. }
  554.  
  555. // Creates a button
  556. //    buttonData->name; is buttons name
  557. // Buttons store the form element as the refCon, so that they can broadcast
  558. // to the window.
  559. LPane* UFormElementFactory::MakeButton(
  560.     CHTMLView* inHTMLView,
  561.     CNSContext* inNSContext,
  562.     Int32 &width,
  563.     Int32 &height,
  564.     Int32& baseline,
  565.     LO_FormElementStruct *formElem)
  566. {
  567.     if (!formElem->element_data)
  568.         return nil;
  569.     LControl*        theControl = nil;
  570.     LPane*            thePane = nil;
  571.     LFormElement*    theHost = nil;
  572.     lo_FormElementMinimalData * buttonData= (lo_FormElementMinimalData *)formElem->element_data;
  573.     FontInfo info;
  574.     
  575.     if (!HasFormWidget(formElem))
  576.     {
  577.         // FIX ME?
  578.         LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort()));
  579.         LPane::SetDefaultView(inHTMLView);
  580.         switch (buttonData->type)    {
  581.             case FORM_TYPE_SUBMIT:
  582.                 {
  583.                     XP_Bool    useGrayscaleFormControls;
  584.                     int        prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls);
  585.                     
  586.                     if (prefResult == PREF_NOERROR && useGrayscaleFormControls)
  587.                     {
  588.                         StModifyPPob modifier(formGASubmitButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  589.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGASubmitButton));
  590.                     }
  591.                     else
  592.                     {
  593.                         StModifyPPob modifier(formSubmitButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  594.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formSubmitButton));
  595.                     }
  596.                 }
  597.                 break;
  598.             case FORM_TYPE_RESET:
  599.                 {
  600.                     XP_Bool    useGrayscaleFormControls;
  601.                     int        prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls);
  602.                     
  603.                     if (prefResult == PREF_NOERROR && useGrayscaleFormControls)
  604.                     {
  605.                         StModifyPPob modifier(formGAResetButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  606.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGAResetButton));
  607.                     }
  608.                     else
  609.                     {
  610.                         StModifyPPob modifier(formResetButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  611.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formResetButton));
  612.                     }
  613.                 }
  614.                 break;
  615.             case FORM_TYPE_BUTTON:
  616.                 {
  617.                     XP_Bool    useGrayscaleFormControls;
  618.                     int        prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls);
  619.                     
  620.                     if (prefResult == PREF_NOERROR && useGrayscaleFormControls)
  621.                     {
  622.                         StModifyPPob modifier(formGAPlainButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  623.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGAPlainButton));
  624.                     }
  625.                     else
  626.                     {
  627.                         StModifyPPob modifier(formPlainButton, 0x46, inNSContext->GetWinCSID(), TRUE);
  628.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formPlainButton));
  629.                     }
  630.                 }
  631.                 break;
  632.             default:
  633.                 Throw_(0);
  634.         }
  635.         
  636.         ThrowIfNil_(theHost = dynamic_cast<LFormElement*>(thePane));
  637.         ThrowIfNil_(theControl = dynamic_cast<LControl*>(thePane));
  638.  
  639.         thePane->FinishCreate();
  640.         theHost->InitFormElement(*inNSContext, formElem);
  641.  
  642.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,thePane,theHost, NULL));
  643.     // Set up buttons as broadcasters. Store the LO_FormElementStruct * in refCon
  644.         theControl->AddListener(inHTMLView);
  645.     }
  646.     else
  647.     {
  648.         thePane = FEDATAPANE;
  649.         ThrowIfNil_(theHost = dynamic_cast<LFormElement*>(thePane));
  650.         ThrowIfNil_(theControl = dynamic_cast<LControl*>(thePane));
  651.         
  652.         //
  653.         // We've already created a widget for the
  654.         // form element, but layout has gone and
  655.         // reallocated the form element, so we must
  656.         // update our reference to it.
  657.         //
  658.         theHost->SetLayoutElement(formElem);
  659.     }
  660.     
  661.     thePane->SetUserCon((long)formElem); // Always do this
  662.     
  663.     char * name;
  664.     PA_LOCK(name, char*, buttonData->value);
  665.     CStr255 pName(name);
  666.     thePane->SetDescriptor(pName);
  667.     PA_UNLOCK(buttonData->value);
  668.     ::GetFontInfo(&info);
  669.     
  670. // Get width/height/baseline
  671.     SDimension16 size;
  672.     thePane->GetFrameSize(size);
  673.     width = size.width + buttomLeftExtra + buttonRightExtra;
  674.     height = size.height + buttonTopExtra + buttonBottomExtra;
  675.     baseline = info.ascent + 2 + buttonTopExtra;
  676.     return thePane;
  677. }
  678.  
  679. LPane* UFormElementFactory::MakeFilePicker(
  680.     CHTMLView* inHTMLView,
  681.     CNSContext* inNSContext,
  682.     Int32 &width,
  683.     Int32 &height,
  684.     Int32& baseline,
  685.     LO_FormElementStruct *formElem)
  686. {
  687.     if (!formElem->element_data)
  688.         return nil;
  689.     CFormFile * filePicker = NULL;
  690.     lo_FormElementTextData * pickerData= (lo_FormElementTextData *)formElem->element_data;
  691.     
  692.     if (!HasFormWidget(formElem))
  693.     {
  694.         // FIX ME?
  695.         LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort()));
  696.         LPane::SetDefaultView(inHTMLView);
  697.         filePicker = (CFormFile *)UReanimator::ReadObjects('PPob', formFilePicker);
  698.         ThrowIfNil_(filePicker);
  699.  
  700.         filePicker->InitFormElement(*inNSContext, formElem);
  701.  
  702.         filePicker->FinishCreate();
  703.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,filePicker,filePicker, filePicker->fEditField));
  704.     }
  705.     else
  706.     {
  707.         //
  708.         // We've already created a widget for the
  709.         // form element, but layout has gone and
  710.         // reallocated the form element, so we must
  711.         // update our reference to it.
  712.         //
  713.         filePicker = (CFormFile *)FEDATAPANE;
  714.         if (!filePicker)
  715.             return NULL;
  716.         filePicker->SetLayoutElement(formElem);
  717.     }
  718.  
  719.     
  720. /*
  721.     char * name;
  722.     PA_LOCK(name, char*, pickerData->default_text);
  723.     CStr255 pName(name);
  724.     filePicker->SetDescriptor(pName);
  725.     PA_UNLOCK(pickerData->default_text);
  726.     ::GetFontInfo(&info);
  727. */
  728.     
  729. // Get width/height/baseline
  730.     filePicker->GetFontInfo(width, height, baseline);
  731.     width = width + buttomLeftExtra + buttonRightExtra;
  732.     height = height + buttonTopExtra + buttonBottomExtra;
  733.     return filePicker;
  734. }
  735.  
  736. // Creates buttons/checkboxes
  737. // Boolean toggleData->default_toggle is default on/off
  738. LPane* UFormElementFactory::MakeToggle(
  739.     CHTMLView* inHTMLView,
  740.     CNSContext* inNSContext,
  741.     Int32 &width,
  742.     Int32 &height,
  743.     Int32& baseline,
  744.     LO_FormElementStruct *formElem)
  745. {
  746.     if (!formElem->element_data)
  747.         return nil;
  748.         
  749.     LControl*    toggle = nil;
  750.     LPane*        thePane;
  751.     LFormElement *host;
  752.     lo_FormElementToggleData * toggleData = (lo_FormElementToggleData *)formElem->element_data;
  753.     if (!HasFormWidget(formElem))
  754.     {
  755.         // FIX ME?
  756.         LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort()));
  757.         LPane::SetDefaultView(inHTMLView);
  758.         switch (toggleData->type)
  759.         {
  760.             case FORM_TYPE_RADIO:
  761.                 {
  762.                     XP_Bool    useGrayscaleFormControls;
  763.                     int        prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls);
  764.                     
  765.                     if (prefResult == PREF_NOERROR && useGrayscaleFormControls)
  766.                     {
  767.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGARadio));
  768.                     }
  769.                     else
  770.                     {
  771.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formRadio));
  772.                     }
  773.                 }
  774.                 break;
  775.             case FORM_TYPE_CHECKBOX:
  776.                 {
  777.                     XP_Bool    useGrayscaleFormControls;
  778.                     int        prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls);
  779.                     
  780.                     if (prefResult == PREF_NOERROR && useGrayscaleFormControls)
  781.                     {
  782.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGACheckbox));
  783.                     }
  784.                     else
  785.                     {
  786.                         ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formCheckbox));
  787.                     }
  788.                 }
  789.                 break;
  790.             default:
  791.                 Throw_(0);
  792.         }
  793.  
  794.         ThrowIfNil_(host    = dynamic_cast<LFormElement*>(thePane));
  795.         ThrowIfNil_(toggle    = dynamic_cast<LControl*>(thePane));
  796.  
  797.         host->InitFormElement(*inNSContext, formElem);
  798.             
  799.         thePane->FinishCreate();
  800.         thePane->Enable();
  801.  
  802.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,toggle, host, NULL ));
  803.             
  804.         // Set up toggles as broadcasters. Store the LO_FormElementStruct * in refCon
  805. //        toggle->AddListener(this);
  806.  
  807.     }
  808.     else
  809.     {
  810.         LFormElement*    formWidget;
  811.         
  812.         lo_FormElementToggleData* toggleData = (lo_FormElementToggleData *)formElem->element_data;
  813.         toggle = dynamic_cast<LControl*>(FEDATAPANE);
  814.         if (!toggle)
  815.             return NULL;
  816.         
  817.         // We've already created a widget for the
  818.         // form element, but layout has gone and
  819.         // reallocated the form element, so we must
  820.         // update our reference to it.
  821.         //
  822.         if (toggleData->type == FORM_TYPE_RADIO)                // fun with C++ casting
  823.         {
  824.             formWidget = dynamic_cast<LFormElement*>(toggle);
  825.             ThrowIfNil_(formWidget);
  826.         }
  827.         else if (toggleData->type == FORM_TYPE_CHECKBOX)
  828.         {
  829.             formWidget = dynamic_cast<LFormElement*>(toggle);
  830.             ThrowIfNil_(formWidget);
  831.         }
  832.         else
  833.         {
  834.             Assert_(false);
  835.         }
  836.         
  837.         formWidget->SetLayoutElement(formElem);
  838.     }
  839.     
  840.     toggle->SetUserCon((long)formElem);
  841.  
  842.     short extra;    // extra space to be left after the control
  843.     switch (toggleData->type)    {
  844.         case FORM_TYPE_RADIO:
  845.             extra = 3;
  846.             break;
  847.         case FORM_TYPE_CHECKBOX:
  848.             extra = 5;
  849.             break;
  850.     }
  851. // width/height/baseline
  852.     SDimension16 size;
  853.     toggle->GetFrameSize(size);
  854.     width = size.width + extra;
  855.     height = size.height;
  856.     baseline = size.height - 2;
  857.     return toggle;
  858. }
  859.  
  860. LPane* UFormElementFactory::MakePopup (
  861.     CHTMLView* inHTMLView,
  862.     CNSContext* inNSContext,
  863.     Int32 &width,
  864.     Int32 &height,
  865.     Int32& baseline,
  866.     LO_FormElementStruct *formElem)
  867. {
  868.     if (!formElem->element_data)
  869.         return nil;
  870.     if (!HasFormWidget(formElem))
  871.     {
  872.         lo_FormElementSelectData * selections = (lo_FormElementSelectData *)formElem->element_data;
  873.         // Create the popup
  874.         LCommander::SetDefaultCommander(inHTMLView);
  875.         LPane::SetDefaultView(inHTMLView);
  876.         
  877.         LPane* thePane = (LPane*)(UReanimator::ReadObjects ('PPob', formGAPopup));
  878.  
  879.         CGAPopupMenu* popupCtrl = dynamic_cast<CGAPopupMenu*>(thePane);
  880.         ThrowIfNil_(popupCtrl);
  881.         
  882.         popupCtrl->SetTextTraits(CPrefs::GetButtonFontTextResIDs(inNSContext->GetWinCSID()));
  883.  
  884.         popupCtrl->FinishCreate();
  885.  
  886.         // pointer from host widget to layout
  887.         popupCtrl->SetUserCon ((Int32)selections);
  888.         // tell popup what data to display
  889.         FormsPopup * popupText = new FormsPopup (popupCtrl, selections);
  890.         ThrowIfNil_(popupText);
  891.         
  892.         popupText->InitFormElement(*inNSContext, formElem);
  893.         
  894.         popupCtrl->AddAttachment (popupText);
  895.         // reset values
  896.         ResetFormElement(formElem, FALSE, SetFE_Data(formElem,popupCtrl,popupText, NULL ));            // Reset the selection
  897. #if 1    /*    POPUP MENU VERTICAL POSITION FIX */
  898.         FontInfo fontInfo;
  899.         GetFontInfo (&fontInfo);
  900. #endif
  901.         // Resize the popup to max width
  902.         short widgetBaseline;
  903.         Point popupSize = popupText->CalcTargetFrame (widgetBaseline);
  904.         popupCtrl->ResizeFrameTo (popupSize.h, popupSize.v, false);
  905.         width = popupSize.h;
  906.         height = popupSize.v + 1; // add 1 for "leading" between lines in forms
  907. #if 1    /*    POPUP MENU VERTICAL POSITION FIX */
  908.         baseline = fontInfo.ascent + 1;
  909. #else
  910.         baseline = widgetBaseline;
  911. #endif
  912.         
  913.         popupCtrl->Show();
  914.         popupCtrl->Enable();
  915.  
  916.         return popupCtrl;
  917.     }
  918.     else
  919.     {
  920.         LPane*            widget         = dynamic_cast<LPane*>(FEDATAPANE);
  921.         FormsPopup*     popupText     = dynamic_cast<FormsPopup*>(FEDATAHOST);
  922.         SDimension16     size;
  923.         
  924.         ThrowIfNil_(widget);
  925.         ThrowIfNil_(popupText);
  926.         
  927. #if 1    /*    POPUP MENU VERTICAL POSITION FIX */
  928.         FontInfo fontInfo;
  929.         GetFontInfo (&fontInfo);
  930. #endif
  931.         //
  932.         // We've already created a widget for the
  933.         // form element, but layout has gone and
  934.         // reallocated the form element, so we must
  935.         // update our reference to it.
  936.         //
  937.         if (popupText != NULL)
  938.             popupText->SetLayoutElement(formElem);
  939.             
  940.         if (widget != NULL)
  941.             widget->GetFrameSize(size);
  942.         width = size.width;
  943.         height = size.height + 1; // add 1 for "leading" between lines in forms
  944. #if 1    /*    POPUP MENU VERTICAL POSITION FIX */
  945.         baseline = fontInfo.ascent + 1;
  946. #else
  947.         baseline = 2;    // ERROR. Does not get the proper baseline
  948. #endif
  949.         return widget;
  950.     }
  951. }
  952.  
  953. LPane* UFormElementFactory::MakeList(
  954.     CHTMLView* inHTMLView,
  955.     CNSContext* inNSContext,
  956.     Int32 &width,
  957.     Int32 &height,
  958.     Int32& baseline,
  959.     LO_FormElementStruct *formElem)
  960. {
  961.     if (!formElem->element_data)
  962.         return nil;
  963.     CFormList * myList = NULL; // (CFormList*)FEDATAPANE;
  964.     if (!HasFormWidget(formElem))
  965.     {
  966.         lo_FormElementSelectData* selectData = (lo_FormElementSelectData *)formElem->element_data;
  967.         // Create the form
  968.         LCommander::SetDefaultCommander( inHTMLView );
  969.         LPane::SetDefaultView( inHTMLView );
  970.         StModifyPPob modifier( formScrollingList, 0x3C, inNSContext->GetWinCSID(), false );
  971.         myList = (CFormList *)UReanimator::ReadObjects( 'PPob', formScrollingList );
  972.         ThrowIfNil_( myList );
  973.  
  974.         myList->InitFormElement( *inNSContext, formElem );
  975.         myList->FinishCreate();
  976.  
  977.         // Initialize the list items from the form data
  978.         myList->SetSelectMultiple( selectData->multiple );
  979.         myList->SyncRows( selectData->option_cnt );
  980.         
  981.         ResetFormElement( formElem, FALSE,     SetFE_Data( formElem, myList, myList, myList) );            // Reset the selection
  982.         myList->ShrinkToFit( selectData->size );
  983.     }
  984.     else
  985.     {
  986.         myList = (CFormList*)FEDATAPANE;
  987.         if (!myList)
  988.             return NULL;
  989.         myList->FocusDraw();
  990.  
  991.         //
  992.         // We've already created a widget for the
  993.         // form element, but layout has gone and
  994.         // reallocated the form element, so we must
  995.         // update our reference to it.
  996.         //
  997.         myList->SetLayoutElement(formElem);
  998.     }
  999.     
  1000.     FontInfo        info;
  1001.     SDimension16    size;
  1002.  
  1003.     ::GetFontInfo( &info );
  1004.     myList->GetFrameSize( size );
  1005.  
  1006.     // +6 to account for the focus ring
  1007.     width    = size.width + 6;
  1008.     height     = size.height + 6;
  1009.  
  1010.     baseline = info.ascent;
  1011.     return myList;
  1012. }
  1013.  
  1014. // FreeFormElement is called when eric finally wants to free the FE form data
  1015. void UFormElementFactory::FreeFormElement(
  1016.     LO_FormElementData *formElem)
  1017. {
  1018.     XP_TRACE(("FreeFormElement, data %d \n", (Int32)formElem->ele_minimal.FE_Data));
  1019.     switch (formElem->type) {
  1020.         case FORM_TYPE_TEXT:
  1021.         case FORM_TYPE_PASSWORD:
  1022.         case FORM_TYPE_ISINDEX:        // Sets the original text
  1023.         case FORM_TYPE_FILE:
  1024.             if (formElem->ele_text.current_text)
  1025.                 PA_FREE(formElem->ele_text.current_text);
  1026.             formElem->ele_text.current_text = NULL;
  1027.             FormFEData * FEData = (FormFEData *)formElem->ele_text.FE_Data;
  1028.             if (FEData)
  1029.             {    // don't forget to null out pointer to FEData in fHost
  1030.                 if (FEData->fHost)
  1031.                     FEData->fHost->SetFEData(NULL);
  1032.                 delete FEData;
  1033.             }
  1034.             formElem->ele_text.FE_Data = NULL;
  1035.             break;
  1036.         case FORM_TYPE_TEXTAREA:
  1037.             if (formElem->ele_textarea.current_text)        // Free up the old memory
  1038.                 PA_FREE(formElem->ele_textarea.current_text);
  1039.             formElem->ele_textarea.current_text = NULL;
  1040.             FEData = (FormFEData *)formElem->ele_textarea.FE_Data;
  1041.             if (FEData)
  1042.             {    // don't forget to null out pointer to FEData in fHost
  1043.                 if (FEData->fHost)
  1044.                     FEData->fHost->SetFEData(NULL);
  1045.                 delete FEData;
  1046.             }
  1047.             formElem->ele_textarea.FE_Data = NULL;
  1048.             break;
  1049.         case FORM_TYPE_RADIO:
  1050.         case FORM_TYPE_CHECKBOX:
  1051.             FEData = (FormFEData *)formElem->ele_toggle.FE_Data;
  1052.             if (FEData)
  1053.             {    // don't forget to null out pointer to FEData in fHost
  1054.                 if (FEData->fHost)
  1055.                     FEData->fHost->SetFEData(NULL);
  1056.                 delete FEData;
  1057.             }
  1058.             formElem->ele_toggle.FE_Data = NULL;
  1059.             break;
  1060.         case FORM_TYPE_SELECT_ONE:
  1061.         case FORM_TYPE_SELECT_MULT:
  1062.             FEData = (FormFEData *)formElem->ele_select.FE_Data;
  1063.             if ( FEData )
  1064.             {    // don't forget to null out pointer to FEData in fHost
  1065.                 if (FEData->fHost)
  1066.                     FEData->fHost->SetFEData(NULL);
  1067.                 delete FEData;
  1068.             }
  1069.             formElem->ele_select.FE_Data = NULL;
  1070.             break;
  1071.         case FORM_TYPE_SUBMIT:
  1072.         case FORM_TYPE_RESET:
  1073.         case FORM_TYPE_BUTTON:
  1074.         case FORM_TYPE_READONLY:
  1075.             FEData = (FormFEData *)formElem->ele_minimal.FE_Data;
  1076.             if (FEData)
  1077.             {    // don't forget to null out pointer to FEData in fHost
  1078.                 if (FEData->fHost)
  1079.                     FEData->fHost->SetFEData(NULL);
  1080.                 delete FEData;
  1081.             }
  1082.             formElem->ele_minimal.FE_Data = NULL;
  1083.             break;
  1084.         case FORM_TYPE_HIDDEN:
  1085.         case FORM_TYPE_IMAGE:
  1086.         case FORM_TYPE_JOT:
  1087.         case FORM_TYPE_KEYGEN:
  1088.         case FORM_TYPE_OBJECT:
  1089.             // no FE_Data for these guys
  1090.             break;
  1091.     };
  1092. }
  1093.  
  1094. /*-----------------------------------------------------------------------------
  1095.     Forms. 
  1096.     lo_ele.h
  1097.     
  1098.     Just like in other web clients, size is the size in characters the field should be, 
  1099.     max_size is the maximum length in characters that can be entered.
  1100.     default_text is the text the user wants to have appear in the textfield
  1101.     on creation and reset.
  1102.     
  1103.     The layout needs the front end to fill in the width and height fields in the
  1104.     LO_FormElementStruct.  It also needs the baseline field filled in.
  1105.     This may be difficult to impossible on some front ends.  baseline is
  1106.     the y position from 0 to (height - 1) that should line up with regular text on
  1107.     the same line as this form element. If necessary, just punt to
  1108.     baseline = (height - 1).
  1109. -----------------------------------------------------------------------------*/
  1110.  
  1111. // Took out XP_TRACEFORM call, so why use this function?
  1112.  
  1113. void UFormElementFactory::DisplayFormElement(
  1114.     CNSContext* inNSContext,
  1115.     LO_FormElementStruct* formElem )
  1116. {
  1117.     Rect    oldElementFrame, newElementFrame;
  1118.     Int32    extraX, extraY;
  1119.     LPane    *pane;
  1120.  
  1121.     pane = 0;
  1122.  
  1123.     Try_    // Because stupid LNTextEdit does a throw when you resize it too large
  1124.     {        
  1125.         // Ñ the x,y passed to us originally may have been adjusted by layout
  1126.         //        so we have to update the widget. We don't actually need to draw it.
  1127.         //        It should only be adjusted once I think.
  1128.         if ( !XP_CheckElementSpan( *inNSContext,
  1129.             formElem->y + formElem->y_offset, formElem->height ) )
  1130.             return;
  1131.     
  1132.         if (!formElem->element_data)
  1133.             return; // jrm 97/03/21
  1134.  
  1135.         switch ( formElem->element_data->type )
  1136.         {
  1137.             case FORM_TYPE_SUBMIT:
  1138.             case FORM_TYPE_RESET:
  1139.             case FORM_TYPE_BUTTON:
  1140.             case FORM_TYPE_FILE:
  1141.                 if (GetFEData (formElem)) {
  1142.                     pane = GetFEDataPane(formElem);
  1143.                     extraX = buttomLeftExtra;    // [sic]
  1144.                     extraY = buttonTopExtra;
  1145.                 }
  1146.                 break;
  1147.  
  1148.             case FORM_TYPE_TEXT:
  1149.             case FORM_TYPE_PASSWORD:
  1150.             case FORM_TYPE_ISINDEX:
  1151.             case FORM_TYPE_READONLY:
  1152.             case FORM_TYPE_TEXTAREA:
  1153.                 if (GetFEData (formElem)) {
  1154.                     pane = GetFEDataPane(formElem);
  1155.                     extraX = textLeftExtra;
  1156.                     extraY = textTopExtra;
  1157.                 }
  1158.             break;
  1159.  
  1160.             case FORM_TYPE_RADIO:
  1161.             case FORM_TYPE_CHECKBOX:
  1162.             case FORM_TYPE_SELECT_ONE:
  1163.             case FORM_TYPE_SELECT_MULT:
  1164.                 if (GetFEData (formElem)) {
  1165.                     pane = GetFEDataPane(formElem);
  1166.                     extraX = 0;
  1167.                     extraY = 0;
  1168.                 }
  1169.                 break;
  1170.  
  1171.             case FORM_TYPE_OBJECT:
  1172.                 break;
  1173.  
  1174.             case FORM_TYPE_HIDDEN:
  1175.             case FORM_TYPE_KEYGEN:
  1176.             case FORM_TYPE_IMAGE:
  1177.             case FORM_TYPE_JOT:
  1178.             default:
  1179.                 Assert_(FALSE);
  1180.                 break;
  1181.         }
  1182.  
  1183.         if (pane) {
  1184.             if (pane->IsVisible() && formElem->ele_attrmask & LO_ELE_INVISIBLE) {
  1185.                 pane->Hide();
  1186.             }
  1187.             pane->CalcPortFrameRect (oldElementFrame);
  1188.             pane->PlaceInSuperImageAt (formElem->x + formElem->x_offset + extraX,
  1189.                                       formElem->y + formElem->y_offset + extraY, TRUE);
  1190.             pane->CalcPortFrameRect (newElementFrame);
  1191.             // if the element had to be moved, invalidate a slightly larger area than its current frame
  1192.             // (see notes below)
  1193.             if (oldElementFrame.top != newElementFrame.top || oldElementFrame.left != newElementFrame.left) {
  1194.                 newElementFrame.left--;
  1195.                 newElementFrame.top--;
  1196.                 newElementFrame.right++;
  1197.                 newElementFrame.bottom++;
  1198.                 pane->InvalPortRect (&newElementFrame);
  1199.             }
  1200.             if (!pane->IsVisible() && !(formElem->ele_attrmask & LO_ELE_INVISIBLE)) {
  1201.                 pane->Show();
  1202.                 pane->Enable();
  1203.             }
  1204.             pane->Draw(nil);
  1205.         }
  1206.     }
  1207.     Catch_(inErr)
  1208.     {}
  1209.     EndCatch_
  1210.  
  1211.     /*    Why we invalidate a slightly larger rectangle than that occupied by the form element
  1212.         pane itself: when generating a page from HTML, the compositor creates a unique layer
  1213.         for each form element.  This layer is strictly rectangular and slightly larger than
  1214.         the form element pane, and is used as a mask to punch out a hole in its background.
  1215.         If the new form element happens to be located in a table cell using a background
  1216.         color different from that used by the document, the element will have a frame
  1217.         of the document background color around it after the document has been created.
  1218.         That frame is temporary; it is erased when the document is redrawn, because on
  1219.         subsequent draw operations, the element frame is no longer used to punch a hole
  1220.         in the cell background.  The cell background is rendered in the same pass as the
  1221.         document background, before PowerPlant panes (already created form elements) are
  1222.         drawn.  Invalidating a slightly larger framerect when the form element pane
  1223.         is first moved onto the document forces the important part of that redraw to happen
  1224.         immediately, erasing the inappropriately colored frame around the pane.
  1225.     */
  1226. }
  1227.  
  1228. void UFormElementFactory::ResetFormElement(
  1229.     LO_FormElementStruct *formElem,
  1230.     Boolean redraw,
  1231.     Boolean fromDefaults)
  1232. {
  1233.     ResetFormElementData(formElem, redraw, fromDefaults, true);
  1234. }
  1235.  
  1236. void UFormElementFactory::SetFormElementToggle(
  1237.     LO_FormElementStruct* formElem,
  1238.     Boolean value )
  1239. {
  1240. #ifdef DEBUG
  1241.     if ( !formElem->element_data || formElem->element_data->type != FORM_TYPE_RADIO )
  1242.         XP_ABORT(("no form radio"));
  1243. #endif
  1244.  
  1245.     if ( !GetFEData( formElem ) )
  1246.         return;
  1247.     LStdControl* control = (LStdControl*)FEDATAPANE;
  1248.     if (!control)
  1249.         return;
  1250.     
  1251. //    control->SetValue( value );
  1252. //    control->Refresh();
  1253.     
  1254.     // MGY: In order to eliminate flickering, I changed the unenlightened call
  1255.     // to Refresh above to be a little more enlightened. TODO: find out why
  1256.     // it's here at all and remove it if no one can give a satifactory reason.
  1257.     // Before removing it, test both GA and non-GA toggles on a variety of backgfounds
  1258.     // to verify that it indeed did not perform any useful service.
  1259.  
  1260. #if 0
  1261.     Int32 oldValue = control->GetValue();
  1262.     if (value != oldValue)
  1263.     {
  1264.         control->SetValue(value);
  1265.         control->Refresh();
  1266.     }    
  1267. #endif
  1268.     
  1269.     // MGY: Do it this way instead
  1270.     
  1271.     control->SetValue(value);
  1272. }
  1273.  
  1274. void UFormElementFactory::FormTextIsSubmit(
  1275.     LO_FormElementStruct * formElem)
  1276. {
  1277.     if ( !GetFEData( formElem ) )
  1278.         return;
  1279.     if (!formElem->element_data)
  1280.         return;
  1281.     lo_FormElementTextData * textData = (lo_FormElementTextData *) formElem->element_data;
  1282.     CFormLittleText* editField = (CFormLittleText*)FEDATAPANE;
  1283.     if (editField)
  1284.         editField->SetBroadcast(TRUE);
  1285. }
  1286. //
  1287. // We should move this to some utility class
  1288. //
  1289. // To Do: Figure out is this ok for 
  1290. //     TEXTAREA_WRAP_OFF, TEXTAREA_WRAP_SOFT and TEXTAREA_WRAP_HARD
  1291. //
  1292. static char* ConvertDataInTextEnginToUTF8(CWASTEEdit* engine)
  1293. {
  1294.     Handle        h = engine->GetTextHandle();
  1295.     Int32        offset, theTextSize = engine->GetTextLength();
  1296.     ScriptCode    script;
  1297.     INTL_Encoding_ID    encoding;
  1298.     WERunInfo    runInfo;
  1299.     Int32        gatherSize = theTextSize * 3 + 1;
  1300.     char*        utf8gather = (char*)XP_ALLOC(gatherSize);    
  1301.     
  1302.     if(utf8gather) {
  1303.         StHandleLocker lock(h);
  1304.         *utf8gather = '\0';    // null terminated the beginning
  1305.  
  1306.         for (offset = 0; offset < theTextSize; ) {
  1307.             engine->GetRunInfo(offset, &runInfo);
  1308.             script = FontToScript(runInfo.runStyle.tsFont);
  1309.             encoding = ScriptToEncoding(script);
  1310.             
  1311.             Int32 runLength = runInfo.runEnd - runInfo.runStart;
  1312.             char * utftemp = (char*)INTL_ConvertLineWithoutAutoDetect (encoding, CS_UTF8, 
  1313.                 (unsigned char *)((*h) + offset), runLength);
  1314.             if(utftemp) {
  1315.                 XP_STRCAT(utf8gather, utftemp);            
  1316.                 XP_FREE(utftemp);
  1317.             }
  1318.             offset += runLength;
  1319.         }
  1320.  
  1321.         Int32 reallocatedLen = strlen(utf8gather) + 1;
  1322.         if(reallocatedLen < (gatherSize - 8))
  1323.         {    
  1324.             // Let's try to allocate a smalle buffer and return that instead if possible
  1325.             if(char* reallocated = (char*)XP_ALLOC(reallocatedLen))
  1326.             {
  1327.                 XP_STRCPY(reallocated,utf8gather);
  1328.                 XP_FREE(utf8gather);        
  1329.                 return reallocated;
  1330.             }
  1331.         }
  1332.         return utf8gather; // otherwise, just return the one we allocated.
  1333.     }
  1334.     
  1335.     return "";
  1336. }
  1337.  
  1338.  
  1339. void UFormElementFactory::GetFormElementValue(
  1340.     LO_FormElementStruct *formElem,
  1341.     Boolean hide)
  1342. {
  1343.     if (!formElem->element_data)
  1344.         return;
  1345.     Try_
  1346.     {
  1347.         switch (formElem->element_data->type)
  1348.         {
  1349.             case FORM_TYPE_TEXT:
  1350.             case FORM_TYPE_PASSWORD:
  1351.             case FORM_TYPE_ISINDEX:        // Sets the original text
  1352.                 {
  1353.                 if ( !GetFEData( formElem ) )
  1354.                     return;
  1355.                 lo_FormElementTextData* textData =  (lo_FormElementTextData*)formElem->element_data;
  1356.                 if (textData->current_text)
  1357.                     PA_FREE(textData->current_text);
  1358.                 textData->current_text = NULL;
  1359.                 
  1360.                 LEditField * editField = (LEditField*)FEDATAPANE;
  1361.                 if (!editField)
  1362.                     return;
  1363.                 CStr255 text;
  1364.                 editField->GetDescriptor(text);
  1365.                 textData->current_text = PA_ALLOC(text.Length() +1);
  1366.                 char * textPtr;
  1367.                 PA_LOCK(textPtr, char*, textData->current_text);
  1368.                 BlockMoveData(&(text[1]), textPtr, text.Length());
  1369.                 textPtr[text.Length()] = 0;
  1370.                 PA_UNLOCK(textData->current_text);
  1371.                 }
  1372.                 break;
  1373.                 
  1374.             case FORM_TYPE_TEXTAREA:
  1375.                 {
  1376.                 if ( !GetFEData( formElem ) )
  1377.                     return;
  1378.                 lo_FormElementTextareaData * textAreaData = (lo_FormElementTextareaData *) formElem->element_data;
  1379.                 if (textAreaData->current_text)        // Free up the old memory
  1380.                     PA_FREE(textAreaData->current_text);
  1381.                 textAreaData->current_text = NULL;
  1382.                 // find the views
  1383.                 LView * scroller = (LView*)FEDATAPANE;
  1384.                 if (!scroller)
  1385.                     return;
  1386.                 CSimpleTextView*  textEdit = (CSimpleTextView*)scroller->FindPaneByID(formBigTextID);
  1387.                 // Copy the text over
  1388.                 Handle h = NULL;
  1389.                 Boolean disposeHandle;        // Depending if we are making a copy of the text handle
  1390.                 if(CS_UTF8 == formElem->text_attr->charset)
  1391.                 {
  1392.                     disposeHandle = FALSE;
  1393.                     textAreaData->current_text = 
  1394.                         (PA_Block) ConvertDataInTextEnginToUTF8(dynamic_cast<CWASTEEdit *>(textEdit));            
  1395.                     
  1396.                 } else {
  1397.                     Int32 theTextSize;
  1398.                     switch(textAreaData->auto_wrap)
  1399.                         {
  1400.                         case TEXTAREA_WRAP_OFF:
  1401.                         case TEXTAREA_WRAP_SOFT:
  1402.                             {
  1403.                             disposeHandle = FALSE;
  1404.                             h = textEdit->GetTextHandle();
  1405.                             theTextSize = textEdit->GetTextLength();
  1406.                             }
  1407.                         break;
  1408.                         case TEXTAREA_WRAP_HARD:
  1409.                             {
  1410.                             
  1411.                             disposeHandle = TRUE;
  1412.                             h = TextHandleToHardLineBreaks( *textEdit );
  1413.                             theTextSize = ::GetHandleSize(h);
  1414.                                                         
  1415.                             }
  1416.                         break;        
  1417.                         }
  1418.                         
  1419.                     ThrowIfNULL_(h);
  1420.  
  1421.                     // note that in the hard wrapped case we're adding an extra null byte
  1422.                     // on the end.  this wont hurt.
  1423.                     char* newTextPtr = (char*)XP_ALLOC(theTextSize + 1);
  1424.                     ::BlockMoveData(*h, newTextPtr, theTextSize);
  1425.                     newTextPtr[theTextSize] = 0;
  1426.  
  1427.                     textAreaData->current_text = (PA_Block)newTextPtr;
  1428.                 }
  1429.  
  1430.                 if (disposeHandle)
  1431.                     DisposeHandle(h);
  1432.                 }
  1433.                 break;
  1434.                 
  1435.             case FORM_TYPE_RADIO:
  1436.             case FORM_TYPE_CHECKBOX:    // Sets the original check state
  1437.                 if ( !GetFEData( formElem ) )
  1438.                     return;
  1439.                 lo_FormElementToggleData * toggleData = (lo_FormElementToggleData*)formElem->element_data;
  1440.                 LStdControl * toggle = (LStdControl *)FEDATAPANE;
  1441.                 if (toggle)
  1442.                     toggleData->toggled = toggle->GetValue();
  1443.                 break;
  1444.             case FORM_TYPE_FILE:
  1445.                 lo_FormElementTextData * pickData = (lo_FormElementTextData*)formElem->element_data;
  1446.                 CFormFile * formFile = (CFormFile *)FEDATAPANE;
  1447.                 FSSpec spec;
  1448.                 if (formFile && formFile->GetFileSpec(spec))
  1449.                 {
  1450.                     char * fileURL = CFileMgr::EncodedPathNameFromFSSpec( spec, TRUE );
  1451.                     if (fileURL)
  1452.                     {
  1453.                         PA_Block newValueBlock = PA_ALLOC(XP_STRLEN(fileURL) + 1);
  1454.                         char * value;
  1455.                         PA_LOCK(value, char*, newValueBlock);
  1456.                         ::BlockMoveData(fileURL, value, XP_STRLEN(fileURL) + 1);
  1457.                         PA_UNLOCK(newValueBlock);
  1458.                         pickData->current_text = newValueBlock;
  1459.                         XP_FREE(fileURL);
  1460.                     }
  1461.                     else
  1462.                         pickData->current_text = NULL;
  1463.                 }
  1464.                 else
  1465.                     pickData->current_text = NULL;
  1466.                 break;
  1467.             case FORM_TYPE_HIDDEN:
  1468.             case FORM_TYPE_KEYGEN:
  1469.             case FORM_TYPE_SUBMIT:
  1470.             case FORM_TYPE_RESET:
  1471.             case FORM_TYPE_BUTTON:
  1472.             case FORM_TYPE_READONLY:
  1473.                 break;
  1474.             case FORM_TYPE_SELECT_ONE:
  1475.             {    // Resets the selects
  1476.                 if ( !GetFEData( formElem ) )
  1477.                     return;
  1478.                 lo_FormElementSelectData_struct* selections = &formElem->element_data->ele_select;
  1479.                 LButton* widget = (LButton*)FEDATAPANE;
  1480.                 int value = widget ? widget->GetValue() : 0;
  1481.                 lo_FormElementOptionData_struct* options = (lo_FormElementOptionData_struct*)selections->options;
  1482.                 for ( int i = 0; i < selections->option_cnt; i++ )
  1483.                     options[ i ].selected = FALSE;
  1484.                 if ( value )
  1485.                     options[ value - 1].selected = TRUE;
  1486.             }
  1487.             break;
  1488.             case FORM_TYPE_SELECT_MULT:
  1489.             {
  1490.                 lo_FormElementSelectData* selectData = (lo_FormElementSelectData *)formElem->element_data;
  1491.                 CFormList* myList = (CFormList*)FEDATAPANE;
  1492.                 if (!myList)
  1493.                     return;
  1494.                 lo_FormElementOptionData* mother = (lo_FormElementOptionData*)selectData->options;
  1495.                 for ( int i = 0 ; i < selectData->option_cnt; i++ )
  1496.                     mother[ i ].selected = myList->IsSelected( i );
  1497.             }
  1498.             break;
  1499.             case FORM_TYPE_IMAGE:
  1500.             case FORM_TYPE_JOT:
  1501.             case FORM_TYPE_OBJECT:
  1502.                 break;
  1503.         }
  1504.     }
  1505.     Catch_(inErr){}
  1506.     EndCatch_
  1507.     if (hide)
  1508.         HideFormElement(formElem);
  1509. }
  1510.  
  1511. void UFormElementFactory::HideFormElement(
  1512.     LO_FormElementStruct* formElem)
  1513. {
  1514.     if (!formElem->element_data)
  1515.         return;
  1516.     switch ( formElem->element_data->type )
  1517.     {
  1518.         case FORM_TYPE_TEXT:
  1519.         case FORM_TYPE_PASSWORD:
  1520.         case FORM_TYPE_ISINDEX:
  1521.         case FORM_TYPE_TEXTAREA:
  1522.         case FORM_TYPE_RADIO:
  1523.         case FORM_TYPE_CHECKBOX:
  1524.         case FORM_TYPE_SUBMIT:
  1525.         case FORM_TYPE_RESET:
  1526.         case FORM_TYPE_BUTTON:
  1527.         case FORM_TYPE_SELECT_ONE:
  1528.         case FORM_TYPE_SELECT_MULT:
  1529.         case FORM_TYPE_FILE:
  1530.         case FORM_TYPE_READONLY:
  1531.  
  1532.             LFormElement*    host = FEDATAHOST;
  1533.             
  1534.             // Schedule the form element to be destroyed.
  1535.             // We don't do it immediately because we may
  1536.             // be in the middle of a JavaScript which could
  1537.             // then return to some PowerPlant code which
  1538.             // still needs access to the form element widget
  1539.             //
  1540.             // Read the comments for MarkForDeath for more details
  1541.             //
  1542.             if (host != NULL)  {
  1543.                 host->MarkForDeath();
  1544.             }
  1545.                 
  1546.             FEDATAPANE = NULL;
  1547.             FEDATAHOST = NULL;            
  1548.             break;
  1549.             
  1550.             
  1551.         case FORM_TYPE_HIDDEN:
  1552.         case FORM_TYPE_KEYGEN:
  1553.             // no value to set or reset
  1554.         break;
  1555.         case FORM_TYPE_IMAGE:
  1556.         case FORM_TYPE_JOT:
  1557.         case FORM_TYPE_OBJECT:
  1558.         break;
  1559.     }
  1560. }
  1561. static void ValidateTextByCharset(int csid,    char* text)
  1562. {
  1563.     if(text && (csid & MULTIBYTE))
  1564.     {
  1565.         int pos;
  1566.         int lastIdx = 0;
  1567.         int boundary = strlen(text);
  1568.         for(pos = 0 ; pos < boundary ; pos += (INTL_IsLeadByte(csid, text[pos])+1))
  1569.             lastIdx = pos;
  1570.         if(pos != boundary)
  1571.             text[lastIdx] = '\0';
  1572.     }
  1573. }
  1574.  
  1575.  
  1576. static void PutUnicodeIntoTextEngine( CWASTEEdit* engine, INTL_Unicode* unicode, Int32 len)
  1577. {
  1578.     INTL_CompoundStr* cs = INTL_CompoundStrFromUnicode(unicode, len);
  1579.     UFontSwitcher* fs= UFixedFontSwitcher::Instance();
  1580.     if(cs)
  1581.     {
  1582.         // Clear the text before insertining text runs.
  1583.         engine->SelectAll();
  1584.         engine->Delete();
  1585.  
  1586.         INTL_Encoding_ID encoding;
  1587.         unsigned char* outtext;
  1588.         INTL_CompoundStrIterator iter;
  1589.         for(iter = INTL_CompoundStrFirstStr((INTL_CompoundStrIterator)cs, &encoding , &outtext);
  1590.                 iter != NULL;
  1591.                     iter = INTL_CompoundStrNextStr(iter, &encoding, &outtext))
  1592.         {
  1593.             if((outtext) && (*outtext))
  1594.             {
  1595.                 Int32    theTextSize = engine->GetTextLength();
  1596.                 // Set the Text
  1597.                 engine->SetSelection(LONG_MAX, LONG_MAX);
  1598.                 engine->InsertPtr((char*)outtext, XP_STRLEN((char*)outtext), NULL, NULL);
  1599.                 
  1600.                 CCharSet charset;    // Don't move this line since the fontname is point to it.
  1601.                 unsigned char* fontname;
  1602.                 switch(encoding)
  1603.                 {
  1604.                     case CS_SYMBOL:
  1605.                         fontname = (unsigned char*)"\pSymbol";
  1606.                         break;
  1607.                     case CS_DINGBATS:
  1608.                         fontname = (unsigned char*)"\pZapf Dingbats";
  1609.                         break;
  1610.                     default:
  1611.                         Boolean gotFont = CPrefs::GetFont(encoding, &charset);                    
  1612.                         Assert_(gotFont);
  1613.                         fontname = &charset.fPropFont[0];//fFixedFont[0];
  1614.                         break;                    
  1615.                 }
  1616.                 
  1617.                 TextStyle    inTextStyle;
  1618.                 GetFNum(fontname, &inTextStyle.tsFont);
  1619.                 engine->SetSelection(theTextSize, LONG_MAX);
  1620.                 engine->SetStyle(weDoFont, &inTextStyle);
  1621.             }
  1622.         }
  1623.         INTL_CompoundStrDestroy(cs);
  1624.     }
  1625. }
  1626.  
  1627.  
  1628. static void PutUTF8IntoTextEngine( CWASTEEdit* engine, char* text, Int32 len)
  1629. {
  1630.     if(len >0)
  1631.     {
  1632.         uint32 ubuflen = len+1;
  1633.         uint32 ucs2len;
  1634.         INTL_Unicode* ucs2buf = NULL;
  1635.         ucs2buf = new INTL_Unicode[ubuflen];
  1636.         if(ucs2buf && (0 != (ucs2len = UUTF8TextHandler::Instance()->UTF8ToUCS2((unsigned char*) text, len, ucs2buf,  ubuflen) )))
  1637.             PutUnicodeIntoTextEngine(engine, ucs2buf, ucs2len);    
  1638.         else
  1639.             Assert_(FALSE);
  1640.             
  1641.         if(ucs2buf)
  1642.             delete ucs2buf;
  1643.     }
  1644. }
  1645.  
  1646.  
  1647. static void ChangeTextTraitsForSingleScript( CWASTEEdit* engine, unsigned short csid)
  1648. {
  1649.     TextTraitsH    theTextTraits = UTextTraits::LoadTextTraits(CPrefs::GetTextFieldTextResIDs(csid));
  1650.     TextStyle    ts;
  1651.  
  1652.     if (theTextTraits != NULL) {
  1653.         ts.tsFont = (*theTextTraits)->fontNumber;
  1654.         ts.tsSize = (*theTextTraits)->size;
  1655.         ts.tsFace = (*theTextTraits)->style;
  1656.         ts.tsColor = (*theTextTraits)->color;
  1657.  
  1658.         engine->SetStyle(weDoAll, &ts);
  1659.     }
  1660. }
  1661.  
  1662.  
  1663. static void SetupTextInTextEngine( CWASTEEdit* engine, int16 csid, char* text, int32 len)
  1664. {
  1665.     if(CS_UTF8 == csid)
  1666.     {
  1667.         PutUTF8IntoTextEngine( engine, text, len );
  1668.     } else {
  1669.         ChangeTextTraitsForSingleScript(engine, csid );
  1670.         engine->InsertPtr( text, len, NULL, NULL, true );
  1671.     }
  1672. }
  1673.  
  1674.  
  1675. void UFormElementFactory::ResetFormElementData(
  1676.     LO_FormElementStruct *formElem,
  1677.     Boolean redraw,
  1678.     Boolean fromDefaults,
  1679.     Boolean reflect)
  1680. {    
  1681.     if (!formElem->element_data)
  1682.         return;
  1683.     switch (formElem->element_data->type)
  1684.     {
  1685.         case FORM_TYPE_TEXT:                // Set the text
  1686.         case FORM_TYPE_PASSWORD:
  1687.         case FORM_TYPE_ISINDEX:
  1688.         {
  1689.             if ( !GetFEData( formElem ) )
  1690.                 return;
  1691.             lo_FormElementTextData* textData =  & formElem->element_data->ele_text;
  1692.             LEditField * editField = (LEditField *)FEDATAPANE;
  1693.             if (!editField)
  1694.                 return;
  1695.             char* newText = NULL;
  1696.             if ( fromDefaults )
  1697.             {
  1698.                 if ( textData->default_text )        // Eric might be passing us NULL
  1699.                 {
  1700.                     newText = (char*)textData->default_text;
  1701.                     editField->SetDescriptor( CStr255( newText ) );
  1702.                 }
  1703.                 else
  1704.                     editField->SetDescriptor( "\p" );
  1705.             }
  1706.             else
  1707.             {
  1708.                 newText = (char*)textData->current_text;
  1709.                 editField->SetDescriptor( CStr255( newText ) );
  1710.             }
  1711.             if ( redraw )
  1712.             {
  1713.                 editField->Refresh();
  1714.                 editField->UpdatePort();
  1715.             }
  1716.         }
  1717.         break;
  1718.     
  1719.         case FORM_TYPE_TEXTAREA:
  1720.         {        
  1721.             if ( !GetFEData( formElem ) )
  1722.                 return;
  1723.             lo_FormElementTextareaData* textAreaData = (lo_FormElementTextareaData*) formElem->element_data;
  1724.             LView* scroller = (LView*)FEDATAPANE;
  1725.             if (!scroller)
  1726.                 return;
  1727.             CSimpleTextView* textEdit = (CSimpleTextView*)scroller->FindPaneByID(formBigTextID);
  1728.             CWASTEEdit* engine = dynamic_cast<CWASTEEdit *>(textEdit);
  1729.             char* default_text;
  1730.             if ( fromDefaults )
  1731.             {
  1732.                 if ( textAreaData->default_text )
  1733.                 {
  1734.                     default_text = (char*)textAreaData->default_text;
  1735.                     ValidateTextByCharset(formElem->text_attr->charset, default_text);
  1736.                     Try_
  1737.                     {
  1738.                         SetupTextInTextEngine(engine, formElem->text_attr->charset, default_text, XP_STRLEN((char*)default_text));
  1739.                     }
  1740.                     Catch_( inErr )
  1741.                     {
  1742.                     }
  1743.                     EndCatch_
  1744.                 }
  1745.                 else            // No default value
  1746.                 {
  1747.                     Try_
  1748.                     {
  1749.                         SetupTextInTextEngine(engine, formElem->text_attr->charset, NULL, 0);
  1750.                     }
  1751.                     Catch_( inErr )
  1752.                     {
  1753.                     }
  1754.                 }
  1755.             }
  1756.             else
  1757.             {
  1758.                 default_text = (char*)textAreaData->current_text;
  1759.                 ValidateTextByCharset(formElem->text_attr->charset, default_text);
  1760.                 Try_
  1761.                 {
  1762.                     SetupTextInTextEngine(engine, formElem->text_attr->charset, default_text, XP_STRLEN((char*)default_text));
  1763.                 }
  1764.                 Catch_( inErr ) 
  1765.                 {
  1766.                 }
  1767.             }
  1768.             if ( redraw )
  1769.                 textEdit->Refresh();
  1770.         }
  1771.         break;
  1772.  
  1773.         case FORM_TYPE_RADIO:        // Set the toggle to on or off
  1774.         case FORM_TYPE_CHECKBOX:
  1775.         {
  1776.             if ( !GetFEData( formElem ) )
  1777.                 return;
  1778.             lo_FormElementToggleData* toggleData = (lo_FormElementToggleData*)formElem->element_data;
  1779.             LStdControl* toggle = (LStdControl*)FEDATAPANE;
  1780.             if (!toggle)
  1781.                 return;
  1782.             if ( fromDefaults )
  1783.             {            
  1784.                 if ( toggle->GetValue() == toggleData->default_toggle )    // Do not change unless we have to
  1785.                     break;
  1786.                 toggle->SetValue( toggleData->default_toggle );
  1787.             }
  1788.             else // use the stored value
  1789.             {            
  1790.                 if ( toggle->GetValue() == toggleData->toggled )    
  1791.                     break;
  1792.                 toggle->SetValue( toggleData->toggled );
  1793.             }
  1794.             if ( redraw )
  1795.                 toggle->Refresh();
  1796.         }
  1797.         break;
  1798.  
  1799.         case FORM_TYPE_FILE:
  1800.         {
  1801.             lo_FormElementTextData * pickData = (lo_FormElementTextData*)formElem->element_data;
  1802.             CFormFile * formFile = (CFormFile *)FEDATAPANE;
  1803.             if (!formFile)
  1804.                 return;
  1805.             formFile->SetVisibleChars(pickData->size);
  1806.             if (fromDefaults)
  1807.                 ;    // Do nothing
  1808.             else
  1809.             {
  1810.                 char * default_text;
  1811.                 FSSpec spec;
  1812.                 OSErr err;
  1813.                 PA_LOCK(default_text, char*, pickData->current_text);
  1814.                 if (default_text)
  1815.                     err = CFileMgr::FSSpecFromLocalUnixPath(default_text, &spec);
  1816.                 else
  1817.                     err = fnfErr;
  1818.                 PA_UNLOCK(pickData->current_text);                
  1819.                 if (err == noErr)
  1820.                     formFile->SetFileSpec(spec);
  1821.             }
  1822.             if (redraw)
  1823.                 formFile->Refresh();
  1824.         }
  1825.         break;
  1826.         
  1827.         case FORM_TYPE_HIDDEN:
  1828.         case FORM_TYPE_KEYGEN:
  1829.         case FORM_TYPE_SUBMIT:
  1830.         case FORM_TYPE_RESET:
  1831.         case FORM_TYPE_BUTTON:
  1832.         // no value to set or reset
  1833.         break;
  1834.         
  1835.         case FORM_TYPE_SELECT_ONE:
  1836.         {
  1837.             if ( !GetFEData( formElem ) )
  1838.                 return;
  1839.             lo_FormElementSelectData* selectData = (lo_FormElementSelectData*)formElem->element_data;
  1840.             int offset = CalcCurrentSelected( selectData, fromDefaults );
  1841.             
  1842.             LButton*        widget = (LButton*)FEDATAPANE;
  1843.             FormsPopup*        popup  = (FormsPopup*)FEDATAHOST;
  1844.             
  1845.             if (popup)
  1846.                 popup->DirtyMenu();
  1847.             if (!widget)
  1848.                 return;
  1849.             widget->SetValue( offset + 1 );
  1850.             if ( redraw )
  1851.                 widget->Refresh();
  1852.         }
  1853.         break;
  1854.  
  1855.         case FORM_TYPE_SELECT_MULT:        // Select/unselect the cells
  1856.         {
  1857.             if ( !GetFEData( formElem ) )
  1858.                 return;
  1859.             lo_FormElementOptionData*    mother;
  1860.             lo_FormElementSelectData*    selectData = (lo_FormElementSelectData *)formElem->element_data;
  1861.             CFormList*                    myList      = (CFormList*)FEDATAPANE;
  1862.             
  1863.             if (!myList)
  1864.                 return;
  1865.             myList->SelectNone();        
  1866.             myList->FocusDraw();
  1867.                 
  1868.             ::LSetDrawingMode( FALSE, myList->GetMacListH() );
  1869.         
  1870.             mother = (lo_FormElementOptionData*)selectData->options;
  1871.             myList->SyncRows( selectData->option_cnt );
  1872.             for ( int i = 0; i < selectData->option_cnt; i++ )
  1873.             {
  1874.                 char* itemName = NULL;
  1875.                 Boolean select;
  1876.                 
  1877.                 itemName = (char*)mother[ i ].text_value;
  1878.                 myList->AddItem( itemName, i );
  1879.                  
  1880.                 if ( fromDefaults )
  1881.                     select = mother[ i ].def_selected;
  1882.                 else
  1883.                     select = mother[ i ].selected;
  1884.                     
  1885.                 if (select)
  1886.                     myList->SetSelect( i, select );
  1887.             }
  1888.  
  1889.             ::LSetDrawingMode( TRUE, myList->GetMacListH() );
  1890.             // Ñ╩this forces an update of the scrollbar, if there is
  1891.             //        one
  1892.             ::LUpdate( NULL, myList->GetMacListH() );
  1893.             myList->ShrinkToFit( selectData->size );
  1894.             Cell selection = { myList->GetValue(), 0 };        // cells are v, h
  1895.             myList->MakeCellVisible ( selection );
  1896.             if ( redraw )
  1897.                 myList->Refresh();
  1898.         }
  1899.         break;
  1900.  
  1901.         case FORM_TYPE_IMAGE:
  1902.         case FORM_TYPE_JOT:
  1903.         case FORM_TYPE_OBJECT:
  1904.         break;
  1905.     }
  1906.  
  1907.     
  1908. // immediately reflect our state
  1909.     if (reflect)
  1910.         FEDATAHOST->ReflectData();
  1911. }
  1912.