/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ #include "nsInput.h" #include "nsIFormManager.h" #include "nsInputFrame.h" #include "nsHTMLParts.h" #include "nsHTMLContainer.h" #include "nsIRenderingContext.h" #include "nsIPresShell.h" #include "nsIPresContext.h" #include "nsIStyleContext.h" #include "nsLeafFrame.h" #include "nsCSSRendering.h" #include "nsHTMLIIDs.h" #include "nsHTMLAtoms.h" #include "nsIView.h" #include "nsIViewManager.h" #include "nsCoord.h" #include "nsDebug.h" #include "nsIWidget.h" #include "nsHTMLForms.h" #include "nsStyleConsts.h" static NS_DEFINE_IID(kStyleDisplaySID, NS_STYLEDISPLAY_SID); static NS_DEFINE_IID(kStyleTextSID, NS_STYLETEXT_SID); // Note: we inherit a base class operator new that zeros our memory nsInput::nsInput(nsIAtom* aTag, nsIFormManager* aManager) : nsHTMLContainer(aTag), mControl() { mFormMan = aManager; if (nsnull != mFormMan) { NS_ADDREF(mFormMan); mFormMan->AddFormControl(&mControl); } mSize = ATTR_NOTSET; mAlign = ATTR_NOTSET; } nsInput::~nsInput() { NS_IF_RELEASE(mWidget); if (nsnull != mName) { delete mName; } if (nsnull != mValue) { delete mName; } if (nsnull != mFormMan) { // prevent mFormMan from decrementing its ref count on us mFormMan->RemoveFormControl(&mControl, PR_FALSE); NS_RELEASE(mFormMan); } } void nsInput::MapAttributesInto(nsIStyleContext* aContext, nsIPresContext* aPresContext) { #if 0 if (ATTR_NOTSET != mAlign) { nsStyleDisplay* display = (nsStyleDisplay*) aContext->GetData(kStyleDisplaySID); nsStyleText* text = (nsStyleText*) aContext->GetData(kStyleTextSID); switch (mAlign) { case NS_STYLE_TEXT_ALIGN_LEFT: display->mFloats = NS_STYLE_FLOAT_LEFT; break; case NS_STYLE_TEXT_ALIGN_RIGHT: display->mFloats = NS_STYLE_FLOAT_RIGHT; break; default: text->mVerticalAlignFlags = mAlign; break; } } #endif } static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); nsresult nsInput::QueryInterface(REFNSIID aIID, void** aInstancePtr) { if (aIID.Equals(kIFormControlIID)) { AddRef(); *aInstancePtr = (void**) &mControl; return NS_OK; } return nsHTMLContainer::QueryInterface(aIID, aInstancePtr); } nsrefcnt nsInput::Release() { --mRefCnt; int debugRefCnt = mRefCnt; if (mRefCnt == 0) { delete this; return 0; } if ((mFormMan == nsnull) || (mRefCnt > 1)) { return mRefCnt; } int numSiblings = mFormMan->GetFormControlCount(); PRBool externalRefs = PR_FALSE; // are there external refs to dad or any siblings if ((int)mFormMan->GetRefCount() > numSiblings) { externalRefs = PR_TRUE; } else { for (int i = 0; i < numSiblings; i++) { nsIFormControl* sibling = mFormMan->GetFormControlAt(i); if (sibling->GetRefCount() > 1) { externalRefs = PR_TRUE; break; } } } if (!externalRefs) { mRefCnt = 0; delete this; return 0; } return mRefCnt; } nsIFrame* nsInput::CreateFrame(nsIPresContext *aPresContext, PRInt32 aIndexInParent, nsIFrame *aParentFrame) { NS_ASSERTION(0, "frames must be created by subclasses of Input"); return nsnull; } PRBool nsInput::IsHidden() { return PR_FALSE; } void nsInput::SetWidget(nsIWidget* aWidget) { if (aWidget != mWidget) { NS_IF_RELEASE(mWidget); NS_IF_ADDREF(aWidget); mWidget = aWidget; } } nsrefcnt nsInput::GetRefCount() const { return mRefCnt; } // this is for internal use and does not do an AddRef nsIWidget* nsInput::GetWidget() { return mWidget; } void nsInput::SetFormManager(nsIFormManager* aFormMan, PRBool aDecrementRef) { if (aDecrementRef) { NS_IF_RELEASE(mFormMan); } mFormMan = aFormMan; NS_IF_ADDREF(aFormMan); } nsIFormManager* nsInput::GetFormManager() const { NS_IF_ADDREF(mFormMan); return mFormMan; } /** * Get the name associated with this form element. If there is no name * then return PR_FALSE (form elements without names are not submitable). */ PRBool nsInput::GetName(nsString& aName) const { if ((nsnull != mName) && (0 != mName->Length())) { aName = *mName; return PR_TRUE; } return PR_FALSE; } void nsInput::Reset() { } PRInt32 nsInput::GetMaxNumValues() { return 0; } PRBool nsInput::GetValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues) { aNumValues = 0; return PR_FALSE; } void nsInput::CacheAttribute(const nsString& aValue, nsString*& aLoc) { if (nsnull == aLoc) { aLoc = new nsString(aValue); } else { aLoc->SetLength(0); aLoc->Append(aValue); } } void nsInput::CacheAttribute(const nsString& aValue, PRInt32 aMinValue, PRInt32& aLoc) { PRInt32 status; PRInt32 intVal = aValue.ToInteger(&status); aLoc = ((NS_OK == status) && (intVal >= aMinValue)) ? intVal : aMinValue; } void nsInput::SetAttribute(nsIAtom* aAttribute, const nsString& aValue) { if (aAttribute == nsHTMLAtoms::type) { // You cannot set the type of a form element return; } else if (aAttribute == nsHTMLAtoms::name) { CacheAttribute(aValue, mName); } else if (aAttribute == nsHTMLAtoms::size) { CacheAttribute(aValue, ATTR_NOTSET, mSize); } else if (aAttribute == nsHTMLAtoms::value) { CacheAttribute(aValue, mValue); } else if (aAttribute == nsHTMLAtoms::align) { CacheAttribute(aValue, ATTR_NOTSET, mAlign); } else { super::SetAttribute(aAttribute, aValue); } } nsContentAttr nsInput::GetCacheAttribute(nsString* const& aLoc, nsHTMLValue& aValue) const { aValue.Reset(); if (nsnull == aLoc) { return eContentAttr_NotThere; } else { aValue.Set(*aLoc); return eContentAttr_HasValue; } } nsContentAttr nsInput::GetCacheAttribute(PRInt32 aLoc, nsHTMLValue& aValue) const { aValue.Reset(); if (aLoc <= ATTR_NOTSET) { return eContentAttr_NotThere; } else { aValue.Set(aLoc); return eContentAttr_HasValue; } } #if 0 nsContentAttr nsInput::GetCacheAttribute(PRBool aLoc, nsHTMLValue& aValue) const { aValue.Reset(); if (aLoc) { aValue.Set(1); return eContentAttr_HasValue; } else { return eContentAttr_NotThere; } } #endif nsContentAttr nsInput::GetAttribute(nsIAtom* aAttribute, nsString& aValue) const { nsHTMLValue htmlValue; nsContentAttr result = GetAttribute(aAttribute, htmlValue); if (eContentAttr_HasValue == result) { htmlValue.GetStringValue(aValue); return eContentAttr_HasValue; } else { aValue = ""; return eContentAttr_NoValue; } } nsContentAttr nsInput::GetAttribute(nsIAtom* aAttribute, PRInt32& aValue) const { nsHTMLValue htmlValue; nsContentAttr result = GetAttribute(aAttribute, htmlValue); if (eContentAttr_HasValue == result) { aValue = htmlValue.GetIntValue(); return eContentAttr_HasValue; } else { aValue = ATTR_NOTSET; return eContentAttr_NoValue; } } #if 0 nsContentAttr nsInput::GetAttribute(nsIAtom* aAttribute, PRBool& aValue) const { PRInt32 intVal; nsContentAttr result = GetAttribute(aAttribute, intVal); if ((eContentAttr_HasValue == result) && (intVal > 0)) { aValue = PR_TRUE; return eContentAttr_HasValue; } else { aValue = PR_FALSE; return eContentAttr_NoValue; } } #endif nsContentAttr nsInput::GetAttribute(nsIAtom* aAttribute, nsHTMLValue& aValue) const { if (aAttribute == nsHTMLAtoms::type) { nsAutoString tmp; GetType(tmp); if (tmp.Length() == 0) { // derivatives that don't support type return zero length string return eContentAttr_NotThere; } else { aValue.Set(tmp); return eContentAttr_HasValue; } } else if (aAttribute == nsHTMLAtoms::name) { return GetCacheAttribute(mName, aValue); } else if (aAttribute == nsHTMLAtoms::size) { return GetCacheAttribute(mSize, aValue); } else if (aAttribute == nsHTMLAtoms::value) { return GetCacheAttribute(mValue, aValue); } else if (aAttribute == nsHTMLAtoms::align) { return GetCacheAttribute(mAlign, aValue); } else { return super::GetAttribute(aAttribute, aValue); } } PRBool nsInput::GetChecked(PRBool aGetInitialValue) const { return PR_FALSE; } void nsInput::SetChecked(PRBool aState, PRBool aSetInitialValue) { } //---------------------------------------------------------------------- #define GET_OUTER() ((nsInput*) ((char*)this - nsInput::GetOuterOffset())) nsInput::AggInputControl::AggInputControl() { } nsInput::AggInputControl::~AggInputControl() { } nsrefcnt nsInput::AggInputControl::AddRef() { return GET_OUTER()->AddRef(); } nsrefcnt nsInput::AggInputControl::Release() { return GET_OUTER()->Release(); } nsresult nsInput::AggInputControl::QueryInterface(REFNSIID aIID, void** aInstancePtr) { return GET_OUTER()->QueryInterface(aIID, aInstancePtr); } PRBool nsInput::AggInputControl::GetName(nsString& aName) const { return GET_OUTER()->GetName(aName); } PRInt32 nsInput::AggInputControl::GetMaxNumValues() { return GET_OUTER()->GetMaxNumValues(); } PRBool nsInput::AggInputControl::GetValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues) { return GET_OUTER()->GetValues(aMaxNumValues, aNumValues, aValues); } void nsInput::AggInputControl::Reset() { GET_OUTER()->Reset(); } void nsInput::AggInputControl::SetFormManager(nsIFormManager* aFormMan, PRBool aDecrementRef) { GET_OUTER()->SetFormManager(aFormMan, aDecrementRef); } nsIFormManager* nsInput::AggInputControl::GetFormManager() const { return GET_OUTER()->GetFormManager(); } nsrefcnt nsInput::AggInputControl::GetRefCount() const { return GET_OUTER()->GetRefCount(); } PRBool nsInput::AggInputControl::GetChecked(PRBool aGetInitialValue) const { return GET_OUTER()->GetChecked(aGetInitialValue); } void nsInput::AggInputControl::SetChecked(PRBool aState, PRBool aSetInitialValue) { GET_OUTER()->SetChecked(aState, aSetInitialValue); } void nsInput::AggInputControl::GetType(nsString& aName) const { GET_OUTER()->GetType(aName); }