1998-04-29 19:52:45 +00:00

470 lines
11 KiB
C++

/* -*- 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);
}