1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextxml.cpp
3 // Purpose: XML and HTML I/O for wxRichTextCtrl
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
19 #if wxUSE_RICHTEXT && wxUSE_XML
21 #include "wx/richtext/richtextxml.h"
25 #include "wx/module.h"
29 #include "wx/filename.h"
30 #include "wx/clipbrd.h"
31 #include "wx/wfstream.h"
32 #include "wx/sstream.h"
33 #include "wx/txtstrm.h"
34 #include "wx/mstream.h"
35 #include "wx/tokenzr.h"
36 #include "wx/stopwatch.h"
37 #include "wx/xml/xml.h"
39 // Set to 1 for slower wxXmlDocument method, 0 for faster direct method.
40 // If we make wxXmlDocument::Save more efficient, we might switch to this
42 #define wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT 0
44 #if wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
45 # error Must define wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT in richtextxml.h to use this method.
48 #if !wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_DIRECT_OUTPUT
49 # error Must define wxRICHTEXT_HAVE_DIRECT_OUTPUT in richtextxml.h to use this method.
52 // Set to 1 to time file saving
53 #define wxRICHTEXT_USE_OUTPUT_TIMINGS 0
55 // Convert a colour to a 6-digit hex string
56 static wxString
ColourToHexString(const wxColour
& col
)
60 hex
+= wxDecToHex(col
.Red());
61 hex
+= wxDecToHex(col
.Green());
62 hex
+= wxDecToHex(col
.Blue());
67 // Convert 6-digit hex string to a colour
68 static wxColour
HexStringToColour(const wxString
& hex
)
70 unsigned char r
= (unsigned char)wxHexToDec(hex
.Mid(0, 2));
71 unsigned char g
= (unsigned char)wxHexToDec(hex
.Mid(2, 2));
72 unsigned char b
= (unsigned char)wxHexToDec(hex
.Mid(4, 2));
74 return wxColour(r
, g
, b
);
77 static inline wxString
MakeString(const int& v
) { return wxString::Format(wxT("%d"), v
); }
78 static inline wxString
MakeString(const long& v
) { return wxString::Format(wxT("%ld"), v
); }
79 static inline wxString
MakeString(const double& v
) { return wxString::Format(wxT("%.2f"), (float) v
); }
80 static inline wxString
MakeString(const wxString
& s
) { return s
; }
81 static inline wxString
MakeString(const wxColour
& col
) { return wxT("#") + ColourToHexString(col
); }
83 static inline void AddString(wxString
& str
, const int& v
) { str
<< wxString::Format(wxT("%d"), v
); }
84 static inline void AddString(wxString
& str
, const long& v
) { str
<< wxString::Format(wxT("%ld"), v
); }
85 static inline void AddString(wxString
& str
, const double& v
) { str
<< wxString::Format(wxT("%.2f"), (float) v
); }
86 static inline void AddString(wxString
& str
, const wxChar
* s
) { str
<< s
; }
87 static inline void AddString(wxString
& str
, const wxString
& s
) { str
<< s
; }
88 static inline void AddString(wxString
& str
, const wxColour
& col
) { str
<< wxT("#") << ColourToHexString(col
); }
90 IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler
, wxRichTextFileHandler
)
92 wxStringToStringHashMap
wxRichTextXMLHandler::sm_nodeNameToClassMap
;
94 void wxRichTextXMLHandler::Init()
96 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
104 bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer
*buffer
, wxInputStream
& stream
)
109 buffer
->ResetAndClearCommands();
112 wxXmlDocument
* xmlDoc
= new wxXmlDocument
;
115 // This is the encoding to convert to (memory encoding rather than file encoding)
116 wxString
encoding(wxT("UTF-8"));
118 #if !wxUSE_UNICODE && wxUSE_INTL
119 encoding
= wxLocale::GetSystemEncodingName();
122 if (!xmlDoc
->Load(stream
, encoding
))
124 buffer
->ResetAndClearCommands();
129 if (xmlDoc
->GetRoot() && xmlDoc
->GetRoot()->GetType() == wxXML_ELEMENT_NODE
&& xmlDoc
->GetRoot()->GetName() == wxT("richtext"))
131 wxXmlNode
* child
= xmlDoc
->GetRoot()->GetChildren();
134 if (child
->GetType() == wxXML_ELEMENT_NODE
)
136 wxString name
= child
->GetName();
137 if (name
== wxT("richtext-version"))
141 ImportXML(buffer
, buffer
, child
);
144 child
= child
->GetNext();
155 buffer
->UpdateRanges();
160 /// Creates an object given an XML element name
161 wxRichTextObject
* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject
* WXUNUSED(parent
), const wxString
& name
) const
163 // The standard node to class mappings are added in wxRichTextModule::OnInit in richtextbuffer.cpp
164 wxStringToStringHashMap::const_iterator it
= sm_nodeNameToClassMap
.find(name
);
165 if (it
== sm_nodeNameToClassMap
.end())
168 return wxDynamicCast(wxCreateDynamicObject(it
->second
), wxRichTextObject
);
171 /// Recursively import an object
172 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer
* buffer
, wxRichTextObject
* obj
, wxXmlNode
* node
)
174 bool recurse
= false;
175 obj
->ImportFromXML(buffer
, node
, this, & recurse
);
177 // TODO: how to control whether to import children.
179 wxRichTextCompositeObject
* compositeParent
= wxDynamicCast(obj
, wxRichTextCompositeObject
);
180 if (recurse
&& compositeParent
)
182 wxXmlNode
* child
= node
->GetChildren();
185 if (child
->GetName() != wxT("stylesheet"))
187 wxRichTextObject
* childObj
= CreateObjectForXMLName(obj
, child
->GetName());
190 compositeParent
->AppendChild(childObj
);
191 ImportXML(buffer
, childObj
, child
);
194 child
= child
->GetNext();
201 bool wxRichTextXMLHandler::ImportProperties(wxRichTextObject
* obj
, wxXmlNode
* node
)
203 return ImportProperties(obj
->GetProperties(), node
);
206 bool wxRichTextXMLHandler::ImportProperties(wxRichTextProperties
& properties
, wxXmlNode
* node
)
208 wxXmlNode
* child
= node
->GetChildren();
211 if (child
->GetName() == wxT("properties"))
213 wxXmlNode
* propertyChild
= child
->GetChildren();
214 while (propertyChild
)
216 if (propertyChild
->GetName() == wxT("property"))
218 wxString name
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
);
219 wxString value
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
);
220 wxString type
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
);
222 wxVariant var
= MakePropertyFromString(name
, value
, type
);
225 properties
.SetProperty(var
);
228 propertyChild
= propertyChild
->GetNext();
231 child
= child
->GetNext();
236 bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
)
238 wxString styleType
= node
->GetName();
239 wxString styleName
= node
->GetAttribute(wxT("name"), wxEmptyString
);
240 wxString baseStyleName
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
);
242 if (styleName
.empty())
245 if (styleType
== wxT("characterstyle"))
247 wxRichTextCharacterStyleDefinition
* def
= new wxRichTextCharacterStyleDefinition(styleName
);
248 def
->SetBaseStyle(baseStyleName
);
250 wxXmlNode
* child
= node
->GetChildren();
253 if (child
->GetName() == wxT("style"))
256 ImportStyle(attr
, child
, false);
259 child
= child
->GetNext();
262 ImportProperties(def
->GetProperties(), node
);
264 sheet
->AddCharacterStyle(def
);
266 else if (styleType
== wxT("paragraphstyle"))
268 wxRichTextParagraphStyleDefinition
* def
= new wxRichTextParagraphStyleDefinition(styleName
);
270 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
271 def
->SetNextStyle(nextStyleName
);
272 def
->SetBaseStyle(baseStyleName
);
274 wxXmlNode
* child
= node
->GetChildren();
277 if (child
->GetName() == wxT("style"))
280 ImportStyle(attr
, child
, true);
283 child
= child
->GetNext();
286 ImportProperties(def
->GetProperties(), node
);
288 sheet
->AddParagraphStyle(def
);
290 else if (styleType
== wxT("boxstyle"))
292 wxRichTextBoxStyleDefinition
* def
= new wxRichTextBoxStyleDefinition(styleName
);
294 def
->SetBaseStyle(baseStyleName
);
296 wxXmlNode
* child
= node
->GetChildren();
299 if (child
->GetName() == wxT("style"))
302 ImportStyle(attr
, child
, true);
305 child
= child
->GetNext();
308 ImportProperties(def
->GetProperties(), node
);
310 sheet
->AddBoxStyle(def
);
312 else if (styleType
== wxT("liststyle"))
314 wxRichTextListStyleDefinition
* def
= new wxRichTextListStyleDefinition(styleName
);
316 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
317 def
->SetNextStyle(nextStyleName
);
318 def
->SetBaseStyle(baseStyleName
);
320 wxXmlNode
* child
= node
->GetChildren();
323 if (child
->GetName() == wxT("style"))
326 ImportStyle(attr
, child
, true);
328 wxString styleLevel
= child
->GetAttribute(wxT("level"), wxEmptyString
);
329 if (styleLevel
.empty())
335 int level
= wxAtoi(styleLevel
);
336 if (level
> 0 && level
<= 10)
338 def
->SetLevelAttributes(level
-1, attr
);
342 child
= child
->GetNext();
345 ImportProperties(def
->GetProperties(), node
);
347 sheet
->AddListStyle(def
);
353 //-----------------------------------------------------------------------------
354 // xml support routines
355 //-----------------------------------------------------------------------------
357 bool wxRichTextXMLHandler::HasParam(wxXmlNode
* node
, const wxString
& param
)
359 return (GetParamNode(node
, param
) != NULL
);
362 wxXmlNode
*wxRichTextXMLHandler::GetParamNode(wxXmlNode
* node
, const wxString
& param
)
364 wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!"));
366 wxXmlNode
*n
= node
->GetChildren();
370 if (n
->GetType() == wxXML_ELEMENT_NODE
&& n
->GetName() == param
)
378 wxString
wxRichTextXMLHandler::GetNodeContent(wxXmlNode
*node
)
381 if (n
== NULL
) return wxEmptyString
;
382 n
= n
->GetChildren();
386 if (n
->GetType() == wxXML_TEXT_NODE
||
387 n
->GetType() == wxXML_CDATA_SECTION_NODE
)
388 return n
->GetContent();
391 return wxEmptyString
;
395 wxString
wxRichTextXMLHandler::GetParamValue(wxXmlNode
*node
, const wxString
& param
)
398 return GetNodeContent(node
);
400 return GetNodeContent(GetParamNode(node
, param
));
403 wxString
wxRichTextXMLHandler::GetText(wxXmlNode
*node
, const wxString
& param
, bool WXUNUSED(translate
))
405 wxXmlNode
*parNode
= GetParamNode(node
, param
);
408 wxString
str1(GetNodeContent(parNode
));
412 wxXmlNode
* wxRichTextXMLHandler::FindNode(wxXmlNode
* node
, const wxString
& name
)
414 if (node
->GetName() == name
&& name
== wxT("stylesheet"))
417 wxXmlNode
* child
= node
->GetChildren();
420 if (child
->GetName() == name
)
422 child
= child
->GetNext();
427 // For use with earlier versions of wxWidgets
428 #ifndef WXUNUSED_IN_UNICODE
430 #define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
432 #define WXUNUSED_IN_UNICODE(x) x
436 // write string to output
437 inline static void OutputString(wxOutputStream
& stream
, const wxString
& str
,
438 wxMBConv
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv
*convFile
)
440 if (str
.empty()) return;
444 const wxWX2MBbuf
buf(str
.mb_str(*convFile
));
445 stream
.Write((const char*)buf
, strlen((const char*)buf
));
449 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
450 stream
.Write((const char*)buf
, strlen((const char*)buf
));
453 if ( convFile
== NULL
)
454 stream
.Write(str
.mb_str(), str
.Len());
457 wxString
str2(str
.wc_str(*convMem
), *convFile
);
458 stream
.Write(str2
.mb_str(), str2
.Len());
463 static void OutputIndentation(wxOutputStream
& stream
, int indent
)
465 wxString str
= wxT("\n");
466 for (int i
= 0; i
< indent
; i
++)
467 str
<< wxT(' ') << wxT(' ');
468 ::OutputString(stream
, str
, NULL
, NULL
);
471 // Same as above, but create entities first.
472 // Translates '<' to "<", '>' to ">" and '&' to "&"
473 static void OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
,
474 wxMBConv
*convMem
= NULL
, wxMBConv
*convFile
= NULL
)
482 for (i
= 0; i
< len
; i
++)
486 // Original code excluded "&" but we _do_ want to convert
487 // the ampersand beginning & because otherwise when read in,
488 // the original "&" becomes "&".
490 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
491 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
493 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
497 OutputString(stream
, wxT("<"), NULL
, NULL
);
500 OutputString(stream
, wxT(">"), NULL
, NULL
);
503 OutputString(stream
, wxT("&"), NULL
, NULL
);
506 OutputString(stream
, wxT("""), NULL
, NULL
);
512 else if (wxUChar(c
) > 127)
514 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
516 wxString
s(wxT("&#"));
520 s
<< (int) wxUChar(c
);
523 OutputString(stream
, s
, NULL
, NULL
);
527 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
530 void wxRichTextXMLHandler::OutputString(wxOutputStream
& stream
, const wxString
& str
)
532 ::OutputString(stream
, str
, m_convMem
, m_convFile
);
535 void wxRichTextXMLHandler::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
)
537 ::OutputStringEnt(stream
, str
, m_convMem
, m_convFile
);
540 void wxRichTextXMLHandler::OutputIndentation(wxOutputStream
& stream
, int indent
)
542 wxString str
= wxT("\n");
543 for (int i
= 0; i
< indent
; i
++)
544 str
<< wxT(' ') << wxT(' ');
545 ::OutputString(stream
, str
, NULL
, NULL
);
548 wxString
wxRichTextXMLHandler::AttributeToXML(const wxString
& str
)
556 for (i
= 0; i
< len
; i
++)
560 // Original code excluded "&" but we _do_ want to convert
561 // the ampersand beginning & because otherwise when read in,
562 // the original "&" becomes "&".
564 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
565 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
567 str1
+= str
.Mid(last
, i
- last
);
577 str1
+= wxT("&");
580 str1
+= wxT(""");
586 else if (wxUChar(c
) > 127)
588 str1
+= str
.Mid(last
, i
- last
);
590 wxString
s(wxT("&#"));
594 s
<< (int) wxUChar(c
);
601 str1
+= str
.Mid(last
, i
- last
);
605 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
607 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const int& v
)
609 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\"");
612 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const long& v
)
614 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\"");
617 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const double& v
)
619 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\"");
622 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxChar
* s
)
624 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
627 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxString
& s
)
629 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
632 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxColour
& col
)
634 str
<< wxT(" ") << name
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\"");
637 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxTextAttrDimension
& dim
)
641 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags());
642 str
<< wxT(" ") << name
<< wxT("=\"");
648 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
650 if (dims
.GetLeft().IsValid())
651 AddAttribute(str
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
652 if (dims
.GetRight().IsValid())
653 AddAttribute(str
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
654 if (dims
.GetTop().IsValid())
655 AddAttribute(str
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
656 if (dims
.GetBottom().IsValid())
657 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
660 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
662 if (border
.HasStyle())
663 AddAttribute(str
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
664 if (border
.HasColour())
665 AddAttribute(str
, rootName
+ wxString(wxT("-color")), border
.GetColour());
666 if (border
.HasWidth())
667 AddAttribute(str
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
670 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
672 AddAttribute(str
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
673 AddAttribute(str
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
674 AddAttribute(str
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
675 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
679 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
681 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
683 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const int& v
)
685 node
->AddAttribute(name
, MakeString(v
));
688 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const long& v
)
690 node
->AddAttribute(name
, MakeString(v
));
693 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const double& v
)
695 node
->AddAttribute(name
, MakeString(v
));
698 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxString
& s
)
700 node
->AddAttribute(name
, s
);
703 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxColour
& col
)
705 node
->AddAttribute(name
, MakeString(col
));
708 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxTextAttrDimension
& dim
)
712 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags());
713 AddAttribute(node
, name
, value
);
717 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
719 if (dims
.GetLeft().IsValid())
720 AddAttribute(node
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
721 if (dims
.GetRight().IsValid())
722 AddAttribute(node
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
723 if (dims
.GetTop().IsValid())
724 AddAttribute(node
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
725 if (dims
.GetBottom().IsValid())
726 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
729 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
731 if (border
.HasStyle())
732 AddAttribute(node
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
733 if (border
.HasColour())
734 AddAttribute(node
, rootName
+ wxString(wxT("-color")), border
.GetColour());
735 if (border
.HasWidth())
736 AddAttribute(node
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
739 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
741 AddAttribute(node
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
742 AddAttribute(node
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
743 AddAttribute(node
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
744 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
747 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
749 bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer
*buffer
, wxOutputStream
& stream
)
754 wxString
version(wxT("1.0") ) ;
756 bool deleteConvFile
= false;
757 wxString fileEncoding
;
758 //wxMBConv* convFile = NULL;
761 fileEncoding
= wxT("UTF-8");
762 m_convFile
= & wxConvUTF8
;
764 fileEncoding
= wxT("ISO-8859-1");
765 m_convFile
= & wxConvISO8859_1
;
768 // If SetEncoding has been called, change the output encoding.
769 if (!m_encoding
.empty() && m_encoding
.Lower() != fileEncoding
.Lower())
771 if (m_encoding
== wxT("<System>"))
774 fileEncoding
= wxLocale::GetSystemEncodingName();
775 // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below
780 fileEncoding
= m_encoding
;
783 // GetSystemEncodingName may not have returned a name
784 if (fileEncoding
.empty())
786 fileEncoding
= wxT("UTF-8");
788 fileEncoding
= wxT("ISO-8859-1");
790 m_convFile
= new wxCSConv(fileEncoding
);
791 deleteConvFile
= true;
794 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT
795 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
796 wxStopWatch stopwatch
;
798 wxXmlDocument
* doc
= new wxXmlDocument
;
799 doc
->SetFileEncoding(fileEncoding
);
801 wxXmlNode
* rootNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("richtext"));
802 doc
->SetRoot(rootNode
);
803 rootNode
->AddAttribute(wxT("version"), wxT("1.0.0.0"));
804 rootNode
->AddAttribute(wxT("xmlns"), wxT("http://www.wxwidgets.org"));
806 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
808 wxXmlNode
* styleSheetNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("stylesheet"));
809 rootNode
->AddChild(styleSheetNode
);
811 wxString nameAndDescr
;
813 if (!buffer
->GetStyleSheet()->GetName().empty())
814 styleSheetNode
->AddAttribute(wxT("name"), buffer
->GetStyleSheet()->GetName());
816 if (!buffer
->GetStyleSheet()->GetDescription().empty())
817 styleSheetNode
->AddAttribute(wxT("description"), buffer
->GetStyleSheet()->GetDescription());
820 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
822 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
823 ExportStyleDefinition(styleSheetNode
, def
);
826 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
828 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
829 ExportStyleDefinition(styleSheetNode
, def
);
832 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
834 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
835 ExportStyleDefinition(styleSheetNode
, def
);
838 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
840 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
841 ExportStyleDefinition(styleSheetNode
, def
);
844 WriteProperties(styleSheetNode
, buffer
->GetStyleSheet()->GetProperties());
846 bool success
= ExportXML(rootNode
, *buffer
);
847 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
848 long t
= stopwatch
.Time();
849 wxLogDebug(wxT("Creating the document took %ldms"), t
);
850 wxMessageBox(wxString::Format(wxT("Creating the document took %ldms"), t
));
854 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
857 success
= doc
->Save(stream
);
858 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
860 wxLogDebug(wxT("Save() took %ldms"), t2
);
861 wxMessageBox(wxString::Format(wxT("Save() took %ldms"), t2
));
868 // !(wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT)
871 m_convMem
= wxConvCurrent
;
877 s
.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"),
878 version
, fileEncoding
);
879 OutputString(stream
, s
);
880 OutputString(stream
, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">"));
884 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
886 OutputIndentation(stream
, level
);
887 wxString nameAndDescr
;
888 if (!buffer
->GetStyleSheet()->GetName().empty())
889 nameAndDescr
<< wxT(" name=\"") << buffer
->GetStyleSheet()->GetName() << wxT("\"");
890 if (!buffer
->GetStyleSheet()->GetDescription().empty())
891 nameAndDescr
<< wxT(" description=\"") << buffer
->GetStyleSheet()->GetDescription() << wxT("\"");
892 OutputString(stream
, wxString(wxT("<stylesheet")) + nameAndDescr
+ wxT(">"));
896 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
898 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
899 ExportStyleDefinition(stream
, def
, level
+ 1);
902 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
904 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
905 ExportStyleDefinition(stream
, def
, level
+ 1);
908 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
910 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
911 ExportStyleDefinition(stream
, def
, level
+ 1);
914 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
916 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
917 ExportStyleDefinition(stream
, def
, level
+ 1);
920 WriteProperties(stream
, buffer
->GetStyleSheet()->GetProperties(), level
);
922 OutputIndentation(stream
, level
);
923 OutputString(stream
, wxT("</stylesheet>"));
927 bool success
= ExportXML(stream
, *buffer
, level
);
929 OutputString(stream
, wxT("\n</richtext>"));
930 OutputString(stream
, wxT("\n"));
941 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
943 /// Recursively export an object
944 bool wxRichTextXMLHandler::ExportXML(wxOutputStream
& stream
, wxRichTextObject
& obj
, int indent
)
946 obj
.ExportXML(stream
, indent
, this);
951 bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
)
953 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
954 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
955 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
956 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
958 wxString name
= def
->GetName();
961 nameProp
= wxT(" name=\"") + AttributeToXML(name
) + wxT("\"");
963 wxString baseStyle
= def
->GetBaseStyle();
964 wxString baseStyleProp
;
965 if (!baseStyle
.empty())
966 baseStyleProp
= wxT(" basestyle=\"") + AttributeToXML(baseStyle
) + wxT("\"");
968 wxString descr
= def
->GetDescription();
971 descrProp
= wxT(" description=\"") + AttributeToXML(descr
) + wxT("\"");
975 OutputIndentation(stream
, level
);
976 OutputString(stream
, wxT("<characterstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
980 wxString style
= AddAttributes(def
->GetStyle(), false);
982 OutputIndentation(stream
, level
);
983 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
985 OutputIndentation(stream
, level
);
986 OutputString(stream
, wxT("</style>"));
990 OutputIndentation(stream
, level
);
991 OutputString(stream
, wxT("</characterstyle>"));
995 OutputIndentation(stream
, level
);
997 if (!listDef
->GetNextStyle().empty())
998 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(listDef
->GetNextStyle()) << wxT("\"");
1000 OutputString(stream
, wxT("<liststyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1004 wxString style
= AddAttributes(def
->GetStyle(), true);
1006 OutputIndentation(stream
, level
);
1007 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1009 OutputIndentation(stream
, level
);
1010 OutputString(stream
, wxT("</style>"));
1013 for (i
= 0; i
< 10; i
++)
1015 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1018 wxString style
= AddAttributes(def
->GetStyle(), true);
1019 wxString levelStr
= wxString::Format(wxT(" level=\"%d\" "), (i
+1));
1021 OutputIndentation(stream
, level
);
1022 OutputString(stream
, wxT("<style ") + levelStr
+ style
+ wxT(">"));
1024 OutputIndentation(stream
, level
);
1025 OutputString(stream
, wxT("</style>"));
1031 OutputIndentation(stream
, level
);
1032 OutputString(stream
, wxT("</liststyle>"));
1036 OutputIndentation(stream
, level
);
1038 if (!paraDef
->GetNextStyle().empty())
1039 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(paraDef
->GetNextStyle()) << wxT("\"");
1041 OutputString(stream
, wxT("<paragraphstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1045 wxString style
= AddAttributes(def
->GetStyle(), true);
1047 OutputIndentation(stream
, level
);
1048 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1050 OutputIndentation(stream
, level
);
1051 OutputString(stream
, wxT("</style>"));
1055 OutputIndentation(stream
, level
);
1056 OutputString(stream
, wxT("</paragraphstyle>"));
1060 OutputIndentation(stream
, level
);
1062 OutputString(stream
, wxT("<boxstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1066 wxString style
= AddAttributes(def
->GetStyle(), true);
1068 OutputIndentation(stream
, level
);
1069 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1071 OutputIndentation(stream
, level
);
1072 OutputString(stream
, wxT("</style>"));
1076 OutputIndentation(stream
, level
);
1077 OutputString(stream
, wxT("</boxstyle>"));
1080 WriteProperties(stream
, def
->GetProperties(), level
);
1085 /// Create a string containing style attributes
1086 wxString
wxRichTextXMLHandler::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
)
1089 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1090 AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour());
1092 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1093 AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour());
1095 if (attr
.HasFontSize())
1096 AddAttribute(str
, wxT("fontsize"), attr
.GetFontSize());
1098 if (attr
.HasFontFamily())
1099 AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily());
1101 if (attr
.HasFontItalic())
1102 AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle());
1104 if (attr
.HasFontWeight())
1105 AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight());
1107 if (attr
.HasFontUnderlined())
1108 AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined());
1110 if (attr
.HasFontFaceName())
1111 AddAttribute(str
, wxT("fontface"), AttributeToXML(attr
.GetFontFaceName()));
1113 if (attr
.HasTextEffects())
1115 AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects());
1116 AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags());
1119 if (!attr
.GetCharacterStyleName().empty())
1120 AddAttribute(str
, wxT("characterstyle"), AttributeToXML(attr
.GetCharacterStyleName()));
1123 AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL()));
1127 if (attr
.HasAlignment())
1128 AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment());
1130 if (attr
.HasLeftIndent())
1132 AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent());
1133 AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent());
1136 if (attr
.HasRightIndent())
1137 AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent());
1139 if (attr
.HasParagraphSpacingAfter())
1140 AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter());
1142 if (attr
.HasParagraphSpacingBefore())
1143 AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore());
1145 if (attr
.HasLineSpacing())
1146 AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing());
1148 if (attr
.HasBulletStyle())
1149 AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle());
1151 if (attr
.HasBulletNumber())
1152 AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber());
1154 if (attr
.HasBulletText())
1156 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1157 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1158 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1159 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0]));
1161 AddAttribute(str
, wxT("bullettext"), AttributeToXML(attr
.GetBulletText()));
1163 AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont());
1166 if (attr
.HasBulletName())
1167 AddAttribute(str
, wxT("bulletname"), AttributeToXML(attr
.GetBulletName()));
1169 if (!attr
.GetParagraphStyleName().empty())
1170 AddAttribute(str
, wxT("parstyle"), AttributeToXML(attr
.GetParagraphStyleName()));
1172 if (!attr
.GetListStyleName().empty())
1173 AddAttribute(str
, wxT("liststyle"), AttributeToXML(attr
.GetListStyleName()));
1175 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1176 AddAttribute(str
, wxT("boxstyle"), AttributeToXML(attr
.GetTextBoxAttr().GetBoxStyleName()));
1182 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1184 if (i
> 0) strTabs
<< wxT(",");
1185 strTabs
<< attr
.GetTabs()[i
];
1187 AddAttribute(str
, wxT("tabs"), strTabs
);
1190 if (attr
.HasPageBreak())
1192 AddAttribute(str
, wxT("pagebreak"), 1);
1195 if (attr
.HasOutlineLevel())
1196 AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel());
1199 AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1200 AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1201 AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1202 AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1203 AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1204 AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1205 AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1206 AddAttribute(str
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1207 AddAttribute(str
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1208 AddAttribute(str
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1209 AddAttribute(str
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1211 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1214 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1216 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1217 value
= wxT("centre");
1218 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1219 value
= wxT("bottom");
1221 value
= wxT("none");
1222 AddAttribute(str
, wxT("verticalalignment"), value
);
1225 if (attr
.GetTextBoxAttr().HasFloatMode())
1228 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1229 value
= wxT("left");
1230 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1231 value
= wxT("right");
1233 value
= wxT("none");
1234 AddAttribute(str
, wxT("float"), value
);
1237 if (attr
.GetTextBoxAttr().HasClearMode())
1240 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1241 value
= wxT("left");
1242 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1243 value
= wxT("right");
1244 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1245 value
= wxT("both");
1247 value
= wxT("none");
1248 AddAttribute(str
, wxT("clear"), value
);
1251 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1252 AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1257 // Make a string from the given property. This can be overridden for custom variants.
1258 wxString
wxRichTextXMLHandler::MakeStringFromProperty(const wxVariant
& var
)
1260 return var
.MakeString();
1263 // Create a proprty from the string read from the XML file.
1264 wxVariant
wxRichTextXMLHandler::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
))
1266 wxVariant
var(value
, name
);
1267 // TODO: use type to create using common types
1271 // Write the properties
1272 bool wxRichTextXMLHandler::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
)
1274 if (properties
.GetCount() > 0)
1278 OutputIndentation(stream
, level
);
1279 OutputString(stream
, wxT("<properties>"));
1284 for (i
= 0; i
< properties
.GetCount(); i
++)
1286 const wxVariant
& var
= properties
[i
];
1289 const wxString
& name
= var
.GetName();
1290 wxString value
= MakeStringFromProperty(var
);
1292 OutputIndentation(stream
, level
);
1293 OutputString(stream
, wxT("<property name=\"") + name
+
1294 wxT("\" type=\"") + var
.GetType() + wxT("\" value=\""));
1295 OutputStringEnt(stream
, value
);
1296 OutputString(stream
, wxT("\"/>"));
1302 OutputIndentation(stream
, level
);
1303 OutputString(stream
, wxT("</properties>"));
1313 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
1315 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1316 bool wxRichTextXMLHandler::ExportXML(wxXmlNode
* parent
, wxRichTextObject
& obj
)
1318 obj
.ExportXML(parent
, this);
1323 bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
)
1325 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
1326 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
1327 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
1328 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
1330 wxString baseStyle
= def
->GetBaseStyle();
1331 wxString descr
= def
->GetDescription();
1333 wxXmlNode
* defNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
);
1334 parent
->AddChild(defNode
);
1335 if (!baseStyle
.empty())
1336 defNode
->AddAttribute(wxT("basestyle"), baseStyle
);
1338 defNode
->AddAttribute(wxT("description"), descr
);
1340 wxXmlNode
* styleNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1341 defNode
->AddChild(styleNode
);
1345 defNode
->SetName(wxT("characterstyle"));
1346 AddAttributes(styleNode
, def
->GetStyle(), false);
1350 defNode
->SetName(wxT("liststyle"));
1352 if (!listDef
->GetNextStyle().empty())
1353 defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle());
1355 AddAttributes(styleNode
, def
->GetStyle(), true);
1358 for (i
= 0; i
< 10; i
++)
1360 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1363 wxXmlNode
* levelNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1364 defNode
->AddChild(levelNode
);
1365 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1));
1366 AddAttributes(levelNode
, * levelAttr
, true);
1372 defNode
->SetName(wxT("boxstyle"));
1374 AddAttributes(styleNode
, def
->GetStyle(), true);
1378 defNode
->SetName(wxT("paragraphstyle"));
1380 if (!paraDef
->GetNextStyle().empty())
1381 defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle());
1383 AddAttributes(styleNode
, def
->GetStyle(), true);
1386 WriteProperties(defNode
, def
->GetProperties());
1391 bool wxRichTextXMLHandler::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
)
1393 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1394 node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour()));
1395 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1396 node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour()));
1398 if (attr
.HasFontSize())
1399 node
->AddAttribute(wxT("fontsize"), MakeString(attr
.GetFontSize()));
1400 if (attr
.HasFontFamily())
1401 node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily()));
1402 if (attr
.HasFontItalic())
1403 node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle()));
1404 if (attr
.HasFontWeight())
1405 node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight()));
1406 if (attr
.HasFontUnderlined())
1407 node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined()));
1408 if (attr
.HasFontFaceName())
1409 node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName());
1411 if (attr
.HasTextEffects())
1413 node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects()));
1414 node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags()));
1416 if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty())
1417 node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName());
1420 node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML?
1424 if (attr
.HasAlignment())
1425 node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment()));
1427 if (attr
.HasLeftIndent())
1429 node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent()));
1430 node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent()));
1433 if (attr
.HasRightIndent())
1434 node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent()));
1436 if (attr
.HasParagraphSpacingAfter())
1437 node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter()));
1439 if (attr
.HasParagraphSpacingBefore())
1440 node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore()));
1442 if (attr
.HasLineSpacing())
1443 node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing()));
1445 if (attr
.HasBulletStyle())
1446 node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle()));
1448 if (attr
.HasBulletNumber())
1449 node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber()));
1451 if (attr
.HasBulletText())
1453 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1454 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1455 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1456 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0])));
1458 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText());
1460 if (!attr
.GetBulletFont().empty())
1461 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont());
1464 if (attr
.HasBulletName())
1465 node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName());
1467 if (!attr
.GetParagraphStyleName().empty())
1468 node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName());
1470 if (!attr
.GetListStyleName().empty())
1471 node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName());
1473 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1474 node
->AddAttribute(wxT("boxstyle"), attr
.GetTextBoxAttr().GetBoxStyleName());
1480 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1484 tabs
<< attr
.GetTabs()[i
];
1486 node
->AddAttribute(wxT("tabs"), tabs
);
1489 if (attr
.HasPageBreak())
1490 node
->AddAttribute(wxT("pagebreak"), wxT("1"));
1492 if (attr
.HasOutlineLevel())
1493 node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel()));
1496 AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1497 AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1498 AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1499 AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1500 AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1501 AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1502 AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1503 AddAttribute(node
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1504 AddAttribute(node
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1505 AddAttribute(node
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1506 AddAttribute(node
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1508 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1511 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1513 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1514 value
= wxT("centre");
1515 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1516 value
= wxT("bottom");
1518 value
= wxT("none");
1519 AddAttribute(node
, wxT("verticalalignment"), value
);
1522 if (attr
.GetTextBoxAttr().HasFloatMode())
1525 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1526 value
= wxT("left");
1527 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1528 value
= wxT("right");
1530 value
= wxT("none");
1531 AddAttribute(node
, wxT("float"), value
);
1534 if (attr
.GetTextBoxAttr().HasClearMode())
1537 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1538 value
= wxT("left");
1539 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1540 value
= wxT("right");
1541 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1542 value
= wxT("both");
1544 value
= wxT("none");
1545 AddAttribute(node
, wxT("clear"), value
);
1548 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1549 AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1554 bool wxRichTextXMLHandler::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
)
1556 if (properties
.GetCount() > 0)
1558 wxXmlNode
* propertiesNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties"));
1559 node
->AddChild(propertiesNode
);
1561 for (i
= 0; i
< properties
.GetCount(); i
++)
1563 const wxVariant
& var
= properties
[i
];
1566 wxXmlNode
* propertyNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property"));
1567 propertiesNode
->AddChild(propertyNode
);
1569 const wxString
& name
= var
.GetName();
1570 wxString value
= MakeStringFromProperty(var
);
1572 AddAttribute(propertyNode
, wxT("name"), name
);
1573 AddAttribute(propertyNode
, wxT("type"), var
.GetType());
1574 AddAttribute(propertyNode
, wxT("value"), value
);
1582 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1584 /// Replace face name with current name for platform.
1585 /// TODO: introduce a virtual function or settable table to
1586 /// do this comprehensively.
1587 bool wxRichTextFixFaceName(wxString
& facename
)
1589 if (facename
.empty())
1593 if (facename
== wxT("Times"))
1595 facename
= wxT("Times New Roman");
1598 else if (facename
== wxT("Helvetica"))
1600 facename
= wxT("Arial");
1603 else if (facename
== wxT("Courier"))
1605 facename
= wxT("Courier New");
1611 if (facename
== wxT("Times New Roman"))
1613 facename
= wxT("Times");
1616 else if (facename
== wxT("Arial"))
1618 facename
= wxT("Helvetica");
1621 else if (facename
== wxT("Courier New"))
1623 facename
= wxT("Courier");
1631 static inline long wxRichTextColourStringToLong(const wxString
& colStr
)
1633 if (!colStr
.IsEmpty())
1635 wxColour
col(colStr
);
1636 return col
.GetRGB();
1642 static inline wxTextAttrDimension
wxRichTextParseDimension(const wxString
& dimStr
)
1644 wxString valuePart
= dimStr
.BeforeFirst(wxT(','));
1646 if (dimStr
.Contains(wxT(",")))
1647 flagsPart
= dimStr
.AfterFirst(wxT(','));
1648 wxTextAttrDimension dim
;
1649 dim
.SetValue(wxAtoi(valuePart
));
1650 dim
.SetFlags(wxAtoi(flagsPart
));
1655 /// Import style parameters
1656 bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
)
1658 wxXmlAttribute
* xmlAttr
= node
->GetAttributes();
1662 const wxString
& name
= xmlAttr
->GetName();
1663 const wxString
& value
= xmlAttr
->GetValue();
1666 if (name
== wxT("fontface"))
1671 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
)
1672 wxRichTextFixFaceName(v
);
1673 attr
.SetFontFaceName(v
);
1676 else if (name
== wxT("fontfamily"))
1679 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
));
1681 else if (name
== wxT("fontstyle"))
1684 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
));
1686 else if (name
== wxT("fontsize"))
1689 attr
.SetFontSize(wxAtoi(value
));
1691 else if (name
== wxT("fontweight"))
1694 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
));
1696 else if (name
== wxT("fontunderlined"))
1699 attr
.SetFontUnderlined(wxAtoi(value
) != 0);
1701 else if (name
== wxT("textcolor"))
1705 if (value
[0] == wxT('#'))
1706 attr
.SetTextColour(HexStringToColour(value
.Mid(1)));
1708 attr
.SetTextColour(value
);
1711 else if (name
== wxT("bgcolor"))
1715 if (value
[0] == wxT('#'))
1716 attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1)));
1718 attr
.SetBackgroundColour(value
);
1721 else if (name
== wxT("characterstyle"))
1724 attr
.SetCharacterStyleName(value
);
1726 else if (name
== wxT("texteffects"))
1729 attr
.SetTextEffects(wxAtoi(value
));
1731 else if (name
== wxT("texteffectflags"))
1734 attr
.SetTextEffectFlags(wxAtoi(value
));
1736 else if (name
== wxT("url"))
1743 if (name
== wxT("alignment"))
1746 attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
));
1748 else if (name
== wxT("leftindent"))
1751 attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent());
1753 else if (name
== wxT("leftsubindent"))
1756 attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
));
1758 else if (name
== wxT("rightindent"))
1761 attr
.SetRightIndent(wxAtoi(value
));
1763 else if (name
== wxT("parspacingbefore"))
1766 attr
.SetParagraphSpacingBefore(wxAtoi(value
));
1768 else if (name
== wxT("parspacingafter"))
1771 attr
.SetParagraphSpacingAfter(wxAtoi(value
));
1773 else if (name
== wxT("linespacing"))
1776 attr
.SetLineSpacing(wxAtoi(value
));
1778 else if (name
== wxT("bulletstyle"))
1781 attr
.SetBulletStyle(wxAtoi(value
));
1783 else if (name
== wxT("bulletnumber"))
1786 attr
.SetBulletNumber(wxAtoi(value
));
1788 else if (name
== wxT("bulletsymbol"))
1792 wxChar ch
= wxAtoi(value
);
1795 attr
.SetBulletText(s
);
1798 else if (name
== wxT("bullettext"))
1802 attr
.SetBulletText(value
);
1805 else if (name
== wxT("bulletfont"))
1809 attr
.SetBulletFont(value
);
1812 else if (name
== wxT("bulletname"))
1816 attr
.SetBulletName(value
);
1819 else if (name
== wxT("parstyle"))
1823 attr
.SetParagraphStyleName(value
);
1826 else if (name
== wxT("liststyle"))
1830 attr
.SetListStyleName(value
);
1833 else if (name
== wxT("boxstyle"))
1837 attr
.GetTextBoxAttr().SetBoxStyleName(value
);
1840 else if (name
== wxT("tabs"))
1845 wxStringTokenizer
tkz(value
, wxT(","));
1846 while (tkz
.HasMoreTokens())
1848 wxString token
= tkz
.GetNextToken();
1849 tabs
.Add(wxAtoi(token
));
1854 else if (name
== wxT("pagebreak"))
1858 attr
.SetPageBreak(wxAtoi(value
) != 0);
1861 else if (name
== wxT("outlinelevel"))
1865 attr
.SetOutlineLevel(wxAtoi(value
));
1878 if (name
== wxT("width"))
1880 attr
.GetTextBoxAttr().GetWidth().SetValue(wxRichTextParseDimension(value
));
1882 else if (name
== wxT("height"))
1884 attr
.GetTextBoxAttr().GetHeight().SetValue(wxRichTextParseDimension(value
));
1886 else if (name
== wxT("minwidth"))
1888 attr
.GetTextBoxAttr().GetMinSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1890 else if (name
== wxT("minheight"))
1892 attr
.GetTextBoxAttr().GetMinSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1894 else if (name
== wxT("maxwidth"))
1896 attr
.GetTextBoxAttr().GetMaxSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1898 else if (name
== wxT("maxheight"))
1900 attr
.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1903 else if (name
== wxT("verticalalignment"))
1905 if (value
== wxT("top"))
1906 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
);
1907 else if (value
== wxT("centre"))
1908 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
);
1909 else if (value
== wxT("bottom"))
1910 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
);
1911 else if (value
== wxT("none"))
1912 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
);
1914 else if (name
== wxT("float"))
1916 if (value
== wxT("left"))
1917 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
);
1918 else if (value
== wxT("right"))
1919 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
);
1920 else if (value
== wxT("none"))
1921 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
);
1923 else if (name
== wxT("clear"))
1925 if (value
== wxT("left"))
1926 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
);
1927 else if (value
== wxT("right"))
1928 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
);
1929 else if (value
== wxT("both"))
1930 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
);
1931 else if (value
== wxT("none"))
1932 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
);
1934 else if (name
== wxT("collapse-borders"))
1935 attr
.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode
) wxAtoi(value
));
1937 else if (name
.Contains(wxT("border-")))
1939 if (name
== wxT("border-left-style"))
1940 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
));
1941 else if (name
== wxT("border-right-style"))
1942 attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
));
1943 else if (name
== wxT("border-top-style"))
1944 attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
));
1945 else if (name
== wxT("border-bottom-style"))
1946 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
));
1948 else if (name
== wxT("border-left-colour"))
1949 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1950 else if (name
== wxT("border-right-colour"))
1951 attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1952 else if (name
== wxT("border-top-colour"))
1953 attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1954 else if (name
== wxT("border-bottom-colour"))
1955 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1957 else if (name
== wxT("border-left-width"))
1958 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1959 else if (name
== wxT("border-right-width"))
1960 attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(wxRichTextParseDimension(value
));
1961 else if (name
== wxT("border-top-width"))
1962 attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(wxRichTextParseDimension(value
));
1963 else if (name
== wxT("border-bottom-width"))
1964 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(wxRichTextParseDimension(value
));
1966 else if (name
.Contains(wxT("outline-")))
1968 if (name
== wxT("outline-left-style"))
1969 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
));
1970 else if (name
== wxT("outline-right-style"))
1971 attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
));
1972 else if (name
== wxT("outline-top-style"))
1973 attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
));
1974 else if (name
== wxT("outline-bottom-style"))
1975 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
));
1977 else if (name
== wxT("outline-left-colour"))
1978 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1979 else if (name
== wxT("outline-right-colour"))
1980 attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1981 else if (name
== wxT("outline-top-colour"))
1982 attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1983 else if (name
== wxT("outline-bottom-colour"))
1984 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1986 else if (name
== wxT("outline-left-width"))
1987 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1988 else if (name
== wxT("outline-right-width"))
1989 attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(wxRichTextParseDimension(value
));
1990 else if (name
== wxT("outline-top-width"))
1991 attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(wxRichTextParseDimension(value
));
1992 else if (name
== wxT("outline-bottom-width"))
1993 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(wxRichTextParseDimension(value
));
1995 else if (name
.Contains(wxT("margin-")))
1997 if (name
== wxT("margin-left"))
1998 attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(wxRichTextParseDimension(value
));
1999 else if (name
== wxT("margin-right"))
2000 attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(wxRichTextParseDimension(value
));
2001 else if (name
== wxT("margin-top"))
2002 attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(wxRichTextParseDimension(value
));
2003 else if (name
== wxT("margin-bottom"))
2004 attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(wxRichTextParseDimension(value
));
2006 else if (name
.Contains(wxT("padding-")))
2008 if (name
== wxT("padding-left"))
2009 attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(wxRichTextParseDimension(value
));
2010 else if (name
== wxT("padding-right"))
2011 attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(wxRichTextParseDimension(value
));
2012 else if (name
== wxT("padding-top"))
2013 attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(wxRichTextParseDimension(value
));
2014 else if (name
== wxT("padding-bottom"))
2015 attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(wxRichTextParseDimension(value
));
2017 else if (name
.Contains(wxT("position-")))
2019 if (name
== wxT("position-left"))
2020 attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(wxRichTextParseDimension(value
));
2021 else if (name
== wxT("position-right"))
2022 attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(wxRichTextParseDimension(value
));
2023 else if (name
== wxT("position-top"))
2024 attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(wxRichTextParseDimension(value
));
2025 else if (name
== wxT("position-bottom"))
2026 attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(wxRichTextParseDimension(value
));
2030 xmlAttr
= xmlAttr
->GetNext();
2039 // Import this object from XML
2040 bool wxRichTextObject::ImportFromXML(wxRichTextBuffer
* WXUNUSED(buffer
), wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2042 handler
->ImportProperties(this, node
);
2043 handler
->ImportStyle(GetAttributes(), node
, UsesParagraphAttributes());
2050 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2051 // Export this object directly to the given stream.
2052 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2054 ::OutputIndentation(stream
, indent
);
2055 ::OutputString(stream
, wxT("<") + GetXMLNodeName(), handler
->GetConvMem(), handler
->GetConvFile());
2057 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2059 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2061 if (GetProperties().GetCount() > 0)
2063 handler
->WriteProperties(stream
, GetProperties(), indent
);
2066 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2070 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2072 wxRichTextObject
* child
= composite
->GetChild(i
);
2073 child
->ExportXML(stream
, indent
+1, handler
);
2077 ::OutputIndentation(stream
, indent
);
2078 ::OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2083 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2084 // Export this object to the given parent node, usually creating at least one child node.
2085 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2087 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2088 parent
->AddChild(elementNode
);
2089 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2090 handler
->WriteProperties(elementNode
, GetProperties());
2092 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2096 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2098 wxRichTextObject
* child
= composite
->GetChild(i
);
2099 child
->ExportXML(elementNode
, handler
);
2107 // Import this object from XML
2108 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2110 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2112 if (node
->GetName() == wxT("text"))
2115 wxXmlNode
* textChild
= node
->GetChildren();
2118 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2119 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2121 wxString text2
= textChild
->GetContent();
2123 // Strip whitespace from end
2124 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n'))
2125 text2
= text2
.Mid(0, text2
.length()-1);
2127 if (!text2
.empty() && text2
[0] == wxT('"'))
2128 text2
= text2
.Mid(1);
2129 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"'))
2130 text2
= text2
.Mid(0, text2
.length() - 1);
2134 textChild
= textChild
->GetNext();
2139 else if (node
->GetName() == wxT("symbol"))
2141 // This is a symbol that XML can't read in the normal way
2143 wxXmlNode
* textChild
= node
->GetChildren();
2146 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2147 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2149 wxString text2
= textChild
->GetContent();
2152 textChild
= textChild
->GetNext();
2155 wxString actualText
;
2156 actualText
<< (wxChar
) wxAtoi(text
);
2157 SetText(actualText
);
2165 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2166 // Export this object directly to the given stream.
2167 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2169 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2173 const wxString
& text
= GetText();
2174 int len
= (int) text
.Length();
2179 ::OutputIndentation(stream
, indent
);
2180 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2181 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2182 if (GetProperties().GetCount() > 0)
2184 handler
->WriteProperties(stream
, GetProperties(), indent
);
2185 ::OutputIndentation(stream
, indent
);
2187 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2189 else for (i
= 0; i
< len
; i
++)
2192 int c
= (int) text
[i
];
2194 int c
= (int) wxUChar(text
[i
]);
2196 if ((c
< 32 || c
== 34) && /* c != 9 && */ c
!= 10 && c
!= 13)
2200 wxString
fragment(text
.Mid(last
, i
-last
));
2201 if (!fragment
.empty())
2203 ::OutputIndentation(stream
, indent
);
2204 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2206 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2208 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2210 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2211 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2212 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2215 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2217 if (GetProperties().GetCount() > 0)
2219 handler
->WriteProperties(stream
, GetProperties(), indent
);
2220 ::OutputIndentation(stream
, indent
);
2222 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2227 // Output this character as a number in a separate tag, because XML can't cope
2228 // with entities below 32 except for 10 and 13
2230 ::OutputIndentation(stream
, indent
);
2231 ::OutputString(stream
, wxT("<symbol"), handler
->GetConvMem(), handler
->GetConvFile());
2233 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2234 ::OutputString(stream
, wxString::Format(wxT("%d"), c
), handler
->GetConvMem(), handler
->GetConvFile());
2236 if (GetProperties().GetCount() > 0)
2238 handler
->WriteProperties(stream
, GetProperties(), indent
);
2239 ::OutputIndentation(stream
, indent
);
2241 ::OutputString(stream
, wxT("</symbol>"), handler
->GetConvMem(), handler
->GetConvFile());
2249 fragment
= text
.Mid(last
, i
-last
);
2253 ::OutputIndentation(stream
, indent
);
2254 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2256 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2258 if (GetProperties().GetCount() > 0)
2260 handler
->WriteProperties(stream
, GetProperties(), indent
);
2261 ::OutputIndentation(stream
, indent
);
2264 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2266 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2267 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2268 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2271 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2273 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2279 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2280 // Export this object to the given parent node, usually creating at least one child node.
2281 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2285 const wxString
& text
= GetText();
2286 int len
= (int) text
.Length();
2292 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2293 parent
->AddChild(elementNode
);
2295 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2296 handler
->WriteProperties(elementNode
, GetProperties());
2298 else for (i
= 0; i
< len
; i
++)
2301 int c
= (int) text
[i
];
2303 int c
= (int) wxUChar(text
[i
]);
2305 if ((c
< 32 || c
== 34) && c
!= 10 && c
!= 13)
2309 wxString
fragment(text
.Mid(last
, i
-last
));
2310 if (!fragment
.empty())
2312 // TODO: I'm assuming wxXmlDocument will output quotes if necessary
2313 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2314 parent
->AddChild(elementNode
);
2315 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2316 handler
->WriteProperties(elementNode
, GetProperties());
2318 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2319 elementNode
->AddChild(textNode
);
2321 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2322 fragment
= wxT("\"") + fragment
+ wxT("\"");
2324 textNode
->SetContent(fragment
);
2329 // Output this character as a number in a separate tag, because XML can't cope
2330 // with entities below 32 except for 10 and 13
2332 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol"));
2333 parent
->AddChild(elementNode
);
2335 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2336 handler
->WriteProperties(elementNode
, GetProperties());
2338 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2339 elementNode
->AddChild(textNode
);
2340 textNode
->SetContent(wxString::Format(wxT("%d"), c
));
2350 fragment
= text
.Mid(last
, i
-last
);
2354 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2355 parent
->AddChild(elementNode
);
2356 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2358 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2359 elementNode
->AddChild(textNode
);
2361 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2362 fragment
= wxT("\"") + fragment
+ wxT("\"");
2364 textNode
->SetContent(fragment
);
2371 // Import this object from XML
2372 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2374 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2376 wxBitmapType imageType
= wxBITMAP_TYPE_PNG
;
2377 wxString value
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
);
2380 int type
= wxAtoi(value
);
2382 // note: 0 == wxBITMAP_TYPE_INVALID
2383 if (type
<= 0 || type
>= wxBITMAP_TYPE_MAX
)
2385 wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
);
2389 imageType
= (wxBitmapType
)type
;
2395 wxXmlNode
* imageChild
= node
->GetChildren();
2398 wxString childName
= imageChild
->GetName();
2399 if (childName
== wxT("data"))
2401 wxXmlNode
* dataChild
= imageChild
->GetChildren();
2404 data
= dataChild
->GetContent();
2405 // wxLogDebug(data);
2406 dataChild
= dataChild
->GetNext();
2410 imageChild
= imageChild
->GetNext();
2415 wxStringInputStream
strStream(data
);
2417 GetImageBlock().ReadHex(strStream
, data
.length(), imageType
);
2425 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2426 // Export this object directly to the given stream.
2427 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2429 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2431 ::OutputIndentation(stream
, indent
);
2432 ::OutputString(stream
, wxT("<image"), handler
->GetConvMem(), handler
->GetConvFile());
2433 if (!GetImageBlock().IsOk())
2436 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2440 ::OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2442 if (GetProperties().GetCount() > 0)
2444 handler
->WriteProperties(stream
, GetProperties(), indent
);
2445 ::OutputIndentation(stream
, indent
);
2448 ::OutputIndentation(stream
, indent
+1);
2449 ::OutputString(stream
, wxT("<data>"), handler
->GetConvMem(), handler
->GetConvFile());
2451 // wxStopWatch stopwatch;
2453 GetImageBlock().WriteHex(stream
);
2455 // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time());
2457 ::OutputString(stream
, wxT("</data>\n"), handler
->GetConvMem(), handler
->GetConvFile());
2458 ::OutputIndentation(stream
, indent
);
2459 ::OutputString(stream
, wxT("</image>"), handler
->GetConvMem(), handler
->GetConvFile());
2464 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2465 // Export this object to the given parent node, usually creating at least one child node.
2466 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2468 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image"));
2469 parent
->AddChild(elementNode
);
2471 if (GetImageBlock().IsOk())
2472 elementNode
->AddAttribute(wxT("imagetype"), MakeString((int) GetImageBlock().GetImageType()));
2474 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2475 handler
->WriteProperties(elementNode
, GetProperties());
2477 wxXmlNode
* dataNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data"));
2478 elementNode
->AddChild(dataNode
);
2479 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2480 dataNode
->AddChild(textNode
);
2485 wxMemoryOutputStream stream
;
2486 if (GetImageBlock().WriteHex(stream
))
2488 if (stream
.GetSize() > 0)
2490 int size
= stream
.GetSize();
2492 int size2
= stream
.GetOutputStreamBuffer()->GetIntPosition();
2493 wxASSERT(size
== size2
);
2495 unsigned char* data
= new unsigned char[size
];
2496 stream
.CopyTo(data
, size
);
2497 strData
= wxString((const char*) data
, wxConvUTF8
, size
);
2501 strData
= wxEmptyString
;
2507 wxStringOutputStream
strStream(& strData
);
2508 GetImageBlock().WriteHex(strStream
);
2512 textNode
->SetContent(strData
);
2513 textNode
->SetNoConversion(true); // optimize speed
2520 // Import this object from XML
2521 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2523 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2527 wxString partial
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
);
2528 if (partial
== wxT("true"))
2529 SetPartialParagraph(true);
2531 wxXmlNode
* child
= wxRichTextXMLHandler::FindNode(node
, wxT("stylesheet"));
2532 if (child
&& (handler
->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
2534 wxRichTextStyleSheet
* sheet
= new wxRichTextStyleSheet
;
2535 wxString sheetName
= child
->GetAttribute(wxT("name"), wxEmptyString
);
2536 wxString sheetDescription
= child
->GetAttribute(wxT("description"), wxEmptyString
);
2537 sheet
->SetName(sheetName
);
2538 sheet
->SetDescription(sheetDescription
);
2540 wxXmlNode
* child2
= child
->GetChildren();
2543 handler
->ImportStyleDefinition(sheet
, child2
);
2545 child2
= child2
->GetNext();
2547 handler
->ImportProperties(sheet
->GetProperties(), child
);
2549 // Notify that styles have changed. If this is vetoed by the app,
2550 // the new sheet will be deleted. If it is not vetoed, the
2551 // old sheet will be deleted and replaced with the new one.
2552 buffer
->SetStyleSheetAndNotify(sheet
);
2558 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2559 // Export this object directly to the given stream.
2560 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2562 ::OutputIndentation(stream
, indent
);
2563 wxString nodeName
= GetXMLNodeName();
2564 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2566 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2568 if (GetPartialParagraph())
2569 style
<< wxT(" partialparagraph=\"true\"");
2571 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2573 if (GetProperties().GetCount() > 0)
2575 handler
->WriteProperties(stream
, GetProperties(), indent
);
2579 for (i
= 0; i
< GetChildCount(); i
++)
2581 wxRichTextObject
* child
= GetChild(i
);
2582 child
->ExportXML(stream
, indent
+1, handler
);
2585 ::OutputIndentation(stream
, indent
);
2586 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2591 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2592 // Export this object to the given parent node, usually creating at least one child node.
2593 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2595 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2596 parent
->AddChild(elementNode
);
2597 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2598 handler
->WriteProperties(elementNode
, GetProperties());
2600 if (GetPartialParagraph())
2601 elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true"));
2604 for (i
= 0; i
< GetChildCount(); i
++)
2606 wxRichTextObject
* child
= GetChild(i
);
2607 child
->ExportXML(elementNode
, handler
);
2614 // Import this object from XML
2615 bool wxRichTextTable::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2617 wxRichTextBox::ImportFromXML(buffer
, node
, handler
, recurse
);
2621 m_rowCount
= wxAtoi(node
->GetAttribute(wxT("rows"), wxEmptyString
));
2622 m_colCount
= wxAtoi(node
->GetAttribute(wxT("cols"), wxEmptyString
));
2624 wxXmlNode
* child
= node
->GetChildren();
2627 wxRichTextObject
* childObj
= handler
->CreateObjectForXMLName(this, child
->GetName());
2630 AppendChild(childObj
);
2631 handler
->ImportXML(buffer
, childObj
, child
);
2633 child
= child
->GetNext();
2636 m_cells
.Add(wxRichTextObjectPtrArray(), m_rowCount
);
2638 for (i
= 0; i
< m_rowCount
; i
++)
2640 wxRichTextObjectPtrArray
& colArray
= m_cells
[i
];
2641 for (j
= 0; j
< m_colCount
; j
++)
2643 int idx
= i
* m_colCount
+ j
;
2644 if (idx
< (int) GetChildren().GetCount())
2646 wxRichTextCell
* cell
= wxDynamicCast(GetChildren().Item(idx
)->GetData(), wxRichTextCell
);
2656 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2657 // Export this object directly to the given stream.
2658 bool wxRichTextTable::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2660 ::OutputIndentation(stream
, indent
);
2661 wxString nodeName
= GetXMLNodeName();
2662 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2664 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2666 style
<< wxT(" rows=\"") << m_rowCount
<< wxT("\"");
2667 style
<< wxT(" cols=\"") << m_colCount
<< wxT("\"");
2669 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2671 if (GetProperties().GetCount() > 0)
2673 handler
->WriteProperties(stream
, GetProperties(), indent
);
2677 for (i
= 0; i
< m_rowCount
; i
++)
2679 for (j
= 0; j
< m_colCount
; j
++)
2681 wxRichTextCell
* cell
= GetCell(i
, j
);
2682 cell
->ExportXML(stream
, indent
+1, handler
);
2686 ::OutputIndentation(stream
, indent
);
2687 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2693 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2694 // Export this object to the given parent node, usually creating at least one child node.
2695 bool wxRichTextTable::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2697 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2698 parent
->AddChild(elementNode
);
2699 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2700 handler
->WriteProperties(elementNode
, GetProperties());
2702 elementNode
->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount
));
2703 elementNode
->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount
));
2706 for (i
= 0; i
< m_rowCount
; i
++)
2708 for (j
= 0; j
< m_colCount
; j
++)
2710 wxRichTextCell
* cell
= GetCell(i
, j
);
2711 cell
->ExportXML(elementNode
, handler
);
2721 // wxUSE_RICHTEXT && wxUSE_XML