]> git.saurik.com Git - wxWidgets.git/blame - utils/wxrc/wxrc.cpp
compilation fix after wxCStrData changes
[wxWidgets.git] / utils / wxrc / wxrc.cpp
CommitLineData
56d2f750
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: wxrc.cpp
3// Purpose: XML resource compiler
1dce6f09 4// Author: Vaclav Slavik, Eduardo Marques <edrdo@netcabo.pt>
56d2f750
VS
5// Created: 2000/03/05
6// RCS-ID: $Id$
7// Copyright: (c) 2000 Vaclav Slavik
8// Licence: wxWindows licence
9/////////////////////////////////////////////////////////////////////////////
10
56d2f750
VS
11// For compilers that support precompilation, includes "wx/wx.h".
12#include "wx/wxprec.h"
13
14#ifdef __BORLANDC__
15 #pragma hdrstop
16#endif
17
07ee782b 18// for all others, include the necessary headers
56d2f750 19#ifndef WX_PRECOMP
07ee782b
MB
20 #include "wx/app.h"
21 #include "wx/log.h"
56d2f750
VS
22#endif
23
24#include "wx/cmdline.h"
cecc483e 25#include "wx/xml/xml.h"
56d2f750 26#include "wx/ffile.h"
4249ec2c 27#include "wx/filename.h"
f6853b4a 28#include "wx/wfstream.h"
097d3ba2 29#include "wx/utils.h"
aac18ec7 30#include "wx/hashset.h"
f6853b4a 31
aac18ec7 32WX_DECLARE_HASH_SET(wxString, wxStringHash, wxStringEqual, StringSet);
f6853b4a 33
1dce6f09
VS
34class XRCWidgetData
35{
36public:
f80ea77b 37 XRCWidgetData(const wxString& vname,const wxString& vclass)
1dce6f09
VS
38 : m_class(vclass), m_name(vname) {}
39 const wxString& GetName() const { return m_name; }
40 const wxString& GetClass() const { return m_class; }
41private:
42 wxString m_class;
43 wxString m_name;
44};
2ad1ff54 45
1dce6f09
VS
46#include "wx/arrimpl.cpp"
47WX_DECLARE_OBJARRAY(XRCWidgetData,ArrayOfXRCWidgetData);
17a1ebd1 48WX_DEFINE_OBJARRAY(ArrayOfXRCWidgetData)
1dce6f09
VS
49
50class XRCWndClassData
51{
f80ea77b 52private:
1dce6f09
VS
53 wxString m_className;
54 wxString m_parentClassName;
aac18ec7 55 StringSet m_ancestorClassNames;
1dce6f09 56 ArrayOfXRCWidgetData m_wdata;
f80ea77b 57
1dce6f09
VS
58 void BrowseXmlNode(wxXmlNode* node)
59 {
60 wxString classValue;
61 wxString nameValue;
f80ea77b 62 wxXmlNode* children;
1dce6f09
VS
63 while (node)
64 {
65 if (node->GetName() == _T("object")
66 && node->GetPropVal(_T("class"),&classValue)
67 && node->GetPropVal(_T("name"),&nameValue))
68 {
69 m_wdata.Add(XRCWidgetData(nameValue,classValue));
70 }
71 children = node->GetChildren();
72 if (children)
f80ea77b 73 BrowseXmlNode(children);
1dce6f09
VS
74 node = node->GetNext();
75 }
76 }
f80ea77b 77
1dce6f09 78public:
aac18ec7
VZ
79 XRCWndClassData(const wxString& className,
80 const wxString& parentClassName,
81 const wxXmlNode* node) :
2ad1ff54
WS
82 m_className(className) , m_parentClassName(parentClassName)
83 {
aac18ec7
VZ
84 if ( className == _T("wxMenu") )
85 {
86 m_ancestorClassNames.insert(_T("wxMenu"));
87 m_ancestorClassNames.insert(_T("wxMenuBar"));
88 }
89 else if ( className == _T("wxMDIChildFrame") )
90 {
91 m_ancestorClassNames.insert(_T("wxMDIParentFrame"));
92 }
93 else if( className == _T("wxMenuBar") ||
94 className == _T("wxStatusBar") ||
95 className == _T("wxToolBar") )
96 {
97 m_ancestorClassNames.insert(_T("wxFrame"));
98 }
99 else
100 {
101 m_ancestorClassNames.insert(_T("wxWindow"));
102 }
103
aa063b24 104 BrowseXmlNode(node->GetChildren());
aa063b24 105 }
f80ea77b 106
2ad1ff54
WS
107 const ArrayOfXRCWidgetData& GetWidgetData()
108 {
aa063b24
RD
109 return m_wdata;
110 }
76ee0497 111
216d173f 112 bool CanBeUsedWithXRCCTRL(const wxString& name)
76ee0497 113 {
2ad1ff54
WS
114 if (name == _T("tool") ||
115 name == _T("unknown") ||
116 name == _T("notebookpage") ||
117 name == _T("separator") ||
76ee0497 118 name == _T("sizeritem") ||
76ff8ed6
VZ
119 name == _T("wxMenuBar") ||
120 name == _T("wxMenuItem") ||
121 name == _T("wxStaticBoxSizer") )
76ee0497
VS
122 {
123 return false;
124 }
125 return true;
126 }
2ad1ff54 127
76ee0497
VS
128 void GenerateHeaderCode(wxFFile& file)
129 {
aa063b24
RD
130
131 file.Write(_T("class ") + m_className + _T(" : public ") + m_parentClassName
132 + _T(" {\nprotected:\n"));
133 size_t i;
76ee0497
VS
134 for(i=0;i<m_wdata.Count();++i)
135 {
aa063b24 136 const XRCWidgetData& w = m_wdata.Item(i);
216d173f 137 if( !CanBeUsedWithXRCCTRL(w.GetClass()) ) continue;
2ad1ff54 138 if( w.GetName().Length() == 0 ) continue;
aa063b24
RD
139 file.Write(
140 _T(" ") + w.GetClass() + _T("* ") + w.GetName()
141 + _T(";\n"));
142 }
aac18ec7
VZ
143 file.Write(_T("\nprivate:\n void InitWidgetsFromXRC(wxWindow *parent){\n")
144 _T(" wxXmlResource::Get()->LoadObject(this,parent,_T(\"")
f80ea77b 145 + m_className
caf6f468 146 + _T("\"), _T(\"")
f80ea77b 147 + m_parentClassName
caf6f468 148 + _T("\"));\n"));
76ee0497
VS
149 for(i=0;i<m_wdata.Count();++i)
150 {
aa063b24 151 const XRCWidgetData& w = m_wdata.Item(i);
216d173f 152 if( !CanBeUsedWithXRCCTRL(w.GetClass()) ) continue;
2ad1ff54 153 if( w.GetName().Length() == 0 ) continue;
f80ea77b
WS
154 file.Write( _T(" ")
155 + w.GetName()
aa063b24 156 + _T(" = XRCCTRL(*this,\"")
f80ea77b 157 + w.GetName()
aa063b24
RD
158 + _T("\",")
159 + w.GetClass()
aac18ec7 160 + _T(");\n"));
aa063b24 161 }
2ad1ff54
WS
162 file.Write(_T(" }\n"));
163
aac18ec7
VZ
164 file.Write( _T("public:\n"));
165
166 if ( m_ancestorClassNames.size() == 1 )
167 {
168 file.Write
169 (
170 m_className +
171 _T("(") +
172 *m_ancestorClassNames.begin() +
173 _T(" *parent=NULL){\n") +
174 _T(" InitWidgetsFromXRC((wxWindow *)parent);\n")
175 _T(" }\n")
176 _T("};\n")
177 );
178 }
179 else
180 {
181 file.Write(m_className + _T("(){\n") +
182 _T(" InitWidgetsFromXRC(NULL);\n")
183 _T(" }\n")
184 _T("};\n"));
185
186 for ( StringSet::const_iterator it = m_ancestorClassNames.begin();
187 it != m_ancestorClassNames.end();
188 ++it )
189 {
190 file.Write(m_className + _T("(") + *it + _T(" *parent){\n") +
191 _T(" InitWidgetsFromXRC((wxWindow *)parent);\n")
192 _T(" }\n")
193 _T("};\n"));
194 }
195 }
196 }
1dce6f09
VS
197};
198WX_DECLARE_OBJARRAY(XRCWndClassData,ArrayOfXRCWndClassData);
17a1ebd1 199WX_DEFINE_OBJARRAY(ArrayOfXRCWndClassData)
1dce6f09
VS
200
201
cecc483e 202class XmlResApp : public wxAppConsole
56d2f750
VS
203{
204public:
6fcef5ed 205 // don't use builtin cmd line parsing:
f80ea77b 206 virtual bool OnInit() { return true; }
56d2f750 207 virtual int OnRun();
f80ea77b
WS
208
209private:
56d2f750
VS
210 void ParseParams(const wxCmdLineParser& cmdline);
211 void CompileRes();
212 wxArrayString PrepareTempFiles();
f6853b4a
VS
213 void FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath);
214
a7501aeb 215 wxString GetInternalFileName(const wxString& name, const wxArrayString& flist);
56d2f750
VS
216 void DeleteTempFiles(const wxArrayString& flist);
217 void MakePackageZIP(const wxArrayString& flist);
218 void MakePackageCPP(const wxArrayString& flist);
b8b8c49b 219 void MakePackagePython(const wxArrayString& flist);
c8b7a961
VS
220
221 void OutputGettext();
222 wxArrayString FindStrings();
223 wxArrayString FindStrings(wxXmlNode *node);
f80ea77b 224
b8b8c49b 225 bool flagVerbose, flagCPP, flagPython, flagGettext;
56d2f750
VS
226 wxString parOutput, parFuncname, parOutputPath;
227 wxArrayString parFiles;
228 int retCode;
1dce6f09
VS
229
230 ArrayOfXRCWndClassData aXRCWndClassData;
aa063b24
RD
231 bool flagH;
232 void GenCPPHeader();
56d2f750
VS
233};
234
80b2db4e 235IMPLEMENT_APP_CONSOLE(XmlResApp)
56d2f750
VS
236
237int XmlResApp::OnRun()
238{
239 static const wxCmdLineEntryDesc cmdLineDesc[] =
240 {
f80ea77b 241 { wxCMD_LINE_SWITCH, _T("h"), _T("help"), _T("show help message"),
99cd20be 242 wxCMD_LINE_VAL_NONE, wxCMD_LINE_OPTION_HELP },
e7694e3b
WS
243 { wxCMD_LINE_SWITCH, _T("v"), _T("verbose"), _T("be verbose"), (wxCmdLineParamType)0, 0 },
244 { wxCMD_LINE_SWITCH, _T("e"), _T("extra-cpp-code"), _T("output C++ header file with XRC derived classes"), (wxCmdLineParamType)0, 0 },
245 { wxCMD_LINE_SWITCH, _T("c"), _T("cpp-code"), _T("output C++ source rather than .rsc file"), (wxCmdLineParamType)0, 0 },
246 { wxCMD_LINE_SWITCH, _T("p"), _T("python-code"), _T("output wxPython source rather than .rsc file"), (wxCmdLineParamType)0, 0 },
247 { wxCMD_LINE_SWITCH, _T("g"), _T("gettext"), _T("output list of translatable strings (to stdout or file if -o used)"), (wxCmdLineParamType)0, 0 },
248 { wxCMD_LINE_OPTION, _T("n"), _T("function"), _T("C++/Python function name (with -c or -p) [InitXmlResource]"), (wxCmdLineParamType)0, 0 },
249 { wxCMD_LINE_OPTION, _T("o"), _T("output"), _T("output file [resource.xrs/cpp]"), (wxCmdLineParamType)0, 0 },
99cd20be 250#if 0 // not yet implemented
d6922577 251 { wxCMD_LINE_OPTION, _T("l"), _T("list-of-handlers"), _T("output list of necessary handlers to this file"), (wxCmdLineParamType)0, 0 },
99cd20be 252#endif
2b5f62a0 253 { wxCMD_LINE_PARAM, NULL, NULL, _T("input file(s)"),
f80ea77b 254 wxCMD_LINE_VAL_STRING,
99cd20be 255 wxCMD_LINE_PARAM_MULTIPLE | wxCMD_LINE_OPTION_MANDATORY },
56d2f750 256
e7694e3b 257 { wxCMD_LINE_NONE, NULL, NULL, NULL, (wxCmdLineParamType)0, 0 }
56d2f750
VS
258 };
259
260 wxCmdLineParser parser(cmdLineDesc, argc, argv);
261
262 switch (parser.Parse())
263 {
264 case -1:
265 return 0;
56d2f750
VS
266
267 case 0:
268 retCode = 0;
269 ParseParams(parser);
c8b7a961
VS
270 if (flagGettext)
271 OutputGettext();
272 else
273 CompileRes();
56d2f750 274 return retCode;
56d2f750 275 }
0a0be6d5 276 return 1;
56d2f750
VS
277}
278
279
280
281
282void XmlResApp::ParseParams(const wxCmdLineParser& cmdline)
283{
2b5f62a0
VZ
284 flagGettext = cmdline.Found(_T("g"));
285 flagVerbose = cmdline.Found(_T("v"));
286 flagCPP = cmdline.Found(_T("c"));
287 flagPython = cmdline.Found(_T("p"));
1dce6f09
VS
288 flagH = flagCPP && cmdline.Found(_T("e"));
289
56d2f750 290
f80ea77b 291 if (!cmdline.Found(_T("o"), &parOutput))
c8b7a961
VS
292 {
293 if (flagGettext)
294 parOutput = wxEmptyString;
295 else
b8b8c49b
VS
296 {
297 if (flagCPP)
2b5f62a0 298 parOutput = _T("resource.cpp");
b8b8c49b 299 else if (flagPython)
2b5f62a0 300 parOutput = _T("resource.py");
b8b8c49b 301 else
2b5f62a0 302 parOutput = _T("resource.xrs");
b8b8c49b 303 }
c8b7a961 304 }
1dce6f09
VS
305 if (!parOutput.empty())
306 {
307 wxFileName fn(parOutput);
308 fn.Normalize();
309 parOutput = fn.GetFullPath();
310 parOutputPath = wxPathOnly(parOutput);
311 }
2b5f62a0 312 if (!parOutputPath) parOutputPath = _T(".");
56d2f750 313
f80ea77b 314 if (!cmdline.Found(_T("n"), &parFuncname))
2b5f62a0 315 parFuncname = _T("InitXmlResource");
56d2f750
VS
316
317 for (size_t i = 0; i < cmdline.GetParamCount(); i++)
f65a69e9
VS
318 {
319#ifdef __WINDOWS__
320 wxString fn=wxFindFirstFile(cmdline.GetParam(i), wxFILE);
2ad1ff54 321 while (!fn.empty())
f65a69e9
VS
322 {
323 parFiles.Add(fn);
324 fn=wxFindNextFile();
325 }
326#else
56d2f750 327 parFiles.Add(cmdline.GetParam(i));
f65a69e9
VS
328#endif
329 }
56d2f750
VS
330}
331
332
333
334
335void XmlResApp::CompileRes()
336{
337 wxArrayString files = PrepareTempFiles();
338
339 wxRemoveFile(parOutput);
340
56d2f750 341 if (!retCode)
f80ea77b 342 {
1dce6f09 343 if (flagCPP){
56d2f750 344 MakePackageCPP(files);
1dce6f09
VS
345 if (flagH)
346 GenCPPHeader();
347 }
b8b8c49b
VS
348 else if (flagPython)
349 MakePackagePython(files);
56d2f750
VS
350 else
351 MakePackageZIP(files);
352 }
f80ea77b 353
56d2f750
VS
354 DeleteTempFiles(files);
355}
356
357
a7501aeb
VS
358wxString XmlResApp::GetInternalFileName(const wxString& name, const wxArrayString& flist)
359{
360 wxString name2 = name;
2b5f62a0
VZ
361 name2.Replace(_T(":"), _T("_"));
362 name2.Replace(_T("/"), _T("_"));
363 name2.Replace(_T("\\"), _T("_"));
364 name2.Replace(_T("*"), _T("_"));
365 name2.Replace(_T("?"), _T("_"));
f80ea77b 366
2b5f62a0 367 wxString s = wxFileNameFromPath(parOutput) + _T("$") + name2;
a7501aeb
VS
368
369 if (wxFileExists(s) && flist.Index(s) == wxNOT_FOUND)
f80ea77b 370 {
a7501aeb
VS
371 for (int i = 0;; i++)
372 {
2b5f62a0 373 s.Printf(wxFileNameFromPath(parOutput) + _T("$%03i-") + name2, i);
a7501aeb
VS
374 if (!wxFileExists(s) || flist.Index(s) != wxNOT_FOUND)
375 break;
376 }
377 }
378 return s;
379}
56d2f750
VS
380
381wxArrayString XmlResApp::PrepareTempFiles()
382{
383 wxArrayString flist;
f80ea77b 384
56d2f750
VS
385 for (size_t i = 0; i < parFiles.Count(); i++)
386 {
f80ea77b 387 if (flagVerbose)
2b5f62a0 388 wxPrintf(_T("processing ") + parFiles[i] + _T("...\n"));
56d2f750
VS
389
390 wxXmlDocument doc;
f80ea77b 391
56d2f750
VS
392 if (!doc.Load(parFiles[i]))
393 {
2b5f62a0 394 wxLogError(_T("Error parsing file ") + parFiles[i]);
56d2f750
VS
395 retCode = 1;
396 continue;
397 }
f80ea77b 398
f6853b4a
VS
399 wxString name, ext, path;
400 wxSplitPath(parFiles[i], &path, &name, &ext);
401
402 FindFilesInXML(doc.GetRoot(), flist, path);
1dce6f09
VS
403 if (flagH)
404 {
405 wxXmlNode* node = (doc.GetRoot())->GetChildren();
aa063b24
RD
406 wxString classValue,nameValue;
407 while(node){
1dce6f09 408 if(node->GetName() == _T("object")
aa063b24
RD
409 && node->GetPropVal(_T("class"),&classValue)
410 && node->GetPropVal(_T("name"),&nameValue)){
1dce6f09
VS
411
412 aXRCWndClassData.Add(
aa063b24 413 XRCWndClassData(nameValue,classValue,node)
1dce6f09
VS
414 );
415 }
aa063b24 416 node = node -> GetNext();
1dce6f09
VS
417 }
418 }
a7501aeb 419 wxString internalName = GetInternalFileName(parFiles[i], flist);
f80ea77b 420
4249ec2c 421 doc.Save(parOutputPath + wxFILE_SEP_PATH + internalName);
a7501aeb 422 flist.Add(internalName);
56d2f750 423 }
f80ea77b 424
56d2f750
VS
425 return flist;
426}
427
428
4249ec2c
VS
429// Does 'node' contain filename information at all?
430static bool NodeContainsFilename(wxXmlNode *node)
431{
bc151e84
VZ
432 const wxString name = node->GetName();
433
434 // Any bitmaps (bitmap2 is used for disabled toolbar buttons):
435 if ( name == _T("bitmap") || name == _T("bitmap2") )
f80ea77b 436 return true;
2ad1ff54 437
bc151e84 438 if ( name == _T("icon") )
8b34993d 439 return true;
4249ec2c
VS
440
441 // URLs in wxHtmlWindow:
bc151e84 442 if ( name == _T("url") )
f80ea77b
WS
443 return true;
444
4249ec2c
VS
445 // wxBitmapButton:
446 wxXmlNode *parent = node->GetParent();
f80ea77b 447 if (parent != NULL &&
4249ec2c 448 parent->GetPropVal(_T("class"), _T("")) == _T("wxBitmapButton") &&
bc151e84
VZ
449 (name == _T("focus") ||
450 name == _T("disabled") ||
451 name == _T("selected")))
f80ea77b
WS
452 return true;
453
4249ec2c 454 // wxBitmap or wxIcon toplevel resources:
bc151e84 455 if ( name == _T("object") )
4249ec2c
VS
456 {
457 wxString klass = node->GetPropVal(_T("class"), wxEmptyString);
458 if (klass == _T("wxBitmap") || klass == _T("wxIcon"))
f80ea77b 459 return true;
4249ec2c 460 }
f80ea77b
WS
461
462 return false;
4249ec2c 463}
56d2f750 464
f6853b4a
VS
465// find all files mentioned in structure, e.g. <bitmap>filename</bitmap>
466void XmlResApp::FindFilesInXML(wxXmlNode *node, wxArrayString& flist, const wxString& inputPath)
467{
2b5f62a0
VZ
468 // Is 'node' XML node element?
469 if (node == NULL) return;
470 if (node->GetType() != wxXML_ELEMENT_NODE) return;
471
4249ec2c 472 bool containsFilename = NodeContainsFilename(node);
2b5f62a0
VZ
473
474 wxXmlNode *n = node->GetChildren();
f6853b4a
VS
475 while (n)
476 {
2b5f62a0 477 if (containsFilename &&
f80ea77b 478 (n->GetType() == wxXML_TEXT_NODE ||
2b5f62a0 479 n->GetType() == wxXML_CDATA_SECTION_NODE))
f6853b4a
VS
480 {
481 wxString fullname;
2b5f62a0
VZ
482 if (wxIsAbsolutePath(n->GetContent()) || inputPath.empty())
483 fullname = n->GetContent();
484 else
4249ec2c 485 fullname = inputPath + wxFILE_SEP_PATH + n->GetContent();
a7501aeb 486
f80ea77b 487 if (flagVerbose)
2b5f62a0
VZ
488 wxPrintf(_T("adding ") + fullname + _T("...\n"));
489
a7501aeb 490 wxString filename = GetInternalFileName(n->GetContent(), flist);
f6853b4a 491 n->SetContent(filename);
f6853b4a 492
2b5f62a0
VZ
493 if (flist.Index(filename) == wxNOT_FOUND)
494 flist.Add(filename);
f6853b4a
VS
495
496 wxFileInputStream sin(fullname);
4249ec2c 497 wxFileOutputStream sout(parOutputPath + wxFILE_SEP_PATH + filename);
f6853b4a
VS
498 sin.Read(sout); // copy the stream
499 }
2b5f62a0 500
f6853b4a
VS
501 // subnodes:
502 if (n->GetType() == wxXML_ELEMENT_NODE)
503 FindFilesInXML(n, flist, inputPath);
2b5f62a0 504
f6853b4a
VS
505 n = n->GetNext();
506 }
507}
508
509
510
56d2f750
VS
511void XmlResApp::DeleteTempFiles(const wxArrayString& flist)
512{
513 for (size_t i = 0; i < flist.Count(); i++)
4249ec2c 514 wxRemoveFile(parOutputPath + wxFILE_SEP_PATH + flist[i]);
56d2f750
VS
515}
516
517
518
519void XmlResApp::MakePackageZIP(const wxArrayString& flist)
520{
521 wxString files;
f80ea77b 522
56d2f750 523 for (size_t i = 0; i < flist.Count(); i++)
2b5f62a0 524 files += flist[i] + _T(" ");
56d2f750 525 files.RemoveLast();
f80ea77b
WS
526
527 if (flagVerbose)
2b5f62a0 528 wxPrintf(_T("compressing ") + parOutput + _T("...\n"));
f80ea77b 529
4249ec2c
VS
530 wxString cwd = wxGetCwd();
531 wxSetWorkingDirectory(parOutputPath);
f80ea77b 532 int execres = wxExecute(_T("zip -9 -j ") +
be575a01
VZ
533 wxString(flagVerbose ? _T("\"") : _T("-q \"")) +
534 parOutput + _T("\" ") + files, true);
4249ec2c
VS
535 wxSetWorkingDirectory(cwd);
536 if (execres == -1)
56d2f750 537 {
2b5f62a0
VZ
538 wxLogError(_T("Unable to execute zip program. Make sure it is in the path."));
539 wxLogError(_T("You can download it at http://www.cdrom.com/pub/infozip/"));
56d2f750
VS
540 retCode = 1;
541 return;
542 }
543}
544
545
546
56d2f750
VS
547static wxString FileToCppArray(wxString filename, int num)
548{
549 wxString output;
56d2f750 550 wxString tmp;
f6853b4a 551 wxString snum;
5851504d 552 wxFFile file(filename, wxT("rb"));
2ad1ff54
WS
553 wxFileOffset offset = file.Length();
554 wxASSERT_MSG( offset >= 0 , wxT("Invalid file length") );
17a1ebd1
VZ
555
556 const size_t lng = wx_truncate_cast(size_t, offset);
557 wxASSERT_MSG( lng == offset, wxT("Huge file not supported") );
f80ea77b 558
2b5f62a0
VZ
559 snum.Printf(_T("%i"), num);
560 output.Printf(_T("static size_t xml_res_size_") + snum + _T(" = %i;\n"), lng);
561 output += _T("static unsigned char xml_res_file_") + snum + _T("[] = {\n");
e066e256
VS
562 // we cannot use string literals because MSVC is dumb wannabe compiler
563 // with arbitrary limitation to 2048 strings :(
f80ea77b 564
56d2f750
VS
565 unsigned char *buffer = new unsigned char[lng];
566 file.Read(buffer, lng);
f80ea77b 567
f6853b4a 568 for (size_t i = 0, linelng = 0; i < lng; i++)
56d2f750 569 {
2b5f62a0
VZ
570 tmp.Printf(_T("%i"), buffer[i]);
571 if (i != 0) output << _T(',');
e066e256 572 if (linelng > 70)
f6853b4a
VS
573 {
574 linelng = 0;
2b5f62a0 575 output << _T("\n");
f6853b4a 576 }
e066e256
VS
577 output << tmp;
578 linelng += tmp.Length()+1;
56d2f750 579 }
f80ea77b 580
56d2f750 581 delete[] buffer;
f80ea77b 582
2b5f62a0 583 output += _T("};\n\n");
f80ea77b 584
56d2f750
VS
585 return output;
586}
587
588
589void XmlResApp::MakePackageCPP(const wxArrayString& flist)
590{
5851504d 591 wxFFile file(parOutput, wxT("wt"));
56d2f750
VS
592 size_t i;
593
f80ea77b 594 if (flagVerbose)
2b5f62a0 595 wxPrintf(_T("creating C++ source file ") + parOutput + _T("...\n"));
f80ea77b 596
2b5f62a0
VZ
597 file.Write(_T("")
598_T("//\n")
599_T("// This file was automatically generated by wxrc, do not edit by hand.\n")
600_T("//\n\n")
601_T("#include <wx/wxprec.h>\n")
602_T("\n")
603_T("#ifdef __BORLANDC__\n")
604_T(" #pragma hdrstop\n")
605_T("#endif\n")
606_T("\n")
2b5f62a0
VZ
607_T("")
608_T("#include <wx/filesys.h>\n")
609_T("#include <wx/fs_mem.h>\n")
610_T("#include <wx/xrc/xmlres.h>\n")
611_T("#include <wx/xrc/xh_all.h>\n")
612_T("\n"));
56d2f750
VS
613
614 for (i = 0; i < flist.Count(); i++)
4249ec2c
VS
615 file.Write(
616 FileToCppArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
f80ea77b 617
2b5f62a0 618 file.Write(_T("")
5851504d 619_T("void ") + parFuncname + wxT("()\n")
2b5f62a0
VZ
620_T("{\n")
621_T("\n")
622_T(" // Check for memory FS. If not present, load the handler:\n")
623_T(" {\n")
5851504d 624_T(" wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/dummy_file\"), wxT(\"dummy one\"));\n")
2b5f62a0 625_T(" wxFileSystem fsys;\n")
5851504d
VS
626_T(" wxFSFile *f = fsys.OpenFile(wxT(\"memory:XRC_resource/dummy_file\"));\n")
627_T(" wxMemoryFSHandler::RemoveFile(wxT(\"XRC_resource/dummy_file\"));\n")
2b5f62a0
VZ
628_T(" if (f) delete f;\n")
629_T(" else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n")
630_T(" }\n")
631_T("\n"));
56d2f750
VS
632
633 for (i = 0; i < flist.Count(); i++)
634 {
635 wxString s;
5851504d
VS
636 s.Printf(_T(" wxMemoryFSHandler::AddFile(wxT(\"XRC_resource/") + flist[i] +
637 _T("\"), xml_res_file_%i, xml_res_size_%i);\n"), i, i);
56d2f750
VS
638 file.Write(s);
639 }
f6853b4a
VS
640
641 for (i = 0; i < parFiles.Count(); i++)
642 {
5851504d
VS
643 file.Write(_T(" wxXmlResource::Get()->Load(wxT(\"memory:XRC_resource/") +
644 GetInternalFileName(parFiles[i], flist) + _T("\"));\n"));
f6853b4a 645 }
f80ea77b 646
2b5f62a0 647 file.Write(_T("}\n"));
56d2f750 648
f6853b4a 649
56d2f750 650}
c8b7a961 651
1dce6f09
VS
652void XmlResApp::GenCPPHeader()
653{
76ee0497 654 wxString fileSpec = ((parOutput.BeforeLast('.')).AfterLast('/')).AfterLast('\\');
1dce6f09 655 wxString heaFileName = fileSpec + _T(".h");
f80ea77b 656
1dce6f09
VS
657 wxFFile file(heaFileName, wxT("wt"));
658 file.Write(
659_T("//\n")
660_T("// This file was automatically generated by wxrc, do not edit by hand.\n")
661_T("//\n\n")
662_T("#ifndef __") + fileSpec + _T("_h__\n")
663_T("#define __") + fileSpec + _T("_h__\n")
f80ea77b 664);
1dce6f09 665 for(size_t i=0;i<aXRCWndClassData.Count();++i){
f80ea77b
WS
666 aXRCWndClassData.Item(i).GenerateHeaderCode(file);
667 }
1dce6f09 668 file.Write(
aa063b24
RD
669 _T("\nvoid \n")
670 + parFuncname
671 + _T("();\n#endif\n"));
1dce6f09
VS
672}
673
b8b8c49b
VS
674static wxString FileToPythonArray(wxString filename, int num)
675{
676 wxString output;
677 wxString tmp;
678 wxString snum;
5851504d 679 wxFFile file(filename, wxT("rb"));
2ad1ff54
WS
680 wxFileOffset offset = file.Length();
681 wxASSERT_MSG( offset >= 0 , wxT("Invalid file length") );
17a1ebd1
VZ
682
683 const size_t lng = wx_truncate_cast(size_t, offset);
684 wxASSERT_MSG( offset == lng, wxT("Huge file not supported") );
f80ea77b 685
2b5f62a0 686 snum.Printf(_T("%i"), num);
9a9942f7 687 output = _T(" xml_res_file_") + snum + _T(" = '''\\\n");
f80ea77b 688
b8b8c49b
VS
689 unsigned char *buffer = new unsigned char[lng];
690 file.Read(buffer, lng);
f80ea77b 691
b8b8c49b
VS
692 for (size_t i = 0, linelng = 0; i < lng; i++)
693 {
694 unsigned char c = buffer[i];
695 if (c == '\n')
696 {
697 tmp = (wxChar)c;
698 linelng = 0;
699 }
9a9942f7 700 else if (c < 32 || c > 127 || c == '\'')
2b5f62a0 701 tmp.Printf(_T("\\x%02x"), c);
b8b8c49b 702 else if (c == '\\')
2b5f62a0 703 tmp = _T("\\\\");
b8b8c49b
VS
704 else
705 tmp = (wxChar)c;
706 if (linelng > 70)
707 {
708 linelng = 0;
2b5f62a0 709 output << _T("\\\n");
b8b8c49b
VS
710 }
711 output << tmp;
712 linelng += tmp.Length();
713 }
f80ea77b 714
b8b8c49b 715 delete[] buffer;
f80ea77b 716
9a9942f7 717 output += _T("'''\n\n");
f80ea77b 718
b8b8c49b
VS
719 return output;
720}
721
722
723void XmlResApp::MakePackagePython(const wxArrayString& flist)
724{
5851504d 725 wxFFile file(parOutput, wxT("wt"));
b8b8c49b
VS
726 size_t i;
727
f80ea77b 728 if (flagVerbose)
2b5f62a0 729 wxPrintf(_T("creating Python source file ") + parOutput + _T("...\n"));
f80ea77b 730
b8b8c49b 731 file.Write(
2b5f62a0
VZ
732 _T("#\n")
733 _T("# This file was automatically generated by wxrc, do not edit by hand.\n")
734 _T("#\n\n")
b27a4ef4
RD
735 _T("import wx\n")
736 _T("import wx.xrc\n\n")
b8b8c49b
VS
737 );
738
f80ea77b 739
2b5f62a0 740 file.Write(_T("def ") + parFuncname + _T("():\n"));
b8b8c49b
VS
741
742 for (i = 0; i < flist.Count(); i++)
4249ec2c
VS
743 file.Write(
744 FileToPythonArray(parOutputPath + wxFILE_SEP_PATH + flist[i], i));
b8b8c49b 745
2ad1ff54 746 file.Write(
b27a4ef4
RD
747 _T(" # check if the memory filesystem handler has been loaded yet, and load it if not\n")
748 _T(" wx.MemoryFSHandler.AddFile('XRC_resource/dummy_file', 'dummy value')\n")
749 _T(" fsys = wx.FileSystem()\n")
750 _T(" f = fsys.OpenFile('memory:XRC_resource/dummy_file')\n")
751 _T(" wx.MemoryFSHandler.RemoveFile('XRC_resource/dummy_file')\n")
752 _T(" if f is not None:\n")
753 _T(" f.Destroy()\n")
754 _T(" else:\n")
755 _T(" wx.FileSystem.AddHandler(wx.MemoryFSHandler())\n")
756 _T("\n")
757 _T(" # load all the strings as memory files and load into XmlRes\n")
758 );
759
2ad1ff54 760
b8b8c49b
VS
761 for (i = 0; i < flist.Count(); i++)
762 {
763 wxString s;
b27a4ef4
RD
764 s.Printf(_T(" wx.MemoryFSHandler.AddFile('XRC_resource/") + flist[i] +
765 _T("', xml_res_file_%i)\n"), i);
b8b8c49b
VS
766 file.Write(s);
767 }
b27a4ef4
RD
768 for (i = 0; i < parFiles.Count(); i++)
769 {
770 file.Write(_T(" wx.xrc.XmlResource.Get().Load('memory:XRC_resource/") +
771 GetInternalFileName(parFiles[i], flist) + _T("')\n"));
772 }
773
774 file.Write(_T("\n"));
b8b8c49b
VS
775}
776
c8b7a961
VS
777
778
779void XmlResApp::OutputGettext()
780{
781 wxArrayString str = FindStrings();
f80ea77b 782
c8b7a961 783 wxFFile fout;
1dce6f09
VS
784 if (parOutput.empty())
785 fout.Attach(stdout);
786 else
787 fout.Open(parOutput, wxT("wt"));
f80ea77b 788
c8b7a961 789 for (size_t i = 0; i < str.GetCount(); i++)
0653d364 790 fout.Write(_T("_(\"") + str[i] + _T("\");\n"));
f80ea77b 791
c8b7a961
VS
792 if (!parOutput) fout.Detach();
793}
794
795
796
797wxArrayString XmlResApp::FindStrings()
798{
799 wxArrayString arr, a2;
800
801 for (size_t i = 0; i < parFiles.Count(); i++)
802 {
f80ea77b 803 if (flagVerbose)
2b5f62a0 804 wxPrintf(_T("processing ") + parFiles[i] + _T("...\n"));
c8b7a961 805
f80ea77b 806 wxXmlDocument doc;
c8b7a961
VS
807 if (!doc.Load(parFiles[i]))
808 {
2b5f62a0 809 wxLogError(_T("Error parsing file ") + parFiles[i]);
c8b7a961
VS
810 retCode = 1;
811 continue;
812 }
813 a2 = FindStrings(doc.GetRoot());
814 WX_APPEND_ARRAY(arr, a2);
815 }
f80ea77b 816
c8b7a961
VS
817 return arr;
818}
819
820
821
c109ef11
VS
822static wxString ConvertText(const wxString& str)
823{
824 wxString str2;
825 const wxChar *dt;
826
827 for (dt = str.c_str(); *dt; dt++)
828 {
829 if (*dt == wxT('_'))
830 {
831 if ( *(++dt) == wxT('_') )
832 str2 << wxT('_');
833 else
834 str2 << wxT('&') << *dt;
835 }
f80ea77b 836 else
c109ef11
VS
837 {
838 switch (*dt)
839 {
840 case wxT('\n') : str2 << wxT("\\n"); break;
841 case wxT('\t') : str2 << wxT("\\t"); break;
842 case wxT('\r') : str2 << wxT("\\r"); break;
2b5f62a0
VZ
843 case wxT('\\') : if ((*(dt+1) != 'n') &&
844 (*(dt+1) != 't') &&
845 (*(dt+1) != 'r'))
846 str2 << wxT("\\\\");
847 else
f80ea77b 848 str2 << wxT("\\");
2b5f62a0 849 break;
904a226c 850 case wxT('"') : str2 << wxT("\\\""); break;
c109ef11
VS
851 default : str2 << *dt; break;
852 }
853 }
854 }
855
856 return str2;
857}
858
859
c8b7a961
VS
860wxArrayString XmlResApp::FindStrings(wxXmlNode *node)
861{
862 wxArrayString arr;
863
864 wxXmlNode *n = node;
865 if (n == NULL) return arr;
866 n = n->GetChildren();
f80ea77b 867
c8b7a961
VS
868 while (n)
869 {
870 if ((node->GetType() == wxXML_ELEMENT_NODE) &&
871 // parent is an element, i.e. has subnodes...
f80ea77b 872 (n->GetType() == wxXML_TEXT_NODE ||
c8b7a961
VS
873 n->GetType() == wxXML_CDATA_SECTION_NODE) &&
874 // ...it is textnode...
875 (
876 node/*not n!*/->GetName() == _T("label") ||
877 (node/*not n!*/->GetName() == _T("value") &&
878 !n->GetContent().IsNumber()) ||
879 node/*not n!*/->GetName() == _T("help") ||
880 node/*not n!*/->GetName() == _T("longhelp") ||
881 node/*not n!*/->GetName() == _T("tooltip") ||
882 node/*not n!*/->GetName() == _T("htmlcode") ||
0653d364
VS
883 node/*not n!*/->GetName() == _T("title") ||
884 node/*not n!*/->GetName() == _T("item")
c8b7a961 885 ))
c109ef11 886 // ...and known to contain translatable string
c8b7a961 887 {
8da9d91c
VS
888 if (!flagGettext ||
889 node->GetPropVal(_T("translate"), _T("1")) != _T("0"))
890 {
891 arr.Add(ConvertText(n->GetContent()));
892 }
c8b7a961 893 }
f80ea77b 894
c8b7a961
VS
895 // subnodes:
896 if (n->GetType() == wxXML_ELEMENT_NODE)
897 {
898 wxArrayString a2 = FindStrings(n);
899 WX_APPEND_ARRAY(arr, a2);
900 }
f80ea77b 901
c8b7a961
VS
902 n = n->GetNext();
903 }
904 return arr;
905}