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
22 #include "wx/wxcrtvararg.h"
25 #include "wx/cmdline.h"
26 #include "wx/xml/xml.h"
28 #include "wx/filename.h"
29 #include "wx/wfstream.h"
31 #include "wx/hashset.h"
32 #include "wx/mimetype.h"
33 #include "wx/vector.h"
35 WX_DECLARE_HASH_SET(wxString
, wxStringHash
, wxStringEqual
, StringSet
);
40 XRCWidgetData(const wxString
& vname
,const wxString
& vclass
)
41 : m_class(vclass
), m_name(vname
) {}
42 const wxString
& GetName() const { return m_name
; }
43 const wxString
& GetClass() const { return m_class
; }
49 #include "wx/arrimpl.cpp"
50 WX_DECLARE_OBJARRAY(XRCWidgetData
,ArrayOfXRCWidgetData
);
51 WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData
)
57 wxString m_parentClassName
;
58 StringSet m_ancestorClassNames
;
59 ArrayOfXRCWidgetData m_wdata
;
61 void BrowseXmlNode(wxXmlNode
* node
)
68 if (node
->GetName() == wxT("object")
69 && node
->GetAttribute(wxT("class"),&classValue
)
70 && node
->GetAttribute(wxT("name"),&nameValue
))
72 m_wdata
.Add(XRCWidgetData(nameValue
,classValue
));
74 children
= node
->GetChildren();
76 BrowseXmlNode(children
);
77 node
= node
->GetNext();
82 XRCWndClassData(const wxString
& className
,
83 const wxString
& parentClassName
,
84 const wxXmlNode
* node
) :
85 m_className(className
) , m_parentClassName(parentClassName
)
87 if ( className
== wxT("wxMenu") )
89 m_ancestorClassNames
.insert(wxT("wxMenu"));
90 m_ancestorClassNames
.insert(wxT("wxMenuBar"));
92 else if ( className
== wxT("wxMDIChildFrame") )
94 m_ancestorClassNames
.insert(wxT("wxMDIParentFrame"));
96 else if( className
== wxT("wxMenuBar") ||
97 className
== wxT("wxStatusBar") ||
98 className
== wxT("wxToolBar") )
100 m_ancestorClassNames
.insert(wxT("wxFrame"));
104 m_ancestorClassNames
.insert(wxT("wxWindow"));
107 BrowseXmlNode(node
->GetChildren());
110 const ArrayOfXRCWidgetData
& GetWidgetData()
115 bool CanBeUsedWithXRCCTRL(const wxString
& name
)
117 if (name
== wxT("tool") ||
118 name
== wxT("data") ||
119 name
== wxT("unknown") ||
120 name
== wxT("notebookpage") ||
121 name
== wxT("separator") ||
122 name
== wxT("sizeritem") ||
123 name
== wxT("wxMenu") ||
124 name
== wxT("wxMenuBar") ||
125 name
== wxT("wxMenuItem") ||
126 name
.EndsWith(wxT("Sizer")) )
133 void GenerateHeaderCode(wxFFile
& file
)
136 file
.Write(wxT("class ") + m_className
+ wxT(" : public ") + m_parentClassName
137 + wxT(" {\nprotected:\n"));
139 for(i
=0;i
<m_wdata
.GetCount();++i
)
141 const XRCWidgetData
& w
= m_wdata
.Item(i
);
142 if( !CanBeUsedWithXRCCTRL(w
.GetClass()) ) continue;
143 if( w
.GetName().empty() ) continue;
145 wxT(" ") + w
.GetClass() + wxT("* ") + w
.GetName()
148 file
.Write(wxT("\nprivate:\n void InitWidgetsFromXRC(wxWindow *parent){\n")
149 wxT(" wxXmlResource::Get()->LoadObject(this,parent,wxT(\"")
154 for(i
=0;i
<m_wdata
.GetCount();++i
)
156 const XRCWidgetData
& w
= m_wdata
.Item(i
);
157 if( !CanBeUsedWithXRCCTRL(w
.GetClass()) ) continue;
158 if( w
.GetName().empty() ) continue;
161 + wxT(" = XRCCTRL(*this,\"")
167 file
.Write(wxT(" }\n"));
169 file
.Write( wxT("public:\n"));
171 if ( m_ancestorClassNames
.size() == 1 )
177 *m_ancestorClassNames
.begin() +
178 wxT(" *parent=NULL){\n") +
179 wxT(" InitWidgetsFromXRC((wxWindow *)parent);\n")
186 file
.Write(m_className
+ wxT("(){\n") +
187 wxT(" InitWidgetsFromXRC(NULL);\n")
191 for ( StringSet::const_iterator it
= m_ancestorClassNames
.begin();
192 it
!= m_ancestorClassNames
.end();
195 file
.Write(m_className
+ wxT("(") + *it
+ wxT(" *parent){\n") +
196 wxT(" InitWidgetsFromXRC((wxWindow *)parent);\n")
203 WX_DECLARE_OBJARRAY(XRCWndClassData
,ArrayOfXRCWndClassData
);
204 WX_DEFINE_OBJARRAY(ArrayOfXRCWndClassData
)
206 struct ExtractedString
208 ExtractedString() : lineNo(-1) {}
209 ExtractedString(const wxString
& str_
,
210 const wxString
& filename_
, int lineNo_
)
211 : str(str_
), filename(filename_
), lineNo(lineNo_
)
220 typedef wxVector
<ExtractedString
> ExtractedStrings
;
223 class XmlResApp
: public wxAppConsole
226 // don't use builtin cmd line parsing:
227 virtual bool OnInit() { return true; }
231 void ParseParams(const wxCmdLineParser
& cmdline
);
233 wxArrayString
PrepareTempFiles();
234 void FindFilesInXML(wxXmlNode
*node
, wxArrayString
& flist
, const wxString
& inputPath
);
236 wxString
GetInternalFileName(const wxString
& name
, const wxArrayString
& flist
);
237 void DeleteTempFiles(const wxArrayString
& flist
);
238 void MakePackageZIP(const wxArrayString
& flist
);
239 void MakePackageCPP(const wxArrayString
& flist
);
240 void MakePackagePython(const wxArrayString
& flist
);
242 void OutputGettext();
243 ExtractedStrings
FindStrings();
244 ExtractedStrings
FindStrings(const wxString
& filename
, wxXmlNode
*node
);
246 bool flagVerbose
, flagCPP
, flagPython
, flagGettext
;
247 wxString parOutput
, parFuncname
, parOutputPath
;
248 wxArrayString parFiles
;
251 ArrayOfXRCWndClassData aXRCWndClassData
;
256 IMPLEMENT_APP_CONSOLE(XmlResApp
)
258 int XmlResApp::OnRun()
260 static const wxCmdLineEntryDesc cmdLineDesc
[] =
262 { wxCMD_LINE_SWITCH
, "h", "help", "show help message", wxCMD_LINE_VAL_NONE
, wxCMD_LINE_OPTION_HELP
},
263 { wxCMD_LINE_SWITCH
, "v", "verbose", "be verbose" },
264 { wxCMD_LINE_SWITCH
, "e", "extra-cpp-code", "output C++ header file with XRC derived classes" },
265 { wxCMD_LINE_SWITCH
, "c", "cpp-code", "output C++ source rather than .rsc file" },
266 { wxCMD_LINE_SWITCH
, "p", "python-code", "output wxPython source rather than .rsc file" },
267 { wxCMD_LINE_SWITCH
, "g", "gettext", "output list of translatable strings (to stdout or file if -o used)" },
268 { wxCMD_LINE_OPTION
, "n", "function", "C++/Python function name (with -c or -p) [InitXmlResource]" },
269 { wxCMD_LINE_OPTION
, "o", "output", "output file [resource.xrs/cpp]" },
270 #if 0 // not yet implemented
271 { wxCMD_LINE_OPTION
, "l", "list-of-handlers", "output list of necessary handlers to this file" },
273 { wxCMD_LINE_PARAM
, NULL
, NULL
, "input file(s)",
274 wxCMD_LINE_VAL_STRING
,
275 wxCMD_LINE_PARAM_MULTIPLE
| wxCMD_LINE_OPTION_MANDATORY
},
280 wxCmdLineParser
parser(cmdLineDesc
, argc
, argv
);
282 switch (parser
.Parse())
302 void XmlResApp::ParseParams(const wxCmdLineParser
& cmdline
)
304 flagGettext
= cmdline
.Found("g");
305 flagVerbose
= cmdline
.Found("v");
306 flagCPP
= cmdline
.Found("c");
307 flagPython
= cmdline
.Found("p");
308 flagH
= flagCPP
&& cmdline
.Found("e");
311 if (!cmdline
.Found("o", &parOutput
))
314 parOutput
= wxEmptyString
;
318 parOutput
= wxT("resource.cpp");
320 parOutput
= wxT("resource.py");
322 parOutput
= wxT("resource.xrs");
325 if (!parOutput
.empty())
327 wxFileName
fn(parOutput
);
329 parOutput
= fn
.GetFullPath();
330 parOutputPath
= wxPathOnly(parOutput
);
332 if (!parOutputPath
) parOutputPath
= wxT(".");
334 if (!cmdline
.Found("n", &parFuncname
))
335 parFuncname
= wxT("InitXmlResource");
337 for (size_t i
= 0; i
< cmdline
.GetParamCount(); i
++)
340 wxString fn
=wxFindFirstFile(cmdline
.GetParam(i
), wxFILE
);
347 parFiles
.Add(cmdline
.GetParam(i
));
355 void XmlResApp::CompileRes()
357 wxArrayString files
= PrepareTempFiles();
359 if ( wxFileExists(parOutput
) )
360 wxRemoveFile(parOutput
);
365 MakePackageCPP(files
);
370 MakePackagePython(files
);
372 MakePackageZIP(files
);
375 DeleteTempFiles(files
);
379 wxString
XmlResApp::GetInternalFileName(const wxString
& name
, const wxArrayString
& flist
)
381 wxString name2
= name
;
382 name2
.Replace(wxT(":"), wxT("_"));
383 name2
.Replace(wxT("/"), wxT("_"));
384 name2
.Replace(wxT("\\"), wxT("_"));
385 name2
.Replace(wxT("*"), wxT("_"));
386 name2
.Replace(wxT("?"), wxT("_"));
388 wxString s
= wxFileNameFromPath(parOutput
) + wxT("$") + name2
;
390 if (wxFileExists(s
) && flist
.Index(s
) == wxNOT_FOUND
)
392 for (int i
= 0;; i
++)
394 s
.Printf(wxFileNameFromPath(parOutput
) + wxT("$%03i-") + name2
, i
);
395 if (!wxFileExists(s
) || flist
.Index(s
) != wxNOT_FOUND
)
402 wxArrayString
XmlResApp::PrepareTempFiles()
406 for (size_t i
= 0; i
< parFiles
.GetCount(); i
++)
409 wxPrintf(wxT("processing ") + parFiles
[i
] + wxT("...\n"));
413 if (!doc
.Load(parFiles
[i
]))
415 wxLogError(wxT("Error parsing file ") + parFiles
[i
]);
420 wxString name
, ext
, path
;
421 wxFileName::SplitPath(parFiles
[i
], &path
, &name
, &ext
);
423 FindFilesInXML(doc
.GetRoot(), flist
, path
);
426 wxXmlNode
* node
= (doc
.GetRoot())->GetChildren();
427 wxString classValue
,nameValue
;
429 if(node
->GetName() == wxT("object")
430 && node
->GetAttribute(wxT("class"),&classValue
)
431 && node
->GetAttribute(wxT("name"),&nameValue
)){
433 aXRCWndClassData
.Add(
434 XRCWndClassData(nameValue
,classValue
,node
)
437 node
= node
-> GetNext();
440 wxString internalName
= GetInternalFileName(parFiles
[i
], flist
);
442 doc
.Save(parOutputPath
+ wxFILE_SEP_PATH
+ internalName
);
443 flist
.Add(internalName
);
450 // Does 'node' contain filename information at all?
451 static bool NodeContainsFilename(wxXmlNode
*node
)
453 const wxString name
= node
->GetName();
455 // Any bitmaps (bitmap2 is used for disabled toolbar buttons):
456 if ( name
== wxT("bitmap") || name
== wxT("bitmap2") )
459 if ( name
== wxT("icon") )
463 wxXmlNode
*parent
= node
->GetParent();
464 if (parent
!= NULL
&&
465 parent
->GetAttribute(wxT("class"), wxT("")) == wxT("wxBitmapButton") &&
466 (name
== wxT("focus") ||
467 name
== wxT("disabled") ||
468 name
== wxT("hover") ||
469 name
== wxT("selected")))
472 // wxBitmap or wxIcon toplevel resources:
473 if ( name
== wxT("object") )
475 wxString klass
= node
->GetAttribute(wxT("class"), wxEmptyString
);
476 if (klass
== wxT("wxBitmap") ||
477 klass
== wxT("wxIcon") ||
478 klass
== wxT("data") )
482 // URLs in wxHtmlWindow:
483 if ( name
== wxT("url") &&
485 parent
->GetAttribute(wxT("class"), wxT("")) == wxT("wxHtmlWindow") )
487 // FIXME: this is wrong for e.g. http:// URLs
494 // find all files mentioned in structure, e.g. <bitmap>filename</bitmap>
495 void XmlResApp::FindFilesInXML(wxXmlNode
*node
, wxArrayString
& flist
, const wxString
& inputPath
)
497 // Is 'node' XML node element?
498 if (node
== NULL
) return;
499 if (node
->GetType() != wxXML_ELEMENT_NODE
) return;
501 bool containsFilename
= NodeContainsFilename(node
);
503 wxXmlNode
*n
= node
->GetChildren();
506 if (containsFilename
&&
507 (n
->GetType() == wxXML_TEXT_NODE
||
508 n
->GetType() == wxXML_CDATA_SECTION_NODE
))
511 if (wxIsAbsolutePath(n
->GetContent()) || inputPath
.empty())
512 fullname
= n
->GetContent();
514 fullname
= inputPath
+ wxFILE_SEP_PATH
+ n
->GetContent();
517 wxPrintf(wxT("adding ") + fullname
+ wxT("...\n"));
519 wxString filename
= GetInternalFileName(n
->GetContent(), flist
);
520 n
->SetContent(filename
);
522 if (flist
.Index(filename
) == wxNOT_FOUND
)
525 wxFileInputStream
sin(fullname
);
526 wxFileOutputStream
sout(parOutputPath
+ wxFILE_SEP_PATH
+ filename
);
527 sin
.Read(sout
); // copy the stream
531 if (n
->GetType() == wxXML_ELEMENT_NODE
)
532 FindFilesInXML(n
, flist
, inputPath
);
540 void XmlResApp::DeleteTempFiles(const wxArrayString
& flist
)
542 for (size_t i
= 0; i
< flist
.GetCount(); i
++)
543 wxRemoveFile(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
]);
548 void XmlResApp::MakePackageZIP(const wxArrayString
& flist
)
552 for (size_t i
= 0; i
< flist
.GetCount(); i
++)
553 files
+= flist
[i
] + wxT(" ");
557 wxPrintf(wxT("compressing ") + parOutput
+ wxT("...\n"));
559 wxString cwd
= wxGetCwd();
560 wxSetWorkingDirectory(parOutputPath
);
561 int execres
= wxExecute(wxT("zip -9 -j ") +
562 wxString(flagVerbose
? wxT("\"") : wxT("-q \"")) +
563 parOutput
+ wxT("\" ") + files
, true);
564 wxSetWorkingDirectory(cwd
);
567 wxLogError(wxT("Unable to execute zip program. Make sure it is in the path."));
568 wxLogError(wxT("You can download it at http://www.cdrom.com/pub/infozip/"));
576 static wxString
FileToCppArray(wxString filename
, int num
)
581 wxFFile
file(filename
, wxT("rb"));
582 wxFileOffset offset
= file
.Length();
583 wxASSERT_MSG( offset
>= 0 , wxT("Invalid file length") );
585 const size_t lng
= wx_truncate_cast(size_t, offset
);
586 wxASSERT_MSG( static_cast<wxFileOffset
>(lng
) == offset
,
587 wxT("Huge file not supported") );
589 snum
.Printf(wxT("%i"), num
);
590 output
.Printf(wxT("static size_t xml_res_size_") + snum
+ wxT(" = %lu;\n"),
591 static_cast<unsigned long>(lng
));
592 output
+= wxT("static unsigned char xml_res_file_") + snum
+ wxT("[] = {\n");
593 // we cannot use string literals because MSVC is dumb wannabe compiler
594 // with arbitrary limitation to 2048 strings :(
596 unsigned char *buffer
= new unsigned char[lng
];
597 file
.Read(buffer
, lng
);
599 for (size_t i
= 0, linelng
= 0; i
< lng
; i
++)
601 tmp
.Printf(wxT("%i"), buffer
[i
]);
602 if (i
!= 0) output
<< wxT(',');
609 linelng
+= tmp
.Length()+1;
614 output
+= wxT("};\n\n");
620 void XmlResApp::MakePackageCPP(const wxArrayString
& flist
)
622 wxFFile
file(parOutput
, wxT("wt"));
626 wxPrintf(wxT("creating C++ source file ") + parOutput
+ wxT("...\n"));
630 "// This file was automatically generated by wxrc, do not edit by hand.\n"
632 "#include <wx/wxprec.h>\n"
634 "#ifdef __BORLANDC__\n"
639 "#include <wx/filesys.h>\n"
640 "#include <wx/fs_mem.h>\n"
641 "#include <wx/xrc/xmlres.h>\n"
642 "#include <wx/xrc/xh_all.h>\n"
644 "#if wxCHECK_VERSION(2,8,5) && wxABI_VERSION >= 20805\n"
645 " #define XRC_ADD_FILE(name, data, size, mime) \\\n"
646 " wxMemoryFSHandler::AddFileWithMimeType(name, data, size, mime)\n"
648 " #define XRC_ADD_FILE(name, data, size, mime) \\\n"
649 " wxMemoryFSHandler::AddFile(name, data, size)\n"
653 for (i
= 0; i
< flist
.GetCount(); i
++)
655 FileToCppArray(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
], i
));
658 "void " + parFuncname
+ "()\n"
661 " // Check for memory FS. If not present, load the handler:\n"
663 " wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/dummy_file\"), wxT(\"dummy one\"));\n"
664 " wxFileSystem fsys;\n"
665 " wxFSFile *f = fsys.OpenFile(wxT(\"memory:XRC_resource/dummy_file\"));\n"
666 " wxMemoryFSHandler::RemoveFile(wxT(\"XRC_resource/dummy_file\"));\n"
667 " if (f) delete f;\n"
668 " else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n"
672 for (i
= 0; i
< flist
.GetCount(); i
++)
677 wxString ext
= wxFileName(flist
[i
]).GetExt();
678 if ( ext
.Lower() == wxT("xrc") )
679 mime
= wxT("text/xml");
683 wxFileType
*ft
= wxTheMimeTypesManager
->GetFileTypeFromExtension(ext
);
686 ft
->GetMimeType(&mime
);
690 #endif // wxUSE_MIMETYPE
692 s
.Printf(" XRC_ADD_FILE(wxT(\"XRC_resource/" + flist
[i
] +
693 "\"), xml_res_file_%u, xml_res_size_%u, wxT(\"%s\"));\n",
698 for (i
= 0; i
< parFiles
.GetCount(); i
++)
700 file
.Write(" wxXmlResource::Get()->Load(wxT(\"memory:XRC_resource/" +
701 GetInternalFileName(parFiles
[i
], flist
) + "\"));\n");
709 void XmlResApp::GenCPPHeader()
711 // Generate the output header in the same directory as the source file.
712 wxFileName
headerName(parOutput
);
713 headerName
.SetExt("h");
715 wxFFile
file(headerName
.GetFullPath(), wxT("wt"));
718 "// This file was automatically generated by wxrc, do not edit by hand.\n"
720 "#ifndef __" + headerName
.GetName() + "_h__\n"
721 "#define __" + headerName
.GetName() + "_h__\n"
723 for(size_t i
=0;i
<aXRCWndClassData
.GetCount();++i
){
724 aXRCWndClassData
.Item(i
).GenerateHeaderCode(file
);
732 static wxString
FileToPythonArray(wxString filename
, int num
)
737 wxFFile
file(filename
, wxT("rb"));
738 wxFileOffset offset
= file
.Length();
739 wxASSERT_MSG( offset
>= 0 , wxT("Invalid file length") );
741 const size_t lng
= wx_truncate_cast(size_t, offset
);
742 wxASSERT_MSG( static_cast<wxFileOffset
>(lng
) == offset
,
743 wxT("Huge file not supported") );
745 snum
.Printf(wxT("%i"), num
);
746 output
= " xml_res_file_" + snum
+ " = '''\\\n";
748 unsigned char *buffer
= new unsigned char[lng
];
749 file
.Read(buffer
, lng
);
751 for (size_t i
= 0, linelng
= 0; i
< lng
; i
++)
753 unsigned char c
= buffer
[i
];
759 else if (c
< 32 || c
> 127 || c
== '\'')
760 tmp
.Printf(wxT("\\x%02x"), c
);
768 output
<< wxT("\\\n");
771 linelng
+= tmp
.Length();
776 output
+= wxT("'''\n\n");
782 void XmlResApp::MakePackagePython(const wxArrayString
& flist
)
784 wxFFile
file(parOutput
, wxT("wt"));
788 wxPrintf(wxT("creating Python source file ") + parOutput
+ wxT("...\n"));
792 "# This file was automatically generated by wxrc, do not edit by hand.\n"
799 file
.Write("def " + parFuncname
+ "():\n");
801 for (i
= 0; i
< flist
.GetCount(); i
++)
803 FileToPythonArray(parOutputPath
+ wxFILE_SEP_PATH
+ flist
[i
], i
));
806 " # check if the memory filesystem handler has been loaded yet, and load it if not\n"
807 " wx.MemoryFSHandler.AddFile('XRC_resource/dummy_file', 'dummy value')\n"
808 " fsys = wx.FileSystem()\n"
809 " f = fsys.OpenFile('memory:XRC_resource/dummy_file')\n"
810 " wx.MemoryFSHandler.RemoveFile('XRC_resource/dummy_file')\n"
811 " if f is not None:\n"
814 " wx.FileSystem.AddHandler(wx.MemoryFSHandler())\n"
816 " # load all the strings as memory files and load into XmlRes\n"
820 for (i
= 0; i
< flist
.GetCount(); i
++)
823 s
.Printf(" wx.MemoryFSHandler.AddFile('XRC_resource/" + flist
[i
] +
824 "', xml_res_file_%u)\n", i
);
827 for (i
= 0; i
< parFiles
.GetCount(); i
++)
829 file
.Write(" wx.xrc.XmlResource.Get().Load('memory:XRC_resource/" +
830 GetInternalFileName(parFiles
[i
], flist
) + "')\n");
838 void XmlResApp::OutputGettext()
840 ExtractedStrings str
= FindStrings();
843 if (parOutput
.empty())
846 fout
.Open(parOutput
, wxT("wt"));
848 for (ExtractedStrings::const_iterator i
= str
.begin(); i
!= str
.end(); ++i
)
850 const wxFileName
filename(i
->filename
);
853 s
.Printf("#line %d \"%s\"\n",
854 i
->lineNo
, filename
.GetFullPath(wxPATH_UNIX
));
857 fout
.Write("_(\"" + i
->str
+ "\");\n");
860 if (!parOutput
) fout
.Detach();
865 ExtractedStrings
XmlResApp::FindStrings()
867 ExtractedStrings arr
, a2
;
869 for (size_t i
= 0; i
< parFiles
.GetCount(); i
++)
872 wxPrintf(wxT("processing ") + parFiles
[i
] + wxT("...\n"));
875 if (!doc
.Load(parFiles
[i
]))
877 wxLogError(wxT("Error parsing file ") + parFiles
[i
]);
881 a2
= FindStrings(parFiles
[i
], doc
.GetRoot());
883 WX_APPEND_ARRAY(arr
, a2
);
891 static wxString
ConvertText(const wxString
& str
)
896 for (dt
= str
.c_str(); *dt
; dt
++)
902 else if ( *(++dt
) == wxT('_') )
905 str2
<< wxT('&') << *dt
;
911 case wxT('\n') : str2
<< wxT("\\n"); break;
912 case wxT('\t') : str2
<< wxT("\\t"); break;
913 case wxT('\r') : str2
<< wxT("\\r"); break;
914 case wxT('\\') : if ((*(dt
+1) != 'n') &&
921 case wxT('"') : str2
<< wxT("\\\""); break;
922 default : str2
<< *dt
; break;
932 XmlResApp::FindStrings(const wxString
& filename
, wxXmlNode
*node
)
934 ExtractedStrings arr
;
937 if (n
== NULL
) return arr
;
938 n
= n
->GetChildren();
942 if ((node
->GetType() == wxXML_ELEMENT_NODE
) &&
943 // parent is an element, i.e. has subnodes...
944 (n
->GetType() == wxXML_TEXT_NODE
||
945 n
->GetType() == wxXML_CDATA_SECTION_NODE
) &&
946 // ...it is textnode...
948 node
/*not n!*/->GetName() == wxT("label") ||
949 (node
/*not n!*/->GetName() == wxT("value") &&
950 !n
->GetContent().IsNumber()) ||
951 node
/*not n!*/->GetName() == wxT("help") ||
952 node
/*not n!*/->GetName() == wxT("longhelp") ||
953 node
/*not n!*/->GetName() == wxT("tooltip") ||
954 node
/*not n!*/->GetName() == wxT("htmlcode") ||
955 node
/*not n!*/->GetName() == wxT("title") ||
956 node
/*not n!*/->GetName() == wxT("item") ||
957 node
/*not n!*/->GetName() == wxT("message") ||
958 node
/*not n!*/->GetName() == wxT("note") ||
959 node
/*not n!*/->GetName() == wxT("defaultdirectory") ||
960 node
/*not n!*/->GetName() == wxT("defaultfilename") ||
961 node
/*not n!*/->GetName() == wxT("defaultfolder") ||
962 node
/*not n!*/->GetName() == wxT("filter") ||
963 node
/*not n!*/->GetName() == wxT("caption")
965 // ...and known to contain translatable string
968 node
->GetAttribute(wxT("translate"), wxT("1")) != wxT("0"))
974 ConvertText(n
->GetContent()),
983 if (n
->GetType() == wxXML_ELEMENT_NODE
)
985 ExtractedStrings a2
= FindStrings(filename
, n
);
986 WX_APPEND_ARRAY(arr
, a2
);