diff --git a/layout/html/forms/src/nsInput.cpp b/layout/html/forms/src/nsInput.cpp index 75b9251050d..c5f58957992 100644 --- a/layout/html/forms/src/nsInput.cpp +++ b/layout/html/forms/src/nsInput.cpp @@ -355,7 +355,8 @@ nsContentAttr nsInput::GetAttribute(nsIAtom* aAttribute, nsString& aValue) const return eContentAttr_HasValue; } else { - aValue = ""; + //aValue = ""; // XXX string class was crashing on this line + aValue.SetLength(0); return eContentAttr_NoValue; } } diff --git a/layout/html/forms/src/nsSelect.cpp b/layout/html/forms/src/nsSelect.cpp index db141413e12..5c1572abf85 100644 --- a/layout/html/forms/src/nsSelect.cpp +++ b/layout/html/forms/src/nsSelect.cpp @@ -43,10 +43,16 @@ #include "nsStyleUtil.h" #include "nsFont.h" +#define NS_IOPTION_IID \ +{ 0xfa6a8b11, 0x2af2, 0x11d2, \ + { 0x80, 0x3a, 0x0, 0x60, 0x8, 0x15, 0xa7, 0x91 } } + static NS_DEFINE_IID(kListWidgetIID, NS_ILISTWIDGET_IID); static NS_DEFINE_IID(kComboBoxIID, NS_ICOMBOBOX_IID); static NS_DEFINE_IID(kListBoxIID, NS_ILISTBOX_IID); +static NS_DEFINE_IID(kOptionIID, NS_IOPTION_IID); +class nsOption; class nsSelectFrame : public nsInputFrame { public: @@ -88,6 +94,8 @@ public: nsIStyleContext* aStyleContext, nsIFrame*& aResult); + nsOption* GetNthOption(PRInt32 aIndex); + virtual void SetAttribute(nsIAtom* aAttribute, const nsString& aValue); virtual nsContentAttr GetAttribute(nsIAtom* aAttribute, @@ -126,6 +134,8 @@ public: nsIStyleContext* aStyleContext, nsIFrame*& aResult); + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); + virtual void SetAttribute(nsIAtom* aAttribute, const nsString& aValue); virtual nsContentAttr GetAttribute(nsIAtom* aAttribute, @@ -242,23 +252,28 @@ nsSelectFrame::GetDesiredSize(nsIPresContext* aPresContext, nsSize styleSize; GetStyleSize(*aPresContext, aReflowState, styleSize); - // get the size of the longest child + // get the size of the longest option child PRInt32 maxWidth = 1; PRInt32 numChildren = select->ChildCount(); - for (int i = 0; i < numChildren; i++) { - nsOption* option = (nsOption*) select->ChildAt(i); // YYY this had better be an option - option->CompressContent(); - nsString text; - if (PR_FALSE == option->GetContent(text)) { - continue; + for (int childX = 0; childX < numChildren; childX++) { + nsIContent* child = select->ChildAt(childX); + nsOption* option; + nsresult result = child->QueryInterface(kOptionIID, (void**)&option); + if (NS_OK == result) { + option->CompressContent(); + nsString text; + if (PR_FALSE == option->GetContent(text)) { + continue; + } + nsSize textSize; + // use the style for the select rather that the option, since widgets don't support it + nsInputFrame::GetTextSize(*aPresContext, this, text, textSize); + if (textSize.width > maxWidth) { + maxWidth = textSize.width; + } + NS_RELEASE(option); } - nsSize textSize; - // use the style for the select rather that the option, since widgets don't support it - nsInputFrame::GetTextSize(*aPresContext, this, text, textSize); - if (textSize.width > maxWidth) { - maxWidth = textSize.width; - } - NS_RELEASE(option); // YYY remove this comment if ok + NS_RELEASE(child); } PRInt32 rowHeight = 0; @@ -363,14 +378,21 @@ nsSelectFrame::PostCreateWidget(nsIPresContext* aPresContext, nsIView *aView) } PRInt32 numChildren = select->ChildCount(); - for (int i = 0; i < numChildren; i++) { - nsOption* option = (nsOption*) select->ChildAt(i); // YYY this had better be an option - nsString text; - if (PR_TRUE != option->GetContent(text)) { - text = " "; + int optionX = -1; + for (int childX = 0; childX < numChildren; childX++) { + nsIContent* child = select->ChildAt(childX); + nsOption* option; + nsresult result = child->QueryInterface(kOptionIID, (void**)&option); + if (NS_OK == result) { + optionX++; + nsString text; + if (PR_TRUE != option->GetContent(text)) { + text = " "; + } + list->AddItemAt(text, optionX); + NS_RELEASE(option); } - list->AddItemAt(text, i); - NS_RELEASE(option); // YYY remove comment if ok + NS_RELEASE(child); } NS_RELEASE(view); @@ -443,6 +465,27 @@ nsSelect::GetMaxNumValues() } } +nsOption* nsSelect::GetNthOption(PRInt32 aIndex) +{ + int optionX = -1; + PRInt32 numChildren = ChildCount(); + for (int childX = 0; childX < numChildren; childX++) { + nsIContent* child = ChildAt(childX); + nsOption* option; + nsresult result = child->QueryInterface(kOptionIID, (void**)&option); + if (NS_OK == result) { + optionX++; + if (aIndex == optionX) { + NS_RELEASE(child); + return option; + } + NS_RELEASE(option); + } + NS_RELEASE(child); + } + return nsnull; +} + PRBool nsSelect::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames) @@ -459,11 +502,13 @@ nsSelect::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, NS_ASSERTION((NS_OK == stat), "invalid widget"); PRInt32 index = list->GetSelectedIndex(); if (index >= 0) { - nsOption* selected = (nsOption*)ChildAt(index); - selected->GetNamesValues(aMaxNumValues, aNumValues, aValues, aNames); - aNames[0] = *mName; - NS_RELEASE(selected); // YYY remove this comment if ok - return PR_TRUE; + nsOption* selected = GetNthOption(index); + if (selected) { + selected->GetNamesValues(aMaxNumValues, aNumValues, aValues, aNames); + aNames[0] = *mName; + NS_RELEASE(selected); // YYY remove this comment if ok + return PR_TRUE; + } } else { aNumValues = 0; @@ -482,13 +527,16 @@ nsSelect::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, PRInt32 numValues; aNumValues = 0; for (int i = 0; i < numSelections; i++) { - nsOption* selected = (nsOption*)ChildAt(selections[i]); - selected->GetNamesValues(aMaxNumValues - i, numValues, - aValues + i, aNames + i); // options can only have 1 value - aNames[i] = *mName; - aNumValues += 1; - NS_RELEASE(selected); // YYY remove this comment if ok + nsOption* selected = GetNthOption(selections[i]); + if (selected) { + selected->GetNamesValues(aMaxNumValues - i, numValues, + aValues + i, aNames + i); // options can only have 1 value + aNames[i] = *mName; + aNumValues += 1; + NS_RELEASE(selected); // YYY remove this comment if ok + } } + delete [] selections; return PR_TRUE; } else { @@ -496,6 +544,8 @@ nsSelect::GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, return PR_FALSE; } } + aNumValues = 0; + return PR_FALSE; } @@ -513,18 +563,25 @@ nsSelect::Reset() list->Deselect(); PRInt32 selIndex = -1; - for (int i = 0; i < numChildren; i++) { - nsOption* option = (nsOption*)ChildAt(i); // YYY this had better be an option - PRInt32 selAttr; - ((nsInput *)option)->GetAttribute(nsHTMLAtoms::selected, selAttr); - if (ATTR_NOTSET != selAttr) { - list->SelectItem(i); - selIndex = i; - if (!mMultiple) { - break; + int optionX = -1; + for (int childX = 0; childX < numChildren; childX++) { + nsIContent* child = ChildAt(childX); + nsOption* option; + nsresult result = child->QueryInterface(kOptionIID, (void**)&option); + if (NS_OK == result) { + optionX++; + PRInt32 selAttr; + ((nsInput *)option)->GetAttribute(nsHTMLAtoms::selected, selAttr); + if (ATTR_NOTSET != selAttr) { + list->SelectItem(optionX); + selIndex = optionX; + if (!mMultiple) { + break; + } } + NS_RELEASE(option); } - NS_RELEASE(option); // YYY remove this comment if ok + NS_RELEASE(child); } // if none were selected, select 1st one if we are a combo box @@ -571,6 +628,16 @@ nsOption::CreateFrame(nsIPresContext* aPresContext, return NS_OK; } +nsresult nsOption::QueryInterface(REFNSIID aIID, void** aInstancePtr) +{ + if (aIID.Equals(kOptionIID)) { + AddRef(); + *aInstancePtr = (void**) this; + return NS_OK; + } + return nsInput::QueryInterface(aIID, aInstancePtr); +} + void nsOption::SetAttribute(nsIAtom* aAttribute, const nsString& aValue) {