]> git.saurik.com Git - wxWidgets.git/blobdiff - src/richtext/richtextxml.cpp
Define KEY_WOW64_64KEY if it is missing from SDK headers.
[wxWidgets.git] / src / richtext / richtextxml.cpp
index c62cabfdac92376d9db7ecf58a3a6a721d2fd07d..de049434c78a9e159d5dab10d5424bdb0ccc9d98 100644 (file)
@@ -166,6 +166,12 @@ wxRichTextObject* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject*
         return new wxRichTextParagraph;
     else if (name == wxT("paragraphlayout"))
         return new wxRichTextParagraphLayoutBox;
+    else if (name == wxT("textbox"))
+        return new wxRichTextBox;
+    else if (name == wxT("cell"))
+        return new wxRichTextCell;
+    else if (name == wxT("table"))
+        return new wxRichTextTable;
     else
         return NULL;
 }
@@ -173,39 +179,18 @@ wxRichTextObject* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject*
 /// Recursively import an object
 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxRichTextObject* obj, wxXmlNode* node)
 {
-    obj->ImportFromXML(buffer, node, this);
+    bool recurse = false;
+    obj->ImportFromXML(buffer, node, this, & recurse);
+    
+    // TODO: how to control whether to import children.
     
     wxRichTextCompositeObject* compositeParent = wxDynamicCast(obj, wxRichTextCompositeObject);
-    if (compositeParent)
+    if (recurse && compositeParent)
     {
         wxXmlNode* child = node->GetChildren();
         while (child)
         {
-            if (child->GetName() == wxT("stylesheet"))
-            {
-                if (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET)
-                {
-                    wxRichTextStyleSheet* sheet = new wxRichTextStyleSheet;
-                    wxString sheetName = child->GetAttribute(wxT("name"), wxEmptyString);
-                    wxString sheetDescription = child->GetAttribute(wxT("description"), wxEmptyString);
-                    sheet->SetName(sheetName);
-                    sheet->SetDescription(sheetDescription);
-
-                    wxXmlNode* child2 = child->GetChildren();
-                    while (child2)
-                    {
-                        ImportStyleDefinition(sheet, child2);
-
-                        child2 = child2->GetNext();
-                    }
-
-                    // Notify that styles have changed. If this is vetoed by the app,
-                    // the new sheet will be deleted. If it is not vetoed, the
-                    // old sheet will be deleted and replaced with the new one.
-                    buffer->SetStyleSheetAndNotify(sheet);
-                }
-            }
-            else
+            if (child->GetName() != wxT("stylesheet"))
             {
                 wxRichTextObject* childObj = CreateObjectForXMLName(obj, child->GetName());
                 if (childObj)
@@ -301,6 +286,26 @@ bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet* sheet, wx
 
         sheet->AddParagraphStyle(def);
     }
+    else if (styleType == wxT("boxstyle"))
+    {
+        wxRichTextBoxStyleDefinition* def = new wxRichTextBoxStyleDefinition(styleName);
+
+        def->SetBaseStyle(baseStyleName);
+
+        wxXmlNode* child = node->GetChildren();
+        while (child)
+        {
+            if (child->GetName() == wxT("style"))
+            {
+                wxRichTextAttr attr;
+                ImportStyle(attr, child, true);
+                def->SetStyle(attr);
+            }
+            child = child->GetNext();
+        }
+
+        sheet->AddBoxStyle(def);
+    }
     else if (styleType == wxT("liststyle"))
     {
         wxRichTextListStyleDefinition* def = new wxRichTextListStyleDefinition(styleName);
@@ -399,6 +404,18 @@ wxString wxRichTextXMLHandler::GetText(wxXmlNode *node, const wxString& param, b
     return str1;
 }
 
+wxXmlNode* wxRichTextXMLHandler::FindNode(wxXmlNode* node, const wxString& name)
+{
+    wxXmlNode* child = node->GetChildren();
+    while (child)
+    {
+        if (child->GetName() == name)
+            return child;
+        child = child->GetNext();
+    }
+    return NULL;
+}
+
 // For use with earlier versions of wxWidgets
 #ifndef WXUNUSED_IN_UNICODE
 #if wxUSE_UNICODE
@@ -579,39 +596,39 @@ wxString wxRichTextXMLHandler::AttributeToXML(const wxString& str)
 
 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const int& v)
+static inline void AddAttribute(wxString& str, const wxString& name, const int& v)
 {
     str << wxT(" ") << name << wxT("=\"") << wxString::Format(wxT("%d"), v) << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const long& v)
+static inline void AddAttribute(wxString& str, const wxString& name, const long& v)
 {
     str << wxT(" ") << name << wxT("=\"") << wxString::Format(wxT("%ld"), v) << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const double& v)
+static inline void AddAttribute(wxString& str, const wxString& name, const double& v)
 {
     str << wxT(" ") << name << wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v) << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const wxChar* s)
+static inline void AddAttribute(wxString& str, const wxString& name, const wxChar* s)
 {
     str << wxT(" ") << name << wxT("=\"") << s << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const wxString& s)
+static inline void AddAttribute(wxString& str, const wxString& name, const wxString& s)
 {
     str << wxT(" ") << name << wxT("=\"") << s << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const wxColour& col)
+static inline void AddAttribute(wxString& str, const wxString& name, const wxColour& col)
 {
     str << wxT(" ") << name << wxT("=\"") << wxT("#") << ColourToHexString(col) << wxT("\"");
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* name, const wxTextAttrDimension& dim)
+static inline void AddAttribute(wxString& str, const wxString& name, const wxTextAttrDimension& dim)
 {
-    if (dim.IsPresent())
+    if (dim.IsValid())
     {
         wxString value = MakeString(dim.GetValue()) + wxT(",") + MakeString((int) dim.GetFlags());
         str << wxT(" ") << name << wxT("=\"");
@@ -620,24 +637,19 @@ static inline void AddAttribute(wxString& str, const wxChar* name, const wxTextA
     }
 }
 
-static inline void AddAttribute(wxString& str, const wxString& name, const wxTextAttrDimension& dim)
-{
-    AddAttribute(str, name.c_str(), dim);
-}
-
-static inline void AddAttribute(wxString& str, const wxChar* rootName, const wxTextAttrDimensions& dims)
+static inline void AddAttribute(wxString& str, const wxString& rootName, const wxTextAttrDimensions& dims)
 {
-    if (dims.GetLeft().IsPresent())
+    if (dims.GetLeft().IsValid())
         AddAttribute(str, rootName + wxString(wxT("-left")), dims.GetLeft());
-    if (dims.GetRight().IsPresent())
+    if (dims.GetRight().IsValid())
         AddAttribute(str, rootName + wxString(wxT("-right")), dims.GetRight());
-    if (dims.GetTop().IsPresent())
+    if (dims.GetTop().IsValid())
         AddAttribute(str, rootName + wxString(wxT("-top")), dims.GetTop());
-    if (dims.GetBottom().IsPresent())
+    if (dims.GetBottom().IsValid())
         AddAttribute(str, rootName + wxString(wxT("-bottom")), dims.GetBottom());
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* rootName, const wxTextAttrBorder& border)
+static inline void AddAttribute(wxString& str, const wxString& rootName, const wxTextAttrBorder& border)
 {
     if (border.HasStyle())
         AddAttribute(str, rootName + wxString(wxT("-style")), border.GetStyle());
@@ -647,7 +659,7 @@ static inline void AddAttribute(wxString& str, const wxChar* rootName, const wxT
         AddAttribute(str, rootName + wxString(wxT("-width")), border.GetWidth());
 }
 
-static inline void AddAttribute(wxString& str, const wxChar* rootName, const wxTextAttrBorders& borders)
+static inline void AddAttribute(wxString& str, const wxString& rootName, const wxTextAttrBorders& borders)
 {
     AddAttribute(str, rootName + wxString(wxT("-left")), borders.GetLeft());
     AddAttribute(str, rootName + wxString(wxT("-right")), borders.GetRight());
@@ -660,53 +672,53 @@ static inline void AddAttribute(wxString& str, const wxChar* rootName, const wxT
 
 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const int& v)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const int& v)
 {
     node->AddAttribute(name, MakeString(v));
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const long& v)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const long& v)
 {
     node->AddAttribute(name, MakeString(v));
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const double& v)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const double& v)
 {
     node->AddAttribute(name, MakeString(v));
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const wxString& s)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const wxString& s)
 {
     node->AddAttribute(name, s);
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const wxColour& col)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const wxColour& col)
 {
     node->AddAttribute(name, MakeString(col));
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* name, const wxTextAttrDimension& dim)
+static inline void AddAttribute(wxXmlNode* node, const wxString& name, const wxTextAttrDimension& dim)
 {
-    if (dim.IsPresent())
+    if (dim.IsValid())
     {
         wxString value = MakeString(dim.GetValue()) + wxT(",") + MakeString(dim.GetFlags());
         AddAttribute(node, name, value);
     }
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* rootName, const wxTextAttrDimensions& dims)
+static inline void AddAttribute(wxXmlNode* node, const wxString& rootName, const wxTextAttrDimensions& dims)
 {
-    if (dims.GetLeft().IsPresent())
+    if (dims.GetLeft().IsValid())
         AddAttribute(node, rootName + wxString(wxT("-left")), dims.GetLeft());
-    if (dims.GetRight().IsPresent())
+    if (dims.GetRight().IsValid())
         AddAttribute(node, rootName + wxString(wxT("-right")), dims.GetRight());
-    if (dims.GetTop().IsPresent())
+    if (dims.GetTop().IsValid())
         AddAttribute(node, rootName + wxString(wxT("-top")), dims.GetTop());
-    if (dims.GetBottom().IsPresent())
+    if (dims.GetBottom().IsValid())
         AddAttribute(node, rootName + wxString(wxT("-bottom")), dims.GetBottom());
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* rootName, const wxTextAttrBorder& border)
+static inline void AddAttribute(wxXmlNode* node, const wxString& rootName, const wxTextAttrBorder& border)
 {
     if (border.HasStyle())
         AddAttribute(node, rootName + wxString(wxT("-style")), border.GetStyle());
@@ -716,7 +728,7 @@ static inline void AddAttribute(wxXmlNode* node, const wxChar* rootName, const w
         AddAttribute(node, rootName + wxString(wxT("-width")), border.GetWidth());
 }
 
-static inline void AddAttribute(wxXmlNode* node, const wxChar* rootName, const wxTextAttrBorders& borders)
+static inline void AddAttribute(wxXmlNode* node, const wxString& rootName, const wxTextAttrBorders& borders)
 {
     AddAttribute(node, rootName + wxString(wxT("-left")), borders.GetLeft());
     AddAttribute(node, rootName + wxString(wxT("-right")), borders.GetRight());
@@ -814,6 +826,12 @@ bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
             wxRichTextListStyleDefinition* def = buffer->GetStyleSheet()->GetListStyle(i);
             ExportStyleDefinition(styleSheetNode, def);
         }
+
+        for (i = 0; i < (int) buffer->GetStyleSheet()->GetBoxStyleCount(); i++)
+        {
+            wxRichTextBoxStyleDefinition* def = buffer->GetStyleSheet()->GetBoxStyle(i);
+            ExportStyleDefinition(styleSheetNode, def);
+        }
     }
     bool success = ExportXML(rootNode, *buffer);
 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
