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 - + @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 - + 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; } }