]> git.saurik.com Git - wxWidgets.git/blobdiff - contrib/src/xml/xmlpars.cpp
allow people use modal dialogs in wxApp::OnInit
[wxWidgets.git] / contrib / src / xml / xmlpars.cpp
index 797c76d0a9ca907de99100d07e8d07ad0205f7b2..978dab5fb1f3d0adcea6d35c3726765e21f8a790 100644 (file)
 #include "wx/xml/xmlio.h"
 
 #include <libxml/parser.h>
+#include <libxml/SAX.h>
+
+
+// wxWindows SAX handlers for bugs reporting:
+
+static void wxXmlParserError(void *ctx, const char *msg, ...)
+{
+    wxString text;
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    if (ctxt->input)
+       text.Printf( _("XML parser error at line %d: "), ctxt->input->line );
+    va_list args;
+    wxString tmp;
+    va_start(args, msg);
+    tmp.PrintfV( msg, args );
+    va_end(args);
+    text += tmp;
+    wxLogError( text.c_str() );
+}
+
+static void wxXmlParserWarning(void *ctx, const char *msg, ...)
+{
+    wxString text;
+    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
+    if (ctxt->input)
+       text.Printf( _("XML parser warning at line %d: "), ctxt->input->line );
+    va_list args;
+    wxString tmp;
+    va_start(args, msg);
+    tmp.PrintfV( msg, args );
+    va_end(args);
+    text += tmp;
+    wxLogWarning( text.c_str() );
+}
+
+static xmlSAXHandler gs_wxXmlSAXHandler;
+
+
 
 // dynamically loaded functions from libxml:
 typedef xmlParserCtxtPtr (*type_xmlCreatePushParserCtxt)