@@ -883,6 +901,12 @@ bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream&
             ExportStyleDefinition(stream, def, level + 1);
         }
 
+        for (i = 0; i < (int) buffer->GetStyleSheet()->GetBoxStyleCount(); i++)
+        {
+            wxRichTextBoxStyleDefinition* def = buffer->GetStyleSheet()->GetBoxStyle(i);
+            ExportStyleDefinition(stream, def, level + 1);
+        }
+
         OutputIndentation(stream, level);
         OutputString(stream, wxT("</stylesheet>"));
     }
@@ -917,6 +941,7 @@ bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream& stream, wxRichT
     wxRichTextCharacterStyleDefinition* charDef = wxDynamicCast(def, wxRichTextCharacterStyleDefinition);
     wxRichTextParagraphStyleDefinition* paraDef = wxDynamicCast(def, wxRichTextParagraphStyleDefinition);
     wxRichTextListStyleDefinition* listDef = wxDynamicCast(def, wxRichTextListStyleDefinition);
+    wxRichTextBoxStyleDefinition* boxDef = wxDynamicCast(def, wxRichTextBoxStyleDefinition);
 
     wxString baseStyle = def->GetBaseStyle();
     wxString baseStyleProp;
@@ -1000,7 +1025,7 @@ bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream& stream, wxRichT
 
         level ++;
 
