diff --git a/docs/doxygen/overviews/xrc_format.h b/docs/doxygen/overviews/xrc_format.h
index abffacb471..ebc25b1513 100644
--- a/docs/doxygen/overviews/xrc_format.h
+++ b/docs/doxygen/overviews/xrc_format.h
@@ -1595,6 +1595,11 @@ can also have some optional XML @em attributes (not properties!):
Is the button enabled (default: 1)?}
@row3col{hidden, @ref overview_xrcformat_type_bool,
Is the button hidden initially (default: 0)?}
+@row3col{label, @ref overview_xrcformat_type_bool,
+ Should this item text be interpreted as a label, i.e. escaping underscores
+ in it as done for the label properties of other controls? This attribute
+ exists since wxWidgets 3.1.1 and was always treated as having the value of
+ 0, which still remains its default, until then.}
@endTable
Example:
@@ -1611,7 +1616,7 @@ Example:
- Energy 98.3
- CHUM FM
- 92FM
- - Very quit station
+ - Very quiet station
@endcode
diff --git a/include/wx/xrc/xmlres.h b/include/wx/xrc/xmlres.h
index de31ea27a4..bde64138a5 100644
--- a/include/wx/xrc/xmlres.h
+++ b/include/wx/xrc/xmlres.h
@@ -513,7 +513,10 @@ public:
// - replaces \n, \r, \t by respective chars (according to C syntax)
// - replaces _ by & and __ by _ (needed for _File => &File because of XML)
// - calls wxGetTranslations (unless disabled in wxXmlResource)
- wxString GetText(const wxString& param, bool translate = true) wxOVERRIDE;
+ //
+ // The first two conversions can be disabled by using wxXRC_TEXT_NO_ESCAPE
+ // in flags and the last one -- by using wxXRC_TEXT_NO_TRANSLATE.
+ wxString GetNodeText(const wxXmlNode *node, int flags = 0) wxOVERRIDE;
// Returns the XRCID.
int GetID() wxOVERRIDE;
diff --git a/include/wx/xrc/xmlreshandler.h b/include/wx/xrc/xmlreshandler.h
index 5c2f6b4be1..cdf7f0ab17 100644
--- a/include/wx/xrc/xmlreshandler.h
+++ b/include/wx/xrc/xmlreshandler.h
@@ -32,6 +32,13 @@ class WXDLLIMPEXP_FWD_CORE wxXmlResourceHandler;
// by wxXmlResourceHandler implementation itself.
#define XRC_ADD_STYLE(style) AddStyle(wxT(#style), style)
+// Flags for GetNodeText().
+enum
+{
+ wxXRC_TEXT_NO_TRANSLATE = 1,
+ wxXRC_TEXT_NO_ESCAPE = 2
+};
+
// Abstract base class for the implementation object used by
// wxXmlResourceHandlerImpl. The real implementation is in
// wxXmlResourceHandlerImpl class in the "xrc" library while this class is in
@@ -61,7 +68,7 @@ public:
virtual wxString GetParamValue(const wxString& param) = 0;
virtual wxString GetParamValue(const wxXmlNode* node) = 0;
virtual int GetStyle(const wxString& param = wxT("style"), int defaults = 0) = 0;
- virtual wxString GetText(const wxString& param, bool translate = true) = 0;
+ virtual wxString GetNodeText(const wxXmlNode *node, int flags = 0) = 0;
virtual int GetID() = 0;
virtual wxString GetName() = 0;
virtual bool GetBool(const wxString& param, bool defaultv = false) = 0;
@@ -254,9 +261,14 @@ protected:
{
return GetImpl()->GetStyle(param, defaults);
}
+ wxString GetNodeText(const wxXmlNode *node, int flags = 0)
+ {
+ return GetImpl()->GetNodeText(node, flags);
+ }
wxString GetText(const wxString& param, bool translate = true)
{
- return GetImpl()->GetText(param, translate);
+ return GetImpl()->GetNodeText(GetImpl()->GetParamNode(param),
+ translate ? 0 : wxXRC_TEXT_NO_TRANSLATE);
}
int GetID() const
{
diff --git a/misc/schema/xrc_schema.rnc b/misc/schema/xrc_schema.rnc
index e4617452f6..ada4360591 100644
--- a/misc/schema/xrc_schema.rnc
+++ b/misc/schema/xrc_schema.rnc
@@ -1225,6 +1225,7 @@ wxRadioBox =
attribute helptext { t_string }?,
attribute enabled { t_bool }?,
attribute hidden { t_bool }?,
+ attribute label { t_bool }?,
t_text
}*
}?
diff --git a/samples/xrc/rc/controls.xrc b/samples/xrc/rc/controls.xrc
index bac4812e5e..a6c4406570 100644
--- a/samples/xrc/rc/controls.xrc
+++ b/samples/xrc/rc/controls.xrc
@@ -779,7 +779,7 @@ lay them out using wxSizers, absolute positioning, everything you like!
- Energy 98.3
- CHUM FM
- 92FM
- - Very quite station
+ - Very quiet station
diff --git a/src/xrc/xh_chckl.cpp b/src/xrc/xh_chckl.cpp
index fddfcf97c2..61675db8f4 100644
--- a/src/xrc/xh_chckl.cpp
+++ b/src/xrc/xh_chckl.cpp
@@ -94,10 +94,7 @@ wxObject *wxCheckListBoxXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
}
diff --git a/src/xrc/xh_choic.cpp b/src/xrc/xh_choic.cpp
index 445ec6b43a..52a3358cac 100644
--- a/src/xrc/xh_choic.cpp
+++ b/src/xrc/xh_choic.cpp
@@ -70,10 +70,7 @@ wxObject *wxChoiceXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_combo.cpp b/src/xrc/xh_combo.cpp
index a11d24bef9..e0f672ebe4 100644
--- a/src/xrc/xh_combo.cpp
+++ b/src/xrc/xh_combo.cpp
@@ -77,10 +77,7 @@ wxObject *wxComboBoxXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_editlbox.cpp b/src/xrc/xh_editlbox.cpp
index 32ab05f525..48a57847d4 100644
--- a/src/xrc/xh_editlbox.cpp
+++ b/src/xrc/xh_editlbox.cpp
@@ -99,10 +99,7 @@ wxObject *wxEditableListBoxXmlHandler::DoCreateResource()
}
else if ( m_insideBox && m_node->GetName() == EDITLBOX_ITEM_NAME )
{
- wxString str = GetNodeContent(m_node);
- if ( m_resource->GetFlags() & wxXRC_USE_LOCALE )
- str = wxGetTranslation(str, m_resource->GetDomain());
- m_items.push_back(str);
+ m_items.push_back(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_htmllbox.cpp b/src/xrc/xh_htmllbox.cpp
index 2b310e4c4e..82c01f10ad 100644
--- a/src/xrc/xh_htmllbox.cpp
+++ b/src/xrc/xh_htmllbox.cpp
@@ -69,10 +69,7 @@ wxObject *wxSimpleHtmlListBoxXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_listb.cpp b/src/xrc/xh_listb.cpp
index f496023095..e74eb99e2c 100644
--- a/src/xrc/xh_listb.cpp
+++ b/src/xrc/xh_listb.cpp
@@ -77,10 +77,7 @@ wxObject *wxListBoxXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_odcombo.cpp b/src/xrc/xh_odcombo.cpp
index 955ac1d826..293e7c5d30 100644
--- a/src/xrc/xh_odcombo.cpp
+++ b/src/xrc/xh_odcombo.cpp
@@ -85,10 +85,7 @@ wxObject *wxOwnerDrawnComboBoxXmlHandler::DoCreateResource()
// handle - Label
// add to the list
- wxString str = GetNodeContent(m_node);
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- str = wxGetTranslation(str, m_resource->GetDomain());
- strList.Add(str);
+ strList.Add(GetNodeText(m_node, wxXRC_TEXT_NO_ESCAPE));
return NULL;
}
diff --git a/src/xrc/xh_radbx.cpp b/src/xrc/xh_radbx.cpp
index 12c9e02a25..5fd8a84287 100644
--- a/src/xrc/xh_radbx.cpp
+++ b/src/xrc/xh_radbx.cpp
@@ -107,30 +107,21 @@ wxObject *wxRadioBoxXmlHandler::DoCreateResource()
// we handle handle - Label
constructs here, and the item
// tag can have tooltip, helptext, enabled and hidden attributes
- wxString label = GetNodeContent(m_node);
-
- wxString tooltip;
- m_node->GetAttribute(wxT("tooltip"), &tooltip);
-
- wxString helptext;
- bool hasHelptext = m_node->GetAttribute(wxT("helptext"), &helptext);
-
- if (m_resource->GetFlags() & wxXRC_USE_LOCALE)
- {
- label = wxGetTranslation(label, m_resource->GetDomain());
- if ( !tooltip.empty() )
- tooltip = wxGetTranslation(tooltip, m_resource->GetDomain());
- if ( hasHelptext )
- helptext = wxGetTranslation(helptext, m_resource->GetDomain());
- }
-
- m_labels.push_back(label);
+ // For compatibility, labels are not escaped in XRC by default and
+ // label="1" attribute needs to be explicitly specified to handle them
+ // consistently with the other labels.
+ m_labels.push_back(GetNodeText(m_node,
+ GetBoolAttr("label", 0)
+ ? 0
+ : wxXRC_TEXT_NO_ESCAPE));
#if wxUSE_TOOLTIPS
- m_tooltips.push_back(tooltip);
+ m_tooltips.push_back(GetNodeText(GetParamNode(wxT("tooltip")),
+ wxXRC_TEXT_NO_ESCAPE));
#endif // wxUSE_TOOLTIPS
#if wxUSE_HELP
- m_helptexts.push_back(helptext);
- m_helptextSpecified.push_back(hasHelptext);
+ const wxXmlNode* const nodeHelp = GetParamNode(wxT("helptext"));
+ m_helptexts.push_back(GetNodeText(nodeHelp, wxXRC_TEXT_NO_ESCAPE));
+ m_helptextSpecified.push_back(nodeHelp != NULL);
#endif // wxUSE_HELP
m_isEnabled.push_back(GetBoolAttr("enabled", 1));
m_isShown.push_back(!GetBoolAttr("hidden", 0));
diff --git a/src/xrc/xmlres.cpp b/src/xrc/xmlres.cpp
index 6a1e813c26..1963ba9d73 100644
--- a/src/xrc/xmlres.cpp
+++ b/src/xrc/xmlres.cpp
@@ -1506,73 +1506,83 @@ int wxXmlResourceHandlerImpl::GetStyle(const wxString& param, int defaults)
-wxString wxXmlResourceHandlerImpl::GetText(const wxString& param, bool translate)
+wxString wxXmlResourceHandlerImpl::GetNodeText(const wxXmlNode* node, int flags)
{
- wxXmlNode *parNode = GetParamNode(param);
- wxString str1(GetNodeContent(parNode));
+ wxString str1(GetNodeContent(node));
+ if ( str1.empty() )
+ return str1;
+
wxString str2;
- // "\\" wasn't translated to "\" prior to 2.5.3.0:
- const bool escapeBackslash = (m_handler->m_resource->CompareVersion(2,5,3,0) >= 0);
-
- // VS: First version of XRC resources used $ instead of & (which is
- // illegal in XML), but later I realized that '_' fits this purpose
- // much better (because &File means "File with F underlined").
- const wxChar amp_char = (m_handler->m_resource->CompareVersion(2,3,0,1) < 0)
- ? '$' : '_';
-
- for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
+ if ( !(flags & wxXRC_TEXT_NO_ESCAPE) )
{
- // Remap amp_char to &, map double amp_char to amp_char (for things
- // like "&File..." -- this is illegal in XML, so we use "_File..."):
- if ( *dt == amp_char )
+ // "\\" wasn't translated to "\" prior to 2.5.3.0:
+ const bool escapeBackslash = (m_handler->m_resource->CompareVersion(2,5,3,0) >= 0);
+
+ // VS: First version of XRC resources used $ instead of & (which is
+ // illegal in XML), but later I realized that '_' fits this purpose
+ // much better (because &File means "File with F underlined").
+ const wxChar amp_char = (m_handler->m_resource->CompareVersion(2,3,0,1) < 0)
+ ? '$' : '_';
+
+ for ( wxString::const_iterator dt = str1.begin(); dt != str1.end(); ++dt )
{
- if ( dt+1 == str1.end() || *(++dt) == amp_char )
- str2 << amp_char;
- else
- str2 << wxT('&') << *dt;
- }
- // Remap \n to CR, \r to LF, \t to TAB, \\ to \:
- else if ( *dt == wxT('\\') )
- {
- switch ( (*(++dt)).GetValue() )
+ // Remap amp_char to &, map double amp_char to amp_char (for things
+ // like "&File..." -- this is illegal in XML, so we use "_File..."):
+ if ( *dt == amp_char )
{
- case wxT('n'):
- str2 << wxT('\n');
- break;
-
- case wxT('t'):
- str2 << wxT('\t');
- break;
-
- case wxT('r'):
- str2 << wxT('\r');
- break;
-
- case wxT('\\') :
- // "\\" wasn't translated to "\" prior to 2.5.3.0:
- if ( escapeBackslash )
- {
- str2 << wxT('\\');
+ if ( dt+1 == str1.end() || *(++dt) == amp_char )
+ str2 << amp_char;
+ else
+ str2 << wxT('&') << *dt;
+ }
+ // Remap \n to CR, \r to LF, \t to TAB, \\ to \:
+ else if ( *dt == wxT('\\') )
+ {
+ switch ( (*(++dt)).GetValue() )
+ {
+ case wxT('n'):
+ str2 << wxT('\n');
break;
- }
- wxFALLTHROUGH;// else fall-through to default: branch below
- default:
- str2 << wxT('\\') << *dt;
- break;
+ case wxT('t'):
+ str2 << wxT('\t');
+ break;
+
+ case wxT('r'):
+ str2 << wxT('\r');
+ break;
+
+ case wxT('\\') :
+ // "\\" wasn't translated to "\" prior to 2.5.3.0:
+ if ( escapeBackslash )
+ {
+ str2 << wxT('\\');
+ break;
+ }
+ wxFALLTHROUGH;// else fall-through to default: branch below
+
+ default:
+ str2 << wxT('\\') << *dt;
+ break;
+ }
+ }
+ else
+ {
+ str2 << *dt;
}
}
- else
- {
- str2 << *dt;
- }
+ }
+ else // Don't escape anything in this string.
+ {
+ // We won't use str1 at all, so move its contents to str2.
+ str2.swap(str1);
}
if (m_handler->m_resource->GetFlags() & wxXRC_USE_LOCALE)
{
- if (translate && parNode &&
- parNode->GetAttribute(wxT("translate"), wxEmptyString) != wxT("0"))
+ if (!(flags & wxXRC_TEXT_NO_TRANSLATE) && node &&
+ node->GetAttribute(wxT("translate"), wxEmptyString) != wxT("0"))
{
return wxGetTranslation(str2, m_handler->m_resource->GetDomain());
}
@@ -2508,14 +2518,14 @@ void wxXmlResourceHandlerImpl::SetupWindow(wxWindow *wnd)
wnd->SetFocus();
#if wxUSE_TOOLTIPS
if (HasParam(wxT("tooltip")))
- wnd->SetToolTip(GetText(wxT("tooltip")));
+ wnd->SetToolTip(GetNodeText(GetParamNode(wxT("tooltip"))));
#endif
if (HasParam(wxT("font")))
wnd->SetFont(GetFont(wxT("font"), wnd));
if (HasParam(wxT("ownfont")))
wnd->SetOwnFont(GetFont(wxT("ownfont"), wnd));
if (HasParam(wxT("help")))
- wnd->SetHelpText(GetText(wxT("help")));
+ wnd->SetHelpText(GetNodeText(GetParamNode(wxT("help"))));
}
diff --git a/utils/wxrc/wxrc.cpp b/utils/wxrc/wxrc.cpp
index 56f4c9799f..72bfd49738 100644
--- a/utils/wxrc/wxrc.cpp
+++ b/utils/wxrc/wxrc.cpp
@@ -949,6 +949,51 @@ static wxString ConvertText(const wxString& str)
}
+enum ContentsKind
+{
+ Contents_NotTrans, // Not a translatable text at all.
+ Contents_TransOnly, // Translatable but not escaped text.
+ Contents_Text // Text, i.e. both translatable and escaped.
+};
+
+// Check if the given node contains translatable text and, if it does, whether
+// it's escaped (i.e. parsed using GetText()) or not.
+ContentsKind
+GetNodeContentsKind(wxXmlNode& node, const wxString& contents)
+{
+ if ( node.GetName() == wxT("label") ||
+ (node.GetName() == wxT("value") && !contents.IsNumber()) ||
+ node.GetName() == wxT("help") ||
+ node.GetName() == wxT("hint") ||
+ node.GetName() == wxT("longhelp") ||
+ node.GetName() == wxT("tooltip") ||
+ node.GetName() == wxT("htmlcode") ||
+ node.GetName() == wxT("title") ||
+ node.GetName() == wxT("message") ||
+ node.GetName() == wxT("note") ||
+ node.GetName() == wxT("defaultdirectory") ||
+ node.GetName() == wxT("defaultfilename") ||
+ node.GetName() == wxT("defaultfolder") ||
+ node.GetName() == wxT("filter") ||
+ node.GetName() == wxT("caption") )
+ {
+ return Contents_Text;
+ }
+
+ // This one is special: it is translated in XRC, but its contents is not
+ // escaped, except for the special case of wxRadioBox when it can be, if
+ // "label" attribute is supplied.
+ if ( node.GetName() == wxT("item") )
+ {
+ return node.GetAttribute(wxT("label"), wxT("0")) == wxT("1")
+ ? Contents_Text
+ : Contents_TransOnly;
+ }
+
+ return Contents_NotTrans;
+}
+
+
ExtractedStrings
XmlResApp::FindStrings(const wxString& filename, wxXmlNode *node)
{
@@ -963,41 +1008,26 @@ XmlResApp::FindStrings(const wxString& filename, wxXmlNode *node)
if ((node->GetType() == wxXML_ELEMENT_NODE) &&
// parent is an element, i.e. has subnodes...
(n->GetType() == wxXML_TEXT_NODE ||
- n->GetType() == wxXML_CDATA_SECTION_NODE) &&
+ n->GetType() == wxXML_CDATA_SECTION_NODE))
// ...it is textnode...
- (
- node/*not n!*/->GetName() == wxT("label") ||
- (node/*not n!*/->GetName() == wxT("value") &&
- !n->GetContent().IsNumber()) ||
- node/*not n!*/->GetName() == wxT("help") ||
- node/*not n!*/->GetName() == wxT("hint") ||
- node/*not n!*/->GetName() == wxT("longhelp") ||
- node/*not n!*/->GetName() == wxT("tooltip") ||
- node/*not n!*/->GetName() == wxT("htmlcode") ||
- node/*not n!*/->GetName() == wxT("title") ||
- node/*not n!*/->GetName() == wxT("item") ||
- node/*not n!*/->GetName() == wxT("message") ||
- node/*not n!*/->GetName() == wxT("note") ||
- node/*not n!*/->GetName() == wxT("defaultdirectory") ||
- node/*not n!*/->GetName() == wxT("defaultfilename") ||
- node/*not n!*/->GetName() == wxT("defaultfolder") ||
- node/*not n!*/->GetName() == wxT("filter") ||
- node/*not n!*/->GetName() == wxT("caption")
- ))
- // ...and known to contain translatable string
{
- if (!flagGettext ||
- node->GetAttribute(wxT("translate"), wxT("1")) != wxT("0"))
+ wxString s = n->GetContent();
+ switch ( GetNodeContentsKind(*node, s) )
{
- arr.push_back
- (
- ExtractedString
- (
- ConvertText(n->GetContent()),
- filename,
- n->GetLineNumber()
- )
- );
+ case Contents_NotTrans:
+ break;
+
+ case Contents_Text:
+ s = ConvertText(s);
+ wxFALLTHROUGH;
+
+ case Contents_TransOnly:
+ if (!flagGettext ||
+ node->GetAttribute(wxT("translate"), wxT("1")) != wxT("0"))
+ {
+ arr.push_back(ExtractedString(s, filename, n->GetLineNumber()));
+ }
+ break;
}
}