]> git.saurik.com Git - wxWidgets.git/blame - utils/wxrc/wxrc.cpp
corrected getting FSRef associated with the POSIX path in wxString
[wxWidgets.git] / utils / wxrc / wxrc.cpp
CommitLineData
56d2f750
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: wxrc.cpp
3// Purpose: XML resource compiler
4// Author: Vaclav Slavik
5// Created: 2000/03/05
6// RCS-ID: $Id$
7// Copyright: (c) 2000 Vaclav Slavik
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
ab7ce33c 11#if defined(__GNUG__) && !defined(__APPLE__)
56d2f750
VS
12 #pragma implementation
13 #pragma interface
14#endif
15
16// For compilers that support precompilation, includes "wx/wx.h".
17#include "wx/wxprec.h"
18
19#ifdef __BORLANDC__
20 #pragma hdrstop
21#endif
22
23// for all others, include the necessary headers (this file is usually all you
24// need because it includes almost all "standard" wxWindows headers
25#ifndef WX_PRECOMP
26 #include "wx/wx.h"
27#endif
28
29#include "wx/cmdline.h"
999d9a9f 30#include "wx/xrc/xml.h"
56d2f750 31#include "wx/ffile.h"
4249ec2c 32#include "wx/filename.h"
f6853b4a
VS
33#include "wx/wfstream.h"
34
35
36
37
56d2f750 38
031dfec8 39/*
56d2f750
VS
40#if wxUSE_GUI
41#error "You must compile the resource compiler with wxBase!"
42#endif
031dfec8 43*/
56d2f750
VS
44
45class XmlResApp : public wxApp
46{
47public:
031dfec8
JS
48
49#if wxUSE_GUI
50 bool OnInit();
51#else
56d2f750 52 virtual int OnRun();
031dfec8 53#endif
56d2f750
VS
54
55private:
56
57 void ParseParams(const wxCmdLineParser& cmdline);
58 void CompileRes();
59 wxArrayString PrepareTempFiles();
f6853b4a
VS
60 void FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath);
61
a7501aeb 62 wxString GetInternalFileName(const wxString& name, const wxArrayString& flist);
56d2f750
VS
63 void DeleteTempFiles(const wxArrayString& flist);
64 void MakePackageZIP(const wxArrayString& flist);
65 void MakePackageCPP(const wxArrayString& flist);
b8b8c49b 66 void MakePackagePython(const wxArrayString& flist);
c8b7a961
VS
67
68 void OutputGettext();
69 wxArrayString FindStrings();
70 wxArrayString FindStrings(wxXmlNode *node);
56d2f750 71
b8b8c49b 72 bool flagVerbose, flagCPP, flagPython, flagGettext;
56d2f750
VS
73 wxString parOutput, parFuncname, parOutputPath;
74 wxArrayString parFiles;
75 int retCode;
76};
77
78IMPLEMENT_APP(XmlResApp)
79
031dfec8
JS
80#if wxUSE_GUI
81bool XmlResApp::OnInit()
82#else
56d2f750 83int XmlResApp::OnRun()
031dfec8 84#endif
56d2f750
VS
85{
86 static const wxCmdLineEntryDesc cmdLineDesc[] =
87 {
2b5f62a0 88 { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show help message"),
99cd20be 89 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
2b5f62a0
VZ
90 { wxCMD_LINE_SWITCH, _T("v"), _T("verbose"), _T("be verbose") },
91 { wxCMD_LINE_SWITCH, _T("c"), _T("cpp-code"), _T("output C++ source rather than .rsc file") },
92 { wxCMD_LINE_SWITCH, _T("p"), _T("python-code"), _T("output wxPython source rather than .rsc file") },
93 { wxCMD_LINE_SWITCH, _T("g"), _T("gettext"), _T("output list of translatable strings (to stdout or file if -o used)") },
94 { wxCMD_LINE_OPTION, _T("n"), _T("function"), _T("C++/Python function name (with -c or -p) [InitXmlResource]") },
95 { wxCMD_LINE_OPTION, _T("o"), _T("output"), _T("output file [resource.xrs/cpp]") },
99cd20be 96#if 0 // not yet implemented
2b5f62a0 97 { wxCMD_LINE_OPTION, _T("l"), _T("list-of-handlers", _T("output list of neccessary handlers to this file" },
99cd20be 98#endif
2b5f62a0 99 { wxCMD_LINE_PARAM, NULL, NULL, _T("input file(s)"),
99cd20be
VS
100 wxCMD_LINE_VAL_STRING,
101 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_OPTION_MANDATORY },
56d2f750
VS
102
103 { wxCMD_LINE_NONE }
104 };
105
106 wxCmdLineParser parser(cmdLineDesc, argc, argv);
107
108 switch (parser.Parse())
109 {
110 case -1:
111 return 0;
112 break;
113
114 case 0:
115 retCode = 0;
116 ParseParams(parser);
c8b7a961
VS
117 if (flagGettext)
118 OutputGettext();
119 else
120 CompileRes();
031dfec8
JS
121#if wxUSE_GUI
122 return FALSE;
123#else
56d2f750 124 return retCode;
031dfec8 125#endif
56d2f750
VS
126 break;
127
128 default:
031dfec8
JS
129#if wxUSE_GUI
130 return FALSE;
131#else
56d2f750 132 return 1;
031dfec8 133#endif
56d2f750
VS
134 break;
135 }
136}
137
138
139
140
141void XmlResApp::ParseParams(const wxCmdLineParser& cmdline)
142{
2b5f62a0
VZ
143 flagGettext = cmdline.Found(_T("g"));
144 flagVerbose = cmdline.Found(_T("v"));
145 flagCPP = cmdline.Found(_T("c"));
146 flagPython = cmdline.Found(_T("p"));
56d2f750 147
2b5f62a0 148 if (!cmdline.Found(_T("o"), &parOutput))
c8b7a961
VS
149 {
150 if (flagGettext)
151 parOutput = wxEmptyString;
152 else
b8b8c49b
VS
153 {
154 if (flagCPP)
2b5f62a0 155 parOutput = _T("resource.cpp");
b8b8c49b 156 else if (flagPython)
2b5f62a0 157 parOutput = _T("resource.py");
b8b8c49b 158 else
2b5f62a0 159 parOutput = _T("resource.xrs");
b8b8c49b 160 }
c8b7a961 161 }
4249ec2c
VS
162 wxFileName fn(parOutput);
163 fn.Normalize();
164 parOutput = fn.GetFullPath();
56d2f750 165 parOutputPath = wxPathOnly(parOutput);
2b5f62a0 166 if (!parOutputPath) parOutputPath = _T(".");
56d2f750 167
2b5f62a0
VZ
168 if (!cmdline.Found(_T("n"), &parFuncname))
169 parFuncname = _T("InitXmlResource");
56d2f750
VS
170
171 for (size_t i = 0; i < cmdline.GetParamCount(); i++)
172 parFiles.Add(cmdline.GetParam(i));
173}
174
175
176
177
178void XmlResApp::CompileRes()
179{
180 wxArrayString files = PrepareTempFiles();
181
182 wxRemoveFile(parOutput);
183
56d2f750
VS
184 if (!retCode)
185 {
186 if (flagCPP)
187 MakePackageCPP(files);
b8b8c49b
VS
188 else if (flagPython)
189 MakePackagePython(files);
56d2f750
VS
190 else
191 MakePackageZIP(files);
192 }
193
194 DeleteTempFiles(files);
195}
196
197
a7501aeb
VS
198wxString XmlResApp::GetInternalFileName(const wxString& name, const wxArrayString& flist)
199{
200 wxString name2 = name;
2b5f62a0
VZ
201 name2.Replace(_T(":"), _T("_"));
202 name2.Replace(_T("/"), _T("_"));
203 name2.Replace(_T("\\"), _T("_"));
204 name2.Replace(_T("*"), _T("_"));
205 name2.Replace(_T("?"), _T("_"));
a7501aeb 206
2b5f62a0 207 wxString s = wxFileNameFromPath(parOutput) + _T("$") + name2;
a7501aeb
VS
208
209 if (wxFileExists(s) && flist.Index(s) == wxNOT_FOUND)
210 {
211 for (int i = 0;; i++)
212 {
2b5f62a0 213 s.Printf(wxFileNameFromPath(parOutput) + _T("$%03i-") + name2, i);
a7501aeb
VS
214 if (!wxFileExists(s) || flist.Index(s) != wxNOT_FOUND)
215 break;
216 }
217 }
218 return s;
219}
56d2f750
VS
220
221wxArrayString XmlResApp::PrepareTempFiles()
222{
223 wxArrayString flist;
224
225 for (size_t i = 0; i < parFiles.Count(); i++)
226 {
227 if (flagVerbose)
2b5f62a0 228 wxPrintf(_T("processing ") + parFiles[i] + _T("...\n"));
56d2f750
VS
229
230 wxXmlDocument doc;
231
232 if (!doc.Load(parFiles[i]))
233 {
2b5f62a0 234 wxLogError(_T("Error parsing file ") + parFiles[i]);
56d2f750
VS
235 retCode = 1;
236 continue;
237 }
238
f6853b4a
VS
239 wxString name, ext, path;
240 wxSplitPath(parFiles[i], &path, &name, &ext);
241
242 FindFilesInXML(doc.GetRoot(), flist, path);
56d2f750 243
a7501aeb
VS
244 wxString internalName = GetInternalFileName(parFiles[i], flist);
245
4249ec2c 246 doc.Save(parOutputPath + wxFILE_SEP_PATH + internalName);
a7501aeb 247 flist.Add(internalName);
56d2f750
VS
248 }
249
250 return flist;
251}
252
253
4249ec2c
VS
254// Does 'node' contain filename information at all?
255static bool NodeContainsFilename(wxXmlNode *node)
256{
257 // Any bitmaps:
258 if (node->GetName() == _T("bitmap"))
259 return TRUE;
260
261 // URLs in wxHtmlWindow:
262 if (node->GetName() == _T("url"))
263 return TRUE;
264
265 // wxBitmapButton:
266 wxXmlNode *parent = node->GetParent();
267 if (parent != NULL &&
268 parent->GetPropVal(_T("class"), _T("")) == _T("wxBitmapButton") &&
269 (node->GetName() == _T("focus") ||
270 node->GetName() == _T("disabled") ||
271 node->GetName() == _T("selected")))
272 return TRUE;
273
274 // wxBitmap or wxIcon toplevel resources:
275 if (node->GetName() == _T("object"))
276 {
277 wxString klass = node->GetPropVal(_T("class"), wxEmptyString);
278 if (klass == _T("wxBitmap") || klass == _T("wxIcon"))
279 return TRUE;
280 }
281
282 return FALSE;
283}
56d2f750 284
f6853b4a
VS
285// find all files mentioned in structure, e.g. <bitmap>filename</bitmap>
286void XmlResApp::FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath)
287{
2b5f62a0
VZ
288 // Is 'node' XML node element?
289 if (node == NULL) return;
290 if (node->GetType() != wxXML_ELEMENT_NODE) return;
291
4249ec2c 292 bool containsFilename = NodeContainsFilename(node);
2b5f62a0
VZ
293
294 wxXmlNode *n = node->GetChildren();
f6853b4a
VS
295 while (n)
296 {
2b5f62a0 297 if (containsFilename &&
f6853b4a 298 (n->GetType() == wxXML_TEXT_NODE ||
2b5f62a0 299 n->GetType() == wxXML_CDATA_SECTION_NODE))
f6853b4a
VS
300 {
301 wxString fullname;
2b5f62a0
VZ
302 if (wxIsAbsolutePath(n->GetContent()) || inputPath.empty())
303 fullname = n->GetContent();
304 else
4249ec2c 305 fullname = inputPath + wxFILE_SEP_PATH + n->GetContent();
a7501aeb
VS
306
307 if (flagVerbose)
2b5f62a0
VZ
308 wxPrintf(_T("adding ") + fullname + _T("...\n"));
309
a7501aeb 310 wxString filename = GetInternalFileName(n->GetContent(), flist);
f6853b4a 311 n->SetContent(filename);
f6853b4a 312
2b5f62a0
VZ
313 if (flist.Index(filename) == wxNOT_FOUND)
314 flist.Add(filename);
f6853b4a
VS
315
316 wxFileInputStream sin(fullname);
4249ec2c 317 wxFileOutputStream sout(parOutputPath + wxFILE_SEP_PATH + filename);
f6853b4a
VS
318 sin.Read(sout); // copy the stream
319 }
2b5f62a0 320
f6853b4a
VS
321 // subnodes:
322 if (n->GetType() == wxXML_ELEMENT_NODE)
323 FindFilesInXML(n, flist, inputPath);
2b5f62a0 324
f6853b4a
VS
325 n = n->GetNext();
326 }
327}
328
329
330
56d2f750
VS
331void XmlResApp::DeleteTempFiles(const wxArrayString& flist)
332{
333 for (size_t i = 0; i < flist.Count(); i++)
4249ec2c 334 wxRemoveFile(parOutputPath + wxFILE_SEP_PATH + flist[i]);
56d2f750
VS
335}
336
337
338
339void XmlResApp::MakePackageZIP(const wxArrayString& flist)
340{
341 wxString files;
342
343 for (size_t i = 0; i < flist.Count(); i++)
2b5f62a0 344 files += flist[i] + _T(" ");
56d2f750
VS
345 files.RemoveLast();
346
347 if (flagVerbose)
2b5f62a0 348 wxPrintf(_T("compressing ") + parOutput + _T("...\n"));
4249ec2c
VS
349
350 wxString cwd = wxGetCwd();
351 wxSetWorkingDirectory(parOutputPath);
352 int execres = wxExecute(_T("zip -9 -j ") +
353 wxString(flagVerbose ? _T("") : _T("-q ")) +
354 parOutput + _T(" ") + files, TRUE);
355 wxSetWorkingDirectory(cwd);
356 if (execres == -1)
56d2f750 357 {
2b5f62a0
VZ
358 wxLogError(_T("Unable to execute zip program. Make sure it is in the path."));
359 wxLogError(_T("You can download it at http://www.cdrom.com/pub/infozip/"));
56d2f750
VS
360 retCode = 1;
361 return;
362 }
363}
364
365
366
367
368static wxString FileToCppArray(wxString filename, int num)
369{
370 wxString output;
56d2f750 371 wxString tmp;
f6853b4a 372 wxString snum;
56d2f750
VS
373 wxFFile file(filename, "rb");
374 size_t lng = file.Length();
375
2b5f62a0
VZ
376 snum.Printf(_T("%i"), num);
377 output.Printf(_T("static size_t xml_res_size_") + snum + _T(" = %i;\n"), lng);
378 output += _T("static unsigned char xml_res_file_") + snum + _T("[] = {\n");
e066e256
VS
379 // we cannot use string literals because MSVC is dumb wannabe compiler
380 // with arbitrary limitation to 2048 strings :(
56d2f750
VS
381
382 unsigned char *buffer = new unsigned char[lng];
383 file.Read(buffer, lng);
384
f6853b4a 385 for (size_t i = 0, linelng = 0; i < lng; i++)
56d2f750 386 {
2b5f62a0
VZ
387 tmp.Printf(_T("%i"), buffer[i]);
388 if (i != 0) output << _T(',');
e066e256 389 if (linelng > 70)
f6853b4a
VS
390 {
391 linelng = 0;
2b5f62a0 392 output << _T("\n");
f6853b4a 393 }
e066e256
VS
394 output << tmp;
395 linelng += tmp.Length()+1;
56d2f750
VS
396 }
397
398 delete[] buffer;
399
2b5f62a0 400 output += _T("};\n\n");
56d2f750
VS
401
402 return output;
403}
404
405
406void XmlResApp::MakePackageCPP(const wxArrayString& flist)
407{
408 wxFFile file(parOutput, "wt");
409 size_t i;
410
411 if (flagVerbose)
2b5f62a0 412 wxPrintf(_T("creating C++ source file ") + parOutput + _T("...\n"));
56d2f750 413
2b5f62a0
VZ
414 file.Write(_T("")
415_T("//\n")
416_T("// This file was automatically generated by wxrc, do not edit by hand.\n")
417_T("//\n\n")
418_T("#include <wx/wxprec.h>\n")
419_T("\n")
420_T("#ifdef __BORLANDC__\n")
421_T(" #pragma hdrstop\n")
422_T("#endif\n")
423_T("\n")
424_T("#ifndef WX_PRECOMP\n")
425_T(" #include <wx/wx.h>\n")
426_T("#endif\n")
427_T("")
428_T("#include <wx/filesys.h>\n")
429_T("#include <wx/fs_mem.h>\n")
430_T("#include <wx/xrc/xmlres.h>\n")
431_T("#include <wx/xrc/xh_all.h>\n")
432_T("\n"));
56d2f750
VS
433
434 for (i = 0; i < flist.Count(); i++)
4249ec2c
VS
435 file.Write(
436 FileToCppArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
56d2f750 437
2b5f62a0
VZ
438 file.Write(_T("")
439_T("void " + parFuncname + "()\n")
440_T("{\n")
441_T("\n")
442_T(" // Check for memory FS. If not present, load the handler:\n")
443_T(" {\n")
444_T(" wxMemoryFSHandler::AddFile(\"XRC_resource/dummy_file\", \"dummy one\");\n")
445_T(" wxFileSystem fsys;\n")
446_T(" wxFSFile *f = fsys.OpenFile(\"memory:XRC_resource/dummy_file\");\n")
447_T(" wxMemoryFSHandler::RemoveFile(\"XRC_resource/dummy_file\");\n")
448_T(" if (f) delete f;\n")
449_T(" else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n")
450_T(" }\n")
451_T("\n"));
56d2f750
VS
452
453 for (i = 0; i < flist.Count(); i++)
454 {
455 wxString s;
2b5f62a0
VZ
456 s.Printf(_T(" wxMemoryFSHandler::AddFile(\"XRC_resource/") + flist[i] +
457 _T("\", xml_res_file_%i, xml_res_size_%i);\n"), i, i);
56d2f750
VS
458 file.Write(s);
459 }
f6853b4a
VS
460
461 for (i = 0; i < parFiles.Count(); i++)
462 {
2b5f62a0
VZ
463 file.Write(_T(" wxXmlResource::Get()->Load(\"memory:XRC_resource/") +
464 GetInternalFileName(parFiles[i], flist) + _T("\");\n"));
f6853b4a 465 }
56d2f750 466
2b5f62a0 467 file.Write(_T("}\n"));
56d2f750 468
f6853b4a 469
56d2f750 470}
c8b7a961 471
b8b8c49b
VS
472static wxString FileToPythonArray(wxString filename, int num)
473{
474 wxString output;
475 wxString tmp;
476 wxString snum;
477 wxFFile file(filename, "rb");
478 size_t lng = file.Length();
479
2b5f62a0
VZ
480 snum.Printf(_T("%i"), num);
481 output = _T(" xml_res_file_") + snum + _T(" = \"\"\"\\\n");
b8b8c49b
VS
482
483 unsigned char *buffer = new unsigned char[lng];
484 file.Read(buffer, lng);
485
486 for (size_t i = 0, linelng = 0; i < lng; i++)
487 {
488 unsigned char c = buffer[i];
489 if (c == '\n')
490 {
491 tmp = (wxChar)c;
492 linelng = 0;
493 }
494 else if (c < 32 || c > 127)
2b5f62a0 495 tmp.Printf(_T("\\x%02x"), c);
b8b8c49b 496 else if (c == '\\')
2b5f62a0 497 tmp = _T("\\\\");
b8b8c49b
VS
498 else
499 tmp = (wxChar)c;
500 if (linelng > 70)
501 {
502 linelng = 0;
2b5f62a0 503 output << _T("\\\n");
b8b8c49b
VS
504 }
505 output << tmp;
506 linelng += tmp.Length();
507 }
508
509 delete[] buffer;
510
2b5f62a0 511 output += _T("\"\"\"\n\n");
b8b8c49b
VS
512
513 return output;
514}
515
516
517void XmlResApp::MakePackagePython(const wxArrayString& flist)
518{
519 wxFFile file(parOutput, "wt");
520 size_t i;
521
522 if (flagVerbose)
2b5f62a0 523 wxPrintf(_T("creating Python source file ") + parOutput + _T("...\n"));
b8b8c49b
VS
524
525 file.Write(
2b5f62a0
VZ
526 _T("#\n")
527 _T("# This file was automatically generated by wxrc, do not edit by hand.\n")
528 _T("#\n\n")
529 _T("from wxPython.wx import *\n")
530 _T("from wxPython.xrc import *\n\n")
b8b8c49b
VS
531 );
532
533
2b5f62a0 534 file.Write(_T("def ") + parFuncname + _T("():\n"));
b8b8c49b
VS
535
536 for (i = 0; i < flist.Count(); i++)
4249ec2c
VS
537 file.Write(
538 FileToPythonArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
b8b8c49b
VS
539
540 for (i = 0; i < flist.Count(); i++)
541 {
542 wxString s;
2b5f62a0 543 s.Printf(_T(" wxXmlResource_Get().LoadFromString(xml_res_file_%i)\n"), i);
b8b8c49b
VS
544 file.Write(s);
545 }
546}
547
c8b7a961
VS
548
549
550void XmlResApp::OutputGettext()
551{
552 wxArrayString str = FindStrings();
553
554 wxFFile fout;
555 if (!parOutput) fout.Attach(stdout);
2b5f62a0 556 else fout.Open(parOutput, "wt");
c8b7a961
VS
557
558 for (size_t i = 0; i < str.GetCount(); i++)
0653d364 559 fout.Write(_T("_(\"") + str[i] + _T("\");\n"));
c8b7a961
VS
560
561 if (!parOutput) fout.Detach();
562}
563
564
565
566wxArrayString XmlResApp::FindStrings()
567{
568 wxArrayString arr, a2;
569
570 for (size_t i = 0; i < parFiles.Count(); i++)
571 {
572 if (flagVerbose)
2b5f62a0 573 wxPrintf(_T("processing ") + parFiles[i] + _T("...\n"));
c8b7a961
VS
574
575 wxXmlDocument doc;
576 if (!doc.Load(parFiles[i]))
577 {
2b5f62a0 578 wxLogError(_T("Error parsing file ") + parFiles[i]);
c8b7a961
VS
579 retCode = 1;
580 continue;
581 }
582 a2 = FindStrings(doc.GetRoot());
583 WX_APPEND_ARRAY(arr, a2);
584 }
585
586 return arr;
587}
588
589
590
c109ef11
VS
591static wxString ConvertText(const wxString& str)
592{
593 wxString str2;
594 const wxChar *dt;
595
596 for (dt = str.c_str(); *dt; dt++)
597 {
598 if (*dt == wxT('_'))
599 {
600 if ( *(++dt) == wxT('_') )
601 str2 << wxT('_');
602 else
603 str2 << wxT('&') << *dt;
604 }
605 else
606 {
607 switch (*dt)
608 {
609 case wxT('\n') : str2 << wxT("\\n"); break;
610 case wxT('\t') : str2 << wxT("\\t"); break;
611 case wxT('\r') : str2 << wxT("\\r"); break;
2b5f62a0
VZ
612 case wxT('\\') : if ((*(dt+1) != 'n') &&
613 (*(dt+1) != 't') &&
614 (*(dt+1) != 'r'))
615 str2 << wxT("\\\\");
616 else
617 str2 << wxT("\\");
618 break;
904a226c 619 case wxT('"') : str2 << wxT("\\\""); break;
c109ef11
VS
620 default : str2 << *dt; break;
621 }
622 }
623 }
624
625 return str2;
626}
627
628
c8b7a961
VS
629wxArrayString XmlResApp::FindStrings(wxXmlNode *node)
630{
631 wxArrayString arr;
632
633 wxXmlNode *n = node;
634 if (n == NULL) return arr;
635 n = n->GetChildren();
636
637 while (n)
638 {
639 if ((node->GetType() == wxXML_ELEMENT_NODE) &&
640 // parent is an element, i.e. has subnodes...
641 (n->GetType() == wxXML_TEXT_NODE ||
642 n->GetType() == wxXML_CDATA_SECTION_NODE) &&
643 // ...it is textnode...
644 (
645 node/*not n!*/->GetName() == _T("label") ||
646 (node/*not n!*/->GetName() == _T("value") &&
647 !n->GetContent().IsNumber()) ||
648 node/*not n!*/->GetName() == _T("help") ||
649 node/*not n!*/->GetName() == _T("longhelp") ||
650 node/*not n!*/->GetName() == _T("tooltip") ||
651 node/*not n!*/->GetName() == _T("htmlcode") ||
0653d364
VS
652 node/*not n!*/->GetName() == _T("title") ||
653 node/*not n!*/->GetName() == _T("item")
c8b7a961 654 ))
c109ef11 655 // ...and known to contain translatable string
c8b7a961 656 {
c109ef11 657 arr.Add(ConvertText(n->GetContent()));
c8b7a961
VS
658 }
659
660 // subnodes:
661 if (n->GetType() == wxXML_ELEMENT_NODE)
662 {
663 wxArrayString a2 = FindStrings(n);
664 WX_APPEND_ARRAY(arr, a2);
665 }
666
667 n = n->GetNext();
668 }
669 return arr;
670}