-        wxString style = AddAttributes(def->GetStyle(), false);
+        wxString style = AddAttributes(def->GetStyle(), true);
 
         OutputIndentation(stream, level);
         OutputString(stream, wxT("<style ") + style + wxT(">"));
@@ -1013,6 +1038,28 @@ bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream& stream, wxRichT
         OutputIndentation(stream, level);
         OutputString(stream, wxT("</paragraphstyle>"));
     }
+    else if (boxDef)
+    {
+        OutputIndentation(stream, level);
+
+        OutputString(stream, wxT("<boxstyle") + baseStyleProp + descrProp + wxT(">"));
+
+        level ++;
+
+        wxString style = AddAttributes(def->GetStyle(), true);
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("<style ") + style + wxT(">"));
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</style>"));
+
+        level --;
+
+        OutputIndentation(stream, level);
+        OutputString(stream, wxT("</boxstyle>"));
+    }
+
 
     return true;
 }
@@ -1153,9 +1200,9 @@ wxString wxRichTextXMLHandler::AddAttributes(const wxRichTextAttr& attr, bool is
         wxString value;
         if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT)
             value = wxT("left");
-        else if (attr.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT)
+        else if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT)
             value = wxT("right");
-        else if (attr.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH)
+        else if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH)
             value = wxT("both");
         else
             value = wxT("none");
