added binz handler
[wxWidgets.git] / utils / wxrc / wxrc.cpp
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
11 #ifdef __GNUG__
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"
30 #include "wx/xml/xml.h"
31 #include "wx/xml/xmlio.h"
32 #include "wx/ffile.h"
33
34 /*
35 #if wxUSE_GUI
36 #error "You must compile the resource compiler with wxBase!"
37 #endif
38 */
39
40 class XmlResApp : public wxApp
41 {
42 public:
43
44 #if wxUSE_GUI
45 bool OnInit();
46 #else
47 virtual int OnRun();
48 #endif
49
50 private:
51
52 void ParseParams(const wxCmdLineParser& cmdline);
53 void CompileRes();
54 wxArrayString PrepareTempFiles();
55 void DeleteTempFiles(const wxArrayString& flist);
56 void MakePackageZIP(const wxArrayString& flist);
57 void MakePackageCPP(const wxArrayString& flist);
58
59 bool flagVerbose, flagCPP, flagCompress;
60 wxString parOutput, parFuncname, parOutputPath;
61 wxArrayString parFiles;
62 int retCode;
63 };
64
65 IMPLEMENT_APP(XmlResApp)
66
67 #if wxUSE_GUI
68 bool XmlResApp::OnInit()
69 #else
70 int XmlResApp::OnRun()
71 #endif
72 {
73 static const wxCmdLineEntryDesc cmdLineDesc[] =
74 {
75 { wxCMD_LINE_SWITCH, "v", "verbose", "be verbose" },
76 { wxCMD_LINE_SWITCH, "c", "cpp-code", "output C++ source rather than .rsc file" },
77 { wxCMD_LINE_SWITCH, "u", "uncompressed", "do not compress .xml files (C++ only)" },
78 { wxCMD_LINE_OPTION, "n", "function", "C++ function name (with -c) [InitXmlResource]" },
79 { wxCMD_LINE_OPTION, "o", "output", "output file [resource.rsc/cpp]" },
80 { wxCMD_LINE_OPTION, "l", "list-of-handlers", "output list of neccessary handlers to this file" },
81
82 { wxCMD_LINE_PARAM, NULL, NULL, "input file",
83 wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_MULTIPLE },
84
85 { wxCMD_LINE_NONE }
86 };
87
88 wxXmlDocument::AddHandler(new wxXmlIOHandlerBinZ);
89
90 wxCmdLineParser parser(cmdLineDesc, argc, argv);
91
92 switch (parser.Parse())
93 {
94 case -1:
95 return 0;
96 break;
97
98 case 0:
99 retCode = 0;
100 ParseParams(parser);
101 CompileRes();
102 #if wxUSE_GUI
103 return FALSE;
104 #else
105 return retCode;
106 #endif
107 break;
108
109 default:
110 #if wxUSE_GUI
111 return FALSE;
112 #else
113 return 1;
114 #endif
115 break;
116 }
117 }
118
119
120
121
122 void XmlResApp::ParseParams(const wxCmdLineParser& cmdline)
123 {
124 flagVerbose = cmdline.Found("v");
125 flagCPP = cmdline.Found("c");
126 flagCompress = flagCPP && !cmdline.Found("u");
127
128 if (!cmdline.Found("o", &parOutput))
129 parOutput = flagCPP ? "resource.cpp" : "resource.rsc";
130 parOutputPath = wxPathOnly(parOutput);
131 if (!parOutputPath) parOutputPath = ".";
132
133 if (!cmdline.Found("n", &parFuncname))
134 parFuncname = "InitXmlResource";
135
136 for (size_t i = 0; i < cmdline.GetParamCount(); i++)
137 parFiles.Add(cmdline.GetParam(i));
138 }
139
140
141
142
143 void XmlResApp::CompileRes()
144 {
145 wxArrayString files = PrepareTempFiles();
146
147 wxRemoveFile(parOutput);
148
149 printf("TODO: include bitmaps, list of handlers\n");
150
151 if (!retCode)
152 {
153 if (flagCPP)
154 MakePackageCPP(files);
155 else
156 MakePackageZIP(files);
157 }
158
159 DeleteTempFiles(files);
160 }
161
162
163
164 wxArrayString XmlResApp::PrepareTempFiles()
165 {
166 wxArrayString flist;
167
168 for (size_t i = 0; i < parFiles.Count(); i++)
169 {
170 if (flagVerbose)
171 wxPrintf("processing " + parFiles[i] + "...\n");
172
173 wxXmlDocument doc;
174
175 if (!doc.Load(parFiles[i]))
176 {
177 wxLogError("Error parsing file " + parFiles[i]);
178 retCode = 1;
179 continue;
180 }
181
182 wxString name, ext;
183 wxSplitPath(parFiles[i], NULL, &name, &ext);
184
185 doc.Save(parOutputPath + "/" + name + ".xmb", flagCompress ? wxXML_IO_BINZ : wxXML_IO_BIN);
186 flist.Add(name + ".xmb");
187 }
188
189 return flist;
190 }
191
192
193
194 void XmlResApp::DeleteTempFiles(const wxArrayString& flist)
195 {
196 for (size_t i = 0; i < flist.Count(); i++)
197 wxRemoveFile(parOutputPath + "/" + flist[i]);
198 }
199
200
201
202 void XmlResApp::MakePackageZIP(const wxArrayString& flist)
203 {
204 wxString files;
205
206 for (size_t i = 0; i < flist.Count(); i++)
207 files += flist[i] + " ";
208 files.RemoveLast();
209
210 if (flagVerbose)
211 wxPrintf("compressing " + parOutput + "...\n");
212
213 if (wxExecute("zip -9 -j " + wxString(flagVerbose ? "" : "-q ") +
214 parOutput + " " + files, TRUE) == -1)
215 {
216 wxLogError("Unable to execute zip program. Make sure it is in the path.");
217 wxLogError("You can download it at http://www.cdrom.com/pub/infozip/");
218 retCode = 1;
219 return;
220 }
221 }
222
223
224
225
226 static wxString FileToCppArray(wxString filename, int num)
227 {
228 wxString output;
229 wxString snum;
230 wxString tmp;
231 wxFFile file(filename, "rb");
232 size_t lng = file.Length();
233
234 snum.Printf("%i", num);
235 output.Printf("static size_t xml_res_size_" + snum + " = %i;\n", lng);
236 output += "static unsigned char xml_res_file_" + snum + "[] = {";
237
238 unsigned char *buffer = new unsigned char[lng];
239 file.Read(buffer, lng);
240
241 for (size_t i = 0; i < lng; i++)
242 {
243 if (i % 16 == 0) output += "\n";
244 tmp.Printf("0x%02X", buffer[i]);
245 output += tmp;
246 if (i != lng-1) output += ",";
247 }
248
249 delete[] buffer;
250
251 output += "\n};\n\n";
252
253 return output;
254 }
255
256
257 void XmlResApp::MakePackageCPP(const wxArrayString& flist)
258 {
259 wxFFile file(parOutput, "wt");
260 size_t i;
261
262 if (flagVerbose)
263 wxPrintf("creating C++ source file " + parOutput + "...\n");
264
265 file.Write("\
266 #include \"wx/wxprec.h\"\n\
267 \n\
268 #ifdef __BORLANDC__\n\
269 #pragma hdrstop\n\
270 #endif\n\
271 \n\
272 #ifndef WX_PRECOMP\n\
273 #include \"wx/wx.h\"\n\
274 #endif\n\
275 \
276 #include \"wx/filesys.h\"\n\
277 #include \"wx/fs_mem.h\"\n\
278 #include \"wx/xml/xmlres.h\"\n\
279 #include \"wx/xml/xh_all.h\"\n\
280 \n");
281
282 for (i = 0; i < flist.Count(); i++)
283 file.Write(FileToCppArray(flist[i], i));
284
285 file.Write("\
286 void " + parFuncname + "()\n\
287 {\n\
288 \n\
289 // Check for memory FS. If not present, load the handler:\n\
290 {\n\
291 wxMemoryFSHandler::AddFile(\"xml_resource/dummy_file\", \"dummy one\");\n\
292 wxFileSystem fsys;\n\
293 wxFSFile *f = fsys.OpenFile(\"memory:xml_resource/dummy_file\");\n\
294 wxMemoryFSHandler::RemoveFile(\"xml_resource/dummy_file\");\n\
295 if (f) delete f;\n\
296 else wxFileSystem::AddHandler(new wxMemoryFSHandler);\n\
297 }\n\
298 \n");
299
300 for (i = 0; i < flist.Count(); i++)
301 {
302 wxString s;
303 s.Printf(" wxMemoryFSHandler::AddFile(\"xml_resource/" + flist[i] +
304 "\", xml_res_file_%i, xml_res_size_%i);\n"
305 " wxTheXmlResource->Load(\"memory:xml_resource/" + flist[i] +
306 "\", wxXML_BINARY);\n", i, i);
307 file.Write(s);
308 }
309
310 file.Write("\n}\n");
311
312 }