diff --git a/mozilla/layout/forms/nsFileControlFrame.cpp b/mozilla/layout/forms/nsFileControlFrame.cpp index 2baa2c1e54d..52e884a8595 100644 --- a/mozilla/layout/forms/nsFileControlFrame.cpp +++ b/mozilla/layout/forms/nsFileControlFrame.cpp @@ -20,6 +20,7 @@ #include "nsFormFrame.h" #include "nsButtonControlFrame.h" #include "nsTextControlFrame.h" +#include "nsNativeTextControlFrame.h" // XXX: remove when frame construction is done properly #include "nsIContent.h" #include "prtypes.h" #include "nsIAtom.h" @@ -200,7 +201,10 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, if (disabled) { text->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::disabled, nsAutoString("1"), PR_FALSE); // XXX this should use an "empty" bool value } - NS_NewTextControlFrame(&childFrame); + + // XXX: hard-wired for the native text control frame + // construction of the text control should happen in nsCSSFrameConstruction + NS_NewNativeTextControlFrame(&childFrame); //XXX: This style should be cached, rather than resolved each time. // Get pseudo style for the text field diff --git a/mozilla/layout/forms/nsFormControlHelper.cpp b/mozilla/layout/forms/nsFormControlHelper.cpp index 8d46abfc28c..8d5d0e42be0 100644 --- a/mozilla/layout/forms/nsFormControlHelper.cpp +++ b/mozilla/layout/forms/nsFormControlHelper.cpp @@ -299,12 +299,15 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsWidgetRendering mode; aPresContext->GetWidgetRenderingMode(&mode); - // only add in padding if we are not Gfx + // only add in padding if we are not Gfx, or if we're a Gfx text widget PRBool requiresWidget = PR_FALSE; - aFrame->RequiresWidget(requiresWidget); + PRInt32 type; + aFrame->GetType(&type); - if (PR_TRUE == requiresWidget || eWidgetRendering_Gfx != mode) { + if (PR_TRUE == requiresWidget || eWidgetRendering_Gfx != mode || + type==NS_FORM_INPUT_TEXT || type==NS_FORM_TEXTAREA || type==NS_FORM_INPUT_PASSWORD) + { if (!aWidthExplicit) { PRInt32 hPadding = (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aDesiredSize.width, charWidth)); aDesiredSize.width += hPadding; @@ -340,14 +343,20 @@ nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, nsWidgetRendering m; aPresContext->GetWidgetRenderingMode(&m); - // only add in padding if we are not Gfx + // only add in padding if we are not Gfx, excluding the text widgets PRBool requiresWidget = PR_FALSE; - aFormFrame->RequiresWidget(requiresWidget); - if (PR_TRUE != requiresWidget && eWidgetRendering_Gfx == m) { - aFont = styleFont->mFont; - return; + PRInt32 type; + aFormFrame->GetType(&type); + + if (type!=NS_FORM_INPUT_TEXT && + type!=NS_FORM_TEXTAREA && + type!=NS_FORM_INPUT_PASSWORD) { + if (PR_TRUE != requiresWidget && eWidgetRendering_Gfx == m) { + aFont = styleFont->mFont; + return; + } } nsCompatibility mode; @@ -358,8 +367,6 @@ nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, return; } - PRInt32 type; - aFormFrame->GetType(&type); switch (type) { case NS_FORM_INPUT_TEXT: case NS_FORM_TEXTAREA: diff --git a/mozilla/layout/forms/nsTextControlFrame.cpp b/mozilla/layout/forms/nsTextControlFrame.cpp index f61f26a621c..34d3edec0c0 100644 --- a/mozilla/layout/forms/nsTextControlFrame.cpp +++ b/mozilla/layout/forms/nsTextControlFrame.cpp @@ -66,21 +66,6 @@ static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); -nsresult -NS_NewTextControlFrame(nsIFrame** aNewFrame) -{ - NS_PRECONDITION(aNewFrame, "null OUT ptr"); - if (nsnull == aNewFrame) { - return NS_ERROR_NULL_POINTER; - } - nsTextControlFrame* it = new nsTextControlFrame; - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - *aNewFrame = it; - return NS_OK; -} - nscoord nsTextControlFrame::GetVerticalBorderWidth(float aPixToTwip) const { @@ -209,26 +194,6 @@ nsTextControlFrame::GetCID() } } -void -nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) -{ - if (mFormFrame && mFormFrame->CanSubmit(*this)) { - nsIContent *formContent = nsnull; - - mFormFrame->GetContent(&formContent); - if (nsnull != formContent) { - nsEvent event; - nsEventStatus status = nsEventStatus_eIgnore; - - event.eventStructType = NS_EVENT; - event.message = NS_FORM_SUBMIT; - formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); - NS_RELEASE(formContent); - } - - mFormFrame->OnSubmit(&aPresContext, this); - } -} #define DEFAULT_PIXEL_WIDTH 20 void @@ -315,311 +280,12 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } -nsWidgetInitData* -nsTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) -{ - PRInt32 type; - GetType(&type); - - nsTextWidgetInitData* data = nsnull; - - PRBool readOnly = nsFormFrame::GetReadonly(this); - - if ((NS_FORM_INPUT_PASSWORD == type) || readOnly) { - data = new nsTextWidgetInitData(); - data->mIsPassword = PR_FALSE; - data->mIsReadOnly = PR_FALSE; - if (NS_FORM_INPUT_PASSWORD == type) { - data->clipChildren = PR_TRUE; - data->mIsPassword = PR_TRUE; - } - if (readOnly) { - data->mIsReadOnly = PR_TRUE; - } - } - - return data; -} - -NS_IMETHODIMP -nsTextControlFrame::GetText(nsString* aText, PRBool aInitialValue) -{ - nsresult result = NS_CONTENT_ATTR_NOT_THERE; - PRInt32 type; - GetType(&type); - if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { - result = nsFormControlHelper::GetInputElementValue(mContent, aText, aInitialValue); -/* XXX REMOVE - nsIDOMHTMLInputElement* textElem = nsnull; - result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); - if ((NS_OK == result) && textElem) { - if (PR_TRUE == aInitialValue) { - result = textElem->GetDefaultValue(*aText); - } - else { - result = textElem->GetValue(*aText); - } - - NS_RELEASE(textElem); - } -*/ - - } else { - nsIDOMHTMLTextAreaElement* textArea = nsnull; - result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); - if ((NS_OK == result) && textArea) { - if (PR_TRUE == aInitialValue) { - result = textArea->GetDefaultValue(*aText); - } - else { - result = textArea->GetValue(*aText); - } - NS_RELEASE(textArea); - } - } - return result; -} - -NS_IMETHODIMP -nsTextControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint) -{ - nsresult result = NS_OK; - if (mWidget) { - nsITextWidget* text = nsnull; - result = mWidget->QueryInterface(kITextWidgetIID, (void**)&text); - if ((NS_OK == result) && (nsnull != text)) { - if (nsHTMLAtoms::value == aAttribute) { - nsString value; - /*XXXnsresult rv = */GetText(&value, PR_TRUE); - PRUint32 ignore; - text->SetText(value, ignore); - nsFormFrame::StyleChangeReflow(aPresContext, this); - } else if (nsHTMLAtoms::maxlength == aAttribute) { - PRInt32 maxLength; - nsresult rv = GetMaxLength(&maxLength); - if (NS_CONTENT_ATTR_NOT_THERE != rv) { - text->SetMaxTextLength(maxLength); - } - } else if (nsHTMLAtoms::readonly == aAttribute) { - PRBool oldReadOnly; - text->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); - } - else if (nsHTMLAtoms::size == aAttribute) { - nsFormFrame::StyleChangeReflow(aPresContext, this); - } - // Allow the base class to handle common attributes supported - // by all form elements... - else { - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - NS_RELEASE(text); - } - // XXX Ick, create an common interface that has the functionality of nsTextHelper - else { // We didn't get a Text, is it a TextArea? - nsITextAreaWidget* textArea = nsnull; - result = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textArea); - if ((NS_OK == result) && (nsnull != textArea)) { - if (nsHTMLAtoms::value == aAttribute) { - nsString value; - /*XXXnsresult rv = */GetText(&value, PR_TRUE); - PRUint32 ignore; - textArea->SetText(value, ignore); - nsFormFrame::StyleChangeReflow(aPresContext, this); - } else if (nsHTMLAtoms::maxlength == aAttribute) { - PRInt32 maxLength; - nsresult rv = GetMaxLength(&maxLength); - if (NS_CONTENT_ATTR_NOT_THERE != rv) { - textArea->SetMaxTextLength(maxLength); - } - } else if (nsHTMLAtoms::readonly == aAttribute) { - PRBool oldReadOnly; - textArea->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); - } - else if (nsHTMLAtoms::size == aAttribute) { - nsFormFrame::StyleChangeReflow(aPresContext, this); - } - // Allow the base class to handle common attributes supported - // by all form elements... - else { - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - NS_RELEASE(textArea); - } - else { // We didn't get a Text or TextArea. Uh oh... - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - } - } - - return result; -} - -void -nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight) -{ - if (!mWidget) { - return; - } - - PRInt32 type; - GetType(&type); - - nsFont font(aPresContext->GetDefaultFixedFontDeprecated()); - GetFont(aPresContext, font); - mWidget->SetFont(font); - SetColors(*aPresContext); - - PRUint32 ignore; - nsAutoString value; - - nsITextAreaWidget* textArea = nsnull; - nsITextWidget* text = nsnull; - if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { - -#ifdef SingleSignon - /* get name of text */ - PRBool failed = PR_TRUE; - nsAutoString name; - GetName(&name); - - /* get url name */ - char *URLName = nsnull; - nsIURL* docURL = nsnull; - nsIDocument* doc = nsnull; - mContent->GetDocument(doc); - if (nsnull != doc) { - docURL = doc->GetDocumentURL(); - NS_RELEASE(doc); - if (nsnull != docURL) { - const char* spec; - (void)docURL->GetSpec(&spec); - if (nsnull != spec) { - URLName = (char*)PR_Malloc(PL_strlen(spec)+1); - PL_strcpy(URLName, spec); - } - NS_RELEASE(docURL); - } - } - - if (nsnull != URLName) { - /* invoke single-signon to get previously-used value of text */ - nsIWalletService *service; - nsresult res = nsServiceManager::GetService(kWalletServiceCID, - kIWalletServiceIID, - (nsISupports **)&service); - if ((NS_OK == res) && (nsnull != service)) { - char* valueString = NULL; - char* nameString = name.ToNewCString(); - res = service->SI_RestoreSignonData(URLName, nameString, &valueString); - delete[] nameString; - NS_RELEASE(service); - PR_FREEIF(URLName); - if (valueString && *valueString) { - value = valueString; - failed = PR_FALSE; - } - } - } - if (failed) { - GetText(&value, PR_TRUE); - } -#else - GetText(&value, PR_TRUE); -#endif - - 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)) { - GetText(&value, PR_TRUE); - textArea->SetText(value, ignore); - NS_RELEASE(textArea); - } - if (nsFormFrame::GetDisabled(this)) { - mWidget->Enable(PR_FALSE); - } -} 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, PR_TRUE); - - 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); - } - -} NS_IMETHODIMP nsTextControlFrame::GetCursor(nsIPresContext& aPresContext, nsPoint& aPoint, PRInt32& aCursor) @@ -639,261 +305,3 @@ nsTextControlFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TextControl", aResult); } - - -void -nsTextControlFrame::PaintTextControlBackground(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) { - nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); -} - -void -nsTextControlFrame::PaintTextControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsString& aText, - nsIStyleContext* aStyleContext, nsRect& aRect) -{ - aRenderingContext.PushState(); - - const nsStyleSpacing* spacing = - (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - spacing->CalcBorderFor(this, border); - - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - nsRect outside(aRect.x, aRect.y, aRect.width, aRect.height); - outside.Deflate(border); - outside.Deflate(onePixel, onePixel); - - nsRect inside(outside); - inside.Deflate(onePixel, onePixel); - -#if 0 - if (mGotFocus) { - PaintFocus(aRenderingContext, - aDirtyRect, inside, outside); - } -#endif - - float appUnits; - float devUnits; - float scale; - nsIDeviceContext * context; - aRenderingContext.GetDeviceContext(context); - - context->GetCanonicalPixelScale(scale); - context->GetAppUnitsToDevUnits(devUnits); - context->GetDevUnitsToAppUnits(appUnits); - - aRenderingContext.SetColor(NS_RGB(0,0,0)); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - aRenderingContext.SetFont(font); - - nscoord textWidth; - nscoord textHeight; - - aRenderingContext.GetWidth(aText, textWidth); - - nsIFontMetrics* metrics; - context->GetMetricsFor(font, metrics); - metrics->GetHeight(textHeight); - - PRInt32 type; - GetType(&type); - if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type) { - nscoord x = inside.x + onePixel + onePixel; - nscoord y; - - if (NS_FORM_INPUT_TEXT == type) { - y = ((inside.height - textHeight) / 2) + inside.y; - } else { - metrics->GetMaxAscent(textHeight); - y = ((inside.height - textHeight) / 2) + inside.y; - PRInt32 i; - PRInt32 len = aText.Length(); - aText.SetLength(0); - for (i=0;iGetCanonicalPixelScale(scale); - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); - PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale); - - inside.width -= scrollbarScaledWidth; - inside.height -= scrollbarScaledHeight; - PRBool clipEmpty; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty); - - nscoord x = inside.x + onePixel; - nscoord y = inside.y + onePixel; - - // Draw multi-line text - PRInt32 oldPos = 0; - PRInt32 pos = aText.Find('\n', 0); - while (1) { - nsString substr; - if (-1 == pos) { - // Single line, no carriage return. - aText.Right(substr, aText.Length()-oldPos); - aRenderingContext.DrawString(substr, x, y); - break; - } - // Strip off substr up to carriage return - aText.Mid(substr, oldPos, ((pos - oldPos) - 1)); - - aRenderingContext.DrawString(substr, x, y); - y += textHeight; - // Advance to the next carriage return - pos++; - oldPos = pos; - pos = aText.Find('\n', pos); - } - - aRenderingContext.PopState(clipEmpty); - - // Scrollbars - nsIAtom * sbAtom = NS_NewAtom(":scrollbar-look"); - nsIStyleContext* scrollbarStyle; - aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &scrollbarStyle); - NS_RELEASE(sbAtom); - - sbAtom = NS_NewAtom(":scrollbar-arrow-look"); - nsIStyleContext* arrowStyle; - aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &arrowStyle); - NS_RELEASE(sbAtom); - - nsRect srect(aRect.width-scrollbarScaledWidth-(2*onePixel), 2*onePixel, scrollbarScaledWidth, aRect.height-(onePixel*4)-scrollbarScaledWidth); - - nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_FALSE, onePixel, - scrollbarStyle, arrowStyle, this, aRect); - // Horizontal - srect.SetRect(2*onePixel, aRect.height-scrollbarScaledHeight-(2*onePixel), aRect.width-(onePixel*4)-scrollbarScaledHeight, scrollbarScaledHeight); - nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_TRUE, onePixel, - scrollbarStyle, arrowStyle, this, aRect); - - // Draw the small rect "gap" in the bottom right that the two scrollbars don't cover - const nsStyleColor* sbColor = (const nsStyleColor*)scrollbarStyle->GetStyleData(eStyleStruct_Color); - srect.SetRect(aRect.width-scrollbarScaledWidth-(2*onePixel), aRect.height-scrollbarScaledHeight-(onePixel*2), scrollbarScaledWidth, scrollbarScaledHeight); - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, srect, *sbColor, *spacing, 0, 0); - } - - - NS_RELEASE(context); - - PRBool status; - aRenderingContext.PopState(status); -} - -NS_METHOD -nsTextControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - PaintTextControlBackground(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsString text; - GetText(&text, PR_FALSE); - nsRect rect(0, 0, mRect.width, mRect.height); - PaintTextControl(aPresContext, aRenderingContext, aDirtyRect, text, mStyleContext, rect); - } - return NS_OK; -} - -void nsTextControlFrame::GetTextControlFrameState(nsString& aValue) -{ - if (nsnull != mWidget) { - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - PRUint32 size = 0; - if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { - text->GetText(aValue,0,size); - NS_RELEASE(text); - } - else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, - (void**)&textArea)) { - textArea->GetText(aValue,0, size); - NS_RELEASE(textArea); - } - } - else { - //XXX: this should return the a local field for GFX-rendered widgets aValue = ""; - } -} - -void nsTextControlFrame::SetTextControlFrameState(const nsString& aValue) -{ - if (nsnull != mWidget) { - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - PRUint32 size = 0; - if (NS_SUCCEEDED(mWidget->QueryInterface(kITextWidgetIID,(void**)&text))) { - text->SetText(aValue,size); - NS_RELEASE(text); - } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, - (void**)&textArea)) { - textArea->SetText(aValue,size); - NS_RELEASE(textArea); - } - } -} - -NS_IMETHODIMP nsTextControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) -{ - nsresult rv = NS_OK; - if (nsHTMLAtoms::value == aName) { - SetTextControlFrameState(aValue); - } else if (nsHTMLAtoms::select == aName) { - if (nsnull != mWidget) { - nsITextWidget *textWidget; - rv = mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget); - if (NS_SUCCEEDED(rv)) { - textWidget->SelectAll(); - NS_RELEASE(textWidget); - } - - nsITextAreaWidget *textAreaWidget; - rv = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textAreaWidget); - if (NS_SUCCEEDED(rv)) { - textAreaWidget->SelectAll(); - NS_RELEASE(textAreaWidget); - } - } - } - else { - return nsFormControlFrame::SetProperty(aName, aValue); - } - return rv; -} - -NS_IMETHODIMP nsTextControlFrame::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); - } - else { - return nsFormControlFrame::GetProperty(aName, aValue); - } - - return NS_OK; -} diff --git a/mozilla/layout/forms/nsTextControlFrame.h b/mozilla/layout/forms/nsTextControlFrame.h index 2555735dc38..989f6d70815 100644 --- a/mozilla/layout/forms/nsTextControlFrame.h +++ b/mozilla/layout/forms/nsTextControlFrame.h @@ -24,33 +24,15 @@ class nsIContent; class nsIFrame; class nsIPresContext; -class nsTextControlFrame : public nsFormControlFrame { +class nsTextControlFrame : public nsFormControlFrame +{ +/* ---------- methods implemented by base class ---------- */ public: - // nsIFormControlFrame - NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); - NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - - virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); - - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint); - - NS_IMETHOD GetFrameName(nsString& aResult) const; - - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight); - virtual const nsIID& GetCID(); - virtual const nsIID& GetIID(); - NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue); - - virtual void EnterPressed(nsIPresContext& aPresContext) ; - + NS_IMETHOD GetFrameName(nsString& aResult) const; + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; virtual nscoord GetVerticalInsidePadding(float aPixToTwip, @@ -60,40 +42,65 @@ public: nscoord aInnerWidth, nscoord aCharWidth) const; virtual PRInt32 GetMaxNumValues(); - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - virtual void Reset(); NS_IMETHOD GetCursor(nsIPresContext& aPresContext, nsPoint& aPoint, PRInt32& aCursor); - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - virtual void PaintTextControlBackground(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - virtual void PaintTextControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, nsString& aText, - nsIStyleContext* aStyleContext, - nsRect& aRect); - - // Utility methods to get and set current widget state - void GetTextControlFrameState(nsString& aValue); - void SetTextControlFrameState(const nsString& aValue); - protected: - - virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); + + + +/* ---------- abstract methods derived class must implement ---------- */ +public: + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue)=0; + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue)=0; + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext)=0; + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint)=0; + + virtual void PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight)=0; + + NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue)=0; + + virtual void EnterPressed(nsIPresContext& aPresContext)=0; + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames)=0; + virtual void Reset()=0; + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer)=0; + + virtual void PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer)=0; + + virtual void PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsString& aText, + nsIStyleContext* aStyleContext, + nsRect& aRect)=0; + + // Utility methods to get and set current widget state + virtual void GetTextControlFrameState(nsString& aValue)=0; + virtual void SetTextControlFrameState(const nsString& aValue)=0; + + virtual nsresult RequiresWidget(PRBool &aRequiresWidget)=0; + }; #endif diff --git a/mozilla/layout/html/forms/src/Makefile.in b/mozilla/layout/html/forms/src/Makefile.in index 8b991595ae8..81e0da41dc5 100644 --- a/mozilla/layout/html/forms/src/Makefile.in +++ b/mozilla/layout/html/forms/src/Makefile.in @@ -39,14 +39,16 @@ CPPSRCS = \ nsCheckboxControlFrame.cpp \ nsFileControlFrame.cpp \ nsRadioControlFrame.cpp \ - nsTextControlFrame.cpp \ + nsTextControlFrame.cpp \ + nsNativeTextControlFrame.cpp \ + nsGfxTextControlFrame.cpp \ nsSelectControlFrame.cpp \ nsFieldSetFrame.cpp \ nsLegendFrame.cpp \ nsHTMLButtonControlFrame.cpp \ nsLabelFrame.cpp \ nsImageControlFrame.cpp \ - nsButtonFrameRenderer.cpp \ + nsButtonFrameRenderer.cpp \ $(NULL) MODULE=layout diff --git a/mozilla/layout/html/forms/src/makefile.win b/mozilla/layout/html/forms/src/makefile.win index 4e2ba1f55fb..c5be928d9d4 100644 --- a/mozilla/layout/html/forms/src/makefile.win +++ b/mozilla/layout/html/forms/src/makefile.win @@ -33,7 +33,9 @@ CPPSRCS= \ nsCheckboxControlFrame.cpp \ nsFileControlFrame.cpp \ nsRadioControlFrame.cpp \ - nsTextControlFrame.cpp \ + nsTextControlFrame.cpp \ + nsGfxTextControlFrame.cpp \ + nsTextControlFrame.cpp \ nsSelectControlFrame.cpp \ nsFieldSetFrame.cpp \ nsLegendFrame.cpp \ @@ -53,6 +55,8 @@ CPP_OBJS= \ .\$(OBJDIR)\nsFileControlFrame.obj \ .\$(OBJDIR)\nsRadioControlFrame.obj \ .\$(OBJDIR)\nsTextControlFrame.obj \ + .\$(OBJDIR)\nsGfxTextControlFrame.obj \ + .\$(OBJDIR)\nsNativeTextControlFrame.obj \ .\$(OBJDIR)\nsSelectControlFrame.obj \ .\$(OBJDIR)\nsFieldSetFrame.obj \ .\$(OBJDIR)\nsLegendFrame.obj \ @@ -61,12 +65,23 @@ CPP_OBJS= \ .\$(OBJDIR)\nsButtonFrameRenderer.obj \ .\$(OBJDIR)\nsImageControlFrame.obj -LINCS=-I$(PUBLIC)\xpcom -I$(PUBLIC)\raptor -I$(PUBLIC)\js \ - -I$(PUBLIC)\dom -I$(PUBLIC)\netlib \ - -I$(PUBLIC)\wallet \ - -I..\..\base\src -I..\..\style\src \ - -I..\..\..\base\src -I..\..\content\src -I$(PUBLIC)\uconv \ - -I$(PUBLIC)\rdf + +LINCS= -I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\js \ + -I$(PUBLIC)\dom \ + -I$(PUBLIC)\pref \ + -I$(PUBLIC)\editor \ + -I$(PUBLIC)\netlib \ + -I$(PUBLIC)\wallet \ + -I$(PUBLIC)\uconv \ + -I$(PUBLIC)\rdf \ + -I..\..\base\src \ + -I..\..\style\src \ + -I..\..\..\base\src \ + -I..\..\content\src \ + -I$(PUBLIC)\uconv + LCFLAGS = \ $(LCFLAGS) \ diff --git a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp index 2baa2c1e54d..52e884a8595 100644 --- a/mozilla/layout/html/forms/src/nsFileControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsFileControlFrame.cpp @@ -20,6 +20,7 @@ #include "nsFormFrame.h" #include "nsButtonControlFrame.h" #include "nsTextControlFrame.h" +#include "nsNativeTextControlFrame.h" // XXX: remove when frame construction is done properly #include "nsIContent.h" #include "prtypes.h" #include "nsIAtom.h" @@ -200,7 +201,10 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsIPresContext& aPresContext, if (disabled) { text->SetAttribute(kNameSpaceID_HTML, nsHTMLAtoms::disabled, nsAutoString("1"), PR_FALSE); // XXX this should use an "empty" bool value } - NS_NewTextControlFrame(&childFrame); + + // XXX: hard-wired for the native text control frame + // construction of the text control should happen in nsCSSFrameConstruction + NS_NewNativeTextControlFrame(&childFrame); //XXX: This style should be cached, rather than resolved each time. // Get pseudo style for the text field diff --git a/mozilla/layout/html/forms/src/nsFormControlHelper.cpp b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp index 8d46abfc28c..8d5d0e42be0 100644 --- a/mozilla/layout/html/forms/src/nsFormControlHelper.cpp +++ b/mozilla/layout/html/forms/src/nsFormControlHelper.cpp @@ -299,12 +299,15 @@ nsFormControlHelper::CalculateSize (nsIPresContext* aPresContext, nsWidgetRendering mode; aPresContext->GetWidgetRenderingMode(&mode); - // only add in padding if we are not Gfx + // only add in padding if we are not Gfx, or if we're a Gfx text widget PRBool requiresWidget = PR_FALSE; - aFrame->RequiresWidget(requiresWidget); + PRInt32 type; + aFrame->GetType(&type); - if (PR_TRUE == requiresWidget || eWidgetRendering_Gfx != mode) { + if (PR_TRUE == requiresWidget || eWidgetRendering_Gfx != mode || + type==NS_FORM_INPUT_TEXT || type==NS_FORM_TEXTAREA || type==NS_FORM_INPUT_PASSWORD) + { if (!aWidthExplicit) { PRInt32 hPadding = (2 * aFrame->GetHorizontalInsidePadding(*aPresContext, p2t, aDesiredSize.width, charWidth)); aDesiredSize.width += hPadding; @@ -340,14 +343,20 @@ nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, nsWidgetRendering m; aPresContext->GetWidgetRenderingMode(&m); - // only add in padding if we are not Gfx + // only add in padding if we are not Gfx, excluding the text widgets PRBool requiresWidget = PR_FALSE; - aFormFrame->RequiresWidget(requiresWidget); - if (PR_TRUE != requiresWidget && eWidgetRendering_Gfx == m) { - aFont = styleFont->mFont; - return; + PRInt32 type; + aFormFrame->GetType(&type); + + if (type!=NS_FORM_INPUT_TEXT && + type!=NS_FORM_TEXTAREA && + type!=NS_FORM_INPUT_PASSWORD) { + if (PR_TRUE != requiresWidget && eWidgetRendering_Gfx == m) { + aFont = styleFont->mFont; + return; + } } nsCompatibility mode; @@ -358,8 +367,6 @@ nsFormControlHelper::GetFont(nsIFormControlFrame * aFormFrame, return; } - PRInt32 type; - aFormFrame->GetType(&type); switch (type) { case NS_FORM_INPUT_TEXT: case NS_FORM_TEXTAREA: diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxTextControlFrame.cpp new file mode 100644 index 00000000000..07986cce4d5 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame.cpp @@ -0,0 +1,1570 @@ +/* -*- 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 "nsCOMPtr.h" +#include "nsGfxTextControlFrame.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" + +#include "nsCSSRendering.h" +#include "nsIDeviceContext.h" +#include "nsIFontMetrics.h" +#include "nsILookAndFeel.h" +#include "nsIComponentManager.h" + +#include "nsIWebShell.h" +#include "nsINameSpaceManager.h" +#include "nsIPref.h" +#include "nsIView.h" +#include "nsIDocumentViewer.h" +#include "nsViewsCID.h" +#include "nsWidgetsCID.h" + +#include "nsIHTMLEditor.h" +#include "nsEditorCID.h" +#include "nsIDOMNode.h" +#include "nsIDOMElement.h" +#include "nsIDOMNodeList.h" +#include "nsIDOMSelection.h" +#include "nsIDOMCharacterData.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMEventReceiver.h" + +#ifdef SingleSignon +#include "prmem.h" +#include "nsIURL.h" +#include "nsIWalletService.h" +#include "nsIServiceManager.h" +static NS_DEFINE_IID(kIWalletServiceIID, NS_IWALLETSERVICE_IID); +static NS_DEFINE_IID(kWalletServiceCID, NS_WALLETSERVICE_CID); +#endif + +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); +static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); +static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIWebShellContainerIID, NS_IWEB_SHELL_CONTAINER_IID); +static NS_DEFINE_IID(kIWebShellIID, NS_IWEB_SHELL_IID); +static NS_DEFINE_IID(kWebShellCID, NS_WEB_SHELL_CID); +static NS_DEFINE_IID(kIViewIID, NS_IVIEW_IID); +static NS_DEFINE_IID(kCViewCID, NS_VIEW_CID); +static NS_DEFINE_IID(kCChildCID, NS_CHILD_CID); +static NS_DEFINE_IID(kIStreamObserverIID, NS_ISTREAMOBSERVER_IID); +static NS_DEFINE_IID(kIDocumentObserverIID, NS_IDOCUMENT_OBSERVER_IID); + +static NS_DEFINE_IID(kITextEditorIID, NS_ITEXTEDITOR_IID); +static NS_DEFINE_CID(kTextEditorCID, NS_TEXTEDITOR_CID); +static NS_DEFINE_IID(kIHTMLEditorIID, NS_IHTMLEDITOR_IID); +static NS_DEFINE_CID(kHTMLEditorCID, NS_HTMLEDITOR_CID); +static NS_DEFINE_IID(kIEditorIID, NS_IEDITOR_IID); +static NS_DEFINE_CID(kEditorCID, NS_EDITOR_CID); +static NS_DEFINE_IID(kIDocumentViewerIID, NS_IDOCUMENT_VIEWER_IID); +static NS_DEFINE_IID(kIDOMEventReceiverIID, NS_IDOMEVENTRECEIVER_IID); +static NS_DEFINE_IID(kIDOMKeyListenerIID, NS_IDOMKEYLISTENER_IID); + + +#define EMPTY_DOCUMENT "resource:/res/html/empty_doc.html" + +//#define NOISY + +extern nsresult NS_NewNativeTextControlFrame(nsIFrame** aNewFrame); + +nsresult +NS_NewGfxTextControlFrame(nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + *aNewFrame = new nsGfxTextControlFrame; + if (nsnull == aNewFrame) { + return NS_ERROR_OUT_OF_MEMORY; + } + nsresult result = ((nsGfxTextControlFrame*)(*aNewFrame))->InitTextControl(); + if (NS_FAILED(result)) + { // can't properly initialized ender, probably it isn't installed + //NS_RELEASE(*aNewFrame); // XXX: need to release allocated ender text frame! + result = NS_NewNativeTextControlFrame(aNewFrame); + } + return result; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::InitTextControl() +{ + nsresult result = NS_OK; + + mWebShell = 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); + + if (PR_TRUE==IsPlainTextControl()) + { + nsCOMPtr theEditor; + result = nsComponentManager::CreateInstance(kTextEditorCID, + nsnull, + kITextEditorIID, + 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; } + } + else + { + nsCOMPtr theEditor; + result = nsComponentManager::CreateInstance(kHTMLEditorCID, + nsnull, + kIHTMLEditorIID, 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; } + } + + // allocate mDummy here to self-check native text control impl. vs. ender text control impl. + //NS_NewNativeTextControlFrame((nsIFrame **)&mDummyFrame); //DUMMY + // mDummyInitialized = PR_TRUE; //DUMMY + return NS_OK; +} + +nsGfxTextControlFrame::nsGfxTextControlFrame() +: mWebShell(0), mCreatingViewer(PR_FALSE), + mTempObserver(0), mDocObserver(0), + mDummyFrame(0), mNeedsStyleInit(PR_TRUE), + mDummyInitialized(PR_FALSE) // DUMMY +{ +} + +nsGfxTextControlFrame::~nsGfxTextControlFrame() +{ + if (mTempObserver) + { + mTempObserver->SetFrame(nsnull); + NS_RELEASE(mTempObserver); + } + if (mKeyListener) + { + nsCOMPtreditor = do_QueryInterface(mEditor); + NS_ASSERTION(editor, "bad QI to nsIEditor from mEditor"); + if (editor) + { + nsCOMPtrdomDoc; + nsresult result = editor->GetDocument(getter_AddRefs(domDoc)); + if (NS_SUCCEEDED(result) && domDoc) + { + nsCOMPtr er; + result = domDoc->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(er)); + if (NS_SUCCEEDED(result) && er) { + er->RemoveEventListenerByIID(mKeyListener, kIDOMKeyListenerIID); + } + } + } + } + mEditor = do_QueryInterface(nsnull); // editor must be destroyed before the webshell! + if (nsnull != mWebShell) + { + mWebShell->Destroy(); + NS_RELEASE(mWebShell); + } + if (mDocObserver) + { + mDocObserver->SetFrame(nsnull); + NS_RELEASE(mDocObserver); + } + + // this will be a leak -- NS_IF_RELEASE(mDummyFrame); +} + +void +nsGfxTextControlFrame::EnterPressed(nsIPresContext& aPresContext) +{ + if (mFormFrame && mFormFrame->CanSubmit(*this)) { + nsIContent *formContent = nsnull; + + mFormFrame->GetContent(&formContent); + if (nsnull != formContent) { + nsEvent event; + nsEventStatus status = nsEventStatus_eIgnore; + + event.eventStructType = NS_EVENT; + event.message = NS_FORM_SUBMIT; + formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + NS_RELEASE(formContent); + } + + mFormFrame->OnSubmit(&aPresContext, this); + } +} + +nsWidgetInitData* +nsGfxTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) +{ + return nsnull; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetText(nsString* aText, PRBool aInitialValue) +{ + nsresult result = NS_CONTENT_ATTR_NOT_THERE; + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) + { + if (PR_TRUE==aInitialValue) + { + result = nsFormControlHelper::GetInputElementValue(mContent, aText, aInitialValue); + } + else + { + if (PR_TRUE==IsInitialized()) { + result = mEditor->OutputTextToString(*aText); + } + else { + result = nsFormControlHelper::GetInputElementValue(mContent, aText, aInitialValue); + } + } + RemoveNewlines(*aText); + } + else + { + nsIDOMHTMLTextAreaElement* textArea = nsnull; + result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + if ((NS_OK == result) && textArea) { + if (PR_TRUE == aInitialValue) { + result = textArea->GetDefaultValue(*aText); + } + else { + result = textArea->GetValue(*aText); + } + NS_RELEASE(textArea); + } + } + return result; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + if (PR_FALSE==IsInitialized()) {return NS_ERROR_NOT_INITIALIZED;} + nsresult result = NS_OK; + + if (nsHTMLAtoms::value == aAttribute) + { + nsString value; + GetText(&value, PR_TRUE); // get the initial value from the content attribute + mEditor->EnableUndo(PR_FALSE); // wipe out undo info + SetTextControlFrameState(value); // set new text value + mEditor->EnableUndo(PR_TRUE); // fire up a new txn stack + nsFormFrame::StyleChangeReflow(aPresContext, this); + } + else if (nsHTMLAtoms::maxlength == aAttribute) + { + PRInt32 maxLength; + nsresult rv = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != rv) { + mEditor->SetMaxTextLength(maxLength); + } + } + else if (nsHTMLAtoms::readonly == aAttribute) + { + PRBool readOnly = nsFormFrame::GetReadonly(this); + PRUint32 flags; + mEditor->GetFlags(&flags); + flags |= readOnly; + mEditor->SetFlags(flags); + } + else if (nsHTMLAtoms::size == aAttribute) { + nsFormFrame::StyleChangeReflow(aPresContext, this); + } + // Allow the base class to handle common attributes supported + // by all form elements... + else { + result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); + } + +// DUMMY + if (mDummyFrame) + { + nsresult dummyResult = mDummyFrame->AttributeChanged(aPresContext, aChild, aAttribute, aHint); + } +// END DUMMY + + return result; +} + +void +nsGfxTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight) +{ + nsresult rv; + // initialize the webshell, if it hasn't already been constructed + // if the size is not 0 and there is a src, create the web shell + if (aPresContext && (aWidth >= 0) && (aHeight >= 0)) + { + if (nsnull == mWebShell) + { + nsSize maxSize(aWidth, aHeight); + rv = CreateWebShell(*aPresContext, maxSize); + NS_ASSERTION(nsnull!=mWebShell, "null web shell after attempt to create."); + } + + if (nsnull != mWebShell) + { + mCreatingViewer=PR_TRUE; + nsAutoString url(EMPTY_DOCUMENT); + rv = mWebShell->LoadURL(url.GetUnicode()); // URL string with a default nsnull value for post Data + } + } +} + +PRBool +nsGfxTextControlFrame::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames) +{ + if (!aValues || !aNames) { return PR_FALSE; } + + nsAutoString name; + nsresult result = GetName(&name); + if ((aMaxNumValues <= 0) || (NS_CONTENT_ATTR_NOT_THERE == result)) { + return PR_FALSE; + } + + aNames[0] = name; + aNumValues = 1; + + GetText(&(aValues[0]), PR_FALSE); + // XXX: error checking + return PR_TRUE; +} + + +void +nsGfxTextControlFrame::Reset() +{ + nsAutoString value; + nsresult valStatus = GetText(&value, PR_TRUE); + // XXX: error checking + SetTextControlFrameState(value); +} + +NS_METHOD +nsGfxTextControlFrame::Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + if (mWebShell) + { + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) + { + nsAutoString text(" "); + nsRect rect(0, 0, mRect.width, mRect.height); + PaintTextControl(aPresContext, aRenderingContext, aDirtyRect, + text, mStyleContext, rect); + } + } + return NS_OK; +} + +void +nsGfxTextControlFrame::PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + // we paint our own border, but everything else is painted by the mWebshell + if (mWebShell) + { + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) + { + nsAutoString text(" "); + nsRect rect(0, 0, mRect.width, mRect.height); + PaintTextControl(aPresContext, aRenderingContext, aDirtyRect, + text, mStyleContext, rect); + } + } +} + +void +nsGfxTextControlFrame::PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsString& aText, + nsIStyleContext* aStyleContext, + nsRect& aRect) +{ + // XXX: aText is currently unused! + const nsStyleDisplay* disp = (const nsStyleDisplay*)mStyleContext->GetStyleData(eStyleStruct_Display); + if (disp->mVisible) + { + const nsStyleSpacing* mySpacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + PRIntn skipSides = 0; + nsRect rect(0, 0, mRect.width, mRect.height); + //PaintTextControl(aPresContext, aRenderingContext, text, mStyleContext, rect); + nsCSSRendering::PaintBorder(aPresContext, aRenderingContext, this, + aDirtyRect, rect, *mySpacing, aStyleContext, skipSides); + } +} + +void nsGfxTextControlFrame::GetTextControlFrameState(nsString& aValue) +{ + aValue = ""; // initialize out param + if (PR_TRUE==IsInitialized()) { + mEditor->OutputTextToString(aValue); + } +} + +void nsGfxTextControlFrame::SetTextControlFrameState(const nsString& aValue) +{ + if (PR_TRUE==IsInitialized()) + { + nsAutoString currentValue; + nsresult result = mEditor->OutputTextToString(currentValue); + if (PR_TRUE==IsSingleLineTextControl()) { + RemoveNewlines(currentValue); + } + if (PR_FALSE==currentValue.Equals(aValue)) // this is necessary to avoid infinite recursion + { + nsCOMPtreditor = do_QueryInterface(mEditor); + NS_ASSERTION(editor, "bad QI to nsIEditor from mEditor"); + if (editor) + { + nsCOMPtrselection; + result = editor->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(result) && selection) + { + nsCOMPtrdomDoc; + editor->GetDocument(getter_AddRefs(domDoc)); + if (domDoc) + { + nsCOMPtr bodyNode; + nsAutoString bodyTag = "body"; + result = GetFirstNodeOfType(bodyTag, domDoc, getter_AddRefs(bodyNode)); + SelectAllTextContent(bodyNode, selection); + mEditor->InsertText(aValue); + } + } + } + } + } +} + +NS_IMETHODIMP nsGfxTextControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) +{ + if (nsHTMLAtoms::value == aName) + { + mEditor->EnableUndo(PR_FALSE); // wipe out undo info + SetTextControlFrameState(aValue); // set new text value + mEditor->EnableUndo(PR_TRUE); // fire up a new txn stack + } + else { + return nsFormControlFrame::SetProperty(aName, aValue); + } + return NS_OK; +} + +NS_IMETHODIMP nsGfxTextControlFrame::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); + } + else { + return nsFormControlFrame::GetProperty(aName, aValue); + } + + return NS_OK; +} + + +/* --------------------- Ender methods ---------------------- */ + + +nsresult +nsGfxTextControlFrame::CreateWebShell(nsIPresContext& aPresContext, + const nsSize& aSize) +{ + nsresult rv; + nsIContent* content; + GetContent(&content); // ??? + + rv = nsComponentManager::CreateInstance(kWebShellCID, nsnull, kIWebShellIID, + (void**)&mWebShell); + if (NS_OK != rv) { + NS_ASSERTION(0, "could not create web widget"); + return rv; + } + + // pass along marginwidth, marginheight, scrolling so sub document can use it + mWebShell->SetMarginWidth(0); + mWebShell->SetMarginHeight(0); + nsCompatibility mode; + aPresContext.GetCompatibilityMode(&mode); + mWebShell->SetScrolling(NS_STYLE_OVERFLOW_AUTO); + mWebShell->SetIsFrame(PR_TRUE); + + /* XXX + nsString frameName; + if (GetName(content, frameName)) { + mWebShell->SetName(frameName.GetUnicode()); + } + */ + + // If our container is a web-shell, inform it that it has a new + // child. If it's not a web-shell then some things will not operate + // properly. + nsISupports* container; + aPresContext.GetContainer(&container); + if (nsnull != container) + { + nsIWebShell* outerShell = nsnull; + container->QueryInterface(kIWebShellIID, (void**) &outerShell); + if (nsnull != outerShell) { + outerShell->AddChild(mWebShell); + + // connect the container... + nsIWebShellContainer* outerContainer = nsnull; + container->QueryInterface(kIWebShellContainerIID, (void**) &outerContainer); + if (nsnull != outerContainer) { + mWebShell->SetContainer(outerContainer); + NS_RELEASE(outerContainer); + } + +#ifdef INCLUDE_XUL + nsWebShellType parentType; + outerShell->GetWebShellType(parentType); + nsIAtom* typeAtom = NS_NewAtom("type"); + nsAutoString value; + content->GetAttribute(kNameSpaceID_None, typeAtom, value); + if (value.EqualsIgnoreCase("content")) { + // The web shell's type is content. + mWebShell->SetWebShellType(nsWebShellContent); + nsCOMPtr shellAsContainer; + shellAsContainer = do_QueryInterface(mWebShell); + shellAsContainer->ContentShellAdded(mWebShell, content); + } + else { + // Inherit our type from our parent webshell. If it is + // chrome, we'll be chrome. If it is content, we'll be + // content. + mWebShell->SetWebShellType(parentType); + } +#endif // INCLUDE_XUL + + nsIPref* outerPrefs = nsnull; // connect the prefs + outerShell->GetPrefs(outerPrefs); + if (nsnull != outerPrefs) + { + mWebShell->SetPrefs(outerPrefs); + NS_RELEASE(outerPrefs); + } + NS_RELEASE(outerShell); + } + NS_RELEASE(container); + } + + float t2p; + aPresContext.GetTwipsToPixels(&t2p); + nsCOMPtr presShell; + aPresContext.GetShell(getter_AddRefs(presShell)); + + // create, init, set the parent of the view + nsIView* view; + rv = nsComponentManager::CreateInstance(kCViewCID, nsnull, kIViewIID, + (void **)&view); + if (NS_OK != rv) { + NS_ASSERTION(0, "Could not create view for nsHTMLFrame"); + return rv; + } + + nsIView* parView; + nsPoint origin; + GetOffsetFromView(origin, &parView); + nsRect viewBounds(origin.x, origin.y, aSize.width, aSize.height); + + nsCOMPtr viewMan; + presShell->GetViewManager(getter_AddRefs(viewMan)); + rv = view->Init(viewMan, viewBounds, parView); + viewMan->InsertChild(parView, view, 0); + rv = view->CreateWidget(kCChildCID); + SetView(view); + + // if the visibility is hidden, reflect that in the view + const nsStyleDisplay* display; + GetStyleData(eStyleStruct_Display, ((const nsStyleStruct *&)display)); + if (NS_STYLE_VISIBILITY_HIDDEN == display->mVisible) { + view->SetVisibility(nsViewVisibility_kHide); + } + + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); + nsMargin border; + spacing->CalcBorderFor(this, border); + + nsIWidget* widget; + view->GetWidget(widget); + nsRect webBounds(NSToCoordRound(border.left * t2p), + NSToCoordRound(border.top * t2p), + NSToCoordRound((aSize.width - border.right) * t2p), + NSToCoordRound((aSize.height - border.bottom) * t2p)); + + mWebShell->Init(widget->GetNativeData(NS_NATIVE_WIDGET), + webBounds.x, webBounds.y, + webBounds.width, webBounds.height); + NS_RELEASE(content); + NS_RELEASE(widget); + + mWebShell->SetObserver(mTempObserver); + mWebShell->Show(); + + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aMetrics, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, + ("enter nsGfxTextControlFrame::Reflow: aMaxSize=%d,%d", + aReflowState.availableWidth, aReflowState.availableHeight)); + + NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow"); + + nsresult rv = nsFormControlFrame::Reflow(aPresContext, aMetrics, aReflowState, aStatus); +#ifdef NOISY + printf ("exit nsGfxTextControlFrame::Reflow: size=%d,%d", + aMetrics.width, aMetrics.height); +#endif + + + // resize the sub document + if (NS_SUCCEEDED(rv) && mWebShell) + { + // get the border + const nsStyleSpacing* spacing; + GetStyleData(eStyleStruct_Spacing, (const nsStyleStruct *&)spacing); nsMargin border; + spacing->CalcBorderFor(this, border); + + float t2p; + aPresContext.GetTwipsToPixels(&t2p); + nsRect subBounds; + + // XXX: the point here is to make a single-line edit field as wide as it wants to be, + // so it will scroll horizontally if the characters take up more space than the field + subBounds.x = NSToCoordRound(border.left * t2p); + subBounds.y = NSToCoordRound(border.top * t2p); + subBounds.width = NSToCoordRound((aMetrics.width - (border.left + border.right)) * t2p); + subBounds.height = NSToCoordRound((aMetrics.height - (border.top + border.bottom)) * t2p); + mWebShell->SetBounds(subBounds.x, subBounds.y, 106, 20); + mWebShell->SetBounds(subBounds.x, subBounds.y, subBounds.width, subBounds.height); + mWebShell->Repaint(PR_TRUE); +#ifdef NOISY + printf("webshell set to (%d, %d, %d %d)\n", + border.left, border.top, + (aMetrics.width - (border.left + border.right)), + (aMetrics.height - (border.top + border.bottom))); +#endif + } + + NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS, + ("exit nsGfxTextControlFrame::Reflow: size=%d,%d", + aMetrics.width, aMetrics.height)); + +// DUMMY + if (mDummyFrame) + { + if (!mDummyInitialized) + { + mDummyFrame->Init(aPresContext, mContent, mParent, mStyleContext, nsnull); + mDummyInitialized = PR_TRUE; + } + nsHTMLReflowMetrics metrics = aMetrics; + nsHTMLReflowState reflowState = aReflowState; + nsReflowStatus status = aStatus; + nsresult dummyResult = mDummyFrame->Reflow(aPresContext, metrics, reflowState, status); + if (aMetrics.width != metrics.width) + { + printf("CT: different widths\n"); + NS_ASSERTION(0, "CT: different widths\n"); + } + if (aMetrics.height != metrics.height) + { + printf("CT: different heights\n"); + NS_ASSERTION(0, "CT: different heights\n"); + } + } +// END DUMMY + + return NS_OK; +} + +nsresult +nsGfxTextControlFrame::RequiresWidget(PRBool &aRequiresWidget) +{ + aRequiresWidget = PR_FALSE; + return NS_OK; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetPresShellFor(nsIWebShell* aWebShell, nsIPresShell** aPresShell) +{ + if (!aWebShell || !aPresShell) { return NS_ERROR_NULL_POINTER; } + nsresult result = NS_ERROR_NULL_POINTER; + *aPresShell = nsnull; + nsIContentViewer* cv = nsnull; + aWebShell->GetContentViewer(&cv); + if (nsnull != cv) + { + nsIDocumentViewer* docv = nsnull; + cv->QueryInterface(kIDocumentViewerIID, (void**) &docv); + if (nsnull != docv) + { + nsIPresContext* cx; + docv->GetPresContext(cx); + if (nsnull != cx) + { + result = cx->GetShell(aPresShell); + NS_RELEASE(cx); + } + NS_RELEASE(docv); + } + NS_RELEASE(cv); + } + return result; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::GetFirstNodeOfType(const nsString& aTag, nsIDOMDocument *aDOMDoc, nsIDOMNode **aNode) +{ + if (!aDOMDoc || !aNode) { return NS_ERROR_NULL_POINTER; } + *aNode=nsnull; + nsCOMPtrnodeList; + nsresult result = aDOMDoc->GetElementsByTagName(aTag, getter_AddRefs(nodeList)); + if ((NS_SUCCEEDED(result)) && nodeList) + { + PRUint32 count; + nodeList->GetLength(&count); + result = nodeList->Item(0, aNode); + if (!aNode) { result = NS_ERROR_NULL_POINTER; } + } + return result; +} + +nsresult +nsGfxTextControlFrame::GetFirstFrameForType(const nsString& aTag, nsIPresShell *aPresShell, + nsIDOMDocument *aDOMDoc, nsIFrame **aResult) +{ + if (!aPresShell || !aDOMDoc || !aResult) { return NS_ERROR_NULL_POINTER; } + nsresult result; + *aResult = nsnull; + nsCOMPtrnode; + result = GetFirstNodeOfType(aTag, aDOMDoc, getter_AddRefs(node)); + if ((NS_SUCCEEDED(result)) && node) + { + nsCOMPtrcontent = do_QueryInterface(node); + if (content) + { + result = aPresShell->GetPrimaryFrameFor(content, aResult); + } + } + return result; +} + +// XXX: this really should use a content iterator over the whole document +// looking for the first and last text node +nsresult +nsGfxTextControlFrame::SelectAllTextContent(nsIDOMNode *aBodyNode, nsIDOMSelection *aSelection) +{ + if (!aBodyNode || !aSelection) { return NS_ERROR_NULL_POINTER; } + nsCOMPtrfirstChild, lastChild; + nsresult result = aBodyNode->GetFirstChild(getter_AddRefs(firstChild)); + if ((NS_SUCCEEDED(result)) && firstChild) + { + result = aBodyNode->GetLastChild(getter_AddRefs(lastChild)); + if ((NS_SUCCEEDED(result)) && lastChild) + { + aSelection->Collapse(firstChild, 0); + nsCOMPtrtext = do_QueryInterface(lastChild); + if (text) + { + PRUint32 length; + text->GetLength(&length); + aSelection->Extend(lastChild, length); + } + } + } + return result; +} + +// XXX: wouldn't it be nice to get this from the style context! +PRBool nsGfxTextControlFrame::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 nsGfxTextControlFrame::IsPlainTextControl() const +{ + // need to check HTML attribute of mContent and/or CSS. + return PR_TRUE; +} + +PRBool nsGfxTextControlFrame::IsPasswordTextControl() const +{ + PRInt32 type; + GetType(&type); + if (NS_FORM_INPUT_PASSWORD==type) { + return PR_TRUE; + } + return PR_FALSE; +} + +// so we don't have to keep an extra flag around, just see if +// we've allocated the key listener or not. +PRBool nsGfxTextControlFrame::IsInitialized() const +{ + return (PRBool)(nsnull!=mEditor.get() && nsnull!=mKeyListener.get()); +} + +NS_IMETHODIMP +nsGfxTextControlFrame::InstallEditor() +{ + nsresult result = NS_ERROR_NULL_POINTER; + if (mEditor) + { + nsCOMPtr presShell; + result = GetPresShellFor(mWebShell, getter_AddRefs(presShell)); + if (NS_FAILED(result)) { return result; } + if (!presShell) { return NS_ERROR_NULL_POINTER; } + nsCOMPtr domDoc; + nsCOMPtr doc; + presShell->GetDocument(getter_AddRefs(doc)); + NS_ASSERTION(doc, "null document"); + if (!doc) { return NS_ERROR_NULL_POINTER; } + domDoc = do_QueryInterface(doc); + if (!domDoc) { return NS_ERROR_NULL_POINTER; } + + if (mDocObserver) { + doc->AddObserver(mDocObserver); + } + + // we need to hook up our key listener before the editor is initialized + result = NS_NewEnderKeyListener(getter_AddRefs(mKeyListener)); + if (NS_SUCCEEDED(result) && mKeyListener) + { + mKeyListener->SetFrame(this); + // get the DOM event receiver + nsCOMPtr er; + result = domDoc->QueryInterface(kIDOMEventReceiverIID, getter_AddRefs(er)); + if (!er) { result = NS_ERROR_NULL_POINTER; } + if (NS_SUCCEEDED(result)) { + result = er->AddEventListenerByIID(mKeyListener, kIDOMKeyListenerIID); + } + if (NS_FAILED(result)) { // either we couldn't get er, or we couldn't add the listener + mKeyListener = do_QueryInterface(nsnull); // null out the listener, it's useless + } + } + + result = mEditor->Init(domDoc, presShell); + if (NS_SUCCEEDED(result)) { + result = InitializeTextControl(presShell, domDoc); + } + } + return result; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::InitializeTextControl(nsIPresShell *aPresShell, nsIDOMDocument *aDoc) +{ + nsresult result; + if (!aPresShell || !aDoc) { return NS_ERROR_NULL_POINTER; } + + nsIFrame *htmlFrame; + nsAutoString htmlTag("body"); + result = GetFirstFrameForType(htmlTag, aPresShell, aDoc, &htmlFrame); + if (NS_SUCCEEDED(result) && htmlFrame) + { + PRInt32 type; + GetType(&type); + + nsCOMPtrpresContext; + aPresShell->GetPresContext(getter_AddRefs(presContext)); + NS_ASSERTION(presContext, "null presentation context"); + if (!presContext) { return NS_ERROR_NULL_POINTER; } + + /* this is the code for setting the pres context, which is MUCH better + * than grabbing the imbedded HTML frame and setting it. + * alas, the mechanisms for doing this are not yet in place. + * what I want to do is hand the webshell my pres context at creation + */ + /* + nsFont font(presContext->GetDefaultFixedFontDeprecated()); + GetFont(presContext, font); + const nsStyleFont* controlFont; + GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)controlFont); + presContext->SetDefaultFont(font); + presContext->SetDefaultFixedFont(font); + + const nsStyleColor* controlColor; + GetStyleData(eStyleStruct_Color, (const nsStyleStruct *&)controlColor); + presContext->SetDefaultColor(controlColor->mColor); + presContext->SetDefaultBackgroundColor(controlColor->mBackgroundColor); + presContext->SetDefaultBackgroundImageRepeat(controlColor->mBackgroundRepeat); + presContext->SetDefaultBackgroundImageAttachment(controlColor->mBackgroundAttachment); + presContext->SetDefaultBackgroundImageOffset(controlColor->mBackgroundXPosition, controlColor->mBackgroundYPosition); + presContext->SetDefaultBackgroundImage(controlColor->mBackgroundImage); + */ + + nsIStyleContext* bodySC = nsnull; + htmlFrame->GetStyleContext(&bodySC); + nsStyleSpacing* bodySpacing = nsnull; + bodySpacing = (nsStyleSpacing*)bodySC->GetMutableStyleData(eStyleStruct_Spacing); + nsStyleCoord zero(0); + bodySpacing->mMargin.SetLeft(zero); + bodySpacing->mMargin.SetRight(zero); + bodySpacing->mMargin.SetTop(zero); + bodySpacing->mMargin.SetBottom(zero); + bodySpacing->mPadding.SetLeft(zero); + bodySpacing->mPadding.SetRight(zero); + bodySpacing->mPadding.SetTop(zero); + bodySpacing->mPadding.SetBottom(zero); + bodySpacing->mBorder.SetLeft(zero); + bodySpacing->mBorder.SetRight(zero); + bodySpacing->mBorder.SetTop(zero); + bodySpacing->mBorder.SetBottom(zero); + + nsStylePosition* bodyPosition = nsnull; + bodyPosition = (nsStylePosition*)bodySC->GetMutableStyleData(eStyleStruct_Position); + const nsStylePosition* controlPosition; + GetStyleData(eStyleStruct_Position, (const nsStyleStruct *&)controlPosition); + *bodyPosition = *controlPosition; +/* qqq + if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type) { + bodyPosition->mWidth.SetIntValue(10000, eStyleUnit_Chars); + } +*/ + + nsStyleFont* bodyFont = nsnull; + bodyFont = (nsStyleFont*)bodySC->GetMutableStyleData(eStyleStruct_Font); + //const nsStyleFont* controlFont; + //GetStyleData(eStyleStruct_Font, (const nsStyleStruct *&)controlFont); + //*bodyFont = *controlFont; + nsFont font(presContext->GetDefaultFixedFontDeprecated()); + GetFont(presContext, font); + bodyFont->mFont = font; + bodyFont->mFixedFont = font; + + nsStyleColor* bodyColor = nsnull; + bodyColor = (nsStyleColor*)bodySC->GetMutableStyleData(eStyleStruct_Color); + const nsStyleColor* controlColor; + GetStyleData(eStyleStruct_Color, (const nsStyleStruct *&)controlColor); + *bodyColor = *controlColor; + + nsStyleText* bodyText = nsnull; + bodyText = (nsStyleText*)bodySC->GetMutableStyleData(eStyleStruct_Text); + const nsStyleText* controlText; + GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)controlText); + *bodyText = *controlText; + if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type) { + // qqq bodyText->mWhiteSpace = NS_STYLE_WHITESPACE_MOZ_PRE_WRAP; + bodyText->mWhiteSpace = NS_STYLE_WHITESPACE_PRE; + } + bodyText->mTextAlign = NS_STYLE_TEXT_ALIGN_LEFT; + + bodySC->RecalcAutomaticData(presContext); + NS_RELEASE(bodySC); + + // now that the style context is initialized, initialize the content + + nsAutoString value; + + nsITextAreaWidget* textArea = nsnull; + nsITextWidget* text = nsnull; + if (PR_TRUE == IsSingleLineTextControl()) + { + #ifdef SingleSignon + // get name of text + PRBool failed = PR_TRUE; + nsAutoString name; + GetName(&name); + + // get url name + char *URLName = nsnull; + nsIURL* docURL = nsnull; + nsIDocument* doc = nsnull; + mContent->GetDocument(doc); + if (nsnull != doc) { + docURL = doc->GetDocumentURL(); + NS_RELEASE(doc); + if (nsnull != docURL) { + const char* spec; + (void)docURL->GetSpec(&spec); + if (nsnull != spec) { + URLName = (char*)PR_Malloc(PL_strlen(spec)+1); + PL_strcpy(URLName, spec); + } + NS_RELEASE(docURL); + } + } + + if (nsnull != URLName) { + // invoke single-signon to get previously-used value of text + nsIWalletService *service; + nsresult res = nsServiceManager::GetService(kWalletServiceCID, + kIWalletServiceIID, + (nsISupports **)&service); + if ((NS_OK == res) && (nsnull != service)) { + char* valueString = NULL; + char* nameString = name.ToNewCString(); + res = service->SI_RestoreSignonData(URLName, nameString, &valueString); + delete[] nameString; + NS_RELEASE(service); + PR_FREEIF(URLName); + if (valueString && *valueString) { + value = valueString; + failed = PR_FALSE; + } + } + } + if (failed) { + GetText(&value, PR_TRUE); + } + #else + GetText(&value, PR_TRUE); + #endif + } + else { + GetText(&value, PR_TRUE); + } + mEditor->EnableUndo(PR_FALSE); + + PRInt32 maxLength; + nsresult result = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != result) { + mEditor->SetMaxTextLength(maxLength); + } + + nsCOMPtreditor = do_QueryInterface(mEditor); + NS_ASSERTION(editor, "bad QI to nsIEditor from mEditor"); + if (editor) + { + nsCOMPtrselection; + result = editor->GetSelection(getter_AddRefs(selection)); + if (NS_SUCCEEDED(result) && selection) + { + nsCOMPtrbodyNode; + nsAutoString bodyTag = "body"; + result = GetFirstNodeOfType(bodyTag, aDoc, getter_AddRefs(bodyNode)); + if (NS_SUCCEEDED(result) && bodyNode) + { + result = SelectAllTextContent(bodyNode, selection); + if (NS_SUCCEEDED(result)) + { + if (0!=value.Length()) + { + result = mEditor->InsertText(value); + result = SelectAllTextContent(bodyNode, selection); + } + selection->ClearSelection(); + } + } + } + } + + + /* + SetColors(*aPresContext); + + if (nsFormFrame::GetDisabled(this)) { + mWidget->Enable(PR_FALSE); + } + */ + + // finish initializing editor + mEditor->EnableUndo(PR_TRUE); + + // set readonly and disabled states + if (mContent) + { + PRUint32 flags=0; + if (IsPlainTextControl()) { + flags |= TEXT_EDITOR_FLAG_PLAINTEXT; + } + if (IsSingleLineTextControl()) { + flags |= TEXT_EDITOR_FLAG_SINGLELINE; + } + if (IsPasswordTextControl()) { + flags |= TEXT_EDITOR_FLAG_PASSWORD; + } + nsCOMPtr content; + result = mContent->QueryInterface(nsIContent::GetIID(), getter_AddRefs(content)); + if (NS_SUCCEEDED(result) && content) + { + PRInt32 nameSpaceID; + content->GetNameSpaceID(nameSpaceID); + nsAutoString resultValue; + result = content->GetAttribute(nameSpaceID, nsHTMLAtoms::readonly, resultValue); + if (NS_CONTENT_ATTR_NOT_THERE != result) { + flags |= TEXT_EDITOR_FLAG_READONLY; + aPresShell->SetCaretEnabled(PR_FALSE); + } + result = content->GetAttribute(nameSpaceID, nsHTMLAtoms::disabled, resultValue); + if (NS_CONTENT_ATTR_NOT_THERE != result) + { + flags |= TEXT_EDITOR_FLAG_DISABLED; + aPresShell->SetCaretEnabled(PR_FALSE); + nsCOMPtrdoc = do_QueryInterface(aDoc); + if (doc) { + doc->SetDisplaySelection(PR_FALSE); + } + } + } + mEditor->SetFlags(flags); + } + } + else { result = NS_ERROR_NULL_POINTER; } + return result; +} + +NS_IMETHODIMP +nsGfxTextControlFrame::ContentChanged() +{ + if (PR_FALSE==IsInitialized()) { return NS_ERROR_NOT_INITIALIZED; } + nsAutoString value; + // XXX: need to check here if we're an HTML edit field or a text edit field + mEditor->OutputTextToString(value); + if (PR_TRUE==IsSingleLineTextControl()) { + RemoveNewlines(value); + } + SetTextControlFrameState(value); // set new text value + return NS_OK; +} + +void nsGfxTextControlFrame::RemoveNewlines(nsString &aString) +{ + // strip CR/LF + static const char badChars[] = {10, 13, 0}; + aString.StripChars(badChars); +} + + +/******************************************************************************* + * EnderFrameLoadingInfo + ******************************************************************************/ +class EnderFrameLoadingInfo : public nsISupports +{ +public: + EnderFrameLoadingInfo(const nsSize& aSize); + + // nsISupports interface... + NS_DECL_ISUPPORTS + +protected: + virtual ~EnderFrameLoadingInfo() {} + +public: + nsSize mFrameSize; +}; + +EnderFrameLoadingInfo::EnderFrameLoadingInfo(const nsSize& aSize) +{ + NS_INIT_REFCNT(); + + mFrameSize = aSize; +} + +/* + * Implementation of ISupports methods... + */ +NS_IMPL_ISUPPORTS(EnderFrameLoadingInfo,kISupportsIID); + + +/******************************************************************************* + * nsEnderDocumentObserver + ******************************************************************************/ +NS_IMPL_ADDREF(nsEnderDocumentObserver); +NS_IMPL_RELEASE(nsEnderDocumentObserver); + + +nsresult +nsEnderDocumentObserver::QueryInterface(const nsIID& aIID, + void** aInstancePtrResult) +{ + NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); + if (nsnull == aInstancePtrResult) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIDocumentObserverIID)) { + *aInstancePtrResult = (void*) ((nsIStreamObserver*)this); + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtrResult = (void*) ((nsISupports*)((nsIDocumentObserver*)this)); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + + +NS_IMETHODIMP +nsEnderDocumentObserver::SetFrame(nsGfxTextControlFrame *aFrame) +{ + mFrame = aFrame; + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::BeginUpdate(nsIDocument *aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::EndUpdate(nsIDocument *aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::BeginLoad(nsIDocument *aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::EndLoad(nsIDocument *aDocument) +{ + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell) +{ + return NS_OK; +} + +NS_IMETHODIMP nsEnderDocumentObserver::EndReflow(nsIDocument *aDocument, nsIPresShell* aShell) +{ return NS_OK; } + +NS_IMETHODIMP nsEnderDocumentObserver::ContentChanged(nsIDocument *aDocument, + nsIContent* aContent, + nsISupports* aSubContent) +{ + nsresult result = NS_OK; + if (mFrame) { + result = mFrame->ContentChanged(); + } + return result; +} + +NS_IMETHODIMP nsEnderDocumentObserver::ContentStatesChanged(nsIDocument* aDocument, + nsIContent* aContent1, + nsIContent* aContent2) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::AttributeChanged(nsIDocument *aDocument, + nsIContent* aContent, + nsIAtom* aAttribute, + PRInt32 aHint) +{ return NS_OK; } + +NS_IMETHODIMP nsEnderDocumentObserver::ContentAppended(nsIDocument *aDocument, + nsIContent* aContainer, + PRInt32 aNewIndexInContainer) +{ + nsresult result = NS_OK; + if (mFrame) { + result = mFrame->ContentChanged(); + } + return result; +} + +NS_IMETHODIMP nsEnderDocumentObserver::ContentInserted(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + nsresult result = NS_OK; + if (mFrame) { + result = mFrame->ContentChanged(); + } + return result; +} + +NS_IMETHODIMP nsEnderDocumentObserver::ContentReplaced(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aOldChild, + nsIContent* aNewChild, + PRInt32 aIndexInContainer) +{ + nsresult result = NS_OK; + if (mFrame) { + result = mFrame->ContentChanged(); + } + return result; +} + +NS_IMETHODIMP nsEnderDocumentObserver::ContentRemoved(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer) +{ + nsresult result = NS_OK; + if (mFrame) { + result = mFrame->ContentChanged(); + } + return result; +} + +NS_IMETHODIMP nsEnderDocumentObserver::StyleSheetAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::StyleSheetRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::StyleSheetDisabledStateChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + PRBool aDisabled) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::StyleRuleChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule, + PRInt32 aHint) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::StyleRuleAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::StyleRuleRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule) +{ return NS_OK; } +NS_IMETHODIMP nsEnderDocumentObserver::DocumentWillBeDestroyed(nsIDocument *aDocument) +{ return NS_OK; } + + + +/******************************************************************************* + * nsEnderKeyListener + ******************************************************************************/ + +nsresult +NS_NewEnderKeyListener(nsEnderKeyListener ** aInstancePtrResult) +{ + nsEnderKeyListener* it = new nsEnderKeyListener(); + if (nsnull == it) { + return NS_ERROR_OUT_OF_MEMORY; + } + return it->QueryInterface(kIDOMKeyListenerIID, (void **) aInstancePtrResult); +} + +NS_IMPL_ADDREF(nsEnderKeyListener) + +NS_IMPL_RELEASE(nsEnderKeyListener) + +nsresult +nsEnderKeyListener::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (nsnull == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + static NS_DEFINE_IID(kIDOMEventListenerIID, NS_IDOMEVENTLISTENER_IID); + if (aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*)(nsISupports*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(kIDOMEventListenerIID)) { + *aInstancePtr = (void*)(nsIDOMEventListener*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + if (aIID.Equals(kIDOMKeyListenerIID)) { + *aInstancePtr = (void*)(nsIDOMKeyListener*)this; + NS_ADDREF_THIS(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +nsresult +nsEnderKeyListener::HandleEvent(nsIDOMEvent* aEvent) +{ + return NS_OK; +} + +nsresult +nsEnderKeyListener::KeyDown(nsIDOMEvent* aKeyEvent) +{ + PRUint32 keyCode; + + nsCOMPtruiEvent; + uiEvent = do_QueryInterface(aKeyEvent); + if (!uiEvent) { //non-key event passed to keydown. bad things. + return NS_OK; + } + + if (NS_SUCCEEDED(uiEvent->GetKeyCode(&keyCode))) + { + if (nsIDOMUIEvent::VK_RETURN==keyCode) + { + if (mFrame) + { + // need the pres context. could save it from some other function, but that seems so wrong + //mFrame->EnterPressed(presContext); + return nsEventStatus_eConsumeNoDefault; + } + } + } + + return nsEventStatus_eIgnore; +} + +nsresult +nsEnderKeyListener::KeyUp(nsIDOMEvent* aKeyEvent) +{ + return nsEventStatus_eIgnore; +} + +nsresult +nsEnderKeyListener::KeyPress(nsIDOMEvent* aKeyEvent) +{ + return nsEventStatus_eIgnore; +} + + + + + + +/******************************************************************************* + * EnderTempObserver + ******************************************************************************/ +// XXX temp implementation + +NS_IMPL_ADDREF(EnderTempObserver); +NS_IMPL_RELEASE(EnderTempObserver); + +nsresult +EnderTempObserver::QueryInterface(const nsIID& aIID, + void** aInstancePtrResult) +{ + NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); + if (nsnull == aInstancePtrResult) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIStreamObserverIID)) { + *aInstancePtrResult = (void*) ((nsIStreamObserver*)this); + AddRef(); + return NS_OK; + } + if (aIID.Equals(kISupportsIID)) { + *aInstancePtrResult = (void*) ((nsISupports*)((nsIDocumentObserver*)this)); + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + + +NS_IMETHODIMP +EnderTempObserver::OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax) +{ + return NS_OK; +} + +NS_IMETHODIMP +EnderTempObserver::OnStatus(nsIURL* aURL, const PRUnichar* aMsg) +{ + return NS_OK; +} + +NS_IMETHODIMP +EnderTempObserver::OnStartBinding(nsIURL* aURL, const char *aContentType) +{ + return NS_OK; +} + +NS_IMETHODIMP +EnderTempObserver::OnStopBinding(nsIURL* aURL, nsresult status, const PRUnichar* aMsg) +{ + if (PR_TRUE==mFirstCall) + { + mFirstCall = PR_FALSE; + if (mFrame) { + mFrame->InstallEditor(); + } + } + return NS_OK; +} + +NS_IMETHODIMP +EnderTempObserver::SetFrame(nsGfxTextControlFrame *aFrame) +{ + mFrame = aFrame; + return NS_OK; +} \ No newline at end of file diff --git a/mozilla/layout/html/forms/src/nsGfxTextControlFrame.h b/mozilla/layout/html/forms/src/nsGfxTextControlFrame.h new file mode 100644 index 00000000000..c2d68be4d53 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsGfxTextControlFrame.h @@ -0,0 +1,297 @@ +/* -*- 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 nsGfxTextControlFrame_h___ +#define nsGfxTextControlFrame_h___ + +#include "nsFormControlFrame.h" +#include "nsTextControlFrame.h" +#include "nsIStreamObserver.h" +#include "nsITextEditor.h" +#include "nsIDocumentObserver.h" +#include "nsIDOMKeyListener.h" + +class nsIContent; +class nsIFrame; +class nsIPresContext; +class nsIWebShell; + +class nsGfxTextControlFrame; + + +/******************************************************************************* + * EnderTempObserver XXX temporary until doc manager/loader is in place + ******************************************************************************/ +class EnderTempObserver : public nsIStreamObserver +{ +public: + EnderTempObserver() + { + NS_INIT_REFCNT(); + mFirstCall = PR_TRUE; + } + + NS_IMETHOD SetFrame(nsGfxTextControlFrame *aFrame); + + virtual ~EnderTempObserver() {}; + + // nsISupports + NS_DECL_ISUPPORTS + + // nsIStreamObserver + NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType); + NS_IMETHOD OnProgress(nsIURL* aURL, PRUint32 aProgress, PRUint32 aProgressMax); + NS_IMETHOD OnStatus(nsIURL* aURL, const PRUnichar* aMsg); + NS_IMETHOD OnStopBinding(nsIURL* aURL, nsresult status, const PRUnichar* aMsg); + +protected: + + nsString mURL; + nsString mOverURL; + nsString mOverTarget; + nsGfxTextControlFrame *mFrame; // not ref counted + PRBool mFirstCall; +}; + +/******************************************************************************* + * nsEnderDocumentObserver + * This class responds to document changes + ******************************************************************************/ +class nsEnderDocumentObserver : public nsIDocumentObserver +{ +public: + nsEnderDocumentObserver() { NS_INIT_REFCNT(); } + + NS_IMETHOD SetFrame(nsGfxTextControlFrame *aFrame); + + virtual ~nsEnderDocumentObserver() {}; + + // nsISupports + NS_DECL_ISUPPORTS + + NS_IMETHOD BeginUpdate(nsIDocument *aDocument); + NS_IMETHOD EndUpdate(nsIDocument *aDocument); + NS_IMETHOD BeginLoad(nsIDocument *aDocument); + NS_IMETHOD EndLoad(nsIDocument *aDocument); + NS_IMETHOD BeginReflow(nsIDocument *aDocument, nsIPresShell* aShell); + NS_IMETHOD EndReflow(nsIDocument *aDocument, nsIPresShell* aShell); + NS_IMETHOD ContentChanged(nsIDocument *aDocument, + nsIContent* aContent, + nsISupports* aSubContent); + NS_IMETHOD ContentStatesChanged(nsIDocument* aDocument, + nsIContent* aContent1, + nsIContent* aContent2); + NS_IMETHOD AttributeChanged(nsIDocument *aDocument, + nsIContent* aContent, + nsIAtom* aAttribute, + PRInt32 aHint); + NS_IMETHOD ContentAppended(nsIDocument *aDocument, + nsIContent* aContainer, + PRInt32 aNewIndexInContainer); + NS_IMETHOD ContentInserted(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + NS_IMETHOD ContentReplaced(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aOldChild, + nsIContent* aNewChild, + PRInt32 aIndexInContainer); + NS_IMETHOD ContentRemoved(nsIDocument *aDocument, + nsIContent* aContainer, + nsIContent* aChild, + PRInt32 aIndexInContainer); + NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet); + NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet); + NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + PRBool aDisabled); + NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule, + PRInt32 aHint); + NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule); + NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument, + nsIStyleSheet* aStyleSheet, + nsIStyleRule* aStyleRule); + NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument); + + +protected: + + nsGfxTextControlFrame *mFrame; // not ref counted +}; + +/****************************************************************************** + * nsEnderKeyListener + ******************************************************************************/ + +class nsEnderKeyListener; // forward declaration for factory + +/* factory for ender key listener */ +nsresult NS_NewEnderKeyListener(nsEnderKeyListener ** aInstancePtrResult); + +class nsEnderKeyListener : public nsIDOMKeyListener +{ +public: + /** the default destructor */ + virtual ~nsEnderKeyListener() {}; + + /** SetFrame sets the frame we send event messages to, when necessary + * @param aEditor the frame, can be null, not ref counted (guaranteed to outlive us!) + */ + void SetFrame(nsGfxTextControlFrame *aFrame) {mFrame = aFrame;} + + /*interfaces for addref and release and queryinterface*/ + NS_DECL_ISUPPORTS + + /* nsIDOMKeyListener interfaces */ + virtual nsresult HandleEvent(nsIDOMEvent* aEvent); + virtual nsresult KeyDown(nsIDOMEvent* aKeyEvent); + virtual nsresult KeyUp(nsIDOMEvent* aKeyEvent); + virtual nsresult KeyPress(nsIDOMEvent* aKeyEvent); + /*END interfaces from nsIDOMKeyListener*/ + + friend nsresult NS_NewEnderKeyListener(nsEnderKeyListener ** aInstancePtrResult); + +protected: + /** the default constructor. Protected, use the factory to create an instance. + * @see NS_NewEnderKeyListener + */ + nsEnderKeyListener() {NS_INIT_REFCNT();}; + +protected: + nsGfxTextControlFrame *mFrame; // not ref counted +}; + + +/****************************************************************************** + * nsGfxTextControlFrame + ******************************************************************************/ + +// XXX code related to the dummy native text control frame is marked with DUMMY +// and should be removed asap + +#include "nsNativeTextControlFrame.h" // DUMMY + +class nsGfxTextControlFrame : public nsTextControlFrame +{ +public: + nsGfxTextControlFrame(); + virtual ~nsGfxTextControlFrame(); + NS_IMETHOD InitTextControl(); + + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint); + + virtual void PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight); + + NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue); + + virtual void EnterPressed(nsIPresContext& aPresContext) ; + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(); + + // override to interact with webshell + NS_IMETHOD Reflow(nsIPresContext& aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus); + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + virtual void PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + virtual void PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsString& aText, + nsIStyleContext* aStyleContext, + nsRect& aRect); + + // Utility methods to get and set current widget state + void GetTextControlFrameState(nsString& aValue); + void SetTextControlFrameState(const nsString& aValue); + + NS_IMETHOD InstallEditor(); + + virtual nsresult RequiresWidget(PRBool &aRequiresWidget); + + NS_IMETHOD ContentChanged(); + + void RemoveNewlines(nsString &aString); + +protected: + + + NS_IMETHOD CreateWebShell(nsIPresContext& aPresContext, + const nsSize& aSize); + + NS_IMETHOD InitializeTextControl(nsIPresShell *aPresShell, nsIDOMDocument *aDoc); + + NS_IMETHOD GetPresShellFor(nsIWebShell* aWebShell, nsIPresShell** aPresShell); + + NS_IMETHOD GetFirstNodeOfType(const nsString& aTag, nsIDOMDocument *aDOMDoc, nsIDOMNode **aBodyNode); + + NS_IMETHOD GetFirstFrameForType(const nsString& aTag, nsIPresShell *aPresShell, nsIDOMDocument *aDOMDoc, nsIFrame **aResult); + + NS_IMETHOD SelectAllTextContent(nsIDOMNode *aBodyNode, nsIDOMSelection *aSelection); + + PRBool IsSingleLineTextControl() const; + + PRBool IsPlainTextControl() const; + + PRBool IsPasswordTextControl() const; + + PRBool IsInitialized() const; + + +protected: + nsIWebShell* mWebShell; + PRBool mCreatingViewer; + EnderTempObserver* mTempObserver; + nsEnderDocumentObserver *mDocObserver; + nsCOMPtr mKeyListener; + nsCOMPtrmEditor; + nsNativeTextControlFrame *mDummyFrame; //DUMMY + PRBool mNeedsStyleInit; + PRBool mDummyInitialized; //DUMMY +}; + +#endif diff --git a/mozilla/layout/html/forms/src/nsNativeTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsNativeTextControlFrame.cpp new file mode 100644 index 00000000000..4f3d21c1fc1 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsNativeTextControlFrame.cpp @@ -0,0 +1,652 @@ +/* -*- 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 "nsCOMPtr.h" +#include "nsNativeTextControlFrame.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" + +#include "nsCSSRendering.h" +#include "nsIDeviceContext.h" +#include "nsIFontMetrics.h" +#include "nsILookAndFeel.h" +#include "nsIComponentManager.h" + +#ifdef SingleSignon +#include "nsIDocument.h" +#include "prmem.h" +#include "nsIURL.h" +#include "nsIWalletService.h" +#include "nsIServiceManager.h" +static NS_DEFINE_IID(kIWalletServiceIID, NS_IWALLETSERVICE_IID); +static NS_DEFINE_IID(kWalletServiceCID, NS_WALLETSERVICE_CID); +#endif + +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); +static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); +static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); + +nsresult +NS_NewNativeTextControlFrame(nsIFrame** aNewFrame) +{ + NS_PRECONDITION(aNewFrame, "null OUT ptr"); + if (nsnull == aNewFrame) { + return NS_ERROR_NULL_POINTER; + } + nsNativeTextControlFrame* it = new nsNativeTextControlFrame; + if (!it) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aNewFrame = it; + return NS_OK; +} + +void +nsNativeTextControlFrame::EnterPressed(nsIPresContext& aPresContext) +{ + if (mFormFrame && mFormFrame->CanSubmit(*this)) { + nsIContent *formContent = nsnull; + + mFormFrame->GetContent(&formContent); + if (nsnull != formContent) { + nsEvent event; + nsEventStatus status = nsEventStatus_eIgnore; + + event.eventStructType = NS_EVENT; + event.message = NS_FORM_SUBMIT; + formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); + NS_RELEASE(formContent); + } + + mFormFrame->OnSubmit(&aPresContext, this); + } +} + +nsWidgetInitData* +nsNativeTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) +{ + PRInt32 type; + GetType(&type); + + nsTextWidgetInitData* data = nsnull; + + PRBool readOnly = nsFormFrame::GetReadonly(this); + + if ((NS_FORM_INPUT_PASSWORD == type) || readOnly) { + data = new nsTextWidgetInitData(); + data->mIsPassword = PR_FALSE; + data->mIsReadOnly = PR_FALSE; + if (NS_FORM_INPUT_PASSWORD == type) { + data->clipChildren = PR_TRUE; + data->mIsPassword = PR_TRUE; + } + if (readOnly) { + data->mIsReadOnly = PR_TRUE; + } + } + + return data; +} + +NS_IMETHODIMP +nsNativeTextControlFrame::GetText(nsString* aText, PRBool aInitialValue) +{ + nsresult result = NS_CONTENT_ATTR_NOT_THERE; + PRInt32 type; + GetType(&type); + if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { + result = nsFormControlHelper::GetInputElementValue(mContent, aText, aInitialValue); + } else { + nsIDOMHTMLTextAreaElement* textArea = nsnull; + result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); + if ((NS_OK == result) && textArea) { + if (PR_TRUE == aInitialValue) { + result = textArea->GetDefaultValue(*aText); + } + else { + result = textArea->GetValue(*aText); + } + NS_RELEASE(textArea); + } + } + return result; +} + +NS_IMETHODIMP +nsNativeTextControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + nsresult result = NS_OK; + if (mWidget) { + nsITextWidget* text = nsnull; + result = mWidget->QueryInterface(kITextWidgetIID, (void**)&text); + if ((NS_OK == result) && (nsnull != text)) { + if (nsHTMLAtoms::value == aAttribute) { + nsString value; + /*XXXnsresult rv = */GetText(&value, PR_TRUE); + PRUint32 ignore; + text->SetText(value, ignore); + nsFormFrame::StyleChangeReflow(aPresContext, this); + } else if (nsHTMLAtoms::maxlength == aAttribute) { + PRInt32 maxLength; + nsresult rv = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != rv) { + text->SetMaxTextLength(maxLength); + } + } else if (nsHTMLAtoms::readonly == aAttribute) { + PRBool oldReadOnly; + text->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); + } + else if (nsHTMLAtoms::size == aAttribute) { + nsFormFrame::StyleChangeReflow(aPresContext, this); + } + // Allow the base class to handle common attributes supported + // by all form elements... + else { + result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); + } + NS_RELEASE(text); + } + // XXX Ick, create an common interface that has the functionality of nsTextHelper + else { // We didn't get a Text, is it a TextArea? + nsITextAreaWidget* textArea = nsnull; + result = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textArea); + if ((NS_OK == result) && (nsnull != textArea)) { + if (nsHTMLAtoms::value == aAttribute) { + nsString value; + /*XXXnsresult rv = */GetText(&value, PR_TRUE); + PRUint32 ignore; + textArea->SetText(value, ignore); + nsFormFrame::StyleChangeReflow(aPresContext, this); + } else if (nsHTMLAtoms::maxlength == aAttribute) { + PRInt32 maxLength; + nsresult rv = GetMaxLength(&maxLength); + if (NS_CONTENT_ATTR_NOT_THERE != rv) { + textArea->SetMaxTextLength(maxLength); + } + } else if (nsHTMLAtoms::readonly == aAttribute) { + PRBool oldReadOnly; + textArea->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); + } + else if (nsHTMLAtoms::size == aAttribute) { + nsFormFrame::StyleChangeReflow(aPresContext, this); + } + // Allow the base class to handle common attributes supported + // by all form elements... + else { + result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); + } + NS_RELEASE(textArea); + } + else { // We didn't get a Text or TextArea. Uh oh... + result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); + } + } + } + + return result; +} + +void +nsNativeTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight) +{ + if (!mWidget) { + return; + } + + PRInt32 type; + GetType(&type); + + nsFont font(aPresContext->GetDefaultFixedFontDeprecated()); + GetFont(aPresContext, font); + mWidget->SetFont(font); + SetColors(*aPresContext); + + PRUint32 ignore; + nsAutoString value; + + nsITextAreaWidget* textArea = nsnull; + nsITextWidget* text = nsnull; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + +#ifdef SingleSignon + /* get name of text */ + PRBool failed = PR_TRUE; + nsAutoString name; + GetName(&name); + + /* get url name */ + char *URLName = nsnull; + nsIURL* docURL = nsnull; + nsIDocument* doc = nsnull; + mContent->GetDocument(doc); + if (nsnull != doc) { + docURL = doc->GetDocumentURL(); + NS_RELEASE(doc); + if (nsnull != docURL) { + const char* spec; + (void)docURL->GetSpec(&spec); + if (nsnull != spec) { + URLName = (char*)PR_Malloc(PL_strlen(spec)+1); + PL_strcpy(URLName, spec); + } + NS_RELEASE(docURL); + } + } + + if (nsnull != URLName) { + /* invoke single-signon to get previously-used value of text */ + nsIWalletService *service; + nsresult res = nsServiceManager::GetService(kWalletServiceCID, + kIWalletServiceIID, + (nsISupports **)&service); + if ((NS_OK == res) && (nsnull != service)) { + char* valueString = NULL; + char* nameString = name.ToNewCString(); + res = service->SI_RestoreSignonData(URLName, nameString, &valueString); + delete[] nameString; + NS_RELEASE(service); + PR_FREEIF(URLName); + if (valueString && *valueString) { + value = valueString; + failed = PR_FALSE; + } + } + } + if (failed) { + GetText(&value, PR_TRUE); + } +#else + GetText(&value, PR_TRUE); +#endif + + 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)) { + GetText(&value, PR_TRUE); + textArea->SetText(value, ignore); + NS_RELEASE(textArea); + } + if (nsFormFrame::GetDisabled(this)) { + mWidget->Enable(PR_FALSE); + } +} + +PRBool +nsNativeTextControlFrame::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 +nsNativeTextControlFrame::Reset() +{ + if (!mWidget) { + return; + } + + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + + nsAutoString value; + nsresult valStatus = GetText(&value, PR_TRUE); + + 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); + } + +} + +void +nsNativeTextControlFrame::PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) { + nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); +} + +void +nsNativeTextControlFrame::PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsString& aText, + nsIStyleContext* aStyleContext, nsRect& aRect) +{ + aRenderingContext.PushState(); + + const nsStyleSpacing* spacing = + (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); + nsMargin border; + spacing->CalcBorderFor(this, border); + + float p2t; + aPresContext.GetScaledPixelsToTwips(&p2t); + nscoord onePixel = NSIntPixelsToTwips(1, p2t); + + nsRect outside(aRect.x, aRect.y, aRect.width, aRect.height); + outside.Deflate(border); + outside.Deflate(onePixel, onePixel); + + nsRect inside(outside); + inside.Deflate(onePixel, onePixel); + +#if 0 + if (mGotFocus) { + PaintFocus(aRenderingContext, + aDirtyRect, inside, outside); + } +#endif + + float appUnits; + float devUnits; + float scale; + nsIDeviceContext * context; + aRenderingContext.GetDeviceContext(context); + + context->GetCanonicalPixelScale(scale); + context->GetAppUnitsToDevUnits(devUnits); + context->GetDevUnitsToAppUnits(appUnits); + + aRenderingContext.SetColor(NS_RGB(0,0,0)); + + nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); + GetFont(&aPresContext, font); + + aRenderingContext.SetFont(font); + + nscoord textWidth; + nscoord textHeight; + + aRenderingContext.GetWidth(aText, textWidth); + + nsIFontMetrics* metrics; + context->GetMetricsFor(font, metrics); + metrics->GetHeight(textHeight); + + PRInt32 type; + GetType(&type); + if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type) { + nscoord x = inside.x + onePixel + onePixel; + nscoord y; + + if (NS_FORM_INPUT_TEXT == type) { + y = ((inside.height - textHeight) / 2) + inside.y; + } else { + metrics->GetMaxAscent(textHeight); + y = ((inside.height - textHeight) / 2) + inside.y; + PRInt32 i; + PRInt32 len = aText.Length(); + aText.SetLength(0); + for (i=0;iGetCanonicalPixelScale(scale); + context->GetScrollBarDimensions(sbWidth, sbHeight); + PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); + PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale); + + inside.width -= scrollbarScaledWidth; + inside.height -= scrollbarScaledHeight; + PRBool clipEmpty; + aRenderingContext.PushState(); + aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty); + + nscoord x = inside.x + onePixel; + nscoord y = inside.y + onePixel; + + // Draw multi-line text + PRInt32 oldPos = 0; + PRInt32 pos = aText.Find('\n', 0); + while (1) { + nsString substr; + if (-1 == pos) { + // Single line, no carriage return. + aText.Right(substr, aText.Length()-oldPos); + aRenderingContext.DrawString(substr, x, y); + break; + } + // Strip off substr up to carriage return + aText.Mid(substr, oldPos, ((pos - oldPos) - 1)); + + aRenderingContext.DrawString(substr, x, y); + y += textHeight; + // Advance to the next carriage return + pos++; + oldPos = pos; + pos = aText.Find('\n', pos); + } + + aRenderingContext.PopState(clipEmpty); + + // Scrollbars + nsIAtom * sbAtom = NS_NewAtom(":scrollbar-look"); + nsIStyleContext* scrollbarStyle; + aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &scrollbarStyle); + NS_RELEASE(sbAtom); + + sbAtom = NS_NewAtom(":scrollbar-arrow-look"); + nsIStyleContext* arrowStyle; + aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &arrowStyle); + NS_RELEASE(sbAtom); + + nsRect srect(aRect.width-scrollbarScaledWidth-(2*onePixel), 2*onePixel, scrollbarScaledWidth, aRect.height-(onePixel*4)-scrollbarScaledWidth); + + nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_FALSE, onePixel, + scrollbarStyle, arrowStyle, this, aRect); + // Horizontal + srect.SetRect(2*onePixel, aRect.height-scrollbarScaledHeight-(2*onePixel), aRect.width-(onePixel*4)-scrollbarScaledHeight, scrollbarScaledHeight); + nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_TRUE, onePixel, + scrollbarStyle, arrowStyle, this, aRect); + + // Draw the small rect "gap" in the bottom right that the two scrollbars don't cover + const nsStyleColor* sbColor = (const nsStyleColor*)scrollbarStyle->GetStyleData(eStyleStruct_Color); + srect.SetRect(aRect.width-scrollbarScaledWidth-(2*onePixel), aRect.height-scrollbarScaledHeight-(onePixel*2), scrollbarScaledWidth, scrollbarScaledHeight); + nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, + aDirtyRect, srect, *sbColor, *spacing, 0, 0); + } + + + NS_RELEASE(context); + + PRBool status; + aRenderingContext.PopState(status); +} + +NS_METHOD +nsNativeTextControlFrame::Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer) +{ + PaintTextControlBackground(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); + if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { + nsString text; + GetText(&text, PR_FALSE); + nsRect rect(0, 0, mRect.width, mRect.height); + PaintTextControl(aPresContext, aRenderingContext, aDirtyRect, text, mStyleContext, rect); + } + return NS_OK; +} + +void nsNativeTextControlFrame::GetTextControlFrameState(nsString& aValue) +{ + if (nsnull != mWidget) { + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + PRUint32 size = 0; + if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { + text->GetText(aValue,0,size); + NS_RELEASE(text); + } + else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, + (void**)&textArea)) { + textArea->GetText(aValue,0, size); + NS_RELEASE(textArea); + } + } + else { + //XXX: this should return the a local field for GFX-rendered widgets aValue = ""; + } +} + +void nsNativeTextControlFrame::SetTextControlFrameState(const nsString& aValue) +{ + if (nsnull != mWidget) { + nsITextWidget* text = nsnull; + nsITextAreaWidget* textArea = nsnull; + PRUint32 size = 0; + if (NS_SUCCEEDED(mWidget->QueryInterface(kITextWidgetIID,(void**)&text))) { + text->SetText(aValue,size); + NS_RELEASE(text); + } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, + (void**)&textArea)) { + textArea->SetText(aValue,size); + NS_RELEASE(textArea); + } + } +} + +NS_IMETHODIMP nsNativeTextControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) +{ + nsresult rv = NS_OK; + if (nsHTMLAtoms::value == aName) { + SetTextControlFrameState(aValue); + } else if (nsHTMLAtoms::select == aName) { + if (nsnull != mWidget) { + nsITextWidget *textWidget; + rv = mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget); + if (NS_SUCCEEDED(rv)) { + textWidget->SelectAll(); + NS_RELEASE(textWidget); + } + + nsITextAreaWidget *textAreaWidget; + rv = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textAreaWidget); + if (NS_SUCCEEDED(rv)) { + textAreaWidget->SelectAll(); + NS_RELEASE(textAreaWidget); + } + } + } + else { + return nsFormControlFrame::SetProperty(aName, aValue); + } + return rv; +} + +NS_IMETHODIMP nsNativeTextControlFrame::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); + } + else { + return nsFormControlFrame::GetProperty(aName, aValue); + } + + return NS_OK; +} + +nsresult nsNativeTextControlFrame::RequiresWidget(PRBool &aRequiresWidget) +{ + aRequiresWidget = PR_TRUE; + return NS_OK; +} + diff --git a/mozilla/layout/html/forms/src/nsNativeTextControlFrame.h b/mozilla/layout/html/forms/src/nsNativeTextControlFrame.h new file mode 100644 index 00000000000..86d6c43e066 --- /dev/null +++ b/mozilla/layout/html/forms/src/nsNativeTextControlFrame.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 nsNativeTextControlFrame_h___ +#define nsNativeTextControlFrame_h___ + +#include "nsTextControlFrame.h" +class nsIContent; +class nsIFrame; +class nsIPresContext; + +class nsNativeTextControlFrame : public nsTextControlFrame +{ +public: + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint); + + virtual void PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight); + + NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue); + + virtual void EnterPressed(nsIPresContext& aPresContext) ; + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames); + virtual void Reset(); + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + virtual void PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer); + + virtual void PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsString& aText, + nsIStyleContext* aStyleContext, + nsRect& aRect); + + // Utility methods to get and set current widget state + void GetTextControlFrameState(nsString& aValue); + void SetTextControlFrameState(const nsString& aValue); + + virtual nsresult RequiresWidget(PRBool &aRequiresWidget); + +}; + +#endif diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp index f61f26a621c..34d3edec0c0 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.cpp @@ -66,21 +66,6 @@ static NS_DEFINE_IID(kIDOMHTMLInputElementIID, NS_IDOMHTMLINPUTELEMENT_IID); static NS_DEFINE_IID(kLookAndFeelCID, NS_LOOKANDFEEL_CID); static NS_DEFINE_IID(kILookAndFeelIID, NS_ILOOKANDFEEL_IID); -nsresult -NS_NewTextControlFrame(nsIFrame** aNewFrame) -{ - NS_PRECONDITION(aNewFrame, "null OUT ptr"); - if (nsnull == aNewFrame) { - return NS_ERROR_NULL_POINTER; - } - nsTextControlFrame* it = new nsTextControlFrame; - if (!it) { - return NS_ERROR_OUT_OF_MEMORY; - } - *aNewFrame = it; - return NS_OK; -} - nscoord nsTextControlFrame::GetVerticalBorderWidth(float aPixToTwip) const { @@ -209,26 +194,6 @@ nsTextControlFrame::GetCID() } } -void -nsTextControlFrame::EnterPressed(nsIPresContext& aPresContext) -{ - if (mFormFrame && mFormFrame->CanSubmit(*this)) { - nsIContent *formContent = nsnull; - - mFormFrame->GetContent(&formContent); - if (nsnull != formContent) { - nsEvent event; - nsEventStatus status = nsEventStatus_eIgnore; - - event.eventStructType = NS_EVENT; - event.message = NS_FORM_SUBMIT; - formContent->HandleDOMEvent(aPresContext, &event, nsnull, NS_EVENT_FLAG_INIT, status); - NS_RELEASE(formContent); - } - - mFormFrame->OnSubmit(&aPresContext, this); - } -} #define DEFAULT_PIXEL_WIDTH 20 void @@ -315,311 +280,12 @@ nsTextControlFrame::GetDesiredSize(nsIPresContext* aPresContext, } -nsWidgetInitData* -nsTextControlFrame::GetWidgetInitData(nsIPresContext& aPresContext) -{ - PRInt32 type; - GetType(&type); - - nsTextWidgetInitData* data = nsnull; - - PRBool readOnly = nsFormFrame::GetReadonly(this); - - if ((NS_FORM_INPUT_PASSWORD == type) || readOnly) { - data = new nsTextWidgetInitData(); - data->mIsPassword = PR_FALSE; - data->mIsReadOnly = PR_FALSE; - if (NS_FORM_INPUT_PASSWORD == type) { - data->clipChildren = PR_TRUE; - data->mIsPassword = PR_TRUE; - } - if (readOnly) { - data->mIsReadOnly = PR_TRUE; - } - } - - return data; -} - -NS_IMETHODIMP -nsTextControlFrame::GetText(nsString* aText, PRBool aInitialValue) -{ - nsresult result = NS_CONTENT_ATTR_NOT_THERE; - PRInt32 type; - GetType(&type); - if ((NS_FORM_INPUT_TEXT == type) || (NS_FORM_INPUT_PASSWORD == type)) { - result = nsFormControlHelper::GetInputElementValue(mContent, aText, aInitialValue); -/* XXX REMOVE - nsIDOMHTMLInputElement* textElem = nsnull; - result = mContent->QueryInterface(kIDOMHTMLInputElementIID, (void**)&textElem); - if ((NS_OK == result) && textElem) { - if (PR_TRUE == aInitialValue) { - result = textElem->GetDefaultValue(*aText); - } - else { - result = textElem->GetValue(*aText); - } - - NS_RELEASE(textElem); - } -*/ - - } else { - nsIDOMHTMLTextAreaElement* textArea = nsnull; - result = mContent->QueryInterface(kIDOMHTMLTextAreaElementIID, (void**)&textArea); - if ((NS_OK == result) && textArea) { - if (PR_TRUE == aInitialValue) { - result = textArea->GetDefaultValue(*aText); - } - else { - result = textArea->GetValue(*aText); - } - NS_RELEASE(textArea); - } - } - return result; -} - -NS_IMETHODIMP -nsTextControlFrame::AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint) -{ - nsresult result = NS_OK; - if (mWidget) { - nsITextWidget* text = nsnull; - result = mWidget->QueryInterface(kITextWidgetIID, (void**)&text); - if ((NS_OK == result) && (nsnull != text)) { - if (nsHTMLAtoms::value == aAttribute) { - nsString value; - /*XXXnsresult rv = */GetText(&value, PR_TRUE); - PRUint32 ignore; - text->SetText(value, ignore); - nsFormFrame::StyleChangeReflow(aPresContext, this); - } else if (nsHTMLAtoms::maxlength == aAttribute) { - PRInt32 maxLength; - nsresult rv = GetMaxLength(&maxLength); - if (NS_CONTENT_ATTR_NOT_THERE != rv) { - text->SetMaxTextLength(maxLength); - } - } else if (nsHTMLAtoms::readonly == aAttribute) { - PRBool oldReadOnly; - text->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); - } - else if (nsHTMLAtoms::size == aAttribute) { - nsFormFrame::StyleChangeReflow(aPresContext, this); - } - // Allow the base class to handle common attributes supported - // by all form elements... - else { - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - NS_RELEASE(text); - } - // XXX Ick, create an common interface that has the functionality of nsTextHelper - else { // We didn't get a Text, is it a TextArea? - nsITextAreaWidget* textArea = nsnull; - result = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textArea); - if ((NS_OK == result) && (nsnull != textArea)) { - if (nsHTMLAtoms::value == aAttribute) { - nsString value; - /*XXXnsresult rv = */GetText(&value, PR_TRUE); - PRUint32 ignore; - textArea->SetText(value, ignore); - nsFormFrame::StyleChangeReflow(aPresContext, this); - } else if (nsHTMLAtoms::maxlength == aAttribute) { - PRInt32 maxLength; - nsresult rv = GetMaxLength(&maxLength); - if (NS_CONTENT_ATTR_NOT_THERE != rv) { - textArea->SetMaxTextLength(maxLength); - } - } else if (nsHTMLAtoms::readonly == aAttribute) { - PRBool oldReadOnly; - textArea->SetReadOnly(nsFormFrame::GetReadonly(this),oldReadOnly); - } - else if (nsHTMLAtoms::size == aAttribute) { - nsFormFrame::StyleChangeReflow(aPresContext, this); - } - // Allow the base class to handle common attributes supported - // by all form elements... - else { - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - NS_RELEASE(textArea); - } - else { // We didn't get a Text or TextArea. Uh oh... - result = nsFormControlFrame::AttributeChanged(aPresContext, aChild, aAttribute, aHint); - } - } - } - - return result; -} - -void -nsTextControlFrame::PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight) -{ - if (!mWidget) { - return; - } - - PRInt32 type; - GetType(&type); - - nsFont font(aPresContext->GetDefaultFixedFontDeprecated()); - GetFont(aPresContext, font); - mWidget->SetFont(font); - SetColors(*aPresContext); - - PRUint32 ignore; - nsAutoString value; - - nsITextAreaWidget* textArea = nsnull; - nsITextWidget* text = nsnull; - if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { - -#ifdef SingleSignon - /* get name of text */ - PRBool failed = PR_TRUE; - nsAutoString name; - GetName(&name); - - /* get url name */ - char *URLName = nsnull; - nsIURL* docURL = nsnull; - nsIDocument* doc = nsnull; - mContent->GetDocument(doc); - if (nsnull != doc) { - docURL = doc->GetDocumentURL(); - NS_RELEASE(doc); - if (nsnull != docURL) { - const char* spec; - (void)docURL->GetSpec(&spec); - if (nsnull != spec) { - URLName = (char*)PR_Malloc(PL_strlen(spec)+1); - PL_strcpy(URLName, spec); - } - NS_RELEASE(docURL); - } - } - - if (nsnull != URLName) { - /* invoke single-signon to get previously-used value of text */ - nsIWalletService *service; - nsresult res = nsServiceManager::GetService(kWalletServiceCID, - kIWalletServiceIID, - (nsISupports **)&service); - if ((NS_OK == res) && (nsnull != service)) { - char* valueString = NULL; - char* nameString = name.ToNewCString(); - res = service->SI_RestoreSignonData(URLName, nameString, &valueString); - delete[] nameString; - NS_RELEASE(service); - PR_FREEIF(URLName); - if (valueString && *valueString) { - value = valueString; - failed = PR_FALSE; - } - } - } - if (failed) { - GetText(&value, PR_TRUE); - } -#else - GetText(&value, PR_TRUE); -#endif - - 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)) { - GetText(&value, PR_TRUE); - textArea->SetText(value, ignore); - NS_RELEASE(textArea); - } - if (nsFormFrame::GetDisabled(this)) { - mWidget->Enable(PR_FALSE); - } -} 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, PR_TRUE); - - 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); - } - -} NS_IMETHODIMP nsTextControlFrame::GetCursor(nsIPresContext& aPresContext, nsPoint& aPoint, PRInt32& aCursor) @@ -639,261 +305,3 @@ nsTextControlFrame::GetFrameName(nsString& aResult) const { return MakeFrameName("TextControl", aResult); } - - -void -nsTextControlFrame::PaintTextControlBackground(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) { - nsFormControlFrame::Paint(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); -} - -void -nsTextControlFrame::PaintTextControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsString& aText, - nsIStyleContext* aStyleContext, nsRect& aRect) -{ - aRenderingContext.PushState(); - - const nsStyleSpacing* spacing = - (const nsStyleSpacing*)aStyleContext->GetStyleData(eStyleStruct_Spacing); - nsMargin border; - spacing->CalcBorderFor(this, border); - - float p2t; - aPresContext.GetScaledPixelsToTwips(&p2t); - nscoord onePixel = NSIntPixelsToTwips(1, p2t); - - nsRect outside(aRect.x, aRect.y, aRect.width, aRect.height); - outside.Deflate(border); - outside.Deflate(onePixel, onePixel); - - nsRect inside(outside); - inside.Deflate(onePixel, onePixel); - -#if 0 - if (mGotFocus) { - PaintFocus(aRenderingContext, - aDirtyRect, inside, outside); - } -#endif - - float appUnits; - float devUnits; - float scale; - nsIDeviceContext * context; - aRenderingContext.GetDeviceContext(context); - - context->GetCanonicalPixelScale(scale); - context->GetAppUnitsToDevUnits(devUnits); - context->GetDevUnitsToAppUnits(appUnits); - - aRenderingContext.SetColor(NS_RGB(0,0,0)); - - nsFont font(aPresContext.GetDefaultFixedFontDeprecated()); - GetFont(&aPresContext, font); - - aRenderingContext.SetFont(font); - - nscoord textWidth; - nscoord textHeight; - - aRenderingContext.GetWidth(aText, textWidth); - - nsIFontMetrics* metrics; - context->GetMetricsFor(font, metrics); - metrics->GetHeight(textHeight); - - PRInt32 type; - GetType(&type); - if (NS_FORM_INPUT_TEXT == type || NS_FORM_INPUT_PASSWORD == type) { - nscoord x = inside.x + onePixel + onePixel; - nscoord y; - - if (NS_FORM_INPUT_TEXT == type) { - y = ((inside.height - textHeight) / 2) + inside.y; - } else { - metrics->GetMaxAscent(textHeight); - y = ((inside.height - textHeight) / 2) + inside.y; - PRInt32 i; - PRInt32 len = aText.Length(); - aText.SetLength(0); - for (i=0;iGetCanonicalPixelScale(scale); - context->GetScrollBarDimensions(sbWidth, sbHeight); - PRInt32 scrollbarScaledWidth = PRInt32(sbWidth * scale); - PRInt32 scrollbarScaledHeight = PRInt32(sbWidth * scale); - - inside.width -= scrollbarScaledWidth; - inside.height -= scrollbarScaledHeight; - PRBool clipEmpty; - aRenderingContext.PushState(); - aRenderingContext.SetClipRect(inside, nsClipCombine_kReplace, clipEmpty); - - nscoord x = inside.x + onePixel; - nscoord y = inside.y + onePixel; - - // Draw multi-line text - PRInt32 oldPos = 0; - PRInt32 pos = aText.Find('\n', 0); - while (1) { - nsString substr; - if (-1 == pos) { - // Single line, no carriage return. - aText.Right(substr, aText.Length()-oldPos); - aRenderingContext.DrawString(substr, x, y); - break; - } - // Strip off substr up to carriage return - aText.Mid(substr, oldPos, ((pos - oldPos) - 1)); - - aRenderingContext.DrawString(substr, x, y); - y += textHeight; - // Advance to the next carriage return - pos++; - oldPos = pos; - pos = aText.Find('\n', pos); - } - - aRenderingContext.PopState(clipEmpty); - - // Scrollbars - nsIAtom * sbAtom = NS_NewAtom(":scrollbar-look"); - nsIStyleContext* scrollbarStyle; - aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &scrollbarStyle); - NS_RELEASE(sbAtom); - - sbAtom = NS_NewAtom(":scrollbar-arrow-look"); - nsIStyleContext* arrowStyle; - aPresContext.ResolvePseudoStyleContextFor(mContent, sbAtom, aStyleContext, PR_FALSE, &arrowStyle); - NS_RELEASE(sbAtom); - - nsRect srect(aRect.width-scrollbarScaledWidth-(2*onePixel), 2*onePixel, scrollbarScaledWidth, aRect.height-(onePixel*4)-scrollbarScaledWidth); - - nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_FALSE, onePixel, - scrollbarStyle, arrowStyle, this, aRect); - // Horizontal - srect.SetRect(2*onePixel, aRect.height-scrollbarScaledHeight-(2*onePixel), aRect.width-(onePixel*4)-scrollbarScaledHeight, scrollbarScaledHeight); - nsFormControlHelper::PaintScrollbar(aRenderingContext,aPresContext, aDirtyRect, srect, PR_TRUE, onePixel, - scrollbarStyle, arrowStyle, this, aRect); - - // Draw the small rect "gap" in the bottom right that the two scrollbars don't cover - const nsStyleColor* sbColor = (const nsStyleColor*)scrollbarStyle->GetStyleData(eStyleStruct_Color); - srect.SetRect(aRect.width-scrollbarScaledWidth-(2*onePixel), aRect.height-scrollbarScaledHeight-(onePixel*2), scrollbarScaledWidth, scrollbarScaledHeight); - nsCSSRendering::PaintBackground(aPresContext, aRenderingContext, this, - aDirtyRect, srect, *sbColor, *spacing, 0, 0); - } - - - NS_RELEASE(context); - - PRBool status; - aRenderingContext.PopState(status); -} - -NS_METHOD -nsTextControlFrame::Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer) -{ - PaintTextControlBackground(aPresContext, aRenderingContext, aDirtyRect, aWhichLayer); - if (NS_FRAME_PAINT_LAYER_FOREGROUND == aWhichLayer) { - nsString text; - GetText(&text, PR_FALSE); - nsRect rect(0, 0, mRect.width, mRect.height); - PaintTextControl(aPresContext, aRenderingContext, aDirtyRect, text, mStyleContext, rect); - } - return NS_OK; -} - -void nsTextControlFrame::GetTextControlFrameState(nsString& aValue) -{ - if (nsnull != mWidget) { - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - PRUint32 size = 0; - if (NS_OK == mWidget->QueryInterface(kITextWidgetIID,(void**)&text)) { - text->GetText(aValue,0,size); - NS_RELEASE(text); - } - else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, - (void**)&textArea)) { - textArea->GetText(aValue,0, size); - NS_RELEASE(textArea); - } - } - else { - //XXX: this should return the a local field for GFX-rendered widgets aValue = ""; - } -} - -void nsTextControlFrame::SetTextControlFrameState(const nsString& aValue) -{ - if (nsnull != mWidget) { - nsITextWidget* text = nsnull; - nsITextAreaWidget* textArea = nsnull; - PRUint32 size = 0; - if (NS_SUCCEEDED(mWidget->QueryInterface(kITextWidgetIID,(void**)&text))) { - text->SetText(aValue,size); - NS_RELEASE(text); - } else if (NS_OK == mWidget->QueryInterface(kITextAreaWidgetIID, - (void**)&textArea)) { - textArea->SetText(aValue,size); - NS_RELEASE(textArea); - } - } -} - -NS_IMETHODIMP nsTextControlFrame::SetProperty(nsIAtom* aName, const nsString& aValue) -{ - nsresult rv = NS_OK; - if (nsHTMLAtoms::value == aName) { - SetTextControlFrameState(aValue); - } else if (nsHTMLAtoms::select == aName) { - if (nsnull != mWidget) { - nsITextWidget *textWidget; - rv = mWidget->QueryInterface(kITextWidgetIID, (void**)&textWidget); - if (NS_SUCCEEDED(rv)) { - textWidget->SelectAll(); - NS_RELEASE(textWidget); - } - - nsITextAreaWidget *textAreaWidget; - rv = mWidget->QueryInterface(kITextAreaWidgetIID, (void**)&textAreaWidget); - if (NS_SUCCEEDED(rv)) { - textAreaWidget->SelectAll(); - NS_RELEASE(textAreaWidget); - } - } - } - else { - return nsFormControlFrame::SetProperty(aName, aValue); - } - return rv; -} - -NS_IMETHODIMP nsTextControlFrame::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); - } - else { - return nsFormControlFrame::GetProperty(aName, aValue); - } - - return NS_OK; -} diff --git a/mozilla/layout/html/forms/src/nsTextControlFrame.h b/mozilla/layout/html/forms/src/nsTextControlFrame.h index 2555735dc38..989f6d70815 100644 --- a/mozilla/layout/html/forms/src/nsTextControlFrame.h +++ b/mozilla/layout/html/forms/src/nsTextControlFrame.h @@ -24,33 +24,15 @@ class nsIContent; class nsIFrame; class nsIPresContext; -class nsTextControlFrame : public nsFormControlFrame { +class nsTextControlFrame : public nsFormControlFrame +{ +/* ---------- methods implemented by base class ---------- */ public: - // nsIFormControlFrame - NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue); - NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue); - - virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext); - - NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, - nsIContent* aChild, - nsIAtom* aAttribute, - PRInt32 aHint); - - NS_IMETHOD GetFrameName(nsString& aResult) const; - - virtual void PostCreateWidget(nsIPresContext* aPresContext, - nscoord& aWidth, - nscoord& aHeight); - virtual const nsIID& GetCID(); - virtual const nsIID& GetIID(); - NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue); - - virtual void EnterPressed(nsIPresContext& aPresContext) ; - + NS_IMETHOD GetFrameName(nsString& aResult) const; + virtual nscoord GetVerticalBorderWidth(float aPixToTwip) const; virtual nscoord GetHorizontalBorderWidth(float aPixToTwip) const; virtual nscoord GetVerticalInsidePadding(float aPixToTwip, @@ -60,40 +42,65 @@ public: nscoord aInnerWidth, nscoord aCharWidth) const; virtual PRInt32 GetMaxNumValues(); - virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, - nsString* aValues, nsString* aNames); - virtual void Reset(); NS_IMETHOD GetCursor(nsIPresContext& aPresContext, nsPoint& aPoint, PRInt32& aCursor); - NS_IMETHOD Paint(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - virtual void PaintTextControlBackground(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, - nsFramePaintLayer aWhichLayer); - - virtual void PaintTextControl(nsIPresContext& aPresContext, - nsIRenderingContext& aRenderingContext, - const nsRect& aDirtyRect, nsString& aText, - nsIStyleContext* aStyleContext, - nsRect& aRect); - - // Utility methods to get and set current widget state - void GetTextControlFrameState(nsString& aValue); - void SetTextControlFrameState(const nsString& aValue); - protected: - - virtual void GetDesiredSize(nsIPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredLayoutSize, nsSize& aDesiredWidgetSize); + + + +/* ---------- abstract methods derived class must implement ---------- */ +public: + // nsIFormControlFrame + NS_IMETHOD SetProperty(nsIAtom* aName, const nsString& aValue)=0; + NS_IMETHOD GetProperty(nsIAtom* aName, nsString& aValue)=0; + + virtual nsWidgetInitData* GetWidgetInitData(nsIPresContext& aPresContext)=0; + + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + nsIAtom* aAttribute, + PRInt32 aHint)=0; + + virtual void PostCreateWidget(nsIPresContext* aPresContext, + nscoord& aWidth, + nscoord& aHeight)=0; + + NS_IMETHOD GetText(nsString* aValue, PRBool aInitialValue)=0; + + virtual void EnterPressed(nsIPresContext& aPresContext)=0; + + virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, + nsString* aValues, nsString* aNames)=0; + virtual void Reset()=0; + + NS_IMETHOD Paint(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer)=0; + + virtual void PaintTextControlBackground(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, + nsFramePaintLayer aWhichLayer)=0; + + virtual void PaintTextControl(nsIPresContext& aPresContext, + nsIRenderingContext& aRenderingContext, + const nsRect& aDirtyRect, nsString& aText, + nsIStyleContext* aStyleContext, + nsRect& aRect)=0; + + // Utility methods to get and set current widget state + virtual void GetTextControlFrameState(nsString& aValue)=0; + virtual void SetTextControlFrameState(const nsString& aValue)=0; + + virtual nsresult RequiresWidget(PRBool &aRequiresWidget)=0; + }; #endif