@@ -1238,6 +1285,7 @@ bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode* parent, wxRichTextSt
 {
     wxRichTextCharacterStyleDefinition* charDef = wxDynamicCast(def, wxRichTextCharacterStyleDefinition);
     wxRichTextParagraphStyleDefinition* paraDef = wxDynamicCast(def, wxRichTextParagraphStyleDefinition);
+    wxRichTextBoxStyleDefinition* boxDef = wxDynamicCast(def, wxRichTextBoxStyleDefinition);
     wxRichTextListStyleDefinition* listDef = wxDynamicCast(def, wxRichTextListStyleDefinition);
 
     wxString baseStyle = def->GetBaseStyle();
@@ -1280,6 +1328,12 @@ bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode* parent, wxRichTextSt
             }
         }
     }
+    else if (boxDef)
+    {
+        defNode->SetName(wxT("boxstyle"));
+
+        AddAttributes(styleNode, def->GetStyle(), true);
+    }
     else if (paraDef)
     {
         defNode->SetName(wxT("paragraphstyle"));
@@ -1420,9 +1474,9 @@ bool wxRichTextXMLHandler::AddAttributes(wxXmlNode* node, wxRichTextAttr& attr,
         wxString value;
         if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT)
             value = wxT("left");
-        else if (attr.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT)
+        else if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT)
             value = wxT("right");
-        else if (attr.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH)
+        else if (attr.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH)
             value = wxT("both");
         else
             value = wxT("none");
@@ -1782,7 +1836,7 @@ bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr& attr, wxXmlNode* node, bo
                     attr.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE);
             }
             else if (name == wxT("collapse-borders"))
