diff --git a/mozilla/layout/forms/nsComboboxControlFrame.cpp b/mozilla/layout/forms/nsComboboxControlFrame.cpp index 3e1f315d1fa..80f5abc8639 100644 --- a/mozilla/layout/forms/nsComboboxControlFrame.cpp +++ b/mozilla/layout/forms/nsComboboxControlFrame.cpp @@ -1729,7 +1729,7 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mPopupFrames.SetFrames(aChildList); } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); - InitTextStr(aPresContext, PR_FALSE); + InitTextStr(aPresContext, PR_TRUE); } return rv; } diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp index 653af3cc93c..275c2f947f9 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.cpp @@ -25,9 +25,16 @@ #include "nsWidgetsCID.h" #include "nsIFontMetrics.h" #include "nsFormControlFrame.h" +#include "nsIServiceManager.h" +#include "nsIIOService.h" +#include "nsIURI.h" +#include "nsIStringBundle.h" +#include "nsITextContent.h" +#include "nsISupportsArray.h" +#include "nsXPIDLString.h" -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); -static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); const nscoord kSuggestedNotSet = -1; @@ -36,6 +43,7 @@ nsGfxButtonControlFrame::nsGfxButtonControlFrame() mRenderer.SetNameSpace(kNameSpaceID_None); mSuggestedWidth = kSuggestedNotSet; mSuggestedHeight = kSuggestedNotSet; + mUpdateValue = ""; } PRBool @@ -127,6 +135,42 @@ nsGfxButtonControlFrame::IsSubmit(PRInt32 type) } } +// Special check for the browse button of a file input. +// +// Since this is actually type "NS_FORM_INPUT_BUTTON", we +// can't tell if it is part of a file input by the type. +// We'll return PR_TRUE if either: +// (a) type is NS_FORM_BROWSE or +// (b) type is NS_FORM_INPUT_BUTTON and our parent is a file input +PRBool +nsGfxButtonControlFrame::IsBrowse(PRInt32 type) +{ + if (NS_FORM_BROWSE == type) { + return PR_TRUE; + } + if (NS_FORM_INPUT_BUTTON == type) { + + // Check to see if parent is a file input + nsIContent* parentContent; + mContent->GetParent(parentContent); + nsIAtom* atom; + if (parentContent->GetTag(atom) == NS_OK && atom == nsHTMLAtoms::input) { + + // It's an input, is it a file input? + nsString value; + if (NS_CONTENT_ATTR_HAS_VALUE == parentContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, value)) { + value.ToUpperCase(); + nsString file("FILE"); + if (value == file) { + return PR_TRUE; + } + } + } + NS_RELEASE(parentContent); + } + return PR_FALSE; +} + /* * FIXME: this ::GetIID() method has no meaning in life and should be * removed. @@ -184,33 +228,11 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext // Get the text from the "value" attribute // for measuring the height, width of the text - // if there is no value attr or its length is 0 - // then go to the generated content to get it + // This shouldn't be zero because if it was we set it to + // a default. See CreateAnonymousContent and Reflow nsAutoString value; GetValue(&value); - // if there was no value specified - // then go get the content of the generated content - // we can't make any assumption as to what the default would be - // because of the value is specified in the html.css and for - // for non-english platforms it might not be the string - // "Reset" or "Submit Query" - if (value.Length() == 0) { - value = " "; - // The child frame will br the generated content - nsIFrame* fKid; - firstKid->FirstChild(aPresContext, nsnull, &fKid); - if (fKid) { - const nsStyleContent* content; - fKid->GetStyleData(eStyleStruct_Content, (const nsStyleStruct *&)content); - PRUint32 count = content->ContentCount(); - // XXX not sure if I need to get more than the first index? - if (count > 0) { - nsStyleContentType contentType = eStyleContentType_String; - content->GetContentAt(0, contentType, value); - } - } - } const nsStyleText* textStyle; GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle); if (!textStyle->WhiteSpaceIsSignificant()) { @@ -320,6 +342,164 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext return NS_OK; } +// Create the text content used as label for the button. +// The frame will be generated by the frame constructor. +NS_IMETHODIMP +nsGfxButtonControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, + nsISupportsArray& aChildList) +{ + nsresult result; + + // Get the text from the "value" attribute. + // If it is zero length, set it to a default value (localized) + nsAutoString initvalue, value; + GetValue(&initvalue); + value = initvalue; + if (value.Length() == 0) { + // Generate localized label. + // We can't make any assumption as to what the default would be + // because the value is localized for non-english platforms, thus + // it might not be the string "Reset", "Submit Query", or "Browse..." + result = GetDefaultLabel(value); + if (NS_FAILED(result)) { + return result; + } + } + + // Compress whitespace out of label if needed. + const nsStyleText* textStyle; + GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle); + if (!textStyle->WhiteSpaceIsSignificant()) { + value.CompressWhitespace(); + if (value.Length() == 0) { + value = " "; + } + } + + // Cache this value away until we have created + // a frame so we can update the value attribute. + // This makes input.value return the default string as in Nav and IE. + if (initvalue != value) { + mUpdateValue = value; + } + + // Add a child text content node for the label + nsCOMPtr labelContent; + result = NS_NewTextNode(getter_AddRefs(labelContent)); + if (NS_SUCCEEDED(result) && labelContent) { + // set the value of the text node + labelContent->QueryInterface(NS_GET_IID(nsITextContent), getter_AddRefs(mTextContent)); + mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + aChildList.AppendElement(mTextContent); + } + return result; +} + +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } else if (aIID.Equals(NS_GET_IID(nsIAnonymousContentCreator))) { + *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; + return NS_OK; + } + return nsHTMLButtonControlFrame::QueryInterface(aIID, aInstancePtr); +} + +// Initially we hardcoded the default strings here. +// Next, we used html.css to store the default label for various types +// of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20) +// However, since html.css is not internationalized, we now grab the default +// label from a string bundle as is done for all other UI strings. +// See bug 16999 for further details. +NS_IMETHODIMP +nsGfxButtonControlFrame::GetDefaultLabel(nsString& aString) +{ + nsresult rv = NS_OK; + PRInt32 type; + GetType(&type); + if (IsReset(type)) { + rv = ButtonLocalize("Reset", aString); + } + else if (IsSubmit(type)) { + rv = ButtonLocalize("Submit", aString); + } + else if (IsBrowse(type)) { + rv = ButtonLocalize("Browse", aString); + } + else { + aString = " "; + rv = NS_OK; + } + return rv; +} + +#define form_properties "chrome://layout/locale/HtmlForm.properties" + +// Return localised string for resource string (e.g. "Submit" -> "Submit Query") +// This code is derived from nsBookmarksService::Init() and cookie_Localize() +NS_IMETHODIMP +nsGfxButtonControlFrame::ButtonLocalize(char* aKey, nsString& oVal) +{ + nsresult rv; + nsCOMPtr bundle; + + // Create a URL for the string resource file + // Create a bundle for the localization + NS_WITH_SERVICE(nsIIOService, pNetService, kIOServiceCID, &rv); + if (NS_SUCCEEDED(rv) && pNetService) { + nsCOMPtr uri; + rv = pNetService->NewURI(form_properties, nsnull, getter_AddRefs(uri)); + if (NS_SUCCEEDED(rv) && uri) { + + // Create bundle + NS_WITH_SERVICE(nsIStringBundleService, stringService, kStringBundleServiceCID, &rv); + if (NS_SUCCEEDED(rv) && stringService) { + nsXPIDLCString spec; + rv = uri->GetSpec(getter_Copies(spec)); + if (NS_SUCCEEDED(rv) && spec) { + nsCOMPtr locale = nsnull; + rv = stringService->CreateBundle(spec, locale, getter_AddRefs(bundle)); + } + } + } + } + + // Determine default label from string bundle + if (NS_SUCCEEDED(rv) && bundle && aKey) { + nsXPIDLString valUni; + nsAutoString key(aKey); + rv = bundle->GetStringFromName(key.GetUnicode(), getter_Copies(valUni)); + if (NS_SUCCEEDED(rv) && valUni) { + oVal = valUni; + } else { + oVal.Truncate(); + } + } + return rv; +} + +NS_IMETHODIMP +nsGfxButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + // If the value attribute is set, update the text of the label + if (nsHTMLAtoms::value == aAttribute) { + nsString value; + if (nsnull != mTextContent && NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value)) { + mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + } + } + + return nsHTMLButtonControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); +} + NS_IMETHODIMP nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -328,8 +508,27 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, { // The mFormFrame is set in the initial reflow within nsHTMLButtonControlFrame nsresult rv = NS_OK; - if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); + if (eReflowReason_Initial == aReflowState.reason) { + if (!mFormFrame) { + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); + } + // If we cached a value (mUpdateValue) in CreateAnonymousContent(), + // set the value attribute of the button to this generated label. + // This will allow e.g. submit inputs to return a value of Submit Query + // when none is specified, as they do in IE 5.0 and Nav 4.x. We have to + // wait until now because updating our value attribute will cause a + // reflow and the frame must exist. + if (mUpdateValue.Length() != 0) { + if (mContent) { + nsIHTMLContent* formControl = nsnull; + rv = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if (NS_SUCCEEDED(rv) && formControl) { + rv = formControl->SetHTMLAttribute(nsHTMLAtoms::value, mUpdateValue, PR_TRUE); + NS_RELEASE(formControl); + } + } + mUpdateValue = ""; + } } #if 0 diff --git a/mozilla/layout/forms/nsGfxButtonControlFrame.h b/mozilla/layout/forms/nsGfxButtonControlFrame.h index e3d8d3fd3c7..ab653237b70 100644 --- a/mozilla/layout/forms/nsGfxButtonControlFrame.h +++ b/mozilla/layout/forms/nsGfxButtonControlFrame.h @@ -25,13 +25,17 @@ #include "nsFormControlFrame.h" #include "nsHTMLButtonControlFrame.h" +#include "nsCOMPtr.h" +#include "nsIAnonymousContentCreator.h" // Class which implements the input[type=button, reset, submit] and // browse button for input[type=file]. // The label for button is specified through generated content // in the ua.css file. -class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame { +class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame, + public nsIAnonymousContentCreator +{ public: nsGfxButtonControlFrame(); @@ -57,7 +61,13 @@ public: virtual PRInt32 GetMaxNumValues(); virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames); + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIAnonymousContentCreator + NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, + nsISupportsArray& aChildList); + protected: NS_IMETHOD AddComputedBorderPaddingToDesiredSize(nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aSuggestedReflowState); @@ -65,15 +75,26 @@ protected: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD GetDefaultLabel(nsString& aLabel); + NS_IMETHOD ButtonLocalize(char* aKey, nsString& oVal); + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint); + virtual PRBool IsReset(PRInt32 type); virtual PRBool IsSubmit(PRInt32 type); + virtual PRBool IsBrowse(PRInt32 type); // Browse button of file input private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } nscoord mSuggestedWidth; nscoord mSuggestedHeight; + nsCOMPtr mTextContent; + nsString mUpdateValue; }; diff --git a/mozilla/layout/html/document/src/html.css b/mozilla/layout/html/document/src/html.css index 27b0f1e7ccc..356df71a56b 100644 --- a/mozilla/layout/html/document/src/html.css +++ b/mozilla/layout/html/document/src/html.css @@ -493,7 +493,6 @@ input[type=file][disabled] input[type="button"] { } input[type=file] input[type="button"]:-moz-buttonlabel { - content:"Browse..."; font-family: sans-serif; } @@ -663,7 +662,6 @@ input[type="submit"]:focus:-moz-focus-inner { } input[type=submit]:-moz-buttonlabel { - content:"Submit Query"; font-family: sans-serif; font-size: small; } @@ -672,12 +670,6 @@ input[type="submit"][disabled]:-moz-buttonlabel { color: gray; } -input[type=submit][value]:-moz-buttonlabel { - content:attr(value); - font-family: sans-serif; - font-size: small; -} - /* reset */ input[type="reset"] { @@ -743,7 +735,6 @@ input[type="reset"]:focus:-moz-focus-inner { border : 1px dotted black; } input[type=reset]:-moz-buttonlabel { - content:"Reset"; font-family: sans-serif; font-size: small; } @@ -752,12 +743,6 @@ input[type="reset"][disabled]:-moz-buttonlabel { color: gray; } -input[type=reset][value]:-moz-buttonlabel { - content:attr(value); - font-family: sans-serif; - font-size: small; -} - /* button */ input[type="button"] { box-sizing: border-box; @@ -804,7 +789,6 @@ input[type="button"][disabled]:active { input[type="button"]:-moz-buttonlabel { box-sizing: border-box; - content:" "; font-family: inherit; font-size: inherit; background-color:inherit; @@ -814,13 +798,6 @@ input[type="button"][disabled]:-moz-buttonlabel { color: gray; } -input[type="button"][value]:-moz-buttonlabel { - content:attr(value); - font-family: inherit; - font-size: inherit; - background-color:inherit; -} - input[type="button"]:-moz-focus-inner { /*XXX[PERF] Set the padding to match between diff --git a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp index 3e1f315d1fa..80f5abc8639 100644 --- a/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsComboboxControlFrame.cpp @@ -1729,7 +1729,7 @@ nsComboboxControlFrame::SetInitialChildList(nsIPresContext* aPresContext, mPopupFrames.SetFrames(aChildList); } else { rv = nsAreaFrame::SetInitialChildList(aPresContext, aListName, aChildList); - InitTextStr(aPresContext, PR_FALSE); + InitTextStr(aPresContext, PR_TRUE); } return rv; } diff --git a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp index 653af3cc93c..275c2f947f9 100644 --- a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp +++ b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.cpp @@ -25,9 +25,16 @@ #include "nsWidgetsCID.h" #include "nsIFontMetrics.h" #include "nsFormControlFrame.h" +#include "nsIServiceManager.h" +#include "nsIIOService.h" +#include "nsIURI.h" +#include "nsIStringBundle.h" +#include "nsITextContent.h" +#include "nsISupportsArray.h" +#include "nsXPIDLString.h" -static NS_DEFINE_IID(kIFormControlIID, NS_IFORMCONTROL_IID); -static NS_DEFINE_IID(kIButtonIID, NS_IBUTTON_IID); +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); +static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); const nscoord kSuggestedNotSet = -1; @@ -36,6 +43,7 @@ nsGfxButtonControlFrame::nsGfxButtonControlFrame() mRenderer.SetNameSpace(kNameSpaceID_None); mSuggestedWidth = kSuggestedNotSet; mSuggestedHeight = kSuggestedNotSet; + mUpdateValue = ""; } PRBool @@ -127,6 +135,42 @@ nsGfxButtonControlFrame::IsSubmit(PRInt32 type) } } +// Special check for the browse button of a file input. +// +// Since this is actually type "NS_FORM_INPUT_BUTTON", we +// can't tell if it is part of a file input by the type. +// We'll return PR_TRUE if either: +// (a) type is NS_FORM_BROWSE or +// (b) type is NS_FORM_INPUT_BUTTON and our parent is a file input +PRBool +nsGfxButtonControlFrame::IsBrowse(PRInt32 type) +{ + if (NS_FORM_BROWSE == type) { + return PR_TRUE; + } + if (NS_FORM_INPUT_BUTTON == type) { + + // Check to see if parent is a file input + nsIContent* parentContent; + mContent->GetParent(parentContent); + nsIAtom* atom; + if (parentContent->GetTag(atom) == NS_OK && atom == nsHTMLAtoms::input) { + + // It's an input, is it a file input? + nsString value; + if (NS_CONTENT_ATTR_HAS_VALUE == parentContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::type, value)) { + value.ToUpperCase(); + nsString file("FILE"); + if (value == file) { + return PR_TRUE; + } + } + } + NS_RELEASE(parentContent); + } + return PR_FALSE; +} + /* * FIXME: this ::GetIID() method has no meaning in life and should be * removed. @@ -184,33 +228,11 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext // Get the text from the "value" attribute // for measuring the height, width of the text - // if there is no value attr or its length is 0 - // then go to the generated content to get it + // This shouldn't be zero because if it was we set it to + // a default. See CreateAnonymousContent and Reflow nsAutoString value; GetValue(&value); - // if there was no value specified - // then go get the content of the generated content - // we can't make any assumption as to what the default would be - // because of the value is specified in the html.css and for - // for non-english platforms it might not be the string - // "Reset" or "Submit Query" - if (value.Length() == 0) { - value = " "; - // The child frame will br the generated content - nsIFrame* fKid; - firstKid->FirstChild(aPresContext, nsnull, &fKid); - if (fKid) { - const nsStyleContent* content; - fKid->GetStyleData(eStyleStruct_Content, (const nsStyleStruct *&)content); - PRUint32 count = content->ContentCount(); - // XXX not sure if I need to get more than the first index? - if (count > 0) { - nsStyleContentType contentType = eStyleContentType_String; - content->GetContentAt(0, contentType, value); - } - } - } const nsStyleText* textStyle; GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle); if (!textStyle->WhiteSpaceIsSignificant()) { @@ -320,6 +342,164 @@ nsGfxButtonControlFrame::DoNavQuirksReflow(nsIPresContext* aPresContext return NS_OK; } +// Create the text content used as label for the button. +// The frame will be generated by the frame constructor. +NS_IMETHODIMP +nsGfxButtonControlFrame::CreateAnonymousContent(nsIPresContext* aPresContext, + nsISupportsArray& aChildList) +{ + nsresult result; + + // Get the text from the "value" attribute. + // If it is zero length, set it to a default value (localized) + nsAutoString initvalue, value; + GetValue(&initvalue); + value = initvalue; + if (value.Length() == 0) { + // Generate localized label. + // We can't make any assumption as to what the default would be + // because the value is localized for non-english platforms, thus + // it might not be the string "Reset", "Submit Query", or "Browse..." + result = GetDefaultLabel(value); + if (NS_FAILED(result)) { + return result; + } + } + + // Compress whitespace out of label if needed. + const nsStyleText* textStyle; + GetStyleData(eStyleStruct_Text, (const nsStyleStruct *&)textStyle); + if (!textStyle->WhiteSpaceIsSignificant()) { + value.CompressWhitespace(); + if (value.Length() == 0) { + value = " "; + } + } + + // Cache this value away until we have created + // a frame so we can update the value attribute. + // This makes input.value return the default string as in Nav and IE. + if (initvalue != value) { + mUpdateValue = value; + } + + // Add a child text content node for the label + nsCOMPtr labelContent; + result = NS_NewTextNode(getter_AddRefs(labelContent)); + if (NS_SUCCEEDED(result) && labelContent) { + // set the value of the text node + labelContent->QueryInterface(NS_GET_IID(nsITextContent), getter_AddRefs(mTextContent)); + mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + aChildList.AppendElement(mTextContent); + } + return result; +} + +// Frames are not refcounted, no need to AddRef +NS_IMETHODIMP +nsGfxButtonControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + NS_PRECONDITION(0 != aInstancePtr, "null ptr"); + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } else if (aIID.Equals(NS_GET_IID(nsIAnonymousContentCreator))) { + *aInstancePtr = (void*)(nsIAnonymousContentCreator*) this; + return NS_OK; + } + return nsHTMLButtonControlFrame::QueryInterface(aIID, aInstancePtr); +} + +// Initially we hardcoded the default strings here. +// Next, we used html.css to store the default label for various types +// of buttons. (nsGfxButtonControlFrame::DoNavQuirksReflow rev 1.20) +// However, since html.css is not internationalized, we now grab the default +// label from a string bundle as is done for all other UI strings. +// See bug 16999 for further details. +NS_IMETHODIMP +nsGfxButtonControlFrame::GetDefaultLabel(nsString& aString) +{ + nsresult rv = NS_OK; + PRInt32 type; + GetType(&type); + if (IsReset(type)) { + rv = ButtonLocalize("Reset", aString); + } + else if (IsSubmit(type)) { + rv = ButtonLocalize("Submit", aString); + } + else if (IsBrowse(type)) { + rv = ButtonLocalize("Browse", aString); + } + else { + aString = " "; + rv = NS_OK; + } + return rv; +} + +#define form_properties "chrome://layout/locale/HtmlForm.properties" + +// Return localised string for resource string (e.g. "Submit" -> "Submit Query") +// This code is derived from nsBookmarksService::Init() and cookie_Localize() +NS_IMETHODIMP +nsGfxButtonControlFrame::ButtonLocalize(char* aKey, nsString& oVal) +{ + nsresult rv; + nsCOMPtr bundle; + + // Create a URL for the string resource file + // Create a bundle for the localization + NS_WITH_SERVICE(nsIIOService, pNetService, kIOServiceCID, &rv); + if (NS_SUCCEEDED(rv) && pNetService) { + nsCOMPtr uri; + rv = pNetService->NewURI(form_properties, nsnull, getter_AddRefs(uri)); + if (NS_SUCCEEDED(rv) && uri) { + + // Create bundle + NS_WITH_SERVICE(nsIStringBundleService, stringService, kStringBundleServiceCID, &rv); + if (NS_SUCCEEDED(rv) && stringService) { + nsXPIDLCString spec; + rv = uri->GetSpec(getter_Copies(spec)); + if (NS_SUCCEEDED(rv) && spec) { + nsCOMPtr locale = nsnull; + rv = stringService->CreateBundle(spec, locale, getter_AddRefs(bundle)); + } + } + } + } + + // Determine default label from string bundle + if (NS_SUCCEEDED(rv) && bundle && aKey) { + nsXPIDLString valUni; + nsAutoString key(aKey); + rv = bundle->GetStringFromName(key.GetUnicode(), getter_Copies(valUni)); + if (NS_SUCCEEDED(rv) && valUni) { + oVal = valUni; + } else { + oVal.Truncate(); + } + } + return rv; +} + +NS_IMETHODIMP +nsGfxButtonControlFrame::AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint) +{ + // If the value attribute is set, update the text of the label + if (nsHTMLAtoms::value == aAttribute) { + nsString value; + if (nsnull != mTextContent && NS_CONTENT_ATTR_HAS_VALUE == mContent->GetAttribute(kNameSpaceID_None, nsHTMLAtoms::value, value)) { + mTextContent->SetText(value.GetUnicode(), value.Length(), PR_TRUE); + } + } + + return nsHTMLButtonControlFrame::AttributeChanged(aPresContext, aChild, aNameSpaceID, aAttribute, aHint); +} + NS_IMETHODIMP nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, @@ -328,8 +508,27 @@ nsGfxButtonControlFrame::Reflow(nsIPresContext* aPresContext, { // The mFormFrame is set in the initial reflow within nsHTMLButtonControlFrame nsresult rv = NS_OK; - if (!mFormFrame && (eReflowReason_Initial == aReflowState.reason)) { - nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); + if (eReflowReason_Initial == aReflowState.reason) { + if (!mFormFrame) { + nsFormFrame::AddFormControlFrame(aPresContext, *NS_STATIC_CAST(nsIFrame*, this)); + } + // If we cached a value (mUpdateValue) in CreateAnonymousContent(), + // set the value attribute of the button to this generated label. + // This will allow e.g. submit inputs to return a value of Submit Query + // when none is specified, as they do in IE 5.0 and Nav 4.x. We have to + // wait until now because updating our value attribute will cause a + // reflow and the frame must exist. + if (mUpdateValue.Length() != 0) { + if (mContent) { + nsIHTMLContent* formControl = nsnull; + rv = mContent->QueryInterface(kIHTMLContentIID, (void**)&formControl); + if (NS_SUCCEEDED(rv) && formControl) { + rv = formControl->SetHTMLAttribute(nsHTMLAtoms::value, mUpdateValue, PR_TRUE); + NS_RELEASE(formControl); + } + } + mUpdateValue = ""; + } } #if 0 diff --git a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h index e3d8d3fd3c7..ab653237b70 100644 --- a/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h +++ b/mozilla/layout/html/forms/src/nsGfxButtonControlFrame.h @@ -25,13 +25,17 @@ #include "nsFormControlFrame.h" #include "nsHTMLButtonControlFrame.h" +#include "nsCOMPtr.h" +#include "nsIAnonymousContentCreator.h" // Class which implements the input[type=button, reset, submit] and // browse button for input[type=file]. // The label for button is specified through generated content // in the ua.css file. -class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame { +class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame, + public nsIAnonymousContentCreator +{ public: nsGfxButtonControlFrame(); @@ -57,7 +61,13 @@ public: virtual PRInt32 GetMaxNumValues(); virtual PRBool GetNamesValues(PRInt32 aMaxNumValues, PRInt32& aNumValues, nsString* aValues, nsString* aNames); + NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr); + + // nsIAnonymousContentCreator + NS_IMETHOD CreateAnonymousContent(nsIPresContext* aPresContext, + nsISupportsArray& aChildList); + protected: NS_IMETHOD AddComputedBorderPaddingToDesiredSize(nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aSuggestedReflowState); @@ -65,15 +75,26 @@ protected: nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus); + NS_IMETHOD GetDefaultLabel(nsString& aLabel); + NS_IMETHOD ButtonLocalize(char* aKey, nsString& oVal); + NS_IMETHOD AttributeChanged(nsIPresContext* aPresContext, + nsIContent* aChild, + PRInt32 aNameSpaceID, + nsIAtom* aAttribute, + PRInt32 aHint); + virtual PRBool IsReset(PRInt32 type); virtual PRBool IsSubmit(PRInt32 type); + virtual PRBool IsBrowse(PRInt32 type); // Browse button of file input private: NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; } NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; } nscoord mSuggestedWidth; nscoord mSuggestedHeight; + nsCOMPtr mTextContent; + nsString mUpdateValue; }; diff --git a/mozilla/layout/style/html.css b/mozilla/layout/style/html.css index 27b0f1e7ccc..356df71a56b 100644 --- a/mozilla/layout/style/html.css +++ b/mozilla/layout/style/html.css @@ -493,7 +493,6 @@ input[type=file][disabled] input[type="button"] { } input[type=file] input[type="button"]:-moz-buttonlabel { - content:"Browse..."; font-family: sans-serif; } @@ -663,7 +662,6 @@ input[type="submit"]:focus:-moz-focus-inner { } input[type=submit]:-moz-buttonlabel { - content:"Submit Query"; font-family: sans-serif; font-size: small; } @@ -672,12 +670,6 @@ input[type="submit"][disabled]:-moz-buttonlabel { color: gray; } -input[type=submit][value]:-moz-buttonlabel { - content:attr(value); - font-family: sans-serif; - font-size: small; -} - /* reset */ input[type="reset"] { @@ -743,7 +735,6 @@ input[type="reset"]:focus:-moz-focus-inner { border : 1px dotted black; } input[type=reset]:-moz-buttonlabel { - content:"Reset"; font-family: sans-serif; font-size: small; } @@ -752,12 +743,6 @@ input[type="reset"][disabled]:-moz-buttonlabel { color: gray; } -input[type=reset][value]:-moz-buttonlabel { - content:attr(value); - font-family: sans-serif; - font-size: small; -} - /* button */ input[type="button"] { box-sizing: border-box; @@ -804,7 +789,6 @@ input[type="button"][disabled]:active { input[type="button"]:-moz-buttonlabel { box-sizing: border-box; - content:" "; font-family: inherit; font-size: inherit; background-color:inherit; @@ -814,13 +798,6 @@ input[type="button"][disabled]:-moz-buttonlabel { color: gray; } -input[type="button"][value]:-moz-buttonlabel { - content:attr(value); - font-family: inherit; - font-size: inherit; - background-color:inherit; -} - input[type="button"]:-moz-focus-inner { /*XXX[PERF] Set the padding to match between