diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index 3eb3c64d7ce..de1a107e60c 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -42,6 +42,7 @@ #include "nsIHTMLAttributes.h" #include "nsIFormControl.h" #include "nsIForm.h" +#include "nsIGfxTextControlFrame.h" #include "nsIDocument.h" #include "nsIPresShell.h" #include "nsIFormControlFrame.h" @@ -124,46 +125,7 @@ public: NS_IMPL_IDOMHTMLELEMENT_USING_GENERIC(mInner) // nsIDOMHTMLInputElement - NS_IMETHOD GetDefaultValue(nsString& aDefaultValue); - NS_IMETHOD SetDefaultValue(const nsString& aDefaultValue); - NS_IMETHOD GetDefaultChecked(PRBool* aDefaultChecked); - NS_IMETHOD SetDefaultChecked(PRBool aDefaultChecked); - NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm); - NS_IMETHOD GetAccept(nsString& aAccept); - NS_IMETHOD SetAccept(const nsString& aAccept); - NS_IMETHOD GetAccessKey(nsString& aAccessKey); - NS_IMETHOD SetAccessKey(const nsString& aAccessKey); - NS_IMETHOD GetAlign(nsString& aAlign); - NS_IMETHOD SetAlign(const nsString& aAlign); - NS_IMETHOD GetAlt(nsString& aAlt); - NS_IMETHOD SetAlt(const nsString& aAlt); - NS_IMETHOD GetChecked(PRBool* aChecked); - NS_IMETHOD SetChecked(PRBool aChecked); - NS_IMETHOD GetDisabled(PRBool* aDisabled); - NS_IMETHOD SetDisabled(PRBool aDisabled); - NS_IMETHOD GetMaxLength(PRInt32* aMaxLength); - NS_IMETHOD SetMaxLength(PRInt32 aMaxLength); - NS_IMETHOD GetName(nsString& aName); - NS_IMETHOD SetName(const nsString& aName); - NS_IMETHOD GetReadOnly(PRBool* aReadOnly); - NS_IMETHOD SetReadOnly(PRBool aReadOnly); - NS_IMETHOD GetSize(nsString& aSize); - NS_IMETHOD SetSize(const nsString& aSize); - NS_IMETHOD GetSrc(nsString& aSrc); - NS_IMETHOD SetSrc(const nsString& aSrc); - NS_IMETHOD GetTabIndex(PRInt32* aTabIndex); - NS_IMETHOD SetTabIndex(PRInt32 aTabIndex); - NS_IMETHOD GetType(nsString& aType); - NS_IMETHOD SetType(const nsString& aType); - NS_IMETHOD GetUseMap(nsString& aUseMap); - NS_IMETHOD SetUseMap(const nsString& aUseMap); - NS_IMETHOD GetValue(nsString& aValue); - NS_IMETHOD SetValue(const nsString& aValue); - NS_IMETHOD Blur(); - NS_IMETHOD Focus(); - NS_IMETHOD Select(); - NS_IMETHOD Click(); - + NS_DECL_IDOMHTMLINPUTELEMENT // nsIDOMNSHTMLInputElement NS_DECL_IDOMNSHTMLINPUTELEMENT @@ -192,6 +154,10 @@ public: nsIStatefulFrame::StateType aStateType, PRBool aValue); +protected: + + nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); + protected: nsGenericHTMLLeafElement mInner; nsIForm* mForm; @@ -701,11 +667,11 @@ nsHTMLInputElement::Select() nsIFormControlFrame* formControlFrame = nsnull; nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); if (NS_SUCCEEDED(rv)) { - if (nsnull != formControlFrame ) { - nsIPresContext* presContext; - nsGenericHTMLElement::GetPresContext(this, &presContext); + if (formControlFrame ) + { + nsCOMPtr presContext; + nsGenericHTMLElement::GetPresContext(this, getter_AddRefs(presContext)); formControlFrame->SetProperty(presContext, nsHTMLAtoms::select, ""); - NS_IF_RELEASE(presContext); return NS_OK; } } @@ -725,16 +691,16 @@ nsHTMLInputElement::Click() if (shell) { rv = shell->GetPresContext(getter_AddRefs(context)); if (NS_SUCCEEDED(rv) && context) { - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event; - event.eventStructType = NS_GUI_EVENT; - event.message = NS_MOUSE_LEFT_CLICK; - event.isShift = PR_FALSE; - event.isControl = PR_FALSE; - event.isAlt = PR_FALSE; - event.isMeta = PR_FALSE; - event.clickCount = 0; - event.widget = nsnull; + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_GUI_EVENT; + event.message = NS_MOUSE_LEFT_CLICK; + event.isShift = PR_FALSE; + event.isControl = PR_FALSE; + event.isAlt = PR_FALSE; + event.isMeta = PR_FALSE; + event.clickCount = 0; + event.widget = nsnull; rv = HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } } @@ -1188,3 +1154,103 @@ nsHTMLInputElement::GetControllers(nsIControllers** aResult) NS_IF_ADDREF(*aResult); return NS_OK; } + +NS_IMETHODIMP +nsHTMLInputElement::GetTextLength(PRInt32* aTextLength) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->GetTextLength(aTextLength); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetSelectionStart(PRInt32* aSelectionStart) +{ + NS_ENSURE_ARG_POINTER(aSelectionStart); + + PRInt32 selEnd; + return GetSelectionRange(aSelectionStart, &selEnd); +} + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionStart(aSelectionStart); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetSelectionEnd(PRInt32* aSelectionEnd) +{ + NS_ENSURE_ARG_POINTER(aSelectionEnd); + + PRInt32 selStart; + return GetSelectionRange(&selStart, aSelectionEnd); +} + + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionEnd(aSelectionEnd); + + return NS_OK; + } + return rv; +} + +nsresult +nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->GetSelectionRange(aSelectionStart, aSelectionEnd); + + return NS_OK; + } + return rv; +} + diff --git a/layout/forms/nsITextControlFrame.h b/layout/forms/nsITextControlFrame.h index c48d5f47b21..96e00307a8d 100644 --- a/layout/forms/nsITextControlFrame.h +++ b/layout/forms/nsITextControlFrame.h @@ -35,7 +35,16 @@ class nsIGfxTextControlFrame : public nsISupports public: static const nsIID& GetIID() { static nsIID iid = NS_IGFXTEXTCONTROLFRAME_IID; return iid; } - NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; - NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; - NS_IMETHOD SetInnerFocus() = 0; + NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; + NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; + NS_IMETHOD SetInnerFocus() = 0; + + NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0; + + NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0; + NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0; + + NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) = 0; + NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) = 0; + }; diff --git a/layout/html/content/src/nsHTMLInputElement.cpp b/layout/html/content/src/nsHTMLInputElement.cpp index 3eb3c64d7ce..de1a107e60c 100644 --- a/layout/html/content/src/nsHTMLInputElement.cpp +++ b/layout/html/content/src/nsHTMLInputElement.cpp @@ -42,6 +42,7 @@ #include "nsIHTMLAttributes.h" #include "nsIFormControl.h" #include "nsIForm.h" +#include "nsIGfxTextControlFrame.h" #include "nsIDocument.h" #include "nsIPresShell.h" #include "nsIFormControlFrame.h" @@ -124,46 +125,7 @@ public: NS_IMPL_IDOMHTMLELEMENT_USING_GENERIC(mInner) // nsIDOMHTMLInputElement - NS_IMETHOD GetDefaultValue(nsString& aDefaultValue); - NS_IMETHOD SetDefaultValue(const nsString& aDefaultValue); - NS_IMETHOD GetDefaultChecked(PRBool* aDefaultChecked); - NS_IMETHOD SetDefaultChecked(PRBool aDefaultChecked); - NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm); - NS_IMETHOD GetAccept(nsString& aAccept); - NS_IMETHOD SetAccept(const nsString& aAccept); - NS_IMETHOD GetAccessKey(nsString& aAccessKey); - NS_IMETHOD SetAccessKey(const nsString& aAccessKey); - NS_IMETHOD GetAlign(nsString& aAlign); - NS_IMETHOD SetAlign(const nsString& aAlign); - NS_IMETHOD GetAlt(nsString& aAlt); - NS_IMETHOD SetAlt(const nsString& aAlt); - NS_IMETHOD GetChecked(PRBool* aChecked); - NS_IMETHOD SetChecked(PRBool aChecked); - NS_IMETHOD GetDisabled(PRBool* aDisabled); - NS_IMETHOD SetDisabled(PRBool aDisabled); - NS_IMETHOD GetMaxLength(PRInt32* aMaxLength); - NS_IMETHOD SetMaxLength(PRInt32 aMaxLength); - NS_IMETHOD GetName(nsString& aName); - NS_IMETHOD SetName(const nsString& aName); - NS_IMETHOD GetReadOnly(PRBool* aReadOnly); - NS_IMETHOD SetReadOnly(PRBool aReadOnly); - NS_IMETHOD GetSize(nsString& aSize); - NS_IMETHOD SetSize(const nsString& aSize); - NS_IMETHOD GetSrc(nsString& aSrc); - NS_IMETHOD SetSrc(const nsString& aSrc); - NS_IMETHOD GetTabIndex(PRInt32* aTabIndex); - NS_IMETHOD SetTabIndex(PRInt32 aTabIndex); - NS_IMETHOD GetType(nsString& aType); - NS_IMETHOD SetType(const nsString& aType); - NS_IMETHOD GetUseMap(nsString& aUseMap); - NS_IMETHOD SetUseMap(const nsString& aUseMap); - NS_IMETHOD GetValue(nsString& aValue); - NS_IMETHOD SetValue(const nsString& aValue); - NS_IMETHOD Blur(); - NS_IMETHOD Focus(); - NS_IMETHOD Select(); - NS_IMETHOD Click(); - + NS_DECL_IDOMHTMLINPUTELEMENT // nsIDOMNSHTMLInputElement NS_DECL_IDOMNSHTMLINPUTELEMENT @@ -192,6 +154,10 @@ public: nsIStatefulFrame::StateType aStateType, PRBool aValue); +protected: + + nsresult GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); + protected: nsGenericHTMLLeafElement mInner; nsIForm* mForm; @@ -701,11 +667,11 @@ nsHTMLInputElement::Select() nsIFormControlFrame* formControlFrame = nsnull; nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); if (NS_SUCCEEDED(rv)) { - if (nsnull != formControlFrame ) { - nsIPresContext* presContext; - nsGenericHTMLElement::GetPresContext(this, &presContext); + if (formControlFrame ) + { + nsCOMPtr presContext; + nsGenericHTMLElement::GetPresContext(this, getter_AddRefs(presContext)); formControlFrame->SetProperty(presContext, nsHTMLAtoms::select, ""); - NS_IF_RELEASE(presContext); return NS_OK; } } @@ -725,16 +691,16 @@ nsHTMLInputElement::Click() if (shell) { rv = shell->GetPresContext(getter_AddRefs(context)); if (NS_SUCCEEDED(rv) && context) { - nsEventStatus status = nsEventStatus_eIgnore; - nsMouseEvent event; - event.eventStructType = NS_GUI_EVENT; - event.message = NS_MOUSE_LEFT_CLICK; - event.isShift = PR_FALSE; - event.isControl = PR_FALSE; - event.isAlt = PR_FALSE; - event.isMeta = PR_FALSE; - event.clickCount = 0; - event.widget = nsnull; + nsEventStatus status = nsEventStatus_eIgnore; + nsMouseEvent event; + event.eventStructType = NS_GUI_EVENT; + event.message = NS_MOUSE_LEFT_CLICK; + event.isShift = PR_FALSE; + event.isControl = PR_FALSE; + event.isAlt = PR_FALSE; + event.isMeta = PR_FALSE; + event.clickCount = 0; + event.widget = nsnull; rv = HandleDOMEvent(context, &event, nsnull, NS_EVENT_FLAG_INIT, &status); } } @@ -1188,3 +1154,103 @@ nsHTMLInputElement::GetControllers(nsIControllers** aResult) NS_IF_ADDREF(*aResult); return NS_OK; } + +NS_IMETHODIMP +nsHTMLInputElement::GetTextLength(PRInt32* aTextLength) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->GetTextLength(aTextLength); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionRange(aSelectionStart, aSelectionEnd); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetSelectionStart(PRInt32* aSelectionStart) +{ + NS_ENSURE_ARG_POINTER(aSelectionStart); + + PRInt32 selEnd; + return GetSelectionRange(aSelectionStart, &selEnd); +} + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionStart(PRInt32 aSelectionStart) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionStart(aSelectionStart); + + return NS_OK; + } + return rv; +} + +NS_IMETHODIMP +nsHTMLInputElement::GetSelectionEnd(PRInt32* aSelectionEnd) +{ + NS_ENSURE_ARG_POINTER(aSelectionEnd); + + PRInt32 selStart; + return GetSelectionRange(&selStart, aSelectionEnd); +} + + +NS_IMETHODIMP +nsHTMLInputElement::SetSelectionEnd(PRInt32 aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->SetSelectionEnd(aSelectionEnd); + + return NS_OK; + } + return rv; +} + +nsresult +nsHTMLInputElement::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) +{ + nsIFormControlFrame* formControlFrame = nsnull; + nsresult rv = nsGenericHTMLElement::GetPrimaryFrame(this, formControlFrame); + if (NS_SUCCEEDED(rv) && formControlFrame) + { + nsCOMPtr textControlFrame(do_QueryInterface(formControlFrame)); + if (textControlFrame) + textControlFrame->GetSelectionRange(aSelectionStart, aSelectionEnd); + + return NS_OK; + } + return rv; +} + diff --git a/layout/html/forms/public/nsIGfxTextControlFrame.h b/layout/html/forms/public/nsIGfxTextControlFrame.h index c48d5f47b21..96e00307a8d 100644 --- a/layout/html/forms/public/nsIGfxTextControlFrame.h +++ b/layout/html/forms/public/nsIGfxTextControlFrame.h @@ -35,7 +35,16 @@ class nsIGfxTextControlFrame : public nsISupports public: static const nsIID& GetIID() { static nsIID iid = NS_IGFXTEXTCONTROLFRAME_IID; return iid; } - NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; - NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; - NS_IMETHOD SetInnerFocus() = 0; + NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; + NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; + NS_IMETHOD SetInnerFocus() = 0; + + NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0; + + NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0; + NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0; + + NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) = 0; + NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) = 0; + }; diff --git a/layout/html/forms/public/nsITextControlFrame.h b/layout/html/forms/public/nsITextControlFrame.h index c48d5f47b21..96e00307a8d 100644 --- a/layout/html/forms/public/nsITextControlFrame.h +++ b/layout/html/forms/public/nsITextControlFrame.h @@ -35,7 +35,16 @@ class nsIGfxTextControlFrame : public nsISupports public: static const nsIID& GetIID() { static nsIID iid = NS_IGFXTEXTCONTROLFRAME_IID; return iid; } - NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; - NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; - NS_IMETHOD SetInnerFocus() = 0; + NS_IMETHOD GetEditor(nsIEditor **aEditor) = 0; + NS_IMETHOD GetDocShell(nsIDocShell** aDocShell) = 0; + NS_IMETHOD SetInnerFocus() = 0; + + NS_IMETHOD GetTextLength(PRInt32* aTextLength) = 0; + + NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart) = 0; + NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd) = 0; + + NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd) = 0; + NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) = 0; + }; diff --git a/layout/html/forms/src/nsGfxTextControlFrame.cpp b/layout/html/forms/src/nsGfxTextControlFrame.cpp index 2a5249e90bc..469311706a9 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.cpp +++ b/layout/html/forms/src/nsGfxTextControlFrame.cpp @@ -80,11 +80,13 @@ #include "nsIDOMCharacterData.h" #include "nsIDocument.h" #include "nsIDOMDocument.h" +#include "nsIDOMHTMLDocument.h" #include "nsIDOMEventReceiver.h" #include "nsIPresShell.h" #include "nsIEventStateManager.h" #include "nsStyleUtil.h" #include "nsLinebreakConverter.h" +#include "nsRange.h" // for anonymous content and frames #include "nsHTMLParts.h" @@ -100,7 +102,6 @@ #include "nsLayoutAtoms.h" - static NS_DEFINE_IID(kIFrameIID, NS_IFRAME_IID); static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); static NS_DEFINE_IID(kTextCID, NS_TEXTFIELD_CID); @@ -181,144 +182,6 @@ NS_NewGfxTextControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) return NS_OK; } -// Frames are not refcounted, no need to AddRef -NS_IMETHODIMP -nsGfxTextControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) -{ - NS_PRECONDITION(0 != aInstancePtr, "null ptr"); - if (NULL == aInstancePtr) { - return NS_ERROR_NULL_POINTER; - - } else if (aIID.Equals(NS_GET_IID(nsIGfxTextControlFrame))) { - *aInstancePtr = (void*)(nsIGfxTextControlFrame*) this; - return NS_OK; - - } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { - *aInstancePtr = (void*)(nsIStatefulFrame*) this; - return NS_OK; - } - - return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); -} - -NS_IMETHODIMP -nsGfxTextControlFrame::Init(nsIPresContext* aPresContext, - nsIContent* aContent, - nsIFrame* aParent, - nsIStyleContext* aContext, - nsIFrame* aPrevInFlow) -{ - mFramePresContext = aPresContext; - return nsFormControlFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); -} - -NS_IMETHODIMP -nsGfxTextControlFrame::GetEditor(nsIEditor **aEditor) -{ - NS_ENSURE_ARG_POINTER(aEditor); - - *aEditor = mEditor; - NS_IF_ADDREF(*aEditor); - return NS_OK; -} - -NS_IMETHODIMP -nsGfxTextControlFrame::GetFrameType(nsIAtom** aType) const -{ - NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); - *aType = NS_NewAtom("textControlFrame"); - return NS_OK; -} - - -NS_IMETHODIMP -nsGfxTextControlFrame::GetDocShell(nsIDocShell **aDocShell) -{ - NS_ENSURE_ARG_POINTER(aDocShell); - - *aDocShell = mDocShell; - NS_IF_ADDREF(*aDocShell); - return NS_OK; -} - -NS_IMETHODIMP -nsGfxTextControlFrame::SetInnerFocus() -{ - SetFocus(); - return NS_OK; -} - -NS_IMETHODIMP -nsGfxTextControlFrame::CreateEditor() -{ - nsresult result = NS_OK; - - mDocShell = nsnull; - mCreatingViewer = PR_FALSE; - - // create the stream observer - mTempObserver = new EnderTempObserver(); - if (!mTempObserver) { return NS_ERROR_OUT_OF_MEMORY; } - mTempObserver->SetFrame(this); - NS_ADDREF(mTempObserver); - - // create the document observer - mDocObserver = new nsEnderDocumentObserver(); - if (!mDocObserver) { return NS_ERROR_OUT_OF_MEMORY; } - mDocObserver->SetFrame(this); - NS_ADDREF(mDocObserver); - - // create the drag listener for the content node - if (mContent) - { - mListenerForContent = new nsEnderListenerForContent(); - if (!mListenerForContent) { return NS_ERROR_OUT_OF_MEMORY; } - mListenerForContent->SetFrame(this); - NS_ADDREF(mListenerForContent); - - // get the DOM event receiver - nsCOMPtr contentER; - result = mContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(contentER)); - if NS_FAILED(result) { return result; } - if (contentER) - { - nsCOMPtr dragListenerForContent; - mListenerForContent->QueryInterface(NS_GET_IID(nsIDOMDragListener), getter_AddRefs(dragListenerForContent)); - if (dragListenerForContent) - { - result = contentER->AddEventListenerByIID(dragListenerForContent, NS_GET_IID(nsIDOMDragListener)); - if NS_FAILED(result) { return result; } - } - } - } - - // create the focus listener for HTML Input display content - if (mDisplayContent) - { - mFocusListenerForDisplayContent = new nsEnderFocusListenerForDisplayContent(); - if (!mFocusListenerForDisplayContent) { return NS_ERROR_OUT_OF_MEMORY; } - mFocusListenerForDisplayContent->SetFrame(this); - NS_ADDREF(mFocusListenerForDisplayContent); - // get the DOM event receiver - nsCOMPtr er; - result = mDisplayContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(er)); - if (NS_SUCCEEDED(result) && er) - result = er->AddEventListenerByIID(mFocusListenerForDisplayContent, NS_GET_IID(nsIDOMFocusListener)); - // should check to see if mDisplayContent or mContent has focus and call CreateSubDoc instead if it does - // do something with result - } - - nsCOMPtr theEditor; - result = nsComponentManager::CreateInstance(kHTMLEditorCID, - nsnull, - NS_GET_IID(nsIHTMLEditor), getter_AddRefs(theEditor)); - if (NS_FAILED(result)) { return result; } - if (!theEditor) { return NS_ERROR_OUT_OF_MEMORY; } - mEditor = do_QueryInterface(theEditor); - if (!mEditor) { return NS_ERROR_NO_INTERFACE; } - return NS_OK; -} - nsGfxTextControlFrame::nsGfxTextControlFrame() : mTempObserver(0), mDocObserver(0), mCreatingViewer(PR_FALSE), @@ -328,6 +191,7 @@ nsGfxTextControlFrame::nsGfxTextControlFrame() mDidSetFocus(PR_FALSE), mGotSelectionState(PR_FALSE), mSelectionWasCollapsed(PR_FALSE), + mIsInput(PR_TRUE), mFramePresContext(nsnull), mCachedState(nsnull), mWeakReferent(this), @@ -525,6 +389,458 @@ nsGfxTextControlFrame::~nsGfxTextControlFrame() #endif } +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxTextControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + + } else if (aIID.Equals(NS_GET_IID(nsIGfxTextControlFrame))) { + *aInstancePtr = (void*)(nsIGfxTextControlFrame*) this; + return NS_OK; + + } else if (aIID.Equals(NS_GET_IID(nsIStatefulFrame))) { + *aInstancePtr = (void*)(nsIStatefulFrame*) this; + return NS_OK; + } + + return nsFormControlFrame::QueryInterface(aIID, aInstancePtr); +} + +NS_IMETHODIMP +nsGfxTextControlFrame::Init(nsIPresContext* aPresContext, + nsIContent* aContent, + nsIFrame* aParent, + nsIStyleContext* aContext, + nsIFrame* aPrevInFlow) +{ + mFramePresContext = aPresContext; + nsresult rv = nsFormControlFrame::Init(aPresContext, aContent, aParent, aContext, aPrevInFlow); + if (NS_FAILED(rv)) return rv; + + // we are an input (hence single line)? + NS_ASSERTION(mContent, "Should have content here"); + nsCOMPtr contentAsInput = do_QueryInterface(mContent); + mIsInput = (contentAsInput.get() != nsnull); + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetEditor(nsIEditor **aEditor) +{ + NS_ENSURE_ARG_POINTER(aEditor); + + *aEditor = mEditor; + NS_IF_ADDREF(*aEditor); + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetFrameType(nsIAtom** aType) const +{ + NS_PRECONDITION(nsnull != aType, "null OUT parameter pointer"); + *aType = NS_NewAtom("textControlFrame"); + return NS_OK; +} + + +NS_IMETHODIMP +nsGfxTextControlFrame::GetDocShell(nsIDocShell **aDocShell) +{ + NS_ENSURE_ARG_POINTER(aDocShell); + + *aDocShell = mDocShell; + NS_IF_ADDREF(*aDocShell); + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::SetInnerFocus() +{ + SetFocus(); + return NS_OK; +} + + +NS_IMETHODIMP +nsGfxTextControlFrame::GetFirstTextNode(nsIDOMCharacterData* *aFirstTextNode) +{ + *aFirstTextNode = nsnull; + + // get the doc + nsCOMPtr htmlDoc = do_QueryInterface(mDoc); + if (!htmlDoc) return NS_ERROR_FAILURE; + + nsCOMPtr bodyElement; + htmlDoc->GetBody(getter_AddRefs(bodyElement)); + if (!bodyElement) return NS_ERROR_FAILURE; + + nsCOMPtr bodyNode = do_QueryInterface(bodyElement); + if (!bodyNode) return NS_ERROR_FAILURE; + + // for a text widget, the text of the document is in a single + // text node under the body. Let's make sure that's true. + nsCOMPtr childNodesList; + bodyNode->GetChildNodes(getter_AddRefs(childNodesList)); + if (!childNodesList) + { + NS_WARNING("Subdoc has no text node list"); + return NS_ERROR_FAILURE; + } + + PRUint32 numChildNodes = 0; + childNodesList->GetLength(&numChildNodes); + if (numChildNodes != 1) + { + NS_WARNING("Found zero or several child nodes in a text widget doc!"); + return NS_ERROR_FAILURE; + } + + nsCOMPtr firstChild; + nsresult rv = bodyNode->GetFirstChild(getter_AddRefs(firstChild)); + if (NS_FAILED(rv)) return rv; + if (!firstChild) return NS_ERROR_FAILURE; + + nsCOMPtr charDataNode = do_QueryInterface(firstChild, &rv); + if (NS_FAILED(rv)) return rv; + + NS_ADDREF(*aFirstTextNode = charDataNode); + return NS_OK; +} + + +nsresult +nsGfxTextControlFrame::SelectAllContents() +{ + nsresult rv; + + if (IsSingleLineInput()) + { + rv = SetSelectionRange(0, 0x7FFFFFFF); + } + else + { + // we have to select all + rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mEditor, "Should have an editor here"); + rv = mEditor->SelectAll(); + } + + return rv; +} + + +nsresult +nsGfxTextControlFrame::SetSelectionEndPoints(PRInt32 aSelStart, PRInt32 aSelEnd) +{ + NS_ASSERTION(IsSingleLineInput(), "Should only call this on a single line input"); + NS_ASSERTION(mEditor, "Should have an editor here"); + NS_ASSERTION(mDoc, "Should have an editor here"); + + nsCOMPtr firstTextNode; + nsresult rv = GetFirstTextNode(getter_AddRefs(firstTextNode)); + if (NS_FAILED(rv) || !firstTextNode) + { + NS_WARNING("No first child node!"); + return rv; + } + + nsCOMPtr firstNode = do_QueryInterface(firstTextNode, &rv); + if (!firstNode) return rv; + + // constrain the selection to this node + PRUint32 nodeLengthU; + firstTextNode->GetLength(&nodeLengthU); + PRInt32 nodeLength = (PRInt32)nodeLengthU; + + if (aSelStart < 0) + aSelStart = 0; + if (aSelStart > nodeLength) + aSelStart = nodeLength; + + if (aSelEnd < 0) + aSelEnd = 0; + if (aSelEnd > nodeLength) + aSelEnd = nodeLength; + + nsCOMPtr selection; + mEditor->GetSelection(getter_AddRefs(selection)); + if (!selection) return NS_ERROR_FAILURE; + + // are we setting both start and end? + if (aSelStart != -1 && aSelEnd != -1) + { + // remove existing ranges + selection->ClearSelection(); + + nsCOMPtr selectionRange; + NS_NewRange(getter_AddRefs(selectionRange)); + if (!selectionRange) return NS_ERROR_OUT_OF_MEMORY; + + selectionRange->SetStart(firstTextNode, aSelStart); + selectionRange->SetEnd(firstTextNode, aSelEnd); + + selection->AddRange(selectionRange); + } + else // we're setting either start or end but not both + { + // does a range exist? + nsCOMPtr firstRange; + selection->GetRangeAt(0, getter_AddRefs(firstRange)); + if (!firstRange) + { + // no range. Make a new one. We'll have to rearrange + // the endpoints to be in legal order + nsCOMPtr selectionRange; + NS_NewRange(getter_AddRefs(selectionRange)); + if (!selectionRange) return NS_ERROR_OUT_OF_MEMORY; + + PRInt32 selStart = 0, selEnd = 0; + + if (aSelStart != -1) + selStart = aSelStart; + + if (aSelEnd != -1) + selEnd = aSelEnd; + + // swap them + if (selEnd < selStart) + { + PRInt32 temp = selStart; + selStart = selEnd; + selEnd = temp; + } + + selectionRange->SetStart(firstTextNode, selStart); + selectionRange->SetEnd(firstTextNode, selEnd); + selection->AddRange(selectionRange); + } + else + { + // we have a range. Just set the endpoints + if (aSelStart != -1) + firstRange->SetStart(firstNode, aSelStart); + + if (aSelEnd != -1) + firstRange->SetStart(firstNode, aSelEnd); + } + } + + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::SetSelectionRange(PRInt32 aSelStart, PRInt32 aSelEnd) +{ + if (!IsSingleLineInput()) return NS_ERROR_NOT_IMPLEMENTED; + + // make sure we have an editor + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mEditor, "Should have an editor here"); + NS_ASSERTION(mDoc, "Should have an editor here"); + + return SetSelectionEndPoints(aSelStart, aSelEnd); +} + + +NS_IMETHODIMP +nsGfxTextControlFrame::SetSelectionStart(PRInt32 aSelectionStart) +{ + if (!IsSingleLineInput()) return NS_ERROR_NOT_IMPLEMENTED; + + // make sure we have an editor + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mEditor, "Should have an editor here"); + NS_ASSERTION(mDoc, "Should have an editor here"); + + return SetSelectionEndPoints(aSelectionStart, -1); +} + +NS_IMETHODIMP +nsGfxTextControlFrame::SetSelectionEnd(PRInt32 aSelectionEnd) +{ + if (!IsSingleLineInput()) return NS_ERROR_NOT_IMPLEMENTED; + + // make sure we have an editor + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mEditor, "Should have an editor here"); + NS_ASSERTION(mDoc, "Should have an editor here"); + + return SetSelectionEndPoints(-1, aSelectionEnd); +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetTextLength(PRInt32* aTextLength) +{ + if (!IsSingleLineInput()) return NS_ERROR_NOT_IMPLEMENTED; + + NS_ENSURE_ARG_POINTER(aTextLength); + *aTextLength = 0; + + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr firstTextNode; + rv = GetFirstTextNode(getter_AddRefs(firstTextNode)); + if (NS_FAILED(rv) || !firstTextNode) + { + NS_WARNING("No first child node!"); + return rv; + } + + PRUint32 nodeLengthU; + firstTextNode->GetLength(&nodeLengthU); + *aTextLength = (PRInt32)nodeLengthU; + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd) +{ + if (!IsSingleLineInput()) return NS_ERROR_NOT_IMPLEMENTED; + + NS_ENSURE_ARG_POINTER((aSelectionStart && aSelectionEnd)); + + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(mEditor, "Should have an editor here"); + NS_ASSERTION(mDoc, "Should have an editor here"); + + nsCOMPtr selection; + mEditor->GetSelection(getter_AddRefs(selection)); + if (!selection) return NS_ERROR_FAILURE; + + // we should have only zero or one range + PRInt32 numRanges = 0; + selection->GetRangeCount(&numRanges); + if (numRanges > 1) + { + NS_ASSERTION(0, "Found more than on range in GetSelectionRange"); + } + + if (numRanges == 0) + { + *aSelectionStart = 0; + *aSelectionEnd = 0; + } + else + { + nsCOMPtr firstRange; + selection->GetRangeAt(0, getter_AddRefs(firstRange)); + if (!firstRange) return NS_ERROR_FAILURE; + + // make sure this range is pointing at the first child + nsCOMPtr firstTextNode; + rv = GetFirstTextNode(getter_AddRefs(firstTextNode)); + nsCOMPtr firstNode = do_QueryInterface(firstTextNode); + + nsCOMPtr rangeStartNode; + firstRange->GetStartParent(getter_AddRefs(rangeStartNode)); // maybe we should compare the end too? + if (rangeStartNode != firstNode) return NS_ERROR_FAILURE; + + firstRange->GetStartOffset(aSelectionStart); + firstRange->GetEndOffset(aSelectionEnd); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::EnsureEditor() +{ + nsresult rv = NS_OK; + if (!mDocShell) + { + rv = CreateSubDoc(nsnull); + if (NS_FAILED(rv)) return rv; + } + return NS_OK; +} + + +NS_IMETHODIMP +nsGfxTextControlFrame::CreateEditor() +{ + nsresult result = NS_OK; + + mDocShell = nsnull; + mCreatingViewer = PR_FALSE; + + // create the stream observer + mTempObserver = new EnderTempObserver(); + if (!mTempObserver) { return NS_ERROR_OUT_OF_MEMORY; } + mTempObserver->SetFrame(this); + NS_ADDREF(mTempObserver); + + // create the document observer + mDocObserver = new nsEnderDocumentObserver(); + if (!mDocObserver) { return NS_ERROR_OUT_OF_MEMORY; } + mDocObserver->SetFrame(this); + NS_ADDREF(mDocObserver); + + // create the drag listener for the content node + if (mContent) + { + mListenerForContent = new nsEnderListenerForContent(); + if (!mListenerForContent) { return NS_ERROR_OUT_OF_MEMORY; } + mListenerForContent->SetFrame(this); + NS_ADDREF(mListenerForContent); + + // get the DOM event receiver + nsCOMPtr contentER; + result = mContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(contentER)); + if NS_FAILED(result) { return result; } + if (contentER) + { + nsCOMPtr dragListenerForContent; + mListenerForContent->QueryInterface(NS_GET_IID(nsIDOMDragListener), getter_AddRefs(dragListenerForContent)); + if (dragListenerForContent) + { + result = contentER->AddEventListenerByIID(dragListenerForContent, NS_GET_IID(nsIDOMDragListener)); + if NS_FAILED(result) { return result; } + } + } + } + + // create the focus listener for HTML Input display content + if (mDisplayContent) + { + mFocusListenerForDisplayContent = new nsEnderFocusListenerForDisplayContent(); + if (!mFocusListenerForDisplayContent) { return NS_ERROR_OUT_OF_MEMORY; } + mFocusListenerForDisplayContent->SetFrame(this); + NS_ADDREF(mFocusListenerForDisplayContent); + // get the DOM event receiver + nsCOMPtr er; + result = mDisplayContent->QueryInterface(NS_GET_IID(nsIDOMEventReceiver), getter_AddRefs(er)); + if (NS_SUCCEEDED(result) && er) + result = er->AddEventListenerByIID(mFocusListenerForDisplayContent, NS_GET_IID(nsIDOMFocusListener)); + // should check to see if mDisplayContent or mContent has focus and call CreateSubDoc instead if it does + // do something with result + } + + nsCOMPtr theEditor; + result = nsComponentManager::CreateInstance(kHTMLEditorCID, + nsnull, + NS_GET_IID(nsIHTMLEditor), getter_AddRefs(theEditor)); + if (NS_FAILED(result)) { return result; } + if (!theEditor) { return NS_ERROR_OUT_OF_MEMORY; } + mEditor = do_QueryInterface(theEditor); + if (!mEditor) { return NS_ERROR_NO_INTERFACE; } + return NS_OK; +} + + NS_METHOD nsGfxTextControlFrame::HandleEvent(nsIPresContext* aPresContext, nsGUIEvent* aEvent, nsEventStatus* aEventStatus) @@ -1036,7 +1352,7 @@ nsGfxTextControlFrame::CreateSubDoc(nsRect *aSizeOfSubdocContainer) subBounds.width, subBounds.height, PR_FALSE); } mCreatingViewer=PR_TRUE; - + // create document nsCOMPtr doc; rv = NS_NewHTMLDocument(getter_AddRefs(doc)); @@ -1430,9 +1746,10 @@ nsGfxTextControlFrame::ContentChanged(nsIPresContext* aPresContext, NS_IMETHODIMP nsGfxTextControlFrame::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue) { - if (PR_FALSE==mIsProcessing) + if (!mIsProcessing) { mIsProcessing = PR_TRUE; + if (nsHTMLAtoms::value == aName) { if (mEditor) { @@ -1443,7 +1760,13 @@ NS_IMETHODIMP nsGfxTextControlFrame::SetProperty(nsIPresContext* aPresContext, n mEditor->EnableUndo(PR_TRUE); // fire up a new txn stack } } - else { + else if (nsHTMLAtoms::select == aName) + { + // select all the text + SelectAllContents(); + } + else + { return Inherited::SetProperty(aPresContext, aName, aValue); } mIsProcessing = PR_FALSE; @@ -1477,14 +1800,12 @@ void nsGfxTextControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) // 3) from clicking on it // // If removing any of this code PLEASE read comment below - nsresult result = NS_OK; - if (!mDocShell) - { - result = CreateSubDoc(nsnull); - if (NS_FAILED(result)) return; - } - if (aOn) { + nsresult rv = EnsureEditor(); + if (NS_FAILED(rv)) return; + + if (aOn) + { nsCOMPtr viewer; mDocShell->GetContentViewer(getter_AddRefs(viewer)); if (viewer) { @@ -1517,7 +1838,7 @@ void nsGfxTextControlFrame::SetFocus(PRBool aOn, PRBool aRepaint) // and setting this to true won't propigate into the DOM, because we // got here via the DOM // See: nsEnderEventListener::Focus - result = widget->SetFocus(); + rv = widget->SetFocus(); mDidSetFocus = PR_TRUE; } } diff --git a/layout/html/forms/src/nsGfxTextControlFrame.h b/layout/html/forms/src/nsGfxTextControlFrame.h index 1781f710522..f379b918529 100644 --- a/layout/html/forms/src/nsGfxTextControlFrame.h +++ b/layout/html/forms/src/nsGfxTextControlFrame.h @@ -52,7 +52,7 @@ class nsIFrame; class nsIDOMSelection; - +class nsIDOMCharacterData; class nsGfxTextControlFrame; @@ -531,6 +531,11 @@ public: NS_IMETHOD GetEditor(nsIEditor **aEditor); NS_IMETHOD GetDocShell(nsIDocShell **aDocShell); NS_IMETHOD SetInnerFocus(); + NS_IMETHOD GetTextLength(PRInt32* aTextLength); + NS_IMETHOD SetSelectionStart(PRInt32 aSelectionStart); + NS_IMETHOD SetSelectionEnd(PRInt32 aSelectionEnd); + NS_IMETHOD SetSelectionRange(PRInt32 aSelectionStart, PRInt32 aSelectionEnd); + NS_IMETHOD GetSelectionRange(PRInt32* aSelectionStart, PRInt32* aSelectionEnd); //nsIStatefulFrame NS_IMETHOD GetStateType(nsIPresContext* aPresContext, nsIStatefulFrame::StateType* aStateType); @@ -539,6 +544,7 @@ public: protected: + PRInt32 GetDefaultColumnWidth() const { return (PRInt32)(20); } // this was DEFAULT_PIXEL_WIDTH /** calculate the inner region of the text control (size - border and padding) in pixels */ @@ -638,7 +644,23 @@ protected: nsIAtom** aListName) const; NS_IMETHOD Destroy(nsIPresContext *aPresContext); + // utility method to get the DOM node that contains the character + // data for the contents of the field. This method asserts that + // there is just one such node. + NS_IMETHOD GetFirstTextNode(nsIDOMCharacterData* *aFirstTextNode); + + // Make the editor if it doesn't already exist + NS_IMETHOD EnsureEditor(); + + nsresult SelectAllContents(); + + // internal method. Pass -1 in start or end to indicate "don't set" + nsresult SetSelectionEndPoints(PRInt32 aSelectionStart, PRInt32 aSelectionEnd); + + PRBool IsSingleLineInput() { return mIsInput; } + public: + void SetShouldSetFocus() { mDidSetFocus = PR_FALSE; }; void SetFrameConstructor(nsCSSFrameConstructor *aConstructor) { mFrameConstructor = aConstructor; } // not owner - do not addref! @@ -659,6 +681,8 @@ protected: PRPackedBool mGotSelectionState; PRPackedBool mSelectionWasCollapsed; + PRPackedBool mIsInput; // is input (single line), c.f. multiline textarea + nsIPresContext* mFramePresContext; // not ref counted nsString* mCachedState; // this is used for caching changed between frame creation // and full initialization