-                attr.GetTextBoxAttr().SetCollapseBorders(value == wxT("1"));
+                attr.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode) wxAtoi(value));
 
             else if (name.Contains(wxT("border-")))
             {
@@ -1887,10 +1941,12 @@ bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr& attr, wxXmlNode* node, bo
     // wxUSE_STREAMS
 
 // Import this object from XML
-bool wxRichTextObject::ImportFromXML(wxRichTextBuffer* WXUNUSED(buffer), wxXmlNode* node, wxRichTextXMLHandler* handler)
+bool wxRichTextObject::ImportFromXML(wxRichTextBuffer* WXUNUSED(buffer), wxXmlNode* node, wxRichTextXMLHandler* handler, bool* recurse)
 {
     handler->ImportProperties(this, node);
     handler->ImportStyle(GetAttributes(), node, UsesParagraphAttributes());
+    
+    *recurse = true;
 
     return true;
 }
@@ -1953,9 +2009,9 @@ bool wxRichTextObject::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handle
 
 
 // Import this object from XML
-bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler)
+bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler, bool* recurse)
 {
-    wxRichTextObject::ImportFromXML(buffer, node, handler);
+    wxRichTextObject::ImportFromXML(buffer, node, handler, recurse);
     
     if (node->GetName() == wxT("text"))
     {
@@ -2217,9 +2273,9 @@ bool wxRichTextPlainText::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* han
 
 
 // Import this object from XML
-bool wxRichTextImage::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler)
+bool wxRichTextImage::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler, bool* recurse)
 {
-    wxRichTextObject::ImportFromXML(buffer, node, handler);
+    wxRichTextObject::ImportFromXML(buffer, node, handler, recurse);
 
     wxBitmapType imageType = wxBITMAP_TYPE_PNG;
     wxString value = node->GetAttribute(wxT("imagetype"), wxEmptyString);
@@ -2336,9 +2392,10 @@ bool wxRichTextImage::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler
             if (stream.GetSize() > 0)
             {
                 int size = stream.GetSize();
+#ifdef __WXDEBUG__
                 int size2 = stream.GetOutputStreamBuffer()->GetIntPosition();
                 wxASSERT(size == size2);
-
+#endif
                 unsigned char* data = new unsigned char[size];
                 stream.CopyTo(data, size);
                 strData = wxString((const char*) data, wxConvUTF8, size);
@@ -2365,14 +2422,39 @@ bool wxRichTextImage::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler
 
 
 // Import this object from XML
-bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler)
+bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler, bool* recurse)
 {
-    wxRichTextObject::ImportFromXML(buffer, node, handler);
+    wxRichTextObject::ImportFromXML(buffer, node, handler, recurse);
+    
+    *recurse = true;
 
     wxString partial = node->GetAttribute(wxT("partialparagraph"), wxEmptyString);
     if (partial == wxT("true"))
         SetPartialParagraph(true);
 
+    wxXmlNode* child = wxRichTextXMLHandler::FindNode(node, wxT("stylesheet"));
+    if (child && (handler->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET))
+    {
+        wxRichTextStyleSheet* sheet = new wxRichTextStyleSheet;
+        wxString sheetName = child->GetAttribute(wxT("name"), wxEmptyString);
+        wxString sheetDescription = child->GetAttribute(wxT("description"), wxEmptyString);
+        sheet->SetName(sheetName);
+        sheet->SetDescription(sheetDescription);
+
+        wxXmlNode* child2 = child->GetChildren();
+        while (child2)
+        {
+            handler->ImportStyleDefinition(sheet, child2);
+
+            child2 = child2->GetNext();
+        }
+
+        // Notify that styles have changed. If this is vetoed by the app,
+        // the new sheet will be deleted. If it is not vetoed, the
+        // old sheet will be deleted and replaced with the new one.
+        buffer->SetStyleSheetAndNotify(sheet);
+    }
+
     return true;
 }
 
@@ -2381,7 +2463,8 @@ bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer* buffer, wxXml
 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler)
 {
     ::OutputIndentation(stream, indent);
-    ::OutputString(stream, wxT("<paragraphlayout"), handler->GetConvMem(), handler->GetConvFile());
+    wxString nodeName = GetXMLNodeName();
+    ::OutputString(stream, wxT("<") + nodeName, handler->GetConvMem(), handler->GetConvFile());
 
     wxString style = handler->AddAttributes(GetAttributes(), true);
 
@@ -2403,7 +2486,7 @@ bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream& stream, int indent,
     }
 
     ::OutputIndentation(stream, indent);
-    ::OutputString(stream, wxT("</paragraphlayout>"), handler->GetConvMem(), handler->GetConvFile());
+    ::OutputString(stream, wxT("</") + nodeName + wxT(">"), handler->GetConvMem(), handler->GetConvFile());
     return true;
 }
 #endif
@@ -2412,7 +2495,7 @@ bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream& stream, int indent,
 // Export this object to the given parent node, usually creating at least one child node.
 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler)
 {
-    wxXmlNode* elementNode = new wxXmlNode(wxXML_ELEMENT_NODE, wxT("paragraphlayout"));
+    wxXmlNode* elementNode = new wxXmlNode(wxXML_ELEMENT_NODE, GetXMLNodeName());
     parent->AddChild(elementNode);
     handler->AddAttributes(elementNode, GetAttributes(), true);
     handler->WriteProperties(elementNode, GetProperties());
@@ -2431,6 +2514,112 @@ bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode* parent, wxRichTextXMLHan
 }
 #endif
 
