From ea90ff591e876d3ad766c4617b3648c5338b711e Mon Sep 17 00:00:00 2001 From: "karnaze%netscape.com" Date: Wed, 23 Sep 1998 17:16:51 +0000 Subject: [PATCH] Converted forms to use the new content model classes and better separate content from layout. git-svn-id: svn://10.0.0.236/trunk@10800 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/html/content/makefile.win | 2 +- .../content/html/content/public/makefile.win | 25 + mozilla/content/html/content/public/nsIForm.h | 75 ++ .../html/content/public/nsIFormControl.h | 85 ++ .../html/content/src/nsGenericHTMLElement.cpp | 25 +- .../html/content/src/nsGenericHTMLElement.h | 5 + .../html/content/src/nsHTMLButtonElement.cpp | 1 + .../html/content/src/nsHTMLFormElement.cpp | 383 ++++++- .../html/content/src/nsHTMLInputElement.cpp | 364 +++++- .../html/content/src/nsHTMLOptionElement.cpp | 104 +- .../html/content/src/nsHTMLSelectElement.cpp | 435 ++++++- .../content/src/nsHTMLTextAreaElement.cpp | 210 +++- .../html/document/src/nsHTMLContentSink.cpp | 274 ++--- .../html/document/src/nsHTMLDocument.cpp | 162 +-- .../html/document/src/nsHTMLDocument.h | 14 +- .../html/document/src/nsIHTMLDocument.h | 18 +- .../html/style/src/nsHTMLStyleSheet.cpp | 31 +- mozilla/layout/base/src/nsPresShell.cpp | 8 +- mozilla/layout/base/src/nsStyleConsts.h | 1 - mozilla/layout/forms/nsFileControlFrame.cpp | 314 +++++ .../nsFormControlFrame.h} | 88 +- mozilla/layout/forms/nsTextControlFrame.cpp | 374 ++++++ mozilla/layout/forms/nsTextControlFrame.h | 66 ++ mozilla/layout/generic/nsHTMLParts.h | 32 +- mozilla/layout/html/base/src/nsHTMLParts.h | 32 +- mozilla/layout/html/content/Makefile | 2 +- mozilla/layout/html/content/makefile.win | 2 +- mozilla/layout/html/content/public/Makefile | 29 + .../layout/html/content/public/makefile.win | 25 + mozilla/layout/html/content/public/nsIForm.h | 75 ++ .../html/content/public/nsIFormControl.h | 85 ++ .../html/content/src/nsGenericHTMLElement.cpp | 25 +- .../html/content/src/nsGenericHTMLElement.h | 5 + .../html/content/src/nsHTMLButtonElement.cpp | 1 + .../html/content/src/nsHTMLFormElement.cpp | 383 ++++++- .../html/content/src/nsHTMLInputElement.cpp | 364 +++++- .../html/content/src/nsHTMLOptionElement.cpp | 104 +- .../html/content/src/nsHTMLSelectElement.cpp | 435 ++++++- .../content/src/nsHTMLTextAreaElement.cpp | 210 +++- .../html/document/src/nsHTMLContentSink.cpp | 274 ++--- .../html/document/src/nsHTMLDocument.cpp | 162 +-- .../layout/html/document/src/nsHTMLDocument.h | 14 +- .../html/document/src/nsIHTMLDocument.h | 18 +- mozilla/layout/html/forms/public/Makefile | 1 - mozilla/layout/html/forms/public/makefile.win | 2 +- .../layout/html/forms/public/nsIFormControl.h | 122 -- .../layout/html/forms/public/nsIFormManager.h | 102 +- mozilla/layout/html/forms/src/Makefile | 17 +- mozilla/layout/html/forms/src/makefile.win | 14 +- .../html/forms/src/nsButtonControlFrame.cpp | 418 +++++++ .../html/forms/src/nsButtonControlFrame.h | 77 ++ .../html/forms/src/nsCheckboxControlFrame.cpp | 238 ++++ .../html/forms/src/nsFileControlFrame.cpp | 314 +++++ .../html/forms/src/nsFormControlFrame.h | 255 +++++ mozilla/layout/html/forms/src/nsFormFrame.cpp | 1019 +++++++++++++++++ mozilla/layout/html/forms/src/nsFormFrame.h | 91 ++ mozilla/layout/html/forms/src/nsHTMLForms.h | 169 --- .../html/forms/src/nsIFormControlFrame.h | 58 + mozilla/layout/html/forms/src/nsInput.cpp | 910 --------------- .../layout/html/forms/src/nsInputButton.cpp | 697 ----------- .../layout/html/forms/src/nsInputCheckbox.cpp | 321 ------ .../layout/html/forms/src/nsInputCheckbox.h | 54 - mozilla/layout/html/forms/src/nsInputFile.cpp | 314 ----- mozilla/layout/html/forms/src/nsInputFile.h | 77 -- .../layout/html/forms/src/nsInputFrame.cpp | 693 ----------- .../layout/html/forms/src/nsInputRadio.cpp | 412 ------- mozilla/layout/html/forms/src/nsInputRadio.h | 89 -- mozilla/layout/html/forms/src/nsInputText.cpp | 554 --------- mozilla/layout/html/forms/src/nsInputText.h | 79 -- .../html/forms/src/nsRadioControlFrame.cpp | 281 +++++ .../html/forms/src/nsRadioControlFrame.h | 87 ++ mozilla/layout/html/forms/src/nsSelect.cpp | 754 ------------ .../html/forms/src/nsSelectControlFrame.cpp | 581 ++++++++++ .../html/forms/src/nsTextControlFrame.cpp | 374 ++++++ .../html/forms/src/nsTextControlFrame.h | 66 ++ .../html/style/src/nsHTMLStyleSheet.cpp | 31 +- mozilla/layout/style/nsHTMLStyleSheet.cpp | 31 +- 77 files changed, 8316 insertions(+), 6327 deletions(-) create mode 100644 mozilla/content/html/content/public/makefile.win create mode 100644 mozilla/content/html/content/public/nsIForm.h create mode 100644 mozilla/content/html/content/public/nsIFormControl.h create mode 100644 mozilla/layout/forms/nsFileControlFrame.cpp rename mozilla/layout/{html/forms/src/nsInputFrame.h => forms/nsFormControlFrame.h} (77%) create mode 100644 mozilla/layout/forms/nsTextControlFrame.cpp create mode 100644 mozilla/layout/forms/nsTextControlFrame.h create mode 100644 mozilla/layout/html/content/public/Makefile create mode 100644 mozilla/layout/html/content/public/makefile.win create mode 100644 mozilla/layout/html/content/public/nsIForm.h create mode 100644 mozilla/layout/html/content/public/nsIFormControl.h delete mode 100644 mozilla/layout/html/forms/public/nsIFormControl.h create mode 100644 mozilla/layout/html/forms/src/nsButtonControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsButtonControlFrame.h create mode 100644 mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsFileControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsFormControlFrame.h create mode 100644 mozilla/layout/html/forms/src/nsFormFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsFormFrame.h delete mode 100644 mozilla/layout/html/forms/src/nsHTMLForms.h create mode 100644 mozilla/layout/html/forms/src/nsIFormControlFrame.h delete mode 100644 mozilla/layout/html/forms/src/nsInput.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputButton.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputCheckbox.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputCheckbox.h delete mode 100644 mozilla/layout/html/forms/src/nsInputFile.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputFile.h delete mode 100644 mozilla/layout/html/forms/src/nsInputFrame.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputRadio.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputRadio.h delete mode 100644 mozilla/layout/html/forms/src/nsInputText.cpp delete mode 100644 mozilla/layout/html/forms/src/nsInputText.h create mode 100644 mozilla/layout/html/forms/src/nsRadioControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsRadioControlFrame.h delete mode 100644 mozilla/layout/html/forms/src/nsSelect.cpp create mode 100644 mozilla/layout/html/forms/src/nsSelectControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsTextControlFrame.cpp create mode 100644 mozilla/layout/html/forms/src/nsTextControlFrame.h diff --git a/mozilla/content/html/content/makefile.win b/mozilla/content/html/content/makefile.win index 5620ead1bde..d7edb135b7f 100644 --- a/mozilla/content/html/content/makefile.win +++ b/mozilla/content/html/content/makefile.win @@ -17,6 +17,6 @@ DEPTH=..\..\.. -DIRS=src +DIRS=src public include <$(DEPTH)\layout\config\rules.mak> diff --git a/mozilla/content/html/content/public/makefile.win b/mozilla/content/html/content/public/makefile.win new file mode 100644 index 00000000000..e9d612947ce --- /dev/null +++ b/mozilla/content/html/content/public/makefile.win @@ -0,0 +1,25 @@ +#!nmake +# +# 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. + +DEPTH=..\..\..\.. + +EXPORTS=nsIFormControl.h nsIForm.h + +MODULE=raptor + +include <$(DEPTH)\layout\config\rules.mak> + diff --git a/mozilla/content/html/content/public/nsIForm.h b/mozilla/content/html/content/public/nsIForm.h new file mode 100644 index 00000000000..ad395a1a839 --- /dev/null +++ b/mozilla/content/html/content/public/nsIForm.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#ifndef nsIForm_h___ +#define nsIForm_h___ + +#include "nsISupports.h" +class nsIFormControl; + +#define NS_FORM_METHOD_GET 0 +#define NS_FORM_METHOD_POST 1 +#define NS_FORM_ENCTYPE_URLENCODED 0 +#define NS_FORM_ENCTYPE_MULTIPART 1 + +// IID for the nsIFormManager interface +#define NS_IFORM_IID \ +{ 0xb7e94510, 0x4c19, 0x11d2, \ + { 0x80, 0x3f, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } + +/** + * This interface provides a complete set of methods dealing with elements which + * belong to a form element. When nsIDOMHTMLCollection allows write operations + **/ +class nsIForm : public nsISupports { +public: + + /** + * Add an element to end of this form's list of elements + * @param aElement the element to add + * @return NS_OK if the element was successfully added + */ + NS_IMETHOD AddElement(nsIFormControl* aElement) = 0; + + /** + * Get the element at a specified index position + * @param aIndex the index + * @param aElement the element at that index + * @return NS_OK if there was an element at that position, -1 otherwise + */ + NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const = 0; + + /** + * Get the number of elements in this form + * @param aCount the number of elements + * @return NS_OK if there was an element at that position, -1 otherwise + */ + NS_IMETHOD GetElementCount(PRUint32* aCount) const = 0; + + /** + * Remove an element from this form's list of elements + * @param aElement the element to remove + * @param aChildIsRef if PR_TRUE, the elements ref count will be decremented + * otherwise not. This is to facilitate circular references. + * @return NS_OK if the element was successfully removed. + */ + NS_IMETHOD RemoveElement(nsIFormControl* aElement, + PRBool aChildIsRef = PR_TRUE) = 0; + +}; + +#endif /* nsIForm_h___ */ diff --git a/mozilla/content/html/content/public/nsIFormControl.h b/mozilla/content/html/content/public/nsIFormControl.h new file mode 100644 index 00000000000..7249c803174 --- /dev/null +++ b/mozilla/content/html/content/public/nsIFormControl.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#ifndef nsIFormControl_h___ +#define nsIFormControl_h___ + +#include "nsISupports.h" +class nsIDOMHTMLFormElement; +class nsIWidget; + +#define NS_FORM_BROWSE 0 +#define NS_FORM_BUTTON 1 +#define NS_FORM_FIELDSET 2 +#define NS_FORM_INPUT_BUTTON 3 +#define NS_FORM_INPUT_CHECKBOX 4 +#define NS_FORM_INPUT_FILE 5 +#define NS_FORM_INPUT_HIDDEN 6 +#define NS_FORM_INPUT_RESET 7 +#define NS_FORM_INPUT_IMAGE 8 +#define NS_FORM_INPUT_PASSWORD 9 +#define NS_FORM_INPUT_RADIO 10 +#define NS_FORM_INPUT_SUBMIT 11 +#define NS_FORM_INPUT_TEXT 12 +#define NS_FORM_OPTION 13 +#define NS_FORM_OPTGROUP 14 +#define NS_FORM_LEGEND 15 +#define NS_FORM_SELECT 16 +#define NS_FORM_TEXTAREA 17 + +#define NS_FORM_NOTOK 0xFFFFFFF7 +#define NS_FORM_NOTSET 0xFFFFFFF7 + +#define NS_IFORMCONTROL_IID \ +{ 0x282ff440, 0xcd7e, 0x11d1, \ + {0x89, 0xad, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} } + + +/** + * Interface which all form controls (e.g. buttons, checkboxes, text, + * radio buttons, select, etc) implement in addition to their dom specific interface. + **/ +class nsIFormControl : public nsISupports { +public: + /** + * Get the form for this form control. + * @param aForm the form to get + * @return NS_OK + */ + NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm) = 0; + + /** + * Set the form for this form control. + * @param aForm the form + * @return NS_OK + */ + NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm) = 0; + + /** + * Get the type of this control + * @param aType the type to be returned + * @return NS_OK + */ + NS_IMETHOD GetType(PRInt32* aType) = 0; + + NS_IMETHOD SetWidget(nsIWidget* aWidget) = 0; + + NS_IMETHOD Init() = 0; + +}; + +#endif /* nsIFormControl_h___ */ diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index 610179a5b4b..e963f2d6307 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -936,8 +936,8 @@ nsGenericHTMLElement::SetClassName(const nsString& aClassName) nsresult nsGenericHTMLElement::GetDocument(nsIDocument*& aResult) const { - aResult = mDocument; NS_IF_ADDREF(mDocument); + aResult = mDocument; return NS_OK; } @@ -2253,6 +2253,15 @@ static nsGenericHTMLElement::EnumTable kDivAlignTable[] = { { 0 } }; +static nsGenericHTMLElement::EnumTable kFormAlignTable[] = { + { "left", NS_STYLE_TEXT_ALIGN_LEFT }, + { "right", NS_STYLE_TEXT_ALIGN_RIGHT }, + { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM }, + { "top", NS_STYLE_VERTICAL_ALIGN_TOP }, + { "middle", NS_STYLE_VERTICAL_ALIGN_MIDDLE }, + { 0 } +}; + static nsGenericHTMLElement::EnumTable kFrameborderQuirksTable[] = { { "yes", NS_STYLE_FRAME_YES }, { "no", NS_STYLE_FRAME_NO }, @@ -2331,6 +2340,20 @@ nsGenericHTMLElement::AlignValueToString(const nsHTMLValue& aValue, return EnumValueToString(aValue, kAlignTable, aResult); } +PRBool +nsGenericHTMLElement::ParseFormAlignValue(const nsString& aString, + nsHTMLValue& aResult) +{ + return ParseEnumValue(aString, kFormAlignTable, aResult); +} + +PRBool +nsGenericHTMLElement::FormAlignValueToString(const nsHTMLValue& aValue, + nsString& aResult) +{ + return EnumValueToString(aValue, kFormAlignTable, aResult); +} + PRBool nsGenericHTMLElement::TableHAlignValueToString(const nsHTMLValue& aValue, nsString& aResult) diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.h b/mozilla/content/html/content/src/nsGenericHTMLElement.h index 096b13aaeb2..4e206c5f0f5 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.h @@ -230,6 +230,9 @@ public: static PRBool ParseAlignValue(const nsString& aString, nsHTMLValue& aResult); + static PRBool ParseFormAlignValue(const nsString& aString, + nsHTMLValue& aResult); + static PRBool ParseDivAlignValue(const nsString& aString, nsHTMLValue& aResult); @@ -248,6 +251,8 @@ public: static PRBool AlignValueToString(const nsHTMLValue& aValue, nsString& aResult); + static PRBool FormAlignValueToString(const nsHTMLValue& aValue, + nsString& aResult); static PRBool DivAlignValueToString(const nsHTMLValue& aValue, nsString& aResult); diff --git a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp index 0fcfa436357..d33736e4a70 100644 --- a/mozilla/content/html/content/src/nsHTMLButtonElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLButtonElement.cpp @@ -154,6 +154,7 @@ NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey, eSetAttrNotify_No NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled, eSetAttrNotify_Render) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Name, name, eSetAttrNotify_Restart) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Type, type, eSetAttrNotify_Restart) +NS_IMPL_INT_ATTR(nsHTMLButtonElement, TabIndex, tabindex, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value, eSetAttrNotify_Render) NS_IMETHODIMP diff --git a/mozilla/content/html/content/src/nsHTMLFormElement.cpp b/mozilla/content/html/content/src/nsHTMLFormElement.cpp index f869db3a2e3..57d7ff955b3 100644 --- a/mozilla/content/html/content/src/nsHTMLFormElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLFormElement.cpp @@ -16,7 +16,12 @@ * Corporation. Portions created by Netscape are Copyright (C) 1998 * Netscape Communications Corporation. All Rights Reserved. */ +#include "nsIForm.h" +#include "nsIFormControl.h" +#include "nsIFormManager.h" #include "nsIDOMHTMLFormElement.h" +#include "nsIDOMNSHTMLFormElement.h" +#include "nsIDOMHTMLCollection.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +31,25 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIFrame.h" static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormManagerIID, NS_IFORMMANAGER_IID); +static NS_DEFINE_IID(kIDOMNSHTMLFormElementIID, NS_IDOMNSHTMLFORMELEMENT_IID); + +class nsFormControlList; + +// nsHTMLFormElement class nsHTMLFormElement : public nsIDOMHTMLFormElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIForm { public: nsHTMLFormElement(nsIAtom* aTag); @@ -78,10 +95,45 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIForm + NS_IMETHOD AddElement(nsIFormControl* aElement); + NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const; + NS_IMETHOD GetElementCount(PRUint32* aCount) const; + NS_IMETHOD RemoveElement(nsIFormControl* aElement, PRBool aChildIsRef = PR_TRUE); + protected: + nsFormControlList* mControls; nsGenericHTMLLeafElement mInner; }; +// nsFormControlList +class nsFormControlList : public nsIDOMHTMLCollection, public nsIScriptObjectOwner { +public: + nsFormControlList(); + virtual ~nsFormControlList(); + + void Clear(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void *aScriptObject); + NS_IMETHOD ResetScriptObject(); + + // nsIDOMHTMLCollection interface + NS_DECL_IDOMHTMLCOLLECTION + + // Called to tell us that the form is going away and that we + // should drop our (non ref-counted) reference to it + void ReleaseForm(); + + void *mScriptObject; + nsVoidArray mElements; +}; + +// nsHTMLFormElement implementation + +// construction, destruction nsresult NS_NewHTMLFormElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -100,29 +152,80 @@ nsHTMLFormElement::nsHTMLFormElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mControls = new nsFormControlList(); + NS_ADDREF(mControls); +nsTraceRefcnt::Create((nsIForm*)this, "nsHTMLFormElement", __FILE__, __LINE__); } nsHTMLFormElement::~nsHTMLFormElement() { + // set the controls to have no form + PRUint32 numControls; + GetElementCount(&numControls); + for (PRUint32 i = 0; i < numControls; i++) { + // avoid addref to child + nsIFormControl* control = (nsIFormControl*)mControls->mElements.ElementAt(i); + if (control) { + // it is assummed that passing in nsnull will not release formControl's previous form + control->SetForm(nsnull); + } + } + + NS_RELEASE(mControls); + + // XXX make sure this gets moved into nsFormFrame, but not the 1st one!! + //mChildren.Clear(); + //RemoveRadioGroups(); +nsTraceRefcnt::Destroy((nsIForm*)this, __FILE__, __LINE__); } -NS_IMPL_ADDREF(nsHTMLFormElement) - -NS_IMPL_RELEASE(nsHTMLFormElement) - -nsresult +// nsISupports +NS_IMETHODIMP nsHTMLFormElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) - if (aIID.Equals(kIDOMHTMLFormElementIID)) { - nsIDOMHTMLFormElement* tmp = this; - *aInstancePtr = (void*) tmp; - mRefCnt++; + if (aIID.Equals(kIFormIID)) { + *aInstancePtr = (void*)(nsIForm*)this; + AddRef(); + return NS_OK; + } + else if (aIID.Equals(kIDOMHTMLFormElementIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLFormElement*)this; + AddRef(); + return NS_OK; + } + else if (aIID.Equals(kIDOMNSHTMLFormElementIID)) { + *aInstancePtr = (void*)(nsIDOMNSHTMLFormElement*)this; + AddRef(); return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP +nsHTMLFormElement::AddRef(void) +{ +nsTraceRefcnt::AddRef((nsIForm*)this, mRefCnt+1, __FILE__, __LINE__); + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} + +NS_IMETHODIMP_(nsrefcnt) +nsHTMLFormElement::Release() +{ +nsTraceRefcnt::Release((nsIForm*)this, mRefCnt-1, __FILE__, __LINE__); + --mRefCnt; + PRUint32 numChildren; + GetElementCount(&numChildren); + if ((int)mRefCnt == numChildren) { + mRefCnt = 0; + delete this; + return 0; + } + return mRefCnt; +} + +// nsIDOMHTMLFormElement nsresult nsHTMLFormElement::CloneNode(nsIDOMNode** aReturn) { @@ -135,9 +238,10 @@ nsHTMLFormElement::CloneNode(nsIDOMNode** aReturn) } NS_IMETHODIMP -nsHTMLFormElement::GetElements(nsIDOMHTMLCollection** aResult) +nsHTMLFormElement::GetElements(nsIDOMHTMLCollection** aElements) { - // XXX write me + *aElements = mControls; + NS_ADDREF(mControls); return NS_OK; } @@ -154,26 +258,85 @@ NS_IMPL_STRING_ATTR(nsHTMLFormElement, Method, method, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target, eSetAttrNotify_None) NS_IMETHODIMP -nsHTMLFormElement::Reset() +nsHTMLFormElement::Submit() { - // XXX - return NS_OK; + // XXX Need to do something special with mailto: or news: URLs + nsIDocument* doc = nsnull; + nsresult result = GetDocument(doc); + if ((NS_OK == result) && doc) { + nsIPresShell *shell = doc->GetShellAt(0); + if (nsnull != shell) { + nsIFrame* frame = shell->FindFrameWithContent(this); + if (frame) { + nsIFormManager* formMan = nsnull; + nsresult result = frame->QueryInterface(kIFormManagerIID, (void**)&formMan); + if ((NS_OK == result) && formMan) { + nsIPresContext *context = shell->GetPresContext(); + if (nsnull != context) { + // XXX We're currently passing in null for the frame. + // It works for now, but might not always + // be correct. In the future, we might not need the + // frame to be passed to the link handler. + result = formMan->OnSubmit(context, nsnull); + NS_RELEASE(context); + } + } + } + NS_RELEASE(shell); + } + NS_RELEASE(doc); + } + + return result; } NS_IMETHODIMP -nsHTMLFormElement::Submit() +nsHTMLFormElement::Reset() { - // XXX - return NS_OK; -} + // XXX Need to do something special with mailto: or news: URLs + nsIDocument* doc = nsnull; + nsresult result = GetDocument(doc); + if ((NS_OK == result) && doc) { + nsIPresShell *shell = doc->GetShellAt(0); + if (nsnull != shell) { + nsIFrame* frame = shell->FindFrameWithContent(this); + if (frame) { + nsIFormManager* formMan = nsnull; + nsresult result = frame->QueryInterface(kIFormManagerIID, (void**)&formMan); + if ((NS_OK == result) && formMan) { + result = formMan->OnReset(); + } + } + NS_RELEASE(shell); + } + } + return result; +} +static nsGenericHTMLElement::EnumTable kFormMethodTable[] = { + { "get", NS_FORM_METHOD_GET }, + { "post", NS_FORM_METHOD_POST }, + { 0 } +}; +static nsGenericHTMLElement::EnumTable kFormEnctypeTable[] = { + { "multipart/form-data", NS_FORM_ENCTYPE_MULTIPART }, + { "application/x-www-form-urlencoded", NS_FORM_ENCTYPE_URLENCODED }, + { 0 } +}; NS_IMETHODIMP nsHTMLFormElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::method) { + nsGenericHTMLElement::ParseEnumValue(aValue, kFormMethodTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::enctype) { + nsGenericHTMLElement::ParseEnumValue(aValue, kFormEnctypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -182,7 +345,18 @@ nsHTMLFormElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::method) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kFormMethodTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::enctype) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kFormEnctypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -214,3 +388,166 @@ nsHTMLFormElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIForm + +NS_IMETHODIMP +nsHTMLFormElement::GetElementCount(PRUint32* aCount) const +{ + mControls->GetLength(aCount); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::GetElementAt(PRInt32 aIndex, nsIFormControl** aFormControl) const +{ + *aFormControl = (nsIFormControl*) mControls->mElements.ElementAt(aIndex); + NS_IF_ADDREF(*aFormControl); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::AddElement(nsIFormControl* aChild) +{ + PRBool rv = mControls->mElements.AppendElement(aChild); + if (rv) { + NS_ADDREF(aChild); + } + return rv; +} + +NS_IMETHODIMP +nsHTMLFormElement::RemoveElement(nsIFormControl* aChild, PRBool aChildIsRef) +{ + PRBool rv = mControls->mElements.RemoveElement(aChild); + if (rv && aChildIsRef) { + NS_RELEASE(aChild); + } + return rv; +} + + +// nsFormControlList implementation, this could go away if there were a lightweight collection implementation somewhere + +nsFormControlList::nsFormControlList() +{ + mRefCnt = 0; + mScriptObject = nsnull; +} + +nsFormControlList::~nsFormControlList() +{ +} + +NS_IMETHODIMP +nsFormControlList::SetScriptObject(void *aScriptObject) +{ + mScriptObject = aScriptObject; + return NS_OK; +} + +void +nsFormControlList::Clear() +{ + PRUint32 numElements = mElements.Count(); + for (PRUint32 i = 0; i < numElements; i++) { + nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i); + NS_IF_RELEASE(elem); + } +} + +nsresult nsFormControlList::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + static NS_DEFINE_IID(kIDOMHTMLCollectionIID, NS_IDOMHTMLCOLLECTION_IID); + static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); + if (aIID.Equals(kIDOMHTMLCollectionIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIScriptObjectOwnerIID)) { + *aInstancePtr = (void*)(nsIScriptObjectOwner*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(nsFormControlList) +NS_IMPL_RELEASE(nsFormControlList) + + +nsresult nsFormControlList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) +{ + nsresult res = NS_OK; + if (nsnull == mScriptObject) { + res = NS_NewScriptHTMLCollection(aContext, (nsISupports *)(nsIDOMHTMLCollection *)this, nsnull, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; + return res; +} + +nsresult nsFormControlList::ResetScriptObject() +{ + mScriptObject = nsnull; + return NS_OK; +} + +// nsIDOMHTMLCollection interface +NS_IMETHODIMP +nsFormControlList::GetLength(PRUint32* aLength) +{ + *aLength = mElements.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsFormControlList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(aIndex); + if (control) { + return control->QueryInterface(kIDOMNodeIID, (void**)aReturn); // keep the ref + } + *aReturn = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsFormControlList::NamedItem(const nsString& aName, nsIDOMNode** aReturn) +{ + PRUint32 count = mElements.Count(); + nsresult result = NS_OK; + + *aReturn = nsnull; + for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) { + nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(i); + if (nsnull != control) { + nsIContent *content; + + result = control->QueryInterface(kIContentIID, (void **)&content); + if (NS_OK == result) { + nsAutoString name; + // XXX Should it be an EqualsIgnoreCase? + if (((content->GetAttribute("NAME", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name))) || + ((content->GetAttribute("ID", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name)))) { + result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn); + } + NS_RELEASE(content); + } + } + } + + return result; +} + diff --git a/mozilla/content/html/content/src/nsHTMLInputElement.cpp b/mozilla/content/html/content/src/nsHTMLInputElement.cpp index 899439f9804..50d68fe74e9 100644 --- a/mozilla/content/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLInputElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -27,15 +28,24 @@ #include "nsStyleConsts.h" #include "nsIPresContext.h" #include "nsIHTMLAttributes.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIWidget.h" +#include "nsITextWidget.h" // XXX align=left, hspace, vspace, border? other nav4 attrs static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); class nsHTMLInputElement : public nsIDOMHTMLInputElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLInputElement(nsIAtom* aTag); @@ -105,10 +115,21 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm); + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLLeafElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; + PRInt32 mType; }; +// construction, destruction + nsresult NS_NewHTMLInputElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -127,29 +148,70 @@ nsHTMLInputElement::nsHTMLInputElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mType = NS_FORM_INPUT_TEXT; // default value + mForm = nsnull; + mWidget = nsnull; +nsTraceRefcnt::Create((nsIFormControl*)this, "nsHTMLFormControlElement", __FILE__, __LINE__); } nsHTMLInputElement::~nsHTMLInputElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } +nsTraceRefcnt::Destroy((nsIFormControl*)this, __FILE__, __LINE__); } -NS_IMPL_ADDREF(nsHTMLInputElement) +// nsISupports -NS_IMPL_RELEASE(nsHTMLInputElement) +NS_IMETHODIMP_(nsrefcnt) +nsHTMLInputElement::AddRef(void) +{ +nsTraceRefcnt::AddRef((nsIFormControl*)this, mRefCnt+1, __FILE__, __LINE__); + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} -nsresult + +NS_IMETHODIMP nsHTMLInputElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLInputElementIID)) { - nsIDOMHTMLInputElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLInputElement*) this; + NS_ADDREF_THIS(); + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLInputElement::Release() +{ +nsTraceRefcnt::Release((nsIFormControl*)this, mRefCnt-1, __FILE__, __LINE__); + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLInputElement + nsresult nsHTMLInputElement::CloneNode(nsIDOMNode** aReturn) { @@ -164,7 +226,14 @@ nsHTMLInputElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } @@ -195,66 +264,45 @@ nsHTMLInputElement::GetType(nsString& aValue) NS_IMETHODIMP nsHTMLInputElement::Blur() { - // XXX write me + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Focus() { - // XXX write me + if (nsnull != mWidget) { + mWidget->SetFocus(); + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Select() { - // XXX write me + if ((NS_FORM_INPUT_TEXT == mType) && (nsnull != mWidget)) { + nsITextWidget *textWidget; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget)) { + textWidget->SelectAll(); + NS_RELEASE(textWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Click() { - // XXX write me - return NS_OK; + //XXX TBI + return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP -nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, - const nsString& aValue, - nsHTMLValue& aResult) -{ - // XXX align - return NS_CONTENT_ATTR_NOT_THERE; -} - -NS_IMETHODIMP -nsHTMLInputElement::AttributeToString(nsIAtom* aAttribute, - nsHTMLValue& aValue, - nsString& aResult) const -{ - // XXX align - return mInner.AttributeToString(aAttribute, aValue, aResult); -} - -static void -MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - // XXX align - nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsHTMLInputElement::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &MapAttributesInto; - return NS_OK; -} - - NS_IMETHODIMP nsHTMLInputElement::HandleDOMEvent(nsIPresContext& aPresContext, nsEvent* aEvent, @@ -265,3 +313,221 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIHTMLContent + +static nsGenericHTMLElement::EnumTable kInputTypeTable[] = { + { "browse", NS_FORM_BROWSE }, // XXX not valid html, but it is convient + { "button", NS_FORM_INPUT_BUTTON }, + { "checkbox", NS_FORM_INPUT_CHECKBOX }, + { "file", NS_FORM_INPUT_FILE }, + { "hidden", NS_FORM_INPUT_HIDDEN }, + { "reset", NS_FORM_INPUT_RESET }, + { "image", NS_FORM_INPUT_IMAGE }, + { "password", NS_FORM_INPUT_PASSWORD }, + { "radio", NS_FORM_INPUT_RADIO }, + { "submit", NS_FORM_INPUT_SUBMIT }, + { "text", NS_FORM_INPUT_TEXT }, + { 0 } +}; + +NS_IMETHODIMP +nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, + const nsString& aValue, + nsHTMLValue& aResult) +{ + if (aAttribute == nsHTMLAtoms::type) { + nsGenericHTMLElement::EnumTable *table = kInputTypeTable; + while (nsnull != table->tag) { + if (aValue.EqualsIgnoreCase(table->tag)) { + aResult.SetIntValue(table->value, eHTMLUnit_Enumerated); + mType = table->value; // set the type of this input + return NS_CONTENT_ATTR_HAS_VALUE; + } + table++; + } + } + else if (aAttribute == nsHTMLAtoms::checked) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::width) { + nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, + eHTMLUnit_Pixel); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::height) { + nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, + eHTMLUnit_Pixel); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::maxlength) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::size) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + return NS_CONTENT_ATTR_NOT_THERE; +} + +NS_IMETHODIMP +nsHTMLInputElement::AttributeToString(nsIAtom* aAttribute, + nsHTMLValue& aValue, + nsString& aResult) const +{ + if (aAttribute == nsHTMLAtoms::type) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kInputTypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + return mInner.AttributeToString(aAttribute, aValue, aResult); +} + +static void +MapAttributesInto(nsIHTMLAttributes* aAttributes, + nsIStyleContext* aContext, + nsIPresContext* aPresContext) +{ + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } + + aAttributes->GetAttribute(nsHTMLAtoms::type, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + switch (value.GetIntValue()) { + case NS_FORM_INPUT_CHECKBOX: + case NS_FORM_INPUT_RADIO: + { + float p2t = aPresContext->GetPixelsToTwips(); + nscoord pad = NSIntPixelsToTwips(3, p2t); + + // add left and right padding around the radio button via css + nsStyleSpacing* spacing = (nsStyleSpacing*) aContext->GetMutableStyleData(eStyleStruct_Spacing); + if (eStyleUnit_Null == spacing->mMargin.GetLeftUnit()) { + nsStyleCoord left(pad); + spacing->mMargin.SetLeft(left); + } + if (eStyleUnit_Null == spacing->mMargin.GetRightUnit()) { + nsStyleCoord right(NSIntPixelsToTwips(5, p2t)); + spacing->mMargin.SetRight(right); + } + // add bottom padding if backward mode + // XXX why isn't this working? + nsCompatibility mode; + aPresContext->GetCompatibilityMode(mode); + if (eCompatibility_NavQuirks == mode) { + if (eStyleUnit_Null == spacing->mMargin.GetBottomUnit()) { + nsStyleCoord bottom(pad); + spacing->mMargin.SetBottom(bottom); + } + } + break; + } + case NS_FORM_INPUT_IMAGE: + { + // Apply the image border as well. For form elements the color is + // always forced to blue. + static nscolor blue[4] = { + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255) + }; + nsGenericHTMLElement::MapImageBorderAttributesInto(aAttributes, aContext, aPresContext, blue); + nsGenericHTMLElement::MapImageAttributesInto(aAttributes, aContext, aPresContext); + break; + } + } + } + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); +} + +NS_IMETHODIMP +nsHTMLInputElement::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const +{ + aMapFunc = &MapAttributesInto; + return NS_OK; +} + +// nsIFormControl + +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. +NS_IMETHODIMP +nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm) +{ + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = mType; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLInputElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} diff --git a/mozilla/content/html/content/src/nsHTMLOptionElement.cpp b/mozilla/content/html/content/src/nsHTMLOptionElement.cpp index 5437204034e..0f4a6636f58 100644 --- a/mozilla/content/html/content/src/nsHTMLOptionElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLOptionElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +27,21 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIDOMText.h" static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); class nsHTMLOptionElement : public nsIDOMHTMLOptionElement, public nsIScriptObjectOwner, public nsIDOMEventReceiver, public nsIHTMLContent + //public nsIFormControl { public: nsHTMLOptionElement(nsIAtom* aTag); @@ -82,6 +91,7 @@ public: protected: nsGenericHTMLContainerElement mInner; + nsIForm* mForm; }; nsresult @@ -102,29 +112,56 @@ nsHTMLOptionElement::nsHTMLOptionElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; } nsHTMLOptionElement::~nsHTMLOptionElement() { + if (mForm) { + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLOptionElement) +// ISupports -NS_IMPL_RELEASE(nsHTMLOptionElement) +NS_IMETHODIMP +nsHTMLOptionElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLOptionElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLOptionElementIID)) { - nsIDOMHTMLOptionElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLOptionElement*) this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +// the option has a ref (not ref counted) to the form, but not vice versa. The form can get to the +// options via the select. +NS_IMETHODIMP_(nsrefcnt) +nsHTMLOptionElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else { + return mRefCnt; + } +} + nsresult nsHTMLOptionElement::CloneNode(nsIDOMNode** aReturn) { @@ -139,12 +176,30 @@ nsHTMLOptionElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } +NS_IMETHODIMP +nsHTMLOptionElement::SetForm(nsIDOMHTMLFormElement* aForm) +{ + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + return aForm->QueryInterface(kIFormIID, (void**)&mForm); + } +} + NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, DefaultSelected, defaultselected, eSetAttrNotify_None) -NS_IMPL_STRING_ATTR(nsHTMLOptionElement, Text, text, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLOptionElement, Index, index, eSetAttrNotify_None) NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, Disabled, disabled, eSetAttrNotify_Render) NS_IMPL_STRING_ATTR(nsHTMLOptionElement, Label, label, eSetAttrNotify_Render) @@ -156,7 +211,14 @@ nsHTMLOptionElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::selected) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -165,7 +227,6 @@ nsHTMLOptionElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -174,7 +235,6 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -196,3 +256,29 @@ nsHTMLOptionElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +NS_IMETHODIMP +nsHTMLOptionElement::GetText(nsString& aText) +{ + aText.SetLength(0); + nsIDOMNode* node = nsnull; + nsresult result = mInner.GetFirstChild(&node); + if ((NS_OK == result) && node) { + nsIDOMText* domText = nsnull; + result = node->QueryInterface(kIDOMTextIID, (void**)&domText); + if ((NS_OK == result) && domText) { + result = domText->GetData(aText); + aText.CompressWhitespace(PR_TRUE, PR_TRUE); + NS_RELEASE(domText); + } + NS_RELEASE(node); + } + return result; +} + +NS_IMETHODIMP +nsHTMLOptionElement::SetText(const nsString& aText) +{ + // XXX write me + return NS_OK; +} diff --git a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp index 3bd339914ef..714753a89a4 100644 --- a/mozilla/content/html/content/src/nsHTMLSelectElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLSelectElement.cpp @@ -17,6 +17,10 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIDOMHTMLCollection.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +30,48 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIWidget.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLAttributes.h" +#include "nsIDOMHTMLOptionElement.h" static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); + +class nsHTMLSelectElement; + +// nsOptionList +class nsOptionList : public nsIDOMHTMLCollection, public nsIScriptObjectOwner { +public: + nsOptionList(); + nsOptionList(nsIDOMHTMLCollection* aCollection); + virtual ~nsOptionList(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void *aScriptObject); + NS_IMETHOD ResetScriptObject(); + + // nsIDOMHTMLCollection interface + NS_DECL_IDOMHTMLCOLLECTION + + nsVoidArray& GetElements() { return mElements; } + void Clear(); + +private: + nsVoidArray mElements; + void* mScriptObject; +}; class nsHTMLSelectElement : public nsIDOMHTMLSelectElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLSelectElement(nsIAtom* aTag); @@ -90,10 +129,24 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init(); + protected: + nsGenericHTMLContainerElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; + nsOptionList* mOptions; }; + +// nsHTMLSelectElement + +// construction, destruction + nsresult NS_NewHTMLSelectElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -112,29 +165,66 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mOptions = nsnull; + mForm = nsnull; + mWidget = nsnull; } nsHTMLSelectElement::~nsHTMLSelectElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } + NS_IF_RELEASE(mOptions); } -NS_IMPL_ADDREF(nsHTMLSelectElement) +// ISupports -NS_IMPL_RELEASE(nsHTMLSelectElement) +NS_IMETHODIMP +nsHTMLSelectElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLSelectElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLSelectElementIID)) { - nsIDOMHTMLSelectElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLSelectElement*)this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*)this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLSelectElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLSelectElement + nsresult nsHTMLSelectElement::CloneNode(nsIDOMNode** aReturn) { @@ -147,29 +237,78 @@ nsHTMLSelectElement::CloneNode(nsIDOMNode** aReturn) } NS_IMETHODIMP -nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm) +nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore) { - *aForm = nsnull;/* XXX */ + // XXX write me + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLSelectElement::Remove(PRInt32 aIndex) +{ + // XXX write me return NS_OK; } +NS_IMETHODIMP +nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm) +{ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } + return NS_OK; +} + +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm) { - return NS_OK; + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; } NS_IMETHODIMP nsHTMLSelectElement::GetOptions(nsIDOMHTMLCollection** aValue) { - *aValue = nsnull;/* XXX */ + if (!mOptions) { + Init(); + } + NS_ADDREF(mOptions); + *aValue = mOptions; return NS_OK; } NS_IMETHODIMP nsHTMLSelectElement::SetOptions(nsIDOMHTMLCollection* aValue) { - return NS_OK; + if (mOptions) { + mOptions->Clear(); + NS_RELEASE(mOptions); + } + mOptions = new nsOptionList(aValue); + NS_ADDREF(mOptions); + return NS_OK; } NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Type, type, eSetAttrNotify_Restart) @@ -183,16 +322,24 @@ NS_IMPL_INT_ATTR(nsHTMLSelectElement, Size, size, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex, eSetAttrNotify_Render) NS_IMETHODIMP -nsHTMLSelectElement::Blur() +nsHTMLSelectElement::Blur() // XXX not tested { - // XXX write me + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLSelectElement::Focus() { - // XXX write me + if (nsnull != mWidget) { // XXX not tested + mWidget->SetFocus(); + } return NS_OK; } @@ -201,7 +348,27 @@ nsHTMLSelectElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::multiple) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::size) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -210,7 +377,12 @@ nsHTMLSelectElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -219,7 +391,27 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -241,3 +433,210 @@ nsHTMLSelectElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIFormControl + +NS_IMETHODIMP +nsHTMLSelectElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = NS_FORM_SELECT; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLSelectElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} + +void GetOptionsRecurse(nsIContent* aContent, nsVoidArray& aOptions) +{ + PRInt32 numChildren; + aContent->ChildCount(numChildren); + nsIContent* child = nsnull; + nsIDOMHTMLOptionElement* option = nsnull; + for (int i = 0; i < numChildren; i++) { + aContent->ChildAt(i, child); + if (child) { + nsresult result = child->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + if ((NS_OK == result) && option) { + aOptions.AppendElement(option); // keep the ref count + } else { + GetOptionsRecurse(child, aOptions); + } + NS_RELEASE(child); + } + } +} + +NS_IMETHODIMP +nsHTMLSelectElement::Init() +{ + if (mOptions) { + mOptions->Clear(); + NS_RELEASE(mOptions); + } + mOptions = new nsOptionList(); + NS_ADDREF(mOptions); + GetOptionsRecurse(this, mOptions->GetElements()); + + return NS_OK; +} + +// nsOptionList implementation +// XXX this was modified form nsHTMLFormElement.cpp. We need a base class implementation + +nsOptionList::nsOptionList() +{ + mRefCnt = 0; + mScriptObject = nsnull; +} + +nsOptionList::nsOptionList(nsIDOMHTMLCollection* aCollection) +{ + mRefCnt = 0; + mScriptObject = nsnull; + if (aCollection) { + PRUint32 length = 0; + aCollection->GetLength(&length); + nsIDOMNode* node; + for (PRUint32 elemX = 0; elemX < length; elemX++) { + nsresult result = aCollection->Item(elemX, &node); // this assumes an ADDREF + if ((NS_OK == result) && node) { + nsIDOMHTMLOptionElement* option = nsnull; + result = node->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + if ((NS_OK == result) && option) { + mElements.AppendElement(node); // keep the node ref count + NS_RELEASE(option); + } + } + } + } +} + +nsOptionList::~nsOptionList() +{ + Clear(); +} + + +nsresult nsOptionList::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + static NS_DEFINE_IID(kIDOMHTMLCollectionIID, NS_IDOMHTMLCOLLECTION_IID); + static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); + if (aIID.Equals(kIDOMHTMLCollectionIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIScriptObjectOwnerIID)) { + *aInstancePtr = (void*)(nsIScriptObjectOwner*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(nsOptionList) +NS_IMPL_RELEASE(nsOptionList) + + +nsresult nsOptionList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) +{ + nsresult res = NS_OK; + if (nsnull == mScriptObject) { + res = NS_NewScriptHTMLCollection(aContext, (nsISupports *)(nsIDOMHTMLCollection *)this, nsnull, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; + return res; +} + +NS_IMETHODIMP +nsOptionList::SetScriptObject(void *aScriptObject) +{ + mScriptObject = aScriptObject; + return NS_OK; +} + +nsresult nsOptionList::ResetScriptObject() +{ + mScriptObject = nsnull; + return NS_OK; +} + +// nsIDOMHTMLCollection interface +NS_IMETHODIMP +nsOptionList::GetLength(PRUint32* aLength) +{ + *aLength = mElements.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsOptionList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + *aReturn = (nsIDOMNode*)mElements.ElementAt(aIndex); + NS_ADDREF(*aReturn); + return NS_OK; +} + +NS_IMETHODIMP +nsOptionList::NamedItem(const nsString& aName, nsIDOMNode** aReturn) +{ + PRUint32 count = mElements.Count(); + nsresult result = NS_OK; + + *aReturn = nsnull; + for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) { + nsIDOMHTMLOptionElement *option; + option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i); + if (nsnull != option) { + nsIContent *content; + + result = option->QueryInterface(kIContentIID, (void **)&content); + if (NS_OK == result) { + nsAutoString name; + // XXX Should it be an EqualsIgnoreCase? + if (((content->GetAttribute("NAME", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name))) || + ((content->GetAttribute("ID", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name)))) { + result = option->QueryInterface(kIDOMNodeIID, (void **)aReturn); + } + NS_RELEASE(content); + } + NS_RELEASE(option); + } + } + + return result; +} + +void +nsOptionList::Clear() +{ + PRUint32 numOptions = mElements.Count(); + for (PRUint32 i = 0; i < numOptions; i++) { + nsIDOMHTMLOptionElement* option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i); + NS_RELEASE(option); + } + mElements.Clear(); +} diff --git a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp index 47e0b2052aa..ac59c4a2437 100644 --- a/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/mozilla/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -17,6 +17,9 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIFormControl.h" +#include "nsIForm.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +29,21 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIWidget.h" +#include "nsITextWidget.h" +#include "nsIHTMLAttributes.h" static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); class nsHTMLTextAreaElement : public nsIDOMHTMLTextAreaElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLTextAreaElement(nsIAtom* aTag); @@ -85,8 +96,15 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLContainerElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; }; nsresult @@ -107,29 +125,62 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; + mWidget = nsnull; } nsHTMLTextAreaElement::~nsHTMLTextAreaElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLTextAreaElement) - -NS_IMPL_RELEASE(nsHTMLTextAreaElement) +NS_IMETHODIMP +nsHTMLTextAreaElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLTextAreaElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLTextAreaElementIID)) { - nsIDOMHTMLTextAreaElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLTextAreaElement*) this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLTextAreaElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLTextAreaElement + nsresult nsHTMLTextAreaElement::CloneNode(nsIDOMNode** aReturn) { @@ -144,34 +195,73 @@ nsHTMLTextAreaElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm) { + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLTextAreaElement::Blur() // XXX not tested +{ + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP -nsHTMLTextAreaElement::Blur() +nsHTMLTextAreaElement::Focus() // XXX not tested { - // XXX write me + if (nsnull != mWidget) { + mWidget->SetFocus(); + } return NS_OK; } NS_IMETHODIMP -nsHTMLTextAreaElement::Focus() +nsHTMLTextAreaElement::Select() // XXX not tested { - // XXX write me - return NS_OK; -} - -NS_IMETHODIMP -nsHTMLTextAreaElement::Select() -{ - // XXX write me + if (nsnull != mWidget) { + nsITextWidget *textWidget; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget)) { + textWidget->SelectAll(); + NS_RELEASE(textWidget); + } + } return NS_OK; } @@ -189,7 +279,31 @@ nsHTMLTextAreaElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::cols) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::readonly) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::rows) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -198,7 +312,12 @@ nsHTMLTextAreaElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -207,7 +326,26 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -229,3 +367,29 @@ nsHTMLTextAreaElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIFormControl + +NS_IMETHODIMP +nsHTMLTextAreaElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = NS_FORM_TEXTAREA; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLTextAreaElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} + + diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 48ed10ac6c2..03245295adc 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -36,8 +36,9 @@ #include "nsIDOMText.h" -#include "nsHTMLForms.h" -#include "nsIFormManager.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLOptionElement.h" #include "nsIFormControl.h" #include "nsIImageMap.h" @@ -48,6 +49,7 @@ #include "nsIFrame.h" #include "nsIWebShell.h" +#include "nsIHTMLDocument.h" // XXX Go through a factory for this one #include "nsICSSParser.h" @@ -59,11 +61,16 @@ static NS_DEFINE_IID(kIDOMHTMLTitleElementIID, NS_IDOMHTMLTITLEELEMENT_IID); #define XXX_ART_HACK 1 static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); +static NS_DEFINE_IID(kIHTMLContentIID, NS_IHTMLCONTENT_IID); static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID); static NS_DEFINE_IID(kIHTTPUrlIID, NS_IHTTPURL_IID); static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIHTMLDocumentIID, NS_IHTMLDOCUMENT_IID); //---------------------------------------------------------------------- @@ -174,7 +181,7 @@ public: PRInt32 mInMonolithicContainer; PRBool mDirty; PRBool mLayoutStarted; - nsIFormManager* mCurrentForm; + nsIDOMHTMLFormElement* mCurrentForm; nsIImageMap* mCurrentMap; SinkContext** mContexts; @@ -236,8 +243,6 @@ public: nsresult AddText(const nsString& aText); nsresult FlushText(PRBool* aDidFlush = nsnull); - nsresult AddOptionText(const nsIParserNode& aNode); - void MaybeMarkSinkDirty(); HTMLContentSink* mSink; @@ -260,8 +265,6 @@ public: PRInt32 mTextLength; PRInt32 mTextSize; - nsIHTMLContent* mCurrentSelect; - nsIHTMLContent* mCurrentOption; }; //---------------------------------------------------------------------- @@ -449,13 +452,24 @@ AddAttributes(const nsIParserNode& aNode, return NS_OK; } +void SetForm(nsIHTMLContent* aContent, nsIDOMHTMLFormElement* aForm) +{ + nsIFormControl* formControl = nsnull; + nsresult result = aContent->QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + formControl->SetForm(aForm); + NS_RELEASE(formControl); + } +} + // XXX compare switch statement against nsHTMLTags.h's list static nsresult MakeContentObject(nsHTMLTag aNodeType, nsIAtom* aAtom, - nsIFormManager* aForm, + nsIDOMHTMLFormElement* aForm, nsIWebShell* aWebShell, - nsIHTMLContent** aResult) + nsIHTMLContent** aResult, + const nsString* aContent = nsnull) { nsresult rv = NS_OK; switch (aNodeType) { @@ -512,7 +526,11 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLFontElement(aResult, aAtom); break; case eHTMLTag_form: - rv = NS_NewHTMLFormElement(aResult, aAtom); + // the form was already created + *aResult = nsnull; + if (aForm) { + rv = aForm->QueryInterface(kIHTMLContentIID, (void**)aResult); + } break; case eHTMLTag_frame: rv = NS_NewHTMLFrameElement(aResult, aAtom); @@ -542,6 +560,7 @@ MakeContentObject(nsHTMLTag aNodeType, break; case eHTMLTag_input: rv = NS_NewHTMLInputElement(aResult, aAtom); + SetForm(*aResult, aForm); break; case eHTMLTag_isindex: rv = NS_NewHTMLIsIndexElement(aResult, aAtom); @@ -577,7 +596,7 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLOptGroupElement(aResult, aAtom); break; case eHTMLTag_option: - rv = NS_NewHTMLOption(aResult, aAtom);/* XXX old style */ + rv = NS_NewHTMLOptionElement(aResult, aAtom); break; case eHTMLTag_p: rv = NS_NewHTMLParagraphElement(aResult, aAtom); @@ -595,7 +614,8 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLScriptElement(aResult, aAtom); break; case eHTMLTag_select: - rv = NS_NewHTMLSelect(aResult, aAtom, aForm);/* XXX old style */ + rv = NS_NewHTMLSelectElement(aResult, aAtom); + SetForm(*aResult, aForm); break; case eHTMLTag_spacer: rv = NS_NewHTMLSpacerElement(aResult, aAtom); @@ -617,6 +637,17 @@ MakeContentObject(nsHTMLTag aNodeType, break; case eHTMLTag_textarea: rv = NS_NewHTMLTextAreaElement(aResult, aAtom); + // XXX why is textarea not a container. If it were, this code would not be necessary + // If the text area has some content, set it + if (aContent && (aContent->Length() > 0)) { + nsIDOMHTMLTextAreaElement* taElem; + rv = (*aResult)->QueryInterface(kIDOMHTMLTextAreaElementIID, (void **)&taElem); + if ((NS_OK == rv) && taElem) { + taElem->SetDefaultValue(*aContent); + NS_RELEASE(taElem); + } + } + SetForm(*aResult, aForm); break; case eHTMLTag_title: rv = NS_NewHTMLTitleElement(aResult, aAtom); @@ -634,13 +665,44 @@ MakeContentObject(nsHTMLTag aNodeType, return rv; } +#if 0 +// XXX is this logic needed by nsDOMHTMLOptionElement? +void +GetOptionText(const nsIParserNode& aNode, nsString& aText) +{ + aText.SetLength(0); + switch (aNode.GetTokenType()) { + case eToken_text: + case eToken_whitespace: + case eToken_newline: + aText.Append(aNode.GetText()); + break; + + case eToken_entity: + { + nsAutoString tmp2(""); + PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp2); + if (unicode < 0) { + aText.Append(aNode.GetText()); + } else { + aText.Append(tmp2); + } + } + break; + } + nsAutoString x; + char* y = aText.ToNewCString(); + printf("foo"); +} +#endif + /** * Factory subroutine to create all of the html content objects. */ static nsresult CreateContentObject(const nsIParserNode& aNode, nsHTMLTag aNodeType, - nsIFormManager* aForm, + nsIDOMHTMLFormElement* aForm, nsIWebShell* aWebShell, nsIHTMLContent** aResult) { @@ -660,7 +722,7 @@ CreateContentObject(const nsIParserNode& aNode, // Make the content object nsresult rv; - + // XXX right now this code is here because we need aNode to create // images, textareas and input form elements. As soon as all of the // generic content code is in use, it can be moved up into @@ -720,69 +782,16 @@ CreateContentObject(const nsIParserNode& aNode, rv = NS_NewHTMLImageElement(aResult, atom); #endif /* XXX */ break; - case eHTMLTag_input: - { - nsAutoString val; - if (FindAttribute(aNode, "type", val)) { - if (val.EqualsIgnoreCase("submit")) { - rv = NS_NewHTMLInputSubmit(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("reset")) { - rv = NS_NewHTMLInputReset(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("button")) { - rv = NS_NewHTMLInputButton(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("checkbox")) { - rv = NS_NewHTMLInputCheckbox(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("file")) { - rv = NS_NewHTMLInputFile(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("hidden")) { - rv = NS_NewHTMLInputHidden(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("image")) { - rv = NS_NewHTMLInputImage(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("password")) { - rv = NS_NewHTMLInputPassword(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewHTMLInputRadio(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("text")) { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - else { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - } - else { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - } - break; - case eHTMLTag_textarea: - { - const nsString& content = aNode.GetSkippedContent(); - rv = NS_NewHTMLTextArea(aResult, atom, aForm); - if (NS_OK == rv) { - // If the text area has some content, give it to it now - if (content.Length() > 0) { - nsIFormControl* ctrl; - rv = (*aResult)->QueryInterface(kIFormControlIID, (void **)&ctrl); - if (NS_OK == rv) { - ctrl->SetContent(content); - NS_RELEASE(ctrl); - } - } - } - } - break; default: - rv = MakeContentObject(aNodeType, atom, aForm, aWebShell, aResult); - break; + { + // XXX why is textarea not a container? + nsAutoString content; + if (eHTMLTag_textarea == aNodeType) { + content = aNode.GetSkippedContent(); + } + rv = MakeContentObject(aNodeType, atom, aForm, aWebShell, aResult, &content); + break; + } } NS_RELEASE(atom); @@ -822,8 +831,6 @@ SinkContext::SinkContext(HTMLContentSink* aSink) mText = nsnull; mTextLength = 0; mTextSize = 0; - mCurrentOption = nsnull; - mCurrentSelect = nsnull; } SinkContext::~SinkContext() @@ -837,8 +844,6 @@ SinkContext::~SinkContext() if (nsnull != mText) { delete [] mText; } - NS_IF_RELEASE(mCurrentOption); - NS_IF_RELEASE(mCurrentSelect); } nsresult @@ -923,16 +928,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) case eHTMLTag_a: mSink->ProcessATag(aNode, content); break; - case eHTMLTag_select: - NS_IF_RELEASE(mCurrentSelect); - mCurrentSelect = content; - NS_IF_ADDREF(content); - break; - case eHTMLTag_option: - NS_IF_RELEASE(mCurrentOption); - mCurrentOption = content; - NS_IF_ADDREF(content); - break; case eHTMLTag_table: mSink->mInMonolithicContainer++; break; @@ -964,12 +959,6 @@ SinkContext::CloseContainer(const nsIParserNode& aNode) // Special handling for certain tags switch (nodeType) { - case eHTMLTag_option: - NS_IF_RELEASE(mCurrentOption); - break; - case eHTMLTag_select: - NS_IF_RELEASE(mCurrentSelect); - break; case eHTMLTag_table: mSink->mInMonolithicContainer--; break; @@ -989,12 +978,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode) nsresult rv = NS_OK; - // XXX temporary hack until option layout code can find content - // the proper way. - if (eHTMLTag_option == mStack[mStackPos-1].mType) { - return AddOptionText(aNode); - } - switch (aNode.GetTokenType()) { case eToken_start: { @@ -1181,44 +1164,6 @@ SinkContext::FlushText(PRBool* aDidFlush) return rv; } -nsresult -SinkContext::AddOptionText(const nsIParserNode& aNode) -{ - if ((nsnull != mCurrentSelect) && (nsnull != mCurrentOption)) { - nsIFormControl* control = nsnull; - mCurrentOption->QueryInterface(kIFormControlIID, (void **)&control); - if (nsnull != control) { - // Get current content and append on the new content - nsAutoString currentText; - control->GetContent(currentText); - - switch (aNode.GetTokenType()) { - case eToken_text: - case eToken_whitespace: - case eToken_newline: - currentText.Append(aNode.GetText()); - break; - - case eToken_entity: - { - nsAutoString tmp2(""); - PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp2); - if (unicode < 0) { - currentText.Append(aNode.GetText()); - } else { - currentText.Append(tmp2); - } - } - break; - } - control->SetContent(currentText); - NS_RELEASE(control); - } - } - return NS_OK; -} - -//---------------------------------------------------------------------- nsresult NS_NewHTMLContentSink(nsIHTMLContentSink** aResult, @@ -1610,7 +1555,6 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode) return NS_OK; } -// XXX add code to place form into the content model NS_IMETHODIMP HTMLContentSink::OpenForm(const nsIParserNode& aNode) { @@ -1622,44 +1566,28 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode) // Close out previous form if it's there NS_IF_RELEASE(mCurrentForm); - // Create new form + // set the current form nsAutoString tmp("FORM"); nsIAtom* atom = NS_NewAtom(tmp); - if (nsnull == atom) { - return NS_ERROR_OUT_OF_MEMORY; + nsIHTMLContent* iContent = nsnull; + nsresult rv = NS_NewHTMLFormElement(&iContent, atom); + if ((NS_OK == rv) && iContent) { + iContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm); + NS_RELEASE(iContent); } - nsresult rv = NS_NewHTMLForm(&mCurrentForm, atom); NS_RELEASE(atom); - if (NS_OK == rv) { - // XXX replace with AddAttributes when form's implement nsIHTMLContent - // Add tag attributes to the form; we can't use AddAttributes - // because mCurrentForm is not an nsIHTMLContent (yet). - nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner(); - nsAutoString k, v; - PRInt32 ac = aNode.GetAttributeCount(); - for (PRInt32 i = 0; i < ac; i++) { - // Get upper-cased key - const nsString& key = aNode.GetKeyAt(i); - k.SetLength(0); - k.Append(key); - k.ToUpperCase(); + AddLeaf(aNode); - // Get value and remove mandatory quotes - GetAttributeValueAt(aNode, i, v, sco); - mCurrentForm->SetAttribute(k, v); - } - NS_IF_RELEASE(sco); - - // XXX Temporary code till forms become real content - // Add the form to the document - ((nsHTMLDocument*)mDocument)->AddForm(mCurrentForm); - nsIContent *content; - if (NS_OK == mCurrentForm->QueryInterface(kIContentIID, (void **)&content)) { - content->SetDocument(mDocument); - NS_RELEASE(content); - } - } + // add the form to the document + //nsIHTMLDocument* htmlDoc = nsnull; + //if (mDocument && mCurrentForm) { + // rv = mDocument->QueryInterface(kIHTMLDocumentIID, (void**)&htmlDoc); + // if ((NS_OK == rv) && htmlDoc) { + // htmlDoc->AddForm(mCurrentForm); + // NS_RELEASE(htmlDoc); + // } + //} return NS_OK; } diff --git a/mozilla/content/html/document/src/nsHTMLDocument.cpp b/mozilla/content/html/document/src/nsHTMLDocument.cpp index 64d5d7e1335..ad359d96e12 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/content/html/document/src/nsHTMLDocument.cpp @@ -15,6 +15,7 @@ * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ + #include "nsHTMLDocument.h" #include "nsIParser.h" #include "nsIHTMLContentSink.h" @@ -31,6 +32,7 @@ #include "nsIDOMNode.h" // for Find #include "nsIDOMElement.h" #include "nsIDOMText.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIPostToServer.h" #include "nsIStreamListener.h" #include "nsIURL.h" @@ -88,7 +90,6 @@ nsHTMLDocument::nsHTMLDocument() mEmbeds = nsnull; mLinks = nsnull; mAnchors = nsnull; - mForms = nsnull; mNamedItems = nsnull; mParser = nsnull; nsHTMLAtoms::AddrefAtoms(); @@ -108,27 +109,21 @@ nsHTMLDocument::nsHTMLDocument() mParentStack = (nsIDOMNode**) new PRUint32[32]; mChildStack = (nsIDOMNode**) new PRUint32[32]; mBodyContent = nsnull; + mForms = nsnull; } nsHTMLDocument::~nsHTMLDocument() { - // XXX Temporary code till forms become real content PRInt32 i; - for (i = 0; i < mTempForms.Count(); i++) { - nsIFormManager *form = (nsIFormManager *)mTempForms.ElementAt(i); - if (nsnull != form) { - NS_RELEASE(form); - } - } + DeleteNamedItems(); NS_IF_RELEASE(mImages); NS_IF_RELEASE(mApplets); NS_IF_RELEASE(mEmbeds); NS_IF_RELEASE(mLinks); NS_IF_RELEASE(mAnchors); - NS_IF_RELEASE(mForms); - NS_IF_RELEASE(mAttrStyleSheet); + NS_IF_RELEASE(mAttrStyleSheet); NS_IF_RELEASE(mStyleAttrStyleSheet); NS_IF_RELEASE(mParser); for (i = 0; i < mImageMaps.Count(); i++) { @@ -136,6 +131,10 @@ nsHTMLDocument::~nsHTMLDocument() NS_RELEASE(map); } + if (mForms) { + mForms->Reset(); + NS_RELEASE(mForms); + } // XXX don't bother doing this until the dll is unloaded??? // nsHTMLAtoms::ReleaseAtoms(); @@ -337,41 +336,6 @@ NS_IMETHODIMP nsHTMLDocument::GetImageMap(const nsString& aMapName, return 1;/* XXX NS_NOT_FOUND */ } -// XXX Temporary form methods. Forms will soon become actual content -// elements. For now, the document keeps a list of them. -NS_IMETHODIMP -nsHTMLDocument::AddForm(nsIFormManager *aForm) -{ - NS_PRECONDITION(nsnull != aForm, "null ptr"); - if (nsnull == aForm) { - return NS_ERROR_NULL_POINTER; - } - if (mTempForms.AppendElement(aForm)) { - NS_ADDREF(aForm); - return NS_OK; - } - return NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP_(PRInt32) -nsHTMLDocument::GetFormCount() const -{ - return mTempForms.Count(); -} - -NS_IMETHODIMP -nsHTMLDocument::GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const -{ - *aForm = (nsIFormManager *)mTempForms.ElementAt(aIndex); - - if (nsnull != *aForm) { - NS_ADDREF(*aForm); - return NS_OK; - } - - return 1;/* XXX NS_NOT_FOUND */ -} - NS_IMETHODIMP nsHTMLDocument::GetAttributeStyleSheet(nsIHTMLStyleSheet** aResult) { NS_PRECONDITION(nsnull != aResult, "null ptr"); @@ -596,57 +560,6 @@ nsHTMLDocument::GetLinks(nsIDOMHTMLCollection** aLinks) return NS_OK; } -// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - -// XXX Temporary till form becomes real content - -class nsTempFormContentList : public nsContentList { -public: - nsTempFormContentList(nsHTMLDocument *aDocument); - ~nsTempFormContentList(); -}; - -nsTempFormContentList::nsTempFormContentList(nsHTMLDocument *aDocument) : nsContentList(aDocument) -{ - PRInt32 i, count = aDocument->GetFormCount(); - for (i=0; i < count; i++) { - nsIFormManager *form; - - if (NS_OK == aDocument->GetFormAt(i, &form)) { - nsIContent *content; - if (NS_OK == form->QueryInterface(kIContentIID, (void **)&content)) { - Add(content); - NS_RELEASE(content); - } - NS_RELEASE(form); - } - } -} - -nsTempFormContentList::~nsTempFormContentList() -{ - mDocument = nsnull; -} - -NS_IMETHODIMP -nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms) -{ - if (nsnull == mForms) { - mForms = new nsTempFormContentList(this); - if (nsnull == mForms) { - return NS_ERROR_OUT_OF_MEMORY; - } - NS_ADDREF(mForms); - } - - *aForms = (nsIDOMHTMLCollection *)mForms; - NS_ADDREF(mForms); - - return NS_OK; -} - -// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - PRBool nsHTMLDocument::MatchAnchors(nsIContent *aContent) { @@ -1006,19 +919,6 @@ nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn) mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, PL_CompareValues, nsnull, nsnull); RegisterNamedItems(mRootContent, PR_FALSE); - // XXX Need to do this until forms become real content - PRInt32 i, count = mTempForms.Count(); - for (i = 0; i < count; i++) { - nsIFormManager *form = (nsIFormManager *)mTempForms.ElementAt(i); - if (NS_OK == form->QueryInterface(kIContentIID, (void **)&content)) { - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(name, value)) { - char *nameStr = value.ToNewCString(); - PL_HashTableAdd(mNamedItems, nameStr, content); - } - NS_RELEASE(content); - } - } } char *str = aName.ToNewCString(); @@ -1987,3 +1887,47 @@ NS_IMETHODIMP nsHTMLDocument::FindNext(const nsString &aSearchStr, PRBool aMatch return NS_OK; } +// forms related stuff + +// XXX remove this if GetForms is sufficient +NS_IMETHODIMP +nsHTMLDocument::AddForm(nsIDOMHTMLFormElement *aForm) +{ + NS_PRECONDITION(nsnull != aForm, "null ptr"); + if (nsnull == aForm) { + return NS_ERROR_NULL_POINTER; + } + if (!mForms) { + nsIDOMHTMLCollection* forms = nsnull; + GetForms(&forms); + } + nsIContent* iContent = nsnull; + nsresult result = aForm->QueryInterface(kIContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + if (mForms->Add(iContent)) { + NS_RELEASE(iContent); + return NS_OK; + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms) +{ + if (nsnull == mForms) { + nsAutoString tag("form"); + mForms = new nsContentList(this, tag); + if (nsnull == mForms) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + *aForms = (nsIDOMHTMLCollection *)mForms; + NS_ADDREF(mForms); + + return NS_OK; +} + + + diff --git a/mozilla/content/html/document/src/nsHTMLDocument.h b/mozilla/content/html/document/src/nsHTMLDocument.h index 4ab0da19388..e112876e5ce 100644 --- a/mozilla/content/html/document/src/nsHTMLDocument.h +++ b/mozilla/content/html/document/src/nsHTMLDocument.h @@ -53,17 +53,6 @@ public: NS_IMETHOD GetImageMap(const nsString& aMapName, nsIImageMap** aResult); - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXX Temporary form methods. Forms will soon become actual content - // elements. For now, the document keeps a list of them. - NS_IMETHOD AddForm(nsIFormManager *aForm); - - NS_IMETHOD_(PRInt32) GetFormCount() const; - - NS_IMETHOD GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const; - // XXX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - NS_IMETHOD GetAttributeStyleSheet(nsIHTMLStyleSheet** aStyleSheet); NS_IMETHOD GetDTDMode(nsDTDMode& aMode); @@ -100,6 +89,8 @@ public: // nsIDOMHTMLDocument interface NS_DECL_IDOMHTMLDOCUMENT NS_DECL_IDOMNSHTMLDOCUMENT + // the following is not part of nsIDOMHTMLDOCUMENT but allows the content sink to add forms + NS_IMETHOD AddForm(nsIDOMHTMLFormElement* aForm); // From nsIScriptObjectOwner interface, implemented by nsDocument NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); @@ -163,7 +154,6 @@ protected: nsIHTMLCSSStyleSheet* mStyleAttrStyleSheet; nsDTDMode mDTDMode; nsVoidArray mImageMaps; - nsVoidArray mTempForms; // XXX Temporary nsContentList *mImages; nsContentList *mApplets; diff --git a/mozilla/content/html/document/src/nsIHTMLDocument.h b/mozilla/content/html/document/src/nsIHTMLDocument.h index 6035c3c5c45..eda5e9dfd0f 100644 --- a/mozilla/content/html/document/src/nsIHTMLDocument.h +++ b/mozilla/content/html/document/src/nsIHTMLDocument.h @@ -21,7 +21,8 @@ #include "nsISupports.h" class nsIImageMap; class nsString; -class nsIFormManager; +class nsIDOMHTMLCollection; +class nsIDOMHTMLFormElement; class nsIHTMLStyleSheet; /* b2a848b0-d0a9-11d1-89b1-006008911b81 */ @@ -44,20 +45,13 @@ public: NS_IMETHOD AddImageMap(nsIImageMap* aMap) = 0; NS_IMETHOD GetImageMap(const nsString& aMapName, nsIImageMap** aResult) = 0; - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXX Temporary form methods. Forms will soon become actual content - // elements. For now, the document keeps a list of them. - NS_IMETHOD AddForm(nsIFormManager *aForm) = 0; - - NS_IMETHOD_(PRInt32) GetFormCount() const = 0; - - NS_IMETHOD GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const = 0; - // XXX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX NS_IMETHOD GetAttributeStyleSheet(nsIHTMLStyleSheet** aStyleSheet) = 0; + NS_IMETHOD AddForm(nsIDOMHTMLFormElement* aForm) = 0; + + NS_IMETHOD GetForms(nsIDOMHTMLCollection** aForms) = 0; + /** * Access DTD compatibility mode for this document */ diff --git a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp index fa855959dfd..a5ca59f2a29 100644 --- a/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLStyleSheet.cpp @@ -948,40 +948,40 @@ HTMLStyleSheetImpl::CreateInputFrame(nsIContent* aContent, nsAutoString val; if (NS_OK == aContent->GetAttribute(nsAutoString("type"), val)) { if (val.EqualsIgnoreCase("submit")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("reset")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("button")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("checkbox")) { - rv = NS_NewInputCheckboxFrame(aContent, aParentFrame, aFrame); + rv = NS_NewCheckboxControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("file")) { - rv = NS_NewInputFileFrame(aContent, aParentFrame, aFrame); + rv = NS_NewFileControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("hidden")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("image")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("password")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewInputRadioFrame(aContent, aParentFrame, aFrame); + rv = NS_NewRadioControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("text")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } return rv; @@ -1177,10 +1177,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = CreateInputFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::textarea == aTag) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::select == aTag) { - rv = NS_NewHTMLSelectFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewSelectControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::applet == aTag) { rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); @@ -1195,6 +1195,9 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = NS_NewBodyFrame(aContent, aParentFrame, aNewFrame); processChildren = PR_TRUE; } + else if (nsHTMLAtoms::form == aTag) { + rv = NS_NewFormFrame(aContent, aParentFrame, aNewFrame); + } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aContent, aParentFrame, aNewFrame); } diff --git a/mozilla/layout/base/src/nsPresShell.cpp b/mozilla/layout/base/src/nsPresShell.cpp index ea977eb7f62..dd3cf81164b 100644 --- a/mozilla/layout/base/src/nsPresShell.cpp +++ b/mozilla/layout/base/src/nsPresShell.cpp @@ -347,10 +347,6 @@ PresShell::QueryInterface(const nsIID& aIID, void** aInstancePtr) PresShell::~PresShell() { mRefCnt = 99;/* XXX hack! get around re-entrancy bugs */ - if (nsnull != mDocument) { - mDocument->DeleteShell(this); - NS_RELEASE(mDocument); - } if (nsnull != mRootFrame) { mRootFrame->DeleteFrame(*mPresContext); } @@ -358,6 +354,10 @@ PresShell::~PresShell() //Release mPresContext after mViewManager NS_IF_RELEASE(mPresContext); NS_IF_RELEASE(mStyleSet); + if (nsnull != mDocument) { + mDocument->DeleteShell(this); + NS_RELEASE(mDocument); + } mRefCnt = 0; } diff --git a/mozilla/layout/base/src/nsStyleConsts.h b/mozilla/layout/base/src/nsStyleConsts.h index 9fe220526c4..8a873776af2 100644 --- a/mozilla/layout/base/src/nsStyleConsts.h +++ b/mozilla/layout/base/src/nsStyleConsts.h @@ -153,7 +153,6 @@ #define NS_STYLE_CLIP_RIGHT_AUTO 0x40 #define NS_STYLE_CLIP_BOTTOM_AUTO 0x80 -// XXX Peter, is this ok? // FRAME/FRAMESET/IFRAME specific values including backward compatibility. Boolean values with // the same meaning (e.g. 1 & yes) may need to be distinguished for correct mode processing #define NS_STYLE_FRAME_YES 0 diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp new file mode 100644 index 00000000000..3cf840646b9 --- /dev/null +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsFileControlFrame.h" +#include "nsButtonControlFrame.h" +#include "nsTextControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsHTMLAtoms.h" +#include "nsIFileWidget.h" +#include "nsITextWidget.h" +#include "nsWidgetsCID.h" +#include "nsRepository.h" +#include "nsIView.h" +#include "nsHTMLParts.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsHTMLParts.h" +#include "nsIFormControl.h" + +// XXX make this pixels +#define CONTROL_SPACING 40 + +static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID); +static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); + +nsresult +NS_NewFileControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsFileControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsFileControlFrame::nsFileControlFrame(nsIContent* aContent, nsIFrame* aParentFrame) + : nsHTMLContainerFrame(aContent, aParentFrame) +{ + mTextFrame = nsnull; + mBrowseFrame = nsnull; + mFormFrame = nsnull; +} + +nsFileControlFrame::~nsFileControlFrame() +{ +} + +nsresult +nsFileControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIFormControlFrameIID)) { + *aInstancePtr = (void*) ((nsIFormControlFrame*) this); + return NS_OK; + } + return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +PRBool +nsFileControlFrame::IsSuccessful() +{ + nsAutoString name; + return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name)); +} + +void +nsFileControlFrame::Reset() +{ + if (mTextFrame) { + mTextFrame->Reset(); + } +} + +NS_IMETHODIMP +nsFileControlFrame::GetType(PRInt32* aType) const +{ + *aType = NS_FORM_INPUT_FILE; + return NS_OK; +} + +// XXX this should be removed when nsView exposes it +nsIWidget* +GetWindowTemp(nsIView *aView) +{ + nsIWidget *window = nsnull; + + nsIView *ancestor = aView; + while (nsnull != ancestor) { + ancestor->GetWidget(window); + if (nsnull != window) { + return window; + } + ancestor->GetParent(ancestor); + } + return nsnull; +} + + +// this is in response to the MouseClick from the containing browse button +// XXX still need to get filters from accept attribute +void nsFileControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + nsIView* textView; + mTextFrame->GetView(textView); + if (nsnull == textView) { + return; + } + nsIWidget* widget; + mTextFrame->GetWidget(&widget); + if (!widget) { + return; + } + + nsITextWidget* textWidget; + nsresult result = widget->QueryInterface(kITextWidgetIID, (void**)&textWidget); + if (NS_OK != result) { + NS_RELEASE(widget); + return; + } + + nsIView* parentView; + textView->GetParent(parentView); + nsIWidget* parentWidget = GetWindowTemp(parentView); + + nsIFileWidget *fileWidget; + + nsString title("FileWidget Title mode = save"); + nsRepository::CreateInstance(kCFileWidgetCID, nsnull, kIFileWidgetIID, (void**)&fileWidget); + + nsString titles[] = {"all files"}; + nsString filters[] = {"*.*"}; + fileWidget->SetFilterList(1, titles, filters); + + fileWidget->Create(parentWidget, title, eMode_load, nsnull, nsnull); + result = fileWidget->Show(); + + if (result) { + PRUint32 size; + nsString fileName; + fileWidget->GetFile(fileName); + textWidget->SetText(fileName,size); + } + NS_RELEASE(fileWidget); + NS_RELEASE(parentWidget); + NS_RELEASE(textWidget); + NS_RELEASE(widget); +} + + +void SetType(nsIHTMLContent* aElement, nsString& aValue) +{ + nsIHTMLContent* iContent = nsnull; + nsresult result = aElement->QueryInterface(kIHTMLContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + iContent->SetAttribute("type", aValue, PR_FALSE); + NS_RELEASE(iContent); + } +} + +NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + PRInt32 numChildren = LengthOf(mFirstChild); + + nsIFrame* childFrame; + if (0 == numChildren) { + // XXX This code should move to Init(), someday when the frame construction + // changes are all done and Init() is always getting called... + nsIHTMLContent* text = nsnull; + nsIAtom* tag = NS_NewAtom("text"); + NS_NewHTMLInputElement(&text, tag); + text->SetAttribute("type", "text", PR_FALSE); + NS_NewTextControlFrame(text, this, childFrame); + childFrame->SetStyleContext(&aPresContext, mStyleContext); + mTextFrame = (nsTextControlFrame*)childFrame; + mFirstChild = childFrame; + + nsIHTMLContent* browse = nsnull; + tag = NS_NewAtom("browse"); + NS_NewHTMLInputElement(&browse, tag); + browse->SetAttribute("type", "browse", PR_FALSE); + NS_NewButtonControlFrame(browse, this, childFrame); + ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); + mBrowseFrame = (nsButtonControlFrame*)childFrame; + childFrame->SetStyleContext(&aPresContext, mStyleContext); + + mFirstChild->SetNextSibling(childFrame); + mChildCount = 2; + + NS_RELEASE(text); + NS_RELEASE(browse); + } + + nsSize maxSize = aReflowState.maxSize; + nsReflowMetrics desiredSize = aDesiredSize; + aDesiredSize.width = CONTROL_SPACING; + aDesiredSize.height = 0; + childFrame = mFirstChild; + nsPoint offset(0,0); + while (nsnull != childFrame) { // reflow, place, size the children + nsReflowState reflowState(childFrame, aReflowState, maxSize); + childFrame->WillReflow(aPresContext); + nsresult result = childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); + NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + nsRect rect(offset.x, offset.y, desiredSize.width, desiredSize.height); + childFrame->SetRect(rect); + maxSize.width -= desiredSize.width; + aDesiredSize.width += desiredSize.width; + aDesiredSize.height = desiredSize.height; + childFrame->GetNextSibling(childFrame); + offset.x += desiredSize.width + CONTROL_SPACING; + } + + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + + aStatus = NS_FRAME_COMPLETE; + return NS_OK; +} + +PRIntn +nsFileControlFrame::GetSkipSides() const +{ + return 0; +} + + +NS_IMETHODIMP +nsFileControlFrame::GetName(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::name, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +PRInt32 +nsFileControlFrame::GetMaxNumValues() +{ + return 1; +} + +PRBool +nsFileControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + // use our name and the text widgets value + aNames[0] = name; + nsresult status = PR_FALSE; + nsIWidget* widget; + nsITextWidget* textWidget; + mTextFrame->GetWidget(&widget); + if (widget && (NS_OK == widget->QueryInterface(kITextWidgetIID, (void**)&textWidget))) { + PRUint32 actualSize; + textWidget->GetText(aValues[0], 0, actualSize); + aNumValues = 1; + NS_RELEASE(textWidget); + status = PR_TRUE; + } + NS_IF_RELEASE(widget); + return status; +} + diff --git a/mozilla/layout/html/forms/src/nsInputFrame.h b/mozilla/layout/forms/nsFormControlFrame.h similarity index 77% rename from mozilla/layout/html/forms/src/nsInputFrame.h rename to mozilla/layout/forms/nsFormControlFrame.h index 2d0a3f153b5..739ae4edd12 100644 --- a/mozilla/layout/html/forms/src/nsInputFrame.h +++ b/mozilla/layout/forms/nsFormControlFrame.h @@ -16,9 +16,10 @@ * Reserved. */ -#ifndef nsInputFrame_h___ -#define nsInputFrame_h___ +#ifndef nsFormControlFrame_h___ +#define nsFormControlFrame_h___ +#include "nsIFormControlFrame.h" #include "nsIFormManager.h" #include "nsHTMLContainer.h" #include "nsISupports.h" @@ -29,6 +30,10 @@ class nsIView; class nsIPresContext; class nsStyleCoord; +class nsFormFrame; + +#define CSS_NOTSET -1 +#define ATTR_NOTSET -1 /** * Enumeration of possible mouse states used to detect mouse clicks @@ -67,21 +72,25 @@ struct nsInputDimensionSpec }; /** - * nsInputFrame is the base class for frames of form controls. It + * nsFormControlFrame is the base class for frames of form controls. It * provides a uniform way of creating widgets, resizing, and painting. * @see nsLeafFrame and its base classes for more info */ -class nsInputFrame : public nsLeafFrame { - typedef nsLeafFrame nsInputFrameSuper; +class nsFormControlFrame : public nsLeafFrame, + public nsIFormControlFrame +{ + public: /** * Main constructor * @param aContent the content representing this frame * @param aParentFrame the parent frame */ - nsInputFrame(nsIContent* aContent, nsIFrame* aParentFrame); + nsFormControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); - static nscoord CalculateSize (nsIPresContext* aPresContext, nsInputFrame* aFrame, + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + static nscoord CalculateSize (nsIPresContext* aPresContext, nsFormControlFrame* aFrame, const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, nsSize& aBounds, PRBool& aWidthExplicit, PRBool& aHeightExplicit, nscoord& aRowSize); @@ -94,9 +103,7 @@ public: nsGUIEvent* aEvent, nsEventStatus& aEventStatus); - NS_IMETHOD SetRect(const nsRect& aRect); - - /** + /** * Draw this frame within the context of a presentation context and rendering context * @see nsIFrame::Paint */ @@ -118,12 +125,6 @@ public: // new behavior - nsFormRenderingMode GetMode() const; - /** - * Return true if the underlying form element is a hidden form element - */ - PRBool IsHidden(); - /** * Get the class id of the widget associated with this frame * @return the class id @@ -136,13 +137,21 @@ public: */ virtual const nsIID& GetIID(); + NS_IMETHOD GetType(PRInt32* aType) const; + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetValue(nsString* aName); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + /** * Get the widget associated with this frame * @param aView the view associated with the frame. It is a convience parm. * @param aWidget the address of address of where the widget will be placed. * This method doses an AddRef on the widget. */ - virtual nsresult GetWidget(nsIView* aView, nsIWidget** aWidget); + nsresult GetWidget(nsIView* aView, nsIWidget** aWidget); + nsresult GetWidget(nsIWidget** aWidget); /** * Respond to a enter key being pressed @@ -158,7 +167,10 @@ public: * Perform opertations after the widget associated with this frame has been * created. */ - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView); + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual void Reset(); + virtual PRBool IsSuccessful(); /** * Perform opertations before the widget associated with this frame has been @@ -166,9 +178,9 @@ public: */ virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); - static nscoord GetTextSize(nsIPresContext& aContext, nsInputFrame* aFrame, + static nscoord GetTextSize(nsIPresContext& aContext, nsFormControlFrame* aFrame, const nsString& aString, nsSize& aSize); - static nscoord GetTextSize(nsIPresContext& aContext, nsInputFrame* aFrame, + static nscoord GetTextSize(nsIPresContext& aContext, nsFormControlFrame* aFrame, PRInt32 aNumChars, nsSize& aSize); void GetWidgetSize(nsSize& aSize) const { aSize.width = mWidgetSize.width; @@ -181,22 +193,22 @@ public: virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; virtual nscoord GetVerticalInsidePadding(float aPixToTwip, nscoord aInnerHeight) const; - virtual nscoord GetHorizontalInsidePadding(float aPixToTwip, + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, nscoord aInnerWidth, nscoord aCharWidth) const; + NS_IMETHOD GetSize(PRInt32* aSize) const; + NS_IMETHOD GetMaxLength(PRInt32* aSize); + + virtual void SetClickPoint(nscoord aX, nscoord aY); + nsFormFrame* GetFormFrame() { return mFormFrame; } + virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } protected: - virtual ~nsInputFrame(); + virtual ~nsFormControlFrame(); /** - * Return PR_TRUE if the bounds of this frame have been set - */ - PRBool BoundsAreSet(); - - void SetViewVisiblity(nsIPresContext* aPresContext, PRBool aShow); - - /** * Get the size that this frame would occupy without any constraints * @param aPresContext the presentation context * @param aDesiredSize the size desired by this frame, to be set by this method @@ -211,7 +223,7 @@ protected: nsReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); - const void GetFont(nsIPresContext* aPresContext, nsFont& aFont); + NS_IMETHOD GetFont(nsIPresContext* aPresContext, nsFont& aFont); /** * Get the width and height of this control based on CSS @@ -223,12 +235,20 @@ protected: const nsReflowState& aReflowState, nsSize& aSize); - nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, - nscoord aMaxWidth, const nsStyleCoord& aCoord); + //nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, + // nscoord aMaxWidth, const nsStyleCoord& aCoord); nsMouseState mLastMouseState; - nsSize mWidgetSize; - PRBool mDidInit; + nsIWidget* mWidget; + nsSize mWidgetSize; + PRBool mDidInit; + nsPoint mLastClickPoint; + nsFormFrame* mFormFrame; + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + }; #endif diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp new file mode 100644 index 00000000000..4eb946c6548 --- /dev/null +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsTextControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIFrame.h" +#include "nsISupports.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsITextWidget.h" +#include "nsITextAreaWidget.h" +#include "nsWidgetsCID.h" +#include "nsSize.h" +#include "nsString.h" +#include "nsHTMLAtoms.h" +#include "nsIStyleContext.h" +#include "nsFont.h" +#include "nsDOMEvent.h" +#include "nsIFormControl.h" +#include "nsFormFrame.h" +#include "nsIContent.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLTextAreaElement.h" + +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kTextCID, NS_TEXTFIELD_CID); +static NS_DEFINE_IID(kTextAreaCID, NS_TEXTAREA_CID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); +static NS_DEFINE_IID(kITextAreaWidgetIID, NS_ITEXTAREAWIDGET_IID); +static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); + +nsresult +NS_NewTextControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsTextControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsTextControlFrame::nsTextControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ +} + +nsTextControlFrame::~nsTextControlFrame() +{ +} + +nscoord +nsTextControlFrame::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(4, aPixToTwip); +} + +nscoord +nsTextControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +// for a text area aInnerHeight is the height of one line +nscoord +nsTextControlFrame::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ +#ifdef XP_PC + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return (nscoord)NSToIntRound(float(aInnerHeight) * 0.40f); + } else { + return (nscoord)NSToIntRound(float(aInnerHeight) * 0.25f); + } +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(10, aPixToTwip); // XXX this is probably wrong +#endif +} + +nscoord +nsTextControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ +#ifdef XP_PC + nscoord padding; + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + padding = (nscoord)(40 * aCharWidth / 100); + } else { + padding = (nscoord)(55 * aCharWidth / 100); + } + nscoord min = NSIntPixelsToTwips(3, aPixToTwip); + if (padding > min) { + return padding; + } else { + return min; + } +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(6, aPixToTwip); // XXX this is probably wrong +#endif +} + + +const nsIID& +nsTextControlFrame::GetIID() +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return kITextAreaWidgetIID; + } else { + return kITextWidgetIID; + } +} + +const nsIID& +nsTextControlFrame::GetCID() +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return kTextAreaCID; + } else { + return kTextCID; + } +} + +void +nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) +{ + if (mFormFrame && mFormFrame->CanSubmit(*this)) { + nsEventStatus mStatus = nsEventStatus_eIgnore; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_SUBMIT; + mContent->HandleDOMEvent(aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnSubmit(&aPresContext, this); + } +} + +void +nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + // get the css size and let the frame use or override it + nsSize styleSize; + GetStyleSize(*aPresContext, aReflowState, styleSize); + + nsSize size; + + PRBool widthExplicit, heightExplicit; + PRInt32 ignore; + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { + PRInt32 width; + if (NS_CONTENT_ATTR_HAS_VALUE != GetSize(&width)) { + width = 20; + } + // Nav Quirk!! + width += 1; + nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, + nsnull, width, PR_FALSE, nsnull, 1); + CalculateSize(aPresContext, this, styleSize, textSpec, size, + widthExplicit, heightExplicit, ignore); + } else { + nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, 20, + PR_FALSE, nsHTMLAtoms::rows, 1); + CalculateSize(aPresContext, this, styleSize, areaSpec, size, + widthExplicit, heightExplicit, ignore); + } + + if (NS_FORM_TEXTAREA == type) { + float p2t = aPresContext->GetPixelsToTwips(); + nscoord scrollbarWidth = GetScrollbarWidth(p2t); + + if (!heightExplicit) { + size.height += scrollbarWidth; + } + if (!widthExplicit) { + size.width += scrollbarWidth; + } + } + + + aDesiredLayoutSize.width = size.width; + aDesiredLayoutSize.height = size.height; + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; + aDesiredWidgetSize.width = aDesiredLayoutSize.width; + aDesiredWidgetSize.height = aDesiredLayoutSize.height; +} + +nsWidgetInitData* +nsTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) +{ + PRInt32 type; + GetType(&type); + + nsTextWidgetInitData* data = nsnull; + + if (NS_FORM_INPUT_PASSWORD == type) { + data = new nsTextWidgetInitData(); + data->clipChildren = PR_TRUE; + data->mIsPassword = PR_TRUE; + } + + return data; +} + +NS_IMETHODIMP +nsTextControlFrame::GetText(nsString* aText) +{ + nsresult result = NS_CONTENT_ATTR_NOT_THERE; + PRInt32 type; + GetType(&type); + if (NS_FORM_INPUT_TEXT == type) { + nsIDOMHTMLInputElement* textElem = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); + if ((NS_OK == result) && textElem) { + result = textElem->GetValue(*aText); + NS_RELEASE(textElem); + } + } else { + nsIDOMHTMLTextAreaElement* textArea = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + if ((NS_OK == result) && textArea) { + result = textArea->GetDefaultValue(*aText); + NS_RELEASE(textArea); + } + } + return result; +} + +void +nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + if (!mWidget) { + return; + } + + PRInt32 type; + GetType(&type); + + const nsStyleFont* fontStyle = (const nsStyleFont*)(mStyleContext->GetStyleData(eStyleStruct_Font)); + mWidget->SetFont(fontStyle->mFixedFont); + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + + PRUint32 ignore; + + nsAutoString value; + GetText(&value); + + nsITextAreaWidget* textArea = nsnull; + nsITextWidget* text = nsnull; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + text->SetText(value, ignore); + PRInt32 maxLength; + nsresult result = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != result) { + text->SetMaxTextLength(maxLength); + } + NS_RELEASE(text); + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + textArea->SetText(value, ignore); + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + NS_RELEASE(textArea); + } +} + +PRInt32 +nsTextControlFrame::GetMaxNumValues() +{ + return 1; +} + +PRBool +nsTextControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + if (!mWidget) { + return PR_FALSE; + } + + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_NOT_THERE == result)) { + return PR_FALSE; + } + + PRUint32 size; + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + + aNames[0] = name; + aNumValues = 1; + + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + text->GetText(aValues[0],0,size); // the last parm is not used + NS_RELEASE(text); + return PR_TRUE; + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + textArea->GetText(aValues[0],0,size); // the last parm is not used + NS_RELEASE(textArea); + return PR_TRUE; + } + return PR_FALSE; +} + + +void +nsTextControlFrame::Reset() +{ + if (!mWidget) { + return; + } + + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + + nsAutoString value; + nsresult valStatus = GetText(&value); + + PRUint32 size; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { + text->SetText(value,size); + } else { + text->SetText("",size); + } + NS_RELEASE(text); + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { + textArea->SetText(value,size); + } else { + textArea->SetText("",size); + } + NS_RELEASE(textArea); + } + +} + + diff --git a/mozilla/layout/forms/nsTextControlFrame.h b/mozilla/layout/forms/nsTextControlFrame.h new file mode 100644 index 00000000000..7a792801a05 --- /dev/null +++ b/mozilla/layout/forms/nsTextControlFrame.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsTextControlFrame_h___ +#define nsTextControlFrame_h___ + +#include "nsFormControlFrame.h" +class nsIContent; +class nsIFrame; +class nsIPresContext; + +class nsTextControlFrame : public nsFormControlFrame { +public: + nsTextControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + + NS_IMETHOD GetText(nsString* aValue); + + virtual void EnterPressed(nsIPresContext& aPresContext) ; + + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(); + +protected: + + virtual ~nsTextControlFrame(); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); +}; + +#endif diff --git a/mozilla/layout/generic/nsHTMLParts.h b/mozilla/layout/generic/nsHTMLParts.h index ee1b33d7e8b..72faf33eab4 100644 --- a/mozilla/layout/generic/nsHTMLParts.h +++ b/mozilla/layout/generic/nsHTMLParts.h @@ -295,29 +295,39 @@ nsresult NS_NewWBRFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); +// forms extern nsresult -NS_NewInputButtonFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewFormFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputCheckboxFrame(nsIContent* aContent, nsIFrame* aParentFrame, +NS_NewButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); extern nsresult -NS_NewInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputTextFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewFileControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputRadioFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewTextControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewHTMLSelectFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewRadioControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + +extern nsresult +NS_NewSelectControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + +// bullet +extern nsresult +NS_NewBulletFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult NS_NewBulletFrame(nsIContent* aContent, nsIFrame* aParentFrame, diff --git a/mozilla/layout/html/base/src/nsHTMLParts.h b/mozilla/layout/html/base/src/nsHTMLParts.h index ee1b33d7e8b..72faf33eab4 100644 --- a/mozilla/layout/html/base/src/nsHTMLParts.h +++ b/mozilla/layout/html/base/src/nsHTMLParts.h @@ -295,29 +295,39 @@ nsresult NS_NewWBRFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); +// forms extern nsresult -NS_NewInputButtonFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewFormFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputCheckboxFrame(nsIContent* aContent, nsIFrame* aParentFrame, +NS_NewButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, nsIFrame*& aResult); extern nsresult -NS_NewInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputTextFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewFileControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewInputRadioFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewTextControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult -NS_NewHTMLSelectFrame(nsIContent* aContent, nsIFrame* aParentFrame, - nsIFrame*& aResult); +NS_NewRadioControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + +extern nsresult +NS_NewSelectControlFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); + +// bullet +extern nsresult +NS_NewBulletFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult); extern nsresult NS_NewBulletFrame(nsIContent* aContent, nsIFrame* aParentFrame, diff --git a/mozilla/layout/html/content/Makefile b/mozilla/layout/html/content/Makefile index b0ff7c06fd4..c650dc9b7ab 100644 --- a/mozilla/layout/html/content/Makefile +++ b/mozilla/layout/html/content/Makefile @@ -17,7 +17,7 @@ DEPTH = ../../.. -DIRS = src +DIRS = public src include $(DEPTH)/config/config.mk diff --git a/mozilla/layout/html/content/makefile.win b/mozilla/layout/html/content/makefile.win index 5620ead1bde..d7edb135b7f 100644 --- a/mozilla/layout/html/content/makefile.win +++ b/mozilla/layout/html/content/makefile.win @@ -17,6 +17,6 @@ DEPTH=..\..\.. -DIRS=src +DIRS=src public include <$(DEPTH)\layout\config\rules.mak> diff --git a/mozilla/layout/html/content/public/Makefile b/mozilla/layout/html/content/public/Makefile new file mode 100644 index 00000000000..67177f10c7b --- /dev/null +++ b/mozilla/layout/html/content/public/Makefile @@ -0,0 +1,29 @@ +#!gmake +# +# 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. + +DEPTH=../../../.. + +EXPORTS = \ + nsIFormControl.h \ + nsIForm.h \ + $(NULL) + +MODULE = raptor + +include $(DEPTH)/config/config.mk + +include $(DEPTH)/config/rules.mk diff --git a/mozilla/layout/html/content/public/makefile.win b/mozilla/layout/html/content/public/makefile.win new file mode 100644 index 00000000000..e9d612947ce --- /dev/null +++ b/mozilla/layout/html/content/public/makefile.win @@ -0,0 +1,25 @@ +#!nmake +# +# 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. + +DEPTH=..\..\..\.. + +EXPORTS=nsIFormControl.h nsIForm.h + +MODULE=raptor + +include <$(DEPTH)\layout\config\rules.mak> + diff --git a/mozilla/layout/html/content/public/nsIForm.h b/mozilla/layout/html/content/public/nsIForm.h new file mode 100644 index 00000000000..ad395a1a839 --- /dev/null +++ b/mozilla/layout/html/content/public/nsIForm.h @@ -0,0 +1,75 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#ifndef nsIForm_h___ +#define nsIForm_h___ + +#include "nsISupports.h" +class nsIFormControl; + +#define NS_FORM_METHOD_GET 0 +#define NS_FORM_METHOD_POST 1 +#define NS_FORM_ENCTYPE_URLENCODED 0 +#define NS_FORM_ENCTYPE_MULTIPART 1 + +// IID for the nsIFormManager interface +#define NS_IFORM_IID \ +{ 0xb7e94510, 0x4c19, 0x11d2, \ + { 0x80, 0x3f, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } + +/** + * This interface provides a complete set of methods dealing with elements which + * belong to a form element. When nsIDOMHTMLCollection allows write operations + **/ +class nsIForm : public nsISupports { +public: + + /** + * Add an element to end of this form's list of elements + * @param aElement the element to add + * @return NS_OK if the element was successfully added + */ + NS_IMETHOD AddElement(nsIFormControl* aElement) = 0; + + /** + * Get the element at a specified index position + * @param aIndex the index + * @param aElement the element at that index + * @return NS_OK if there was an element at that position, -1 otherwise + */ + NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const = 0; + + /** + * Get the number of elements in this form + * @param aCount the number of elements + * @return NS_OK if there was an element at that position, -1 otherwise + */ + NS_IMETHOD GetElementCount(PRUint32* aCount) const = 0; + + /** + * Remove an element from this form's list of elements + * @param aElement the element to remove + * @param aChildIsRef if PR_TRUE, the elements ref count will be decremented + * otherwise not. This is to facilitate circular references. + * @return NS_OK if the element was successfully removed. + */ + NS_IMETHOD RemoveElement(nsIFormControl* aElement, + PRBool aChildIsRef = PR_TRUE) = 0; + +}; + +#endif /* nsIForm_h___ */ diff --git a/mozilla/layout/html/content/public/nsIFormControl.h b/mozilla/layout/html/content/public/nsIFormControl.h new file mode 100644 index 00000000000..7249c803174 --- /dev/null +++ b/mozilla/layout/html/content/public/nsIFormControl.h @@ -0,0 +1,85 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#ifndef nsIFormControl_h___ +#define nsIFormControl_h___ + +#include "nsISupports.h" +class nsIDOMHTMLFormElement; +class nsIWidget; + +#define NS_FORM_BROWSE 0 +#define NS_FORM_BUTTON 1 +#define NS_FORM_FIELDSET 2 +#define NS_FORM_INPUT_BUTTON 3 +#define NS_FORM_INPUT_CHECKBOX 4 +#define NS_FORM_INPUT_FILE 5 +#define NS_FORM_INPUT_HIDDEN 6 +#define NS_FORM_INPUT_RESET 7 +#define NS_FORM_INPUT_IMAGE 8 +#define NS_FORM_INPUT_PASSWORD 9 +#define NS_FORM_INPUT_RADIO 10 +#define NS_FORM_INPUT_SUBMIT 11 +#define NS_FORM_INPUT_TEXT 12 +#define NS_FORM_OPTION 13 +#define NS_FORM_OPTGROUP 14 +#define NS_FORM_LEGEND 15 +#define NS_FORM_SELECT 16 +#define NS_FORM_TEXTAREA 17 + +#define NS_FORM_NOTOK 0xFFFFFFF7 +#define NS_FORM_NOTSET 0xFFFFFFF7 + +#define NS_IFORMCONTROL_IID \ +{ 0x282ff440, 0xcd7e, 0x11d1, \ + {0x89, 0xad, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} } + + +/** + * Interface which all form controls (e.g. buttons, checkboxes, text, + * radio buttons, select, etc) implement in addition to their dom specific interface. + **/ +class nsIFormControl : public nsISupports { +public: + /** + * Get the form for this form control. + * @param aForm the form to get + * @return NS_OK + */ + NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm) = 0; + + /** + * Set the form for this form control. + * @param aForm the form + * @return NS_OK + */ + NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm) = 0; + + /** + * Get the type of this control + * @param aType the type to be returned + * @return NS_OK + */ + NS_IMETHOD GetType(PRInt32* aType) = 0; + + NS_IMETHOD SetWidget(nsIWidget* aWidget) = 0; + + NS_IMETHOD Init() = 0; + +}; + +#endif /* nsIFormControl_h___ */ diff --git a/mozilla/layout/html/content/src/nsGenericHTMLElement.cpp b/mozilla/layout/html/content/src/nsGenericHTMLElement.cpp index 610179a5b4b..e963f2d6307 100644 --- a/mozilla/layout/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/layout/html/content/src/nsGenericHTMLElement.cpp @@ -936,8 +936,8 @@ nsGenericHTMLElement::SetClassName(const nsString& aClassName) nsresult nsGenericHTMLElement::GetDocument(nsIDocument*& aResult) const { - aResult = mDocument; NS_IF_ADDREF(mDocument); + aResult = mDocument; return NS_OK; } @@ -2253,6 +2253,15 @@ static nsGenericHTMLElement::EnumTable kDivAlignTable[] = { { 0 } }; +static nsGenericHTMLElement::EnumTable kFormAlignTable[] = { + { "left", NS_STYLE_TEXT_ALIGN_LEFT }, + { "right", NS_STYLE_TEXT_ALIGN_RIGHT }, + { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM }, + { "top", NS_STYLE_VERTICAL_ALIGN_TOP }, + { "middle", NS_STYLE_VERTICAL_ALIGN_MIDDLE }, + { 0 } +}; + static nsGenericHTMLElement::EnumTable kFrameborderQuirksTable[] = { { "yes", NS_STYLE_FRAME_YES }, { "no", NS_STYLE_FRAME_NO }, @@ -2331,6 +2340,20 @@ nsGenericHTMLElement::AlignValueToString(const nsHTMLValue& aValue, return EnumValueToString(aValue, kAlignTable, aResult); } +PRBool +nsGenericHTMLElement::ParseFormAlignValue(const nsString& aString, + nsHTMLValue& aResult) +{ + return ParseEnumValue(aString, kFormAlignTable, aResult); +} + +PRBool +nsGenericHTMLElement::FormAlignValueToString(const nsHTMLValue& aValue, + nsString& aResult) +{ + return EnumValueToString(aValue, kFormAlignTable, aResult); +} + PRBool nsGenericHTMLElement::TableHAlignValueToString(const nsHTMLValue& aValue, nsString& aResult) diff --git a/mozilla/layout/html/content/src/nsGenericHTMLElement.h b/mozilla/layout/html/content/src/nsGenericHTMLElement.h index 096b13aaeb2..4e206c5f0f5 100644 --- a/mozilla/layout/html/content/src/nsGenericHTMLElement.h +++ b/mozilla/layout/html/content/src/nsGenericHTMLElement.h @@ -230,6 +230,9 @@ public: static PRBool ParseAlignValue(const nsString& aString, nsHTMLValue& aResult); + static PRBool ParseFormAlignValue(const nsString& aString, + nsHTMLValue& aResult); + static PRBool ParseDivAlignValue(const nsString& aString, nsHTMLValue& aResult); @@ -248,6 +251,8 @@ public: static PRBool AlignValueToString(const nsHTMLValue& aValue, nsString& aResult); + static PRBool FormAlignValueToString(const nsHTMLValue& aValue, + nsString& aResult); static PRBool DivAlignValueToString(const nsHTMLValue& aValue, nsString& aResult); diff --git a/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp b/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp index 0fcfa436357..d33736e4a70 100644 --- a/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLButtonElement.cpp @@ -154,6 +154,7 @@ NS_IMPL_STRING_ATTR(nsHTMLButtonElement, AccessKey, accesskey, eSetAttrNotify_No NS_IMPL_BOOL_ATTR(nsHTMLButtonElement, Disabled, disabled, eSetAttrNotify_Render) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Name, name, eSetAttrNotify_Restart) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Type, type, eSetAttrNotify_Restart) +NS_IMPL_INT_ATTR(nsHTMLButtonElement, TabIndex, tabindex, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLButtonElement, Value, value, eSetAttrNotify_Render) NS_IMETHODIMP diff --git a/mozilla/layout/html/content/src/nsHTMLFormElement.cpp b/mozilla/layout/html/content/src/nsHTMLFormElement.cpp index f869db3a2e3..57d7ff955b3 100644 --- a/mozilla/layout/html/content/src/nsHTMLFormElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLFormElement.cpp @@ -16,7 +16,12 @@ * Corporation. Portions created by Netscape are Copyright (C) 1998 * Netscape Communications Corporation. All Rights Reserved. */ +#include "nsIForm.h" +#include "nsIFormControl.h" +#include "nsIFormManager.h" #include "nsIDOMHTMLFormElement.h" +#include "nsIDOMNSHTMLFormElement.h" +#include "nsIDOMHTMLCollection.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +31,25 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIDocument.h" +#include "nsIPresShell.h" +#include "nsIFrame.h" static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormManagerIID, NS_IFORMMANAGER_IID); +static NS_DEFINE_IID(kIDOMNSHTMLFormElementIID, NS_IDOMNSHTMLFORMELEMENT_IID); + +class nsFormControlList; + +// nsHTMLFormElement class nsHTMLFormElement : public nsIDOMHTMLFormElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIForm { public: nsHTMLFormElement(nsIAtom* aTag); @@ -78,10 +95,45 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIForm + NS_IMETHOD AddElement(nsIFormControl* aElement); + NS_IMETHOD GetElementAt(PRInt32 aIndex, nsIFormControl** aElement) const; + NS_IMETHOD GetElementCount(PRUint32* aCount) const; + NS_IMETHOD RemoveElement(nsIFormControl* aElement, PRBool aChildIsRef = PR_TRUE); + protected: + nsFormControlList* mControls; nsGenericHTMLLeafElement mInner; }; +// nsFormControlList +class nsFormControlList : public nsIDOMHTMLCollection, public nsIScriptObjectOwner { +public: + nsFormControlList(); + virtual ~nsFormControlList(); + + void Clear(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void *aScriptObject); + NS_IMETHOD ResetScriptObject(); + + // nsIDOMHTMLCollection interface + NS_DECL_IDOMHTMLCOLLECTION + + // Called to tell us that the form is going away and that we + // should drop our (non ref-counted) reference to it + void ReleaseForm(); + + void *mScriptObject; + nsVoidArray mElements; +}; + +// nsHTMLFormElement implementation + +// construction, destruction nsresult NS_NewHTMLFormElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -100,29 +152,80 @@ nsHTMLFormElement::nsHTMLFormElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mControls = new nsFormControlList(); + NS_ADDREF(mControls); +nsTraceRefcnt::Create((nsIForm*)this, "nsHTMLFormElement", __FILE__, __LINE__); } nsHTMLFormElement::~nsHTMLFormElement() { + // set the controls to have no form + PRUint32 numControls; + GetElementCount(&numControls); + for (PRUint32 i = 0; i < numControls; i++) { + // avoid addref to child + nsIFormControl* control = (nsIFormControl*)mControls->mElements.ElementAt(i); + if (control) { + // it is assummed that passing in nsnull will not release formControl's previous form + control->SetForm(nsnull); + } + } + + NS_RELEASE(mControls); + + // XXX make sure this gets moved into nsFormFrame, but not the 1st one!! + //mChildren.Clear(); + //RemoveRadioGroups(); +nsTraceRefcnt::Destroy((nsIForm*)this, __FILE__, __LINE__); } -NS_IMPL_ADDREF(nsHTMLFormElement) - -NS_IMPL_RELEASE(nsHTMLFormElement) - -nsresult +// nsISupports +NS_IMETHODIMP nsHTMLFormElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) - if (aIID.Equals(kIDOMHTMLFormElementIID)) { - nsIDOMHTMLFormElement* tmp = this; - *aInstancePtr = (void*) tmp; - mRefCnt++; + if (aIID.Equals(kIFormIID)) { + *aInstancePtr = (void*)(nsIForm*)this; + AddRef(); + return NS_OK; + } + else if (aIID.Equals(kIDOMHTMLFormElementIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLFormElement*)this; + AddRef(); + return NS_OK; + } + else if (aIID.Equals(kIDOMNSHTMLFormElementIID)) { + *aInstancePtr = (void*)(nsIDOMNSHTMLFormElement*)this; + AddRef(); return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP +nsHTMLFormElement::AddRef(void) +{ +nsTraceRefcnt::AddRef((nsIForm*)this, mRefCnt+1, __FILE__, __LINE__); + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} + +NS_IMETHODIMP_(nsrefcnt) +nsHTMLFormElement::Release() +{ +nsTraceRefcnt::Release((nsIForm*)this, mRefCnt-1, __FILE__, __LINE__); + --mRefCnt; + PRUint32 numChildren; + GetElementCount(&numChildren); + if ((int)mRefCnt == numChildren) { + mRefCnt = 0; + delete this; + return 0; + } + return mRefCnt; +} + +// nsIDOMHTMLFormElement nsresult nsHTMLFormElement::CloneNode(nsIDOMNode** aReturn) { @@ -135,9 +238,10 @@ nsHTMLFormElement::CloneNode(nsIDOMNode** aReturn) } NS_IMETHODIMP -nsHTMLFormElement::GetElements(nsIDOMHTMLCollection** aResult) +nsHTMLFormElement::GetElements(nsIDOMHTMLCollection** aElements) { - // XXX write me + *aElements = mControls; + NS_ADDREF(mControls); return NS_OK; } @@ -154,26 +258,85 @@ NS_IMPL_STRING_ATTR(nsHTMLFormElement, Method, method, eSetAttrNotify_None) NS_IMPL_STRING_ATTR(nsHTMLFormElement, Target, target, eSetAttrNotify_None) NS_IMETHODIMP -nsHTMLFormElement::Reset() +nsHTMLFormElement::Submit() { - // XXX - return NS_OK; + // XXX Need to do something special with mailto: or news: URLs + nsIDocument* doc = nsnull; + nsresult result = GetDocument(doc); + if ((NS_OK == result) && doc) { + nsIPresShell *shell = doc->GetShellAt(0); + if (nsnull != shell) { + nsIFrame* frame = shell->FindFrameWithContent(this); + if (frame) { + nsIFormManager* formMan = nsnull; + nsresult result = frame->QueryInterface(kIFormManagerIID, (void**)&formMan); + if ((NS_OK == result) && formMan) { + nsIPresContext *context = shell->GetPresContext(); + if (nsnull != context) { + // XXX We're currently passing in null for the frame. + // It works for now, but might not always + // be correct. In the future, we might not need the + // frame to be passed to the link handler. + result = formMan->OnSubmit(context, nsnull); + NS_RELEASE(context); + } + } + } + NS_RELEASE(shell); + } + NS_RELEASE(doc); + } + + return result; } NS_IMETHODIMP -nsHTMLFormElement::Submit() +nsHTMLFormElement::Reset() { - // XXX - return NS_OK; -} + // XXX Need to do something special with mailto: or news: URLs + nsIDocument* doc = nsnull; + nsresult result = GetDocument(doc); + if ((NS_OK == result) && doc) { + nsIPresShell *shell = doc->GetShellAt(0); + if (nsnull != shell) { + nsIFrame* frame = shell->FindFrameWithContent(this); + if (frame) { + nsIFormManager* formMan = nsnull; + nsresult result = frame->QueryInterface(kIFormManagerIID, (void**)&formMan); + if ((NS_OK == result) && formMan) { + result = formMan->OnReset(); + } + } + NS_RELEASE(shell); + } + } + return result; +} +static nsGenericHTMLElement::EnumTable kFormMethodTable[] = { + { "get", NS_FORM_METHOD_GET }, + { "post", NS_FORM_METHOD_POST }, + { 0 } +}; +static nsGenericHTMLElement::EnumTable kFormEnctypeTable[] = { + { "multipart/form-data", NS_FORM_ENCTYPE_MULTIPART }, + { "application/x-www-form-urlencoded", NS_FORM_ENCTYPE_URLENCODED }, + { 0 } +}; NS_IMETHODIMP nsHTMLFormElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::method) { + nsGenericHTMLElement::ParseEnumValue(aValue, kFormMethodTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::enctype) { + nsGenericHTMLElement::ParseEnumValue(aValue, kFormEnctypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -182,7 +345,18 @@ nsHTMLFormElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::method) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kFormMethodTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::enctype) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kFormEnctypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -214,3 +388,166 @@ nsHTMLFormElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIForm + +NS_IMETHODIMP +nsHTMLFormElement::GetElementCount(PRUint32* aCount) const +{ + mControls->GetLength(aCount); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::GetElementAt(PRInt32 aIndex, nsIFormControl** aFormControl) const +{ + *aFormControl = (nsIFormControl*) mControls->mElements.ElementAt(aIndex); + NS_IF_ADDREF(*aFormControl); + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLFormElement::AddElement(nsIFormControl* aChild) +{ + PRBool rv = mControls->mElements.AppendElement(aChild); + if (rv) { + NS_ADDREF(aChild); + } + return rv; +} + +NS_IMETHODIMP +nsHTMLFormElement::RemoveElement(nsIFormControl* aChild, PRBool aChildIsRef) +{ + PRBool rv = mControls->mElements.RemoveElement(aChild); + if (rv && aChildIsRef) { + NS_RELEASE(aChild); + } + return rv; +} + + +// nsFormControlList implementation, this could go away if there were a lightweight collection implementation somewhere + +nsFormControlList::nsFormControlList() +{ + mRefCnt = 0; + mScriptObject = nsnull; +} + +nsFormControlList::~nsFormControlList() +{ +} + +NS_IMETHODIMP +nsFormControlList::SetScriptObject(void *aScriptObject) +{ + mScriptObject = aScriptObject; + return NS_OK; +} + +void +nsFormControlList::Clear() +{ + PRUint32 numElements = mElements.Count(); + for (PRUint32 i = 0; i < numElements; i++) { + nsIFormControl* elem = (nsIFormControl*) mElements.ElementAt(i); + NS_IF_RELEASE(elem); + } +} + +nsresult nsFormControlList::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + static NS_DEFINE_IID(kIDOMHTMLCollectionIID, NS_IDOMHTMLCOLLECTION_IID); + static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); + if (aIID.Equals(kIDOMHTMLCollectionIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIScriptObjectOwnerIID)) { + *aInstancePtr = (void*)(nsIScriptObjectOwner*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(nsFormControlList) +NS_IMPL_RELEASE(nsFormControlList) + + +nsresult nsFormControlList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) +{ + nsresult res = NS_OK; + if (nsnull == mScriptObject) { + res = NS_NewScriptHTMLCollection(aContext, (nsISupports *)(nsIDOMHTMLCollection *)this, nsnull, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; + return res; +} + +nsresult nsFormControlList::ResetScriptObject() +{ + mScriptObject = nsnull; + return NS_OK; +} + +// nsIDOMHTMLCollection interface +NS_IMETHODIMP +nsFormControlList::GetLength(PRUint32* aLength) +{ + *aLength = mElements.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsFormControlList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(aIndex); + if (control) { + return control->QueryInterface(kIDOMNodeIID, (void**)aReturn); // keep the ref + } + *aReturn = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsFormControlList::NamedItem(const nsString& aName, nsIDOMNode** aReturn) +{ + PRUint32 count = mElements.Count(); + nsresult result = NS_OK; + + *aReturn = nsnull; + for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) { + nsIFormControl *control = (nsIFormControl*)mElements.ElementAt(i); + if (nsnull != control) { + nsIContent *content; + + result = control->QueryInterface(kIContentIID, (void **)&content); + if (NS_OK == result) { + nsAutoString name; + // XXX Should it be an EqualsIgnoreCase? + if (((content->GetAttribute("NAME", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name))) || + ((content->GetAttribute("ID", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name)))) { + result = control->QueryInterface(kIDOMNodeIID, (void **)aReturn); + } + NS_RELEASE(content); + } + } + } + + return result; +} + diff --git a/mozilla/layout/html/content/src/nsHTMLInputElement.cpp b/mozilla/layout/html/content/src/nsHTMLInputElement.cpp index 899439f9804..50d68fe74e9 100644 --- a/mozilla/layout/html/content/src/nsHTMLInputElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLInputElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -27,15 +28,24 @@ #include "nsStyleConsts.h" #include "nsIPresContext.h" #include "nsIHTMLAttributes.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIWidget.h" +#include "nsITextWidget.h" // XXX align=left, hspace, vspace, border? other nav4 attrs static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); class nsHTMLInputElement : public nsIDOMHTMLInputElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLInputElement(nsIAtom* aTag); @@ -105,10 +115,21 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD SetForm(nsIDOMHTMLFormElement* aForm); + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLLeafElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; + PRInt32 mType; }; +// construction, destruction + nsresult NS_NewHTMLInputElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -127,29 +148,70 @@ nsHTMLInputElement::nsHTMLInputElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mType = NS_FORM_INPUT_TEXT; // default value + mForm = nsnull; + mWidget = nsnull; +nsTraceRefcnt::Create((nsIFormControl*)this, "nsHTMLFormControlElement", __FILE__, __LINE__); } nsHTMLInputElement::~nsHTMLInputElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } +nsTraceRefcnt::Destroy((nsIFormControl*)this, __FILE__, __LINE__); } -NS_IMPL_ADDREF(nsHTMLInputElement) +// nsISupports -NS_IMPL_RELEASE(nsHTMLInputElement) +NS_IMETHODIMP_(nsrefcnt) +nsHTMLInputElement::AddRef(void) +{ +nsTraceRefcnt::AddRef((nsIFormControl*)this, mRefCnt+1, __FILE__, __LINE__); + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} -nsresult + +NS_IMETHODIMP nsHTMLInputElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLInputElementIID)) { - nsIDOMHTMLInputElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLInputElement*) this; + NS_ADDREF_THIS(); + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; NS_ADDREF_THIS(); return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLInputElement::Release() +{ +nsTraceRefcnt::Release((nsIFormControl*)this, mRefCnt-1, __FILE__, __LINE__); + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLInputElement + nsresult nsHTMLInputElement::CloneNode(nsIDOMNode** aReturn) { @@ -164,7 +226,14 @@ nsHTMLInputElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLInputElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } @@ -195,66 +264,45 @@ nsHTMLInputElement::GetType(nsString& aValue) NS_IMETHODIMP nsHTMLInputElement::Blur() { - // XXX write me + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Focus() { - // XXX write me + if (nsnull != mWidget) { + mWidget->SetFocus(); + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Select() { - // XXX write me + if ((NS_FORM_INPUT_TEXT == mType) && (nsnull != mWidget)) { + nsITextWidget *textWidget; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget)) { + textWidget->SelectAll(); + NS_RELEASE(textWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLInputElement::Click() { - // XXX write me - return NS_OK; + //XXX TBI + return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP -nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, - const nsString& aValue, - nsHTMLValue& aResult) -{ - // XXX align - return NS_CONTENT_ATTR_NOT_THERE; -} - -NS_IMETHODIMP -nsHTMLInputElement::AttributeToString(nsIAtom* aAttribute, - nsHTMLValue& aValue, - nsString& aResult) const -{ - // XXX align - return mInner.AttributeToString(aAttribute, aValue, aResult); -} - -static void -MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - // XXX align - nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsHTMLInputElement::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &MapAttributesInto; - return NS_OK; -} - - NS_IMETHODIMP nsHTMLInputElement::HandleDOMEvent(nsIPresContext& aPresContext, nsEvent* aEvent, @@ -265,3 +313,221 @@ nsHTMLInputElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIHTMLContent + +static nsGenericHTMLElement::EnumTable kInputTypeTable[] = { + { "browse", NS_FORM_BROWSE }, // XXX not valid html, but it is convient + { "button", NS_FORM_INPUT_BUTTON }, + { "checkbox", NS_FORM_INPUT_CHECKBOX }, + { "file", NS_FORM_INPUT_FILE }, + { "hidden", NS_FORM_INPUT_HIDDEN }, + { "reset", NS_FORM_INPUT_RESET }, + { "image", NS_FORM_INPUT_IMAGE }, + { "password", NS_FORM_INPUT_PASSWORD }, + { "radio", NS_FORM_INPUT_RADIO }, + { "submit", NS_FORM_INPUT_SUBMIT }, + { "text", NS_FORM_INPUT_TEXT }, + { 0 } +}; + +NS_IMETHODIMP +nsHTMLInputElement::StringToAttribute(nsIAtom* aAttribute, + const nsString& aValue, + nsHTMLValue& aResult) +{ + if (aAttribute == nsHTMLAtoms::type) { + nsGenericHTMLElement::EnumTable *table = kInputTypeTable; + while (nsnull != table->tag) { + if (aValue.EqualsIgnoreCase(table->tag)) { + aResult.SetIntValue(table->value, eHTMLUnit_Enumerated); + mType = table->value; // set the type of this input + return NS_CONTENT_ATTR_HAS_VALUE; + } + table++; + } + } + else if (aAttribute == nsHTMLAtoms::checked) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::width) { + nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, + eHTMLUnit_Pixel); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::height) { + nsGenericHTMLElement::ParseValueOrPercent(aValue, aResult, + eHTMLUnit_Pixel); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::maxlength) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::size) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + return NS_CONTENT_ATTR_NOT_THERE; +} + +NS_IMETHODIMP +nsHTMLInputElement::AttributeToString(nsIAtom* aAttribute, + nsHTMLValue& aValue, + nsString& aResult) const +{ + if (aAttribute == nsHTMLAtoms::type) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::EnumValueToString(aValue, kInputTypeTable, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + return mInner.AttributeToString(aAttribute, aValue, aResult); +} + +static void +MapAttributesInto(nsIHTMLAttributes* aAttributes, + nsIStyleContext* aContext, + nsIPresContext* aPresContext) +{ + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } + + aAttributes->GetAttribute(nsHTMLAtoms::type, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + switch (value.GetIntValue()) { + case NS_FORM_INPUT_CHECKBOX: + case NS_FORM_INPUT_RADIO: + { + float p2t = aPresContext->GetPixelsToTwips(); + nscoord pad = NSIntPixelsToTwips(3, p2t); + + // add left and right padding around the radio button via css + nsStyleSpacing* spacing = (nsStyleSpacing*) aContext->GetMutableStyleData(eStyleStruct_Spacing); + if (eStyleUnit_Null == spacing->mMargin.GetLeftUnit()) { + nsStyleCoord left(pad); + spacing->mMargin.SetLeft(left); + } + if (eStyleUnit_Null == spacing->mMargin.GetRightUnit()) { + nsStyleCoord right(NSIntPixelsToTwips(5, p2t)); + spacing->mMargin.SetRight(right); + } + // add bottom padding if backward mode + // XXX why isn't this working? + nsCompatibility mode; + aPresContext->GetCompatibilityMode(mode); + if (eCompatibility_NavQuirks == mode) { + if (eStyleUnit_Null == spacing->mMargin.GetBottomUnit()) { + nsStyleCoord bottom(pad); + spacing->mMargin.SetBottom(bottom); + } + } + break; + } + case NS_FORM_INPUT_IMAGE: + { + // Apply the image border as well. For form elements the color is + // always forced to blue. + static nscolor blue[4] = { + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255), + NS_RGB(0, 0, 255) + }; + nsGenericHTMLElement::MapImageBorderAttributesInto(aAttributes, aContext, aPresContext, blue); + nsGenericHTMLElement::MapImageAttributesInto(aAttributes, aContext, aPresContext); + break; + } + } + } + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); +} + +NS_IMETHODIMP +nsHTMLInputElement::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const +{ + aMapFunc = &MapAttributesInto; + return NS_OK; +} + +// nsIFormControl + +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. +NS_IMETHODIMP +nsHTMLInputElement::SetForm(nsIDOMHTMLFormElement* aForm) +{ + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = mType; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLInputElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} diff --git a/mozilla/layout/html/content/src/nsHTMLOptionElement.cpp b/mozilla/layout/html/content/src/nsHTMLOptionElement.cpp index 5437204034e..0f4a6636f58 100644 --- a/mozilla/layout/html/content/src/nsHTMLOptionElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLOptionElement.cpp @@ -17,6 +17,7 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +27,21 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIDOMText.h" static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); class nsHTMLOptionElement : public nsIDOMHTMLOptionElement, public nsIScriptObjectOwner, public nsIDOMEventReceiver, public nsIHTMLContent + //public nsIFormControl { public: nsHTMLOptionElement(nsIAtom* aTag); @@ -82,6 +91,7 @@ public: protected: nsGenericHTMLContainerElement mInner; + nsIForm* mForm; }; nsresult @@ -102,29 +112,56 @@ nsHTMLOptionElement::nsHTMLOptionElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; } nsHTMLOptionElement::~nsHTMLOptionElement() { + if (mForm) { + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLOptionElement) +// ISupports -NS_IMPL_RELEASE(nsHTMLOptionElement) +NS_IMETHODIMP +nsHTMLOptionElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLOptionElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLOptionElementIID)) { - nsIDOMHTMLOptionElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLOptionElement*) this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +// the option has a ref (not ref counted) to the form, but not vice versa. The form can get to the +// options via the select. +NS_IMETHODIMP_(nsrefcnt) +nsHTMLOptionElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else { + return mRefCnt; + } +} + nsresult nsHTMLOptionElement::CloneNode(nsIDOMNode** aReturn) { @@ -139,12 +176,30 @@ nsHTMLOptionElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } +NS_IMETHODIMP +nsHTMLOptionElement::SetForm(nsIDOMHTMLFormElement* aForm) +{ + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + return aForm->QueryInterface(kIFormIID, (void**)&mForm); + } +} + NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, DefaultSelected, defaultselected, eSetAttrNotify_None) -NS_IMPL_STRING_ATTR(nsHTMLOptionElement, Text, text, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLOptionElement, Index, index, eSetAttrNotify_None) NS_IMPL_BOOL_ATTR(nsHTMLOptionElement, Disabled, disabled, eSetAttrNotify_Render) NS_IMPL_STRING_ATTR(nsHTMLOptionElement, Label, label, eSetAttrNotify_Render) @@ -156,7 +211,14 @@ nsHTMLOptionElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::selected) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -165,7 +227,6 @@ nsHTMLOptionElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -174,7 +235,6 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -196,3 +256,29 @@ nsHTMLOptionElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +NS_IMETHODIMP +nsHTMLOptionElement::GetText(nsString& aText) +{ + aText.SetLength(0); + nsIDOMNode* node = nsnull; + nsresult result = mInner.GetFirstChild(&node); + if ((NS_OK == result) && node) { + nsIDOMText* domText = nsnull; + result = node->QueryInterface(kIDOMTextIID, (void**)&domText); + if ((NS_OK == result) && domText) { + result = domText->GetData(aText); + aText.CompressWhitespace(PR_TRUE, PR_TRUE); + NS_RELEASE(domText); + } + NS_RELEASE(node); + } + return result; +} + +NS_IMETHODIMP +nsHTMLOptionElement::SetText(const nsString& aText) +{ + // XXX write me + return NS_OK; +} diff --git a/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp b/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp index 3bd339914ef..714753a89a4 100644 --- a/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLSelectElement.cpp @@ -17,6 +17,10 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIFormControl.h" +#include "nsIForm.h" +#include "nsIDOMHTMLCollection.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +30,48 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIWidget.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLAttributes.h" +#include "nsIDOMHTMLOptionElement.h" static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); + +class nsHTMLSelectElement; + +// nsOptionList +class nsOptionList : public nsIDOMHTMLCollection, public nsIScriptObjectOwner { +public: + nsOptionList(); + nsOptionList(nsIDOMHTMLCollection* aCollection); + virtual ~nsOptionList(); + + NS_DECL_ISUPPORTS + + NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); + NS_IMETHOD SetScriptObject(void *aScriptObject); + NS_IMETHOD ResetScriptObject(); + + // nsIDOMHTMLCollection interface + NS_DECL_IDOMHTMLCOLLECTION + + nsVoidArray& GetElements() { return mElements; } + void Clear(); + +private: + nsVoidArray mElements; + void* mScriptObject; +}; class nsHTMLSelectElement : public nsIDOMHTMLSelectElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLSelectElement(nsIAtom* aTag); @@ -90,10 +129,24 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init(); + protected: + nsGenericHTMLContainerElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; + nsOptionList* mOptions; }; + +// nsHTMLSelectElement + +// construction, destruction + nsresult NS_NewHTMLSelectElement(nsIHTMLContent** aInstancePtrResult, nsIAtom* aTag) { @@ -112,29 +165,66 @@ nsHTMLSelectElement::nsHTMLSelectElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mOptions = nsnull; + mForm = nsnull; + mWidget = nsnull; } nsHTMLSelectElement::~nsHTMLSelectElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } + NS_IF_RELEASE(mOptions); } -NS_IMPL_ADDREF(nsHTMLSelectElement) +// ISupports -NS_IMPL_RELEASE(nsHTMLSelectElement) +NS_IMETHODIMP +nsHTMLSelectElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLSelectElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLSelectElementIID)) { - nsIDOMHTMLSelectElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLSelectElement*)this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*)this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLSelectElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLSelectElement + nsresult nsHTMLSelectElement::CloneNode(nsIDOMNode** aReturn) { @@ -147,29 +237,78 @@ nsHTMLSelectElement::CloneNode(nsIDOMNode** aReturn) } NS_IMETHODIMP -nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm) +nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement, nsIDOMHTMLElement* aBefore) { - *aForm = nsnull;/* XXX */ + // XXX write me + return NS_OK; +} + +NS_IMETHODIMP +nsHTMLSelectElement::Remove(PRInt32 aIndex) +{ + // XXX write me return NS_OK; } +NS_IMETHODIMP +nsHTMLSelectElement::GetForm(nsIDOMHTMLFormElement** aForm) +{ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } + return NS_OK; +} + +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLSelectElement::SetForm(nsIDOMHTMLFormElement* aForm) { - return NS_OK; + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; } NS_IMETHODIMP nsHTMLSelectElement::GetOptions(nsIDOMHTMLCollection** aValue) { - *aValue = nsnull;/* XXX */ + if (!mOptions) { + Init(); + } + NS_ADDREF(mOptions); + *aValue = mOptions; return NS_OK; } NS_IMETHODIMP nsHTMLSelectElement::SetOptions(nsIDOMHTMLCollection* aValue) { - return NS_OK; + if (mOptions) { + mOptions->Clear(); + NS_RELEASE(mOptions); + } + mOptions = new nsOptionList(aValue); + NS_ADDREF(mOptions); + return NS_OK; } NS_IMPL_STRING_ATTR(nsHTMLSelectElement, Type, type, eSetAttrNotify_Restart) @@ -183,16 +322,24 @@ NS_IMPL_INT_ATTR(nsHTMLSelectElement, Size, size, eSetAttrNotify_Render) NS_IMPL_INT_ATTR(nsHTMLSelectElement, TabIndex, tabindex, eSetAttrNotify_Render) NS_IMETHODIMP -nsHTMLSelectElement::Blur() +nsHTMLSelectElement::Blur() // XXX not tested { - // XXX write me + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP nsHTMLSelectElement::Focus() { - // XXX write me + if (nsnull != mWidget) { // XXX not tested + mWidget->SetFocus(); + } return NS_OK; } @@ -201,7 +348,27 @@ nsHTMLSelectElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::multiple) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::size) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -210,7 +377,12 @@ nsHTMLSelectElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -219,7 +391,27 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } + nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -241,3 +433,210 @@ nsHTMLSelectElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIFormControl + +NS_IMETHODIMP +nsHTMLSelectElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = NS_FORM_SELECT; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLSelectElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} + +void GetOptionsRecurse(nsIContent* aContent, nsVoidArray& aOptions) +{ + PRInt32 numChildren; + aContent->ChildCount(numChildren); + nsIContent* child = nsnull; + nsIDOMHTMLOptionElement* option = nsnull; + for (int i = 0; i < numChildren; i++) { + aContent->ChildAt(i, child); + if (child) { + nsresult result = child->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + if ((NS_OK == result) && option) { + aOptions.AppendElement(option); // keep the ref count + } else { + GetOptionsRecurse(child, aOptions); + } + NS_RELEASE(child); + } + } +} + +NS_IMETHODIMP +nsHTMLSelectElement::Init() +{ + if (mOptions) { + mOptions->Clear(); + NS_RELEASE(mOptions); + } + mOptions = new nsOptionList(); + NS_ADDREF(mOptions); + GetOptionsRecurse(this, mOptions->GetElements()); + + return NS_OK; +} + +// nsOptionList implementation +// XXX this was modified form nsHTMLFormElement.cpp. We need a base class implementation + +nsOptionList::nsOptionList() +{ + mRefCnt = 0; + mScriptObject = nsnull; +} + +nsOptionList::nsOptionList(nsIDOMHTMLCollection* aCollection) +{ + mRefCnt = 0; + mScriptObject = nsnull; + if (aCollection) { + PRUint32 length = 0; + aCollection->GetLength(&length); + nsIDOMNode* node; + for (PRUint32 elemX = 0; elemX < length; elemX++) { + nsresult result = aCollection->Item(elemX, &node); // this assumes an ADDREF + if ((NS_OK == result) && node) { + nsIDOMHTMLOptionElement* option = nsnull; + result = node->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + if ((NS_OK == result) && option) { + mElements.AppendElement(node); // keep the node ref count + NS_RELEASE(option); + } + } + } + } +} + +nsOptionList::~nsOptionList() +{ + Clear(); +} + + +nsresult nsOptionList::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + static NS_DEFINE_IID(kIDOMHTMLCollectionIID, NS_IDOMHTMLCOLLECTION_IID); + static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID); + if (aIID.Equals(kIDOMHTMLCollectionIID)) { + *aInstancePtr = (void*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kIScriptObjectOwnerIID)) { + *aInstancePtr = (void*)(nsIScriptObjectOwner*)this; + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)(nsIDOMHTMLCollection*)this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_IMPL_ADDREF(nsOptionList) +NS_IMPL_RELEASE(nsOptionList) + + +nsresult nsOptionList::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) +{ + nsresult res = NS_OK; + if (nsnull == mScriptObject) { + res = NS_NewScriptHTMLCollection(aContext, (nsISupports *)(nsIDOMHTMLCollection *)this, nsnull, (void**)&mScriptObject); + } + *aScriptObject = mScriptObject; + return res; +} + +NS_IMETHODIMP +nsOptionList::SetScriptObject(void *aScriptObject) +{ + mScriptObject = aScriptObject; + return NS_OK; +} + +nsresult nsOptionList::ResetScriptObject() +{ + mScriptObject = nsnull; + return NS_OK; +} + +// nsIDOMHTMLCollection interface +NS_IMETHODIMP +nsOptionList::GetLength(PRUint32* aLength) +{ + *aLength = mElements.Count(); + return NS_OK; +} + +NS_IMETHODIMP +nsOptionList::Item(PRUint32 aIndex, nsIDOMNode** aReturn) +{ + *aReturn = (nsIDOMNode*)mElements.ElementAt(aIndex); + NS_ADDREF(*aReturn); + return NS_OK; +} + +NS_IMETHODIMP +nsOptionList::NamedItem(const nsString& aName, nsIDOMNode** aReturn) +{ + PRUint32 count = mElements.Count(); + nsresult result = NS_OK; + + *aReturn = nsnull; + for (PRUint32 i = 0; i < count && *aReturn == nsnull; i++) { + nsIDOMHTMLOptionElement *option; + option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i); + if (nsnull != option) { + nsIContent *content; + + result = option->QueryInterface(kIContentIID, (void **)&content); + if (NS_OK == result) { + nsAutoString name; + // XXX Should it be an EqualsIgnoreCase? + if (((content->GetAttribute("NAME", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name))) || + ((content->GetAttribute("ID", name) == NS_CONTENT_ATTR_HAS_VALUE) && + (aName.Equals(name)))) { + result = option->QueryInterface(kIDOMNodeIID, (void **)aReturn); + } + NS_RELEASE(content); + } + NS_RELEASE(option); + } + } + + return result; +} + +void +nsOptionList::Clear() +{ + PRUint32 numOptions = mElements.Count(); + for (PRUint32 i = 0; i < numOptions; i++) { + nsIDOMHTMLOptionElement* option = (nsIDOMHTMLOptionElement*)mElements.ElementAt(i); + NS_RELEASE(option); + } + mElements.Clear(); +} diff --git a/mozilla/layout/html/content/src/nsHTMLTextAreaElement.cpp b/mozilla/layout/html/content/src/nsHTMLTextAreaElement.cpp index 47e0b2052aa..ac59c4a2437 100644 --- a/mozilla/layout/html/content/src/nsHTMLTextAreaElement.cpp +++ b/mozilla/layout/html/content/src/nsHTMLTextAreaElement.cpp @@ -17,6 +17,9 @@ * Netscape Communications Corporation. All Rights Reserved. */ #include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIFormControl.h" +#include "nsIForm.h" #include "nsIScriptObjectOwner.h" #include "nsIDOMEventReceiver.h" #include "nsIHTMLContent.h" @@ -26,13 +29,21 @@ #include "nsIStyleContext.h" #include "nsStyleConsts.h" #include "nsIPresContext.h" +#include "nsIWidget.h" +#include "nsITextWidget.h" +#include "nsIHTMLAttributes.h" static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); class nsHTMLTextAreaElement : public nsIDOMHTMLTextAreaElement, - public nsIScriptObjectOwner, - public nsIDOMEventReceiver, - public nsIHTMLContent + public nsIScriptObjectOwner, + public nsIDOMEventReceiver, + public nsIHTMLContent, + public nsIFormControl { public: nsHTMLTextAreaElement(nsIAtom* aTag); @@ -85,8 +96,15 @@ public: // nsIHTMLContent NS_IMPL_IHTMLCONTENT_USING_GENERIC(mInner) + // nsIFormControl + NS_IMETHOD GetType(PRInt32* aType); + NS_IMETHOD SetWidget(nsIWidget* aWidget); + NS_IMETHOD Init() { return NS_OK; } + protected: nsGenericHTMLContainerElement mInner; + nsIWidget* mWidget; // XXX this needs to go away when FindFrameWithContent is efficient + nsIForm* mForm; }; nsresult @@ -107,29 +125,62 @@ nsHTMLTextAreaElement::nsHTMLTextAreaElement(nsIAtom* aTag) { NS_INIT_REFCNT(); mInner.Init(this, aTag); + mForm = nsnull; + mWidget = nsnull; } nsHTMLTextAreaElement::~nsHTMLTextAreaElement() { + NS_IF_RELEASE(mWidget); + if (nsnull != mForm) { + // prevent mForm from decrementing its ref count on us + mForm->RemoveElement(this, PR_FALSE); + NS_RELEASE(mForm); + } } -NS_IMPL_ADDREF(nsHTMLTextAreaElement) - -NS_IMPL_RELEASE(nsHTMLTextAreaElement) +NS_IMETHODIMP +nsHTMLTextAreaElement::AddRef(void) +{ + PRInt32 refCnt = mRefCnt; // debugging + return ++mRefCnt; +} nsresult nsHTMLTextAreaElement::QueryInterface(REFNSIID aIID, void** aInstancePtr) { NS_IMPL_HTML_CONTENT_QUERY_INTERFACE(aIID, aInstancePtr, this) if (aIID.Equals(kIDOMHTMLTextAreaElementIID)) { - nsIDOMHTMLTextAreaElement* tmp = this; - *aInstancePtr = (void*) tmp; + *aInstancePtr = (void*)(nsIDOMHTMLTextAreaElement*) this; + mRefCnt++; + return NS_OK; + } + else if (aIID.Equals(kIFormControlIID)) { + *aInstancePtr = (void*)(nsIFormControl*) this; mRefCnt++; return NS_OK; } return NS_NOINTERFACE; } +NS_IMETHODIMP_(nsrefcnt) +nsHTMLTextAreaElement::Release() +{ + --mRefCnt; + if (mRefCnt <= 0) { + delete this; + return 0; + } else if ((1 == mRefCnt) && mForm) { + mRefCnt = 0; + delete this; + return 0; + } else { + return mRefCnt; + } +} + +// nsIDOMHTMLTextAreaElement + nsresult nsHTMLTextAreaElement::CloneNode(nsIDOMNode** aReturn) { @@ -144,34 +195,73 @@ nsHTMLTextAreaElement::CloneNode(nsIDOMNode** aReturn) NS_IMETHODIMP nsHTMLTextAreaElement::GetForm(nsIDOMHTMLFormElement** aForm) { - *aForm = nsnull;/* XXX */ + *aForm = nsnull; + if (nsnull != mForm) { + nsIDOMHTMLFormElement* formElem = nsnull; + nsresult result = mForm->QueryInterface(kIDOMHTMLFormElementIID, (void**)&formElem); + if (NS_OK == result) { + *aForm = formElem; + } + } return NS_OK; } +// An important assumption is that if aForm is null, the previous mForm will not be released +// This allows nsHTMLFormElement to deal with circular references. NS_IMETHODIMP nsHTMLTextAreaElement::SetForm(nsIDOMHTMLFormElement* aForm) { + nsresult result = NS_OK; + if (nsnull == aForm) { + mForm = nsnull; + return NS_OK; + } else { + NS_IF_RELEASE(mForm); + nsIFormControl* formControl = nsnull; + result = QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + result = aForm->QueryInterface(kIFormIID, (void**)&mForm); // keep the ref + if ((NS_OK == result) && mForm) { + mForm->AddElement(formControl); + } + NS_RELEASE(formControl); + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLTextAreaElement::Blur() // XXX not tested +{ + if (nsnull != mWidget) { + nsIWidget *mParentWidget = mWidget->GetParent(); + if (nsnull != mParentWidget) { + mParentWidget->SetFocus(); + NS_RELEASE(mParentWidget); + } + } return NS_OK; } NS_IMETHODIMP -nsHTMLTextAreaElement::Blur() +nsHTMLTextAreaElement::Focus() // XXX not tested { - // XXX write me + if (nsnull != mWidget) { + mWidget->SetFocus(); + } return NS_OK; } NS_IMETHODIMP -nsHTMLTextAreaElement::Focus() +nsHTMLTextAreaElement::Select() // XXX not tested { - // XXX write me - return NS_OK; -} - -NS_IMETHODIMP -nsHTMLTextAreaElement::Select() -{ - // XXX write me + if (nsnull != mWidget) { + nsITextWidget *textWidget; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget)) { + textWidget->SelectAll(); + NS_RELEASE(textWidget); + } + } return NS_OK; } @@ -189,7 +279,31 @@ nsHTMLTextAreaElement::StringToAttribute(nsIAtom* aAttribute, const nsString& aValue, nsHTMLValue& aResult) { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (nsGenericHTMLElement::ParseFormAlignValue(aValue, aResult)) { + return NS_CONTENT_ATTR_HAS_VALUE; + } + } + else if (aAttribute == nsHTMLAtoms::disabled) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::cols) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::readonly) { + aResult.SetEmptyValue(); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::rows) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } + else if (aAttribute == nsHTMLAtoms::tabindex) { + nsGenericHTMLElement::ParseValue(aValue, 0, aResult, eHTMLUnit_Integer); + return NS_CONTENT_ATTR_HAS_VALUE; + } return NS_CONTENT_ATTR_NOT_THERE; } @@ -198,7 +312,12 @@ nsHTMLTextAreaElement::AttributeToString(nsIAtom* aAttribute, nsHTMLValue& aValue, nsString& aResult) const { - // XXX write me + if (aAttribute == nsHTMLAtoms::align) { + if (eHTMLUnit_Enumerated == aValue.GetUnit()) { + nsGenericHTMLElement::FormAlignValueToString(aValue, aResult); + return NS_CONTENT_ATTR_HAS_VALUE; + } + } return mInner.AttributeToString(aAttribute, aValue, aResult); } @@ -207,7 +326,26 @@ MapAttributesInto(nsIHTMLAttributes* aAttributes, nsIStyleContext* aContext, nsIPresContext* aPresContext) { - // XXX write me + nsHTMLValue value; + + aAttributes->GetAttribute(nsHTMLAtoms::align, value); + if (eHTMLUnit_Enumerated == value.GetUnit()) { + nsStyleDisplay* display = (nsStyleDisplay*) + aContext->GetMutableStyleData(eStyleStruct_Display); + nsStyleText* text = (nsStyleText*) + aContext->GetMutableStyleData(eStyleStruct_Text); + switch (value.GetIntValue()) { + case NS_STYLE_TEXT_ALIGN_LEFT: + display->mFloats = NS_STYLE_FLOAT_LEFT; + break; + case NS_STYLE_TEXT_ALIGN_RIGHT: + display->mFloats = NS_STYLE_FLOAT_RIGHT; + break; + default: + text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); + break; + } + } nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); } @@ -229,3 +367,29 @@ nsHTMLTextAreaElement::HandleDOMEvent(nsIPresContext& aPresContext, return mInner.HandleDOMEvent(aPresContext, aEvent, aDOMEvent, aFlags, aEventStatus); } + +// nsIFormControl + +NS_IMETHODIMP +nsHTMLTextAreaElement::GetType(PRInt32* aType) +{ + if (aType) { + *aType = NS_FORM_TEXTAREA; + return NS_OK; + } else { + return NS_FORM_NOTOK; + } +} + +NS_IMETHODIMP +nsHTMLTextAreaElement::SetWidget(nsIWidget* aWidget) +{ + if (aWidget != mWidget) { + NS_IF_RELEASE(mWidget); + NS_IF_ADDREF(aWidget); + mWidget = aWidget; + } + return NS_OK; +} + + diff --git a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp index 48ed10ac6c2..03245295adc 100644 --- a/mozilla/layout/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/layout/html/document/src/nsHTMLContentSink.cpp @@ -36,8 +36,9 @@ #include "nsIDOMText.h" -#include "nsHTMLForms.h" -#include "nsIFormManager.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIDOMHTMLTextAreaElement.h" +#include "nsIDOMHTMLOptionElement.h" #include "nsIFormControl.h" #include "nsIImageMap.h" @@ -48,6 +49,7 @@ #include "nsIFrame.h" #include "nsIWebShell.h" +#include "nsIHTMLDocument.h" // XXX Go through a factory for this one #include "nsICSSParser.h" @@ -59,11 +61,16 @@ static NS_DEFINE_IID(kIDOMHTMLTitleElementIID, NS_IDOMHTMLTITLEELEMENT_IID); #define XXX_ART_HACK 1 static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); +static NS_DEFINE_IID(kIHTMLContentIID, NS_IHTMLCONTENT_IID); static NS_DEFINE_IID(kIDOMTextIID, NS_IDOMTEXT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kIHTMLContentSinkIID, NS_IHTML_CONTENT_SINK_IID); static NS_DEFINE_IID(kIHTTPUrlIID, NS_IHTTPURL_IID); static NS_DEFINE_IID(kIScrollableViewIID, NS_ISCROLLABLEVIEW_IID); +static NS_DEFINE_IID(kIHTMLDocumentIID, NS_IHTMLDOCUMENT_IID); //---------------------------------------------------------------------- @@ -174,7 +181,7 @@ public: PRInt32 mInMonolithicContainer; PRBool mDirty; PRBool mLayoutStarted; - nsIFormManager* mCurrentForm; + nsIDOMHTMLFormElement* mCurrentForm; nsIImageMap* mCurrentMap; SinkContext** mContexts; @@ -236,8 +243,6 @@ public: nsresult AddText(const nsString& aText); nsresult FlushText(PRBool* aDidFlush = nsnull); - nsresult AddOptionText(const nsIParserNode& aNode); - void MaybeMarkSinkDirty(); HTMLContentSink* mSink; @@ -260,8 +265,6 @@ public: PRInt32 mTextLength; PRInt32 mTextSize; - nsIHTMLContent* mCurrentSelect; - nsIHTMLContent* mCurrentOption; }; //---------------------------------------------------------------------- @@ -449,13 +452,24 @@ AddAttributes(const nsIParserNode& aNode, return NS_OK; } +void SetForm(nsIHTMLContent* aContent, nsIDOMHTMLFormElement* aForm) +{ + nsIFormControl* formControl = nsnull; + nsresult result = aContent->QueryInterface(kIFormControlIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + formControl->SetForm(aForm); + NS_RELEASE(formControl); + } +} + // XXX compare switch statement against nsHTMLTags.h's list static nsresult MakeContentObject(nsHTMLTag aNodeType, nsIAtom* aAtom, - nsIFormManager* aForm, + nsIDOMHTMLFormElement* aForm, nsIWebShell* aWebShell, - nsIHTMLContent** aResult) + nsIHTMLContent** aResult, + const nsString* aContent = nsnull) { nsresult rv = NS_OK; switch (aNodeType) { @@ -512,7 +526,11 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLFontElement(aResult, aAtom); break; case eHTMLTag_form: - rv = NS_NewHTMLFormElement(aResult, aAtom); + // the form was already created + *aResult = nsnull; + if (aForm) { + rv = aForm->QueryInterface(kIHTMLContentIID, (void**)aResult); + } break; case eHTMLTag_frame: rv = NS_NewHTMLFrameElement(aResult, aAtom); @@ -542,6 +560,7 @@ MakeContentObject(nsHTMLTag aNodeType, break; case eHTMLTag_input: rv = NS_NewHTMLInputElement(aResult, aAtom); + SetForm(*aResult, aForm); break; case eHTMLTag_isindex: rv = NS_NewHTMLIsIndexElement(aResult, aAtom); @@ -577,7 +596,7 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLOptGroupElement(aResult, aAtom); break; case eHTMLTag_option: - rv = NS_NewHTMLOption(aResult, aAtom);/* XXX old style */ + rv = NS_NewHTMLOptionElement(aResult, aAtom); break; case eHTMLTag_p: rv = NS_NewHTMLParagraphElement(aResult, aAtom); @@ -595,7 +614,8 @@ MakeContentObject(nsHTMLTag aNodeType, rv = NS_NewHTMLScriptElement(aResult, aAtom); break; case eHTMLTag_select: - rv = NS_NewHTMLSelect(aResult, aAtom, aForm);/* XXX old style */ + rv = NS_NewHTMLSelectElement(aResult, aAtom); + SetForm(*aResult, aForm); break; case eHTMLTag_spacer: rv = NS_NewHTMLSpacerElement(aResult, aAtom); @@ -617,6 +637,17 @@ MakeContentObject(nsHTMLTag aNodeType, break; case eHTMLTag_textarea: rv = NS_NewHTMLTextAreaElement(aResult, aAtom); + // XXX why is textarea not a container. If it were, this code would not be necessary + // If the text area has some content, set it + if (aContent && (aContent->Length() > 0)) { + nsIDOMHTMLTextAreaElement* taElem; + rv = (*aResult)->QueryInterface(kIDOMHTMLTextAreaElementIID, (void **)&taElem); + if ((NS_OK == rv) && taElem) { + taElem->SetDefaultValue(*aContent); + NS_RELEASE(taElem); + } + } + SetForm(*aResult, aForm); break; case eHTMLTag_title: rv = NS_NewHTMLTitleElement(aResult, aAtom); @@ -634,13 +665,44 @@ MakeContentObject(nsHTMLTag aNodeType, return rv; } +#if 0 +// XXX is this logic needed by nsDOMHTMLOptionElement? +void +GetOptionText(const nsIParserNode& aNode, nsString& aText) +{ + aText.SetLength(0); + switch (aNode.GetTokenType()) { + case eToken_text: + case eToken_whitespace: + case eToken_newline: + aText.Append(aNode.GetText()); + break; + + case eToken_entity: + { + nsAutoString tmp2(""); + PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp2); + if (unicode < 0) { + aText.Append(aNode.GetText()); + } else { + aText.Append(tmp2); + } + } + break; + } + nsAutoString x; + char* y = aText.ToNewCString(); + printf("foo"); +} +#endif + /** * Factory subroutine to create all of the html content objects. */ static nsresult CreateContentObject(const nsIParserNode& aNode, nsHTMLTag aNodeType, - nsIFormManager* aForm, + nsIDOMHTMLFormElement* aForm, nsIWebShell* aWebShell, nsIHTMLContent** aResult) { @@ -660,7 +722,7 @@ CreateContentObject(const nsIParserNode& aNode, // Make the content object nsresult rv; - + // XXX right now this code is here because we need aNode to create // images, textareas and input form elements. As soon as all of the // generic content code is in use, it can be moved up into @@ -720,69 +782,16 @@ CreateContentObject(const nsIParserNode& aNode, rv = NS_NewHTMLImageElement(aResult, atom); #endif /* XXX */ break; - case eHTMLTag_input: - { - nsAutoString val; - if (FindAttribute(aNode, "type", val)) { - if (val.EqualsIgnoreCase("submit")) { - rv = NS_NewHTMLInputSubmit(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("reset")) { - rv = NS_NewHTMLInputReset(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("button")) { - rv = NS_NewHTMLInputButton(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("checkbox")) { - rv = NS_NewHTMLInputCheckbox(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("file")) { - rv = NS_NewHTMLInputFile(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("hidden")) { - rv = NS_NewHTMLInputHidden(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("image")) { - rv = NS_NewHTMLInputImage(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("password")) { - rv = NS_NewHTMLInputPassword(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewHTMLInputRadio(aResult, atom, aForm); - } - else if (val.EqualsIgnoreCase("text")) { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - else { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - } - else { - rv = NS_NewHTMLInputText(aResult, atom, aForm); - } - } - break; - case eHTMLTag_textarea: - { - const nsString& content = aNode.GetSkippedContent(); - rv = NS_NewHTMLTextArea(aResult, atom, aForm); - if (NS_OK == rv) { - // If the text area has some content, give it to it now - if (content.Length() > 0) { - nsIFormControl* ctrl; - rv = (*aResult)->QueryInterface(kIFormControlIID, (void **)&ctrl); - if (NS_OK == rv) { - ctrl->SetContent(content); - NS_RELEASE(ctrl); - } - } - } - } - break; default: - rv = MakeContentObject(aNodeType, atom, aForm, aWebShell, aResult); - break; + { + // XXX why is textarea not a container? + nsAutoString content; + if (eHTMLTag_textarea == aNodeType) { + content = aNode.GetSkippedContent(); + } + rv = MakeContentObject(aNodeType, atom, aForm, aWebShell, aResult, &content); + break; + } } NS_RELEASE(atom); @@ -822,8 +831,6 @@ SinkContext::SinkContext(HTMLContentSink* aSink) mText = nsnull; mTextLength = 0; mTextSize = 0; - mCurrentOption = nsnull; - mCurrentSelect = nsnull; } SinkContext::~SinkContext() @@ -837,8 +844,6 @@ SinkContext::~SinkContext() if (nsnull != mText) { delete [] mText; } - NS_IF_RELEASE(mCurrentOption); - NS_IF_RELEASE(mCurrentSelect); } nsresult @@ -923,16 +928,6 @@ SinkContext::OpenContainer(const nsIParserNode& aNode) case eHTMLTag_a: mSink->ProcessATag(aNode, content); break; - case eHTMLTag_select: - NS_IF_RELEASE(mCurrentSelect); - mCurrentSelect = content; - NS_IF_ADDREF(content); - break; - case eHTMLTag_option: - NS_IF_RELEASE(mCurrentOption); - mCurrentOption = content; - NS_IF_ADDREF(content); - break; case eHTMLTag_table: mSink->mInMonolithicContainer++; break; @@ -964,12 +959,6 @@ SinkContext::CloseContainer(const nsIParserNode& aNode) // Special handling for certain tags switch (nodeType) { - case eHTMLTag_option: - NS_IF_RELEASE(mCurrentOption); - break; - case eHTMLTag_select: - NS_IF_RELEASE(mCurrentSelect); - break; case eHTMLTag_table: mSink->mInMonolithicContainer--; break; @@ -989,12 +978,6 @@ SinkContext::AddLeaf(const nsIParserNode& aNode) nsresult rv = NS_OK; - // XXX temporary hack until option layout code can find content - // the proper way. - if (eHTMLTag_option == mStack[mStackPos-1].mType) { - return AddOptionText(aNode); - } - switch (aNode.GetTokenType()) { case eToken_start: { @@ -1181,44 +1164,6 @@ SinkContext::FlushText(PRBool* aDidFlush) return rv; } -nsresult -SinkContext::AddOptionText(const nsIParserNode& aNode) -{ - if ((nsnull != mCurrentSelect) && (nsnull != mCurrentOption)) { - nsIFormControl* control = nsnull; - mCurrentOption->QueryInterface(kIFormControlIID, (void **)&control); - if (nsnull != control) { - // Get current content and append on the new content - nsAutoString currentText; - control->GetContent(currentText); - - switch (aNode.GetTokenType()) { - case eToken_text: - case eToken_whitespace: - case eToken_newline: - currentText.Append(aNode.GetText()); - break; - - case eToken_entity: - { - nsAutoString tmp2(""); - PRInt32 unicode = aNode.TranslateToUnicodeStr(tmp2); - if (unicode < 0) { - currentText.Append(aNode.GetText()); - } else { - currentText.Append(tmp2); - } - } - break; - } - control->SetContent(currentText); - NS_RELEASE(control); - } - } - return NS_OK; -} - -//---------------------------------------------------------------------- nsresult NS_NewHTMLContentSink(nsIHTMLContentSink** aResult, @@ -1610,7 +1555,6 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode) return NS_OK; } -// XXX add code to place form into the content model NS_IMETHODIMP HTMLContentSink::OpenForm(const nsIParserNode& aNode) { @@ -1622,44 +1566,28 @@ HTMLContentSink::OpenForm(const nsIParserNode& aNode) // Close out previous form if it's there NS_IF_RELEASE(mCurrentForm); - // Create new form + // set the current form nsAutoString tmp("FORM"); nsIAtom* atom = NS_NewAtom(tmp); - if (nsnull == atom) { - return NS_ERROR_OUT_OF_MEMORY; + nsIHTMLContent* iContent = nsnull; + nsresult rv = NS_NewHTMLFormElement(&iContent, atom); + if ((NS_OK == rv) && iContent) { + iContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&mCurrentForm); + NS_RELEASE(iContent); } - nsresult rv = NS_NewHTMLForm(&mCurrentForm, atom); NS_RELEASE(atom); - if (NS_OK == rv) { - // XXX replace with AddAttributes when form's implement nsIHTMLContent - // Add tag attributes to the form; we can't use AddAttributes - // because mCurrentForm is not an nsIHTMLContent (yet). - nsIScriptContextOwner* sco = mDocument->GetScriptContextOwner(); - nsAutoString k, v; - PRInt32 ac = aNode.GetAttributeCount(); - for (PRInt32 i = 0; i < ac; i++) { - // Get upper-cased key - const nsString& key = aNode.GetKeyAt(i); - k.SetLength(0); - k.Append(key); - k.ToUpperCase(); + AddLeaf(aNode); - // Get value and remove mandatory quotes - GetAttributeValueAt(aNode, i, v, sco); - mCurrentForm->SetAttribute(k, v); - } - NS_IF_RELEASE(sco); - - // XXX Temporary code till forms become real content - // Add the form to the document - ((nsHTMLDocument*)mDocument)->AddForm(mCurrentForm); - nsIContent *content; - if (NS_OK == mCurrentForm->QueryInterface(kIContentIID, (void **)&content)) { - content->SetDocument(mDocument); - NS_RELEASE(content); - } - } + // add the form to the document + //nsIHTMLDocument* htmlDoc = nsnull; + //if (mDocument && mCurrentForm) { + // rv = mDocument->QueryInterface(kIHTMLDocumentIID, (void**)&htmlDoc); + // if ((NS_OK == rv) && htmlDoc) { + // htmlDoc->AddForm(mCurrentForm); + // NS_RELEASE(htmlDoc); + // } + //} return NS_OK; } diff --git a/mozilla/layout/html/document/src/nsHTMLDocument.cpp b/mozilla/layout/html/document/src/nsHTMLDocument.cpp index 64d5d7e1335..ad359d96e12 100644 --- a/mozilla/layout/html/document/src/nsHTMLDocument.cpp +++ b/mozilla/layout/html/document/src/nsHTMLDocument.cpp @@ -15,6 +15,7 @@ * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ + #include "nsHTMLDocument.h" #include "nsIParser.h" #include "nsIHTMLContentSink.h" @@ -31,6 +32,7 @@ #include "nsIDOMNode.h" // for Find #include "nsIDOMElement.h" #include "nsIDOMText.h" +#include "nsIDOMHTMLFormElement.h" #include "nsIPostToServer.h" #include "nsIStreamListener.h" #include "nsIURL.h" @@ -88,7 +90,6 @@ nsHTMLDocument::nsHTMLDocument() mEmbeds = nsnull; mLinks = nsnull; mAnchors = nsnull; - mForms = nsnull; mNamedItems = nsnull; mParser = nsnull; nsHTMLAtoms::AddrefAtoms(); @@ -108,27 +109,21 @@ nsHTMLDocument::nsHTMLDocument() mParentStack = (nsIDOMNode**) new PRUint32[32]; mChildStack = (nsIDOMNode**) new PRUint32[32]; mBodyContent = nsnull; + mForms = nsnull; } nsHTMLDocument::~nsHTMLDocument() { - // XXX Temporary code till forms become real content PRInt32 i; - for (i = 0; i < mTempForms.Count(); i++) { - nsIFormManager *form = (nsIFormManager *)mTempForms.ElementAt(i); - if (nsnull != form) { - NS_RELEASE(form); - } - } + DeleteNamedItems(); NS_IF_RELEASE(mImages); NS_IF_RELEASE(mApplets); NS_IF_RELEASE(mEmbeds); NS_IF_RELEASE(mLinks); NS_IF_RELEASE(mAnchors); - NS_IF_RELEASE(mForms); - NS_IF_RELEASE(mAttrStyleSheet); + NS_IF_RELEASE(mAttrStyleSheet); NS_IF_RELEASE(mStyleAttrStyleSheet); NS_IF_RELEASE(mParser); for (i = 0; i < mImageMaps.Count(); i++) { @@ -136,6 +131,10 @@ nsHTMLDocument::~nsHTMLDocument() NS_RELEASE(map); } + if (mForms) { + mForms->Reset(); + NS_RELEASE(mForms); + } // XXX don't bother doing this until the dll is unloaded??? // nsHTMLAtoms::ReleaseAtoms(); @@ -337,41 +336,6 @@ NS_IMETHODIMP nsHTMLDocument::GetImageMap(const nsString& aMapName, return 1;/* XXX NS_NOT_FOUND */ } -// XXX Temporary form methods. Forms will soon become actual content -// elements. For now, the document keeps a list of them. -NS_IMETHODIMP -nsHTMLDocument::AddForm(nsIFormManager *aForm) -{ - NS_PRECONDITION(nsnull != aForm, "null ptr"); - if (nsnull == aForm) { - return NS_ERROR_NULL_POINTER; - } - if (mTempForms.AppendElement(aForm)) { - NS_ADDREF(aForm); - return NS_OK; - } - return NS_ERROR_OUT_OF_MEMORY; -} - -NS_IMETHODIMP_(PRInt32) -nsHTMLDocument::GetFormCount() const -{ - return mTempForms.Count(); -} - -NS_IMETHODIMP -nsHTMLDocument::GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const -{ - *aForm = (nsIFormManager *)mTempForms.ElementAt(aIndex); - - if (nsnull != *aForm) { - NS_ADDREF(*aForm); - return NS_OK; - } - - return 1;/* XXX NS_NOT_FOUND */ -} - NS_IMETHODIMP nsHTMLDocument::GetAttributeStyleSheet(nsIHTMLStyleSheet** aResult) { NS_PRECONDITION(nsnull != aResult, "null ptr"); @@ -596,57 +560,6 @@ nsHTMLDocument::GetLinks(nsIDOMHTMLCollection** aLinks) return NS_OK; } -// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - -// XXX Temporary till form becomes real content - -class nsTempFormContentList : public nsContentList { -public: - nsTempFormContentList(nsHTMLDocument *aDocument); - ~nsTempFormContentList(); -}; - -nsTempFormContentList::nsTempFormContentList(nsHTMLDocument *aDocument) : nsContentList(aDocument) -{ - PRInt32 i, count = aDocument->GetFormCount(); - for (i=0; i < count; i++) { - nsIFormManager *form; - - if (NS_OK == aDocument->GetFormAt(i, &form)) { - nsIContent *content; - if (NS_OK == form->QueryInterface(kIContentIID, (void **)&content)) { - Add(content); - NS_RELEASE(content); - } - NS_RELEASE(form); - } - } -} - -nsTempFormContentList::~nsTempFormContentList() -{ - mDocument = nsnull; -} - -NS_IMETHODIMP -nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms) -{ - if (nsnull == mForms) { - mForms = new nsTempFormContentList(this); - if (nsnull == mForms) { - return NS_ERROR_OUT_OF_MEMORY; - } - NS_ADDREF(mForms); - } - - *aForms = (nsIDOMHTMLCollection *)mForms; - NS_ADDREF(mForms); - - return NS_OK; -} - -// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - PRBool nsHTMLDocument::MatchAnchors(nsIContent *aContent) { @@ -1006,19 +919,6 @@ nsHTMLDocument::NamedItem(const nsString& aName, nsIDOMElement** aReturn) mNamedItems = PL_NewHashTable(10, PL_HashString, PL_CompareStrings, PL_CompareValues, nsnull, nsnull); RegisterNamedItems(mRootContent, PR_FALSE); - // XXX Need to do this until forms become real content - PRInt32 i, count = mTempForms.Count(); - for (i = 0; i < count; i++) { - nsIFormManager *form = (nsIFormManager *)mTempForms.ElementAt(i); - if (NS_OK == form->QueryInterface(kIContentIID, (void **)&content)) { - nsAutoString value; - if (NS_CONTENT_ATTR_HAS_VALUE == content->GetAttribute(name, value)) { - char *nameStr = value.ToNewCString(); - PL_HashTableAdd(mNamedItems, nameStr, content); - } - NS_RELEASE(content); - } - } } char *str = aName.ToNewCString(); @@ -1987,3 +1887,47 @@ NS_IMETHODIMP nsHTMLDocument::FindNext(const nsString &aSearchStr, PRBool aMatch return NS_OK; } +// forms related stuff + +// XXX remove this if GetForms is sufficient +NS_IMETHODIMP +nsHTMLDocument::AddForm(nsIDOMHTMLFormElement *aForm) +{ + NS_PRECONDITION(nsnull != aForm, "null ptr"); + if (nsnull == aForm) { + return NS_ERROR_NULL_POINTER; + } + if (!mForms) { + nsIDOMHTMLCollection* forms = nsnull; + GetForms(&forms); + } + nsIContent* iContent = nsnull; + nsresult result = aForm->QueryInterface(kIContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + if (mForms->Add(iContent)) { + NS_RELEASE(iContent); + return NS_OK; + } + } + return result; +} + +NS_IMETHODIMP +nsHTMLDocument::GetForms(nsIDOMHTMLCollection** aForms) +{ + if (nsnull == mForms) { + nsAutoString tag("form"); + mForms = new nsContentList(this, tag); + if (nsnull == mForms) { + return NS_ERROR_OUT_OF_MEMORY; + } + } + + *aForms = (nsIDOMHTMLCollection *)mForms; + NS_ADDREF(mForms); + + return NS_OK; +} + + + diff --git a/mozilla/layout/html/document/src/nsHTMLDocument.h b/mozilla/layout/html/document/src/nsHTMLDocument.h index 4ab0da19388..e112876e5ce 100644 --- a/mozilla/layout/html/document/src/nsHTMLDocument.h +++ b/mozilla/layout/html/document/src/nsHTMLDocument.h @@ -53,17 +53,6 @@ public: NS_IMETHOD GetImageMap(const nsString& aMapName, nsIImageMap** aResult); - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXX Temporary form methods. Forms will soon become actual content - // elements. For now, the document keeps a list of them. - NS_IMETHOD AddForm(nsIFormManager *aForm); - - NS_IMETHOD_(PRInt32) GetFormCount() const; - - NS_IMETHOD GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const; - // XXX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - NS_IMETHOD GetAttributeStyleSheet(nsIHTMLStyleSheet** aStyleSheet); NS_IMETHOD GetDTDMode(nsDTDMode& aMode); @@ -100,6 +89,8 @@ public: // nsIDOMHTMLDocument interface NS_DECL_IDOMHTMLDOCUMENT NS_DECL_IDOMNSHTMLDOCUMENT + // the following is not part of nsIDOMHTMLDOCUMENT but allows the content sink to add forms + NS_IMETHOD AddForm(nsIDOMHTMLFormElement* aForm); // From nsIScriptObjectOwner interface, implemented by nsDocument NS_IMETHOD GetScriptObject(nsIScriptContext *aContext, void** aScriptObject); @@ -163,7 +154,6 @@ protected: nsIHTMLCSSStyleSheet* mStyleAttrStyleSheet; nsDTDMode mDTDMode; nsVoidArray mImageMaps; - nsVoidArray mTempForms; // XXX Temporary nsContentList *mImages; nsContentList *mApplets; diff --git a/mozilla/layout/html/document/src/nsIHTMLDocument.h b/mozilla/layout/html/document/src/nsIHTMLDocument.h index 6035c3c5c45..eda5e9dfd0f 100644 --- a/mozilla/layout/html/document/src/nsIHTMLDocument.h +++ b/mozilla/layout/html/document/src/nsIHTMLDocument.h @@ -21,7 +21,8 @@ #include "nsISupports.h" class nsIImageMap; class nsString; -class nsIFormManager; +class nsIDOMHTMLCollection; +class nsIDOMHTMLFormElement; class nsIHTMLStyleSheet; /* b2a848b0-d0a9-11d1-89b1-006008911b81 */ @@ -44,20 +45,13 @@ public: NS_IMETHOD AddImageMap(nsIImageMap* aMap) = 0; NS_IMETHOD GetImageMap(const nsString& aMapName, nsIImageMap** aResult) = 0; - - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - // XXX Temporary form methods. Forms will soon become actual content - // elements. For now, the document keeps a list of them. - NS_IMETHOD AddForm(nsIFormManager *aForm) = 0; - - NS_IMETHOD_(PRInt32) GetFormCount() const = 0; - - NS_IMETHOD GetFormAt(PRInt32 aIndex, nsIFormManager **aForm) const = 0; - // XXX - // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX NS_IMETHOD GetAttributeStyleSheet(nsIHTMLStyleSheet** aStyleSheet) = 0; + NS_IMETHOD AddForm(nsIDOMHTMLFormElement* aForm) = 0; + + NS_IMETHOD GetForms(nsIDOMHTMLCollection** aForms) = 0; + /** * Access DTD compatibility mode for this document */ diff --git a/mozilla/layout/html/forms/public/Makefile b/mozilla/layout/html/forms/public/Makefile index 07635497a87..02964dbc69b 100644 --- a/mozilla/layout/html/forms/public/Makefile +++ b/mozilla/layout/html/forms/public/Makefile @@ -18,7 +18,6 @@ DEPTH=../../../.. EXPORTS = \ - nsIFormControl.h \ nsIFormManager.h \ $(NULL) diff --git a/mozilla/layout/html/forms/public/makefile.win b/mozilla/layout/html/forms/public/makefile.win index bbb2ca9c645..47537ada07a 100644 --- a/mozilla/layout/html/forms/public/makefile.win +++ b/mozilla/layout/html/forms/public/makefile.win @@ -17,7 +17,7 @@ DEPTH=..\..\..\.. -EXPORTS=nsIFormControl.h nsIFormManager.h +EXPORTS=nsIFormManager.h MODULE=raptor diff --git a/mozilla/layout/html/forms/public/nsIFormControl.h b/mozilla/layout/html/forms/public/nsIFormControl.h deleted file mode 100644 index 371fbd209cf..00000000000 --- a/mozilla/layout/html/forms/public/nsIFormControl.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ -#ifndef nsIFormControl_h___ -#define nsIFormControl_h___ - -#include "nsISupports.h" -class nsIFormManager; - -#define NS_IFORMCONTROL_IID \ -{ 0x282ff440, 0xcd7e, 0x11d1, \ - {0x89, 0xad, 0x00, 0x60, 0x08, 0x91, 0x1b, 0x81} } - -// XXX XPCOM'ize me - -/** - * Interface which all form controls (e.g. buttons, checkboxes, text, - * radio buttons, select, etc) implement. - **/ -class nsIFormControl : public nsISupports { -public: - - virtual void GetType(nsString& aType) const = 0; - virtual PRBool GetChecked(PRBool aGetInitialValue) const = 0; - virtual void SetChecked(PRBool aState, PRBool aSetInitialValue) = 0; - - virtual PRBool GetCanSubmit() const = 0; - /** - * Get the form manager which manages this control. - * @return the form manager - */ - virtual nsIFormManager* GetFormManager() const = 0; - - /** - * Get the max number of values that this control can have; the actual - * number of values may be less. - * @return the max number of values - */ - virtual PRInt32 GetMaxNumValues() = 0; - - /** - * Get the content of this control if applicable - * @param aResult the nsString which will be set to the name (out parm) - * @return PR_TRUE if there was content, PR_FALSE otherwise - */ - virtual PRBool GetContent(nsString& aResult) const = 0; - - /** - * Get the name of this control. Controls without names will not have any - * data submitted. - * @param aResult the nsString which will be set to the name (out parm). - * If the result has a length of 0, the control has no name - * @return NS_OK if successful - */ - virtual nsresult GetName(nsString& aResult) = 0; - - /** - * Get the number of references to this control by other objects. - * @return the ref count - */ - virtual nsrefcnt GetRefCount() const = 0; - - /** - * Get the vaules which this control could submit. - * @param aMaxNumValues the maximum number of values to set (in parm) - * @param aNumValues the actual number of values set (out parm) - * @param aValues an array of nsString which contains the values (out parm - * that is allocated by the caller) - * @param aNames an array of nsString which contains the names (out parm - * that is allocated by the caller) - * @return PR_TRUE if any values were set, PR_FALSE otherwise - */ - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) = 0; - - /** - * Return true if this control should have its data submitted - * @param aSubmitter the submit button or text field that caused the submit - */ - virtual PRBool IsSuccessful(nsIFormControl* aSubmitter) const = 0; - - /** - * Set this control back to its initial value - */ - virtual void Reset() = 0; - - /** - * Set this control to be able to cause a form submission if aFlag is true. - */ - virtual void SetCanSubmit(PRBool aFlag) = 0; - - /** - * Set this content of this control. This is a no-op for controls that do not - * have content set explicitly. - */ - virtual void SetContent(const nsString& aValue) = 0; - - /** - * Set the form manager for this control - * @param aFormMan the new form manager - * @param aDecrementRef if PR_TRUE, decrement the ref count to the existing - * form manager. This facilitates handling circular references. - */ - virtual void SetFormManager(nsIFormManager* aFormMan, PRBool aDecrementRef = PR_TRUE) = 0; - -}; - -#endif /* nsIFormControl_h___ */ diff --git a/mozilla/layout/html/forms/public/nsIFormManager.h b/mozilla/layout/html/forms/public/nsIFormManager.h index 6459498ec89..70b48ab554a 100644 --- a/mozilla/layout/html/forms/public/nsIFormManager.h +++ b/mozilla/layout/html/forms/public/nsIFormManager.h @@ -19,54 +19,25 @@ #define nsIFormManager_h___ #include "nsISupports.h" -#include "nsIContent.h" -class nsIFormControl; class nsIPresContext; class nsIFrame; -class nsString; // IID for the nsIFormManager interface #define NS_IFORMMANAGER_IID \ { 0x592daa01, 0xcb23, 0x11d1, \ { 0x80, 0x2d, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } -// this is temporary until a more global solution is developed -enum nsFormRenderingMode { - kBackwardMode = 0, // nav 4 - kForwardMode // newest -}; - -// XXX XPCOM'ize me /** - * Abstract form manager interface. Form managers are responsible for - * the management of form controls. This includes gathering of data - * for form submission, resetting form controls to their initial state, - * and other programmatic control during form processing. + * Interface to provide submitting and resetting forms **/ class nsIFormManager : public nsISupports { public: - // Event methods - - /** - * Respond to a radio button being checked. This form manager is responsible - * for radio group coordination. - * @param aRadio the radio button that was checked - */ - virtual void OnRadioChecked(nsIFormControl& aRadio) = 0; - /** * Reset the values of all of this manager's controls back to their * initial values. This is in response to a reset button being pushed. */ - virtual void OnReset() = 0; - - /** - * If there is a single text form control, this is identical to OnReset, - * otherwise do nothing. This in response to a carriage return being - * entered within a text control. - */ - virtual void OnReturn() = 0; + NS_IMETHOD OnReset() = 0; /** * Submit the values of this manager's controls depending on its action, @@ -75,75 +46,8 @@ public: * @param aFrame the frame of the submit button * @param aSubmitter the control that caused the submit */ - virtual void OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame, - nsIFormControl* aSubmitter) = 0; + NS_IMETHOD OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) = 0; - /** - * This is tbd and is in repsonse to a tab key being entered in one - * of the controls. - */ - virtual void OnTab() = 0; - - // methods accessing controls - - /** - * Add a control to end of this manager's list of controls - * @param aFormControl the control to add - * @return PR_TRUE if the control was successfully added - */ - virtual PRBool AddFormControl(nsIFormControl* aFormControl) = 0; - - /** - * Get the number of controls that this manager has in its list - * @return the number of controls - */ - virtual PRInt32 GetFormControlCount() const = 0; - - /** - * Get the control at a specific position in this manager's list - * @param aIndex the position at which to get - * @return the control at that position - */ - virtual nsIFormControl* GetFormControlAt(PRInt32 aIndex) const = 0; - - /** - * Remove a control from this manager's list - * @param aFormControl thc control to remove - * @param aChildIsRef if PR_TRUE, the controls ref count will be decremented - * otherwise not. This is to facilitate circular references. - * @return PR_TRUE if the control was successfully removed. - */ - virtual PRBool RemoveFormControl(nsIFormControl* aFormControl, - PRBool aChildIsRef = PR_TRUE) = 0; - - // methods accessing attributes - - NS_IMETHOD GetAttribute(const nsString& aName, nsString& aResult) const = 0; - - /** - * Set the named attribute of this manager - * @param aName the name of the attribute - * @param aValue the value of the attribute - */ - NS_IMETHOD SetAttribute(const nsString& aName, const nsString& aValue) = 0; - - // misc methods - - /** - * Initialize this form manager after all of the controls have been added - * This makes it possible to determine what the radio groups are. - * @param aReinit if PR_TRUE initialize even if Init has been called before. - */ - virtual void Init(PRBool aReinit) = 0; - - /** - * Get the number of references to this form manager by other objects. - * @return the ref count - */ - virtual nsrefcnt GetRefCount() const = 0; - - virtual nsFormRenderingMode GetMode() const = 0; - virtual void SetMode(nsFormRenderingMode aMode) = 0; }; #endif /* nsIFormManager_h___ */ diff --git a/mozilla/layout/html/forms/src/Makefile b/mozilla/layout/html/forms/src/Makefile index d6cec43dfc2..43c2803e6cb 100644 --- a/mozilla/layout/html/forms/src/Makefile +++ b/mozilla/layout/html/forms/src/Makefile @@ -25,15 +25,14 @@ DEFINES += -D_IMPL_NS_HTML # Note the sophisticated alphabetical ordering :-| CPPSRCS = \ - nsForm.cpp \ - nsInput.cpp \ - nsInputButton.cpp \ - nsInputCheckbox.cpp \ - nsInputFile.cpp \ - nsInputFrame.cpp \ - nsInputRadio.cpp \ - nsInputText.cpp \ - nsSelect.cpp \ + nsFormFrame.cpp \ + nsFormControlFrame.cpp \ + nsButtonControlFrame.cpp \ + nsCheckboxControlFrame.cpp \ + nsFileControlFrame.cpp \ + nsRadioControlFrame.cpp \ + nsTextControlFrame.cpp \ + nsSelectControlFrame.cpp \ $(NULL) MODULE = raptor diff --git a/mozilla/layout/html/forms/src/makefile.win b/mozilla/layout/html/forms/src/makefile.win index 5c4e0c89680..5d278fe612e 100644 --- a/mozilla/layout/html/forms/src/makefile.win +++ b/mozilla/layout/html/forms/src/makefile.win @@ -23,15 +23,13 @@ DEFINES=-D_IMPL_NS_HTML -DWIN32_LEAN_AND_MEAN MODULE=raptor REQUIRES=xpcom raptor js -CPPSRCS=nsForm.cpp nsInput.cpp nsInputButton.cpp nsInputCheckbox.cpp \ - nsInputFile.cpp nsInputFrame.cpp \ - nsInputRadio.cpp nsInputText.cpp nsSelect.cpp +CPPSRCS=nsFormFrame.cpp nsFormControlFrame.cpp nsButtonControlFrame.cpp nsCheckboxControlFrame.cpp \ + nsFileControlFrame.cpp nsRadioControlFrame.cpp nsTextControlFrame.cpp nsSelectControlFrame.cpp -CPP_OBJS=.\$(OBJDIR)\nsForm.obj .\$(OBJDIR)\nsInput.obj \ - .\$(OBJDIR)\nsInputButton.obj .\$(OBJDIR)\nsInputCheckbox.obj \ - .\$(OBJDIR)\nsInputFile.obj .\$(OBJDIR)\nsInputFrame.obj \ - .\$(OBJDIR)\nsInputRadio.obj \ - .\$(OBJDIR)\nsInputText.obj .\$(OBJDIR)\nsSelect.obj +CPP_OBJS=.\$(OBJDIR)\nsFormFrame.obj .\$(OBJDIR)\nsFormControlFrame.obj \ + .\$(OBJDIR)\nsButtonControlFrame.obj .\$(OBJDIR)\nsCheckboxControlFrame.obj \ + .\$(OBJDIR)\nsFileControlFrame.obj .\$(OBJDIR)\nsRadioControlFrame.obj \ + .\$(OBJDIR)\nsTextControlFrame.obj .\$(OBJDIR)\nsSelectControlFrame.obj LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \ -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \ diff --git a/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp new file mode 100644 index 00000000000..341b3adce62 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsButtonControlFrame.cpp @@ -0,0 +1,418 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsFileControlFrame.h" +#include "nsButtonControlFrame.h" +#include "nsHTMLParts.h" +#include "nsHTMLContainer.h" +#include "nsIRenderingContext.h" +#include "nsIPresContext.h" +#include "nsIPresShell.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsIButton.h" +#include "nsIViewManager.h" +#include "nsISupports.h" +#include "nsHTMLAtoms.h" +#include "nsIButton.h" +#include "nsIView.h" +#include "nsViewsCID.h" +#include "nsWidgetsCID.h" +#include "nsIDeviceContext.h" +#include "nsIFontCache.h" +#include "nsIFontMetrics.h" +#include "nsIFormControl.h" +#include "nsIImage.h" +#include "nsHTMLImage.h" +#include "nsStyleUtil.h" +#include "nsDOMEvent.h" +#include "nsStyleConsts.h" +#include "nsIHTMLAttributes.h" +#include "nsGenericHTMLElement.h" +#include "nsFormFrame.h" + +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); + +void +nsButtonControlFrame::GetDefaultLabel(nsString& aString) +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_INPUT_RESET == type) { + aString = "Reset"; + } + else if (NS_FORM_INPUT_SUBMIT == type) { + aString = "Submit Query"; + } + else if (NS_FORM_BROWSE == type) { + aString = "Browse..."; + } + else { + aString = " "; + } +} + + +PRInt32 +nsButtonControlFrame::GetMaxNumValues() +{ + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_HIDDEN == type)) { + return 1; + } else if (NS_FORM_INPUT_IMAGE == type) { + return 2; + } else { + return 0; + } +} + + +PRBool +nsButtonControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRInt32 type; + GetType(&type); + nsAutoString value; + nsresult valResult = GetValue(&value); + + if ((NS_FORM_INPUT_IMAGE == type) || (NS_FORM_INPUT_BUTTON == type)) { + char buf[20]; + aNumValues = 2; + + aValues[0].SetLength(0); + sprintf(&buf[0], "%d", mLastClickPoint.x); + aValues[0].Append(&buf[0]); + + aNames[0] = name; + aNames[0].Append(".x"); + + aValues[1].SetLength(0); + sprintf(&buf[0], "%d", mLastClickPoint.y); + aValues[1].Append(&buf[0]); + + aNames[1] = name; + aNames[1].Append(".y"); + + return PR_TRUE; + } + else if (((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_HIDDEN == type)) && + (NS_CONTENT_ATTR_HAS_VALUE == valResult)) { + aValues[0] = value; + aNames[0] = name; + aNumValues = 1; + return PR_TRUE; + } else { + aNumValues = 0; + return PR_FALSE; + } +} + + +nsresult +NS_NewButtonControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsButtonControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsButtonControlFrame::nsButtonControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ +} + +nsButtonControlFrame::~nsButtonControlFrame() +{ +} + +nscoord +nsButtonControlFrame::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(4, aPixToTwip); +} + +nscoord +nsButtonControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +nscoord +nsButtonControlFrame::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ + //return NSIntPixelsToTwips(4, aPixToTwip); +#ifdef XP_PC + return (nscoord)NSToIntRound((float)aInnerHeight * 0.25f); +#endif +#ifdef XP_UNIX + return (nscoord)NSToIntRound((float)aInnerHeight * 0.50f); +#endif +} + +nscoord +nsButtonControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ + nsCompatibility mode; + aPresContext.GetCompatibilityMode(mode); + +#ifdef XP_PC + if (eCompatibility_NavQuirks == mode) { + return (nscoord)NSToIntRound(float(aInnerWidth) * 0.25f); + } else { + return NSIntPixelsToTwips(10, aPixToTwip) + 8; + } +#endif +#ifdef XP_UNIX + if (eCompatibility_NavQuirks == mode) { + return (nscoord)NSToIntRound(float(aInnerWidth) * 0.5f); + } else { + return NSIntPixelsToTwips(20, aPixToTwip); + } +#endif +} + +NS_METHOD +nsButtonControlFrame::Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect) +{ + PRInt32 type; + GetType(&type); + + const nsStyleDisplay* disp = + (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); + + if (disp->mVisible) { + // let super do processing if there is no image + if (NS_FORM_INPUT_IMAGE != type) { + return nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); + } + + // First paint background and borders + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect); + + nsIImage* image = mImageLoader.GetImage(); + if (nsnull == image) { + // No image yet + return NS_OK; + } + + // Now render the image into our inner area (the area without the + nsRect inner; + GetInnerArea(&aPresContext, inner); + aRenderingContext.DrawImage(image, inner); + } + + return NS_OK; +} + +void +nsButtonControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + PRInt32 type; + GetType(&type); + if (nsnull != mFormFrame) { + if (NS_FORM_INPUT_RESET == type) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_RESET; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnReset(); + } + else if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_IMAGE == type)) { + //Send DOM event + nsEventStatus mStatus; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_SUBMIT; + mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnSubmit(aPresContext, this); + } + } else if ((NS_FORM_BROWSE == type) && mFileControlFrame) { + mFileControlFrame->MouseClicked(aPresContext); + } +} + +NS_METHOD +nsButtonControlFrame::Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + PRInt32 type; + GetType(&type); + + if (NS_FORM_INPUT_IMAGE == type) { + nsSize ignore; + GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, ignore); + AddBordersAndPadding(&aPresContext, aDesiredSize); + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + aStatus = NS_FRAME_COMPLETE; + return NS_OK; + } + else { + return nsFormControlFrame:: Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); + } +} + +void +nsButtonControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + PRInt32 type; + GetType(&type); + + if (NS_FORM_INPUT_HIDDEN == type) { // there is no physical rep + aDesiredLayoutSize.width = 0; + aDesiredLayoutSize.height = 0; + aDesiredLayoutSize.ascent = 0; + aDesiredLayoutSize.descent = 0; + } else { + if (NS_FORM_INPUT_IMAGE == type) { // there is an image + // Setup url before starting the image load + nsAutoString src; + if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute("SRC", src)) { + mImageLoader.SetURL(src); + } + mImageLoader.GetDesiredSize(aPresContext, aReflowState, aDesiredLayoutSize); + } else { // there is a widget + nsSize styleSize; + GetStyleSize(*aPresContext, aReflowState, styleSize); + // a browse button shares is style context with its parent nsInputFile + // it uses everything from it except width + if (NS_FORM_BROWSE == type) { + styleSize.width = CSS_NOTSET; + } + nsSize size; + PRBool widthExplicit, heightExplicit; + PRInt32 ignore; + nsAutoString defaultLabel; + GetDefaultLabel(defaultLabel); + nsInputDimensionSpec spec(nsHTMLAtoms::size, PR_TRUE, nsHTMLAtoms::value, + &defaultLabel, 1, PR_FALSE, nsnull, 1); + CalculateSize(aPresContext, this, styleSize, spec, size, + widthExplicit, heightExplicit, ignore); + aDesiredLayoutSize.width = size.width; + aDesiredLayoutSize.height= size.height; + } + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; + } + + aDesiredWidgetSize.width = aDesiredLayoutSize.width; + aDesiredWidgetSize.height= aDesiredLayoutSize.height; +} + + +void +nsButtonControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + PRInt32 type; + GetType(&type); + + nsIButton* button = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIButtonIID,(void**)&button))) { + if (NS_FORM_BROWSE != type) { // browse button always uses default + const nsStyleFont* styleFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || + (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { + nsFont widgetFont(styleFont->mFixedFont); + widgetFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight + widgetFont.size = styleFont->mFont.size; // normal font size + if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { + widgetFont.name = "Arial"; // XXX windows specific font + } + mWidget->SetFont(widgetFont); + } + else { + // use arial, scaled down one HTML size + // italics, decoration & variant(?) get used + nsFont widgetFont(styleFont->mFont); + widgetFont.name = "Arial"; // XXX windows specific font + widgetFont.weight = NS_FONT_WEIGHT_NORMAL; + const nsFont& normal = aPresContext->GetDefaultFont(); + PRInt32 scaler = aPresContext->GetFontScaler(); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(widgetFont.size, (PRInt32)normal.size, scaleFactor); + widgetFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); + mWidget->SetFont(widgetFont); + } + } + } + else { + NS_ASSERTION(0, "no widget in button control"); + } + + nsString value; + nsresult result = GetValue(&value); + + if (button != nsnull) { + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + button->SetLabel(value); + } else { + nsAutoString label; + GetDefaultLabel(label); + button->SetLabel(label); + } + } + NS_IF_RELEASE(button); +} + +const nsIID& +nsButtonControlFrame::GetIID() +{ + static NS_DEFINE_IID(kButtonIID, NS_IBUTTON_IID); + return kButtonIID; +} + +const nsIID& +nsButtonControlFrame::GetCID() +{ + static NS_DEFINE_IID(kButtonCID, NS_BUTTON_CID); + return kButtonCID; +} + diff --git a/mozilla/layout/html/forms/src/nsButtonControlFrame.h b/mozilla/layout/html/forms/src/nsButtonControlFrame.h new file mode 100644 index 00000000000..253810d3315 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsButtonControlFrame.h @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsButtonControlFrame_h___ +#define nsButtonControlFrame_h___ + +#include "nsFormControlFrame.h" +#include "nsHTMLImage.h" +class nsFileControlFrame; + +class nsButtonControlFrame : public nsFormControlFrame { +public: + nsButtonControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect); + + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual void MouseClicked(nsIPresContext* aPresContext); + + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + nsFileControlFrame* GetFileControlFrame() { return mFileControlFrame; } + void SetFileControlFrame(nsFileControlFrame* aFrame) { mFileControlFrame = aFrame; } + void GetDefaultLabel(nsString& aLabel); + virtual PRInt32 GetMaxNumValues(); + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + +protected: + virtual ~nsButtonControlFrame(); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); + + nsHTMLImageLoader mImageLoader; + nsFileControlFrame* mFileControlFrame; // for browse buttons only +}; + + +#endif + diff --git a/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp new file mode 100644 index 00000000000..bf6eb510c50 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsCheckboxControlFrame.cpp @@ -0,0 +1,238 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsICheckButton.h" +#include "nsFormControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIFrame.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsWidgetsCID.h" +#include "nsIView.h" +#include "nsHTMLAtoms.h" +#include "nsIStyleContext.h" +#include "nsStyleUtil.h" +#include "nsIFormControl.h" + +static NS_DEFINE_IID(kICheckButtonIID, NS_ICHECKBUTTON_IID); +//static NS_DEFINE_IID(kIHTMLContentIID, NS_IHTMLCONTENT_IID); + +class nsCheckboxControlFrame : public nsFormControlFrame { +public: + nsCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + + virtual void MouseClicked(nsIPresContext* aPresContext); + + virtual PRInt32 GetMaxNumValues(); + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + virtual void Reset(); + + NS_IMETHOD GetChecked(PRBool* aResult); + +protected: + virtual ~nsCheckboxControlFrame(); + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); +}; + +nsresult +NS_NewCheckboxControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsCheckboxControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsCheckboxControlFrame::nsCheckboxControlFrame(nsIContent* aContent, nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ +} + +nsCheckboxControlFrame::~nsCheckboxControlFrame() +{ +} + +const nsIID& +nsCheckboxControlFrame::GetIID() +{ + static NS_DEFINE_IID(kCheckboxIID, NS_ICHECKBUTTON_IID); + return kCheckboxIID; +} + +const nsIID& +nsCheckboxControlFrame::GetCID() +{ + static NS_DEFINE_IID(kCheckboxCID, NS_CHECKBUTTON_CID); + return kCheckboxCID; +} + +void +nsCheckboxControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + float p2t = aPresContext->GetPixelsToTwips(); +#ifdef XP_PC + aDesiredWidgetSize.width = NSIntPixelsToTwips(12, p2t); + aDesiredWidgetSize.height = NSIntPixelsToTwips(12, p2t); +#endif +#ifdef XP_PC + aDesiredWidgetSize.width = NSIntPixelsToTwips(20, p2t); + aDesiredWidgetSize.height = NSIntPixelsToTwips(20, p2t); +#endif + aDesiredLayoutSize.width = aDesiredWidgetSize.width; + aDesiredLayoutSize.height = aDesiredWidgetSize.height; + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; +} + +NS_IMETHODIMP +nsCheckboxControlFrame::GetChecked(PRBool* aResult) +{ + nsresult result = NS_FORM_NOTOK; + *aResult = PR_FALSE; + if (mContent) { + nsIHTMLContent* iContent = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + nsHTMLValue value; + result = iContent->GetAttribute(nsHTMLAtoms::checked, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + *aResult = PR_TRUE; + } + NS_RELEASE(iContent); + } + } + return result; +} + +void +nsCheckboxControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + PRBool checked; + nsresult result = GetChecked(&checked); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + // set the widget to the initial state + nsICheckButton* checkbox = nsnull; + + if (mWidget && (NS_OK == mWidget->QueryInterface(GetIID(),(void**)&checkbox))) { + checkbox->SetState(checked); + + const nsStyleColor* color = + nsStyleUtil::FindNonTransparentBackground(mStyleContext); + + if (nsnull != color) { + mWidget->SetBackgroundColor(color->mBackgroundColor); + } else { + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + } + + NS_IF_RELEASE(checkbox); + } + } +} + +void +nsCheckboxControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + nsICheckButton* checkbox = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(GetIID(),(void**)&checkbox))) { + PRBool oldState; + checkbox->GetState(oldState); + PRBool newState = oldState ? PR_FALSE : PR_TRUE; + checkbox->SetState(newState); + NS_IF_RELEASE(checkbox); + } +} + +PRInt32 +nsCheckboxControlFrame::GetMaxNumValues() +{ + return 1; +} + + +PRBool +nsCheckboxControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult nameResult = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != nameResult)) { + return PR_FALSE; + } + + PRBool result = PR_TRUE; + + nsAutoString value; + nsresult valueResult = GetValue(&value); + + nsICheckButton* checkBox = nsnull; + if ((nsnull != mWidget) && + (NS_OK == mWidget->QueryInterface(kICheckButtonIID,(void**)&checkBox))) { + PRBool state = PR_FALSE; + checkBox->GetState(state); + if (PR_TRUE != state) { + result = PR_FALSE; + } else { + if (NS_CONTENT_ATTR_HAS_VALUE == valueResult) { + aValues[0] = "on"; + } else { + aValues[0] = value; + } + aNames[0] = name; + aNumValues = 1; + } + NS_RELEASE(checkBox); + } + + return result; +} + +void +nsCheckboxControlFrame::Reset() +{ + nsICheckButton* checkBox = nsnull; + if ((mWidget != nsnull) && + (NS_OK == mWidget->QueryInterface(kICheckButtonIID,(void**)&checkBox))) { + PRBool checked; + GetChecked(&checked); + checkBox->SetState(checked); + NS_RELEASE(checkBox); + } +} + diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp new file mode 100644 index 00000000000..3cf840646b9 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -0,0 +1,314 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsFileControlFrame.h" +#include "nsButtonControlFrame.h" +#include "nsTextControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsHTMLAtoms.h" +#include "nsIFileWidget.h" +#include "nsITextWidget.h" +#include "nsWidgetsCID.h" +#include "nsRepository.h" +#include "nsIView.h" +#include "nsHTMLParts.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsHTMLParts.h" +#include "nsIFormControl.h" + +// XXX make this pixels +#define CONTROL_SPACING 40 + +static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID); +static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); + +nsresult +NS_NewFileControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsFileControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsFileControlFrame::nsFileControlFrame(nsIContent* aContent, nsIFrame* aParentFrame) + : nsHTMLContainerFrame(aContent, aParentFrame) +{ + mTextFrame = nsnull; + mBrowseFrame = nsnull; + mFormFrame = nsnull; +} + +nsFileControlFrame::~nsFileControlFrame() +{ +} + +nsresult +nsFileControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIFormControlFrameIID)) { + *aInstancePtr = (void*) ((nsIFormControlFrame*) this); + return NS_OK; + } + return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); +} + +PRBool +nsFileControlFrame::IsSuccessful() +{ + nsAutoString name; + return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name)); +} + +void +nsFileControlFrame::Reset() +{ + if (mTextFrame) { + mTextFrame->Reset(); + } +} + +NS_IMETHODIMP +nsFileControlFrame::GetType(PRInt32* aType) const +{ + *aType = NS_FORM_INPUT_FILE; + return NS_OK; +} + +// XXX this should be removed when nsView exposes it +nsIWidget* +GetWindowTemp(nsIView *aView) +{ + nsIWidget *window = nsnull; + + nsIView *ancestor = aView; + while (nsnull != ancestor) { + ancestor->GetWidget(window); + if (nsnull != window) { + return window; + } + ancestor->GetParent(ancestor); + } + return nsnull; +} + + +// this is in response to the MouseClick from the containing browse button +// XXX still need to get filters from accept attribute +void nsFileControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + nsIView* textView; + mTextFrame->GetView(textView); + if (nsnull == textView) { + return; + } + nsIWidget* widget; + mTextFrame->GetWidget(&widget); + if (!widget) { + return; + } + + nsITextWidget* textWidget; + nsresult result = widget->QueryInterface(kITextWidgetIID, (void**)&textWidget); + if (NS_OK != result) { + NS_RELEASE(widget); + return; + } + + nsIView* parentView; + textView->GetParent(parentView); + nsIWidget* parentWidget = GetWindowTemp(parentView); + + nsIFileWidget *fileWidget; + + nsString title("FileWidget Title mode = save"); + nsRepository::CreateInstance(kCFileWidgetCID, nsnull, kIFileWidgetIID, (void**)&fileWidget); + + nsString titles[] = {"all files"}; + nsString filters[] = {"*.*"}; + fileWidget->SetFilterList(1, titles, filters); + + fileWidget->Create(parentWidget, title, eMode_load, nsnull, nsnull); + result = fileWidget->Show(); + + if (result) { + PRUint32 size; + nsString fileName; + fileWidget->GetFile(fileName); + textWidget->SetText(fileName,size); + } + NS_RELEASE(fileWidget); + NS_RELEASE(parentWidget); + NS_RELEASE(textWidget); + NS_RELEASE(widget); +} + + +void SetType(nsIHTMLContent* aElement, nsString& aValue) +{ + nsIHTMLContent* iContent = nsnull; + nsresult result = aElement->QueryInterface(kIHTMLContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + iContent->SetAttribute("type", aValue, PR_FALSE); + NS_RELEASE(iContent); + } +} + +NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + PRInt32 numChildren = LengthOf(mFirstChild); + + nsIFrame* childFrame; + if (0 == numChildren) { + // XXX This code should move to Init(), someday when the frame construction + // changes are all done and Init() is always getting called... + nsIHTMLContent* text = nsnull; + nsIAtom* tag = NS_NewAtom("text"); + NS_NewHTMLInputElement(&text, tag); + text->SetAttribute("type", "text", PR_FALSE); + NS_NewTextControlFrame(text, this, childFrame); + childFrame->SetStyleContext(&aPresContext, mStyleContext); + mTextFrame = (nsTextControlFrame*)childFrame; + mFirstChild = childFrame; + + nsIHTMLContent* browse = nsnull; + tag = NS_NewAtom("browse"); + NS_NewHTMLInputElement(&browse, tag); + browse->SetAttribute("type", "browse", PR_FALSE); + NS_NewButtonControlFrame(browse, this, childFrame); + ((nsButtonControlFrame*)childFrame)->SetFileControlFrame(this); + mBrowseFrame = (nsButtonControlFrame*)childFrame; + childFrame->SetStyleContext(&aPresContext, mStyleContext); + + mFirstChild->SetNextSibling(childFrame); + mChildCount = 2; + + NS_RELEASE(text); + NS_RELEASE(browse); + } + + nsSize maxSize = aReflowState.maxSize; + nsReflowMetrics desiredSize = aDesiredSize; + aDesiredSize.width = CONTROL_SPACING; + aDesiredSize.height = 0; + childFrame = mFirstChild; + nsPoint offset(0,0); + while (nsnull != childFrame) { // reflow, place, size the children + nsReflowState reflowState(childFrame, aReflowState, maxSize); + childFrame->WillReflow(aPresContext); + nsresult result = childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); + NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); + nsRect rect(offset.x, offset.y, desiredSize.width, desiredSize.height); + childFrame->SetRect(rect); + maxSize.width -= desiredSize.width; + aDesiredSize.width += desiredSize.width; + aDesiredSize.height = desiredSize.height; + childFrame->GetNextSibling(childFrame); + offset.x += desiredSize.width + CONTROL_SPACING; + } + + aDesiredSize.ascent = aDesiredSize.height; + aDesiredSize.descent = 0; + + if (nsnull != aDesiredSize.maxElementSize) { + aDesiredSize.maxElementSize->width = aDesiredSize.width; + aDesiredSize.maxElementSize->height = aDesiredSize.height; + } + + aStatus = NS_FRAME_COMPLETE; + return NS_OK; +} + +PRIntn +nsFileControlFrame::GetSkipSides() const +{ + return 0; +} + + +NS_IMETHODIMP +nsFileControlFrame::GetName(nsString* aResult) +{ + nsresult result = NS_FORM_NOTOK; + if (mContent) { + nsIHTMLContent* formControl = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if ((NS_OK == result) && formControl) { + nsHTMLValue value; + result = formControl->GetAttribute(nsHTMLAtoms::name, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + if (eHTMLUnit_String == value.GetUnit()) { + value.GetStringValue(*aResult); + } + } + NS_RELEASE(formControl); + } + } + return result; +} + +PRInt32 +nsFileControlFrame::GetMaxNumValues() +{ + return 1; +} + +PRBool +nsFileControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + // use our name and the text widgets value + aNames[0] = name; + nsresult status = PR_FALSE; + nsIWidget* widget; + nsITextWidget* textWidget; + mTextFrame->GetWidget(&widget); + if (widget && (NS_OK == widget->QueryInterface(kITextWidgetIID, (void**)&textWidget))) { + PRUint32 actualSize; + textWidget->GetText(aValues[0], 0, actualSize); + aNumValues = 1; + NS_RELEASE(textWidget); + status = PR_TRUE; + } + NS_IF_RELEASE(widget); + return status; +} + diff --git a/mozilla/layout/html/forms/src/nsFormControlFrame.h b/mozilla/layout/html/forms/src/nsFormControlFrame.h new file mode 100644 index 00000000000..739ae4edd12 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFormControlFrame.h @@ -0,0 +1,255 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsFormControlFrame_h___ +#define nsFormControlFrame_h___ + +#include "nsIFormControlFrame.h" +#include "nsIFormManager.h" +#include "nsHTMLContainer.h" +#include "nsISupports.h" +#include "nsIWidget.h" +#include "nsLeafFrame.h" +#include "nsCoord.h" + +class nsIView; +class nsIPresContext; +class nsStyleCoord; +class nsFormFrame; + +#define CSS_NOTSET -1 +#define ATTR_NOTSET -1 + +/** + * Enumeration of possible mouse states used to detect mouse clicks + */ +enum nsMouseState { + eMouseNone, + eMouseEnter, + eMouseDown, + eMouseUp +}; + +struct nsInputDimensionSpec +{ + nsIAtom* mColSizeAttr; // attribute used to determine width + PRBool mColSizeAttrInPixels; // is attribute value in pixels (otherwise num chars) + nsIAtom* mColValueAttr; // attribute used to get value to determine size + // if not determined above + nsString* mColDefaultValue; // default value if not determined above + nscoord mColDefaultSize; // default width if not determined above + PRBool mColDefaultSizeInPixels; // is default width in pixels (otherswise num chars) + nsIAtom* mRowSizeAttr; // attribute used to determine height + nscoord mRowDefaultSize; // default height if not determined above + + nsInputDimensionSpec(nsIAtom* aColSizeAttr, PRBool aColSizeAttrInPixels, + nsIAtom* aColValueAttr, nsString* aColDefaultValue, + nscoord aColDefaultSize, PRBool aColDefaultSizeInPixels, + nsIAtom* aRowSizeAttr, nscoord aRowDefaultSize) + : mColSizeAttr(aColSizeAttr), mColSizeAttrInPixels(aColSizeAttrInPixels), + mColValueAttr(aColValueAttr), + mColDefaultValue(aColDefaultValue), mColDefaultSize(aColDefaultSize), + mColDefaultSizeInPixels(aColDefaultSizeInPixels), + mRowSizeAttr(aRowSizeAttr), mRowDefaultSize(aRowDefaultSize) + { + } + +}; + +/** + * nsFormControlFrame is the base class for frames of form controls. It + * provides a uniform way of creating widgets, resizing, and painting. + * @see nsLeafFrame and its base classes for more info + */ +class nsFormControlFrame : public nsLeafFrame, + public nsIFormControlFrame +{ + +public: + /** + * Main constructor + * @param aContent the content representing this frame + * @param aParentFrame the parent frame + */ + nsFormControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + static nscoord CalculateSize (nsIPresContext* aPresContext, nsFormControlFrame* aFrame, + const nsSize& aCSSSize, nsInputDimensionSpec& aDimensionSpec, + nsSize& aBounds, PRBool& aWidthExplicit, + PRBool& aHeightExplicit, nscoord& aRowSize); + + /** + * Respond to a gui event + * @see nsIFrame::HandleEvent + */ + NS_IMETHOD HandleEvent(nsIPresContext& aPresContext, + nsGUIEvent* aEvent, + nsEventStatus& aEventStatus); + + /** + * Draw this frame within the context of a presentation context and rendering context + * @see nsIFrame::Paint + */ + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect); + + NS_IMETHOD DidReflow(nsIPresContext& aPresContext, + nsDidReflowStatus aStatus); + + /** + * Respond to the request to resize and/or reflow + * @see nsIFrame::Reflow + */ + NS_IMETHOD Reflow(nsIPresContext& aCX, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus); + + // new behavior + + /** + * Get the class id of the widget associated with this frame + * @return the class id + */ + virtual const nsIID& GetCID(); + + /** + * Get the interface id of widget associated with this frame + * @return the interface id + */ + virtual const nsIID& GetIID(); + + NS_IMETHOD GetType(PRInt32* aType) const; + NS_IMETHOD GetName(nsString* aName); + NS_IMETHOD GetValue(nsString* aName); + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + /** + * Get the widget associated with this frame + * @param aView the view associated with the frame. It is a convience parm. + * @param aWidget the address of address of where the widget will be placed. + * This method doses an AddRef on the widget. + */ + nsresult GetWidget(nsIView* aView, nsIWidget** aWidget); + nsresult GetWidget(nsIWidget** aWidget); + + /** + * Respond to a enter key being pressed + */ + virtual void EnterPressed(nsIPresContext& aPresContext) {} + + /** + * Respond to a mouse click (e.g. mouse enter, mouse down, mouse up) + */ + virtual void MouseClicked(nsIPresContext* aPresContext) {} + + /** + * Perform opertations after the widget associated with this frame has been + * created. + */ + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual void Reset(); + virtual PRBool IsSuccessful(); + + /** + * Perform opertations before the widget associated with this frame has been + * created. + */ + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + static nscoord GetTextSize(nsIPresContext& aContext, nsFormControlFrame* aFrame, + const nsString& aString, nsSize& aSize); + static nscoord GetTextSize(nsIPresContext& aContext, nsFormControlFrame* aFrame, + PRInt32 aNumChars, nsSize& aSize); + + void GetWidgetSize(nsSize& aSize) const { aSize.width = mWidgetSize.width; + aSize.height = mWidgetSize.height; } + + // XXX similar functionality needs to be added to widget library and these + // need to change to use it. + static nscoord GetScrollbarWidth(float aPixToTwip); + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + NS_IMETHOD GetSize(PRInt32* aSize) const; + NS_IMETHOD GetMaxLength(PRInt32* aSize); + + virtual void SetClickPoint(nscoord aX, nscoord aY); + nsFormFrame* GetFormFrame() { return mFormFrame; } + virtual void SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } + +protected: + + virtual ~nsFormControlFrame(); + + /** + * Get the size that this frame would occupy without any constraints + * @param aPresContext the presentation context + * @param aDesiredSize the size desired by this frame, to be set by this method + * @param aMaxSize the maximum size available for this frame + */ + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredSize); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); + + NS_IMETHOD GetFont(nsIPresContext* aPresContext, nsFont& aFont); + + /** + * Get the width and height of this control based on CSS + * @param aPresContext the presentation context + * @param aSize the size that this frame wants, set by this method. values of -1 + * for aSize.width or aSize.height indicate unset values. + */ + void GetStyleSize(nsIPresContext& aContext, + const nsReflowState& aReflowState, + nsSize& aSize); + + //nscoord GetStyleDim(nsIPresContext& aPresContext, nscoord aMaxDim, + // nscoord aMaxWidth, const nsStyleCoord& aCoord); + + nsMouseState mLastMouseState; + nsIWidget* mWidget; + nsSize mWidgetSize; + PRBool mDidInit; + nsPoint mLastClickPoint; + nsFormFrame* mFormFrame; + +private: + NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } + NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } + +}; + +#endif + diff --git a/mozilla/layout/html/forms/src/nsFormFrame.cpp b/mozilla/layout/html/forms/src/nsFormFrame.cpp new file mode 100644 index 00000000000..c661cd772b2 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFormFrame.cpp @@ -0,0 +1,1019 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#include "nsFormFrame.h" +#include "nsFormControlFrame.h" +#include "nsFileControlFrame.h" +#include "nsRadioControlFrame.h" + +#include "nsIForm.h" +#include "nsIFormControl.h" +#include "nsIAtom.h" +#include "nsHTMLIIDs.h" +#include "nsIRenderingContext.h" +#include "nsIPresShell.h" +#include "nsIPresContext.h" +#include "nsIStyleContext.h" +#include "nsLeafFrame.h" +#include "nsCSSRendering.h" +#include "nsHTMLIIDs.h" +#include "nsDebug.h" +#include "nsIWidget.h" +#include "nsVoidArray.h" +#include "nsHTMLAtoms.h" +#include "nsIHTMLAttributes.h" +#include "nsCRT.h" +#include "nsIURL.h" +#include "nsIDocument.h" +#include "nsILinkHandler.h" +#include "nsRadioControlFrame.h" +#include "nsIRadioButton.h" +#include "nsDocument.h" +#include "nsHTMLContainer.h" +#include "nsIDOMHTMLFormElement.h" +#include "nsIDOMNSHTMLFormElement.h" +#include "nsLeafFrame.h" + +#include "net.h" +#include "xp_file.h" +#include "prio.h" +#include "prmem.h" +#include "prenv.h" + +//---------------------------------------------------------------------- + +static NS_DEFINE_IID(kIFormManagerIID, NS_IFORMMANAGER_IID); +static NS_DEFINE_IID(kIFormIID, NS_IFORM_IID); +static NS_DEFINE_IID(kIFormControlFrameIID, NS_IFORMCONTROLFRAME_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kIDOMElementIID, NS_IDOMELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIDOMNSHTMLFormElementIID, NS_IDOMNSHTMLFORMELEMENT_IID); +static NS_DEFINE_IID(kIContentIID, NS_ICONTENT_IID); + +NS_IMETHODIMP +nsFormFrame::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (aIID.Equals(kIFormManagerIID)) { + *aInstancePtr = (void*)(nsIFormManager*)this; + return NS_OK; + } + return nsLeafFrame::QueryInterface(aIID, aInstancePtr); +} + +nsrefcnt nsFormFrame::AddRef(void) +{ + NS_ERROR("not supported"); + return 0; +} + +nsrefcnt nsFormFrame::Release(void) +{ + NS_ERROR("not supported"); + return 0; +} + +nsFormFrame::nsFormFrame(nsIContent* aContent, nsIFrame* aParentFrame) + : nsLeafFrame(aContent, aParentFrame) +{ + mInited = PR_FALSE; + mTextSubmitter = nsnull; +} + +nsFormFrame::~nsFormFrame() +{ + mFormControls.Clear(); +} + +PRBool +nsFormFrame::CanSubmit(nsFormControlFrame& aFrame) +{ + if (mTextSubmitter == &aFrame) { + return PR_TRUE; + } + PRInt32 type; + aFrame.GetType(&type); + if ((NS_FORM_INPUT_SUBMIT == type) || (NS_FORM_INPUT_IMAGE == type)) { + return PR_TRUE; + } + return PR_FALSE; +} + +void +nsFormFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredSize) +{ + aDesiredSize.width = 0; + aDesiredSize.height = 0; + aDesiredSize.ascent = 0; + aDesiredSize.descent = 0; +} + +NS_IMETHODIMP +nsFormFrame::GetAction(nsString* aAction) +{ + nsresult result = NS_OK; + if (mContent) { + nsIDOMHTMLFormElement* form = nsnull; + result = mContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&form); + if ((NS_OK == result) && form) { + form->GetAction(*aAction); + NS_RELEASE(form); + } + } + return result; +} + +NS_IMETHODIMP +nsFormFrame::GetTarget(nsString* aTarget) +{ + nsresult result = NS_OK; + if (mContent) { + nsIDOMHTMLFormElement* form = nsnull; + result = mContent->QueryInterface(kIDOMHTMLFormElementIID, (void**)&form); + if ((NS_OK == result) && form) { + form->GetTarget(*aTarget); + NS_RELEASE(form); + } + } + return result; +} + +NS_IMETHODIMP +nsFormFrame::GetMethod(PRInt32* aMethod) +{ + nsresult result = NS_OK; + if (mContent) { + nsIHTMLContent* form = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&form); + if ((NS_OK == result) && form) { + nsHTMLValue value; + if (NS_CONTENT_ATTR_HAS_VALUE == (form->GetAttribute(nsHTMLAtoms::method, value))) { + if (eHTMLUnit_Enumerated == value.GetUnit()) { + *aMethod = value.GetIntValue(); + NS_RELEASE(form); + return NS_OK; + } + } + NS_RELEASE(form); + } + } + *aMethod = NS_FORM_METHOD_GET; + return result; +} + +NS_IMETHODIMP +nsFormFrame::GetEnctype(PRInt32* aEnctype) +{ + nsresult result = NS_OK; + if (mContent) { + nsIHTMLContent* form = nsnull; + result = mContent->QueryInterface(kIHTMLContentIID, (void**)&form); + if ((NS_OK == result) && form) { + nsHTMLValue value; + if (NS_CONTENT_ATTR_HAS_VALUE == (form->GetAttribute(nsHTMLAtoms::enctype, value))) { + if (eHTMLUnit_Enumerated == value.GetUnit()) { + *aEnctype = value.GetIntValue(); + NS_RELEASE(form); + return NS_OK; + } + } + NS_RELEASE(form); + } + } + *aEnctype = NS_FORM_ENCTYPE_URLENCODED; + return result; +} + +NS_IMETHODIMP +nsFormFrame::Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + GetDesiredSize(&aPresContext, aReflowState, aDesiredSize); + if (!mInited) { + Init(aPresContext, PR_TRUE); + } + aStatus = NS_FRAME_COMPLETE; + return NS_OK; +} + +NS_IMETHODIMP +nsFormFrame::OnReset() +{ + PRInt32 numControls = mFormControls.Count(); + for (int i = 0; i < numControls; i++) { + nsIFormControlFrame* fcFrame = (nsIFormControlFrame*) mFormControls.ElementAt(i); + fcFrame->Reset(); + } + return NS_OK; +} + +void nsFormFrame::RemoveRadioGroups() +{ + int numRadioGroups = mRadioGroups.Count(); + for (int i = 0; i < numRadioGroups; i++) { + nsRadioControlGroup* radioGroup = (nsRadioControlGroup *) mRadioGroups.ElementAt(i); + delete radioGroup; + } + mRadioGroups.Clear(); +} + +void nsFormFrame::Init(nsIPresContext& aPresContext, PRBool aReinit) +{ + if (mInited && !aReinit) { + return; + } + + PRUint32 numControls = mFormControls.Count(); + nsIPresShell* presShell = aPresContext.GetShell(); + // first time - add the controls + if ((0 == numControls) && mContent) { + nsIForm* form = nsnull; + nsresult result = mContent->QueryInterface(kIFormIID, (void**)&form); + if ((NS_OK == result) && form) { + form->GetElementCount(&numControls); + for (PRUint32 childX = 0; childX < numControls; childX++) { + nsIFormControl* formControl; + form->GetElementAt(childX, &formControl); + if (formControl) { + nsIContent* content = nsnull; + result = formControl->QueryInterface(kIContentIID, (void**)&content); + if ((NS_OK == result) && content) { + nsIFrame* frame = presShell->FindFrameWithContent(content); + if (frame) { + nsIFormControlFrame* fcFrame = nsnull; + result = frame->QueryInterface(kIFormControlFrameIID, (void**)&fcFrame); + if ((NS_OK == result) && fcFrame) { + mFormControls.AppendElement(fcFrame); + fcFrame->SetFormFrame(this); + } + } + NS_RELEASE(content); + } + NS_RELEASE(formControl); + } + } + NS_RELEASE(form); + } + } + NS_RELEASE(presShell); + + RemoveRadioGroups(); + + // determine which radio buttons belong to which radio groups, unnamed radio buttons + // don't go into any group since they can't be submitted. Determine which controls + // are capable of form submission. + PRInt32 textCount = 0; + nsIFormControlFrame* textFrame = nsnull; + numControls = mFormControls.Count(); + + for (PRUint32 i = 0; i < numControls; i++) { + nsIFormControlFrame* fcFrame = (nsIFormControlFrame *)mFormControls.ElementAt(i); + nsString name; + name.SetLength(0); + fcFrame->GetName(&name); + PRBool hasName = name.Length() > 0; + PRInt32 type; + fcFrame->GetType(&type); + + // count text for determining "return" submission + if (NS_FORM_INPUT_TEXT == type) { + textCount++; + textFrame = fcFrame; + } + + // radio group processing + if (hasName && (NS_FORM_INPUT_RADIO == type)) { + nsRadioControlFrame* radioFrame = (nsRadioControlFrame*)fcFrame; + int numGroups = mRadioGroups.Count(); + PRBool added = PR_FALSE; + nsRadioControlGroup* group; + for (int j = 0; j < numGroups; j++) { + group = (nsRadioControlGroup *) mRadioGroups.ElementAt(j); + nsString groupName; + group->GetName(groupName); + if (groupName.Equals(name)) { + group->AddRadio(radioFrame); + added = PR_TRUE; + break; + } + } + if (!added) { + group = new nsRadioControlGroup(name); + mRadioGroups.AppendElement(group); + group->AddRadio(radioFrame); + } + // allow only one checked radio button + if (radioFrame->GetChecked(PR_TRUE)) { + if (nsnull == group->GetCheckedRadio()) { + group->SetCheckedRadio(radioFrame); + } + else { + radioFrame->SetChecked(PR_FALSE, PR_TRUE); + } + } + } + } + + // if there is only one text field, it can submit on "return" + if (1 == textCount) { + mTextSubmitter = textFrame; + } + mInited = PR_TRUE; +} + +void +nsFormFrame::OnRadioChecked(nsRadioControlFrame& aControl) +{ + nsString radioName; + aControl.GetName(&radioName); + if (0 == radioName.Length()) { // don't consider a radio without a name + return; + } + + // locate the radio group with the name of aRadio + int numGroups = mRadioGroups.Count(); + for (int j = 0; j < numGroups; j++) { + nsRadioControlGroup* group = (nsRadioControlGroup *) mRadioGroups.ElementAt(j); + nsString groupName; + group->GetName(groupName); + nsRadioControlFrame* checkedRadio = group->GetCheckedRadio(); + if (groupName.Equals(radioName) && (&aControl != checkedRadio)) { + if (checkedRadio) { + checkedRadio->SetChecked(PR_FALSE, PR_FALSE); + } + group->SetCheckedRadio(&aControl); + } + } +} + + +nsresult +NS_NewFormFrame(nsIContent* aContent, nsIFrame* aParentFrame, + nsIFrame*& aResult) +{ + nsIFrame* frame = new nsFormFrame(aContent, aParentFrame); + if (nsnull == frame) { + return NS_ERROR_OUT_OF_MEMORY; + } + aResult = frame; + return NS_OK; +} + + +void DebugPrint(char* aLabel, nsString aString) +{ + char* out = aString.ToNewCString(); + printf("\n %s=%s\n", aLabel, out); + delete [] out; +} + +// submission + +NS_IMETHODIMP +nsFormFrame::OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame) +{ + if (!mContent) { + return NS_FORM_NOTOK; + } + + nsString data; // this could be more efficient, by allocating a larger buffer + + PRInt32 method, enctype; + GetMethod(&method); + GetEnctype(&enctype); + + PRBool isURLEncoded = (NS_FORM_ENCTYPE_MULTIPART != enctype); + + // for enctype=multipart/form-data, force it to be post + // if method is "" (not specified) use "get" as default + PRBool isPost = (NS_FORM_METHOD_POST == method) || !isURLEncoded; + + if (isURLEncoded) { + ProcessAsURLEncoded(isPost, data); + } + else { + ProcessAsMultipart(data); + } + + + // make the url string + nsILinkHandler* handler; + if (NS_OK == aPresContext->GetLinkHandler(&handler)) { + // Resolve url to an absolute url + nsIURL* docURL = nsnull; + nsIDocument* doc = nsnull; + mContent->GetDocument(doc); + if (nsnull != doc) { + docURL = doc->GetDocumentURL(); + NS_RELEASE(doc); + } + + nsAutoString target; + GetTarget(&target); + + nsAutoString href; + GetAction(&href); + if (!isPost) { + href.Append(data); + } + nsAutoString absURLSpec; + nsAutoString base; + nsresult rv = NS_MakeAbsoluteURL(docURL, base, href, absURLSpec); + NS_IF_RELEASE(docURL); + + // Now pass on absolute url to the click handler + nsIPostData* postData = nsnull; + if (isPost) { + nsresult rv; + char* postBuffer = data.ToNewCString(); + + rv = NS_NewPostData(!isURLEncoded, postBuffer, &postData); + if (NS_OK != rv) { + delete [] postBuffer; + } + + /* The postBuffer is now owned by the IPostData instance */ + } + handler->OnLinkClick(aFrame, absURLSpec, target, postData); + NS_IF_RELEASE(postData); + NS_RELEASE(handler); + +DebugPrint("url", absURLSpec); +DebugPrint("data", data); + } + return NS_OK; +} + +// netlib has a general function (netlib\modules\liburl\src\escape.c) +// which does url encoding. Since netlib is not yet available for raptor, +// the following will suffice. Convert space to +, don't convert alphanumeric, +// conver each non alphanumeric char to %XY where XY is the hexadecimal +// equavalent of the binary representation of the character. +// +void URLEncode(char* aInString, char* aOutString) +{ + if (nsnull == aInString) { + return; + } + static char *toHex = "0123456789ABCDEF"; + char* outChar = aOutString; + for (char* inChar = aInString; *inChar; inChar++) { + if(' ' == *inChar) { // convert space to + + *outChar++ = '+'; + } else if ( (((*inChar - '0') >= 0) && (('9' - *inChar) >= 0)) || // don't conver + (((*inChar - 'a') >= 0) && (('z' - *inChar) >= 0)) || // alphanumeric + (((*inChar - 'A') >= 0) && (('Z' - *inChar) >= 0)) ) { + *outChar++ = *inChar; + } else { // convert all else to hex + *outChar++ = '%'; + *outChar++ = toHex[(*inChar >> 4) & 0x0F]; + *outChar++ = toHex[*inChar & 0x0F]; + } + } + *outChar = 0; // terminate the string +} + +nsString* URLEncode(nsString& aString) +{ + char* inBuf = aString.ToNewCString(); + char* outBuf = new char[ (strlen(inBuf) * 3) + 1 ]; + URLEncode(inBuf, outBuf); + nsString* result = new nsString(outBuf); + delete [] outBuf; + delete [] inBuf; + return result; +} + +#define CRLF "\015\012" +void nsFormFrame::ProcessAsURLEncoded(PRBool isPost, nsString& aData) +{ + nsString buf; + PRBool firstTime = PR_TRUE; + + PRUint32 numChildren = mFormControls.Count(); + // collect and encode the data from the children controls + for (PRUint32 childX = 0; childX < numChildren; childX++) { + nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX); + if (child && child->IsSuccessful()) { + PRInt32 numValues = 0; + PRInt32 maxNumValues = child->GetMaxNumValues(); + if (maxNumValues <= 0) { + continue; + } + nsString* names = new nsString[maxNumValues]; + nsString* values = new nsString[maxNumValues]; + if (PR_TRUE == child->GetNamesValues(maxNumValues, numValues, values, names)) { + for (int valueX = 0; valueX < numValues; valueX++) { + if (PR_TRUE == firstTime) { + firstTime = PR_FALSE; + } else { + buf += "&"; + } + nsString* convName = URLEncode(names[valueX]); + buf += *convName; + delete convName; + buf += "="; + nsString* convValue = URLEncode(values[valueX]); + buf += *convValue; + delete convValue; + } + } + delete [] names; + delete [] values; + } + } + + aData.SetLength(0); + if (isPost) { + char size[16]; + sprintf(size, "%d", buf.Length()); + aData = "Content-type: application/x-www-form-urlencoded"; + aData += CRLF; + aData += "Content-Length: "; + aData += size; + aData += CRLF; + aData += CRLF; + } + else { + aData += '?'; + } + + aData += buf; +} + +// include the file name without the directory +const char* nsFormFrame::GetFileNameWithinPath(char* aPathName) +{ + char* fileNameStart = PL_strrchr(aPathName, '\\'); // windows + if (!fileNameStart) { // try unix + fileNameStart = PL_strrchr(aPathName, '\\'); + } + if (fileNameStart) { + return fileNameStart+1; + } + else { + return aPathName; + } +} + +// this needs to be provided by a higher level, since navigator might override +// the temp directory. XXX does not check that parm is big enough +nsFormFrame::Temp_GetTempDir(char* aTempDirName) +{ + aTempDirName[0] = 0; + const char* env; + + if ((env = (const char *) getenv("TMP")) == nsnull) { + if ((env = (const char *) getenv("TEMP")) == nsnull) { + strcpy(aTempDirName, "."); + } + } + if (*env == '\0') { // null string means "." + strcpy(aTempDirName, "."); + } + if (0 == aTempDirName[0]) { + strcpy(aTempDirName, env); + } + return PR_TRUE; +} + +// the following is a temporary measure until NET_cinfo_find_type or its +// replacement is available +void nsFormFrame::Temp_GetContentType(char* aPathName, char* aContentType) +{ + if (!aPathName) { + strcpy(aContentType, "unknown"); + return; + } + + int len = strlen(aPathName); + if (len <= 0) { + strcpy(aContentType, "unknown"); + return; + } + + char* fileExt = &aPathName[len-1]; + for (int i = len-1; i >= 0; i--) { + if ('.' == aPathName[i]) { + break; + } + fileExt--; + } + if ((0 == nsCRT::strcasecmp(fileExt, ".html")) || + (0 == nsCRT::strcasecmp(fileExt, ".htm"))) { + strcpy(aContentType, "text/html"); + } + else if (0 == nsCRT::strcasecmp(fileExt, ".txt")) { + strcpy(aContentType, "text/plain"); + } + else if (0 == nsCRT::strcasecmp(fileExt, ".gif")) { + strcpy(aContentType, "image/gif"); + } + else if ((0 == nsCRT::strcasecmp(fileExt, ".jpeg")) || + (0 == nsCRT::strcasecmp(fileExt, ".jpg"))) { + strcpy(aContentType, "image/jpeg"); + } + else { // don't bother trying to do the others here + strcpy(aContentType, "unknown"); + } +} + + +#if 0 + char* tmpDir = aFileName; // copy name to fname */ + // Keep generating file names till we find one that's not in use + while ((*env != '\0') && count++ { + *ptr++ = *env++; + } + if (ptr[-1] != '\\' && ptr[-1] != '/') + *ptr++ = '\\'; /* append backslash if not in env variable */ + /* Append a suitable file name */ + next_file_num++; /* advance counter */ + sprintf(ptr, "JPG%03d.TMP", next_file_num); + /* Probe to see if file name is already in use */ + if ((tfile = fopen(fname, READ_BINARY)) == NULL) + break; + fclose(tfile); /* oops, it's there; close tfile & try again */ + } + + char* tempDir = getenv("temp"); + if (!tempDir) { + tempDir = getenv("tmp"); + } + if (tempDir) { + return PR_TRUE; + } + else { + return PR_FALSE; + } +#endif + +#define CONTENT_DISP "Content-Disposition: form-data; name=\"" +#define FILENAME "\"; filename=\"" +#define CONTENT_TYPE "Content-Type: " +#define CONTENT_ENCODING "Content-Encoding: " +#define BUFSIZE 1024 +#define MULTIPART "multipart/form-data" +#define END "--" + +void nsFormFrame::ProcessAsMultipart(nsString& aData) +{ + aData.SetLength(0); + char buffer[BUFSIZE]; + PRInt32 numChildren = mFormControls.Count(); + + // construct a temporary file to put the data into + char tmpFileName[BUFSIZE]; + char* result = Temp_GenerateTempFileName((PRInt32)BUFSIZE, tmpFileName); + if (!result) { + return; + } + + PRFileDesc* tmpFile = PR_Open(tmpFileName, PR_CREATE_FILE | PR_WRONLY, 0644); + if (!tmpFile) { + return; + } + + // write the content-type, boundary to the tmp file + char boundary[80]; + sprintf(boundary, "-----------------------------%d%d%d", + boundary, rand(), rand(), rand()); + sprintf(buffer, "Content-type: %s; boundary=%s" CRLF, MULTIPART, boundary); + PRInt32 len = PR_Write(tmpFile, buffer, PL_strlen(buffer)); + if (len < 0) { + return; + } + + PRInt32 boundaryLen = PL_strlen(boundary); + PRInt32 contDispLen = PL_strlen(CONTENT_DISP); + PRInt32 crlfLen = PL_strlen(CRLF); + + // compute the content length, passing through all of the form controls + PRInt32 contentLen = crlfLen; // extra crlf after content-length header + + PRInt32 childX; // stupid compiler + for (childX = 0; childX < numChildren; childX++) { + nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX); + if (child) { + PRInt32 type; + child->GetType(&type); + if (child->IsSuccessful()) { + PRInt32 numValues = 0; + PRInt32 maxNumValues = child->GetMaxNumValues(); + if (maxNumValues <= 0) { + continue; + } + nsString* names = new nsString[maxNumValues]; + nsString* values = new nsString[maxNumValues]; + if (PR_FALSE == child->GetNamesValues(maxNumValues, numValues, values, names)) { + continue; + } + contentLen += boundaryLen + crlfLen; + contentLen += contDispLen; + for (int valueX = 0; valueX < numValues; valueX++) { + char* name = names[valueX].ToNewCString(); + char* value = values[valueX].ToNewCString(); + if ((0 == names[valueX].Length()) || (0 == values[valueX].Length())) { + continue; + } + contentLen += PL_strlen(name); + contentLen += 1 + crlfLen; // ending name quote plus CRLF + if (NS_FORM_INPUT_FILE == type) { + contentLen += PL_strlen(FILENAME); + + // include the file name without the directory + char* fileNameStart = PL_strrchr(value, '/'); // unix + if (!fileNameStart) { // try windows + fileNameStart = PL_strrchr(value, '\\'); + } + fileNameStart = (fileNameStart) ? fileNameStart+1 : value; + contentLen += PL_strlen(fileNameStart); + + // determine the content-type of the file + + char contentType[128]; + Temp_GetContentType(value, &contentType[0]); + contentLen += PL_strlen(CONTENT_TYPE); + contentLen += PL_strlen(contentType) + crlfLen + crlfLen; + + // get the size of the file + PRFileInfo fileInfo; + if (PR_SUCCESS == PR_GetFileInfo(value, &fileInfo)) { + contentLen += fileInfo.size; + } + } + else { + contentLen += PL_strlen(value) + crlfLen; + } + delete [] name; + delete [] value; + } + delete [] names; + delete [] values; + } + + aData = tmpFileName; + } + } + + contentLen += boundaryLen + PL_strlen(END) + crlfLen; + + // write the content + sprintf(buffer, "Content-Length: %ld" CRLF CRLF, contentLen); + PR_Write(tmpFile, buffer, PL_strlen(buffer)); + + // write the content passing through all of the form controls a 2nd time + for (childX = 0; childX < numChildren; childX++) { + nsIFormControlFrame* child = (nsIFormControlFrame*) mFormControls.ElementAt(childX); + if (child) { + PRInt32 type; + child->GetType(&type); + if (child->IsSuccessful()) { + PRInt32 numValues = 0; + PRInt32 maxNumValues = child->GetMaxNumValues(); + if (maxNumValues <= 0) { + continue; + } + nsString* names = new nsString[maxNumValues]; + nsString* values = new nsString[maxNumValues]; + if (PR_FALSE == child->GetNamesValues(maxNumValues, numValues, values, names)) { + continue; + } + for (int valueX = 0; valueX < numValues; valueX++) { + char* name = names[valueX].ToNewCString(); + char* value = values[valueX].ToNewCString(); + if ((0 == names[valueX].Length()) || (0 == values[valueX].Length())) { + continue; + } + sprintf(buffer, "%s" CRLF, boundary); + PR_Write(tmpFile, buffer, PL_strlen(buffer)); + PR_Write(tmpFile, CONTENT_DISP, contDispLen); + PR_Write(tmpFile, name, PL_strlen(name)); + + if (NS_FORM_INPUT_FILE == type) { + PR_Write(tmpFile, FILENAME, PL_strlen(FILENAME)); + const char* fileNameStart = GetFileNameWithinPath(value); + PR_Write(tmpFile, fileNameStart, PL_strlen(fileNameStart)); + } + PR_Write(tmpFile, "\"" CRLF, PL_strlen("\"" CRLF)); // end content disp + + if (NS_FORM_INPUT_FILE == type) { + // determine the content-type of the file + char contentType[128]; + Temp_GetContentType(value, &contentType[0]); + PR_Write(tmpFile, CONTENT_TYPE, PL_strlen(CONTENT_TYPE)); + PR_Write(tmpFile, contentType, PL_strlen(contentType)); + PR_Write(tmpFile, CRLF, PL_strlen(CRLF)); + PR_Write(tmpFile, CRLF, PL_strlen(CRLF)); // end content-type header + + PRFileDesc* contentFile = PR_Open(value, PR_RDONLY, 0644); + if(contentFile) { + PRInt32 size; + while((size = PR_Read(contentFile, buffer, BUFSIZE)) > 0) { + PR_Write(tmpFile, buffer, size); + } + PR_Close(contentFile); + } + } + else { + PR_Write(tmpFile, value, PL_strlen(value)); + PR_Write(tmpFile, CRLF, crlfLen); + } + delete [] name; + delete [] value; + } + delete [] names; + delete [] values; + } + } + } + + sprintf(buffer, "%s--" CRLF, boundary); + PR_Write(tmpFile, buffer, PL_strlen(buffer)); + + PR_Close(tmpFile); + + //StrAllocCopy(url_struct->post_data, tmpfilename); + //url_struct->post_data_is_file = TRUE; +} + +// THE FOLLOWING WAS TAKEN FROM CMD/WINFE/FEGUI AND MODIFIED TO JUST +// GENERATE A TEMPFILE NAME. + + +// Windows _tempnam() lets the TMP environment variable override things sent in +// so it look like we're going to have to make a temp name by hand +// +// The user should *NOT* free the returned string. It is stored in static space +// and so is not valid across multiple calls to this function +// +// The names generated look like +// c:\netscape\cache\m0.moz +// c:\netscape\cache\m1.moz +// up to... +// c:\netscape\cache\m9999999.moz +// after that if fails +// +char* nsFormFrame::Temp_GenerateTempFileName(PRInt32 aMaxSize, char* file_buf) +{ + char directory[128]; + Temp_GetTempDir(&directory[0]); + static char ext[] = ".TMP"; + static char prefix[] = "nsform"; + + // We need to base our temporary file names on time, and not on sequential + // addition because of the cache not being updated when the user + // crashes and files that have been deleted are over written with + // other files; bad data. + // The 52 valid DOS file name characters are + // 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_^$~!#%&-{}@`'() + // We will only be using the first 32 of the choices. + // + // Time name format will be M+++++++.MOZ + // Where M is the single letter prefix (can be longer....) + // Where +++++++ is the 7 character time representation (a full 8.3 + // file name will be made). + // Where .MOZ is the file extension to be used. + // + // In the event that the time requested is the same time as the last call + // to this function, then the current time is incremented by one, + // as is the last time called to facilitate unique file names. + // In the event that the invented file name already exists (can't + // really happen statistically unless the clock is messed up or we + // manually incremented the time), then the times are incremented + // until an open name can be found. + // + // time_t (the time) has 32 bits, or 4,294,967,296 combinations. + // We will map the 32 bits into the 7 possible characters as follows: + // Starting with the lsb, sets of 5 bits (32 values) will be mapped + // over to the appropriate file name character, and then + // incremented to an approprate file name character. + // The left over 2 bits will be mapped into the seventh file name + // character. + // + + int i_letter, i_timechars, i_numtries = 0; + char ca_time[8]; + time_t this_call = (time_t)0; + + // We have to base the length of our time string on the length + // of the incoming prefix.... + // + i_timechars = 8 - strlen(prefix); + + // Infinite loop until the conditions are satisfied. + // There is no danger, unless every possible file name is used. + // + while(1) { + // We used to use the time to generate this. + // Now, we use some crypto to avoid bug #47027 + //RNG_GenerateGlobalRandomBytes((void *)&this_call, sizeof(this_call)); + char* output=(char *)&this_call; + size_t len = sizeof(this_call); + size_t i; + srand((unsigned int) PR_IntervalToMilliseconds(PR_IntervalNow())); + for (i=0;i> (i_letter * 5)) & 0x1F); + + // Convert any numbers to their equivalent ascii code + // + if(ca_time[i_letter] <= 9) { + ca_time[i_letter] += '0'; + } + // Convert the character to it's equivalent ascii code + // + else { + ca_time[i_letter] += 'A' - 10; + } + } + + // End the created time string. + // + ca_time[i_letter] = '\0'; + + // Reverse the time string. + // +// XXX fix this +#ifdef XP_PC + _strrev(ca_time); +#endif + // Create the fully qualified path and file name. + // + sprintf(file_buf, "%s\\%s%s%s", directory, prefix, ca_time, ext); + + // Determine if the file exists, and mark that we've tried yet + // another file name (mark to be used later). + // + // Use the system call instead of XP_Stat since we already + // know the name and we don't want recursion + // +// XXX fix this +#ifdef XP_PC + struct _stat statinfo; + int status = _stat(file_buf, &statinfo); +#else + int status = 1; +#endif + i_numtries++; + + // If it does not exists, we are successful, return the name. + // + if(status == -1) { + // TRACE("Temp file name is %s\n", file_buf); + return(file_buf); + } + + // If there is no room for additional characters in the time, + // we'll have to return NULL here, or we go infinite. + // This is a one case scenario where the requested prefix is + // actually 8 letters long. + // Infinite loops could occur with a 7, 6, 5, etc character prefixes + // if available files are all eaten up (rare to impossible), in + // which case, we should check at some arbitrary frequency of + // tries before we give up instead of attempting to Vulcanize + // this code. Live long and prosper. + // + if(i_timechars == 0) { + break; + } + else if(i_numtries == 0x00FF) { + break; + } + } + + // Requested name is thought to be impossible to generate. + // + //TRACE("No more temp file names....\n"); + return(NULL); + +} + diff --git a/mozilla/layout/html/forms/src/nsFormFrame.h b/mozilla/layout/html/forms/src/nsFormFrame.h new file mode 100644 index 00000000000..2082a269807 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsFormFrame.h @@ -0,0 +1,91 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ +#ifndef nsFormFrame_h___ +#define nsFormFrame_h___ + +#include "nsIFormManager.h" +#include "nsLeafFrame.h" +#include "nsVoidArray.h" + +class nsString; +class nsIContent; +class nsIFrame; +class nsIPresContext; +struct nsReflowMetrics; +struct nsReflowState; +class nsFormControlFrame; +class nsRadioControlFrame; +class nsIFormControlFrame; + +class nsFormFrame : public nsLeafFrame, + public nsIFormManager +{ +public: + nsFormFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsReflowMetrics& aDesiredSize, + const nsReflowState& aReflowState, + nsReflowStatus& aStatus); + virtual ~nsFormFrame(); + + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + + // nsIFormManager + + NS_IMETHOD OnReset(); + + NS_IMETHOD OnSubmit(nsIPresContext* aPresContext, nsIFrame* aFrame); + + // other methods + + void OnRadioChecked(nsRadioControlFrame& aRadio); + + void Init(nsIPresContext& aPresContext, PRBool aReinit); + + PRBool CanSubmit(nsFormControlFrame& aFrame); + + NS_IMETHOD GetMethod(PRInt32* aMethod); + NS_IMETHOD GetEnctype(PRInt32* aEnctype); + NS_IMETHOD GetTarget(nsString* aTarget); + NS_IMETHOD GetAction(nsString* aAction); + + +protected: + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredSize); + void RemoveRadioGroups(); + void ProcessAsURLEncoded(PRBool aIsPost, nsString& aData); + void ProcessAsMultipart(nsString& aData); + static const char* GetFileNameWithinPath(char* aPathName); + + // the following are temporary until nspr and/or netlib provide them + static Temp_GetTempDir(char* aTempDirName); + static char* Temp_GenerateTempFileName(PRInt32 aMaxSize, char* aBuffer); + static void Temp_GetContentType(char* aPathName, char* aContentType); + + nsVoidArray mFormControls; + nsVoidArray mRadioGroups; + PRBool mInited; + nsIFormControlFrame* mTextSubmitter; +}; + +#endif // nsFormFrame_h___ diff --git a/mozilla/layout/html/forms/src/nsHTMLForms.h b/mozilla/layout/html/forms/src/nsHTMLForms.h deleted file mode 100644 index 51d922ba814..00000000000 --- a/mozilla/layout/html/forms/src/nsHTMLForms.h +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ -#ifndef nsHTMLForms_h___ -#define nsHTMLForms_h___ - -#include "nsIHTMLContent.h" -class nsIAtom; -class nsIFormManager; - -// fix this -#define CSS_NOTSET -1 -#define ATTR_NOTSET -1 - -// Form and Form Controls - -/** - * Construct an object implementing nsIFormManager - * @param aInstancePtrResult the address at which to place the - * address of the new instance. - * @param aTag the html tag which corresponds to the nsIFormManager - * @return NS_OK if the object was successfully constructed. - */ -extern nsresult -NS_NewHTMLForm(nsIFormManager** aInstancePtrResult, - nsIAtom* aTag); - -/** - * Construct an object with behavior of an html input button - * @param aInstancePtrResult the address at which to place the - * address of the new instance. - * @param aTag the html tag which corresponds to the nsIFormManager - * @param aManager the form manager which will manage the constructed object - * @return NS_OK if the object was successfully constructed. - */ -extern nsresult -NS_NewHTMLInputButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html button to - * be used with a nsInputFile as the browse button. - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputBrowse(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html reset button - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputReset(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html submit button - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputSubmit(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html checkbox - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputCheckbox(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input file - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputFile(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input hidden - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputHidden(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input image - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputImage(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html select - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLOption(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag); - - -/** - * Construct an nsIHTMLContent with behavior of an html input password - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputPassword(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input radio - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputRadio(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html select - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLSelect(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input text - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputText(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html input text that - * serves as the text for an html input file. - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLInputFileText(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -/** - * Construct an nsIHTMLContent with behavior of an html text area - * @see NS_NewHTMLInputButton for parameter and return values - */ -extern nsresult -NS_NewHTMLTextArea(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - -#endif /* nsHTMLForms_h___ */ diff --git a/mozilla/layout/html/forms/src/nsIFormControlFrame.h b/mozilla/layout/html/forms/src/nsIFormControlFrame.h new file mode 100644 index 00000000000..98db501cae9 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsIFormControlFrame.h @@ -0,0 +1,58 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsIFormControlFrame_h___ +#define nsIFormControlFrame_h___ + +#include "nsISupports.h" +class nsFormFrame; +class nsIPresContext; +class nsString; + +// IID for the nsIFormControlFrame class +#define NS_IFORMCONTROLFRAME_IID \ +{ 0x38eb3980, 0x4d99, 0x11d2, \ + { 0x80, 0x3f, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } + +/** + * nsIFormControlFrame is the common interface for frames of form controls. It + * provides a uniform way of creating widgets, resizing, and painting. + * @see nsLeafFrame and its base classes for more info + */ +class nsIFormControlFrame : public nsISupports { + +public: + + NS_IMETHOD GetType(PRInt32* aType) const = 0; + NS_IMETHOD GetName(nsString* aName) = 0; + virtual void MouseClicked(nsIPresContext* aPresContext) = 0; + + virtual void Reset() = 0; + + virtual PRBool IsSuccessful() = 0; + + virtual PRInt32 GetMaxNumValues() = 0; + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) = 0; + + virtual void SetFormFrame(nsFormFrame* aFrame) = 0; +}; + +#endif + diff --git a/mozilla/layout/html/forms/src/nsInput.cpp b/mozilla/layout/html/forms/src/nsInput.cpp deleted file mode 100644 index 61e2b2e497a..00000000000 --- a/mozilla/layout/html/forms/src/nsInput.cpp +++ /dev/null @@ -1,910 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ -#include "nsInput.h" -#include "nsIFormManager.h" -#include "nsInputFrame.h" -#include "nsHTMLParts.h" -#include "nsHTMLContainer.h" -#include "nsIRenderingContext.h" -#include "nsIPresShell.h" -#include "nsIPresContext.h" -#include "nsIStyleContext.h" -#include "nsLeafFrame.h" -#include "nsCSSRendering.h" -#include "nsHTMLIIDs.h" -#include "nsHTMLAtoms.h" -#include "nsIView.h" -#include "nsIViewManager.h" -#include "nsCoord.h" -#include "nsDebug.h" -#include "nsIWidget.h" -#include "nsHTMLForms.h" -#include "nsStyleConsts.h" -#include "nsIDOMHTMLFormElement.h" -#include "nsITextWidget.h" -#include "nsIHTMLAttributes.h" -#include "nsGenericHTMLElement.h" - -#define ALIGN_UNSET PRUint8(-1) - -static NS_DEFINE_IID(kSupportsIID, NS_ISUPPORTS_IID); -static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); - -// Note: we inherit a base class operator new that zeros our memory -nsInput::nsInput(nsIAtom* aTag, nsIFormManager* aManager) - : nsHTMLContainer(aTag), mControl() -{ - mFormMan = aManager; - if (nsnull != mFormMan) { - NS_ADDREF(mFormMan); - mFormMan->AddFormControl(&mControl); - } - mSize = ATTR_NOTSET; - mAlign = ALIGN_UNSET; - mLastClickPoint.x = -1; - mLastClickPoint.y = -1; - mCanSubmit = PR_FALSE; -} - -nsInput::~nsInput() -{ - NS_IF_RELEASE(mWidget); - NS_IF_RELEASE(mWidgetSupports); - if (nsnull != mName) { - delete mName; - } - if (nsnull != mValue) { - delete mValue; - } - if (nsnull != mFormMan) { - // prevent mFormMan from decrementing its ref count on us - mFormMan->RemoveFormControl(&mControl, PR_FALSE); - NS_RELEASE(mFormMan); - } -} - -void nsInput::SetClickPoint(nscoord aX, nscoord aY) -{ - mLastClickPoint.x = aX; - mLastClickPoint.y = aY; -} - -PRBool nsInput::GetCanSubmit() const -{ - return mCanSubmit; -} - -void nsInput::SetCanSubmit(PRBool aFlag) -{ - mCanSubmit = aFlag; -} - -void nsInput::SetContent(const nsString& aValue) -{ - if (nsnull == mValue) { - mValue = new nsString(aValue); - } else { - *mValue = aValue; - } -} - -void -nsInput::MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - nsHTMLValue value; - - aAttributes->GetAttribute(nsHTMLAtoms::align, value); - if (eHTMLUnit_Enumerated == value.GetUnit()) { - nsStyleDisplay* display = (nsStyleDisplay*) - aContext->GetMutableStyleData(eStyleStruct_Display); - nsStyleText* text = (nsStyleText*) - aContext->GetMutableStyleData(eStyleStruct_Text); - switch (value.GetIntValue()) { - case NS_STYLE_TEXT_ALIGN_LEFT: - display->mFloats = NS_STYLE_FLOAT_LEFT; - break; - case NS_STYLE_TEXT_ALIGN_RIGHT: - display->mFloats = NS_STYLE_FLOAT_RIGHT; - break; - default: - text->mVerticalAlign.SetIntValue(value.GetIntValue(), eStyleUnit_Enumerated); - break; - } - } - nsGenericHTMLElement::MapImageAttributesInto(aAttributes, aContext, aPresContext); - nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsInput::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &nsInput::MapAttributesInto; - return NS_OK; -} - - -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); -static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); - -nsresult nsInput::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (aIID.Equals(kIFormControlIID)) { - AddRef(); - *aInstancePtr = (void*) (nsIFormControl *)&mControl; - return NS_OK; - } - if (aIID.Equals(kIDOMHTMLInputElementIID)) { - AddRef(); - *aInstancePtr = (void*) (nsIDOMHTMLInputElement *)this; - return NS_OK; - } - return nsHTMLContainer::QueryInterface(aIID, aInstancePtr); -} - -nsrefcnt nsInput::AddRef(void) -{ - PRInt32 refCnt = mRefCnt; // debugging - return nsHTMLContainer::AddRef(); -} - -PRBool nsInput::IsSuccessful(nsIFormControl* aSubmitter) const -{ - if (nsnull == mName) { - return PR_FALSE; - } - else { - return PR_TRUE; - } -} - -nsrefcnt nsInput::Release() -{ - --mRefCnt; - if (mRefCnt <= 0) { - delete this; - return 0; - } - if ((mFormMan == nsnull) || (mRefCnt > 1)) { - return mRefCnt; - } - - int numSiblings = mFormMan->GetFormControlCount(); - PRBool externalRefs = PR_FALSE; // are there external refs to dad or any siblings - if ((int)mFormMan->GetRefCount() > numSiblings) { - externalRefs = PR_TRUE; - } else { - for (int i = 0; i < numSiblings; i++) { - nsIFormControl* sibling = mFormMan->GetFormControlAt(i); - if (sibling->GetRefCount() > 1) { - externalRefs = PR_TRUE; - break; - } - } - } - - if (!externalRefs) { - mRefCnt = 0; - delete this; - return 0; - } - - return mRefCnt; -} - -PRBool -nsInput::IsHidden() -{ - return PR_FALSE; -} - -void -nsInput::SetWidget(nsIWidget* aWidget) -{ - if (aWidget != mWidget) { - NS_IF_RELEASE(mWidget); - NS_IF_ADDREF(aWidget); - mWidget = aWidget; - - NS_IF_RELEASE(mWidgetSupports); - mWidget->QueryInterface(kSupportsIID, (void**)&mWidgetSupports); - } -} - -nsrefcnt nsInput::GetRefCount() const -{ - return mRefCnt; -} - -// these do not AddRef -nsIWidget* nsInput::GetWidget() -{ - return mWidget; -} -nsISupports* nsInput::GetWidgetSupports() -{ - return mWidgetSupports; -} - -PRBool nsInput::GetContent(nsString& aResult) const -{ - if (nsnull == mValue) { - aResult.SetLength(0); - return PR_FALSE; - } else { - aResult = *mValue; - return PR_TRUE; - } -} - -void -nsInput::SetFormManager(nsIFormManager* aFormMan, PRBool aDecrementRef) -{ - if (aDecrementRef) { - NS_IF_RELEASE(mFormMan); - } - mFormMan = aFormMan; - NS_IF_ADDREF(aFormMan); -} - -nsIFormManager* -nsInput::GetFormManager() const -{ - NS_IF_ADDREF(mFormMan); - return mFormMan; -} - -/** - * Get the name associated with this form element. - * (note that form elements without names are not submitable). - */ -NS_IMETHODIMP -nsInput::GetName(nsString& aName) -{ - if ((nsnull != mName) && (0 != mName->Length())) { - aName = *mName; - } - else { - aName.SetLength(0); - } - - return NS_OK; -} - -void -nsInput::Reset() -{ -} - -PRInt32 -nsInput::GetMaxNumValues() -{ - return 0; -} - -PRBool -nsInput::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - aNumValues = 0; - return PR_FALSE; -} - -void nsInput::CacheAttribute(const nsString& aValue, nsString*& aLoc) -{ - if (nsnull == aLoc) { - aLoc = new nsString(aValue); - } else { - aLoc->SetLength(0); - aLoc->Append(aValue); - } -} - -void nsInput::CacheAttribute(const nsString& aValue, PRInt32 aMinValue, PRInt32& aLoc) -{ - PRInt32 status; - PRInt32 intVal = aValue.ToInteger(&status); - aLoc = ((NS_OK == status) && (intVal >= aMinValue)) ? intVal : aMinValue; -} - -NS_IMETHODIMP -nsInput::SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::type) { // You cannot set the type of a form element - ; - } - else if (aAttribute == nsHTMLAtoms::name) { - CacheAttribute(aValue, mName); - } - else if (aAttribute == nsHTMLAtoms::size) { - CacheAttribute(aValue, ATTR_NOTSET, mSize); - } - else if (aAttribute == nsHTMLAtoms::value) { - CacheAttribute(aValue, mValue); - } - else if (aAttribute == nsHTMLAtoms::align) { - nsHTMLValue val; - if (ParseAlignParam(aValue, val)) { - mAlign = val.GetIntValue(); - // Reflect the attribute into the syle system - return nsHTMLTagContent::SetAttribute(aAttribute, val, aNotify); // is this needed? YES - } else { - mAlign = ALIGN_UNSET; - } - } - - // XXX the following is necessary so that MapAttributesInto gets called - return nsInputSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -nsresult nsInput::GetCacheAttribute(nsString* const& aLoc, nsHTMLValue& aValue) const -{ - aValue.Reset(); - if (nsnull == aLoc) { - return NS_CONTENT_ATTR_NOT_THERE; - } - else { - aValue.SetStringValue(*aLoc); - return NS_CONTENT_ATTR_HAS_VALUE; - } -} - -nsresult -nsInput::GetCacheAttribute(PRInt32 aLoc, nsHTMLValue& aValue, - nsHTMLUnit aUnit) const -{ - aValue.Reset(); - if (aLoc <= ATTR_NOTSET) { - return NS_CONTENT_ATTR_NOT_THERE; - } - else { - if (eHTMLUnit_Pixel == aUnit) { - aValue.SetPixelValue(aLoc); - } - else if (eHTMLUnit_Empty == aUnit) { - if (PRBool(aLoc)) { - aValue.SetEmptyValue(); - } - else { - return NS_CONTENT_ATTR_NOT_THERE; - } - } - else { - aValue.SetIntValue(aLoc, aUnit); - } - - return NS_CONTENT_ATTR_HAS_VALUE; - } -} - -NS_IMETHODIMP -nsInput::GetAttribute(nsIAtom* aAttribute, PRInt32& aValue) const -{ - nsHTMLValue htmlValue; - nsresult result = GetAttribute(aAttribute, htmlValue); - if (NS_CONTENT_ATTR_HAS_VALUE == result) { - if (eHTMLUnit_Empty == htmlValue.GetUnit()) { - aValue = 1; - } - else if (eHTMLUnit_Pixel == htmlValue.GetUnit()) { - aValue = htmlValue.GetPixelValue(); - } - else { - aValue = htmlValue.GetIntValue(); - } - return NS_CONTENT_ATTR_HAS_VALUE; - } - else { - aValue = ATTR_NOTSET; - // XXX for bool values, this should return 0 - return NS_CONTENT_ATTR_NO_VALUE; - } -} - -NS_IMETHODIMP -nsInput::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aValue) const -{ - if (aAttribute == nsHTMLAtoms::type) { - nsAutoString tmp; - GetType(tmp); - if (tmp.Length() == 0) { // derivatives that don't support type return zero length string - return NS_CONTENT_ATTR_NOT_THERE; - } - else { - aValue.SetStringValue(tmp); - return NS_CONTENT_ATTR_HAS_VALUE; - } - } - else if (aAttribute == nsHTMLAtoms::name) { - return GetCacheAttribute(mName, aValue); - } - else if (aAttribute == nsHTMLAtoms::size) { - return GetCacheAttribute(mSize, aValue, eHTMLUnit_Pixel); // XXX pixel or percent?? - } - else if (aAttribute == nsHTMLAtoms::value) { - return GetCacheAttribute(mValue, aValue); - } - else if (aAttribute == nsHTMLAtoms::align) { - return GetCacheAttribute(mAlign, aValue, eHTMLUnit_Enumerated); - } - else { - return nsInputSuper::GetAttribute(aAttribute, aValue); - } -} - -PRBool nsInput::GetChecked(PRBool aGetInitialValue) const -{ - return PR_FALSE; -} - -void nsInput::SetChecked(PRBool aState, PRBool aSetInitialValue) -{ -} - -NS_IMETHODIMP -nsInput::GetDefaultValue(nsString& aDefaultValue) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::value, aDefaultValue); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetDefaultValue(const nsString& aDefaultValue) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::value, aDefaultValue, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetDefaultChecked(PRBool* aDefaultChecked) -{ - *aDefaultChecked = GetChecked(PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetDefaultChecked(PRBool aDefaultChecked) -{ - SetChecked(aDefaultChecked, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetForm(nsIDOMHTMLFormElement** aForm) -{ - static NS_DEFINE_IID(kIDOMHTMLFormElementIID, NS_IDOMHTMLFORMELEMENT_IID); - if (nsnull != mFormMan) { - return mFormMan->QueryInterface(kIDOMHTMLFormElementIID, (void **)aForm); - } - - *aForm = nsnull; - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetAccept(nsString& aAccept) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::accept, aAccept); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetAccept(const nsString& aAccept) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::accept, aAccept, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetAccessKey(nsString& aAccessKey) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::accesskey, aAccessKey); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetAccessKey(const nsString& aAccessKey) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::accesskey, aAccessKey, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetAlign(nsString& aAlign) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::align, aAlign); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetAlign(const nsString& aAlign) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::align, aAlign, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetAlt(nsString& aAlt) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::alt, aAlt); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetAlt(const nsString& aAlt) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::alt, aAlt, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetChecked(PRBool* aChecked) -{ - *aChecked = GetChecked(PR_FALSE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetChecked(PRBool aChecked) -{ - SetChecked(aChecked, PR_FALSE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetDisabled(PRBool* aDisabled) -{ - nsAutoString result; - - *aDisabled = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE == ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::disabled, result)); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetDisabled(PRBool aDisabled) -{ - if (PR_TRUE == aDisabled) { - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::disabled, "", PR_TRUE); - } - else { - UnsetAttribute(nsHTMLAtoms::disabled); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetMaxLength(PRInt32* aMaxLength) -{ - nsHTMLValue val; - - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::maxlength, val); - *aMaxLength = val.GetIntValue(); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetMaxLength(PRInt32 aMaxLength) -{ - nsHTMLValue val; - - val.SetIntValue(aMaxLength, eHTMLUnit_Integer); - ((nsHTMLTagContent *)this)->SetAttribute(nsHTMLAtoms::maxlength, val, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetName(const nsString& aName) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::name, aName, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetReadOnly(PRBool* aReadOnly) -{ - nsAutoString result; - - *aReadOnly = (PRBool)(NS_CONTENT_ATTR_HAS_VALUE == ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::readonly, result)); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetReadOnly(PRBool aReadOnly) -{ - if (PR_TRUE == aReadOnly) { - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::readonly, "", PR_TRUE); - } - else { - UnsetAttribute(nsHTMLAtoms::readonly); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetSize(nsString& aSize) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::size, aSize); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetSize(const nsString& aSize) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::size, aSize, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetSrc(nsString& aSrc) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::src, aSrc); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetSrc(const nsString& aSrc) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::src, aSrc, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetTabIndex(PRInt32* aTabIndex) -{ - nsHTMLValue val; - - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::tabindex, val); - *aTabIndex = val.GetIntValue(); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetTabIndex(PRInt32 aTabIndex) -{ - nsHTMLValue val; - - val.SetIntValue(aTabIndex, eHTMLUnit_Integer); - ((nsHTMLTagContent *)this)->SetAttribute(nsHTMLAtoms::tabindex, val, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetType(nsString& aType) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::type, aType); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetUseMap(nsString& aUseMap) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::usemap, aUseMap); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetUseMap(const nsString& aUseMap) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::usemap, aUseMap, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::GetValue(nsString& aValue) -{ - ((nsHTMLContainer *)this)->GetAttribute(nsHTMLAtoms::value, aValue); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::SetValue(const nsString& aValue) -{ - ((nsHTMLContainer *)this)->SetAttribute(nsHTMLAtoms::value, aValue, PR_TRUE); - - return NS_OK; -} - -NS_IMETHODIMP -nsInput::Blur() -{ - if (nsnull != mWidget) { - nsIWidget *mParentWidget = mWidget->GetParent(); - if (nsnull != mParentWidget) { - mParentWidget->SetFocus(); - NS_RELEASE(mParentWidget); - } - } - return NS_OK; -} - -NS_IMETHODIMP -nsInput::Focus() -{ - if (nsnull != mWidget) { - mWidget->SetFocus(); - } - return NS_OK; -} - -NS_IMETHODIMP -nsInput::Select() -{ - if (nsnull != mWidget) { - nsITextWidget *mTextWidget; - if (NS_OK == mWidget->QueryInterface(kITextWidgetIID, (void**)&mTextWidget)) { - mTextWidget->SelectAll(); - NS_RELEASE(mTextWidget); - } - } - return NS_OK; -} - -NS_IMETHODIMP -nsInput::Click() -{ - //XXX TBI - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP -nsInput::GetScriptObject(nsIScriptContext *aContext, void** aScriptObject) -{ - nsresult res = NS_OK; - if (nsnull == mScriptObject) { - res = NS_NewScriptHTMLInputElement(aContext, (nsISupports *)(nsIDOMHTMLInputElement *)this, mParent, (void**)&mScriptObject); - } - *aScriptObject = mScriptObject; - return res; -} - -//---------------------------------------------------------------------- - -#define GET_OUTER() ((nsInput*) ((char*)this - nsInput::GetOuterOffset())) - -nsInput::AggInputControl::AggInputControl() -{ -} - -nsInput::AggInputControl::~AggInputControl() -{ -} - -nsrefcnt nsInput::AggInputControl::AddRef() -{ - return GET_OUTER()->AddRef(); -} - -nsrefcnt nsInput::AggInputControl::Release() -{ - return GET_OUTER()->Release(); -} - -nsresult nsInput::AggInputControl::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - return GET_OUTER()->QueryInterface(aIID, aInstancePtr); -} - -nsresult nsInput::AggInputControl::GetName(nsString& aName) -{ - return GET_OUTER()->GetName(aName); -} - -PRInt32 nsInput::AggInputControl::GetMaxNumValues() -{ - return GET_OUTER()->GetMaxNumValues(); -} - -PRBool nsInput::AggInputControl::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - return GET_OUTER()->GetNamesValues(aMaxNumValues, aNumValues, aValues, aNames); -} - -void nsInput::AggInputControl::Reset() -{ - GET_OUTER()->Reset(); -} - -void nsInput::AggInputControl::SetFormManager(nsIFormManager* aFormMan, PRBool aDecrementRef) -{ - GET_OUTER()->SetFormManager(aFormMan, aDecrementRef); -} - -nsIFormManager* nsInput::AggInputControl::GetFormManager() const -{ - return GET_OUTER()->GetFormManager(); -} - -nsrefcnt nsInput::AggInputControl::GetRefCount() const -{ - return GET_OUTER()->GetRefCount(); -} - -PRBool nsInput::AggInputControl::GetChecked(PRBool aGetInitialValue) const -{ - return GET_OUTER()->GetChecked(aGetInitialValue); -} - -void nsInput::AggInputControl::SetChecked(PRBool aState, PRBool aSetInitialValue) -{ - GET_OUTER()->SetChecked(aState, aSetInitialValue); -} - -void nsInput::AggInputControl::GetType(nsString& aName) const -{ - GET_OUTER()->GetType(aName); -} - -PRBool nsInput::AggInputControl::IsSuccessful(nsIFormControl* aSubmitter) const -{ - return GET_OUTER()->IsSuccessful(aSubmitter); -} - -void nsInput::AggInputControl::SetContent(const nsString& aValue) -{ - GET_OUTER()->SetContent(aValue); -} - -PRBool nsInput::AggInputControl::GetContent(nsString& aResult) const -{ - return GET_OUTER()->GetContent(aResult); -} - -void nsInput::AggInputControl::SetCanSubmit(PRBool aFlag) -{ - GET_OUTER()->SetCanSubmit(aFlag); -} - -PRBool nsInput::AggInputControl::GetCanSubmit() const -{ - return GET_OUTER()->GetCanSubmit(); -} diff --git a/mozilla/layout/html/forms/src/nsInputButton.cpp b/mozilla/layout/html/forms/src/nsInputButton.cpp deleted file mode 100644 index 32e34aa26df..00000000000 --- a/mozilla/layout/html/forms/src/nsInputButton.cpp +++ /dev/null @@ -1,697 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInput.h" -#include "nsInputFrame.h" -#include "nsInputFile.h" -#include "nsHTMLParts.h" -#include "nsHTMLContainer.h" -#include "nsIRenderingContext.h" -#include "nsIPresContext.h" -#include "nsIPresShell.h" -#include "nsIStyleContext.h" -#include "nsLeafFrame.h" -#include "nsCSSRendering.h" -#include "nsHTMLIIDs.h" -#include "nsIButton.h" -#include "nsIViewManager.h" -#include "nsISupports.h" -#include "nsHTMLAtoms.h" -#include "nsIButton.h" -#include "nsIView.h" -#include "nsViewsCID.h" -#include "nsWidgetsCID.h" -#include "nsIDeviceContext.h" -#include "nsIFontCache.h" -#include "nsIFontMetrics.h" -#include "nsIFormManager.h" -#include "nsIImage.h" -#include "nsHTMLForms.h" -#include "nsHTMLImage.h" -#include "nsStyleUtil.h" -#include "nsDOMEvent.h" -#include "nsStyleConsts.h" -#include "nsIHTMLAttributes.h" -#include "nsGenericHTMLElement.h" - -enum nsButtonTagType { - kButtonTag_Button, - kButtonTag_Input -}; - -enum nsButtonType { - kButton_Button, - kButton_Reset, - kButton_Submit, - kButton_Image, - kButton_Hidden, - kButton_Browse -}; - -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); -static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); - -typedef nsInput nsInputButtonSuper; -class nsInputButton : public nsInputButtonSuper { -public: - nsInputButton (nsIAtom* aTag, nsIFormManager* aManager, - nsButtonType aType); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - NS_IMETHOD GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const; - - nsButtonType GetButtonType() { return mType; } - nsButtonTagType GetButtonTagType() { return mTagType; } - - virtual void GetDefaultLabel(nsString& aLabel); - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - virtual PRBool IsHidden(); - - virtual PRBool IsSuccessful(nsIFormControl* aSubmitter) const; - - protected: - virtual ~nsInputButton(); - - virtual void GetType(nsString& aResult) const; - - nsButtonType mType; - nsButtonTagType mTagType; -}; - -class nsInputButtonFrame : public nsInputFrame { -public: - typedef nsInputFrame nsInputButtonFrameSuper; - nsInputButtonFrame(nsIContent* aContent, nsIFrame* aParentFrame); - - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect); - - NS_IMETHOD Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus); - - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView* aView); - - virtual void MouseClicked(nsIPresContext* aPresContext); - - virtual const nsIID& GetCID(); - - virtual const nsIID& GetIID(); - - nsButtonType GetButtonType() const; - nsButtonTagType GetButtonTagType() const; - - virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; - virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; - virtual nscoord GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const; - virtual nscoord GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const; - -protected: - virtual ~nsInputButtonFrame(); - - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize); - - nsHTMLImageLoader mImageLoader; -}; - - -// nsInputButton Implementation - -nsInputButton::nsInputButton(nsIAtom* aTag, nsIFormManager* aManager, - nsButtonType aType) - : nsInput(aTag, aManager), mType(aType) -{ - nsAutoString tagName; - aTag->ToString(tagName); - mTagType = (tagName.EqualsIgnoreCase("input")) ? kButtonTag_Input : kButtonTag_Button; -} - -nsInputButton::~nsInputButton() -{ -} - -PRBool nsInputButton::IsSuccessful(nsIFormControl* aSubmitter) const -{ - if ((kButton_Hidden == mType) || ((void*)&mControl == (void*)aSubmitter)) { - return nsInputButtonSuper::IsSuccessful(aSubmitter); - } - return PR_FALSE; -} - -PRBool -nsInputButton::IsHidden() -{ - if (kButton_Hidden == mType) { - return PR_TRUE; - } - else { - return PR_FALSE; - } -} - -void nsInputButton::GetType(nsString& aResult) const -{ - aResult.SetLength(0); - - if (kButtonTag_Button == mTagType) { - aResult.Append("button"); - return; - } - - // XXX put these and other literals into statics (e.g. gBUTTON_TYPE) - switch (mType) { - case kButton_Button: - aResult.Append("button"); - break; - case kButton_Reset: - aResult.Append("reset"); - break; - case kButton_Image: - aResult.Append("image"); - break; - case kButton_Hidden: - aResult.Append("hidden"); - break; - case kButton_Browse: - aResult.Append("browse"); - break; - case kButton_Submit: - default: - aResult.Append("submit"); - break; - } -} - -void -nsInputButton::GetDefaultLabel(nsString& aString) -{ - if (kButton_Reset == mType) { - aString = "Reset"; - } else if (kButton_Submit == mType) { - aString = "Submit Query"; - } else if (kButton_Browse == mType) { - aString = "Browse..."; - } else { - aString = " "; - } -} - -PRInt32 -nsInputButton::GetMaxNumValues() -{ - if ((kButton_Submit == mType) || (kButton_Hidden == mType)) { - return 1; - } else if ((kButton_Image == mType) && (kButtonTag_Input == mTagType)) { - return 2; - } else { - return 0; - } -} - - -PRBool -nsInputButton::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - return PR_FALSE; - } - - if ((kButton_Image == mType) && (kButtonTag_Input == mTagType)) { - char buf[20]; - aNumValues = 2; - - aValues[0].SetLength(0); - sprintf(&buf[0], "%d", mLastClickPoint.x); - aValues[0].Append(&buf[0]); - - aNames[0] = *mName; - aNames[0].Append(".x"); - - aValues[1].SetLength(0); - sprintf(&buf[0], "%d", mLastClickPoint.y); - aValues[1].Append(&buf[0]); - - aNames[1] = *mName; - aNames[1].Append(".y"); - - return PR_TRUE; - } - else if (((kButton_Submit == mType) || (kButton_Hidden == mType)) && (nsnull != mValue)) { // XXX fix this in branch - aValues[0] = *mValue; - aNames[0] = *mName; - aNumValues = 1; - return PR_TRUE; - } else { - aNumValues = 0; - return PR_FALSE; - } -} - -NS_IMETHODIMP -nsInputButton::SetAttribute(nsIAtom* aAttribute, const nsString& aString, - PRBool aNotify) -{ - nsHTMLValue val; - if (ParseImageProperty(aAttribute, aString, val)) { - return nsHTMLTagContent::SetAttribute(aAttribute, val, aNotify); - } - return nsInputButtonSuper::SetAttribute(aAttribute, aString, aNotify); -} - -static void -MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - nsHTMLValue value; - aAttributes->GetAttribute(nsHTMLAtoms::type, value); - if (eHTMLUnit_String == value.GetUnit()) { // XXX thiws should be parses in AttributeToString - nsAutoString val; - value.GetStringValue(val); - if (val.EqualsIgnoreCase("image")) { - // Apply the image border as well. For form elements the color is - // always forced to blue. - static nscolor blue[4] = { - NS_RGB(0, 0, 255), - NS_RGB(0, 0, 255), - NS_RGB(0, 0, 255), - NS_RGB(0, 0, 255) - }; - nsGenericHTMLElement::MapImageBorderAttributesInto(aAttributes, aContext, aPresContext, blue); - } - } - nsInputButtonSuper::MapAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsInputButton::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &MapAttributesInto; - return NS_OK; -} - -//---------------------------------------------------------------------- -// nsInputButtonFrame Implementation - -nsresult -NS_NewInputButtonFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsInputButtonFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsInputButtonFrame::nsInputButtonFrame(nsIContent* aContent, - nsIFrame* aParentFrame) - : nsInputFrame(aContent, aParentFrame) -{ -} - -nsInputButtonFrame::~nsInputButtonFrame() -{ -} - -nsButtonType -nsInputButtonFrame::GetButtonType() const -{ - nsInputButton* button = (nsInputButton *)mContent; - return button->GetButtonType(); -} - -nsButtonTagType -nsInputButtonFrame::GetButtonTagType() const -{ - nsInputButton* button = (nsInputButton *)mContent; - return button->GetButtonTagType(); -} - -nscoord nsInputButtonFrame::GetVerticalBorderWidth(float aPixToTwip) const -{ - return NSIntPixelsToTwips(4, aPixToTwip); -} - -nscoord nsInputButtonFrame::GetHorizontalBorderWidth(float aPixToTwip) const -{ - return GetVerticalBorderWidth(aPixToTwip); -} - -nscoord nsInputButtonFrame::GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const -{ - //return NSIntPixelsToTwips(4, aPixToTwip); -#ifdef XP_PC - return (nscoord)NSToIntRound((float)aInnerHeight * 0.25f); -#endif -#ifdef XP_UNIX - return (nscoord)NSToIntRound((float)aInnerHeight * 0.50f); -#endif -} - -nscoord nsInputButtonFrame::GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const -{ -#ifdef XP_PC - if (kBackwardMode == GetMode()) { - return (nscoord)NSToIntRound(float(aInnerWidth) * 0.25f); - } else { - return NSIntPixelsToTwips(10, aPixToTwip) + 8; - } -#endif -#ifdef XP_UNIX - if (kBackwardMode == GetMode()) { - return (nscoord)NSToIntRound(float(aInnerWidth) * 0.5f); - } else { - return NSIntPixelsToTwips(20, aPixToTwip); - } -#endif -} - -NS_METHOD nsInputButtonFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect) -{ - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->mVisible) { - // let super do processing if there is no image - if (kButton_Image != GetButtonType()) { - return nsInputButtonFrameSuper::Paint(aPresContext, aRenderingContext, - aDirtyRect); - } - - // First paint background and borders - nsInputButtonFrameSuper::Paint(aPresContext, aRenderingContext, aDirtyRect); - - nsIImage* image = mImageLoader.GetImage(); - if (nsnull == image) { - // No image yet - return NS_OK; - } - - // Now render the image into our inner area (the area without the - nsRect inner; - GetInnerArea(&aPresContext, inner); - aRenderingContext.DrawImage(image, inner); - } - - return NS_OK; -} - -void -nsInputButtonFrame::MouseClicked(nsIPresContext* aPresContext) -{ - nsInputButton* button = (nsInputButton *)mContent; - nsButtonType butType = button->GetButtonType(); - nsButtonTagType butTagType = button->GetButtonTagType(); - nsIFormManager* formMan = button->GetFormManager(); - if (nsnull != formMan) { - if (kButton_Reset == butType) { - //Send DOM event - nsEventStatus mStatus; - nsEvent mEvent; - mEvent.eventStructType = NS_EVENT; - mEvent.message = NS_FORM_RESET; - mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); - - formMan->OnReset(); - } - else if ((kButton_Submit == butType) || - ((kButton_Image == butType) && (kButtonTag_Input == butTagType))) { - //NS_ADDREF(this); - //Send DOM event - nsEventStatus mStatus; - nsEvent mEvent; - mEvent.eventStructType = NS_EVENT; - mEvent.message = NS_FORM_SUBMIT; - mContent->HandleDOMEvent(*aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); - - nsIFormControl* control; - mContent->QueryInterface(kIFormControlIID, (void**)&control); - formMan->OnSubmit(aPresContext, this, control); - //NS_RELEASE(this); - NS_IF_RELEASE(control); - } - NS_RELEASE(formMan); - } else if (kButton_Browse == butType) { - ((nsInputFileFrame *)mContentParent)->MouseClicked(aPresContext); - } -} - -NS_METHOD -nsInputButtonFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - if ((kButtonTag_Input == GetButtonTagType()) && - (kButton_Image == GetButtonType())) { - nsSize ignore; - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, ignore); - AddBordersAndPadding(&aPresContext, aDesiredSize); - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } - aStatus = NS_FRAME_COMPLETE; - return NS_OK; - } - else { - return nsInputButtonFrameSuper:: - Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); - } -} - -void -nsInputButtonFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - - if (kButton_Hidden == GetButtonType()) { // there is no physical rep - aDesiredLayoutSize.width = 0; - aDesiredLayoutSize.height = 0; - aDesiredLayoutSize.ascent = 0; - aDesiredLayoutSize.descent = 0; - } - else { - if (kButton_Image == GetButtonType()) { // there is an image - // Setup url before starting the image load - nsAutoString src; - if (NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute("SRC", src)) { - mImageLoader.SetURL(src); - } - mImageLoader.GetDesiredSize(aPresContext, aReflowState, aDesiredLayoutSize); - } - else { // there is a widget - nsSize styleSize; - GetStyleSize(*aPresContext, aReflowState, styleSize); - // a browse button shares is style context with its parent nsInputFile - // it uses everything from it except width - if (kButton_Browse == GetButtonType()) { - styleSize.width = CSS_NOTSET; - } - nsSize size; - PRBool widthExplicit, heightExplicit; - PRInt32 ignore; - nsInputButton* button = (nsInputButton *)mContent; - nsAutoString defaultLabel; - button->GetDefaultLabel(defaultLabel); - nsInputDimensionSpec spec(nsHTMLAtoms::size, PR_TRUE, nsHTMLAtoms::value, - &defaultLabel, 1, PR_FALSE, nsnull, 1); - CalculateSize(aPresContext, this, styleSize, spec, size, - widthExplicit, heightExplicit, ignore); - aDesiredLayoutSize.width = size.width; - aDesiredLayoutSize.height= size.height; - } - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; - } - - aDesiredWidgetSize.width = aDesiredLayoutSize.width; - aDesiredWidgetSize.height= aDesiredLayoutSize.height; -} - - -void -nsInputButtonFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ - nsInputButton* content; - GetContent((nsIContent*&) content); - - nsIWidget* widget = nsnull; - nsIButton* button = nsnull; - nsresult result = GetWidget(aView, &widget); - - if (result == NS_OK) { - widget->QueryInterface(kIButtonIID,(void**)&button); - if (kButton_Browse != content->GetButtonType()) { // browse button always uses default - const nsStyleFont* styleFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || - (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { - nsFont widgetFont(styleFont->mFixedFont); - widgetFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight - widgetFont.size = styleFont->mFont.size; // normal font size - if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { - widgetFont.name = "Arial"; // XXX windows specific font - } - widget->SetFont(widgetFont); - } - else { - // use arial, scaled down one HTML size - // italics, decoration & variant(?) get used - nsFont widgetFont(styleFont->mFont); - widgetFont.name = "Arial"; // XXX windows specific font - widgetFont.weight = NS_FONT_WEIGHT_NORMAL; - const nsFont& normal = aPresContext->GetDefaultFont(); - PRInt32 scaler = aPresContext->GetFontScaler(); - float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); - PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(widgetFont.size, (PRInt32)normal.size, scaleFactor); - widgetFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); - widget->SetFont(widgetFont); - } - } - } - else { - NS_ASSERTION(0, "no widget in button control"); - } - - nsString value; - nsresult status = ((nsHTMLTagContent*)content)->GetAttribute(nsHTMLAtoms::value, value); - - if (button != nsnull) - { - if (NS_CONTENT_ATTR_HAS_VALUE == status) { - button->SetLabel(value); - } - else { - nsAutoString label; - content->GetDefaultLabel(label); - button->SetLabel(label); - } - } - NS_IF_RELEASE(button); - NS_IF_RELEASE(content); -} - -const nsIID& -nsInputButtonFrame::GetIID() -{ - static NS_DEFINE_IID(kButtonIID, NS_IBUTTON_IID); - return kButtonIID; -} - -const nsIID& -nsInputButtonFrame::GetCID() -{ - static NS_DEFINE_IID(kButtonCID, NS_BUTTON_CID); - return kButtonCID; -} - -nsresult -CreateButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager, - nsButtonType aType) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputButton(aTag, aManager, aType); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -nsresult -NS_NewHTMLInputButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Button); -} - -nsresult -NS_NewHTMLButton(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Button); -} - -nsresult -NS_NewHTMLInputSubmit(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Submit); -} - -nsresult -NS_NewHTMLInputReset(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Reset); -} - -nsresult -NS_NewHTMLInputImage(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Image); -} - -nsresult -NS_NewHTMLInputHidden(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - return CreateButton(aInstancePtrResult, aTag, aManager, kButton_Hidden); -} - -nsresult -NS_NewHTMLInputBrowse(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - nsresult result = CreateButton(aInstancePtrResult, aTag, aManager, kButton_Browse); - nsAutoString label; - nsInputButton* button = (nsInputButton *)*aInstancePtrResult; - button->GetDefaultLabel(label); - button->SetAttribute(nsHTMLAtoms::value, label, PR_FALSE); - return result; -} diff --git a/mozilla/layout/html/forms/src/nsInputCheckbox.cpp b/mozilla/layout/html/forms/src/nsInputCheckbox.cpp deleted file mode 100644 index 7d700a0885f..00000000000 --- a/mozilla/layout/html/forms/src/nsInputCheckbox.cpp +++ /dev/null @@ -1,321 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInputCheckbox.h" -#include "nsICheckButton.h" -#include "nsInputFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIFrame.h" -#include "nsISupports.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" -#include "nsIHTMLContent.h" -#include "nsHTMLIIDs.h" -#include "nsWidgetsCID.h" -#include "nsIView.h" -#include "nsHTMLAtoms.h" -#include "nsIStyleContext.h" -#include "nsStyleUtil.h" - - -static NS_DEFINE_IID(kICheckButtonIID, NS_ICHECKBUTTON_IID); - - -// Prototypes -nsresult -NS_NewHTMLInputCheckbox(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - - -class nsInputCheckboxFrame : public nsInputFrame { -public: - nsInputCheckboxFrame(nsIContent* aContent, nsIFrame* aParentFrame); - - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView); - - virtual const nsIID& GetCID(); - - virtual const nsIID& GetIID(); - - virtual void MouseClicked(nsIPresContext* aPresContext); - -protected: - virtual ~nsInputCheckboxFrame(); - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize); -}; - -nsresult -NS_NewInputCheckboxFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsInputCheckboxFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsInputCheckboxFrame::nsInputCheckboxFrame(nsIContent* aContent, nsIFrame* aParentFrame) - : nsInputFrame(aContent, aParentFrame) -{ -} - -nsInputCheckboxFrame::~nsInputCheckboxFrame() -{ -} - -const nsIID& -nsInputCheckboxFrame::GetIID() -{ - static NS_DEFINE_IID(kCheckboxIID, NS_ICHECKBUTTON_IID); - return kCheckboxIID; -} - -const nsIID& -nsInputCheckboxFrame::GetCID() -{ - static NS_DEFINE_IID(kCheckboxCID, NS_CHECKBUTTON_CID); - return kCheckboxCID; -} - -void -nsInputCheckboxFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - float p2t = aPresContext->GetPixelsToTwips(); -#ifdef XP_PC - aDesiredWidgetSize.width = NSIntPixelsToTwips(12, p2t); - aDesiredWidgetSize.height = NSIntPixelsToTwips(12, p2t); -#endif -#ifdef XP_PC - aDesiredWidgetSize.width = NSIntPixelsToTwips(20, p2t); - aDesiredWidgetSize.height = NSIntPixelsToTwips(20, p2t); -#endif - aDesiredLayoutSize.width = aDesiredWidgetSize.width; - aDesiredLayoutSize.height = aDesiredWidgetSize.height; - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; -} - -void -nsInputCheckboxFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ - // get the intial state of the checkbox - nsInputCheckbox* content = (nsInputCheckbox *)mContent; // this must be an nsCheckbox - nsHTMLValue value; - nsresult result = content->GetAttribute(nsHTMLAtoms::checked, value); - PRBool checked = (result != NS_CONTENT_ATTR_NOT_THERE) ? PR_TRUE : PR_FALSE; - - // set the widget to the initial state - nsIWidget* widget = nsnull; - nsICheckButton* checkbox = nsnull; - - if (NS_OK == GetWidget(aView, &widget)) { - widget->QueryInterface(GetIID(),(void**)&checkbox); - checkbox->SetState(checked); - - const nsStyleColor* color = - nsStyleUtil::FindNonTransparentBackground(mStyleContext); - - if (nsnull != color) { - widget->SetBackgroundColor(color->mBackgroundColor); - } - else { - widget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); - } - - NS_IF_RELEASE(checkbox); - NS_IF_RELEASE(widget); - } -} - -void -nsInputCheckboxFrame::MouseClicked(nsIPresContext* aPresContext) -{ - nsIWidget* widget = nsnull; - nsICheckButton* checkbox = nsnull; - nsIView* view; - GetView(view); - if (NS_OK == GetWidget(view, &widget)) { - widget->QueryInterface(GetIID(),(void**)&checkbox); - PRBool oldState; - checkbox->GetState(oldState); - PRBool newState = oldState ? PR_FALSE : PR_TRUE; - checkbox->SetState(newState); - NS_IF_RELEASE(checkbox); - NS_IF_RELEASE(widget); - } -} - - - -// nsInputCheckbox - -nsInputCheckbox::nsInputCheckbox(nsIAtom* aTag, nsIFormManager* aManager) - : nsInput(aTag, aManager) -{ - mChecked = PR_FALSE; -} - -nsInputCheckbox::~nsInputCheckbox() -{ -} - - -static void -MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - float p2t = aPresContext->GetPixelsToTwips(); - nscoord pad = NSIntPixelsToTwips(3, p2t); - - // add left and right padding around the radio button via css - nsStyleSpacing* spacing = (nsStyleSpacing*) aContext->GetMutableStyleData(eStyleStruct_Spacing); - if (eStyleUnit_Null == spacing->mMargin.GetLeftUnit()) { - nsStyleCoord left(pad); - spacing->mMargin.SetLeft(left); - } - if (eStyleUnit_Null == spacing->mMargin.GetRightUnit()) { - nsStyleCoord right(NSIntPixelsToTwips(5, p2t)); - spacing->mMargin.SetRight(right); - } - // add bottom padding if backward mode - // XXX why isn't this working? - - nsCompatibility mode; - aPresContext->GetCompatibilityMode(mode); - if (eCompatibility_NavQuirks == mode) { - if (eStyleUnit_Null == spacing->mMargin.GetBottomUnit()) { - nsStyleCoord bottom(pad); - spacing->mMargin.SetBottom(bottom); - } - } - nsInput::MapAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsInputCheckbox::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &MapAttributesInto; - return NS_OK; -} - -PRInt32 -nsInputCheckbox::GetMaxNumValues() -{ - return 1; -} - - -PRBool -nsInputCheckbox::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - return PR_FALSE; - } - - nsIWidget* widget = GetWidget(); - nsICheckButton* checkBox = nsnull; - if (widget != nsnull && NS_OK == widget->QueryInterface(kICheckButtonIID,(void**)&checkBox)) - { - PRBool state = PR_FALSE; - checkBox->GetState(state); - if(PR_TRUE != state) { - return PR_FALSE; - } - - if (nsnull == mValue) { - aValues[0] = "on"; - } else { - aValues[0] = *mValue; - } - aNames[0] = *mName; - aNumValues = 1; - NS_RELEASE(checkBox); - return PR_TRUE; - } - return PR_FALSE; -} - -void -nsInputCheckbox::Reset() -{ - nsIWidget* widget = GetWidget(); - nsICheckButton* checkBox = nsnull; - if (widget != nsnull && NS_OK == widget->QueryInterface(kICheckButtonIID,(void**)&checkBox)) - { - checkBox->SetState(mChecked); - NS_RELEASE(checkBox); - } -} - -void nsInputCheckbox::GetType(nsString& aResult) const -{ - aResult = "checkbox"; -} - -NS_IMETHODIMP -nsInputCheckbox::SetAttribute(nsIAtom* aAttribute, - const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::checked) { - mChecked = PR_TRUE; - } - return nsInputCheckboxSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -NS_IMETHODIMP -nsInputCheckbox::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const -{ - aResult.Reset(); - if (aAttribute == nsHTMLAtoms::checked) { - return GetCacheAttribute(mChecked, aResult, eHTMLUnit_Empty); - } - else { - return nsInputCheckboxSuper::GetAttribute(aAttribute, aResult); - } -} - -nsresult -NS_NewHTMLInputCheckbox(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputCheckbox(aTag, aManager); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - diff --git a/mozilla/layout/html/forms/src/nsInputCheckbox.h b/mozilla/layout/html/forms/src/nsInputCheckbox.h deleted file mode 100644 index cfa642a4d6b..00000000000 --- a/mozilla/layout/html/forms/src/nsInputCheckbox.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#ifndef nsInputCheckbox_h___ -#define nsInputCheckbox_h___ - -#include "nsInput.h" -class nsIAtom; -class nsString; - -class nsInputCheckbox : public nsInput { -public: - typedef nsInput nsInputCheckboxSuper; - nsInputCheckbox (nsIAtom* aTag, nsIFormManager* aManager); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - - NS_IMETHOD GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const; - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - NS_IMETHOD GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const; - - virtual void Reset(); - -protected: - virtual ~nsInputCheckbox(); - - virtual void GetType(nsString& aResult) const; - - PRBool mChecked; // initial checked flag value -}; - -#endif diff --git a/mozilla/layout/html/forms/src/nsInputFile.cpp b/mozilla/layout/html/forms/src/nsInputFile.cpp deleted file mode 100644 index 6834c887a68..00000000000 --- a/mozilla/layout/html/forms/src/nsInputFile.cpp +++ /dev/null @@ -1,314 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInput.h" -#include "nsInputFrame.h" -#include "nsInputFile.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" -#include "nsIHTMLContent.h" -#include "nsHTMLIIDs.h" -#include "nsHTMLAtoms.h" -#include "nsHTMLForms.h" -#include "nsIFileWidget.h" -#include "nsITextWidget.h" -#include "nsWidgetsCID.h" -#include "nsRepository.h" -#include "nsIView.h" -#include "nsHTMLParts.h" - -PRInt32 nsInputFileFrame::gSpacing = 40; -nsString* nsInputFile::gFILE_TYPE = new nsString("file"); - -nsresult -NS_NewInputFileFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsInputFileFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsInputFileFrame::nsInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame) - : nsHTMLContainerFrame(aContent, aParentFrame) -{ -} - -nsInputFileFrame::~nsInputFileFrame() -{ -} - -// XXX this should be removed when nsView exposes it -nsIWidget* -GetWindowTemp(nsIView *aView) -{ - nsIWidget *window = nsnull; - - nsIView *ancestor = aView; - while (nsnull != ancestor) { - ancestor->GetWidget(window); - if (nsnull != window) { - return window; - } - ancestor->GetParent(ancestor); - } - return nsnull; -} - -static NS_DEFINE_IID(kCFileWidgetCID, NS_FILEWIDGET_CID); -static NS_DEFINE_IID(kIFileWidgetIID, NS_IFILEWIDGET_IID); -static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); - -// this is in response to the MouseClick from the containing browse button -// XXX still need to get filters from accept attribute -void nsInputFileFrame::MouseClicked(nsIPresContext* aPresContext) -{ - nsInputFrame* textFrame = (nsInputFrame *)mFirstChild; - nsITextWidget* textWidget; - nsIView* textView; - textFrame->GetView(textView); - if (nsnull == textView) { - return; - } - if (NS_OK != textFrame->GetWidget(textView, (nsIWidget **)&textWidget)) { - return; - } - nsIView* parentView; - textView->GetParent(parentView); - nsIWidget* parentWidget = GetWindowTemp(parentView); - - nsIFileWidget *fileWidget; - - nsString title("FileWidget Title mode = save"); - nsRepository::CreateInstance(kCFileWidgetCID, nsnull, kIFileWidgetIID, (void**)&fileWidget); - - nsString titles[] = {"all files"}; - nsString filters[] = {"*.*"}; - fileWidget->SetFilterList(1, titles, filters); - - fileWidget->Create(parentWidget, title, eMode_load, nsnull, nsnull); - PRUint32 result = fileWidget->Show(); - - if (result) { - PRUint32 size; - nsString fileName; - fileWidget->GetFile(fileName); - ((nsITextWidget *)textWidget)->SetText(fileName,size); - } - NS_RELEASE(fileWidget); - NS_RELEASE(parentWidget); - NS_RELEASE(textWidget); -} - - -NS_IMETHODIMP nsInputFileFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - nsInputFile* content = (nsInputFile*)mContent; - nsIFrame* childFrame; - - if (nsnull == mFirstChild) { - // XXX This code should move to Init(), someday when the frame construction - // changes are all done and Init() is always getting called... - nsInputText* textField = content->GetTextField(); - nsInput* browseButton = content->GetBrowseButton(); - if ((nsnull != textField) && (nsnull != browseButton)) { - NS_NewInputTextFrame(textField, this, childFrame); - childFrame->SetStyleContext(&aPresContext, mStyleContext); - mFirstChild = childFrame; - NS_NewInputButtonFrame(browseButton, this, childFrame); - childFrame->SetStyleContext(&aPresContext, mStyleContext); - mFirstChild->SetNextSibling(childFrame); - mChildCount = 2; - } - NS_IF_RELEASE(textField); - NS_IF_RELEASE(browseButton); - } - - nsSize maxSize = aReflowState.maxSize; - nsReflowMetrics desiredSize = aDesiredSize; - aDesiredSize.width = gSpacing; - aDesiredSize.height = 0; - childFrame = mFirstChild; - nsPoint offset(0,0); - while (nsnull != childFrame) { // reflow, place, size the children - nsReflowState reflowState(childFrame, aReflowState, maxSize); - childFrame->WillReflow(aPresContext); - nsresult result = childFrame->Reflow(aPresContext, desiredSize, reflowState, aStatus); - NS_ASSERTION(NS_FRAME_IS_COMPLETE(aStatus), "bad status"); - nsRect rect(offset.x, offset.y, desiredSize.width, desiredSize.height); - childFrame->SetRect(rect); - maxSize.width -= desiredSize.width; - aDesiredSize.width += desiredSize.width; - aDesiredSize.height = desiredSize.height; - childFrame->GetNextSibling(childFrame); - offset.x += desiredSize.width + gSpacing; - } - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } - - aStatus = NS_FRAME_COMPLETE; - return NS_OK; -} - -PRIntn -nsInputFileFrame::GetSkipSides() const -{ - return 0; -} - - -//---------------------------------------------------------------------- -// nsInputFile - -nsInputFile::nsInputFile(nsIAtom* aTag, nsIFormManager* aManager) - : nsInput(aTag, aManager) -{ - mTextField = nsnull; - mBrowseButton = nsnull; -} - -nsInputFile::~nsInputFile() -{ - NS_IF_RELEASE(mTextField); - NS_IF_RELEASE(mBrowseButton); -} - -nsInputText* nsInputFile::GetTextField() -{ - NS_IF_ADDREF(mTextField); - return mTextField; -} - -void nsInputFile::SetTextField(nsInputText* aTextField) -{ - NS_IF_RELEASE(mTextField); - NS_IF_ADDREF(aTextField); - mTextField = aTextField; -} - -nsInput* nsInputFile::GetBrowseButton() -{ - NS_IF_ADDREF(mBrowseButton); - return mBrowseButton; -} - -void nsInputFile::SetBrowseButton(nsInput* aBrowseButton) -{ - NS_IF_RELEASE(mBrowseButton); - NS_IF_ADDREF(aBrowseButton); - mBrowseButton = aBrowseButton; -} - -void nsInputFile::GetType(nsString& aResult) const -{ - aResult = "file"; -} - -PRInt32 -nsInputFile::GetMaxNumValues() -{ - return 1; -} - -PRBool -nsInputFile::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - return PR_FALSE; - } - // use our name and the text widgets value - aNames[0] = *mName; - nsIWidget* widget = mTextField->GetWidget(); - nsITextWidget* textWidget = nsnull; - - - if (widget != nsnull && NS_OK == widget->QueryInterface(kITextWidgetIID,(void**)textWidget)) - { - PRUint32 actualSize; - textWidget->GetText(aValues[0], 0, actualSize); - aNumValues = 1; - NS_RELEASE(textWidget); - return PR_TRUE; - } - return PR_FALSE; -} - -NS_IMETHODIMP -nsInputFile::SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify) -{ - // get the text and set its relevant attributes - if ((aAttribute == nsHTMLAtoms::size) || (aAttribute == nsHTMLAtoms::maxlength) || - (aAttribute == nsHTMLAtoms::value) || - (aAttribute == nsHTMLAtoms::disabled) || (aAttribute == nsHTMLAtoms::readonly)) - { - mTextField->SetAttribute(aAttribute, aValue, aNotify); - } - - return nsInputFileSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -nsresult -NS_NewHTMLInputFile(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsInputFile* inputFile = new nsInputFile(aTag, aManager); - if (nsnull == inputFile) { - return NS_ERROR_OUT_OF_MEMORY; - } - nsInputText* textField; - // pass in a null form manager, since this text field is not part of the content model - nsresult status = NS_NewHTMLInputText((nsIHTMLContent**)&textField, aTag, nsnull); - if (NS_OK != status) { - return NS_ERROR_OUT_OF_MEMORY; - } - inputFile->SetTextField(textField); - NS_RELEASE(textField); - - nsInput* browseButton; - // pass in a null form manager, since this browse button is not part of the content model - status = NS_NewHTMLInputBrowse((nsIHTMLContent**)&browseButton, aTag, nsnull); - if (NS_OK != status) { - return NS_ERROR_OUT_OF_MEMORY; - } - inputFile->SetBrowseButton(browseButton); - NS_RELEASE(browseButton); - - return inputFile->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - diff --git a/mozilla/layout/html/forms/src/nsInputFile.h b/mozilla/layout/html/forms/src/nsInputFile.h deleted file mode 100644 index 0d7a18e29e0..00000000000 --- a/mozilla/layout/html/forms/src/nsInputFile.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#ifndef nsInputFile_h___ -#define nsInputFile_h___ - -#include "nsInput.h" -#include "nsHTMLContainerFrame.h" -#include "nsInputFrame.h" -#include "nsInputText.h" - -class nsIAtom; -class nsString; - -// this class definition will move to nsInputFile.cpp - -class nsInputFileFrame : public nsHTMLContainerFrame { -public: - nsInputFileFrame(nsIContent* aContent, nsIFrame* aParentFrame); - NS_IMETHOD Reflow(nsIPresContext& aCX, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus); - virtual void MouseClicked(nsIPresContext* aPresContext); - static PRInt32 gSpacing; - -protected: - virtual ~nsInputFileFrame(); - virtual PRIntn GetSkipSides() const; -}; - -class nsInputFile : public nsInput { -public: - typedef nsInput nsInputFileSuper; - static nsString* gFILE_TYPE; - - nsInputFile (nsIAtom* aTag, nsIFormManager* aManager); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - virtual PRInt32 GetMaxNumValues(); - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - nsInputText* GetTextField(); - void SetTextField(nsInputText* aTextField); - nsInput* GetBrowseButton(); - void SetBrowseButton(nsInput* aBrowseButton); - -protected: - virtual ~nsInputFile(); - - virtual void GetType(nsString& aResult) const; - nsInputText* mTextField; - nsInput* mBrowseButton; // XXX don't have type safety until nsInputButton is exposed - - //PRInt32 mMaxLength; -}; - -#endif - - diff --git a/mozilla/layout/html/forms/src/nsInputFrame.cpp b/mozilla/layout/html/forms/src/nsInputFrame.cpp deleted file mode 100644 index cd1fffbf907..00000000000 --- a/mozilla/layout/html/forms/src/nsInputFrame.cpp +++ /dev/null @@ -1,693 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInput.h" -#include "nsInputFrame.h" -#include "nsHTMLParts.h" -#include "nsHTMLContainer.h" -#include "nsIRenderingContext.h" -#include "nsIPresShell.h" -#include "nsIPresContext.h" -#include "nsIStyleContext.h" -#include "nsLeafFrame.h" -#include "nsCSSRendering.h" -#include "nsHTMLIIDs.h" -#include "nsIView.h" -#include "nsIViewManager.h" -#include "nsCoord.h" -#include "nsWidgetsCID.h" -#include "nsViewsCID.h" -#include "nsRepository.h" -#include "nsGUIEvent.h" -#include "nsDOMEvent.h" -#include "nsIFontCache.h" -#include "nsIFontMetrics.h" -#include "nsIFormManager.h" -#include "nsIDeviceContext.h" -#include "nsHTMLAtoms.h" -#include "nsIButton.h" // remove this when GetCID is pure virtual -#include "nsICheckButton.h" //remove this -#include "nsITextWidget.h" //remove this -#include "nsISupports.h" -#include "nsHTMLForms.h" -#include "nsStyleConsts.h" -#include "nsUnitConversion.h" -#include "nsCSSLayout.h" -#include "nsStyleUtil.h" - - -static NS_DEFINE_IID(kIWidgetIID, NS_IWIDGET_IID); - - -nsInputFrame::nsInputFrame(nsIContent* aContent, nsIFrame* aParentFrame) - : nsInputFrameSuper(aContent, aParentFrame) -{ - mLastMouseState = eMouseNone; - mDidInit = PR_FALSE; -} - -nsInputFrame::~nsInputFrame() -{ - //printf("nsInputFrame::~nsInputFrame \n"); -} - -NS_METHOD nsInputFrame::SetRect(const nsRect& aRect) -{ - return nsInputFrameSuper::SetRect(aRect); -} - -nsFormRenderingMode nsInputFrame::GetMode() const -{ - nsInput* content = (nsInput *)mContent; - nsIFormManager* formMan = content->GetFormManager(); - if (formMan) { - nsFormRenderingMode mode = formMan->GetMode(); - NS_RELEASE(formMan); - return mode; - } - else { - return kBackwardMode; - } -} - -nscoord nsInputFrame::GetScrollbarWidth(float aPixToTwip) -{ - return NSIntPixelsToTwips(19, aPixToTwip); // XXX this is windows -} - -nscoord nsInputFrame::GetVerticalBorderWidth(float aPixToTwip) const -{ - return NSIntPixelsToTwips(3, aPixToTwip); -} - -nscoord nsInputFrame::GetHorizontalBorderWidth(float aPixToTwip) const -{ - return GetVerticalBorderWidth(aPixToTwip); -} - -nscoord nsInputFrame::GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const -{ - return NSIntPixelsToTwips(3, aPixToTwip); -} - -nscoord nsInputFrame::GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const -{ - return GetVerticalInsidePadding(aPixToTwip, aInnerWidth); -} - -// XXX it would be cool if form element used our rendering sw, then -// they could be blended, and bordered, and so on... -NS_METHOD -nsInputFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect) -{ - const nsStyleDisplay* disp = - (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); - - if (disp->mVisible) { - // Make sure the widget is visible if it isn't currently visible - nsIView* view = nsnull; - GetView(view); - if (nsnull != view) { - if (PR_FALSE == mDidInit) { - nsIFormManager* formMan = ((nsInput*)mContent)->GetFormManager(); - if (formMan) { - formMan->Init(PR_FALSE); - NS_RELEASE(formMan); - } - PostCreateWidget(&aPresContext, view); - mDidInit = PR_TRUE; - } -// SetViewVisiblity(&aPresContext, PR_TRUE); - } - // Point borders/padding if any - return nsInputFrameSuper::Paint(aPresContext, aRenderingContext, aDirtyRect); - } - return NS_OK; -} - -//don't call this. MMP -void -nsInputFrame::SetViewVisiblity(nsIPresContext* aPresContext, PRBool aShow) -{ - nsIView* view = nsnull; - GetView(view); - if (nsnull != view) { - nsIWidget* widget; - nsresult result = GetWidget(view, &widget); - if (NS_OK == result) { - // initially the widget was created as hidden - nsViewVisibility newVisibility = - aShow ? nsViewVisibility_kShow : nsViewVisibility_kHide; - nsViewVisibility currentVisibility; - view->GetVisibility(currentVisibility); - if (newVisibility != currentVisibility) { - // this only inits the 1st time - // XXX kipp says: this is yucky; init on first visibility seems lame - // XXX is this even called - nsIFormManager* formMan = ((nsInput*)mContent)->GetFormManager(); - if (formMan) { - formMan->Init(PR_FALSE); - NS_RELEASE(formMan); - } - view->SetVisibility(newVisibility); - PostCreateWidget(aPresContext, view); - } - NS_IF_RELEASE(widget); - } - } -} - -PRBool -nsInputFrame::BoundsAreSet() -{ - if ((0 != mRect.width) || (0 != mRect.height)) { - return PR_TRUE; - } else { - return PR_FALSE; - } -} - -PRBool -nsInputFrame::IsHidden() -{ - nsInput* content = (nsInput *)mContent; - return content->IsHidden(); -} - -void -nsInputFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - // get the css size and let the frame use or override it - nsSize styleSize; - GetStyleSize(*aPresContext, aReflowState, styleSize); - - // subclasses should always override this method, but if not and no css, make it small - aDesiredLayoutSize.width = (styleSize.width > CSS_NOTSET) ? styleSize.width : 144; - aDesiredLayoutSize.height = (styleSize.height > CSS_NOTSET) ? styleSize.height : 144; - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; - aDesiredWidgetSize.width = aDesiredLayoutSize.width; - aDesiredWidgetSize.height = aDesiredLayoutSize.height; -} - -void -nsInputFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredSize) -{ - nsSize ignore; - GetDesiredSize(aPresContext, aReflowState, aDesiredSize, ignore); -} - -NS_IMETHODIMP -nsInputFrame::DidReflow(nsIPresContext& aPresContext, - nsDidReflowStatus aStatus) -{ - nsresult rv = nsInputFrameSuper::DidReflow(aPresContext, aStatus); - - // The view is created hidden; once we have reflowed it and it has been - // positioned then we show it. - if (NS_FRAME_REFLOW_FINISHED == aStatus) { - nsIView* view = nsnull; - GetView(view); - if (nsnull != view) { - view->SetVisibility(nsViewVisibility_kShow); - } - } - return rv; -} - -NS_METHOD -nsInputFrame::Reflow(nsIPresContext& aPresContext, - nsReflowMetrics& aDesiredSize, - const nsReflowState& aReflowState, - nsReflowStatus& aStatus) -{ - nsIView* view = nsnull; - GetView(view); - if (nsnull == view) { - static NS_DEFINE_IID(kViewCID, NS_VIEW_CID); - static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); - - // make sure the style context is set - if (nsnull == mStyleContext) { - GetStyleContext(&aPresContext, mStyleContext); - } - nsresult result = - nsRepository::CreateInstance(kViewCID, nsnull, kIViewIID, - (void **)&view); - if (NS_OK != result) { - NS_ASSERTION(0, "Could not create view for button"); - aStatus = NS_FRAME_NOT_COMPLETE; - return result; - } - nsIPresShell *presShell = aPresContext.GetShell(); // need to release - nsIViewManager *viewMan = presShell->GetViewManager(); // need to release - NS_RELEASE(presShell); - - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, mWidgetSize); - - //nsRect boundBox(0, 0, mWidgetSize.width, mWidgetSize.height); - nsRect boundBox(0, 0, aDesiredSize.width, aDesiredSize.height); - - nsIFrame* parWithView; - nsIView *parView; - - GetParentWithView(parWithView); - parWithView->GetView(parView); - - const nsIID& id = GetCID(); - nsWidgetInitData* initData = GetWidgetInitData(aPresContext); // needs to be deleted - // initialize the view as hidden since we don't know the (x,y) until Paint - result = view->Init(viewMan, boundBox, parView, &id, initData, - nsnull, 0, nsnull, - 1.0f, nsViewVisibility_kHide); - if (nsnull != initData) { - delete(initData); - } - if (NS_OK != result) { - NS_ASSERTION(0, "widget initialization failed"); - aStatus = NS_FRAME_NOT_COMPLETE; - return NS_OK; - } - - // set the content's widget, so it can get content modified by the widget - nsIWidget *widget; - result = GetWidget(view, &widget); - if (NS_OK == result) { - nsInput* content = (nsInput *)mContent; // change this cast to QueryInterface - content->SetWidget(widget); - NS_IF_RELEASE(widget); - } else { - NS_ASSERTION(0, "could not get widget"); - } - - viewMan->InsertChild(parView, view, 0); - - SetView(view); - NS_IF_RELEASE(viewMan); - } - else { - GetDesiredSize(&aPresContext, aReflowState, aDesiredSize, mWidgetSize); - - // If we are being reflowed and have a view, hide the view until - // we are told to paint (which is when our location will have - // stabilized). -// SetViewVisiblity(aPresContext, PR_FALSE); - } - - aDesiredSize.ascent = aDesiredSize.height; - aDesiredSize.descent = 0; - - if (nsnull != aDesiredSize.maxElementSize) { - aDesiredSize.maxElementSize->width = aDesiredSize.width; - aDesiredSize.maxElementSize->height = aDesiredSize.height; - } - - aStatus = NS_FRAME_COMPLETE; - return NS_OK; -} - -nsWidgetInitData* -nsInputFrame::GetWidgetInitData(nsIPresContext& aPresContext) -{ - return nsnull; -} - -void -nsInputFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ -} - -nsresult -nsInputFrame::GetWidget(nsIView* aView, nsIWidget** aWidget) -{ - nsIWidget* widget; - aView->GetWidget(widget); - nsresult result; - - if (nsnull == widget) { - aWidget = nsnull; - result = NS_ERROR_FAILURE; - - } else { - const nsIID id = GetIID(); - - result = widget->QueryInterface(kIWidgetIID, (void**)aWidget); - if (NS_FAILED(result)) { - NS_ASSERTION(0, "The widget interface is invalid"); // need to print out more details of the widget - } - NS_RELEASE(widget); - } - - return result; -} - -const nsIID& -nsInputFrame::GetIID() -{ - static NS_DEFINE_IID(kButtonIID, NS_IBUTTON_IID); - return kButtonIID; -} - -const nsIID& -nsInputFrame::GetCID() -{ - static NS_DEFINE_IID(kButtonCID, NS_BUTTON_CID); - return kButtonCID; -} - -NS_METHOD nsInputFrame::HandleEvent(nsIPresContext& aPresContext, - nsGUIEvent* aEvent, - nsEventStatus& aEventStatus) -{ - if (nsnull != mContent) { - mContent->HandleDOMEvent(aPresContext, (nsEvent*)aEvent, nsnull, DOM_EVENT_INIT, aEventStatus); - } - - // make sure that the widget in the event is this - // XXX if there is no view, it could be an image button. Unfortunately, - // every image button will get every event. - nsIView* view; - GetView(view); - if (view) { - nsInput* content = (nsInput *)mContent; - if (content->GetWidget() != aEvent->widget) { - aEventStatus = nsEventStatus_eIgnore; - return NS_OK; - } - } - - //printf(" %d %d %d %d (%d,%d) \n", this, aEvent->widget, aEvent->widgetSupports, - // aEvent->message, aEvent->point.x, aEvent->point.y); - - switch (aEvent->message) { - case NS_MOUSE_ENTER: - mLastMouseState = eMouseEnter; - break; - case NS_MOUSE_LEFT_BUTTON_DOWN: - mLastMouseState = - (eMouseEnter == mLastMouseState) ? eMouseDown : eMouseNone; - break; - case NS_MOUSE_LEFT_BUTTON_UP: - if (eMouseDown == mLastMouseState) { - /*nsIView* view = GetView(); - nsIWidget *widget = view->GetWindow(); - widget->SetFocus(); - NS_RELEASE(widget); - NS_RELEASE(view); */ - float t2p = aPresContext.GetTwipsToPixels(); - ((nsInput*)mContent)->SetClickPoint(NSTwipsToIntPixels(aEvent->point.x, t2p), - NSTwipsToIntPixels(aEvent->point.y, t2p)); - - nsEventStatus mStatus = nsEventStatus_eIgnore; - nsMouseEvent mEvent; - mEvent.eventStructType = NS_MOUSE_EVENT; - mEvent.message = NS_MOUSE_LEFT_CLICK; - mContent->HandleDOMEvent(aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); - - if (nsEventStatus_eConsumeNoDefault != mStatus) { - MouseClicked(&aPresContext); - //return PR_FALSE; - } - } - mLastMouseState = eMouseEnter; - break; - case NS_MOUSE_EXIT: - mLastMouseState = eMouseNone; - break; - case NS_KEY_DOWN: - if (NS_KEY_EVENT == aEvent->eventStructType) { - nsKeyEvent* keyEvent = (nsKeyEvent*)aEvent; - if (NS_VK_RETURN == keyEvent->keyCode) { - EnterPressed(aPresContext); - } - } - break; - } - aEventStatus = nsEventStatus_eConsumeDoDefault; - return NS_OK; -} - -void nsInputFrame::GetStyleSize(nsIPresContext& aPresContext, - const nsReflowState& aReflowState, - nsSize& aSize) -{ - PRIntn ss = nsCSSLayout::GetStyleSize(&aPresContext, aReflowState, aSize); - if (0 == (ss & NS_SIZE_HAS_WIDTH)) { - aSize.width = CSS_NOTSET; - } - if (0 == (ss & NS_SIZE_HAS_HEIGHT)) { - aSize.height = CSS_NOTSET; - } -} - -nscoord -nsInputFrame::GetTextSize(nsIPresContext& aPresContext, nsInputFrame* aFrame, - const nsString& aString, nsSize& aSize) -{ - nsFont font = aPresContext.GetDefaultFixedFont(); - aFrame->GetFont(&aPresContext, font); - //printf("\n GetTextSize %s", aString.ToNewCString()); - nsIDeviceContext* deviceContext = aPresContext.GetDeviceContext(); - nsIFontCache* fontCache; - deviceContext->GetFontCache(fontCache); - - nsIFontMetrics* fontMet; - fontCache->GetMetricsFor(font, fontMet); - fontMet->GetWidth(aString, aSize.width); - fontMet->GetHeight(aSize.height); - - nscoord charWidth; - fontMet->GetWidth("W", charWidth); - - NS_RELEASE(fontMet); - NS_RELEASE(fontCache); - NS_RELEASE(deviceContext); - - return charWidth; -} - -nscoord -nsInputFrame::GetTextSize(nsIPresContext& aPresContext, nsInputFrame* aFrame, - PRInt32 aNumChars, nsSize& aSize) -{ - nsAutoString val; - char repChar = (kBackwardMode == aFrame->GetMode()) ? '%' : 'e'; - for (int i = 0; i < aNumChars; i++) { - val += repChar; - } - return GetTextSize(aPresContext, aFrame, val, aSize); -} - -PRInt32 -nsInputFrame::CalculateSize (nsIPresContext* aPresContext, nsInputFrame* aFrame, - const nsSize& aCSSSize, nsInputDimensionSpec& aSpec, - nsSize& aBounds, PRBool& aWidthExplicit, - PRBool& aHeightExplicit, nscoord& aRowHeight) -{ - nscoord charWidth = 0; - PRInt32 numRows = ATTR_NOTSET; - aWidthExplicit = PR_FALSE; - aHeightExplicit = PR_FALSE; - - /* XXX For some reason on Win95 Paint doesn't initially get called */ - /* for elements that are out of the view, so we weren't calling */ - /* PostCreateWidget. I'm calling it here as a work-around */ - nsIView* view = nsnull; - aFrame->GetView(view); - if (nsnull != view) { - if (PR_FALSE == aFrame->mDidInit) { - nsIFormManager* formMan = ((nsInput*)aFrame->mContent)->GetFormManager(); - if (formMan) { - formMan->Init(PR_FALSE); - aFrame->PostCreateWidget(aPresContext, view); - aFrame->mDidInit = PR_TRUE; - NS_RELEASE(formMan); - } - } - } - - aBounds.width = CSS_NOTSET; - aBounds.height = CSS_NOTSET; - nsSize textSize(0,0); - - nsInput* content; - aFrame->GetContent((nsIContent*&) content); - - nsAutoString valAttr; - nsresult valStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColValueAttr) { - valStatus = ((nsHTMLTagContent*)content)->GetAttribute(aSpec.mColValueAttr, valAttr); - } - nsHTMLValue colAttr; - nsresult colStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mColSizeAttr) { - colStatus = content->GetAttribute(aSpec.mColSizeAttr, colAttr); - } - float p2t = aPresContext->GetPixelsToTwips(); - - // determine the width - nscoord adjSize; - if (NS_CONTENT_ATTR_HAS_VALUE == colStatus) { // col attr will provide width - if (aSpec.mColSizeAttrInPixels) { - adjSize = (colAttr.GetPixelValue() > 0) ? colAttr.GetPixelValue() : 15; - aBounds.width = NSIntPixelsToTwips(adjSize, p2t); - } - else { - PRInt32 col = ((colAttr.GetUnit() == eHTMLUnit_Pixel) ? colAttr.GetPixelValue() : colAttr.GetIntValue()); - if (col <= 0) { - col = 1; - } - charWidth = GetTextSize(*aPresContext, aFrame, col, aBounds); - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - if (aSpec.mColSizeAttrInPixels) { - aWidthExplicit = PR_TRUE; - } - } - else { - if (CSS_NOTSET != aCSSSize.width) { // css provides width - aBounds.width = (aCSSSize.width > 0) ? aCSSSize.width : 1; - aWidthExplicit = PR_TRUE; - } - else { - if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { // use width of initial value - charWidth = GetTextSize(*aPresContext, aFrame, valAttr, aBounds); - } - else if (aSpec.mColDefaultValue) { // use default value - charWidth = GetTextSize(*aPresContext, aFrame, *aSpec.mColDefaultValue, aBounds); - } - else if (aSpec.mColDefaultSizeInPixels) { // use default width in pixels - charWidth = GetTextSize(*aPresContext, aFrame, 1, aBounds); - aBounds.width = aSpec.mColDefaultSize; - } - else { // use default width in num characters - charWidth = GetTextSize(*aPresContext, aFrame, aSpec.mColDefaultSize, aBounds); - } - aRowHeight = aBounds.height; // XXX aBounds.height has CSS_NOTSET - } - } - - // determine the height - nsHTMLValue rowAttr; - nsresult rowStatus = NS_CONTENT_ATTR_NOT_THERE; - if (nsnull != aSpec.mRowSizeAttr) { - rowStatus = content->GetAttribute(aSpec.mRowSizeAttr, rowAttr); - } - if (NS_CONTENT_ATTR_HAS_VALUE == rowStatus) { // row attr will provide height - PRInt32 rowAttrInt = ((rowAttr.GetUnit() == eHTMLUnit_Pixel) ? rowAttr.GetPixelValue() : rowAttr.GetIntValue()); - adjSize = (rowAttrInt > 0) ? rowAttrInt : 1; - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize); - aBounds.height = textSize.height * adjSize; - aRowHeight = textSize.height; - numRows = adjSize; - } - else { - aBounds.height = aBounds.height * adjSize; - } - } - else if (CSS_NOTSET != aCSSSize.height) { // css provides height - aBounds.height = (aCSSSize.height > 0) ? aCSSSize.height : 1; - aHeightExplicit = PR_TRUE; - } - else { // use default height in num lines - if (0 == charWidth) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize); - aBounds.height = textSize.height * aSpec.mRowDefaultSize; - aRowHeight = textSize.height; - } - else { - aBounds.height = aBounds.height * aSpec.mRowDefaultSize; - } - } - - if ((0 == charWidth) || (0 == textSize.width)) { - charWidth = GetTextSize(*aPresContext, aFrame, 1, textSize); - aRowHeight = textSize.height; - } - - // add inside padding if necessary - if (!aWidthExplicit) { - aBounds.width += (2 * aFrame->GetHorizontalInsidePadding(p2t, aBounds.width, charWidth)); - } - if (!aHeightExplicit) { - aBounds.height += (2 * aFrame->GetVerticalInsidePadding(p2t, textSize.height)); - } - - NS_RELEASE(content); - if (ATTR_NOTSET == numRows) { - numRows = aBounds.height / aRowHeight; - } - - return numRows; -} - - -// this handles all of the input types rather than having them do it. -const void -nsInputFrame::GetFont(nsIPresContext* aPresContext, nsFont& aFont) -{ - const nsStyleFont* styleFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - - nsString type; - ((nsInput*)mContent)->GetType(type); - - // XXX shouldn't this be atom compares instead? - if ( type.EqualsIgnoreCase("text") || - type.EqualsIgnoreCase("textarea") || - type.EqualsIgnoreCase("password")) { - aFont = styleFont->mFixedFont; - } else if (type.EqualsIgnoreCase("button") || - type.EqualsIgnoreCase("submit") || - type.EqualsIgnoreCase("reset") || - type.EqualsIgnoreCase("select")) { - if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || - (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { - aFont = styleFont->mFixedFont; - aFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight - aFont.size = styleFont->mFont.size; // normal font size - if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { - aFont.name = "Arial"; // XXX windows specific font - } - } else { - // use arial, scaled down one HTML size - // italics, decoration & variant(?) get used - aFont = styleFont->mFont; - aFont.name = "Arial"; // XXX windows specific font - aFont.weight = NS_FONT_WEIGHT_NORMAL; - const nsFont& normal = aPresContext->GetDefaultFont(); - PRInt32 scaler = aPresContext->GetFontScaler(); - float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); - PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(aFont.size, (PRInt32)normal.size, scaleFactor); - aFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); - } - } -} - - - diff --git a/mozilla/layout/html/forms/src/nsInputRadio.cpp b/mozilla/layout/html/forms/src/nsInputRadio.cpp deleted file mode 100644 index 3992b8b2e3c..00000000000 --- a/mozilla/layout/html/forms/src/nsInputRadio.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInputRadio.h" -#include "nsInputFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIFrame.h" -#include "nsISupports.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" -#include "nsIHTMLContent.h" -#include "nsHTMLIIDs.h" -#include "nsIRadioButton.h" -#include "nsWidgetsCID.h" -#include "nsSize.h" -#include "nsHTMLAtoms.h" -#include "nsIFormManager.h" -#include "nsIView.h" -#include "nsIStyleContext.h" -#include "nsStyleUtil.h" - - -// prototypes -nsresult -NS_NewHTMLInputRadio(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager); - - -static NS_DEFINE_IID(kRadioIID, NS_IRADIOBUTTON_IID); - - -class nsInputRadioFrame : public nsInputFrame { -public: - nsInputRadioFrame(nsIContent* aContent, nsIFrame* aParentFrame); - - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView); - - virtual const nsIID& GetCID(); - - virtual const nsIID& GetIID(); - - virtual void MouseClicked(nsIPresContext* aPresContext); - -protected: - - virtual ~nsInputRadioFrame(); - - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize); -}; - -nsresult -NS_NewInputRadioFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsInputRadioFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsInputRadioFrame::nsInputRadioFrame(nsIContent* aContent, nsIFrame* aParentFrame) - : nsInputFrame(aContent, aParentFrame) -{ -} - -nsInputRadioFrame::~nsInputRadioFrame() -{ -} - -const nsIID& -nsInputRadioFrame::GetIID() -{ - return kRadioIID; -} - -const nsIID& -nsInputRadioFrame::GetCID() -{ - static NS_DEFINE_IID(kRadioCID, NS_RADIOBUTTON_CID); - return kRadioCID; -} - -void -nsInputRadioFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - float p2t = aPresContext->GetPixelsToTwips(); - aDesiredWidgetSize.width = NSIntPixelsToTwips(12, p2t); - aDesiredWidgetSize.height = NSIntPixelsToTwips(12, p2t); - aDesiredLayoutSize.width = aDesiredWidgetSize.width; - aDesiredLayoutSize.height = aDesiredWidgetSize.height; - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; -} - -void -nsInputRadioFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ - nsInputRadio* content = (nsInputRadio *)mContent; - //PRInt32 checkedAttr; - //nsContentAttr result = ((nsInput *)content)->GetAttribute(nsHTMLAtoms::checked, checkedAttr); - //if ((result == eContentAttr_HasValue) && (PR_FALSE != checkedAttr)) { - nsIWidget* widget = nsnull; - nsIRadioButton* radio = nsnull; - nsresult result = GetWidget(aView, &widget); - if (NS_OK == result) { - result = widget->QueryInterface(GetIID(),(void**)&radio); - if (result == NS_OK) - { - radio->SetState(content->mForcedChecked); - - const nsStyleColor* color = - nsStyleUtil::FindNonTransparentBackground(mStyleContext); - - if (nsnull != color) { - widget->SetBackgroundColor(color->mBackgroundColor); - } - else { - widget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); - } - NS_RELEASE(radio); - } - NS_RELEASE(widget); - } -} - -// nsInputRadio - -const nsString* nsInputRadio::kTYPE = new nsString("radio"); - -nsInputRadio::nsInputRadio(nsIAtom* aTag, nsIFormManager* aManager) - : nsInput(aTag, aManager) -{ - mInitialChecked = PR_FALSE; - mForcedChecked = PR_FALSE; -} - -nsInputRadio::~nsInputRadio() -{ -} - -static void -MapAttributesInto(nsIHTMLAttributes* aAttributes, - nsIStyleContext* aContext, - nsIPresContext* aPresContext) -{ - float p2t = aPresContext->GetPixelsToTwips(); - nscoord pad = NSIntPixelsToTwips(3, p2t); - - // add left and right padding around the radio button via css - nsStyleSpacing* spacing = (nsStyleSpacing*) aContext->GetMutableStyleData(eStyleStruct_Spacing); - if (eStyleUnit_Null == spacing->mMargin.GetLeftUnit()) { - nsStyleCoord left(pad); - spacing->mMargin.SetLeft(left); - } - if (eStyleUnit_Null == spacing->mMargin.GetRightUnit()) { - nsStyleCoord right(NSIntPixelsToTwips(5, p2t)); - spacing->mMargin.SetRight(right); - } - // add bottom padding if backward mode - // XXX why isn't this working? - nsCompatibility mode; - aPresContext->GetCompatibilityMode(mode); - if (eCompatibility_NavQuirks == mode) { - if (eStyleUnit_Null == spacing->mMargin.GetBottomUnit()) { - nsStyleCoord bottom(pad); - spacing->mMargin.SetBottom(bottom); - } - } - nsInput::MapAttributesInto(aAttributes, aContext, aPresContext); -} - -NS_IMETHODIMP -nsInputRadio::GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const -{ - aMapFunc = &MapAttributesInto; - return NS_OK; -} - - -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); - -void -nsInputRadioFrame::MouseClicked(nsIPresContext* aPresContext) -{ - nsIRadioButton* radioWidget; - nsIView* view; - GetView(view); - if (NS_OK == GetWidget(view, (nsIWidget **)&radioWidget)) { - radioWidget->SetState(PR_TRUE); - NS_RELEASE(radioWidget); - nsInputRadio* radio; - GetContent((nsIContent *&) radio); - nsIFormControl* control; - nsresult status = radio->QueryInterface(kIFormControlIID, (void **)&control); - NS_ASSERTION(NS_OK == status, "nsInputRadio has no nsIFormControl interface"); - if (NS_OK == status) { - nsIFormManager* formMan = radio->GetFormManager(); - if (formMan) { - formMan->OnRadioChecked(*control); - NS_RELEASE(formMan); - } - NS_RELEASE(radio); - } - } -} - -PRBool -nsInputRadio::GetChecked(PRBool aGetInitialValue) const -{ - if (aGetInitialValue) { - return mInitialChecked; - } - else { - if (mWidget) { - PRBool state = PR_FALSE; - nsIRadioButton* radio = nsnull; - nsresult result = mWidget->QueryInterface(kRadioIID,(void**)&radio); - if (result == NS_OK) - { - radio->GetState(state); - NS_IF_RELEASE(radio); - } - return state; - } - else { - return mForcedChecked; - } - } -} - -void -nsInputRadio::SetChecked(PRBool aValue, PRBool aSetInitialValue) -{ - mForcedChecked = aValue; - if (aSetInitialValue) { - mInitialChecked = aValue; - } - //NS_ASSERTION(mWidget, "no widget for this nsInputRadio"); - if (mWidget) { - ((nsIRadioButton *)mWidget)->SetState(aValue); - } -} - -void nsInputRadio::GetType(nsString& aResult) const -{ - aResult = "radio"; -} - -NS_IMETHODIMP -nsInputRadio::SetAttribute(nsIAtom* aAttribute, - const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::checked) { - mInitialChecked = PR_TRUE; - mForcedChecked = PR_TRUE; - } - return nsInputRadioSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -NS_IMETHODIMP -nsInputRadio::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const -{ - aResult.Reset(); - if (aAttribute == nsHTMLAtoms::checked) { - return GetCacheAttribute(mInitialChecked, aResult, eHTMLUnit_Empty); - } - else { - return nsInputRadioSuper::GetAttribute(aAttribute, aResult); - } -} - -PRBool -nsInputRadio::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - return PR_FALSE; - } - - nsIWidget* widget = GetWidget(); - nsIRadioButton* radio = nsnull; - PRBool state = PR_FALSE; - - if (widget != nsnull) - { - widget->QueryInterface(kRadioIID,(void**)&radio); - radio->GetState(state); - NS_IF_RELEASE(radio); - } - if(PR_TRUE != state) { - return PR_FALSE; - } - - if (nsnull == mValue) { - aValues[0] = "on"; - } else { - aValues[0] = *mValue; - } - aNames[0] = *mName; - aNumValues = 1; - - return PR_TRUE; -} - -void -nsInputRadio::Reset() -{ - nsIWidget* widget = GetWidget(); - nsIRadioButton* radio = nsnull; - if (widget != nsnull && NS_OK == widget->QueryInterface(kRadioIID,(void**)&radio)) - { - radio->SetState(mInitialChecked); - NS_RELEASE(radio); - } -} - -nsresult -NS_NewHTMLInputRadio(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputRadio(aTag, aManager); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -// CLASS nsInputRadioGroup - -nsInputRadioGroup::nsInputRadioGroup(nsString& aName) -:mName(aName), mCheckedRadio(nsnull) -{ -} - -nsInputRadioGroup::~nsInputRadioGroup() -{ - mCheckedRadio = nsnull; -} - -PRInt32 -nsInputRadioGroup::GetRadioCount() const -{ - return mRadios.Count(); -} - -nsIFormControl* -nsInputRadioGroup::GetRadioAt(PRInt32 aIndex) const -{ - return (nsIFormControl*) mRadios.ElementAt(aIndex); -} - -PRBool -nsInputRadioGroup::AddRadio(nsIFormControl* aRadio) -{ - return mRadios.AppendElement(aRadio); -} - -PRBool -nsInputRadioGroup::RemoveRadio(nsIFormControl* aRadio) -{ - return mRadios.RemoveElement(aRadio); -} - -nsIFormControl* -nsInputRadioGroup::GetCheckedRadio() -{ - return mCheckedRadio; -} - -void -nsInputRadioGroup::SetCheckedRadio(nsIFormControl* aRadio) -{ - mCheckedRadio = aRadio; -} - -void -nsInputRadioGroup::GetName(nsString& aNameResult) const -{ - aNameResult = mName; -} diff --git a/mozilla/layout/html/forms/src/nsInputRadio.h b/mozilla/layout/html/forms/src/nsInputRadio.h deleted file mode 100644 index 8a278259b45..00000000000 --- a/mozilla/layout/html/forms/src/nsInputRadio.h +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#ifndef nsInputRadio_h___ -#define nsInputRadio_h___ - -// this class defintion will be moved into nsInputRadio.cpp - -#include "nsInput.h" -#include "nsVoidArray.h" -class nsIAtom; -class nsString; - -class nsInputRadio : public nsInput -{ -public: - typedef nsInput nsInputRadioSuper; - nsInputRadio (nsIAtom* aTag, nsIFormManager* aManager); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - - NS_IMETHOD GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const; - - static const nsString* kTYPE; - - virtual PRBool GetChecked(PRBool aGetInitialValue) const; - virtual void SetChecked(PRBool aValue, PRBool aSetInitialValue); - - virtual PRInt32 GetMaxNumValues() { return 1; } - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - NS_IMETHOD GetAttributeMappingFunction(nsMapAttributesFunc& aMapFunc) const; - - virtual void Reset(); - -protected: - virtual ~nsInputRadio(); - - virtual void GetType(nsString& aResult) const; - - PRBool mInitialChecked; - PRBool mForcedChecked; - - friend class nsInputRadioFrame; -}; - -class nsInputRadioGroup -{ -public: - nsInputRadioGroup(nsString& aName); - virtual ~nsInputRadioGroup(); - - PRBool AddRadio(nsIFormControl* aRadio); - PRInt32 GetRadioCount() const; - nsIFormControl* GetRadioAt(PRInt32 aIndex) const; - PRBool RemoveRadio(nsIFormControl* aRadio); - - nsIFormControl* GetCheckedRadio(); - void SetCheckedRadio(nsIFormControl* aRadio); - void GetName(nsString& aNameResult) const; - -protected: - nsString mName; - nsVoidArray mRadios; - nsIFormControl* mCheckedRadio; -}; - -#endif - - diff --git a/mozilla/layout/html/forms/src/nsInputText.cpp b/mozilla/layout/html/forms/src/nsInputText.cpp deleted file mode 100644 index f5ea8191519..00000000000 --- a/mozilla/layout/html/forms/src/nsInputText.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#include "nsInputText.h" -#include "nsInputFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIFrame.h" -#include "nsISupports.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" -#include "nsIHTMLContent.h" -#include "nsHTMLIIDs.h" -#include "nsITextWidget.h" -#include "nsITextAreaWidget.h" -#include "nsWidgetsCID.h" -#include "nsSize.h" -#include "nsString.h" -#include "nsHTMLAtoms.h" -#include "nsHTMLForms.h" -#include "nsIStyleContext.h" -#include "nsFont.h" -#include "nsDOMEvent.h" - -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); - -class nsInputTextFrame : public nsInputFrame { -public: - nsInputTextFrame(nsIContent* aContent, - nsIFrame* aParentFrame); - - virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); - - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView); - - virtual const nsIID& GetCID(); - - virtual const nsIID& GetIID(); - - virtual void EnterPressed(nsIPresContext& aPresContext) ; - - virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; - virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; - virtual nscoord GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const; - virtual nscoord GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const; -protected: - - virtual ~nsInputTextFrame(); - - nsInputTextType GetTextType(); - - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize); -}; - -nsresult -NS_NewInputTextFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsInputTextFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsInputTextFrame::nsInputTextFrame(nsIContent* aContent, - nsIFrame* aParentFrame) - : nsInputFrame(aContent, aParentFrame) -{ -} - -nsInputTextFrame::~nsInputTextFrame() -{ -} - -nscoord nsInputTextFrame::GetVerticalBorderWidth(float aPixToTwip) const -{ - return NSIntPixelsToTwips(4, aPixToTwip); -} - -nscoord nsInputTextFrame::GetHorizontalBorderWidth(float aPixToTwip) const -{ - return GetVerticalBorderWidth(aPixToTwip); -} - -// for a text area aInnerHeight is the height of one line -nscoord nsInputTextFrame::GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const -{ -#ifdef XP_PC - nsAutoString type; - ((nsInput*)mContent)->GetType(type); - if (type.EqualsIgnoreCase("textarea")) { - return (nscoord)NSToIntRound(float(aInnerHeight) * 0.40f); - } else { - return (nscoord)NSToIntRound(float(aInnerHeight) * 0.25f); - } -#endif -#ifdef XP_UNIX - return NSIntPixelsToTwips(10, aPixToTwip); // XXX this is probably wrong -#endif -} - -nscoord nsInputTextFrame::GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const -{ -#ifdef XP_PC - nscoord padding; - nsAutoString type; - ((nsInput*)mContent)->GetType(type); - if (type.EqualsIgnoreCase("textarea")) { - padding = (nscoord)(40 * aCharWidth / 100); - } else { - padding = (nscoord)(55 * aCharWidth / 100); - } - nscoord min = NSIntPixelsToTwips(3, aPixToTwip); - if (padding > min) { - return padding; - } else { - return min; - } -#endif -#ifdef XP_UNIX - return NSIntPixelsToTwips(6, aPixToTwip); // XXX this is probably wrong -#endif -} - -static NS_DEFINE_IID(kTextIID, NS_ITEXTWIDGET_IID); -static NS_DEFINE_IID(kTextAreaIID, NS_ITEXTAREAWIDGET_IID); - - -const nsIID& -nsInputTextFrame::GetIID() -{ - - if (kInputText_Area == GetTextType()) { - return kTextAreaIID; - } - else { - return kTextIID; - } -} - -const nsIID& -nsInputTextFrame::GetCID() -{ - static NS_DEFINE_IID(kTextCID, NS_TEXTFIELD_CID); - static NS_DEFINE_IID(kTextAreaCID, NS_TEXTAREA_CID); - - if (kInputText_Area == GetTextType()) { - return kTextAreaCID; - } - else { - return kTextCID; - } -} - -nsInputTextType -nsInputTextFrame::GetTextType() -{ - nsInputText* content; - GetContent((nsIContent *&) content); - nsInputTextType type = content->GetTextType(); - NS_RELEASE(content); - return type; -} - -void -nsInputTextFrame::EnterPressed(nsIPresContext& aPresContext) -{ - nsInputText* text = (nsInputText *)mContent; - nsIFormManager* formMan = text->GetFormManager(); - if (nsnull != formMan) { - nsInputTextType type = text->GetTextType(); - // a form with one text area causes a submit when the enter key is pressed - // XXX this logic should be in the form manager, but then it needs to be passed - // enough to trigger the dom event. - if ((kInputText_Text == type) && text->GetCanSubmit()) { - nsEventStatus mStatus = nsEventStatus_eIgnore; - nsEvent mEvent; - mEvent.eventStructType = NS_EVENT; - mEvent.message = NS_FORM_SUBMIT; - mContent->HandleDOMEvent(aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); - - nsIFormControl* control; - mContent->QueryInterface(kIFormControlIID, (void**)&control); - formMan->OnSubmit(&aPresContext, this, control); - NS_IF_RELEASE(control); - } - NS_RELEASE(formMan); - } -} - -void -nsInputTextFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - nsInputTextType textType = GetTextType(); - // get the css size and let the frame use or override it - nsSize styleSize; - GetStyleSize(*aPresContext, aReflowState, styleSize); - - nsSize size; - - PRBool widthExplicit, heightExplicit; - PRInt32 ignore; - if ((kInputText_Text == textType) || (kInputText_Password == textType) || - (kInputText_FileText == textType)) { - nsHTMLValue sizeAttr; - PRInt32 width = 21; - if (NS_CONTENT_ATTR_HAS_VALUE == ((nsInput*)mContent)->GetAttribute(nsHTMLAtoms::size, sizeAttr)) { - width = (sizeAttr.GetUnit() == eHTMLUnit_Pixel) ? sizeAttr.GetPixelValue() : sizeAttr.GetIntValue(); - if (kBackwardMode == GetMode()) { - width += 1; - } - } - nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, - nsnull, width, PR_FALSE, nsnull, 1); - // nsInputDimensionSpec textSpec(nsHTMLAtoms::size, PR_FALSE, nsnull, - // nsnull, 21, PR_FALSE, nsnull, 1); - CalculateSize(aPresContext, this, styleSize, textSpec, size, - widthExplicit, heightExplicit, ignore); - } - else { - nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, 20, - PR_FALSE, nsHTMLAtoms::rows, 1); - CalculateSize(aPresContext, this, styleSize, areaSpec, size, - widthExplicit, heightExplicit, ignore); - } - - if (kInputText_Area == textType) { - float p2t = aPresContext->GetPixelsToTwips(); - nscoord scrollbarWidth = GetScrollbarWidth(p2t); - - if (!heightExplicit) { - size.height += scrollbarWidth; - } - if (!widthExplicit) { - size.width += scrollbarWidth; - } - } - - - aDesiredLayoutSize.width = size.width; - aDesiredLayoutSize.height = size.height; - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; - aDesiredWidgetSize.width = aDesiredLayoutSize.width; - aDesiredWidgetSize.height = aDesiredLayoutSize.height; -} - -nsWidgetInitData* -nsInputTextFrame::GetWidgetInitData(nsIPresContext& aPresContext) -{ - nsTextWidgetInitData* data = nsnull; - nsInputText* content; - GetContent((nsIContent *&) content); - - if (kInputText_Password == content->GetTextType()) { - data = new nsTextWidgetInitData(); - data->clipChildren = PR_TRUE; - data->mIsPassword = PR_TRUE; - } - NS_RELEASE(content); - - return data; -} - -void -nsInputTextFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ - nsIWidget* widget = nsnull; - if (NS_OK == GetWidget(aView, &widget)) { - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - - // This is replicated code for both text interfaces -- this should be factored - if (widget != nsnull && NS_OK == widget->QueryInterface(kTextIID,(void**)&text)) - { - const nsStyleFont* fontStyle = (const nsStyleFont*)(mStyleContext->GetStyleData(eStyleStruct_Font)); - widget->SetFont(fontStyle->mFixedFont); - nsInputText* content; - GetContent((nsIContent *&) content); - nsAutoString valAttr; - nsresult valStatus = ((nsHTMLTagContent *)content)->GetAttribute(nsHTMLAtoms::value, valAttr); - PRUint32 size; - text->SetText(valAttr,size); - PRInt32 maxLength = content->GetMaxLength(); - if (ATTR_NOTSET != maxLength) { - text->SetMaxTextLength(maxLength); - } - widget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); - NS_RELEASE(content); - NS_RELEASE(text); - } - else if (widget != nsnull && NS_OK == widget->QueryInterface(kTextAreaIID,(void**)&textArea)) - { - const nsStyleFont* fontStyle = (const nsStyleFont*)(mStyleContext->GetStyleData(eStyleStruct_Font)); - widget->SetFont(fontStyle->mFixedFont); - nsInputText* content; - GetContent((nsIContent *&) content); - nsAutoString valAttr; - nsresult valStatus = ((nsHTMLTagContent *)content)->GetAttribute(nsHTMLAtoms::value, valAttr); - PRUint32 size; - textArea->SetText(valAttr,size); - PRInt32 maxLength = content->GetMaxLength(); - if (ATTR_NOTSET != maxLength) { - textArea->SetMaxTextLength(maxLength); - } - widget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); - NS_RELEASE(content); - NS_RELEASE(textArea); - } - } -} - -//---------------------------------------------------------------------- -// nsInputText - -nsInputText::nsInputText(nsIAtom* aTag, nsIFormManager* aManager, nsInputTextType aType) - : nsInput(aTag, aManager), mType(aType) -{ - mMaxLength = ATTR_NOTSET; - mNumRows = ATTR_NOTSET; - mNumCols = ATTR_NOTSET; -} - -nsInputText::~nsInputText() -{ -} - -nsInputTextType -nsInputText::GetTextType() const -{ - return mType; -} - -PRInt32 -nsInputText::GetMaxNumValues() -{ - return 1; -} - -static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); -static NS_DEFINE_IID(kITextAreaWidgetIID, NS_ITEXTAREAWIDGET_IID); - -PRBool -nsInputText::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - return PR_FALSE; - } - nsIWidget* widget = GetWidget(); - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - - if (widget != nsnull && NS_OK == widget->QueryInterface(kITextWidgetIID,(void**)&text)) - { - nsString value; - PRUint32 size; - text->GetText(aValues[0],0,size); // the last parm is not used - aNames[0] = *mName; - aNumValues = 1; - - NS_RELEASE(text); - return PR_TRUE; - } - else if (widget != nsnull && NS_OK == widget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) - { - nsString value; - PRUint32 size; - textArea->GetText(aValues[0],0,size); // the last parm is not used - aNames[0] = *mName; - aNumValues = 1; - - NS_RELEASE(textArea); - return PR_TRUE; - } - return PR_FALSE; -} - - -void -nsInputText::Reset() -{ - nsIWidget* widget = GetWidget(); - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - if (widget != nsnull && NS_OK == widget->QueryInterface(kTextIID,(void**)&text)) - { - PRUint32 size; - if (nsnull == mValue) { - text->SetText("",size); - } else { - text->SetText(*mValue,size); - } - NS_RELEASE(text); - } - else if (widget != nsnull && NS_OK == widget->QueryInterface(kTextAreaIID,(void**)&textArea)) - { - PRUint32 size; - if (nsnull == mValue) { - textArea->SetText("",size); - } else { - textArea->SetText(*mValue,size); - } - NS_RELEASE(textArea); - } - -} - -void nsInputText::GetType(nsString& aResult) const -{ - if (kInputText_Text == mType) { - aResult = "text"; - } - else if (kInputText_Password == mType) { - aResult = "password"; - } - else if (kInputText_Area == mType) { - aResult = "textarea"; - } - else if (kInputText_FileText == mType) { - aResult = "filetext"; - } -} - -NS_IMETHODIMP -nsInputText::SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::maxlength) { - CacheAttribute(aValue, ATTR_NOTSET, mMaxLength); - } - else if ((aAttribute == nsHTMLAtoms::rows) && (kInputText_Area == mType)) { - CacheAttribute(aValue, ATTR_NOTSET, mNumRows); - } - else if ((aAttribute == nsHTMLAtoms::cols) && (kInputText_Area == mType)) { - CacheAttribute(aValue, ATTR_NOTSET, mNumCols); - } - return nsInputTextSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -NS_IMETHODIMP -nsInputText::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const -{ - if (aAttribute == nsHTMLAtoms::maxlength) { - return GetCacheAttribute(mMaxLength, aResult, eHTMLUnit_Integer); - } - else if ((aAttribute == nsHTMLAtoms::rows) && (kInputText_Area == mType)) { - return GetCacheAttribute(mNumRows, aResult, eHTMLUnit_Integer); - } - else if ((aAttribute == nsHTMLAtoms::cols) && (kInputText_Area == mType)) { - return GetCacheAttribute(mNumCols, aResult, eHTMLUnit_Integer); - } - else { - return nsInputTextSuper::GetAttribute(aAttribute, aResult); - } -} - -nsresult -NS_NewHTMLInputText(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputText(aTag, aManager, kInputText_Text); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -nsresult -NS_NewHTMLInputPassword(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputText(aTag, aManager, kInputText_Password); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -nsresult -NS_NewHTMLInputFileText(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputText(aTag, aManager, kInputText_FileText); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -nsresult -NS_NewHTMLTextArea(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aManager) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsInputText(aTag, aManager, kInputText_Area); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} diff --git a/mozilla/layout/html/forms/src/nsInputText.h b/mozilla/layout/html/forms/src/nsInputText.h deleted file mode 100644 index 8e2c45fd02a..00000000000 --- a/mozilla/layout/html/forms/src/nsInputText.h +++ /dev/null @@ -1,79 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -#ifndef nsInputText_h___ -#define nsInputText_h___ - -#include "nsInput.h" -#include "nsString.h" -class nsIAtom; -class nsString; -class nsView; - -enum nsInputTextType { - kInputText_Text, - kInputText_FileText, - kInputText_Password, - kInputText_Area -}; - -// this class definition will move to nsInputText.cpp - -class nsInputText : public nsInput { -public: - typedef nsInput nsInputTextSuper; - nsInputText (nsIAtom* aTag, nsIFormManager* aManager, nsInputTextType aType); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - - NS_IMETHOD GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const; - - virtual PRInt32 GetMaxNumValues(); - - nsInputTextType GetTextType() const; - - PRInt32 GetMaxLength() const { return mMaxLength; } - - // From nsIDOMHTMLInputElement interface - NS_IMETHOD GetMaxLength(PRInt32* aMaxLength) - { *aMaxLength = mMaxLength; return NS_OK; } - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - virtual void Reset(); - -protected: - - virtual ~nsInputText(); - - virtual void GetType(nsString& aResult) const; - - nsInputTextType mType; - - PRInt32 mMaxLength; // text, password only - PRInt32 mNumRows; // textarea only - PRInt32 mNumCols; // textarea only - -}; - -#endif - - diff --git a/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp b/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp new file mode 100644 index 00000000000..eeaab586991 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsRadioControlFrame.cpp @@ -0,0 +1,281 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsRadioControlFrame.h" +#include "nsFormControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIFrame.h" +#include "nsISupports.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsIRadioButton.h" +#include "nsWidgetsCID.h" +#include "nsSize.h" +#include "nsHTMLAtoms.h" +#include "nsIFormControl.h" +#include "nsIFormManager.h" +#include "nsIView.h" +#include "nsIStyleContext.h" +#include "nsStyleUtil.h" +#include "nsFormFrame.h" + +static NS_DEFINE_IID(kIRadioIID, NS_IRADIOBUTTON_IID); +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); + + + +nsresult +NS_NewRadioControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsRadioControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsRadioControlFrame::nsRadioControlFrame(nsIContent* aContent, nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ + mInitialChecked = nsnull; + mForcedChecked = PR_FALSE; +} + +nsRadioControlFrame::~nsRadioControlFrame() +{ + if (mInitialChecked) { + delete mInitialChecked; + } +} + +const nsIID& +nsRadioControlFrame::GetIID() +{ + return kIRadioIID; +} + +const nsIID& +nsRadioControlFrame::GetCID() +{ + static NS_DEFINE_IID(kRadioCID, NS_RADIOBUTTON_CID); + return kRadioCID; +} + +void +nsRadioControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + float p2t = aPresContext->GetPixelsToTwips(); + aDesiredWidgetSize.width = NSIntPixelsToTwips(12, p2t); + aDesiredWidgetSize.height = NSIntPixelsToTwips(12, p2t); + aDesiredLayoutSize.width = aDesiredWidgetSize.width; + aDesiredLayoutSize.height = aDesiredWidgetSize.height; + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; +} + +void +nsRadioControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + nsIRadioButton* radio = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(GetIID(),(void**)&radio))) { + radio->SetState(mForcedChecked); + + const nsStyleColor* color = + nsStyleUtil::FindNonTransparentBackground(mStyleContext); + + if (nsnull != color) { + mWidget->SetBackgroundColor(color->mBackgroundColor); + } else { + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + } + NS_RELEASE(radio); + } +} + + +void +nsRadioControlFrame::MouseClicked(nsIPresContext* aPresContext) +{ + nsIRadioButton* radioWidget; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID, (void**)&radioWidget))) { + radioWidget->SetState(PR_TRUE); + NS_RELEASE(radioWidget); + if (mFormFrame) { + mFormFrame->OnRadioChecked(*this); + } + } +} + +PRBool +nsRadioControlFrame::GetChecked(PRBool aGetInitialValue) +{ + if (aGetInitialValue) { + if (!mInitialChecked && mContent) { + mInitialChecked = new PRBool(PR_FALSE); + nsIHTMLContent* iContent = nsnull; + nsresult result = mContent->QueryInterface(kIHTMLContentIID, (void**)&iContent); + if ((NS_OK == result) && iContent) { + nsHTMLValue value; + result = iContent->GetAttribute(nsHTMLAtoms::checked, value); + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + *mInitialChecked = PR_TRUE; + mForcedChecked = PR_TRUE; + } + NS_RELEASE(iContent); + } + } + return *mInitialChecked; + } + + PRBool result = PR_FALSE; + nsIRadioButton* radio = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID,(void**)&radio))) { + radio->GetState(result); + NS_RELEASE(radio); + } else { + result = mForcedChecked; + } + return result; +} + +void +nsRadioControlFrame::SetChecked(PRBool aValue, PRBool aSetInitialValue) +{ + mForcedChecked = aValue; + if (aSetInitialValue) { + if (!mInitialChecked) { + mInitialChecked = new PRBool(aValue); + } + *mInitialChecked = aValue; + } + nsIRadioButton* radio = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID,(void**)&radio))) { + radio->SetState(aValue); + NS_RELEASE(radio); + } +} + + +PRBool +nsRadioControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_HAS_VALUE != result)) { + return PR_FALSE; + } + + PRBool state = PR_FALSE; + + nsIRadioButton* radio = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID,(void**)&radio))) { + radio->GetState(state); + NS_RELEASE(radio); + } + if(PR_TRUE != state) { + return PR_FALSE; + } + + nsAutoString value; + result = GetValue(&value); + + if (NS_CONTENT_ATTR_HAS_VALUE == result) { + aValues[0] = value; + } else { + aValues[0] = "on"; + } + aNames[0] = name; + aNumValues = 1; + + return PR_TRUE; +} + +void +nsRadioControlFrame::Reset() +{ + nsIRadioButton* radio = nsnull; + if (mWidget && (NS_OK == mWidget->QueryInterface(kIRadioIID,(void**)&radio))) { + PRBool state = (nsnull == mInitialChecked) ? PR_FALSE : *mInitialChecked; + radio->SetState(state); + NS_RELEASE(radio); + } +} + + +// CLASS nsRadioControlGroup + +nsRadioControlGroup::nsRadioControlGroup(nsString& aName) +:mName(aName), mCheckedRadio(nsnull) +{ +} + +nsRadioControlGroup::~nsRadioControlGroup() +{ + mCheckedRadio = nsnull; +} + +PRInt32 +nsRadioControlGroup::GetRadioCount() const +{ + return mRadios.Count(); +} + +nsRadioControlFrame* +nsRadioControlGroup::GetRadioAt(PRInt32 aIndex) const +{ + return (nsRadioControlFrame*) mRadios.ElementAt(aIndex); +} + +PRBool +nsRadioControlGroup::AddRadio(nsRadioControlFrame* aRadio) +{ + return mRadios.AppendElement(aRadio); +} + +PRBool +nsRadioControlGroup::RemoveRadio(nsRadioControlFrame* aRadio) +{ + return mRadios.RemoveElement(aRadio); +} + +nsRadioControlFrame* +nsRadioControlGroup::GetCheckedRadio() +{ + return mCheckedRadio; +} + +void +nsRadioControlGroup::SetCheckedRadio(nsRadioControlFrame* aRadio) +{ + mCheckedRadio = aRadio; +} + +void +nsRadioControlGroup::GetName(nsString& aNameResult) const +{ + aNameResult = mName; +} diff --git a/mozilla/layout/html/forms/src/nsRadioControlFrame.h b/mozilla/layout/html/forms/src/nsRadioControlFrame.h new file mode 100644 index 00000000000..d8c18a519dc --- /dev/null +++ b/mozilla/layout/html/forms/src/nsRadioControlFrame.h @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsRadioControlFrame_h___ +#define nsRadioControlFrame_h___ + +#include "nsFormControlFrame.h" +#include "nsVoidArray.h" +#include "nsString.h" +class nsIAtom; + +// nsRadioControlFrame + +class nsRadioControlFrame : public nsFormControlFrame +{ +public: + nsRadioControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual PRBool GetChecked(PRBool aGetInitialValue); + virtual void SetChecked(PRBool aValue, PRBool aSetInitialValue); + + virtual PRInt32 GetMaxNumValues() { return 1; } + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + virtual void MouseClicked(nsIPresContext* aPresContext); + virtual void Reset(); + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + +protected: + + virtual ~nsRadioControlFrame(); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); + PRBool *mInitialChecked; + PRBool mForcedChecked; +}; + +// nsRadioControlGroup + +class nsRadioControlGroup +{ +public: + nsRadioControlGroup(nsString& aName); + virtual ~nsRadioControlGroup(); + + PRBool AddRadio(nsRadioControlFrame* aRadio); + PRInt32 GetRadioCount() const; + nsRadioControlFrame* GetRadioAt(PRInt32 aIndex) const; + PRBool RemoveRadio(nsRadioControlFrame* aRadio); + + nsRadioControlFrame* GetCheckedRadio(); + void SetCheckedRadio(nsRadioControlFrame* aRadio); + void GetName(nsString& aNameResult) const; + +protected: + nsString mName; + nsVoidArray mRadios; + nsRadioControlFrame* mCheckedRadio; +}; + +#endif + + diff --git a/mozilla/layout/html/forms/src/nsSelect.cpp b/mozilla/layout/html/forms/src/nsSelect.cpp deleted file mode 100644 index 8869bf4be14..00000000000 --- a/mozilla/layout/html/forms/src/nsSelect.cpp +++ /dev/null @@ -1,754 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; 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. - */ - -// YY need to pass isMultiple before create called - -#include "nsInputFrame.h" -#include "nsIContent.h" -#include "prtypes.h" -#include "nsIFrame.h" -#include "nsISupports.h" -#include "nsIAtom.h" -#include "nsIPresContext.h" -#include "nsIHTMLContent.h" -#include "nsHTMLIIDs.h" -#include "nsIRadioButton.h" -#include "nsWidgetsCID.h" -#include "nsSize.h" -#include "nsHTMLAtoms.h" -#include "nsIFormManager.h" -#include "nsIView.h" -#include "nsIListWidget.h" -#include "nsIComboBox.h" -#include "nsIListBox.h" -#include "nsInput.h" -#include "nsHTMLForms.h" -#include "nsIStyleContext.h" -#include "nsStyleConsts.h" -#include "nsStyleUtil.h" -#include "nsFont.h" - -#define NS_IOPTION_IID \ -{ 0xfa6a8b11, 0x2af2, 0x11d2, \ - { 0x80, 0x3a, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } - -static NS_DEFINE_IID(kListWidgetIID, NS_ILISTWIDGET_IID); -static NS_DEFINE_IID(kComboBoxIID, NS_ICOMBOBOX_IID); -static NS_DEFINE_IID(kListBoxIID, NS_ILISTBOX_IID); -static NS_DEFINE_IID(kOptionIID, NS_IOPTION_IID); - -class nsOption; - -class nsSelectFrame : public nsInputFrame { -public: - nsSelectFrame(nsIContent* aContent, nsIFrame* aParentFrame); - - virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); - - virtual void PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView); - - virtual const nsIID& GetCID(); - - virtual const nsIID& GetIID(); - - virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; - virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; - virtual nscoord GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const; - virtual nscoord GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const; -protected: - - virtual ~nsSelectFrame(); - - virtual void GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize); -}; - -class nsSelect : public nsInput -{ -public: - typedef nsInput nsSelectSuper; - nsSelect (nsIAtom* aTag, nsIFormManager* aFormMan); - - nsOption* GetNthOption(PRInt32 aIndex); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - - NS_IMETHOD GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const; - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - PRBool IsMultiple() { return mMultiple; } - - PRBool GetMultiple() const { return mMultiple; } - - virtual void Reset(); - - PRBool mIsComboBox; - -protected: - virtual ~nsSelect(); - - virtual void GetType(nsString& aResult) const; - - PRBool mMultiple; -}; - -class nsOption : public nsInput -{ -public: - typedef nsInput nsOptionSuper; - - nsOption (nsIAtom* aTag); - - NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); - - NS_IMETHOD SetAttribute(nsIAtom* aAttribute, const nsString& aValue, - PRBool aNotify); - - NS_IMETHOD GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const; - - virtual PRInt32 GetMaxNumValues(); - - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - - virtual PRBool GetContent(nsString& aString) const; - - virtual void SetContent(const nsString& aValue); - - void CompressContent(); - -protected: - virtual ~nsOption(); - - virtual void GetType(nsString& aResult) const; - - PRBool mSelected; - nsString* mContent; -}; - -nsresult -NS_NewHTMLSelectFrame(nsIContent* aContent, - nsIFrame* aParent, - nsIFrame*& aResult) -{ - aResult = new nsSelectFrame(aContent, aParent); - if (nsnull == aResult) { - return NS_ERROR_OUT_OF_MEMORY; - } - return NS_OK; -} - -nsSelectFrame::nsSelectFrame(nsIContent* aContent, - nsIFrame* aParentFrame) - : nsInputFrame(aContent, aParentFrame) -{ -} - -nsSelectFrame::~nsSelectFrame() -{ -} - - -nscoord nsSelectFrame::GetVerticalBorderWidth(float aPixToTwip) const -{ - return NSIntPixelsToTwips(1, aPixToTwip); -} - -nscoord nsSelectFrame::GetHorizontalBorderWidth(float aPixToTwip) const -{ - return GetVerticalBorderWidth(aPixToTwip); -} - -nscoord nsSelectFrame::GetVerticalInsidePadding(float aPixToTwip, - nscoord aInnerHeight) const -{ -#ifdef XP_PC - return (nscoord)NSToIntRound(float(aInnerHeight) * 0.15f); -#endif -#ifdef XP_UNIX - return NSIntPixelsToTwips(1, aPixToTwip); // XXX this is probably wrong -#endif -} - -PRInt32 nsSelectFrame::GetHorizontalInsidePadding(float aPixToTwip, - nscoord aInnerWidth, - nscoord aCharWidth) const -{ -#ifdef XP_PC - nscoord padding = (nscoord)NSToIntRound(float(aCharWidth) * 0.40f); - nscoord min = NSIntPixelsToTwips(3, aPixToTwip); - if (padding > min) { - return padding; - } else { - return min; - } -#endif -#ifdef XP_UNIX - return NSIntPixelsToTwips(7, aPixToTwip); // XXX this is probably wrong -#endif -} - -const nsIID& -nsSelectFrame::GetIID() -{ - nsSelect* content = (nsSelect *)mContent; - if (content->mIsComboBox) { - return kComboBoxIID; - } - else { - return kListBoxIID; - } -} - -const nsIID& -nsSelectFrame::GetCID() -{ - static NS_DEFINE_IID(kComboCID, NS_COMBOBOX_CID); - static NS_DEFINE_IID(kListCID, NS_LISTBOX_CID); - - nsSelect* content = (nsSelect *)mContent; - if (content->mIsComboBox) { - return kComboCID; - } - else { - return kListCID; - } -} - -void -nsSelectFrame::GetDesiredSize(nsIPresContext* aPresContext, - const nsReflowState& aReflowState, - nsReflowMetrics& aDesiredLayoutSize, - nsSize& aDesiredWidgetSize) -{ - nsSelect* select; - GetContent((nsIContent *&)select); - - // get the css size - nsSize styleSize; - GetStyleSize(*aPresContext, aReflowState, styleSize); - - // get the size of the longest option child - PRInt32 maxWidth = 1; - PRInt32 numChildren; - select->ChildCount(numChildren); - for (int childX = 0; childX < numChildren; childX++) { - nsIContent* child; - select->ChildAt(childX, child); - nsOption* option; - nsresult result = child->QueryInterface(kOptionIID, (void**)&option); - if (NS_OK == result) { - option->CompressContent(); - nsString text; - if (PR_FALSE == option->GetContent(text)) { - continue; - } - nsSize textSize; - // use the style for the select rather that the option, since widgets don't support it - nsInputFrame::GetTextSize(*aPresContext, this, text, textSize); - if (textSize.width > maxWidth) { - maxWidth = textSize.width; - } - NS_RELEASE(option); - } - NS_RELEASE(child); - } - - PRInt32 rowHeight = 0; - nsSize calcSize, charSize; - PRBool widthExplicit, heightExplicit; - nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, - maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); - PRInt32 numRows = CalculateSize(aPresContext, this, styleSize, textSpec, - calcSize, widthExplicit, heightExplicit, rowHeight); - - // here it is determined whether we are a combo box - PRInt32 sizeAttr = select->GetSize(); - if (!select->GetMultiple() && ((1 >= sizeAttr) || ((ATTR_NOTSET == sizeAttr) && (1 >= numRows)))) { - select->mIsComboBox = PR_TRUE; - } - - aDesiredLayoutSize.width = calcSize.width; - // account for vertical scrollbar, if present - if (!widthExplicit && ((numRows < numChildren) || select->mIsComboBox)) { - float p2t = aPresContext->GetPixelsToTwips(); - aDesiredLayoutSize.width += GetScrollbarWidth(p2t); - } - - // XXX put this in widget library, combo boxes are fixed height (visible part) - aDesiredLayoutSize.height = (select->mIsComboBox) ? 350 : calcSize.height; - aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; - aDesiredLayoutSize.descent = 0; - - aDesiredWidgetSize.width = aDesiredLayoutSize.width; - aDesiredWidgetSize.height = aDesiredLayoutSize.height; - if (select->mIsComboBox) { // add in pull down size - aDesiredWidgetSize.height += (rowHeight * (numChildren > 20 ? 20 : numChildren)) + 100; - } - - NS_RELEASE(select); -} - -nsWidgetInitData* -nsSelectFrame::GetWidgetInitData(nsIPresContext& aPresContext) -{ - nsSelect* select = (nsSelect *)mContent; - if (select->mIsComboBox) { - nsComboBoxInitData* initData = new nsComboBoxInitData(); - initData->clipChildren = PR_TRUE; - float twipToPix = aPresContext.GetTwipsToPixels(); - initData->mDropDownHeight = NSTwipsToIntPixels(mWidgetSize.height, twipToPix); - return initData; - } - else { - nsListBoxInitData* initData = nsnull; - nsSelect* content; - GetContent((nsIContent *&) content); - if (content->IsMultiple()) { - initData = new nsListBoxInitData(); - initData->clipChildren = PR_TRUE; - initData->mMultiSelect = PR_TRUE; - } - NS_RELEASE(content); - return initData; - } -} - -void -nsSelectFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) -{ - nsSelect* select; - GetContent((nsIContent *&)select); - - nsIView* view; - GetView(view); - - nsIWidget* widget; - view->GetWidget(widget); - nsIListWidget* list; - if ((nsnull == widget) || NS_FAILED(widget->QueryInterface(kListWidgetIID, (void **) &list))) { - NS_ASSERTION(PR_FALSE, "invalid widget"); - return; - } - widget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); - - const nsStyleFont* styleFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); - if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || - (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { - nsFont widgetFont(styleFont->mFixedFont); - widgetFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight - widgetFont.size = styleFont->mFont.size; // normal font size - if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { - widgetFont.name = "Arial"; // XXX windows specific font - } - widget->SetFont(widgetFont); - } - else { - // use arial, scaled down one HTML size - // italics, decoration & variant(?) get used - nsFont widgetFont(styleFont->mFont); - widgetFont.name = "Arial"; // XXX windows specific font - widgetFont.weight = NS_FONT_WEIGHT_NORMAL; - const nsFont& normal = aPresContext->GetDefaultFont(); - PRInt32 scaler = aPresContext->GetFontScaler(); - float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); - PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(widgetFont.size, (PRInt32)normal.size, scaleFactor); - widgetFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); - widget->SetFont(widgetFont); - } - - PRInt32 numChildren; - select->ChildCount(numChildren); - int optionX = -1; - for (int childX = 0; childX < numChildren; childX++) { - nsIContent* child; - select->ChildAt(childX, child); - nsOption* option; - nsresult result = child->QueryInterface(kOptionIID, (void**)&option); - if (NS_OK == result) { - optionX++; - nsString text; - if (PR_TRUE != option->GetContent(text)) { - text = " "; - } - list->AddItemAt(text, optionX); - NS_RELEASE(option); - } - NS_RELEASE(child); - } - - NS_RELEASE(list); - NS_RELEASE(widget); - - select->Reset(); // initializes selections -} - -// nsSelect - -nsSelect::nsSelect(nsIAtom* aTag, nsIFormManager* aFormMan) - : nsInput(aTag, aFormMan), mIsComboBox(PR_FALSE) -{ - mMultiple = PR_FALSE; -} - -nsSelect::~nsSelect() -{ -} - -void nsSelect::GetType(nsString& aResult) const -{ - aResult = "select"; -} - -NS_IMETHODIMP -nsSelect::SetAttribute(nsIAtom* aAttribute, - const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::multiple) { - mMultiple = PR_TRUE; - } - return nsSelectSuper::SetAttribute(aAttribute, aValue, aNotify); -} - -NS_IMETHODIMP -nsSelect::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const -{ - aResult.Reset(); - if (aAttribute == nsHTMLAtoms::multiple) { - return GetCacheAttribute(mMultiple, aResult, eHTMLUnit_Empty); - } - else { - return nsSelectSuper::GetAttribute(aAttribute, aResult); - } -} - - -PRInt32 -nsSelect::GetMaxNumValues() -{ - if (mMultiple) { - PRInt32 n; - ChildCount(n); - return n; - } - else { - return 1; - } -} - -nsOption* nsSelect::GetNthOption(PRInt32 aIndex) -{ - int optionX = -1; - PRInt32 numChildren; - ChildCount(numChildren); - for (int childX = 0; childX < numChildren; childX++) { - nsIContent* child; - ChildAt(childX, child); - nsOption* option; - nsresult result = child->QueryInterface(kOptionIID, (void**)&option); - if (NS_OK == result) { - optionX++; - if (aIndex == optionX) { - NS_RELEASE(child); - return option; - } - NS_RELEASE(option); - } - NS_RELEASE(child); - } - return nsnull; -} - -PRBool -nsSelect::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if ((aMaxNumValues <= 0) || (nsnull == mName)) { - //NS_ASSERTION(0, "invalid max num values"); // XXX remove this in branch - return PR_FALSE; - } - - if (!IsMultiple()) { - NS_ASSERTION(aMaxNumValues > 0, "invalid max num values"); - nsIListWidget* list; - nsresult stat = mWidget->QueryInterface(kListWidgetIID, (void **) &list); - NS_ASSERTION((NS_OK == stat), "invalid widget"); - PRInt32 index = list->GetSelectedIndex(); - NS_RELEASE(list); - if (index >= 0) { - nsOption* selected = GetNthOption(index); - if (selected) { - selected->GetNamesValues(aMaxNumValues, aNumValues, aValues, aNames); - aNames[0] = *mName; - NS_RELEASE(selected); // YYY remove this comment if ok - return PR_TRUE; - } - } - else { - aNumValues = 0; - return PR_FALSE; - } - } - else { - nsIListBox* list; - nsresult stat = mWidget->QueryInterface(kListBoxIID, (void **) &list); - NS_ASSERTION((NS_OK == stat), "invalid widget"); - PRInt32 numSelections = list->GetSelectedCount(); - NS_ASSERTION(aMaxNumValues >= numSelections, "invalid max num values"); - if (numSelections >= 0) { - PRInt32* selections = new PRInt32[numSelections]; - list->GetSelectedIndices(selections, numSelections); - NS_RELEASE(list); - PRInt32 numValues; - aNumValues = 0; - for (int i = 0; i < numSelections; i++) { - nsOption* selected = GetNthOption(selections[i]); - if (selected) { - selected->GetNamesValues(aMaxNumValues - i, numValues, - aValues + i, aNames + i); // options can only have 1 value - aNames[i] = *mName; - aNumValues += 1; - NS_RELEASE(selected); // YYY remove this comment if ok - } - } - delete [] selections; - return PR_TRUE; - } - else { - aNumValues = 0; - return PR_FALSE; - } - } - aNumValues = 0; - return PR_FALSE; -} - - -void -nsSelect::Reset() -{ -// PRBool allowMultiple; -// super::GetAttribute(nsHTMLAtoms::multiple, allowMultiple); - PRInt32 numChildren; - ChildCount(numChildren); - - nsIListWidget* list; - nsresult stat = mWidget->QueryInterface(kListWidgetIID, (void **) &list); - NS_ASSERTION((NS_OK == stat), "invalid widget"); - - list->Deselect(); - - PRInt32 selIndex = -1; - int optionX = -1; - for (int childX = 0; childX < numChildren; childX++) { - nsIContent* child; - ChildAt(childX, child); - nsOption* option; - nsresult result = child->QueryInterface(kOptionIID, (void**)&option); - if (NS_OK == result) { - optionX++; - PRInt32 selAttr; - ((nsInput *)option)->GetAttribute(nsHTMLAtoms::selected, selAttr); - if (ATTR_NOTSET != selAttr) { - list->SelectItem(optionX); - selIndex = optionX; - if (!mMultiple) { - break; - } - } - NS_RELEASE(option); - } - NS_RELEASE(child); - } - - // if none were selected, select 1st one if we are a combo box - if (mIsComboBox && (numChildren > 0) && (selIndex < 0)) { - list->SelectItem(0); - } - NS_RELEASE(list); -} - - -// nsOption - -nsOption::nsOption(nsIAtom* aTag) - : nsInput(aTag, nsnull) -{ - mContent = nsnull; - mSelected = PR_FALSE; -} - -nsOption::~nsOption() -{ - if (nsnull != mContent) { - delete mContent; - } -} - -void nsOption::GetType(nsString& aResult) const -{ - aResult = "select"; -} - -nsresult nsOption::QueryInterface(REFNSIID aIID, void** aInstancePtr) -{ - if (aIID.Equals(kOptionIID)) { - AddRef(); - *aInstancePtr = (void**) this; - return NS_OK; - } - return nsInput::QueryInterface(aIID, aInstancePtr); -} - -NS_IMETHODIMP -nsOption::SetAttribute(nsIAtom* aAttribute, - const nsString& aValue, - PRBool aNotify) -{ - if (aAttribute == nsHTMLAtoms::selected) { - mSelected = PR_TRUE; - // XXX aNotify - return NS_OK; - } - else { - return nsOptionSuper::SetAttribute(aAttribute, aValue, aNotify); - } -} - -NS_IMETHODIMP -nsOption::GetAttribute(nsIAtom* aAttribute, - nsHTMLValue& aResult) const -{ - aResult.Reset(); - if (aAttribute == nsHTMLAtoms::selected) { - return GetCacheAttribute(mSelected, aResult, eHTMLUnit_Empty); - } - else { - return nsOptionSuper::GetAttribute(aAttribute, aResult); - } -} - -PRInt32 -nsOption::GetMaxNumValues() -{ - return 1; -} - -PRBool nsOption::GetContent(nsString& aString) const -{ - if (nsnull == mContent) { - aString.SetLength(0); - return PR_FALSE; - } - else { - aString = *mContent; - return PR_TRUE; - } -} - -void nsOption::SetContent(const nsString& aString) -{ - if (nsnull == mContent) { - mContent = new nsString(); - } - *mContent = aString; -} - -void -nsOption::CompressContent() -{ - if (nsnull != mContent) { - mContent->CompressWhitespace(PR_TRUE, PR_TRUE); - } -} - -PRBool -nsOption::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames) -{ - if (aMaxNumValues <= 0) { - NS_ASSERTION(aMaxNumValues > 0, "invalid max num values"); - return PR_FALSE; - } - - nsString valAttr; - nsresult stat = nsHTMLTagContent::GetAttribute(nsHTMLAtoms::value, valAttr); - if (NS_CONTENT_ATTR_HAS_VALUE == stat) { - aValues[0] = valAttr; - aNumValues = 1; - return PR_TRUE; - } - else if (nsnull != mContent) { - aValues[0] = *mContent; - aNumValues = 1; - return PR_TRUE; - } - else { - aNumValues = 0; - return PR_FALSE; - } -} - -// FACTORY functions - -nsresult -NS_NewHTMLSelect(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag, nsIFormManager* aFormMan) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsSelect(aTag, aFormMan); - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} - -nsresult -NS_NewHTMLOption(nsIHTMLContent** aInstancePtrResult, - nsIAtom* aTag) -{ - NS_PRECONDITION(nsnull != aInstancePtrResult, "null ptr"); - if (nsnull == aInstancePtrResult) { - return NS_ERROR_NULL_POINTER; - } - - nsIHTMLContent* it = new nsOption(aTag); - - if (nsnull == it) { - return NS_ERROR_OUT_OF_MEMORY; - } - return it->QueryInterface(kIHTMLContentIID, (void**) aInstancePtrResult); -} diff --git a/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp b/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp new file mode 100644 index 00000000000..502f714aa8b --- /dev/null +++ b/mozilla/layout/html/forms/src/nsSelectControlFrame.cpp @@ -0,0 +1,581 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +// YY need to pass isMultiple before create called + +#include "nsFormControlFrame.h" +#include "nsIDOMNode.h" +#include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsIDOMHTMLCollection.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIFrame.h" +#include "nsISupports.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsIRadioButton.h" +#include "nsWidgetsCID.h" +#include "nsSize.h" +#include "nsHTMLAtoms.h" +#include "nsIView.h" +#include "nsIListWidget.h" +#include "nsIComboBox.h" +#include "nsIListBox.h" +#include "nsIStyleContext.h" +#include "nsStyleConsts.h" +#include "nsStyleUtil.h" +#include "nsFont.h" + +static NS_DEFINE_IID(kIDOMHTMLSelectElementIID, NS_IDOMHTMLSELECTELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLOptionElementIID, NS_IDOMHTMLOPTIONELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLCollectionIID, NS_IDOMHTMLCOLLECTION_IID); +static NS_DEFINE_IID(kIDOMNodeIID, NS_IDOMNODE_IID); +static NS_DEFINE_IID(kListWidgetIID, NS_ILISTWIDGET_IID); +static NS_DEFINE_IID(kComboBoxIID, NS_ICOMBOBOX_IID); +static NS_DEFINE_IID(kListBoxIID, NS_ILISTBOX_IID); +static NS_DEFINE_IID(kComboCID, NS_COMBOBOX_CID); +static NS_DEFINE_IID(kListCID, NS_LISTBOX_CID); + + +class nsOption; + +class nsSelectControlFrame : public nsFormControlFrame { +public: + nsSelectControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + virtual PRInt32 GetMaxNumValues(); + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + + NS_METHOD GetMultiple(PRBool* aResult, nsIDOMHTMLSelectElement* aSelect = nsnull); + virtual void Reset(); + +protected: + nsIDOMHTMLSelectElement* GetSelect(); + nsIDOMHTMLCollection* GetOptions(nsIDOMHTMLSelectElement* aSelect = nsnull); + nsIDOMHTMLOptionElement* GetOption(nsIDOMHTMLCollection& aOptions, PRUint32 aIndex); + PRBool GetOptionValue(nsIDOMHTMLCollection& aCollecton, PRUint32 aIndex, nsString& aValue); + + virtual ~nsSelectControlFrame(); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); + + PRBool mIsComboBox; + PRBool mOptionsAdded; +}; + +nsresult +NS_NewSelectControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsSelectControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsSelectControlFrame::nsSelectControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ + mIsComboBox = PR_FALSE; + mOptionsAdded = PR_FALSE; +} + +nsSelectControlFrame::~nsSelectControlFrame() +{ +} + + +nscoord +nsSelectControlFrame::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(1, aPixToTwip); +} + +nscoord +nsSelectControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +nscoord +nsSelectControlFrame::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ +#ifdef XP_PC + return (nscoord)NSToIntRound(float(aInnerHeight) * 0.15f); +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(1, aPixToTwip); // XXX this is probably wrong +#endif +} + +PRInt32 +nsSelectControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ +#ifdef XP_PC + nscoord padding = (nscoord)NSToIntRound(float(aCharWidth) * 0.40f); + nscoord min = NSIntPixelsToTwips(3, aPixToTwip); + if (padding > min) { + return padding; + } else { + return min; + } +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(7, aPixToTwip); // XXX this is probably wrong +#endif +} + +const nsIID& +nsSelectControlFrame::GetIID() +{ + if (mIsComboBox) { + return kComboBoxIID; + } else { + return kListBoxIID; + } +} + +const nsIID& +nsSelectControlFrame::GetCID() +{ + if (mIsComboBox) { + return kComboCID; + } else { + return kListCID; + } +} + +void +nsSelectControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + nsIDOMHTMLSelectElement* select = GetSelect(); + if (!select) { + return; + } + nsIDOMHTMLCollection* options = GetOptions(select); + if (!options) { + return; + } + // get the css size + nsSize styleSize; + GetStyleSize(*aPresContext, aReflowState, styleSize); + + // get the size of the longest option + PRInt32 maxWidth = 1; + PRUint32 numOptions; + options->GetLength(&numOptions); + for (PRUint32 i = 0; i < numOptions; i++) { + nsIDOMHTMLOptionElement* option = GetOption(*options, i); + if (option) { + //option->CompressContent(); + nsAutoString text; + if (NS_CONTENT_ATTR_HAS_VALUE != option->GetText(text)) { + continue; + } + nsSize textSize; + // use the style for the select rather that the option, since widgets don't support it + nsFormControlFrame::GetTextSize(*aPresContext, this, text, textSize); + if (textSize.width > maxWidth) { + maxWidth = textSize.width; + } + NS_RELEASE(option); + } + } + + PRInt32 rowHeight = 0; + nsSize calcSize, charSize; + PRBool widthExplicit, heightExplicit; + nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, nsnull, + maxWidth, PR_TRUE, nsHTMLAtoms::size, 1); + // XXX fix CalculateSize to return PRUint32 + PRUint32 numRows = (PRUint32)CalculateSize(aPresContext, this, styleSize, textSpec, + calcSize, widthExplicit, heightExplicit, rowHeight); + + // here it is determined whether we are a combo box + PRInt32 sizeAttr; + GetSize(&sizeAttr); + PRBool multiple; + if (!GetMultiple(&multiple) && + ((1 >= sizeAttr) || ((ATTR_NOTSET == sizeAttr) && (1 >= numRows)))) { + mIsComboBox = PR_TRUE; + } + + aDesiredLayoutSize.width = calcSize.width; + // account for vertical scrollbar, if present + if (!widthExplicit && ((numRows < numOptions) || mIsComboBox)) { + float p2t = aPresContext->GetPixelsToTwips(); + aDesiredLayoutSize.width += GetScrollbarWidth(p2t); + } + + // XXX put this in widget library, combo boxes are fixed height (visible part) + aDesiredLayoutSize.height = mIsComboBox ? 350 : calcSize.height; + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; + + aDesiredWidgetSize.width = aDesiredLayoutSize.width; + aDesiredWidgetSize.height = aDesiredLayoutSize.height; + if (mIsComboBox) { // add in pull down size + aDesiredWidgetSize.height += (rowHeight * (numOptions > 20 ? 20 : numOptions)) + 100; + } + + NS_RELEASE(options); +} + +nsWidgetInitData* +nsSelectControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) +{ + if (mIsComboBox) { + nsComboBoxInitData* initData = new nsComboBoxInitData(); + initData->clipChildren = PR_TRUE; + float twipToPix = aPresContext.GetTwipsToPixels(); + initData->mDropDownHeight = NSTwipsToIntPixels(mWidgetSize.height, twipToPix); + return initData; + } else { + PRBool multiple; + GetMultiple(&multiple); + nsListBoxInitData* initData = nsnull; + if (multiple) { + initData = new nsListBoxInitData(); + initData->clipChildren = PR_TRUE; + initData->mMultiSelect = PR_TRUE; + } + return initData; + } +} + +NS_IMETHODIMP +nsSelectControlFrame::GetMultiple(PRBool* aMultiple, nsIDOMHTMLSelectElement* aSelect) +{ + if (!aSelect) { + nsIDOMHTMLSelectElement* select = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); + if ((NS_OK == result) && select) { + result = select->GetMultiple(aMultiple); + NS_RELEASE(select); + } + return result; + } else { + return aSelect->GetMultiple(aMultiple); + } +} + +nsIDOMHTMLSelectElement* +nsSelectControlFrame::GetSelect() +{ + nsIDOMHTMLSelectElement* select = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLSelectElementIID, (void**)&select); + if ((NS_OK == result) && select) { + return select; + } else { + return nsnull; + } +} + +nsIDOMHTMLCollection* +nsSelectControlFrame::GetOptions(nsIDOMHTMLSelectElement* aSelect) +{ + nsIDOMHTMLCollection* options = nsnull; + if (!aSelect) { + nsIDOMHTMLSelectElement* select = GetSelect(); + if (select) { + select->GetOptions(&options); + NS_RELEASE(select); + return options; + } else { + return nsnull; + } + } else { + aSelect->GetOptions(&options); + return options; + } +} + +void +nsSelectControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + if (!mWidget) { + return; + } + + nsIListWidget* listWidget; + if (NS_OK != mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget)) { + NS_ASSERTION(PR_FALSE, "invalid widget"); + return; + } + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + + const nsStyleFont* styleFont = (const nsStyleFont*)mStyleContext->GetStyleData(eStyleStruct_Font); + if ((styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT) || + (styleFont->mFlags & NS_STYLE_FONT_SIZE_EXPLICIT)) { + nsFont widgetFont(styleFont->mFixedFont); + widgetFont.weight = NS_FONT_WEIGHT_NORMAL; // always normal weight + widgetFont.size = styleFont->mFont.size; // normal font size + if (0 == (styleFont->mFlags & NS_STYLE_FONT_FACE_EXPLICIT)) { + widgetFont.name = "Arial"; // XXX windows specific font + } + mWidget->SetFont(widgetFont); + } else { + // use arial, scaled down one HTML size + // italics, decoration & variant(?) get used + nsFont widgetFont(styleFont->mFont); + widgetFont.name = "Arial"; // XXX windows specific font + widgetFont.weight = NS_FONT_WEIGHT_NORMAL; + const nsFont& normal = aPresContext->GetDefaultFont(); + PRInt32 scaler = aPresContext->GetFontScaler(); + float scaleFactor = nsStyleUtil::GetScalingFactor(scaler); + PRInt32 fontIndex = nsStyleUtil::FindNextSmallerFontSize(widgetFont.size, (PRInt32)normal.size, scaleFactor); + widgetFont.size = nsStyleUtil::CalcFontPointSize(fontIndex, (PRInt32)normal.size, scaleFactor); + mWidget->SetFont(widgetFont); + } + + // add the options + if (!mOptionsAdded) { + nsIDOMHTMLCollection* options = GetOptions(); + if (options) { + PRUint32 numOptions; + options->GetLength(&numOptions); + nsIDOMNode* node; + nsIDOMHTMLOptionElement* option; + for (PRUint32 i = 0; i < numOptions; i++) { + options->Item(i, &node); + if (node) { + nsresult result = node->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + if ((NS_OK == result) && option) { + nsString text; + // XXX need to compress whitespace + if (NS_CONTENT_ATTR_HAS_VALUE != option->GetText(text)) { + text = " "; + } + listWidget->AddItemAt(text, i); + NS_RELEASE(option); + } + NS_RELEASE(node); + } + } + NS_RELEASE(options); + } + mOptionsAdded = PR_TRUE; + } + + NS_RELEASE(listWidget); + + Reset(); // initializes selections +} + + +PRInt32 +nsSelectControlFrame::GetMaxNumValues() +{ + PRBool multiple; + GetMultiple(&multiple); + if (multiple) { + PRUint32 length = 0; + nsIDOMHTMLCollection* options = GetOptions(); + if (options) { + options->GetLength(&length); + } + return (PRInt32)length; // XXX fix return on GetMaxNumValues + } else { + return 1; + } +} + +PRBool +nsSelectControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + aNumValues = 0; + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_NOT_THERE == result)) { + return PR_FALSE; + } + + nsIDOMHTMLCollection* options = GetOptions(); + if (!options) { + return PR_FALSE; + } + + PRBool status = PR_FALSE; + PRBool multiple; + GetMultiple(&multiple); + if (!multiple) { + nsIListWidget* listWidget; + result = mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget); + if ((NS_OK == result) && listWidget) { + PRInt32 index = listWidget->GetSelectedIndex(); + NS_RELEASE(listWidget); + if (index >= 0) { + nsAutoString value; + GetOptionValue(*options, index, value); + aNames[0] = name; + aValues[0] = value; + status = PR_TRUE; + } + } + } else { + nsIListBox* listBox; + nsresult result = mWidget->QueryInterface(kListBoxIID, (void **) &listBox); + if ((NS_OK == result) && listBox) { + PRInt32 numSelections = listBox->GetSelectedCount(); + NS_ASSERTION(aMaxNumValues >= numSelections, "invalid max num values"); + if (numSelections >= 0) { + PRInt32* selections = new PRInt32[numSelections]; + listBox->GetSelectedIndices(selections, numSelections); + aNumValues = 0; + for (int i = 0; i < numSelections; i++) { + nsAutoString value; + GetOptionValue(*options, i, value); + aNames[i] = name; + aValues[i] = value; + aNumValues++; + } + delete[] selections; + status = PR_TRUE; + } + NS_RELEASE(listBox); + } + } + + NS_RELEASE(options); + + return status; +} + + +void +nsSelectControlFrame::Reset() +{ + nsIDOMHTMLCollection* options = GetOptions(); + if (!options) { + return; + } + + PRBool multiple; + GetMultiple(&multiple); + + PRUint32 numOptions; + options->GetLength(&numOptions); + + PRInt32 selectedIndex = -1; + nsIListWidget* listWidget; + nsresult result = mWidget->QueryInterface(kListWidgetIID, (void **) &listWidget); + if ((NS_OK == result) && listWidget) { + listWidget->Deselect(); + for (PRUint32 i = 0; i < numOptions; i++) { + nsIDOMHTMLOptionElement* option = GetOption(*options, i); + if (option) { + PRBool selected = PR_FALSE; + option->GetSelected(&selected); + if (selected) { + listWidget->SelectItem(i); + selectedIndex = i; + if (!multiple) { + break; + } + } + NS_RELEASE(option); + } + } + } + + // if none were selected, select 1st one if we are a combo box + if (mIsComboBox && (numOptions > 0) && (selectedIndex < 0)) { + listWidget->SelectItem(0); + } + NS_RELEASE(listWidget); + NS_RELEASE(options); +} + + + +/* XXX add this to nsHTMLOptionElement.cpp +void +nsOption::CompressContent() +{ + if (nsnull != mContent) { + mContent->CompressWhitespace(PR_TRUE, PR_TRUE); + } +}*/ + +nsIDOMHTMLOptionElement* +nsSelectControlFrame::GetOption(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex) +{ + nsIDOMNode* node = nsnull; + PRBool status = PR_FALSE; + if ((NS_OK == aCollection.Item(aIndex, &node)) && node) { + nsIDOMHTMLOptionElement* option = nsnull; + nsresult result = node->QueryInterface(kIDOMHTMLOptionElementIID, (void**)&option); + NS_RELEASE(node); + return option; + } + return nsnull; +} + +PRBool +nsSelectControlFrame::GetOptionValue(nsIDOMHTMLCollection& aCollection, PRUint32 aIndex, nsString& aValue) +{ + PRBool status = PR_FALSE; + nsIDOMHTMLOptionElement* option = GetOption(aCollection, aIndex); + if (option) { + if (NS_CONTENT_ATTR_HAS_VALUE == option->GetValue(aValue)) { + status = PR_TRUE; + } else { + if (NS_CONTENT_ATTR_HAS_VALUE == option->GetText(aValue)) { + status = PR_TRUE; + } + } + NS_RELEASE(option); + } + return status; +} + diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp new file mode 100644 index 00000000000..4eb946c6548 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp @@ -0,0 +1,374 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#include "nsTextControlFrame.h" +#include "nsIContent.h" +#include "prtypes.h" +#include "nsIFrame.h" +#include "nsISupports.h" +#include "nsIAtom.h" +#include "nsIPresContext.h" +#include "nsIHTMLContent.h" +#include "nsHTMLIIDs.h" +#include "nsITextWidget.h" +#include "nsITextAreaWidget.h" +#include "nsWidgetsCID.h" +#include "nsSize.h" +#include "nsString.h" +#include "nsHTMLAtoms.h" +#include "nsIStyleContext.h" +#include "nsFont.h" +#include "nsDOMEvent.h" +#include "nsIFormControl.h" +#include "nsFormFrame.h" +#include "nsIContent.h" +#include "nsIDOMHTMLInputElement.h" +#include "nsIDOMHTMLTextAreaElement.h" + +static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); +static NS_DEFINE_IID(kTextCID, NS_TEXTFIELD_CID); +static NS_DEFINE_IID(kTextAreaCID, NS_TEXTAREA_CID); +static NS_DEFINE_IID(kITextWidgetIID, NS_ITEXTWIDGET_IID); +static NS_DEFINE_IID(kITextAreaWidgetIID, NS_ITEXTAREAWIDGET_IID); +static NS_DEFINE_IID(kIDOMHTMLTextAreaElementIID, NS_IDOMHTMLTEXTAREAELEMENT_IID); +static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); + +nsresult +NS_NewTextControlFrame(nsIContent* aContent, + nsIFrame* aParent, + nsIFrame*& aResult) +{ + aResult = new nsTextControlFrame(aContent, aParent); + if (nsnull == aResult) { + return NS_ERROR_OUT_OF_MEMORY; + } + return NS_OK; +} + +nsTextControlFrame::nsTextControlFrame(nsIContent* aContent, + nsIFrame* aParentFrame) + : nsFormControlFrame(aContent, aParentFrame) +{ +} + +nsTextControlFrame::~nsTextControlFrame() +{ +} + +nscoord +nsTextControlFrame::GetVerticalBorderWidth(float aPixToTwip) const +{ + return NSIntPixelsToTwips(4, aPixToTwip); +} + +nscoord +nsTextControlFrame::GetHorizontalBorderWidth(float aPixToTwip) const +{ + return GetVerticalBorderWidth(aPixToTwip); +} + +// for a text area aInnerHeight is the height of one line +nscoord +nsTextControlFrame::GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const +{ +#ifdef XP_PC + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return (nscoord)NSToIntRound(float(aInnerHeight) * 0.40f); + } else { + return (nscoord)NSToIntRound(float(aInnerHeight) * 0.25f); + } +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(10, aPixToTwip); // XXX this is probably wrong +#endif +} + +nscoord +nsTextControlFrame::GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const +{ +#ifdef XP_PC + nscoord padding; + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + padding = (nscoord)(40 * aCharWidth / 100); + } else { + padding = (nscoord)(55 * aCharWidth / 100); + } + nscoord min = NSIntPixelsToTwips(3, aPixToTwip); + if (padding > min) { + return padding; + } else { + return min; + } +#endif +#ifdef XP_UNIX + return NSIntPixelsToTwips(6, aPixToTwip); // XXX this is probably wrong +#endif +} + + +const nsIID& +nsTextControlFrame::GetIID() +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return kITextAreaWidgetIID; + } else { + return kITextWidgetIID; + } +} + +const nsIID& +nsTextControlFrame::GetCID() +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_TEXTAREA == type) { + return kTextAreaCID; + } else { + return kTextCID; + } +} + +void +nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) +{ + if (mFormFrame && mFormFrame->CanSubmit(*this)) { + nsEventStatus mStatus = nsEventStatus_eIgnore; + nsEvent mEvent; + mEvent.eventStructType = NS_EVENT; + mEvent.message = NS_FORM_SUBMIT; + mContent->HandleDOMEvent(aPresContext, &mEvent, nsnull, DOM_EVENT_INIT, mStatus); + + mFormFrame->OnSubmit(&aPresContext, this); + } +} + +void +nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize) +{ + // get the css size and let the frame use or override it + nsSize styleSize; + GetStyleSize(*aPresContext, aReflowState, styleSize); + + nsSize size; + + PRBool widthExplicit, heightExplicit; + PRInt32 ignore; + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { + PRInt32 width; + if (NS_CONTENT_ATTR_HAS_VALUE != GetSize(&width)) { + width = 20; + } + // Nav Quirk!! + width += 1; + nsInputDimensionSpec textSpec(nsnull, PR_FALSE, nsnull, + nsnull, width, PR_FALSE, nsnull, 1); + CalculateSize(aPresContext, this, styleSize, textSpec, size, + widthExplicit, heightExplicit, ignore); + } else { + nsInputDimensionSpec areaSpec(nsHTMLAtoms::cols, PR_FALSE, nsnull, nsnull, 20, + PR_FALSE, nsHTMLAtoms::rows, 1); + CalculateSize(aPresContext, this, styleSize, areaSpec, size, + widthExplicit, heightExplicit, ignore); + } + + if (NS_FORM_TEXTAREA == type) { + float p2t = aPresContext->GetPixelsToTwips(); + nscoord scrollbarWidth = GetScrollbarWidth(p2t); + + if (!heightExplicit) { + size.height += scrollbarWidth; + } + if (!widthExplicit) { + size.width += scrollbarWidth; + } + } + + + aDesiredLayoutSize.width = size.width; + aDesiredLayoutSize.height = size.height; + aDesiredLayoutSize.ascent = aDesiredLayoutSize.height; + aDesiredLayoutSize.descent = 0; + aDesiredWidgetSize.width = aDesiredLayoutSize.width; + aDesiredWidgetSize.height = aDesiredLayoutSize.height; +} + +nsWidgetInitData* +nsTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) +{ + PRInt32 type; + GetType(&type); + + nsTextWidgetInitData* data = nsnull; + + if (NS_FORM_INPUT_PASSWORD == type) { + data = new nsTextWidgetInitData(); + data->clipChildren = PR_TRUE; + data->mIsPassword = PR_TRUE; + } + + return data; +} + +NS_IMETHODIMP +nsTextControlFrame::GetText(nsString* aText) +{ + nsresult result = NS_CONTENT_ATTR_NOT_THERE; + PRInt32 type; + GetType(&type); + if (NS_FORM_INPUT_TEXT == type) { + nsIDOMHTMLInputElement* textElem = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); + if ((NS_OK == result) && textElem) { + result = textElem->GetValue(*aText); + NS_RELEASE(textElem); + } + } else { + nsIDOMHTMLTextAreaElement* textArea = nsnull; + nsresult result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + if ((NS_OK == result) && textArea) { + result = textArea->GetDefaultValue(*aText); + NS_RELEASE(textArea); + } + } + return result; +} + +void +nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext) +{ + if (!mWidget) { + return; + } + + PRInt32 type; + GetType(&type); + + const nsStyleFont* fontStyle = (const nsStyleFont*)(mStyleContext->GetStyleData(eStyleStruct_Font)); + mWidget->SetFont(fontStyle->mFixedFont); + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + + PRUint32 ignore; + + nsAutoString value; + GetText(&value); + + nsITextAreaWidget* textArea = nsnull; + nsITextWidget* text = nsnull; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + text->SetText(value, ignore); + PRInt32 maxLength; + nsresult result = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != result) { + text->SetMaxTextLength(maxLength); + } + NS_RELEASE(text); + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + textArea->SetText(value, ignore); + mWidget->SetBackgroundColor(NS_RGB(0xFF, 0xFF, 0xFF)); + NS_RELEASE(textArea); + } +} + +PRInt32 +nsTextControlFrame::GetMaxNumValues() +{ + return 1; +} + +PRBool +nsTextControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + if (!mWidget) { + return PR_FALSE; + } + + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_NOT_THERE == result)) { + return PR_FALSE; + } + + PRUint32 size; + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + + aNames[0] = name; + aNumValues = 1; + + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + text->GetText(aValues[0],0,size); // the last parm is not used + NS_RELEASE(text); + return PR_TRUE; + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + textArea->GetText(aValues[0],0,size); // the last parm is not used + NS_RELEASE(textArea); + return PR_TRUE; + } + return PR_FALSE; +} + + +void +nsTextControlFrame::Reset() +{ + if (!mWidget) { + return; + } + + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + + nsAutoString value; + nsresult valStatus = GetText(&value); + + PRUint32 size; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { + text->SetText(value,size); + } else { + text->SetText("",size); + } + NS_RELEASE(text); + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID,(void**)&textArea)) { + if (NS_CONTENT_ATTR_HAS_VALUE == valStatus) { + textArea->SetText(value,size); + } else { + textArea->SetText("",size); + } + NS_RELEASE(textArea); + } + +} + + diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.h b/mozilla/layout/html/forms/src/nsTextControlFrame.h new file mode 100644 index 00000000000..7a792801a05 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.h @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 2; 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. + */ + +#ifndef nsTextControlFrame_h___ +#define nsTextControlFrame_h___ + +#include "nsFormControlFrame.h" +class nsIContent; +class nsIFrame; +class nsIPresContext; + +class nsTextControlFrame : public nsFormControlFrame { +public: + nsTextControlFrame(nsIContent* aContent, nsIFrame* aParentFrame); + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + virtual void PostCreateWidget(nsIPresContext* aPresContext); + + virtual const nsIID& GetCID(); + + virtual const nsIID& GetIID(); + + NS_IMETHOD GetText(nsString* aValue); + + virtual void EnterPressed(nsIPresContext& aPresContext) ; + + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; + virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; + virtual nscoord GetVerticalInsidePadding(float aPixToTwip, + nscoord aInnerHeight) const; + virtual nscoord GetHorizontalInsidePadding(nsIPresContext& aPresContext, + float aPixToTwip, + nscoord aInnerWidth, + nscoord aCharWidth) const; + virtual PRInt32 GetMaxNumValues(); + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(); + +protected: + + virtual ~nsTextControlFrame(); + + virtual void GetDesiredSize(nsIPresContext* aPresContext, + const nsReflowState& aReflowState, + nsReflowMetrics& aDesiredLayoutSize, + nsSize& aDesiredWidgetSize); +}; + +#endif diff --git a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp index fa855959dfd..a5ca59f2a29 100644 --- a/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/html/style/src/nsHTMLStyleSheet.cpp @@ -948,40 +948,40 @@ HTMLStyleSheetImpl::CreateInputFrame(nsIContent* aContent, nsAutoString val; if (NS_OK == aContent->GetAttribute(nsAutoString("type"), val)) { if (val.EqualsIgnoreCase("submit")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("reset")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("button")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("checkbox")) { - rv = NS_NewInputCheckboxFrame(aContent, aParentFrame, aFrame); + rv = NS_NewCheckboxControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("file")) { - rv = NS_NewInputFileFrame(aContent, aParentFrame, aFrame); + rv = NS_NewFileControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("hidden")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("image")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("password")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewInputRadioFrame(aContent, aParentFrame, aFrame); + rv = NS_NewRadioControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("text")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } return rv; @@ -1177,10 +1177,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = CreateInputFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::textarea == aTag) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::select == aTag) { - rv = NS_NewHTMLSelectFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewSelectControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::applet == aTag) { rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); @@ -1195,6 +1195,9 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = NS_NewBodyFrame(aContent, aParentFrame, aNewFrame); processChildren = PR_TRUE; } + else if (nsHTMLAtoms::form == aTag) { + rv = NS_NewFormFrame(aContent, aParentFrame, aNewFrame); + } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aContent, aParentFrame, aNewFrame); } diff --git a/mozilla/layout/style/nsHTMLStyleSheet.cpp b/mozilla/layout/style/nsHTMLStyleSheet.cpp index fa855959dfd..a5ca59f2a29 100644 --- a/mozilla/layout/style/nsHTMLStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLStyleSheet.cpp @@ -948,40 +948,40 @@ HTMLStyleSheetImpl::CreateInputFrame(nsIContent* aContent, nsAutoString val; if (NS_OK == aContent->GetAttribute(nsAutoString("type"), val)) { if (val.EqualsIgnoreCase("submit")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("reset")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("button")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("checkbox")) { - rv = NS_NewInputCheckboxFrame(aContent, aParentFrame, aFrame); + rv = NS_NewCheckboxControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("file")) { - rv = NS_NewInputFileFrame(aContent, aParentFrame, aFrame); + rv = NS_NewFileControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("hidden")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("image")) { - rv = NS_NewInputButtonFrame(aContent, aParentFrame, aFrame); + rv = NS_NewButtonControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("password")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("radio")) { - rv = NS_NewInputRadioFrame(aContent, aParentFrame, aFrame); + rv = NS_NewRadioControlFrame(aContent, aParentFrame, aFrame); } else if (val.EqualsIgnoreCase("text")) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } } else { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aFrame); } return rv; @@ -1177,10 +1177,10 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = CreateInputFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::textarea == aTag) { - rv = NS_NewInputTextFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewTextControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::select == aTag) { - rv = NS_NewHTMLSelectFrame(aContent, aParentFrame, aNewFrame); + rv = NS_NewSelectControlFrame(aContent, aParentFrame, aNewFrame); } else if (nsHTMLAtoms::applet == aTag) { rv = NS_NewObjectFrame(aContent, aParentFrame, aNewFrame); @@ -1195,6 +1195,9 @@ HTMLStyleSheetImpl::ConstructFrameByTag(nsIPresContext* aPresContext, rv = NS_NewBodyFrame(aContent, aParentFrame, aNewFrame); processChildren = PR_TRUE; } + else if (nsHTMLAtoms::form == aTag) { + rv = NS_NewFormFrame(aContent, aParentFrame, aNewFrame); + } else if (nsHTMLAtoms::frameset == aTag) { rv = NS_NewHTMLFramesetFrame(aContent, aParentFrame, aNewFrame); }