]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/xml/xmlpars.cpp
allow people use modal dialogs in wxApp::OnInit
[wxWidgets.git] / contrib / src / xml / xmlpars.cpp
CommitLineData
56d2f750
VS
1/////////////////////////////////////////////////////////////////////////////
2// Name: xmlpars.cpp
3// Purpose: wxXmlDocument - XML parser
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// nothing - already in xml.cpp
13#endif
14
15// For compilers that support precompilation, includes "wx.h".
16#include "wx/wxprec.h"
17
18#ifdef __BORLANDC__
19 #pragma hdrstop
20#endif
21
22#include "wx/wfstream.h"
23#include "wx/intl.h"
24#include "wx/log.h"
25#include "wx/dynlib.h"
26#include "wx/xml/xmlio.h"
27
28#include <libxml/parser.h>
2dc1ca84
VS
29#include <libxml/SAX.h>
30
31
32// wxWindows SAX handlers for bugs reporting:
33
34static void wxXmlParserError(void *ctx, const char *msg, ...)
35{
36 wxString text;
37 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
38 if (ctxt->input)
39 text.Printf( _("XML parser error at line %d: "), ctxt->input->line );
40 va_list args;
41 wxString tmp;
42 va_start(args, msg);
43 tmp.PrintfV( msg, args );
44 va_end(args);
45 text += tmp;
46 wxLogError( text.c_str() );
47}
48
49static void wxXmlParserWarning(void *ctx, const char *msg, ...)
50{
51 wxString text;
52 xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
53 if (ctxt->input)
54 text.Printf( _("XML parser warning at line %d: "), ctxt->input->line );
55 va_list args;
56 wxString tmp;
57 va_start(args, msg);
58 tmp.PrintfV( msg, args );
59 va_end(args);
60 text += tmp;
61 wxLogWarning( text.c_str() );
62}
63
64static xmlSAXHandler gs_wxXmlSAXHandler;
65
66
56d2f750
VS
67
68// dynamically loaded functions from libxml:
69typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt)
70 (xmlSAXHandlerPtr sax, void *, const char *, int, const char *);
71typedef xmlNodePtr (*type_xmlNewText)(const xmlChar *);
72typedef xmlAttrPtr (*type_xmlSetProp)(xmlNodePtr, const xmlChar *, const xmlChar *);
73typedef int (*type_xmlParseChunk)(xmlParserCtxtPtr, const char *, int, int);
74typedef void (*type_xmlFreeParserCtxt)(xmlParserCtxtPtr);
75typedef xmlDocPtr (*type_xmlNewDoc)(const xmlChar *);
76typedef void (*type_xmlFreeDoc)(xmlDocPtr);
77typedef xmlNodePtr (*type_xmlNewDocNode)(xmlDocPtr, xmlNsPtr, const xmlChar *, const xmlChar *);
78typedef void (*type_xmlDocDumpMemory)(xmlDocPtr, xmlChar**, int *);
79typedef xmlNodePtr (*type_xmlAddChild)(xmlNodePtr, xmlNodePtr);
80typedef xmlNodePtr (*type_xmlNewChild)(xmlNodePtr, xmlNsPtr, const xmlChar *, const xmlChar *);
81typedef xmlChar * (*type_xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int);
82typedef xmlNodePtr (*type_xmlDocGetRootElement)(xmlDocPtr);
83typedef xmlNodePtr (*type_xmlDocSetRootElement)(xmlDocPtr doc, xmlNodePtr root);
dfc0e3fb
VS
84typedef void (*(*type_xmlFree))(void *);
85typedef int (*type_xmlKeepBlanksDefault)(int);
2dc1ca84
VS
86typedef void (*type_xmlInitParser)(void);
87typedef void (*type_xmlCleanupParser)(void);
88typedef xmlSAXHandler *type_xmlDefaultSAXHandler;
56d2f750
VS
89
90static struct
91{
92 wxDllType Handle;
93
94 type_xmlCreatePushParserCtxt xmlCreatePushParserCtxt;
95 type_xmlNewText xmlNewText;
96 type_xmlSetProp xmlSetProp;
97 type_xmlParseChunk xmlParseChunk;
98 type_xmlFreeParserCtxt xmlFreeParserCtxt;
99 type_xmlNewDoc xmlNewDoc;
100 type_xmlFreeDoc xmlFreeDoc;
101 type_xmlNewDocNode xmlNewDocNode;
102 type_xmlDocDumpMemory xmlDocDumpMemory;
103 type_xmlAddChild xmlAddChild;
104 type_xmlNewChild xmlNewChild;
105 type_xmlNodeListGetString xmlNodeListGetString;
106 type_xmlDocGetRootElement xmlDocGetRootElement;
107 type_xmlDocSetRootElement xmlDocSetRootElement;
dfc0e3fb
VS
108 type_xmlFree xmlFree;
109 type_xmlKeepBlanksDefault xmlKeepBlanksDefault;
2dc1ca84
VS
110 type_xmlInitParser xmlInitParser;
111 type_xmlCleanupParser xmlCleanupParser;
112 type_xmlDefaultSAXHandler xmlDefaultSAXHandler;
56d2f750
VS
113} gs_libxmlDLL;
114
115static bool gs_libxmlLoaded = FALSE;
116static bool gs_libxmlLoadFailed = FALSE;
117
118
119
120static void ReleaseLibxml()
121{
122 if (gs_libxmlLoaded)
123 {
2dc1ca84 124 gs_libxmlDLL.xmlCleanupParser();
56d2f750
VS
125 wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle);
126 }
127 gs_libxmlLoaded = FALSE;
128 gs_libxmlLoadFailed = FALSE;
129}
130
131
132static bool LoadLibxml()
133{
134 if (gs_libxmlLoaded) return TRUE;
135 if (gs_libxmlLoadFailed) return FALSE;
136 gs_libxmlLoadFailed = TRUE;
137
dfc0e3fb
VS
138 {
139 wxLogNull lg;
56d2f750
VS
140#ifdef __UNIX__
141 gs_libxmlDLL.Handle =
dfc0e3fb
VS
142 wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded);
143 if (!gs_libxmlLoaded) gs_libxmlDLL.Handle =
56d2f750
VS
144 wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded);
145#endif
dfc0e3fb
VS
146#ifdef __WXMSW__
147 gs_libxmlDLL.Handle =
148 wxDllLoader::LoadLibrary(_T("wxlibxml2.dll"), &gs_libxmlLoaded);
149 if (!gs_libxmlLoaded) gs_libxmlDLL.Handle =
150 wxDllLoader::LoadLibrary(_T("libxml2.dll"), &gs_libxmlLoaded);
151#endif
152 }
56d2f750 153
dfc0e3fb
VS
154 if (!gs_libxmlLoaded)
155 {
156 wxLogError(_("Failed to load libxml shared library."));
157 return FALSE;
158 }
56d2f750
VS
159
160#define LOAD_SYMBOL(sym) \
161 gs_libxmlDLL.sym = \
162 (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
dfc0e3fb
VS
163 if (!gs_libxmlDLL.sym) \
164 { \
165 ReleaseLibxml(); \
166 wxLogError(_("Failed to load libxml shared library.")); \
167 return FALSE; \
168 }
56d2f750
VS
169
170 LOAD_SYMBOL(xmlCreatePushParserCtxt)
171 LOAD_SYMBOL(xmlNewText)
172 LOAD_SYMBOL(xmlSetProp)
173 LOAD_SYMBOL(xmlParseChunk)
174 LOAD_SYMBOL(xmlFreeParserCtxt)
175 LOAD_SYMBOL(xmlNewDoc)
176 LOAD_SYMBOL(xmlFreeDoc)
177 LOAD_SYMBOL(xmlNewDocNode)
178 LOAD_SYMBOL(xmlDocDumpMemory)
179 LOAD_SYMBOL(xmlAddChild)
180 LOAD_SYMBOL(xmlNewChild)
181 LOAD_SYMBOL(xmlNodeListGetString)
182 LOAD_SYMBOL(xmlDocGetRootElement)
183 LOAD_SYMBOL(xmlDocSetRootElement)
dfc0e3fb
VS
184 LOAD_SYMBOL(xmlFree)
185 LOAD_SYMBOL(xmlKeepBlanksDefault)
2dc1ca84
VS
186 LOAD_SYMBOL(xmlInitParser)
187 LOAD_SYMBOL(xmlCleanupParser)
188 LOAD_SYMBOL(xmlDefaultSAXHandler)
56d2f750
VS
189
190#undef LOAD_SYMBOL
191
192 gs_libxmlLoadFailed = FALSE;
2dc1ca84
VS
193
194 gs_libxmlDLL.xmlInitParser();
195 memcpy(&gs_wxXmlSAXHandler, gs_libxmlDLL.xmlDefaultSAXHandler,
196 sizeof(xmlSAXHandler));
197 gs_wxXmlSAXHandler.error = wxXmlParserError;
198 gs_wxXmlSAXHandler.fatalError = wxXmlParserError;
199 gs_wxXmlSAXHandler.warning = wxXmlParserWarning;
56d2f750 200
56d2f750
VS
201 return TRUE;
202}
203
204
205
206
207bool wxXmlIOHandlerLibxml::CanLoad(wxInputStream& stream)
208{
209 if (!LoadLibxml()) return FALSE;
210 char cheader[7];
211 cheader[6] = 0;
212 stream.Read(cheader, 6);
213 stream.SeekI(-6, wxFromCurrent);
214 return strcmp(cheader, "<?xml ") == 0;
215}
216
217
218
219bool wxXmlIOHandlerLibxml::CanSave()
220{
221 return LoadLibxml();
222}
223
224
225
226static wxXmlProperty *CreateWXProperty(xmlDocPtr doc, xmlAttrPtr attr)
227{
228 if (attr == NULL) return NULL;
229
230 unsigned char *val =
231 gs_libxmlDLL.xmlNodeListGetString(doc, attr->children, 1);
232 wxXmlProperty *prop =
233 new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next));
dfc0e3fb 234 (*gs_libxmlDLL.xmlFree)(val);
56d2f750
VS
235 return prop;
236}
237
238
239
240static wxXmlNode *CreateWXNode(xmlDocPtr doc, wxXmlNode *parent, xmlNodePtr node)
241{
242 if (node == NULL) return NULL;
243
244 wxXmlNode *nd = new wxXmlNode(parent, (wxXmlNodeType)node->type,
245 node->name, node->content,
246 CreateWXProperty(doc, node->properties),
247 CreateWXNode(doc, parent, node->next));
248 CreateWXNode(doc, nd, node->children);
249 return nd;
250}
251
252
253
254bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc)
255{
256 if (!LoadLibxml()) return FALSE;
257
258 xmlDocPtr dc;
259 xmlParserCtxtPtr ctxt;
260
261 char buffer[1024];
262 int res;
263
264 res = stream.Read(buffer, 4).LastRead();
265 if (res > 0)
266 {
267 bool okay = TRUE;
dfc0e3fb 268 gs_libxmlDLL.xmlKeepBlanksDefault(0);
2dc1ca84
VS
269 ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(&gs_wxXmlSAXHandler,
270 NULL, buffer, res, ""/*docname*/);
56d2f750
VS
271 while ((res = stream.Read(buffer, 1024).LastRead()) > 0)
272 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0)
273 okay = FALSE;
274 if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, 0, 1) != 0) okay = FALSE;
275 dc = ctxt->myDoc;
276 gs_libxmlDLL.xmlFreeParserCtxt(ctxt);
277
278 doc.SetVersion(dc->version);
279 doc.SetEncoding(dc->encoding);
280 doc.SetRoot(CreateWXNode(dc, NULL, gs_libxmlDLL.xmlDocGetRootElement(dc)));
281
282 gs_libxmlDLL.xmlFreeDoc(dc);
283
284 return okay;
285 }
286 else return FALSE;
287}
288
289
290
291static void CreateLibxmlNode(xmlNodePtr node, wxXmlNode *wxnode)
292{
293 node->type = (xmlElementType)wxnode->GetType();
294
295 wxXmlProperty *prop = wxnode->GetProperties();
296 while (prop)
297 {
298 gs_libxmlDLL.xmlSetProp(node, (xmlChar*)prop->GetName().mb_str(),
299 (xmlChar*)prop->GetValue().mb_str());
300 prop = prop->GetNext();
301 }
302
303 wxXmlNode *child = wxnode->GetChildren();
304 xmlNodePtr n;
305 xmlChar *content, *name;
306
307 while (child)
308 {
309 name = (xmlChar*)child->GetName().mb_str();
310 if (!child->GetContent()) content = NULL;
311 else content = (xmlChar*)child->GetContent().mb_str();
312 if (child->GetType() == wxXML_TEXT_NODE)
313 gs_libxmlDLL.xmlAddChild(node, n = gs_libxmlDLL.xmlNewText(content));
314 else
315 n = gs_libxmlDLL.xmlNewChild(node, NULL, name, content);
316 CreateLibxmlNode(n, child);
317 child = child->GetNext();
318 }
319}
320
321
322
323bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc)
324{
325 if (!LoadLibxml()) return FALSE;
326
327 xmlDocPtr dc;
328
329 wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!"));
330
dfc0e3fb 331 gs_libxmlDLL.xmlKeepBlanksDefault(0);
56d2f750
VS
332 dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str());
333
334 gs_libxmlDLL.xmlDocSetRootElement(dc,
335 gs_libxmlDLL.xmlNewDocNode(dc, NULL,
336 (xmlChar*)doc.GetRoot()->GetName().mb_str(), NULL));
337 CreateLibxmlNode(gs_libxmlDLL.xmlDocGetRootElement(dc), doc.GetRoot());
338
339 xmlChar *buffer;
340 int size;
341
342 gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size);
343 gs_libxmlDLL.xmlFreeDoc(dc);
344 stream.Write(buffer, size);
dfc0e3fb 345 (*gs_libxmlDLL.xmlFree)(buffer);
56d2f750
VS
346 return stream.LastWrite() == (unsigned)size;
347}
348
349
350
351
352#include "wx/module.h"
353
354class wxXmlLibxmlModule: public wxModule
355{
356 DECLARE_DYNAMIC_CLASS(wxXmlLibxmlModule)
357 public:
358 wxXmlLibxmlModule() {}
359 bool OnInit() { return TRUE; }
360 void OnExit() { ReleaseLibxml(); }
361};
362
363IMPLEMENT_DYNAMIC_CLASS(wxXmlLibxmlModule, wxModule)