+// Import this object from XML
+bool wxRichTextTable::ImportFromXML(wxRichTextBuffer* buffer, wxXmlNode* node, wxRichTextXMLHandler* handler, bool* recurse)
+{
+    wxRichTextBox::ImportFromXML(buffer, node, handler, recurse);
+    
+    *recurse = false;
+
+    m_rowCount = wxAtoi(node->GetAttribute(wxT("rows"), wxEmptyString));
+    m_colCount = wxAtoi(node->GetAttribute(wxT("cols"), wxEmptyString));
+    
+    wxXmlNode* child = node->GetChildren();
+    while (child)
+    {
+        wxRichTextObject* childObj = handler->CreateObjectForXMLName(this, child->GetName());
+        if (childObj)
+        {
+            AppendChild(childObj);
+            handler->ImportXML(buffer, childObj, child);
+        }
+        child = child->GetNext();
+    }
+
+    m_cells.Add(wxRichTextObjectPtrArray(), m_rowCount);
+    int i, j;
+    for (i = 0; i < m_rowCount; i++)
+    {
+        wxRichTextObjectPtrArray& colArray = m_cells[i];
+        for (j = 0; j < m_colCount; j++)
+        {
+            int idx = i * m_colCount + j;
+            if (idx < (int) GetChildren().GetCount())
+            {
+                wxRichTextCell* cell = wxDynamicCast(GetChildren().Item(idx)->GetData(), wxRichTextCell);
+                if (cell)
+                    colArray.Add(cell);
+            }
+        }
+    }
+
+    return true;
+}
+
+#if wxRICHTEXT_HAVE_DIRECT_OUTPUT
+// Export this object directly to the given stream.
+bool wxRichTextTable::ExportXML(wxOutputStream& stream, int indent, wxRichTextXMLHandler* handler)
+{
+    ::OutputIndentation(stream, indent);
+    wxString nodeName = GetXMLNodeName();
+    ::OutputString(stream, wxT("<") + nodeName, handler->GetConvMem(), handler->GetConvFile());
+
+    wxString style = handler->AddAttributes(GetAttributes(), true);
+
+    style << wxT(" rows=\"") << m_rowCount << wxT("\"");
+    style << wxT(" cols=\"") << m_colCount << wxT("\"");
+
+    ::OutputString(stream, style + wxT(">"), handler->GetConvMem(), handler->GetConvFile());
+
+    if (GetProperties().GetCount() > 0)
+    {
+        handler->WriteProperties(stream, GetProperties(), indent);
+    }
+    
+    int i, j;
+    for (i = 0; i < m_rowCount; i++)
+    {
+        for (j = 0; j < m_colCount; j ++)
+        {
+            wxRichTextCell* cell = GetCell(i, j);
+            cell->ExportXML(stream, indent+1, handler);
+        }
+    }
+
+    ::OutputIndentation(stream, indent);
+    ::OutputString(stream, wxT("</") + nodeName + wxT(">"), handler->GetConvMem(), handler->GetConvFile());
+
+    return true;
+}
+#endif
+
+#if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
+// Export this object to the given parent node, usually creating at least one child node.
+bool wxRichTextTable::ExportXML(wxXmlNode* parent, wxRichTextXMLHandler* handler)
+{
+    wxXmlNode* elementNode = new wxXmlNode(wxXML_ELEMENT_NODE, GetXMLNodeName());
+    parent->AddChild(elementNode);
+    handler->AddAttributes(elementNode, GetAttributes(), true);
+    handler->WriteProperties(elementNode, GetProperties());
+
+    elementNode->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount));
+    elementNode->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount));
+
+    int i, j;
+    for (i = 0; i < m_rowCount; i++)
+    {
+        for (j = 0; j < m_colCount; j ++)
+        {
+            wxRichTextCell* cell = GetCell(i, j);
+            cell->ExportXML(elementNode, handler);
+        }
+    }
+
+    return true;
+}
+#endif
+
+
 #endif
     // wxUSE_RICHTEXT && wxUSE_XML