1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: XML resource compiler
4 // Author: Vaclav Slavik, Eduardo Marques <edrdo@netcabo.pt>
7 // Copyright: (c) 2000 Vaclav Slavik
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
18 // for all others, include the necessary headers
24 #include "wx/cmdline.h"
25 #include "wx/xml/xml.h"
27 #include "wx/filename.h"
28 #include "wx/wfstream.h"
30 #include "wx/hashset.h"
32 WX_DECLARE_HASH_SET(wxString
, wxStringHash
, wxStringEqual
, StringSet
);
37 XRCWidgetData(const wxString
& vname
,const wxString
& vclass
)
38 : m_class(vclass
), m_name(vname
) {}
39 const wxString
& GetName() const { return m_name
; }
40 const wxString
& GetClass() const { return m_class
; }
46 #include "wx/arrimpl.cpp"
47 WX_DECLARE_OBJARRAY(XRCWidgetData
,ArrayOfXRCWidgetData
);
48 WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData
)
54 wxString m_parentClassName
;
55 StringSet m_ancestorClassNames
;
56 ArrayOfXRCWidgetData m_wdata
;
58 void BrowseXmlNode(wxXmlNode
* node
)
65 if (node
->GetName() == _T("object")
66 && node
->GetPropVal(_T("class"),&classValue
)
67 && node
->GetPropVal(_T("name"),&nameValue
))
69 m_wdata
.Add(XRCWidgetData(nameValue
,classValue
));
71 children
= node
->GetChildren();
73 BrowseXmlNode(children
);
74 node
= node
->GetNext();
79 XRCWndClassData(const wxString
& className
,
80 const wxString
& parentClassName
,
81 const wxXmlNode
* node
) :
82 m_className(className
) , m_parentClassName(parentClassName
)
84 if ( className
== _T("wxMenu") )
86 m_ancestorClassNames
.insert(_T("wxMenu"));
87 m_ancestorClassNames
.insert(_T("wxMenuBar"));
89 else if ( className
== _T("wxMDIChildFrame") )
91 m_ancestorClassNames
.insert(_T("wxMDIParentFrame"));
93 else if( className
== _T("wxMenuBar") ||
94 className
== _T("wxStatusBar") ||
95 className
== _T("wxToolBar") )
97 m_ancestorClassNames
.insert(_T("wxFrame"));
101 m_ancestorClassNames
.insert(_T("wxWindow"));
104 BrowseXmlNode(node
->GetChildren());
107 const ArrayOfXRCWidgetData
& GetWidgetData()
112 bool CanBeUsedWithXRCCTRL(const wxString
& name
)
114 if (name
== _T("tool") ||
115 name
== _T("data") ||
116 name
== _T("unknown") ||
117 name
== _T("notebookpage") ||
118 name
== _T("separator") ||
119 name
== _T("sizeritem") ||
120 name
== _T("wxMenuBar") ||
121 name
== _T("wxMenuItem") ||
122 name
== _T("wxStaticBoxSizer") )
129 void GenerateHeaderCode(wxFFile
& file
)
132 file
.Write(_T("class ") + m_className
+ _T(" : public ") + m_parentClassName
133 + _T(" {\nprotected:\n"));
135 for(i
=0;i
<m_wdata
.GetCount();++i
)
137 const XRCWidgetData
& w
= m_wdata
.Item(i
);
138 if( !CanBeUsedWithXRCCTRL(w
.GetClass()) ) continue;
139 if( w
.GetName().Length() == 0 ) continue;
141 _T(" ") + w
.GetClass() + _T("* ") + w
.GetName()
144 file
.Write(_T("\nprivate:\n void InitWidgetsFromXRC(wxWindow *parent){\n")
145 _T(" wxXmlResource::Get()->LoadObject(this,parent,_T(\"")
150 for(i
=0;i
<m_wdata
.GetCount();++i
)
152 const XRCWidgetData
& w
= m_wdata
.Item(i
);
153 if( !CanBeUsedWithXRCCTRL(w
.GetClass()) ) continue;
154 if( w
.GetName().Length() == 0 ) continue;
157 + _T(" = XRCCTRL(*this,\"")
163 file
.Write(_T(" }\n"));
165 file
.Write( _T("public:\n"));
167 if ( m_ancestorClassNames
.size() == 1 )
173 *m_ancestorClassNames
.begin() +
174 _T(" *parent=NULL){\n") +
175 _T(" InitWidgetsFromXRC((wxWindow *)parent);\n")
182 file
.Write(m_className
+ _T("(){\n") +
183 _T(" InitWidgetsFromXRC(NULL);\n")
187 for ( StringSet::const_iterator it
= m_ancestorClassNames
.begin();
188 it
!= m_ancestorClassNames
.end();
191 file
.Write(m_className
+ _T("(") + *it
+ _T(" *parent){\n") +
192 _T(" InitWidgetsFromXRC((wxWindow *)parent);\n")
199 WX_DECLARE_OBJARRAY(XRCWndClassData
,ArrayOfXRCWndClassData
);
200 WX_DEFINE_OBJARRAY(ArrayOfXRCWndClassData
)
203 class XmlResApp
: public wxAppConsole
206 // don't use builtin cmd line parsing:
207 virtual bool OnInit() { return true; }
211 void ParseParams(const wxCmdLineParser
& cmdline
);
213 wxArrayString
PrepareTempFiles();
214 void FindFilesInXML(wxXmlNode
*node
, wxArrayString
& flist
, const wxString
& inputPath
);
216 wxString
GetInternalFileName(const wxString
& name
, const wxArrayString
& flist
);
217 void DeleteTempFiles(const wxArrayString
& flist
);
218 void MakePackageZIP(const wxArrayString
& flist
);
219 void MakePackageCPP(const wxArrayString
& flist
);
220 void MakePackagePython(const wxArrayString
& flist
);
222 void OutputGettext();
223 wxArrayString
FindStrings();
224 wxArrayString
FindStrings(wxXmlNode
*node
);
226 bool flagVerbose
, flagCPP
, flagPython
, flagGettext
;
227 wxString parOutput
, parFuncname
, parOutputPath
;
228 wxArrayString parFiles
;
231 ArrayOfXRCWndClassData aXRCWndClassData
;
236 IMPLEMENT_APP_CONSOLE(XmlResApp
)
238 int XmlResApp::OnRun()
240 static const wxCmdLineEntryDesc cmdLineDesc
[] =
242 { wxCMD_LINE_SWITCH
, _T("h"), _T("help"), _T("show help message"),
243 wxCMD_LINE_VAL_NONE
, wxCMD_LINE_OPTION_HELP
},
244 { wxCMD_LINE_SWITCH
, _T("v"), _T("verbose"), _T("be verbose"), (wxCmdLineParamType
)0, 0 },
245 { wxCMD_LINE_SWITCH
, _T("e"), _T("extra-cpp-code"), _T("output C++ header file with XRC derived classes"), (wxCmdLineParamType
)0, 0 },
246 { wxCMD_LINE_SWITCH
, _T("c"), _T("cpp-code"), _T("output C++ source rather than .rsc file"), (wxCmdLineParamType
)0, 0 },
247 { wxCMD_LINE_SWITCH
, _T("p"), _T("python-code"), _T("output wxPython source rather than .rsc file"), (wxCmdLineParamType
)0, 0 },
248 { wxCMD_LINE_SWITCH
, _T("g"), _T("gettext"), _T("output list of translatable strings (to stdout or file if -o used)"), (wxCmdLineParamType
)0, 0 },
249 { wxCMD_LINE_OPTION
, _T("n"), _T("function"), _T("C++/Python function name (with -c or -p) [InitXmlResource]"), (wxCmdLineParamType
)0, 0 },
250 { wxCMD_LINE_OPTION
, _T("o"), _T("output"), _T("output file [resource.xrs/cpp]"), (wxCmdLineParamType
)0, 0 },
251 #if 0 // not yet implemented
252 { wxCMD_LINE_OPTION
, _T("l"), _T("list-of-handlers"), _T("output list of necessary handlers to this file"), (wxCmdLineParamType
)0, 0 },
254 { wxCMD_LINE_PARAM
, NULL
, NULL
, _T("input file(s)"),
255 wxCMD_LINE_VAL_STRING
,
256 wxCMD_LINE_PARAM_MULTIPLE
| wxCMD_LINE_OPTION_MANDATORY
},
258 { wxCMD_LINE_NONE
, NULL
, NULL
, NULL
, (wxCmdLineParamType
)0, 0 }
261 wxCmdLineParser
parser(cmdLineDesc
, argc
, argv
);
263 switch (parser
.Parse())
283 void XmlResApp::ParseParams(const wxCmdLineParser
& cmdline
)
285 flagGettext
= cmdline
.Found(_T("g"));
286 flagVerbose
= cmdline
.Found(_T("v"));
287 flagCPP
= cmdline
.Found(_T("c"));
288 flagPython
= cmdline
.Found(_T("p"));
289 flagH
= flagCPP
&& cmdline
.Found(_T("e"));
292 if (!cmdline
.Found(_T("o"), &parOutput
))
295 parOutput
= wxEmptyString
;
299 parOutput
= _T("resource.cpp");
301 parOutput
= _T("resource.py");
303 parOutput
= _T("resource.xrs");
306 if (!parOutput
.empty())
308 wxFileName
fn(parOutput
);
310 parOutput
= fn
.GetFullPath();
311 parOutputPath
= wxPathOnly(parOutput
);
313 if (!parOutputPath
) parOutputPath
= _T(".");
315 if (!cmdline
.Found(_T("n"), &parFuncname
))
316 parFuncname
= _T("InitXmlResource");
318 for (size_t i
= 0; i
< cmdline
.GetParamCount(); i
++)
321 wxString fn
=wxFindFirstFile(cmdline
.GetParam(i
), wxFILE
);
328 parFiles
.Add(cmdline
.GetParam(i
));
336 void XmlResApp::CompileRes()
338 wxArrayString files
= PrepareTempFiles();
340 wxRemoveFile(parOutput
);
345 MakePackageCPP(files
);
350 MakePackagePython(files
);
352 MakePackageZIP(files
);
355 DeleteTempFiles(files
);
359 wxString
XmlResApp::GetInternalFileName(const wxString
& name
, const wxArrayString
& flist
)
361 wxString name2
= name
;
362 name2
.Replace(_T(":"), _T("_"));
363 name2
.Replace(_T("/"), _T("_"));
364 name2
.Replace(_T("\\"), _T("_"));
365 name2
.Replace(_T("*"), _T("_"));
366 name2
.Replace(_T("?"), _T("_"));
368 wxString s
= wxFileNameFromPath(parOutput
) + _T("$") + name2
;
370 if (wxFileExists(s
) && flist
.Index(s
) == wxNOT_FOUND
)
372 for (int i
= 0;; i
++)
374 s
.Printf(wxFileNameFromPath(parOutput
) + _T("$%03i-") + name2
, i
);
375 if (!wxFileExists(s
) || flist
.Index(s
) != wxNOT_FOUND
)
382 wxArrayString
XmlResApp::PrepareTempFiles()
386 for (size_t i
= 0; i
< parFiles
.GetCount(); i
++)
389 wxPrintf(_T("processing ") + parFiles
[i
] + _T("...\n"));
393 if (!doc
.Load(parFiles
[i
]))
395 wxLogError(_T("Error parsing file ") + parFiles
[i
]);
400 wxString name
, ext
, path
;
401 wxSplitPath(parFiles
[i
], &path
, &name
, &ext
);
403 FindFilesInXML(doc
.GetRoot(), flist
, path
);
406 wxXmlNode
* node
= (doc
.GetRoot())->GetChildren();
407 wxString classValue
,nameValue
;
409 if(node
->GetName() == _T("object")
410 && node
->GetPropVal(_T("class"),&classValue
)
411 && node
->GetPropVal(_T("name"),&nameValue
)){
413 aXRCWndClassData
.Add(
414 XRCWndClassData(nameValue
,classValue
,node
)
417 node
= node
-> GetNext();
420 wxString internalName
= GetInternalFileName(parFiles
[i
], flist
);
422 doc
.Save(parOutputPath
+ wxFILE_SEP_PATH
+ internalName
);
423 flist
.Add(internalName
);
430 // Does 'node' contain filename information at all?
431 static bool NodeContainsFilename(wxXmlNode
*node
)
433 const wxString name
= node
->GetName();
435 // Any bitmaps (bitmap2 is used for disabled toolbar buttons):
436 if ( name
== _T("bitmap") || name
== _T("bitmap2") )
439 if ( name
== _T("icon") )
442 // URLs in wxHtmlWindow:
443 if ( name
== _T("url") )
447 wxXmlNode
*parent
= node
->GetParent();
448 if (parent
!= NULL
&&
449 parent
->GetPropVal(_T("class"), _T("")) == _T("wxBitmapButton") &&
450 (name
== _T("focus") ||
451 name
== _T("disabled") ||
452 name
== _T("selected")))
455 // wxBitmap or wxIcon toplevel resources:
456 if ( name
== _T("object") )
458 wxString klass
= node
->GetPropVal(_T("class"), wxEmptyString
);
459 if (klass
== _T("wxBitmap") ||
460 klass
== _T("wxIcon") ||
461 klass
== _T("data") )
468 // find all files mentioned in structure, e.g. <bitmap>filename</bitmap>
469 void XmlResApp::FindFilesInXML(wxXmlNode
*node
, wxArrayString
& flist
, const wxString
& inputPath
)
471 // Is 'node' XML node element?
472 if (node
== NULL
) return;
473 if (node
->GetType() != wxXML_ELEMENT_NODE
) return;
475 bool containsFilename
= NodeContainsFilename(node
);
477 wxXmlNode
*n
= node
->GetChildren();
480 if (containsFilename
&&
481 (n
->GetType() == wxXML_TEXT_NODE
||
482 n
->GetType() == wxXML_CDATA_SECTION_NODE
))
485 if (wxIsAbsolutePath(n
->GetContent()) || inputPath
.empty())
486 fullname
= n
->GetContent();
488 fullname
= inputPath
+ wxFILE_SEP_PATH
+ n
->GetContent();
491 wxPrintf(_T("adding ") + fullname
+ _T("...\n"));
493 wxString filename
= GetInternalFileName(n
->GetContent(), flist
);
494 n
->SetContent(filename
);
496 if (flist
.Index(filename
) == wxNOT_FOUND
)
499 wxFileInputStream
sin(fullname
);
500 wxFileOutputStream
sout(parOutputPath
+ wxFILE_SEP_PATH
+ filename
);
501 sin
.Read(sout
); // copy the stream
505 if (n
->GetType() == wxXML_ELEMENT_NODE
)
506 FindFilesInXML(n
, flist
, inputPath
);
514 void XmlResApp::DeleteTempFiles(const wxArrayString
& flist
)
516 for (size_t i
= 0; i
< flist
.GetCount(); i
++)
517 wxRemoveFile(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
]);
522 void XmlResApp::MakePackageZIP(const wxArrayString
& flist
)
526 for (size_t i
= 0; i
< flist
.GetCount(); i
++)
527 files
+= flist
[i
] + _T(" ");
531 wxPrintf(_T("compressing ") + parOutput
+ _T("...\n"));
533 wxString cwd
= wxGetCwd();
534 wxSetWorkingDirectory(parOutputPath
);
535 int execres
= wxExecute(_T("zip -9 -j ") +
536 wxString(flagVerbose
? _T("\"") : _T("-q \"")) +
537 parOutput
+ _T("\" ") + files
, true);
538 wxSetWorkingDirectory(cwd
);
541 wxLogError(_T("Unable to execute zip program. Make sure it is in the path."));
542 wxLogError(_T("You can download it at http://www.cdrom.com/pub/infozip/"));
550 static wxString
FileToCppArray(wxString filename
, int num
)
555 wxFFile
file(filename
, wxT("rb"));
556 wxFileOffset offset
= file
.Length();
557 wxASSERT_MSG( offset
>= 0 , wxT("Invalid file length") );
559 const size_t lng
= wx_truncate_cast(size_t, offset
);
560 wxASSERT_MSG( lng
== offset
, wxT("Huge file not supported") );
562 snum
.Printf(_T("%i"), num
);
563 output
.Printf(_T("static size_t xml_res_size_") + snum
+ _T(" = %i;\n"), lng
);
564 output
+= _T("static unsigned char xml_res_file_") + snum
+ _T("[] = {\n");
565 // we cannot use string literals because MSVC is dumb wannabe compiler
566 // with arbitrary limitation to 2048 strings :(
568 unsigned char *buffer
= new unsigned char[lng
];
569 file
.Read(buffer
, lng
);
571 for (size_t i
= 0, linelng
= 0; i
< lng
; i
++)
573 tmp
.Printf(_T("%i"), buffer
[i
]);
574 if (i
!= 0) output
<< _T(',');
581 linelng
+= tmp
.Length()+1;
586 output
+= _T("};\n\n");
592 void XmlResApp::MakePackageCPP(const wxArrayString
& flist
)
594 wxFFile
file(parOutput
, wxT("wt"));
598 wxPrintf(_T("creating C++ source file ") + parOutput
+ _T("...\n"));
602 _T("// This file was automatically generated by wxrc, do not edit by hand.\n")
604 _T("#include <wx/wxprec.h>\n")
606 _T("#ifdef __BORLANDC__\n")
607 _T(" #pragma hdrstop\n")
611 _T("#include <wx/filesys.h>\n")
612 _T("#include <wx/fs_mem.h>\n")
613 _T("#include <wx/xrc/xmlres.h>\n")
614 _T("#include <wx/xrc/xh_all.h>\n")
617 for (i
= 0; i
< flist
.GetCount(); i
++)
619 FileToCppArray(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
], i
));
622 _T("void ") + parFuncname
+ wxT("()\n")
625 _T(" // Check for memory FS. If not present, load the handler:\n")
627 _T(" wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/dummy_file\"), wxT(\"dummy one\"));\n")
628 _T(" wxFileSystem fsys;\n")
629 _T(" wxFSFile *f = fsys.OpenFile(wxT(\"memory:XRC_resource/dummy_file\"));\n")
630 _T(" wxMemoryFSHandler::RemoveFile(wxT(\"XRC_resource/dummy_file\"));\n")
631 _T(" if (f) delete f;\n")
632 _T(" else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n")
636 for (i
= 0; i
< flist
.GetCount(); i
++)
639 s
.Printf(_T(" wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/") + flist
[i
] +
640 _T("\"), xml_res_file_%i, xml_res_size_%i);\n"), i
, i
);
644 for (i
= 0; i
< parFiles
.GetCount(); i
++)
646 file
.Write(_T(" wxXmlResource::Get()->Load(wxT(\"memory:XRC_resource/") +
647 GetInternalFileName(parFiles
[i
], flist
) + _T("\"));\n"));
650 file
.Write(_T("}\n"));
655 void XmlResApp::GenCPPHeader()
657 wxString fileSpec
= ((parOutput
.BeforeLast('.')).AfterLast('/')).AfterLast('\\');
658 wxString heaFileName
= fileSpec
+ _T(".h");
660 wxFFile
file(heaFileName
, wxT("wt"));
663 _T("// This file was automatically generated by wxrc, do not edit by hand.\n")
665 _T("#ifndef __") + fileSpec
+ _T("_h__\n")
666 _T("#define __") + fileSpec
+ _T("_h__\n")
668 for(size_t i
=0;i
<aXRCWndClassData
.GetCount();++i
){
669 aXRCWndClassData
.Item(i
).GenerateHeaderCode(file
);
674 + _T("();\n#endif\n"));
677 static wxString
FileToPythonArray(wxString filename
, int num
)
682 wxFFile
file(filename
, wxT("rb"));
683 wxFileOffset offset
= file
.Length();
684 wxASSERT_MSG( offset
>= 0 , wxT("Invalid file length") );
686 const size_t lng
= wx_truncate_cast(size_t, offset
);
687 wxASSERT_MSG( offset
== lng
, wxT("Huge file not supported") );
689 snum
.Printf(_T("%i"), num
);
690 output
= _T(" xml_res_file_") + snum
+ _T(" = '''\\\n");
692 unsigned char *buffer
= new unsigned char[lng
];
693 file
.Read(buffer
, lng
);
695 for (size_t i
= 0, linelng
= 0; i
< lng
; i
++)
697 unsigned char c
= buffer
[i
];
703 else if (c
< 32 || c
> 127 || c
== '\'')
704 tmp
.Printf(_T("\\x%02x"), c
);
712 output
<< _T("\\\n");
715 linelng
+= tmp
.Length();
720 output
+= _T("'''\n\n");
726 void XmlResApp::MakePackagePython(const wxArrayString
& flist
)
728 wxFFile
file(parOutput
, wxT("wt"));
732 wxPrintf(_T("creating Python source file ") + parOutput
+ _T("...\n"));
736 _T("# This file was automatically generated by wxrc, do not edit by hand.\n")
739 _T("import wx.xrc\n\n")
743 file
.Write(_T("def ") + parFuncname
+ _T("():\n"));
745 for (i
= 0; i
< flist
.GetCount(); i
++)
747 FileToPythonArray(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
], i
));
750 _T(" # check if the memory filesystem handler has been loaded yet, and load it if not\n")
751 _T(" wx.MemoryFSHandler.AddFile('XRC_resource/dummy_file', 'dummy value')\n")
752 _T(" fsys = wx.FileSystem()\n")
753 _T(" f = fsys.OpenFile('memory:XRC_resource/dummy_file')\n")
754 _T(" wx.MemoryFSHandler.RemoveFile('XRC_resource/dummy_file')\n")
755 _T(" if f is not None:\n")
758 _T(" wx.FileSystem.AddHandler(wx.MemoryFSHandler())\n")
760 _T(" # load all the strings as memory files and load into XmlRes\n")
764 for (i
= 0; i
< flist
.GetCount(); i
++)
767 s
.Printf(_T(" wx.MemoryFSHandler.AddFile('XRC_resource/") + flist
[i
] +
768 _T("', xml_res_file_%i)\n"), i
);
771 for (i
= 0; i
< parFiles
.GetCount(); i
++)
773 file
.Write(_T(" wx.xrc.XmlResource.Get().Load('memory:XRC_resource/") +
774 GetInternalFileName(parFiles
[i
], flist
) + _T("')\n"));
777 file
.Write(_T("\n"));
782 void XmlResApp::OutputGettext()
784 wxArrayString str
= FindStrings();
787 if (parOutput
.empty())
790 fout
.Open(parOutput
, wxT("wt"));
792 for (size_t i
= 0; i
< str
.GetCount(); i
++)
793 fout
.Write(_T("_(\"") + str
[i
] + _T("\");\n"));
795 if (!parOutput
) fout
.Detach();
800 wxArrayString
XmlResApp::FindStrings()
802 wxArrayString arr
, a2
;
804 for (size_t i
= 0; i
< parFiles
.GetCount(); i
++)
807 wxPrintf(_T("processing ") + parFiles
[i
] + _T("...\n"));
810 if (!doc
.Load(parFiles
[i
]))
812 wxLogError(_T("Error parsing file ") + parFiles
[i
]);
816 a2
= FindStrings(doc
.GetRoot());
817 WX_APPEND_ARRAY(arr
, a2
);
825 static wxString
ConvertText(const wxString
& str
)
830 for (dt
= str
.c_str(); *dt
; dt
++)
834 if ( *(++dt
) == wxT('_') )
837 str2
<< wxT('&') << *dt
;
843 case wxT('\n') : str2
<< wxT("\\n"); break;
844 case wxT('\t') : str2
<< wxT("\\t"); break;
845 case wxT('\r') : str2
<< wxT("\\r"); break;
846 case wxT('\\') : if ((*(dt
+1) != 'n') &&
853 case wxT('"') : str2
<< wxT("\\\""); break;
854 default : str2
<< *dt
; break;
863 wxArrayString
XmlResApp::FindStrings(wxXmlNode
*node
)
868 if (n
== NULL
) return arr
;
869 n
= n
->GetChildren();
873 if ((node
->GetType() == wxXML_ELEMENT_NODE
) &&
874 // parent is an element, i.e. has subnodes...
875 (n
->GetType() == wxXML_TEXT_NODE
||
876 n
->GetType() == wxXML_CDATA_SECTION_NODE
) &&
877 // ...it is textnode...
879 node
/*not n!*/->GetName() == _T("label") ||
880 (node
/*not n!*/->GetName() == _T("value") &&
881 !n
->GetContent().IsNumber()) ||
882 node
/*not n!*/->GetName() == _T("help") ||
883 node
/*not n!*/->GetName() == _T("longhelp") ||
884 node
/*not n!*/->GetName() == _T("tooltip") ||
885 node
/*not n!*/->GetName() == _T("htmlcode") ||
886 node
/*not n!*/->GetName() == _T("title") ||
887 node
/*not n!*/->GetName() == _T("item")
889 // ...and known to contain translatable string
892 node
->GetPropVal(_T("translate"), _T("1")) != _T("0"))
894 arr
.Add(ConvertText(n
->GetContent()));
899 if (n
->GetType() == wxXML_ELEMENT_NODE
)
901 wxArrayString a2
= FindStrings(n
);
902 WX_APPEND_ARRAY(arr
, a2
);