/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // UFormElementFactory.cp #include "UFormElementFactory.h" // PowerPlant #include #include #include #include //#include //#include //#include // MacFE #include "CHTMLView.h" #include "CNSContext.h" #include "resgui.h" #include "uprefd.h" #include "mforms.h" #include "CConfigActiveScroller.h" #include "macgui.h" #include "macutil.h" #include "ufilemgr.h" #include "uintl.h" #include "CAutoPtr.h" // Backend #include "lo_ele.h" // for struct def'n #include "xlate.h" #include "fe_proto.h" #include "prefapi.h" // macros #define FEDATAPANE ((FormFEData *)formElem->element_data->ele_minimal.FE_Data)->fPane #define FEDATAHOST ((FormFEData *)formElem->element_data->ele_minimal.FE_Data)->fHost // These defines add extra spacing to the controls. // The spacing is needed because the layout puts them too close otherwise #define buttonTopExtra 1 #define buttomLeftExtra 1 #define buttonRightExtra 1 #define buttonBottomExtra 1 #define textTopExtra 1 #define textLeftExtra 1 #define textRightExtra 1 #define textBottomExtra 1 void FE_FreeFormElement( MWContext* /* inContext */, LO_FormElementData * inFormData) { UFormElementFactory::FreeFormElement(inFormData); } // prototypes Boolean SetFE_Data(LO_FormElementStruct *formElem, LPane * pane, LFormElement *host, LCommander *commander); Boolean HasFormWidget(LO_FormElementStruct *formElem); // utilities inline FormFEData *GetFEData(LO_FormElementStruct *formElem) { return ((FormFEData *)formElem->element_data->ele_minimal.FE_Data); } inline LPane *GetFEDataPane( LO_FormElementStruct *formElem) { return FEDATAPANE; } // Sets the value of FE_Data structure in form element // Returns true if form is being created from scratch Boolean SetFE_Data( LO_FormElementStruct* formElem, LPane* pane, LFormElement *host, LCommander *commander) { if (!formElem->element_data) return false; FormFEData *feData; Boolean noFEData = ( formElem->element_data->ele_minimal.FE_Data == NULL ); if ( noFEData ) { FormFEData* feData = new FormFEData; ThrowIfNil_( feData ); formElem->element_data->ele_minimal.FE_Data = feData; } feData = (FormFEData *)formElem->element_data->ele_minimal.FE_Data; feData->fPane = pane; feData->fHost = host; feData->fCommander = commander; Assert_(host); if (host) host->SetFEData(feData); return noFEData; } Boolean HasFormWidget( LO_FormElementStruct *formElem) { return ((formElem->element_data->ele_minimal.FE_Data != NULL) && (FEDATAPANE != NULL)); } /****************************************************************************** * CWhiteScroller * White background instead of gray 'wscr' ******************************************************************************/ class CWhiteScroller: public CConfigActiveScroller { public: //friend class CHyperView; // this class no longer exists enum { class_ID = 'wscr' }; CWhiteScroller( LStream* inStream ); virtual Boolean FocusDraw(LPane* inSubPane = nil); virtual void DrawSelf(); }; CWhiteScroller::CWhiteScroller(LStream *inStream) : CConfigActiveScroller(inStream) { } // The only real routine. Sets background to white Boolean CWhiteScroller::FocusDraw(LPane* /*inSubPane*/) { if (LScroller::FocusDraw()) { UGraphics::SetBack(CPrefs::White); return TRUE; } else { return FALSE; } } void CWhiteScroller::DrawSelf() { Rect frame; if (CalcLocalFrameRect(frame) && IsVisible() && mUpdateRgnH && ((*mUpdateRgnH)->rgnBBox.top != (*mUpdateRgnH)->rgnBBox.bottom)) // Only erase on update ::EraseRect(&frame); // if ((mVerticalBar && mVerticalBar->IsVisible()) || (mHorizontalBar && mHorizontalBar->IsVisible())) // ::EraseRect(&frame); LScroller::DrawSelf(); } /********************************************************************* * StModifyPPob * Modifying PPob for dynamic change of the text resource ID when loading * Constructor modifies the resource by sticking a resID at the appropriate * offset. * Destructor restores it. * Offsets are generated by looking them up in Resourcerer *********************************************************************/ class StModifyPPob { Int16 fResID; Int16 fOffset; Int16 fOldTextR; public: StModifyPPob(Int16 resID, // Resource of the PPob to be modified Int16 offset, // Offset into the resource Int16 csid, // Charset of the current doc Boolean button); // Which TxtR are we looking for (TRUE = button, FALSE = text) ~StModifyPPob(); }; StModifyPPob::StModifyPPob(Int16 resID, Int16 offset, Int16 csid, Boolean button) { fResID = resID; fOffset = offset; Int16 newTextR; if (button) newTextR = CPrefs::GetButtonFontTextResIDs(csid); else newTextR = CPrefs::GetTextFieldTextResIDs(csid); Handle r = ::GetResource('PPob', fResID); ThrowIfNil_(r); HNoPurge(r); // Modify the resource StHandleLocker lock(r); Int16 * myPointer = (Int16*)(*r + fOffset); fOldTextR = *myPointer; *myPointer = newTextR; } StModifyPPob::~StModifyPPob() { Handle r = ::GetResource('PPob', fResID); StHandleLocker lock(r); Int16 * myPointer = (Int16*)(*r + fOffset);; *myPointer = fOldTextR; HPurge(r); } void UFormElementFactory::RegisterFormTypes() { RegisterClass_( CFormButton); RegisterClass_( CGAFormPushButton); RegisterClass_( CFormList); RegisterClass_( CFormLittleText); RegisterClass_( CFormBigText); RegisterClass_( CFormRadio); RegisterClass_( CGAFormRadio); RegisterClass_( CFormCheckbox); RegisterClass_( CGAFormCheckbox); RegisterClass_( CFormFile); RegisterClass_( CFormFileEditField); RegisterClass_( CWhiteScroller); } // // Figures out what kind of form element we're dealing with and dispatches *that* // void UFormElementFactory::MakeFormElem( CHTMLView* inHTMLView, CNSContext* inNSContext, LO_FormElementStruct* formElem) { if (!formElem->element_data) return; Try_ { Int32 width; Int32 height; Int32 baseline; switch ( formElem->element_data->type ) { case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: MakeTextFormElem(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_READONLY: MakeReadOnlyFormElem(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_TEXTAREA: MakeTextArea(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_RADIO: case FORM_TYPE_CHECKBOX: MakeToggle(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_HIDDEN: case FORM_TYPE_KEYGEN: case FORM_TYPE_OBJECT: width = height = baseline = 0; break; case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: MakeButton(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_FILE: MakeFilePicker(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_SELECT_ONE: MakePopup(inHTMLView, inNSContext, width, height, baseline,formElem); break; case FORM_TYPE_SELECT_MULT: MakeList(inHTMLView, inNSContext, width, height, baseline, formElem); break; case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: default: Assert_(FALSE); break; }; formElem->width = width; formElem->height = height; formElem->baseline = baseline; } Catch_(inErr) { Assert_(FALSE); } EndCatch_ } // Creates a simple edit text field // textData->size is the number of characters // textData->max_size is the maximum number of characters // textData->default_text is the default text LPane* UFormElementFactory::MakeTextFormElem( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; CFormLittleText * editField; if (!HasFormWidget(formElem)) { // If we did not have a control, create one lo_FormElementTextData * textData = (lo_FormElementTextData *) formElem->element_data; LCommander::SetDefaultCommander(inHTMLView); // For tabbing LPane::SetDefaultView(inHTMLView); switch (textData->type) { case FORM_TYPE_TEXT: case FORM_TYPE_ISINDEX: { StModifyPPob modifier(formTextField, 0x3F, inNSContext->GetWinCSID(), false); editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formTextField); } break; case FORM_TYPE_PASSWORD: editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formPasswordField); break; default: Throw_(0); } ThrowIfNil_(editField); editField->InitFormElement(*inNSContext, formElem); editField->FinishCreate(); editField->AddListener(inHTMLView); if (textData->max_size < 0) textData->max_size = 32000; editField->SetMaxChars(textData->max_size); editField->SetVisibleChars(textData->size); editField->SetLayoutForm(formElem); // Should allow undo LUndoer* theUndoer = new LUndoer; editField->AddAttachment(theUndoer); // Reset the value ResetFormElement(formElem, FALSE, SetFE_Data(formElem,editField,editField, editField)); // Secure fields are disabled } else { // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // editField = (CFormLittleText *)FEDATAPANE; if (!editField) return NULL; editField->SetLayoutForm(formElem); // CWhiteEdit field only (never uses it...) editField->SetLayoutElement(formElem); // mocha mix-in needs to know too... } // Figure out dimensions SDimension16 size; editField->GetFrameSize(size); width = size.width + textLeftExtra + textRightExtra; height = size.height + textTopExtra + textBottomExtra;; TEHandle textH = editField->GetMacTEH(); baseline = (*textH)->fontAscent + 2 + textTopExtra; return editField; } // Very similar to MakeTextFormElem, for now LPane * UFormElementFactory::MakeReadOnlyFormElem( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; CFormLittleText * editField; if (!HasFormWidget(formElem)) { // If we did not have a control, create one lo_FormElementMinimalData * readData = (lo_FormElementMinimalData *) formElem->element_data; LCommander::SetDefaultCommander(inHTMLView); // For tabbing LPane::SetDefaultView(inHTMLView); StModifyPPob modifier(formTextField, 0x3F, inNSContext->GetWinCSID(), false); editField = (CFormLittleText *)UReanimator::ReadObjects('PPob', formTextField); ThrowIfNil_(editField); editField->InitFormElement(*inNSContext, formElem); editField->FinishCreate(); editField->SetLayoutForm(formElem); editField->Disable(); // Reset the value ResetFormElement(formElem, FALSE, SetFE_Data(formElem,editField,editField, editField)); char * newText; PA_LOCK(newText, char* , readData->value); editField->SetDescriptor(CStr255(newText)); editField->SetVisibleChars(newText ? XP_STRLEN(newText) : 10); PA_UNLOCK(readData->value); } else { // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // editField = (CFormLittleText *)FEDATAPANE; if (!editField) return NULL; editField->SetLayoutForm(formElem); editField->SetLayoutElement(formElem); } // Figure out dimensions SDimension16 size; editField->GetFrameSize(size); width = size.width + textLeftExtra + textRightExtra; height = size.height + textTopExtra + textBottomExtra;; TEHandle textH = editField->GetMacTEH(); baseline = (*textH)->fontAscent + 2 + textTopExtra; return editField; } #define BigTextLeftIndent 5 // same constants are in the forms.r #define BigTextRightIndent 1 #define BigTextTopIndent 1 #define BigTextBottomIndent 1 // Creates a text area // textAreaData->default_text; // textAreaData->rows; // textAreaData->cols; LPane* UFormElementFactory::MakeTextArea( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; CWhiteScroller * theScroller = NULL; CFormBigText * theTextView = NULL; FontInfo fontInfo; if (!HasFormWidget(formElem)) // If there is no form, create it { lo_FormElementTextareaData * textAreaData = (lo_FormElementTextareaData *) formElem->element_data; // Create the view LCommander::SetDefaultCommander(inHTMLView); LView::SetDefaultView(inHTMLView); // since I can't find an API to switch the word wrap property after the element // has been initialized, we need to create two separate PPob's. Read in the // appropriate one depending on if the text area requires wrapping or not. ResIDT elementToRead = 0; switch(textAreaData->auto_wrap) { case TEXTAREA_WRAP_SOFT: case TEXTAREA_WRAP_HARD: elementToRead = formBigText; break; case TEXTAREA_WRAP_OFF: elementToRead = formBigTextScroll; break; } // case of wrap property theScroller = (CWhiteScroller *)UReanimator::ReadObjects('PPob', elementToRead); ThrowIfNil_(theScroller); theScroller->FinishCreate(); theScroller->PutInside(inHTMLView); theTextView = (CFormBigText*)theScroller->FindPaneByID(formBigTextID); Assert_(theTextView != NULL); LModelObject* theSuper = inHTMLView->GetFormElemBaseModel(); theTextView->InitFormElement(*inNSContext, formElem); // Add the undoer for text actions. This will be on a per-text field basis // - Let WASTE handle undo // LUndoer* theUndoer = new LUndoer; // theTextView->AddAttachment(theUndoer); // Resize to proper size theTextView->FocusDraw(); ::GetFontInfo(&fontInfo); // short wantedWidth = textAreaData->cols * fontInfo.widMax + 8; short wantedWidth = textAreaData->cols * ::CharWidth('M') + 8; short wantedHeight = textAreaData->rows * (fontInfo.ascent + fontInfo.descent + fontInfo.leading) + 8; // make the image big so there is something to scroll, if necessary.... if ( textAreaData->auto_wrap == TEXTAREA_WRAP_OFF ) theTextView->ResizeImageTo(2000, 0, false); theScroller->ResizeFrameTo(wantedWidth + 16 + BigTextLeftIndent + BigTextRightIndent, wantedHeight + 16 + BigTextTopIndent + BigTextBottomIndent, FALSE); // Set the default values. ResetFormElement(formElem, FALSE, SetFE_Data(formElem, theScroller, theTextView, theTextView)); theScroller->Show(); } else { theScroller = (CWhiteScroller*)FEDATAPANE; if (!theScroller) return NULL; theTextView = (CFormBigText*)theScroller->FindPaneByID(formBigTextID); theTextView->FocusDraw(); // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // theTextView->SetLayoutElement(formElem); ::GetFontInfo(&fontInfo); } SDimension16 size; theScroller->GetFrameSize(size); width = size.width + textLeftExtra + textRightExtra;; height = size.height + textTopExtra + textBottomExtra;; baseline = fontInfo.ascent + 2; return theScroller; } // Creates a button // buttonData->name; is buttons name // Buttons store the form element as the refCon, so that they can broadcast // to the window. LPane* UFormElementFactory::MakeButton( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; LControl* theControl = nil; LPane* thePane = nil; LFormElement* theHost = nil; lo_FormElementMinimalData * buttonData= (lo_FormElementMinimalData *)formElem->element_data; FontInfo info; if (!HasFormWidget(formElem)) { // FIX ME? LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort())); LPane::SetDefaultView(inHTMLView); switch (buttonData->type) { case FORM_TYPE_SUBMIT: { XP_Bool useGrayscaleFormControls; int prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls); if (prefResult == PREF_NOERROR && useGrayscaleFormControls) { StModifyPPob modifier(formGASubmitButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGASubmitButton)); } else { StModifyPPob modifier(formSubmitButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formSubmitButton)); } } break; case FORM_TYPE_RESET: { XP_Bool useGrayscaleFormControls; int prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls); if (prefResult == PREF_NOERROR && useGrayscaleFormControls) { StModifyPPob modifier(formGAResetButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGAResetButton)); } else { StModifyPPob modifier(formResetButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formResetButton)); } } break; case FORM_TYPE_BUTTON: { XP_Bool useGrayscaleFormControls; int prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls); if (prefResult == PREF_NOERROR && useGrayscaleFormControls) { StModifyPPob modifier(formGAPlainButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGAPlainButton)); } else { StModifyPPob modifier(formPlainButton, 0x46, inNSContext->GetWinCSID(), TRUE); ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formPlainButton)); } } break; default: Throw_(0); } ThrowIfNil_(theHost = dynamic_cast(thePane)); ThrowIfNil_(theControl = dynamic_cast(thePane)); thePane->FinishCreate(); theHost->InitFormElement(*inNSContext, formElem); ResetFormElement(formElem, FALSE, SetFE_Data(formElem,thePane,theHost, NULL)); // Set up buttons as broadcasters. Store the LO_FormElementStruct * in refCon theControl->AddListener(inHTMLView); } else { thePane = FEDATAPANE; ThrowIfNil_(theHost = dynamic_cast(thePane)); ThrowIfNil_(theControl = dynamic_cast(thePane)); // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // theHost->SetLayoutElement(formElem); } thePane->SetUserCon((long)formElem); // Always do this char * name; PA_LOCK(name, char*, buttonData->value); CStr255 pName(name); thePane->SetDescriptor(pName); PA_UNLOCK(buttonData->value); ::GetFontInfo(&info); // Get width/height/baseline SDimension16 size; thePane->GetFrameSize(size); width = size.width + buttomLeftExtra + buttonRightExtra; height = size.height + buttonTopExtra + buttonBottomExtra; baseline = info.ascent + 2 + buttonTopExtra; return thePane; } LPane* UFormElementFactory::MakeFilePicker( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; CFormFile * filePicker = NULL; lo_FormElementTextData * pickerData= (lo_FormElementTextData *)formElem->element_data; if (!HasFormWidget(formElem)) { // FIX ME? LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort())); LPane::SetDefaultView(inHTMLView); filePicker = (CFormFile *)UReanimator::ReadObjects('PPob', formFilePicker); ThrowIfNil_(filePicker); filePicker->InitFormElement(*inNSContext, formElem); filePicker->FinishCreate(); ResetFormElement(formElem, FALSE, SetFE_Data(formElem,filePicker,filePicker, filePicker->fEditField)); } else { // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // filePicker = (CFormFile *)FEDATAPANE; if (!filePicker) return NULL; filePicker->SetLayoutElement(formElem); } /* char * name; PA_LOCK(name, char*, pickerData->default_text); CStr255 pName(name); filePicker->SetDescriptor(pName); PA_UNLOCK(pickerData->default_text); ::GetFontInfo(&info); */ // Get width/height/baseline filePicker->GetFontInfo(width, height, baseline); width = width + buttomLeftExtra + buttonRightExtra; height = height + buttonTopExtra + buttonBottomExtra; return filePicker; } // Creates buttons/checkboxes // Boolean toggleData->default_toggle is default on/off LPane* UFormElementFactory::MakeToggle( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; LControl* toggle = nil; LPane* thePane; LFormElement *host; lo_FormElementToggleData * toggleData = (lo_FormElementToggleData *)formElem->element_data; if (!HasFormWidget(formElem)) { // FIX ME? LCommander::SetDefaultCommander(LWindow::FetchWindowObject(inHTMLView->GetMacPort())); LPane::SetDefaultView(inHTMLView); switch (toggleData->type) { case FORM_TYPE_RADIO: { XP_Bool useGrayscaleFormControls; int prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls); if (prefResult == PREF_NOERROR && useGrayscaleFormControls) { ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGARadio)); } else { ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formRadio)); } } break; case FORM_TYPE_CHECKBOX: { XP_Bool useGrayscaleFormControls; int prefResult = PREF_GetBoolPref("browser.mac.use_grayscale_form_controls", &useGrayscaleFormControls); if (prefResult == PREF_NOERROR && useGrayscaleFormControls) { ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formGACheckbox)); } else { ThrowIfNil_(thePane = (LPane *)UReanimator::ReadObjects('PPob', formCheckbox)); } } break; default: Throw_(0); } ThrowIfNil_(host = dynamic_cast(thePane)); ThrowIfNil_(toggle = dynamic_cast(thePane)); host->InitFormElement(*inNSContext, formElem); thePane->FinishCreate(); thePane->Enable(); ResetFormElement(formElem, FALSE, SetFE_Data(formElem,toggle, host, NULL )); // Set up toggles as broadcasters. Store the LO_FormElementStruct * in refCon // toggle->AddListener(this); } else { LFormElement* formWidget; lo_FormElementToggleData* toggleData = (lo_FormElementToggleData *)formElem->element_data; toggle = dynamic_cast(FEDATAPANE); if (!toggle) return NULL; // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // if (toggleData->type == FORM_TYPE_RADIO) // fun with C++ casting { formWidget = dynamic_cast(toggle); ThrowIfNil_(formWidget); } else if (toggleData->type == FORM_TYPE_CHECKBOX) { formWidget = dynamic_cast(toggle); ThrowIfNil_(formWidget); } else { Assert_(false); } formWidget->SetLayoutElement(formElem); } toggle->SetUserCon((long)formElem); short extra; // extra space to be left after the control switch (toggleData->type) { case FORM_TYPE_RADIO: extra = 3; break; case FORM_TYPE_CHECKBOX: extra = 5; break; } // width/height/baseline SDimension16 size; toggle->GetFrameSize(size); width = size.width + extra; height = size.height; baseline = size.height - 2; return toggle; } LPane* UFormElementFactory::MakePopup ( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; if (!HasFormWidget(formElem)) { lo_FormElementSelectData * selections = (lo_FormElementSelectData *)formElem->element_data; // Create the popup LCommander::SetDefaultCommander(inHTMLView); LPane::SetDefaultView(inHTMLView); LPane* thePane = (LPane*)(UReanimator::ReadObjects ('PPob', formGAPopup)); CGAPopupMenu* popupCtrl = dynamic_cast(thePane); ThrowIfNil_(popupCtrl); popupCtrl->SetTextTraits(CPrefs::GetButtonFontTextResIDs(inNSContext->GetWinCSID())); popupCtrl->FinishCreate(); // pointer from host widget to layout popupCtrl->SetUserCon ((Int32)selections); // tell popup what data to display FormsPopup * popupText = new FormsPopup (popupCtrl, selections); ThrowIfNil_(popupText); popupText->InitFormElement(*inNSContext, formElem); popupCtrl->AddAttachment (popupText); // reset values ResetFormElement(formElem, FALSE, SetFE_Data(formElem,popupCtrl,popupText, NULL )); // Reset the selection #if 1 /* POPUP MENU VERTICAL POSITION FIX */ FontInfo fontInfo; GetFontInfo (&fontInfo); #endif // Resize the popup to max width short widgetBaseline; Point popupSize = popupText->CalcTargetFrame (widgetBaseline); popupCtrl->ResizeFrameTo (popupSize.h, popupSize.v, false); width = popupSize.h; height = popupSize.v + 1; // add 1 for "leading" between lines in forms #if 1 /* POPUP MENU VERTICAL POSITION FIX */ baseline = fontInfo.ascent + 1; #else baseline = widgetBaseline; #endif popupCtrl->Show(); popupCtrl->Enable(); return popupCtrl; } else { LPane* widget = dynamic_cast(FEDATAPANE); FormsPopup* popupText = dynamic_cast(FEDATAHOST); SDimension16 size; ThrowIfNil_(widget); ThrowIfNil_(popupText); #if 1 /* POPUP MENU VERTICAL POSITION FIX */ FontInfo fontInfo; GetFontInfo (&fontInfo); #endif // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // if (popupText != NULL) popupText->SetLayoutElement(formElem); if (widget != NULL) widget->GetFrameSize(size); width = size.width; height = size.height + 1; // add 1 for "leading" between lines in forms #if 1 /* POPUP MENU VERTICAL POSITION FIX */ baseline = fontInfo.ascent + 1; #else baseline = 2; // ERROR. Does not get the proper baseline #endif return widget; } } LPane* UFormElementFactory::MakeList( CHTMLView* inHTMLView, CNSContext* inNSContext, Int32 &width, Int32 &height, Int32& baseline, LO_FormElementStruct *formElem) { if (!formElem->element_data) return nil; CFormList * myList = NULL; // (CFormList*)FEDATAPANE; if (!HasFormWidget(formElem)) { lo_FormElementSelectData* selectData = (lo_FormElementSelectData *)formElem->element_data; // Create the form LCommander::SetDefaultCommander( inHTMLView ); LPane::SetDefaultView( inHTMLView ); StModifyPPob modifier( formScrollingList, 0x3C, inNSContext->GetWinCSID(), false ); myList = (CFormList *)UReanimator::ReadObjects( 'PPob', formScrollingList ); ThrowIfNil_( myList ); myList->InitFormElement( *inNSContext, formElem ); myList->FinishCreate(); // Initialize the list items from the form data myList->SetSelectMultiple( selectData->multiple ); myList->SyncRows( selectData->option_cnt ); ResetFormElement( formElem, FALSE, SetFE_Data( formElem, myList, myList, myList) ); // Reset the selection myList->ShrinkToFit( selectData->size ); } else { myList = (CFormList*)FEDATAPANE; if (!myList) return NULL; myList->FocusDraw(); // // We've already created a widget for the // form element, but layout has gone and // reallocated the form element, so we must // update our reference to it. // myList->SetLayoutElement(formElem); } FontInfo info; SDimension16 size; ::GetFontInfo( &info ); myList->GetFrameSize( size ); // +6 to account for the focus ring width = size.width + 6; height = size.height + 6; baseline = info.ascent; return myList; } // FreeFormElement is called when eric finally wants to free the FE form data void UFormElementFactory::FreeFormElement( LO_FormElementData *formElem) { XP_TRACE(("FreeFormElement, data %d \n", (Int32)formElem->ele_minimal.FE_Data)); switch (formElem->type) { case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: // Sets the original text case FORM_TYPE_FILE: if (formElem->ele_text.current_text) PA_FREE(formElem->ele_text.current_text); formElem->ele_text.current_text = NULL; FormFEData * FEData = (FormFEData *)formElem->ele_text.FE_Data; if (FEData) { // don't forget to null out pointer to FEData in fHost if (FEData->fHost) FEData->fHost->SetFEData(NULL); delete FEData; } formElem->ele_text.FE_Data = NULL; break; case FORM_TYPE_TEXTAREA: if (formElem->ele_textarea.current_text) // Free up the old memory PA_FREE(formElem->ele_textarea.current_text); formElem->ele_textarea.current_text = NULL; FEData = (FormFEData *)formElem->ele_textarea.FE_Data; if (FEData) { // don't forget to null out pointer to FEData in fHost if (FEData->fHost) FEData->fHost->SetFEData(NULL); delete FEData; } formElem->ele_textarea.FE_Data = NULL; break; case FORM_TYPE_RADIO: case FORM_TYPE_CHECKBOX: FEData = (FormFEData *)formElem->ele_toggle.FE_Data; if (FEData) { // don't forget to null out pointer to FEData in fHost if (FEData->fHost) FEData->fHost->SetFEData(NULL); delete FEData; } formElem->ele_toggle.FE_Data = NULL; break; case FORM_TYPE_SELECT_ONE: case FORM_TYPE_SELECT_MULT: FEData = (FormFEData *)formElem->ele_select.FE_Data; if ( FEData ) { // don't forget to null out pointer to FEData in fHost if (FEData->fHost) FEData->fHost->SetFEData(NULL); delete FEData; } formElem->ele_select.FE_Data = NULL; break; case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: case FORM_TYPE_READONLY: FEData = (FormFEData *)formElem->ele_minimal.FE_Data; if (FEData) { // don't forget to null out pointer to FEData in fHost if (FEData->fHost) FEData->fHost->SetFEData(NULL); delete FEData; } formElem->ele_minimal.FE_Data = NULL; break; case FORM_TYPE_HIDDEN: case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: case FORM_TYPE_KEYGEN: case FORM_TYPE_OBJECT: // no FE_Data for these guys break; }; } /*----------------------------------------------------------------------------- Forms. lo_ele.h Just like in other web clients, size is the size in characters the field should be, max_size is the maximum length in characters that can be entered. default_text is the text the user wants to have appear in the textfield on creation and reset. The layout needs the front end to fill in the width and height fields in the LO_FormElementStruct. It also needs the baseline field filled in. This may be difficult to impossible on some front ends. baseline is the y position from 0 to (height - 1) that should line up with regular text on the same line as this form element. If necessary, just punt to baseline = (height - 1). -----------------------------------------------------------------------------*/ // Took out XP_TRACEFORM call, so why use this function? void UFormElementFactory::DisplayFormElement( CNSContext* inNSContext, LO_FormElementStruct* formElem ) { Rect oldElementFrame, newElementFrame; Int32 extraX, extraY; LPane *pane; pane = 0; Try_ // Because stupid LNTextEdit does a throw when you resize it too large { // ¥ the x,y passed to us originally may have been adjusted by layout // so we have to update the widget. We don't actually need to draw it. // It should only be adjusted once I think. if ( !XP_CheckElementSpan( *inNSContext, formElem->y + formElem->y_offset, formElem->height ) ) return; if (!formElem->element_data) return; // jrm 97/03/21 switch ( formElem->element_data->type ) { case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: case FORM_TYPE_FILE: if (GetFEData (formElem)) { pane = GetFEDataPane(formElem); extraX = buttomLeftExtra; // [sic] extraY = buttonTopExtra; } break; case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: case FORM_TYPE_READONLY: case FORM_TYPE_TEXTAREA: if (GetFEData (formElem)) { pane = GetFEDataPane(formElem); extraX = textLeftExtra; extraY = textTopExtra; } break; case FORM_TYPE_RADIO: case FORM_TYPE_CHECKBOX: case FORM_TYPE_SELECT_ONE: case FORM_TYPE_SELECT_MULT: if (GetFEData (formElem)) { pane = GetFEDataPane(formElem); extraX = 0; extraY = 0; } break; case FORM_TYPE_OBJECT: break; case FORM_TYPE_HIDDEN: case FORM_TYPE_KEYGEN: case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: default: Assert_(FALSE); break; } if (pane) { if (pane->IsVisible() && formElem->ele_attrmask & LO_ELE_INVISIBLE) { pane->Hide(); } pane->CalcPortFrameRect (oldElementFrame); pane->PlaceInSuperImageAt (formElem->x + formElem->x_offset + extraX, formElem->y + formElem->y_offset + extraY, TRUE); pane->CalcPortFrameRect (newElementFrame); // if the element had to be moved, invalidate a slightly larger area than its current frame // (see notes below) if (oldElementFrame.top != newElementFrame.top || oldElementFrame.left != newElementFrame.left) { newElementFrame.left--; newElementFrame.top--; newElementFrame.right++; newElementFrame.bottom++; pane->InvalPortRect (&newElementFrame); } if (!pane->IsVisible() && !(formElem->ele_attrmask & LO_ELE_INVISIBLE)) { pane->Show(); pane->Enable(); } pane->Draw(nil); } } Catch_(inErr) {} EndCatch_ /* Why we invalidate a slightly larger rectangle than that occupied by the form element pane itself: when generating a page from HTML, the compositor creates a unique layer for each form element. This layer is strictly rectangular and slightly larger than the form element pane, and is used as a mask to punch out a hole in its background. If the new form element happens to be located in a table cell using a background color different from that used by the document, the element will have a frame of the document background color around it after the document has been created. That frame is temporary; it is erased when the document is redrawn, because on subsequent draw operations, the element frame is no longer used to punch a hole in the cell background. The cell background is rendered in the same pass as the document background, before PowerPlant panes (already created form elements) are drawn. Invalidating a slightly larger framerect when the form element pane is first moved onto the document forces the important part of that redraw to happen immediately, erasing the inappropriately colored frame around the pane. */ } void UFormElementFactory::ResetFormElement( LO_FormElementStruct *formElem, Boolean redraw, Boolean fromDefaults) { ResetFormElementData(formElem, redraw, fromDefaults, true); } void UFormElementFactory::SetFormElementToggle( LO_FormElementStruct* formElem, Boolean value ) { #ifdef DEBUG if ( !formElem->element_data || formElem->element_data->type != FORM_TYPE_RADIO ) XP_ABORT(("no form radio")); #endif if ( !GetFEData( formElem ) ) return; LStdControl* control = (LStdControl*)FEDATAPANE; if (!control) return; // control->SetValue( value ); // control->Refresh(); // MGY: In order to eliminate flickering, I changed the unenlightened call // to Refresh above to be a little more enlightened. TODO: find out why // it's here at all and remove it if no one can give a satifactory reason. // Before removing it, test both GA and non-GA toggles on a variety of backgfounds // to verify that it indeed did not perform any useful service. #if 0 Int32 oldValue = control->GetValue(); if (value != oldValue) { control->SetValue(value); control->Refresh(); } #endif // MGY: Do it this way instead control->SetValue(value); } void UFormElementFactory::FormTextIsSubmit( LO_FormElementStruct * formElem) { if ( !GetFEData( formElem ) ) return; if (!formElem->element_data) return; lo_FormElementTextData * textData = (lo_FormElementTextData *) formElem->element_data; CFormLittleText* editField = (CFormLittleText*)FEDATAPANE; if (editField) editField->SetBroadcast(TRUE); } // // We should move this to some utility class // // To Do: Figure out is this ok for // TEXTAREA_WRAP_OFF, TEXTAREA_WRAP_SOFT and TEXTAREA_WRAP_HARD // static char* ConvertDataInTextEnginToUTF8(CWASTEEdit* engine) { Handle h = engine->GetTextHandle(); Int32 offset, theTextSize = engine->GetTextLength(); ScriptCode script; INTL_Encoding_ID encoding; WERunInfo runInfo; Int32 gatherSize = theTextSize * 3 + 1; char* utf8gather = (char*)XP_ALLOC(gatherSize); if(utf8gather) { StHandleLocker lock(h); *utf8gather = '\0'; // null terminated the beginning for (offset = 0; offset < theTextSize; ) { engine->GetRunInfo(offset, &runInfo); script = FontToScript(runInfo.runStyle.tsFont); encoding = ScriptToEncoding(script); Int32 runLength = runInfo.runEnd - runInfo.runStart; char * utftemp = (char*)INTL_ConvertLineWithoutAutoDetect (encoding, CS_UTF8, (unsigned char *)((*h) + offset), runLength); if(utftemp) { XP_STRCAT(utf8gather, utftemp); XP_FREE(utftemp); } offset += runLength; } Int32 reallocatedLen = strlen(utf8gather) + 1; if(reallocatedLen < (gatherSize - 8)) { // Let's try to allocate a smalle buffer and return that instead if possible if(char* reallocated = (char*)XP_ALLOC(reallocatedLen)) { XP_STRCPY(reallocated,utf8gather); XP_FREE(utf8gather); return reallocated; } } return utf8gather; // otherwise, just return the one we allocated. } return ""; } void UFormElementFactory::GetFormElementValue( LO_FormElementStruct *formElem, Boolean hide) { if (!formElem->element_data) return; Try_ { switch (formElem->element_data->type) { case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: // Sets the original text { if ( !GetFEData( formElem ) ) return; lo_FormElementTextData* textData = (lo_FormElementTextData*)formElem->element_data; if (textData->current_text) PA_FREE(textData->current_text); textData->current_text = NULL; LEditField * editField = (LEditField*)FEDATAPANE; if (!editField) return; CStr255 text; editField->GetDescriptor(text); textData->current_text = PA_ALLOC(text.Length() +1); char * textPtr; PA_LOCK(textPtr, char*, textData->current_text); BlockMoveData(&(text[1]), textPtr, text.Length()); textPtr[text.Length()] = 0; PA_UNLOCK(textData->current_text); } break; case FORM_TYPE_TEXTAREA: { if ( !GetFEData( formElem ) ) return; lo_FormElementTextareaData * textAreaData = (lo_FormElementTextareaData *) formElem->element_data; if (textAreaData->current_text) // Free up the old memory PA_FREE(textAreaData->current_text); textAreaData->current_text = NULL; // find the views LView * scroller = (LView*)FEDATAPANE; if (!scroller) return; CSimpleTextView* textEdit = (CSimpleTextView*)scroller->FindPaneByID(formBigTextID); // Copy the text over Handle h = NULL; Boolean disposeHandle; // Depending if we are making a copy of the text handle if(CS_UTF8 == formElem->text_attr->charset) { disposeHandle = FALSE; textAreaData->current_text = (PA_Block) ConvertDataInTextEnginToUTF8(dynamic_cast(textEdit)); } else { Int32 theTextSize; switch(textAreaData->auto_wrap) { case TEXTAREA_WRAP_OFF: case TEXTAREA_WRAP_SOFT: { disposeHandle = FALSE; h = textEdit->GetTextHandle(); theTextSize = textEdit->GetTextLength(); } break; case TEXTAREA_WRAP_HARD: { disposeHandle = TRUE; h = TextHandleToHardLineBreaks( *textEdit ); theTextSize = ::GetHandleSize(h); } break; } ThrowIfNULL_(h); // note that in the hard wrapped case we're adding an extra null byte // on the end. this wont hurt. char* newTextPtr = (char*)XP_ALLOC(theTextSize + 1); ::BlockMoveData(*h, newTextPtr, theTextSize); newTextPtr[theTextSize] = 0; textAreaData->current_text = (PA_Block)newTextPtr; } if (disposeHandle) DisposeHandle(h); } break; case FORM_TYPE_RADIO: case FORM_TYPE_CHECKBOX: // Sets the original check state if ( !GetFEData( formElem ) ) return; lo_FormElementToggleData * toggleData = (lo_FormElementToggleData*)formElem->element_data; LStdControl * toggle = (LStdControl *)FEDATAPANE; if (toggle) toggleData->toggled = toggle->GetValue(); break; case FORM_TYPE_FILE: lo_FormElementTextData * pickData = (lo_FormElementTextData*)formElem->element_data; CFormFile * formFile = (CFormFile *)FEDATAPANE; FSSpec spec; if (formFile && formFile->GetFileSpec(spec)) { char * fileURL = CFileMgr::EncodedPathNameFromFSSpec( spec, TRUE ); if (fileURL) { PA_Block newValueBlock = PA_ALLOC(XP_STRLEN(fileURL) + 1); char * value; PA_LOCK(value, char*, newValueBlock); ::BlockMoveData(fileURL, value, XP_STRLEN(fileURL) + 1); PA_UNLOCK(newValueBlock); pickData->current_text = newValueBlock; XP_FREE(fileURL); } else pickData->current_text = NULL; } else pickData->current_text = NULL; break; case FORM_TYPE_HIDDEN: case FORM_TYPE_KEYGEN: case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: case FORM_TYPE_READONLY: break; case FORM_TYPE_SELECT_ONE: { // Resets the selects if ( !GetFEData( formElem ) ) return; lo_FormElementSelectData_struct* selections = &formElem->element_data->ele_select; LButton* widget = (LButton*)FEDATAPANE; int value = widget ? widget->GetValue() : 0; lo_FormElementOptionData_struct* options = (lo_FormElementOptionData_struct*)selections->options; for ( int i = 0; i < selections->option_cnt; i++ ) options[ i ].selected = FALSE; if ( value ) options[ value - 1].selected = TRUE; } break; case FORM_TYPE_SELECT_MULT: { lo_FormElementSelectData* selectData = (lo_FormElementSelectData *)formElem->element_data; CFormList* myList = (CFormList*)FEDATAPANE; if (!myList) return; lo_FormElementOptionData* mother = (lo_FormElementOptionData*)selectData->options; for ( int i = 0 ; i < selectData->option_cnt; i++ ) mother[ i ].selected = myList->IsSelected( i ); } break; case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: case FORM_TYPE_OBJECT: break; } } Catch_(inErr){} EndCatch_ if (hide) HideFormElement(formElem); } void UFormElementFactory::HideFormElement( LO_FormElementStruct* formElem) { if (!formElem->element_data) return; switch ( formElem->element_data->type ) { case FORM_TYPE_TEXT: case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: case FORM_TYPE_TEXTAREA: case FORM_TYPE_RADIO: case FORM_TYPE_CHECKBOX: case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: case FORM_TYPE_SELECT_ONE: case FORM_TYPE_SELECT_MULT: case FORM_TYPE_FILE: case FORM_TYPE_READONLY: LFormElement* host = FEDATAHOST; // Schedule the form element to be destroyed. // We don't do it immediately because we may // be in the middle of a JavaScript which could // then return to some PowerPlant code which // still needs access to the form element widget // // Read the comments for MarkForDeath for more details // if (host != NULL) { host->MarkForDeath(); } FEDATAPANE = NULL; FEDATAHOST = NULL; break; case FORM_TYPE_HIDDEN: case FORM_TYPE_KEYGEN: // no value to set or reset break; case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: case FORM_TYPE_OBJECT: break; } } static void ValidateTextByCharset(int csid, char* text) { if(text && (csid & MULTIBYTE)) { int pos; int lastIdx = 0; int boundary = strlen(text); for(pos = 0 ; pos < boundary ; pos += (INTL_IsLeadByte(csid, text[pos])+1)) lastIdx = pos; if(pos != boundary) text[lastIdx] = '\0'; } } static void PutUnicodeIntoTextEngine( CWASTEEdit* engine, INTL_Unicode* unicode, Int32 len) { INTL_CompoundStr* cs = INTL_CompoundStrFromUnicode(unicode, len); UFontSwitcher* fs= UFixedFontSwitcher::Instance(); if(cs) { // Clear the text before insertining text runs. engine->SelectAll(); engine->Delete(); INTL_Encoding_ID encoding; unsigned char* outtext; INTL_CompoundStrIterator iter; for(iter = INTL_CompoundStrFirstStr((INTL_CompoundStrIterator)cs, &encoding , &outtext); iter != NULL; iter = INTL_CompoundStrNextStr(iter, &encoding, &outtext)) { if((outtext) && (*outtext)) { Int32 theTextSize = engine->GetTextLength(); // Set the Text engine->SetSelection(LONG_MAX, LONG_MAX); engine->InsertPtr((char*)outtext, XP_STRLEN((char*)outtext), NULL, NULL); CCharSet charset; // Don't move this line since the fontname is point to it. unsigned char* fontname; switch(encoding) { case CS_SYMBOL: fontname = (unsigned char*)"\pSymbol"; break; case CS_DINGBATS: fontname = (unsigned char*)"\pZapf Dingbats"; break; default: Boolean gotFont = CPrefs::GetFont(encoding, &charset); Assert_(gotFont); fontname = &charset.fPropFont[0];//fFixedFont[0]; break; } TextStyle inTextStyle; GetFNum(fontname, &inTextStyle.tsFont); engine->SetSelection(theTextSize, LONG_MAX); engine->SetStyle(weDoFont, &inTextStyle); } } INTL_CompoundStrDestroy(cs); } } static void PutUTF8IntoTextEngine( CWASTEEdit* engine, char* text, Int32 len) { if(len >0) { uint32 ubuflen = len+1; uint32 ucs2len; INTL_Unicode* ucs2buf = NULL; ucs2buf = new INTL_Unicode[ubuflen]; if(ucs2buf && (0 != (ucs2len = UUTF8TextHandler::Instance()->UTF8ToUCS2((unsigned char*) text, len, ucs2buf, ubuflen) ))) PutUnicodeIntoTextEngine(engine, ucs2buf, ucs2len); else Assert_(FALSE); if(ucs2buf) delete ucs2buf; } } static void ChangeTextTraitsForSingleScript( CWASTEEdit* engine, unsigned short csid) { TextTraitsH theTextTraits = UTextTraits::LoadTextTraits(CPrefs::GetTextFieldTextResIDs(csid)); TextStyle ts; if (theTextTraits != NULL) { ts.tsFont = (*theTextTraits)->fontNumber; ts.tsSize = (*theTextTraits)->size; ts.tsFace = (*theTextTraits)->style; ts.tsColor = (*theTextTraits)->color; engine->SetStyle(weDoAll, &ts); } } static void SetupTextInTextEngine( CWASTEEdit* engine, int16 csid, char* text, int32 len) { if(CS_UTF8 == csid) { PutUTF8IntoTextEngine( engine, text, len ); } else { ChangeTextTraitsForSingleScript(engine, csid ); if (text != NULL) engine->InsertPtr( text, len, NULL, NULL, true ); else { engine->SelectAll(); engine->Delete(); } } } void UFormElementFactory::ResetFormElementData( LO_FormElementStruct *formElem, Boolean redraw, Boolean fromDefaults, Boolean reflect) { if (!formElem->element_data) return; switch (formElem->element_data->type) { case FORM_TYPE_TEXT: // Set the text case FORM_TYPE_PASSWORD: case FORM_TYPE_ISINDEX: { if ( !GetFEData( formElem ) ) return; lo_FormElementTextData* textData = & formElem->element_data->ele_text; LEditField * editField = (LEditField *)FEDATAPANE; if (!editField) return; char* newText = NULL; if ( fromDefaults ) { if ( textData->default_text ) // Eric might be passing us NULL { newText = (char*)textData->default_text; editField->SetDescriptor( CStr255( newText ) ); } else editField->SetDescriptor( "\p" ); } else { newText = (char*)textData->current_text; editField->SetDescriptor( CStr255( newText ) ); } if ( redraw ) { editField->Refresh(); editField->UpdatePort(); } } break; case FORM_TYPE_TEXTAREA: { if ( !GetFEData( formElem ) ) return; lo_FormElementTextareaData* textAreaData = (lo_FormElementTextareaData*) formElem->element_data; LView* scroller = (LView*)FEDATAPANE; if (!scroller) return; CSimpleTextView* textEdit = (CSimpleTextView*)scroller->FindPaneByID(formBigTextID); CWASTEEdit* engine = dynamic_cast(textEdit); char* default_text; if ( fromDefaults ) { if ( textAreaData->default_text ) { default_text = (char*)textAreaData->default_text; ValidateTextByCharset(formElem->text_attr->charset, default_text); Try_ { SetupTextInTextEngine(engine, formElem->text_attr->charset, default_text, XP_STRLEN((char*)default_text)); } Catch_( inErr ) { } EndCatch_ } else // No default value { Try_ { SetupTextInTextEngine(engine, formElem->text_attr->charset, NULL, 0); } Catch_( inErr ) { } } } else { default_text = (char*)textAreaData->current_text; ValidateTextByCharset(formElem->text_attr->charset, default_text); Try_ { // don't want ending linefeed Int32 length = XP_STRLEN((char*)default_text)-1; if( length ) SetupTextInTextEngine(engine, formElem->text_attr->charset, default_text, length); } Catch_( inErr ) { } } if ( redraw ) textEdit->Refresh(); } break; case FORM_TYPE_RADIO: // Set the toggle to on or off case FORM_TYPE_CHECKBOX: { if ( !GetFEData( formElem ) ) return; lo_FormElementToggleData* toggleData = (lo_FormElementToggleData*)formElem->element_data; LStdControl* toggle = (LStdControl*)FEDATAPANE; if (!toggle) return; if ( fromDefaults ) { if ( toggle->GetValue() == toggleData->default_toggle ) // Do not change unless we have to break; toggle->SetValue( toggleData->default_toggle ); } else // use the stored value { if ( toggle->GetValue() == toggleData->toggled ) break; toggle->SetValue( toggleData->toggled ); } if ( redraw ) toggle->Refresh(); } break; case FORM_TYPE_FILE: { lo_FormElementTextData * pickData = (lo_FormElementTextData*)formElem->element_data; CFormFile * formFile = (CFormFile *)FEDATAPANE; if (!formFile) return; formFile->SetVisibleChars(pickData->size); if (fromDefaults) ; // Do nothing else { char * default_text; FSSpec spec; OSErr err; PA_LOCK(default_text, char*, pickData->current_text); if (default_text) err = CFileMgr::FSSpecFromLocalUnixPath(default_text, &spec); else err = fnfErr; PA_UNLOCK(pickData->current_text); if (err == noErr) formFile->SetFileSpec(spec); } if (redraw) formFile->Refresh(); } break; case FORM_TYPE_HIDDEN: case FORM_TYPE_KEYGEN: case FORM_TYPE_SUBMIT: case FORM_TYPE_RESET: case FORM_TYPE_BUTTON: // no value to set or reset break; case FORM_TYPE_SELECT_ONE: { if ( !GetFEData( formElem ) ) return; lo_FormElementSelectData* selectData = (lo_FormElementSelectData*)formElem->element_data; int offset = CalcCurrentSelected( selectData, fromDefaults ); LButton* widget = (LButton*)FEDATAPANE; FormsPopup* popup = (FormsPopup*)FEDATAHOST; if (popup) popup->DirtyMenu(); if (!widget) return; widget->SetValue( offset + 1 ); if ( redraw ) widget->Refresh(); } break; case FORM_TYPE_SELECT_MULT: // Select/unselect the cells { if ( !GetFEData( formElem ) ) return; lo_FormElementOptionData* mother; lo_FormElementSelectData* selectData = (lo_FormElementSelectData *)formElem->element_data; CFormList* myList = (CFormList*)FEDATAPANE; if (!myList) return; myList->SelectNone(); myList->FocusDraw(); ::LSetDrawingMode( FALSE, myList->GetMacListH() ); mother = (lo_FormElementOptionData*)selectData->options; myList->SyncRows( selectData->option_cnt ); for ( int i = 0; i < selectData->option_cnt; i++ ) { char* itemName = NULL; Boolean select; itemName = (char*)mother[ i ].text_value; myList->AddItem( itemName, i ); if ( fromDefaults ) select = mother[ i ].def_selected; else select = mother[ i ].selected; if (select) myList->SetSelect( i, select ); } ::LSetDrawingMode( TRUE, myList->GetMacListH() ); // ¥Êthis forces an update of the scrollbar, if there is // one ::LUpdate( NULL, myList->GetMacListH() ); myList->ShrinkToFit( selectData->size ); Cell selection = { myList->GetValue(), 0 }; // cells are v, h myList->MakeCellVisible ( selection ); if ( redraw ) myList->Refresh(); } break; case FORM_TYPE_IMAGE: case FORM_TYPE_JOT: case FORM_TYPE_OBJECT: break; } // immediately reflect our state if (reflect) FEDATAHOST->ReflectData(); }