@@ -43,6 +81,11 @@ typedef xmlNodePtr (*type_xmlNewChild)(xmlNodePtr, xmlNsPtr, const xmlChar *, co
 typedef xmlChar * (*type_xmlNodeListGetString)(xmlDocPtr, xmlNodePtr, int);
 typedef xmlNodePtr (*type_xmlDocGetRootElement)(xmlDocPtr);
 typedef xmlNodePtr (*type_xmlDocSetRootElement)(xmlDocPtr doc, xmlNodePtr root);
+typedef void (*(*type_xmlFree))(void *);
+typedef int (*type_xmlKeepBlanksDefault)(int);
+typedef void (*type_xmlInitParser)(void);
+typedef void (*type_xmlCleanupParser)(void);
+typedef xmlSAXHandler *type_xmlDefaultSAXHandler;
 
 static struct
 {
@@ -62,6 +105,11 @@ static struct
     type_xmlNodeListGetString xmlNodeListGetString;
     type_xmlDocGetRootElement xmlDocGetRootElement;
     type_xmlDocSetRootElement xmlDocSetRootElement;
+    type_xmlFree xmlFree;
+    type_xmlKeepBlanksDefault xmlKeepBlanksDefault;
+    type_xmlInitParser xmlInitParser;
+    type_xmlCleanupParser xmlCleanupParser;
+    type_xmlDefaultSAXHandler xmlDefaultSAXHandler;
 } gs_libxmlDLL;
 
 static bool gs_libxmlLoaded = FALSE;
@@ -73,7 +121,7 @@ static void ReleaseLibxml()
 {
     if (gs_libxmlLoaded)
     {
-        wxLogDebug("Releasing libxml.so.2");
+        gs_libxmlDLL.xmlCleanupParser();
         wxDllLoader::UnloadLibrary(gs_libxmlDLL.Handle);
     }
     gs_libxmlLoaded = FALSE;
@@ -87,18 +135,37 @@ static bool LoadLibxml()
     if (gs_libxmlLoadFailed) return FALSE;
     gs_libxmlLoadFailed = TRUE;
 
-    wxLogDebug("Loading libxml.so.2...");
+    {
+    wxLogNull lg;
 #ifdef __UNIX__
     gs_libxmlDLL.Handle = 
+        wxDllLoader::LoadLibrary(_T("wxlibxml.so.2"), &gs_libxmlLoaded);
+    if (!gs_libxmlLoaded) gs_libxmlDLL.Handle = 
         wxDllLoader::LoadLibrary(_T("libxml.so.2"), &gs_libxmlLoaded);
 #endif
+#ifdef __WXMSW__
+    gs_libxmlDLL.Handle = 
+        wxDllLoader::LoadLibrary(_T("wxlibxml2.dll"), &gs_libxmlLoaded);
+    if (!gs_libxmlLoaded) gs_libxmlDLL.Handle = 
+        wxDllLoader::LoadLibrary(_T("libxml2.dll"), &gs_libxmlLoaded);
+#endif
+    }
     
-    if (!gs_libxmlLoaded) return FALSE;
+    if (!gs_libxmlLoaded) 
+    {
+        wxLogError(_("Failed to load libxml shared library."));
+        return FALSE;
+    }
     
 #define LOAD_SYMBOL(sym) \
     gs_libxmlDLL.sym = \
         (type_##sym)wxDllLoader::GetSymbol(gs_libxmlDLL.Handle, _T(#sym)); \
-    if (!gs_libxmlDLL.sym) { ReleaseLibxml(); return FALSE; }
+    if (!gs_libxmlDLL.sym) \
+    { \
+        ReleaseLibxml(); \
+        wxLogError(_("Failed to load libxml shared library.")); \
+        return FALSE; \
+    }
 
     LOAD_SYMBOL(xmlCreatePushParserCtxt)
     LOAD_SYMBOL(xmlNewText)
@@ -114,12 +181,23 @@ static bool LoadLibxml()
     LOAD_SYMBOL(xmlNodeListGetString)
     LOAD_SYMBOL(xmlDocGetRootElement)
     LOAD_SYMBOL(xmlDocSetRootElement)
+    LOAD_SYMBOL(xmlFree)
+    LOAD_SYMBOL(xmlKeepBlanksDefault)
+    LOAD_SYMBOL(xmlInitParser)
+    LOAD_SYMBOL(xmlCleanupParser)
+    LOAD_SYMBOL(xmlDefaultSAXHandler)
 
 #undef LOAD_SYMBOL    
 
     gs_libxmlLoadFailed = FALSE;
+    
+    gs_libxmlDLL.xmlInitParser();
+    memcpy(&gs_wxXmlSAXHandler, gs_libxmlDLL.xmlDefaultSAXHandler,
+           sizeof(xmlSAXHandler));
+    gs_wxXmlSAXHandler.error = wxXmlParserError;
+    gs_wxXmlSAXHandler.fatalError = wxXmlParserError;
+    gs_wxXmlSAXHandler.warning = wxXmlParserWarning;
 
-    wxLogDebug("...succeed");
     return TRUE;
 }
 
@@ -153,7 +231,7 @@ static wxXmlProperty *CreateWXProperty(xmlDocPtr doc, xmlAttrPtr attr)
         gs_libxmlDLL.xmlNodeListGetString(doc, attr->children, 1);
     wxXmlProperty *prop = 
         new wxXmlProperty(attr->name, val, CreateWXProperty(doc, attr->next));
-    free(val);
+    (*gs_libxmlDLL.xmlFree)(val);
     return prop;
 }
 
@@ -187,8 +265,9 @@ bool wxXmlIOHandlerLibxml::Load(wxInputStream& stream, wxXmlDocument& doc)
     if (res > 0)
     {
         bool okay = TRUE;
-        ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(NULL, NULL, 
-                                               buffer, res, ""/*docname*/);
+        gs_libxmlDLL.xmlKeepBlanksDefault(0);
+        ctxt = gs_libxmlDLL.xmlCreatePushParserCtxt(&gs_wxXmlSAXHandler, 
+                                          NULL, buffer, res, ""/*docname*/);
         while ((res = stream.Read(buffer, 1024).LastRead()) > 0) 
             if (gs_libxmlDLL.xmlParseChunk(ctxt, buffer, res, 0) != 0) 
                okay = FALSE;
@@ -249,6 +328,7 @@ bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc
 
     wxASSERT_MSG(doc.GetRoot() != NULL, _("Trying to save empty document!"));
     
+    gs_libxmlDLL.xmlKeepBlanksDefault(0);
     dc = gs_libxmlDLL.xmlNewDoc((xmlChar*)doc.GetVersion().mb_str());
     
     gs_libxmlDLL.xmlDocSetRootElement(dc, 
@@ -262,7 +342,7 @@ bool wxXmlIOHandlerLibxml::Save(wxOutputStream& stream, const wxXmlDocument& doc
     gs_libxmlDLL.xmlDocDumpMemory(dc, &buffer, &size);
     gs_libxmlDLL.xmlFreeDoc(dc);
     stream.Write(buffer, size);
-    free(buffer);
+    (*gs_libxmlDLL.xmlFree)(buffer);
     return stream.LastWrite() == (unsigned)size;
 }