/* -*- 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.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Owner: * Michael F. Judge mjudge@netscape.com * * Contributor(s): */ #include "nsCOMPtr.h" #include "nsWeakReference.h" #include "nsGfxTextControlFrame2.h" #include "nsIDocument.h" #include "nsIDOMNSHTMLTextAreaElement.h" #include "nsIDOMNSHTMLInputElement.h" #include "nsIFormControl.h" #include "nsIServiceManager.h" #include "nsIFrameSelection.h" #include "nsIHTMLEditor.h" #include "nsEditorCID.h" #include "nsLayoutCID.h" #include "nsFormControlHelper.h" #include "nsIDocumentEncoder.h" #include "nsICaret.h" #include "nsIDOMSelectionListener.h" #include "nsIController.h" #include "nsIControllers.h" #include "nsIEditorController.h" #include "nsIElementFactory.h" #include "nsIHTMLContent.h" #include "nsFormFrame.h" #include "nsIContent.h" #include "nsIAtom.h" #include "nsIPresContext.h" #include "nsHTMLIIDs.h" #include "nsHTMLAtoms.h" #include "nsIComponentManager.h" #include "nsIView.h" #include "nsIDOMHTMLInputElement.h" #include "nsISupportsArray.h" #include "nsIDOMElement.h" #include "nsIDOMDocument.h" #include "nsIPresShell.h" #include "nsIComponentManager.h" #define DEFAULT_COLUMN_WIDTH 20 static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID); static NS_DEFINE_CID(kFrameSelectionCID, NS_FRAMESELECTION_CID); static void RemoveNewlines(nsString &aString); static void RemoveNewlines(nsString &aString) { // strip CR/LF and null static const char badChars[] = {10, 13, 0}; aString.StripChars(badChars); } class nsTextAreaSelectionImpl : public nsSupportsWeakReference, public nsISelectionController, public nsIFrameSelection { public: NS_DECL_ISUPPORTS nsTextAreaSelectionImpl(nsIFrameSelection *aSel, nsIPresShell *aShell, nsIContent *aLimiter); ~nsTextAreaSelectionImpl(){} //NSISELECTIONCONTROLLER INTERFACES NS_IMETHOD SetDisplaySelection(PRInt16 toggle); NS_IMETHOD GetDisplaySelection(PRInt16 *_retval); NS_IMETHOD GetSelection(PRInt16 type, nsIDOMSelection **_retval); NS_IMETHOD ScrollSelectionIntoView(PRInt16 type, PRInt16 region); NS_IMETHOD RepaintSelection(PRInt16 type); NS_IMETHOD RepaintSelection(nsIPresContext* aPresContext, SelectionType aSelectionType); NS_IMETHOD SetCaretEnabled(PRBool enabled); NS_IMETHOD GetCaretEnabled(PRBool *_retval); NS_IMETHOD CharacterMove(PRBool aForward, PRBool aExtend); NS_IMETHOD WordMove(PRBool aForward, PRBool aExtend); NS_IMETHOD LineMove(PRBool aForward, PRBool aExtend); NS_IMETHOD IntraLineMove(PRBool aForward, PRBool aExtend); NS_IMETHOD PageMove(PRBool aForward, PRBool aExtend){return NS_OK;}//* NS_IMETHOD CompleteScroll(PRBool aForward){return NS_OK;}//* NS_IMETHOD CompleteMove(PRBool aForward, PRBool aExtend){return NS_OK;}//* NS_IMETHOD ScrollPage(PRBool aForward){return NS_OK;}//* NS_IMETHOD ScrollLine(PRBool aForward){return NS_OK;}//* NS_IMETHOD ScrollHorizontal(PRBool aLeft){return NS_OK;}//* NS_IMETHOD SelectAll(void); //NSIFRAMSELECTION INTERFACES NS_IMETHOD Init(nsIFocusTracker *aTracker, nsIContent *aLimiter) ; NS_IMETHOD ShutDown() ; NS_IMETHOD HandleTextEvent(nsGUIEvent *aGuiEvent) ; NS_IMETHOD HandleKeyEvent(nsIPresContext* aPresContext, nsGUIEvent *aGuiEvent); NS_IMETHOD HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset , PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint); NS_IMETHOD HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint); NS_IMETHOD HandleTableSelection(nsIContent *aParentContent, PRInt32 aContentOffset, PRUint32 aTarget, nsMouseEvent *aMouseEvent); NS_IMETHOD StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay); NS_IMETHOD StopAutoScrollTimer(); NS_IMETHOD EnableFrameNotification(PRBool aEnable); NS_IMETHOD LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, SelectionDetails **aReturnDetails, PRBool aSlowCheck); NS_IMETHOD SetMouseDownState(PRBool aState); NS_IMETHOD GetMouseDownState(PRBool *aState); NS_IMETHOD GetTableCellSelection(PRBool *aState); NS_IMETHOD GetTableCellSelectionStyleColor(const nsStyleColor **aStyleColor); NS_IMETHOD GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset); private: nsCOMPtr mFrameSelection; nsCOMPtr mLimiter; nsWeakPtr mPresShellWeak; }; // Implement our nsISupports methods NS_IMPL_ISUPPORTS3(nsTextAreaSelectionImpl, nsISelectionController, nsISupportsWeakReference, nsIFrameSelection) // BEGIN nsTextAreaSelectionImpl nsTextAreaSelectionImpl::nsTextAreaSelectionImpl(nsIFrameSelection *aSel, nsIPresShell *aShell, nsIContent *aLimiter) { NS_INIT_REFCNT(); if (aSel && aShell) { mFrameSelection = aSel;//we are the owner now! nsCOMPtr tracker = do_QueryInterface(aShell); mLimiter = aLimiter; mFrameSelection->Init(tracker, mLimiter); mPresShellWeak = getter_AddRefs( NS_GetWeakReference(aShell) ); } } NS_IMETHODIMP nsTextAreaSelectionImpl::SetDisplaySelection(PRInt16 aToggle) { if (mFrameSelection) return mFrameSelection->SetDisplaySelection(aToggle); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::GetDisplaySelection(PRInt16 *aToggle) { if (mFrameSelection) return mFrameSelection->GetDisplaySelection(aToggle); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::GetSelection(PRInt16 type, nsIDOMSelection **_retval) { if (mFrameSelection) return mFrameSelection->GetSelection(type, _retval); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::ScrollSelectionIntoView(PRInt16 type, PRInt16 region) { if (mFrameSelection) return mFrameSelection->ScrollSelectionIntoView(type, region); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::RepaintSelection(PRInt16 type) { if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr presShell = do_QueryReferent(mPresShellWeak); if (presShell) { nsCOMPtr context; if (NS_SUCCEEDED(presShell->GetPresContext(getter_AddRefs(context))) && context) { return mFrameSelection->RepaintSelection(context, type); } } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsTextAreaSelectionImpl::RepaintSelection(nsIPresContext* aPresContext, SelectionType aSelectionType) { return RepaintSelection(aSelectionType); } NS_IMETHODIMP nsTextAreaSelectionImpl::SetCaretEnabled(PRBool enabled) { if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr selCon = do_QueryReferent(mPresShellWeak); if (selCon) { return selCon->SetCaretEnabled(enabled);//we can use presshells because there is only 1 caret } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsTextAreaSelectionImpl::GetCaretEnabled(PRBool *_retval) { if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED; nsCOMPtr selCon = do_QueryReferent(mPresShellWeak); if (selCon) { return selCon->GetCaretEnabled(_retval);//we can use presshells because there is only 1 caret } return NS_ERROR_FAILURE; } NS_IMETHODIMP nsTextAreaSelectionImpl::CharacterMove(PRBool aForward, PRBool aExtend) { if (mFrameSelection) return mFrameSelection->CharacterMove(aForward, aExtend); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::WordMove(PRBool aForward, PRBool aExtend) { if (mFrameSelection) return mFrameSelection->WordMove(aForward, aExtend); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::LineMove(PRBool aForward, PRBool aExtend) { if (mFrameSelection) return mFrameSelection->LineMove(aForward, aExtend); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::IntraLineMove(PRBool aForward, PRBool aExtend) { if (mFrameSelection) return mFrameSelection->IntraLineMove(aForward, aExtend); return NS_ERROR_NULL_POINTER; } NS_IMETHODIMP nsTextAreaSelectionImpl::SelectAll() { if (mFrameSelection) return mFrameSelection->SelectAll(); return NS_ERROR_NULL_POINTER; } //nsTextAreaSelectionImpl::FRAMESELECTIONAPIS NS_IMETHODIMP nsTextAreaSelectionImpl::Init(nsIFocusTracker *aTracker, nsIContent *aLimiter) { return mFrameSelection->Init(aTracker, aLimiter); } NS_IMETHODIMP nsTextAreaSelectionImpl::ShutDown() { return mFrameSelection->ShutDown(); } NS_IMETHODIMP nsTextAreaSelectionImpl::HandleTextEvent(nsGUIEvent *aGuiEvent) { return mFrameSelection->HandleTextEvent(aGuiEvent); } NS_IMETHODIMP nsTextAreaSelectionImpl::HandleKeyEvent(nsIPresContext* aPresContext, nsGUIEvent *aGuiEvent) { return mFrameSelection->HandleKeyEvent(aPresContext, aGuiEvent); } NS_IMETHODIMP nsTextAreaSelectionImpl::HandleClick(nsIContent *aNewFocus, PRUint32 aContentOffset, PRUint32 aContentEndOffset , PRBool aContinueSelection, PRBool aMultipleSelection, PRBool aHint) { return mFrameSelection->HandleClick(aNewFocus, aContentOffset, aContentEndOffset , aContinueSelection, aMultipleSelection, aHint); } NS_IMETHODIMP nsTextAreaSelectionImpl::HandleDrag(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint) { return mFrameSelection->HandleDrag(aPresContext, aFrame, aPoint); } NS_IMETHODIMP nsTextAreaSelectionImpl::HandleTableSelection(nsIContent *aParentContent, PRInt32 aContentOffset, PRUint32 aTarget, nsMouseEvent *aMouseEvent) { return mFrameSelection->HandleTableSelection(aParentContent, aContentOffset, aTarget, aMouseEvent); } NS_IMETHODIMP nsTextAreaSelectionImpl::StartAutoScrollTimer(nsIPresContext *aPresContext, nsIFrame *aFrame, nsPoint& aPoint, PRUint32 aDelay) { return mFrameSelection->StartAutoScrollTimer(aPresContext, aFrame, aPoint, aDelay); } NS_IMETHODIMP nsTextAreaSelectionImpl::StopAutoScrollTimer() { return mFrameSelection->StopAutoScrollTimer(); } NS_IMETHODIMP nsTextAreaSelectionImpl::EnableFrameNotification(PRBool aEnable) { return mFrameSelection->EnableFrameNotification(aEnable); } NS_IMETHODIMP nsTextAreaSelectionImpl::LookUpSelection(nsIContent *aContent, PRInt32 aContentOffset, PRInt32 aContentLength, SelectionDetails **aReturnDetails, PRBool aSlowCheck) { return mFrameSelection->LookUpSelection(aContent, aContentOffset, aContentLength, aReturnDetails, aSlowCheck); } NS_IMETHODIMP nsTextAreaSelectionImpl::SetMouseDownState(PRBool aState) { return mFrameSelection->SetMouseDownState(aState); } NS_IMETHODIMP nsTextAreaSelectionImpl::GetMouseDownState(PRBool *aState) { return mFrameSelection->GetMouseDownState(aState); } NS_IMETHODIMP nsTextAreaSelectionImpl::GetTableCellSelection(PRBool *aState) { return mFrameSelection->GetTableCellSelection(aState); } NS_IMETHODIMP nsTextAreaSelectionImpl::GetTableCellSelectionStyleColor(const nsStyleColor **aStyleColor) { return mFrameSelection->GetTableCellSelectionStyleColor(aStyleColor); } NS_IMETHODIMP nsTextAreaSelectionImpl::GetFrameForNodeOffset(nsIContent *aNode, PRInt32 aOffset, nsIFrame **aReturnFrame, PRInt32 *aReturnOffset) { return mFrameSelection->GetFrameForNodeOffset(aNode, aOffset,aReturnFrame,aReturnOffset); } // END nsTextAreaSelectionImpl nsresult NS_NewGfxTextControlFrame(nsIPresShell* aPresShell, nsIFrame** aNewFrame) { NS_PRECONDITION(aNewFrame, "null OUT ptr"); if (nsnull == aNewFrame) { return NS_ERROR_NULL_POINTER; } nsGfxTextControlFrame2* it = new (aPresShell) nsGfxTextControlFrame2(); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } *aNewFrame = it; return NS_OK; } NS_IMPL_ADDREF_INHERITED(nsGfxTextControlFrame2, nsHTMLContainerFrame); NS_IMPL_RELEASE_INHERITED(nsGfxTextControlFrame2, nsHTMLContainerFrame); NS_IMETHODIMP nsGfxTextControlFrame2::QueryInterface(const nsIID& aIID, void** aInstancePtr) { if (NULL == aInstancePtr) { return NS_ERROR_NULL_POINTER; } if (aIID.Equals(NS_GET_IID(nsIFormControlFrame))) { *aInstancePtr = (void*) ((nsIFormControlFrame*) this); return NS_OK; } if (aIID.Equals(NS_GET_IID(nsIAnonymousContentCreator))) { *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; return NS_OK; } return nsHTMLContainerFrame::QueryInterface(aIID, aInstancePtr); } nsGfxTextControlFrame2::nsGfxTextControlFrame2() { mIsProcessing=PR_FALSE; mFormFrame = nsnull; } nsGfxTextControlFrame2::~nsGfxTextControlFrame2() { if (mFormFrame) { mFormFrame->RemoveFormControlFrame(*this); mFormFrame = nsnull; } } // XXX: wouldn't it be nice to get this from the style context! PRBool nsGfxTextControlFrame2::IsSingleLineTextControl() const { PRInt32 type; GetType(&type); if ((NS_FORM_INPUT_TEXT==type) || (NS_FORM_INPUT_PASSWORD==type)) { return PR_TRUE; } return PR_FALSE; } // XXX: wouldn't it be nice to get this from the style context! PRBool nsGfxTextControlFrame2::IsPlainTextControl() const { // need to check HTML attribute of mContent and/or CSS. return PR_TRUE; } PRBool nsGfxTextControlFrame2::IsPasswordTextControl() const { PRInt32 type; GetType(&type); if (NS_FORM_INPUT_PASSWORD==type) { return PR_TRUE; } return PR_FALSE; } NS_IMETHODIMP nsGfxTextControlFrame2::CreateFrameFor(nsIPresContext* aPresContext, nsIContent * aContent, nsIFrame** aFrame) { aContent = nsnull; return NS_ERROR_FAILURE; } NS_IMETHODIMP nsGfxTextControlFrame2::CreateAnonymousContent(nsIPresContext* aPresContext, nsISupportsArray& aChildList) { //create editor //create selection //init editor with div. nsCAutoString progID = NS_ELEMENT_FACTORY_PROGID_PREFIX; progID += "http://www.w3.org/TR/REC-html40"; nsresult rv; NS_WITH_SERVICE(nsIElementFactory, elementFactory, progID, &rv); if (!elementFactory) return NS_ERROR_FAILURE; nsCOMPtr content; elementFactory->CreateInstanceByTag(NS_ConvertToString("div"), getter_AddRefs(content)); if (content) { aChildList.AppendElement(content); //make the editor rv = nsComponentManager::CreateInstance(kHTMLEditorCID, nsnull, NS_GET_IID(nsIEditor), getter_AddRefs(mEditor)); if (NS_FAILED(rv)) return rv; if (!mEditor) return NS_ERROR_OUT_OF_MEMORY; //get the presshell nsCOMPtr shell; rv = aPresContext->GetShell(getter_AddRefs(shell)); if (NS_FAILED(rv) || !shell) return rv?rv:NS_ERROR_FAILURE; //create selection nsCOMPtr frameSel; rv = nsComponentManager::CreateInstance(kFrameSelectionCID, nsnull, NS_GET_IID(nsIFrameSelection), getter_AddRefs(frameSel)); //create selection controller nsTextAreaSelectionImpl * textSelImpl = new nsTextAreaSelectionImpl(frameSel,shell,content); mSelCon = do_QueryInterface((nsISupports *)(nsISelectionController *)textSelImpl);//this will addref it once mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_ON); //get the document nsCOMPtr doc; rv = shell->GetDocument(getter_AddRefs(doc)); if (NS_FAILED(rv) || !doc) return rv?rv:NS_ERROR_FAILURE; nsCOMPtr domdoc = do_QueryInterface(doc, &rv); if (NS_FAILED(rv) || !domdoc) return rv?rv:NS_ERROR_FAILURE; //get the flags PRUint32 editorFlags = 0; if (IsPlainTextControl()) editorFlags |= nsIHTMLEditor::eEditorPlaintextMask; if (IsSingleLineTextControl()) editorFlags |= nsIHTMLEditor::eEditorSingleLineMask; if (IsPasswordTextControl()) editorFlags |= nsIHTMLEditor::eEditorPasswordMask; //initialize the editor mEditor->Init(domdoc, shell, content, mSelCon, editorFlags); //initialize the controller for the editor nsCOMPtr textAreaElement = do_QueryInterface(mContent); nsCOMPtr inputElement = do_QueryInterface(mContent); nsCOMPtr controllers; if (textAreaElement) textAreaElement->GetControllers(getter_AddRefs(controllers)); else if (inputElement) inputElement->GetControllers(getter_AddRefs(controllers)); else return rv = NS_ERROR_FAILURE; if (NS_SUCCEEDED(rv)) { PRUint32 count; PRBool found = PR_FALSE; rv = controllers->GetControllerCount(&count); for (PRUint32 i = 0; i < count; i ++) { nsCOMPtr controller; rv = controllers->GetControllerAt(i, getter_AddRefs(controller)); if (NS_SUCCEEDED(rv) && controller) { nsCOMPtr editController = do_QueryInterface(controller); if (editController) { editController->SetCommandRefCon(mEditor); found = PR_TRUE; } } } if (!found) rv = NS_ERROR_FAILURE; } //get the caret nsCOMPtr caret; if (NS_SUCCEEDED(shell->GetCaret(getter_AddRefs(caret))) && caret) { nsCOMPtr listener = do_QueryInterface(caret); nsCOMPtr domSelection; if (listener) { if (NS_SUCCEEDED(mSelCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSelection))) && domSelection) domSelection->AddSelectionListener(listener); } } } return NS_OK; } #if 0 NS_IMETHODIMP nsGfxTextControlFrame2::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { // Figure out if we are doing Quirks or Standard nsCompatibility mode; aPresContext->GetCompatibilityMode(&mode); nsMargin border; border.SizeTo(0, 0, 0, 0); nsMargin padding; padding.SizeTo(0, 0, 0, 0); // Get the CSS border const nsStyleSpacing* spacing; GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); spacing->CalcBorderFor(this, border); spacing->CalcPaddingFor(this, padding); // calculate the the desired size for the text control // use the suggested size if it has been set nsresult rv = NS_OK; nsHTMLReflowState suggestedReflowState(aReflowState); if ((kSuggestedNotSet != mSuggestedWidth) || (kSuggestedNotSet != mSuggestedHeight)) { // Honor the suggested width and/or height. if (kSuggestedNotSet != mSuggestedWidth) { suggestedReflowState.mComputedWidth = mSuggestedWidth; aDesiredSize.width = mSuggestedWidth; } if (kSuggestedNotSet != mSuggestedHeight) { suggestedReflowState.mComputedHeight = mSuggestedHeight; aDesiredSize.height = mSuggestedHeight; } rv = NS_OK; aDesiredSize.ascent = aDesiredSize.height; aDesiredSize.descent = 0; aStatus = NS_FRAME_COMPLETE; } else { // this is the right way // Quirks mode will NOT obey CSS border and padding // GetDesiredSize calculates the size without CSS borders // the nsLeafFrame::Reflow will add in the borders if (eCompatibility_NavQuirks == mode) { rv = ReflowNavQuirks(aPresContext, aDesiredSize, aReflowState, aStatus, border, padding); } else { rv = ReflowStandard(aPresContext, aDesiredSize, aReflowState, aStatus, border, padding); } if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) { if (aReflowState.mComputedWidth > aDesiredSize.width) { aDesiredSize.width = aReflowState.mComputedWidth; } } if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) { if (aReflowState.mComputedHeight > aDesiredSize.height) { aDesiredSize.height = aReflowState.mComputedHeight; } } aStatus = NS_FRAME_COMPLETE; } #endif NS_IMETHODIMP nsGfxTextControlFrame2::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { // assuming 1 child nsIFrame* child = mFrames.FirstChild(); //mFrames.FirstChild(aPresContext,nsnull,&child); if (!child) return nsHTMLContainerFrame::Reflow(aPresContext,aDesiredSize,aReflowState,aStatus); nsSize availSize(aReflowState.availableWidth, aReflowState.availableHeight); nsHTMLReflowState kidReflowState(aPresContext, aReflowState, child, availSize); kidReflowState.mComputedWidth = aReflowState.mComputedWidth; kidReflowState.mComputedHeight = aReflowState.mComputedHeight; if (kidReflowState.mComputedWidth != NS_INTRINSICSIZE) kidReflowState.mComputedWidth -= kidReflowState.mComputedBorderPadding.left + kidReflowState.mComputedBorderPadding.right; if (kidReflowState.mComputedHeight != NS_INTRINSICSIZE) kidReflowState.mComputedHeight -= kidReflowState.mComputedBorderPadding.top + kidReflowState.mComputedBorderPadding.bottom; if (aReflowState.reason == eReflowReason_Initial) { aDesiredSize.height = 10; return nsHTMLContainerFrame::Reflow(aPresContext,aDesiredSize,aReflowState,aStatus); } else if (aReflowState.reason == eReflowReason_Incremental) { if (aReflowState.reflowCommand) { nsIFrame* incrementalChild = nsnull; aReflowState.reflowCommand->GetNext(incrementalChild); NS_ASSERTION(incrementalChild == child || !incrementalChild, "Child is not in our list!!"); if (!incrementalChild) { nsIFrame* target; aReflowState.reflowCommand->GetTarget(target); NS_ASSERTION(target == this, "Not our target!"); nsIReflowCommand::ReflowType type; aReflowState.reflowCommand->GetType(type); switch (type) { case nsIReflowCommand::StyleChanged: kidReflowState.reason = eReflowReason_StyleChange; kidReflowState.reflowCommand = nsnull; break; case nsIReflowCommand::ReflowDirty: kidReflowState.reason = eReflowReason_Dirty; kidReflowState.reflowCommand = nsnull; break; default: NS_ERROR("Unknown incremental reflow type"); } } } } nsresult rv = ReflowChild(child, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus); // Place and size the child. FinishReflowChild(child, aPresContext, aDesiredSize, aReflowState.mComputedBorderPadding.left, aReflowState.mComputedBorderPadding.top, 0); return rv; } //#endif PRIntn nsGfxTextControlFrame2::GetSkipSides() const { return 0; } //IMPLEMENTING NS_IFORMCONTROLFRAME NS_IMETHODIMP nsGfxTextControlFrame2::GetName(nsString* aResult) { nsresult result = NS_FORM_NOTOK; if (mContent) { nsIHTMLContent* formControl = nsnull; result = mContent->QueryInterface(NS_GET_IID(nsIHTMLContent),(void**)&formControl); if (NS_SUCCEEDED(result) && formControl) { nsHTMLValue value; result = formControl->GetHTMLAttribute(nsHTMLAtoms::name, value); if (NS_CONTENT_ATTR_HAS_VALUE == result) { if (eHTMLUnit_String == value.GetUnit()) { value.GetStringValue(*aResult); } } NS_RELEASE(formControl); } } return result; } NS_IMETHODIMP nsGfxTextControlFrame2::GetType(PRInt32* aType) const { nsresult result = NS_FORM_NOTOK; if (mContent) { nsIFormControl* formControl = nsnull; result = mContent->QueryInterface(NS_GET_IID(nsIFormControl), (void**)&formControl); if ((NS_OK == result) && formControl) { result = formControl->GetType(aType); NS_RELEASE(formControl); } } return result; } void nsGfxTextControlFrame2::SetFocus(PRBool aOn , PRBool aRepaint){} void nsGfxTextControlFrame2::ScrollIntoView(nsIPresContext* aPresContext){} void nsGfxTextControlFrame2::MouseClicked(nsIPresContext* aPresContext){} void nsGfxTextControlFrame2::Reset(nsIPresContext* aPresContext){} PRInt32 nsGfxTextControlFrame2::GetMaxNumValues(){return 1;}/**/ PRBool nsGfxTextControlFrame2::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames) { return PR_FALSE; } nscoord nsGfxTextControlFrame2::GetVerticalInsidePadding(nsIPresContext* aPresContext, float aPixToTwip, nscoord aInnerHeight) const { return NSIntPixelsToTwips(0, aPixToTwip); } //--------------------------------------------------------- nscoord nsGfxTextControlFrame2::GetHorizontalInsidePadding(nsIPresContext* aPresContext, float aPixToTwip, nscoord aInnerWidth, nscoord aCharWidth) const { return GetVerticalInsidePadding(aPresContext, aPixToTwip, aInnerWidth); } void nsGfxTextControlFrame2::SetFormFrame(nsFormFrame* aFormFrame) { mFormFrame = aFormFrame; } //--------------------------------------------------------- PRBool nsGfxTextControlFrame2::IsSuccessful(nsIFormControlFrame* aSubmitter) { nsAutoString name; return (NS_CONTENT_ATTR_HAS_VALUE == GetName(&name)); } NS_IMETHODIMP nsGfxTextControlFrame2::SetSuggestedSize(nscoord aWidth, nscoord aHeight) { return NS_OK; } nsresult nsGfxTextControlFrame2::RequiresWidget(PRBool& aRequiresWidget) { aRequiresWidget = PR_FALSE; return NS_OK; } NS_IMETHODIMP nsGfxTextControlFrame2::GetFont(nsIPresContext* aPresContext, const nsFont*& aFont) { return nsFormControlHelper::GetFont(this, aPresContext, mStyleContext, aFont); } NS_IMETHODIMP nsGfxTextControlFrame2::GetFormContent(nsIContent*& aContent) const { nsIContent* content; nsresult rv; rv = GetContent(&content); aContent = content; return rv; } NS_IMETHODIMP nsGfxTextControlFrame2::SetProperty(nsIPresContext* aPresContext, nsIAtom* aName, const nsString& aValue) { if (!mIsProcessing)//some kind of lock. { mIsProcessing = PR_TRUE; if (nsHTMLAtoms::value == aName) { if (mEditor) { mEditor->EnableUndo(PR_FALSE); // wipe out undo info } SetTextControlFrameState(aValue); // set new text value if (mEditor) { mEditor->EnableUndo(PR_TRUE); // fire up a new txn stack } } else if (nsHTMLAtoms::select == aName && mSelCon) { // select all the text mSelCon->SelectAll(); } mIsProcessing = PR_FALSE; } return NS_OK; } NS_IMETHODIMP nsGfxTextControlFrame2::GetProperty(nsIAtom* aName, nsString& aValue) { // Return the value of the property from the widget it is not null. // If widget is null, assume the widget is GFX-rendered and return a member variable instead. if (nsHTMLAtoms::value == aName) { GetTextControlFrameState(aValue); } return NS_OK; } void nsGfxTextControlFrame2::GetTextControlFrameState(nsString& aValue) { aValue.SetLength(0); // initialize out param if (mEditor) { nsString format; format.AssignWithConversion("text/plain"); PRUint32 flags = 0; if (PR_TRUE==IsPlainTextControl()) { flags |= nsIDocumentEncoder::OutputBodyOnly; // OutputNoDoctype if head info needed } nsFormControlHelper::nsHTMLTextWrap wrapProp; nsresult result = nsFormControlHelper::GetWrapPropertyEnum(mContent, wrapProp); if (NS_CONTENT_ATTR_NOT_THERE != result) { if (wrapProp == nsFormControlHelper::eHTMLTextWrap_Hard) { flags |= nsIDocumentEncoder::OutputFormatted; } } mEditor->OutputToString(aValue, format, flags); } } // END IMPLEMENTING NS_IFORMCONTROLFRAME void nsGfxTextControlFrame2::SetTextControlFrameState(const nsString& aValue) { if (mEditor) { nsAutoString currentValue; nsAutoString format; format.AssignWithConversion("text/plain"); nsresult result = mEditor->OutputToString(currentValue, format, 0); if (PR_TRUE==IsSingleLineTextControl()) { RemoveNewlines(currentValue); } if (PR_FALSE==currentValue.Equals(aValue)) // this is necessary to avoid infinite recursion { // \r is an illegal character in the dom, but people use them, // so convert windows and mac platform linebreaks to \n: // Unfortunately aValue is declared const, so we have to copy // in order to do this substitution. currentValue.Assign(aValue); nsFormControlHelper::PlatformToDOMLineBreaks(currentValue); nsCOMPtrdomDoc; result = mEditor->GetDocument(getter_AddRefs(domDoc)); if (NS_FAILED(result)) return; if (!domDoc) return; result = mEditor->SelectAll(); nsCOMPtr htmlEditor = do_QueryInterface(mEditor); if (!htmlEditor) return; // get the flags, remove readonly and disabled, set the value, restore flags PRUint32 flags, savedFlags; mEditor->GetFlags(&savedFlags); flags = savedFlags; flags &= ~(nsIHTMLEditor::eEditorDisabledMask); flags &= ~(nsIHTMLEditor::eEditorReadonlyMask); mEditor->SetFlags(flags); mEditor->SelectAll(); mEditor->DeleteSelection(nsIEditor::eNone); htmlEditor->InsertText(currentValue); mEditor->SetFlags(savedFlags); } } } NS_IMETHODIMP nsGfxTextControlFrame2::SetInitialChildList(nsIPresContext* aPresContext, nsIAtom* aListName, nsIFrame* aChildList) { nsIFrame *list = aChildList; nsFrameState frameState; while (list) { list->GetFrameState(&frameState); frameState |= NS_FRAME_INDEPENDENT_SELECTION; list->SetFrameState(frameState); list->GetNextSibling(&list); } nsresult result = nsHTMLContainerFrame::SetInitialChildList(aPresContext, aListName, aChildList); if (mEditor) mEditor->PostCreate(); return result; } NS_IMETHODIMP nsGfxTextControlFrame2::GetSelectionController(nsIPresContext *aPresContext, nsISelectionController **aSelCon) { if (!aSelCon) return NS_ERROR_INVALID_ARG; NS_IF_ADDREF(*aSelCon = mSelCon); return NS_OK; } nsresult nsGfxTextControlFrame2::GetColRowSizeAttr(nsIFormControlFrame* aFrame, nsIAtom * aColSizeAttr, nsHTMLValue & aColSize, nsresult & aColStatus, nsIAtom * aRowSizeAttr, nsHTMLValue & aRowSize, nsresult & aRowStatus) { nsIContent* iContent = nsnull; aFrame->GetFormContent((nsIContent*&) iContent); if (!iContent) { return NS_ERROR_FAILURE; } nsIHTMLContent* hContent = nsnull; nsresult result = iContent->QueryInterface(kIHTMLContentIID, (void**)&hContent); if ((NS_OK != result) || !hContent) { NS_RELEASE(iContent); return NS_ERROR_FAILURE; } aColStatus = NS_CONTENT_ATTR_NOT_THERE; if (nsnull != aColSizeAttr) { aColStatus = hContent->GetHTMLAttribute(aColSizeAttr, aColSize); } aRowStatus= NS_CONTENT_ATTR_NOT_THERE; if (nsnull != aRowSizeAttr) { aRowStatus = hContent->GetHTMLAttribute(aRowSizeAttr, aRowSize); } NS_RELEASE(hContent); NS_RELEASE(iContent); return NS_OK; } PRInt32 nsGfxTextControlFrame2::GetWidthInCharacters() const { // see if there's a COL attribute, if so it wins nsCOMPtr content; nsresult result = mContent->QueryInterface(NS_GET_IID(nsIHTMLContent), getter_AddRefs(content)); if (NS_SUCCEEDED(result) && content) { nsHTMLValue resultValue; result = content->GetHTMLAttribute(nsHTMLAtoms::cols, resultValue); if (NS_CONTENT_ATTR_NOT_THERE != result) { if (resultValue.GetUnit() == eHTMLUnit_Integer) { return (resultValue.GetIntValue()); } } } // otherwise, see if CSS has a width specified. If so, work backwards to get the // number of characters this width represents. // otherwise, the default is just returned. return DEFAULT_COLUMN_WIDTH; }