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 void wxRichTextXMLHandler::Init()
94 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
102 bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer
*buffer
, wxInputStream
& stream
)
107 buffer
->ResetAndClearCommands();
110 wxXmlDocument
* xmlDoc
= new wxXmlDocument
;
113 // This is the encoding to convert to (memory encoding rather than file encoding)
114 wxString
encoding(wxT("UTF-8"));
116 #if !wxUSE_UNICODE && wxUSE_INTL
117 encoding
= wxLocale::GetSystemEncodingName();
120 if (!xmlDoc
->Load(stream
, encoding
))
122 buffer
->ResetAndClearCommands();
127 if (xmlDoc
->GetRoot() && xmlDoc
->GetRoot()->GetType() == wxXML_ELEMENT_NODE
&& xmlDoc
->GetRoot()->GetName() == wxT("richtext"))
129 wxXmlNode
* child
= xmlDoc
->GetRoot()->GetChildren();
132 if (child
->GetType() == wxXML_ELEMENT_NODE
)
134 wxString name
= child
->GetName();
135 if (name
== wxT("richtext-version"))
139 ImportXML(buffer
, buffer
, child
);
142 child
= child
->GetNext();
153 buffer
->UpdateRanges();
158 /// Creates an object given an XML element name
159 wxRichTextObject
* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject
* WXUNUSED(parent
), const wxString
& name
) const
161 if (name
== wxT("text") || name
== wxT("symbol"))
162 return new wxRichTextPlainText
;
163 else if (name
== wxT("image"))
164 return new wxRichTextImage
;
165 else if (name
== wxT("paragraph"))
166 return new wxRichTextParagraph
;
167 else if (name
== wxT("paragraphlayout"))
168 return new wxRichTextParagraphLayoutBox
;
169 else if (name
== wxT("textbox"))
170 return new wxRichTextBox
;
171 else if (name
== wxT("cell"))
172 return new wxRichTextCell
;
173 else if (name
== wxT("table"))
174 return new wxRichTextTable
;
175 else if (name
== wxT("field"))
176 return new wxRichTextField
;
181 /// Recursively import an object
182 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer
* buffer
, wxRichTextObject
* obj
, wxXmlNode
* node
)
184 bool recurse
= false;
185 obj
->ImportFromXML(buffer
, node
, this, & recurse
);
187 // TODO: how to control whether to import children.
189 wxRichTextCompositeObject
* compositeParent
= wxDynamicCast(obj
, wxRichTextCompositeObject
);
190 if (recurse
&& compositeParent
)
192 wxXmlNode
* child
= node
->GetChildren();
195 if (child
->GetName() != wxT("stylesheet"))
197 wxRichTextObject
* childObj
= CreateObjectForXMLName(obj
, child
->GetName());
200 compositeParent
->AppendChild(childObj
);
201 ImportXML(buffer
, childObj
, child
);
204 child
= child
->GetNext();
211 bool wxRichTextXMLHandler::ImportProperties(wxRichTextObject
* obj
, wxXmlNode
* node
)
213 return ImportProperties(obj
->GetProperties(), node
);
216 bool wxRichTextXMLHandler::ImportProperties(wxRichTextProperties
& properties
, wxXmlNode
* node
)
218 wxXmlNode
* child
= node
->GetChildren();
221 if (child
->GetName() == wxT("properties"))
223 wxXmlNode
* propertyChild
= child
->GetChildren();
224 while (propertyChild
)
226 if (propertyChild
->GetName() == wxT("property"))
228 wxString name
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
);
229 wxString value
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
);
230 wxString type
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
);
232 wxVariant var
= MakePropertyFromString(name
, value
, type
);
235 properties
.SetProperty(var
);
238 propertyChild
= propertyChild
->GetNext();
241 child
= child
->GetNext();
246 bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
)
248 wxString styleType
= node
->GetName();
249 wxString styleName
= node
->GetAttribute(wxT("name"), wxEmptyString
);
250 wxString baseStyleName
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
);
252 if (styleName
.empty())
255 if (styleType
== wxT("characterstyle"))
257 wxRichTextCharacterStyleDefinition
* def
= new wxRichTextCharacterStyleDefinition(styleName
);
258 def
->SetBaseStyle(baseStyleName
);
260 wxXmlNode
* child
= node
->GetChildren();
263 if (child
->GetName() == wxT("style"))
266 ImportStyle(attr
, child
, false);
269 child
= child
->GetNext();
272 ImportProperties(def
->GetProperties(), node
);
274 sheet
->AddCharacterStyle(def
);
276 else if (styleType
== wxT("paragraphstyle"))
278 wxRichTextParagraphStyleDefinition
* def
= new wxRichTextParagraphStyleDefinition(styleName
);
280 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
281 def
->SetNextStyle(nextStyleName
);
282 def
->SetBaseStyle(baseStyleName
);
284 wxXmlNode
* child
= node
->GetChildren();
287 if (child
->GetName() == wxT("style"))
290 ImportStyle(attr
, child
, true);
293 child
= child
->GetNext();
296 ImportProperties(def
->GetProperties(), node
);
298 sheet
->AddParagraphStyle(def
);
300 else if (styleType
== wxT("boxstyle"))
302 wxRichTextBoxStyleDefinition
* def
= new wxRichTextBoxStyleDefinition(styleName
);
304 def
->SetBaseStyle(baseStyleName
);
306 wxXmlNode
* child
= node
->GetChildren();
309 if (child
->GetName() == wxT("style"))
312 ImportStyle(attr
, child
, true);
315 child
= child
->GetNext();
318 ImportProperties(def
->GetProperties(), node
);
320 sheet
->AddBoxStyle(def
);
322 else if (styleType
== wxT("liststyle"))
324 wxRichTextListStyleDefinition
* def
= new wxRichTextListStyleDefinition(styleName
);
326 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
327 def
->SetNextStyle(nextStyleName
);
328 def
->SetBaseStyle(baseStyleName
);
330 wxXmlNode
* child
= node
->GetChildren();
333 if (child
->GetName() == wxT("style"))
336 ImportStyle(attr
, child
, true);
338 wxString styleLevel
= child
->GetAttribute(wxT("level"), wxEmptyString
);
339 if (styleLevel
.empty())
345 int level
= wxAtoi(styleLevel
);
346 if (level
> 0 && level
<= 10)
348 def
->SetLevelAttributes(level
-1, attr
);
352 child
= child
->GetNext();
355 ImportProperties(def
->GetProperties(), node
);
357 sheet
->AddListStyle(def
);
363 //-----------------------------------------------------------------------------
364 // xml support routines
365 //-----------------------------------------------------------------------------
367 bool wxRichTextXMLHandler::HasParam(wxXmlNode
* node
, const wxString
& param
)
369 return (GetParamNode(node
, param
) != NULL
);
372 wxXmlNode
*wxRichTextXMLHandler::GetParamNode(wxXmlNode
* node
, const wxString
& param
)
374 wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!"));
376 wxXmlNode
*n
= node
->GetChildren();
380 if (n
->GetType() == wxXML_ELEMENT_NODE
&& n
->GetName() == param
)
388 wxString
wxRichTextXMLHandler::GetNodeContent(wxXmlNode
*node
)
391 if (n
== NULL
) return wxEmptyString
;
392 n
= n
->GetChildren();
396 if (n
->GetType() == wxXML_TEXT_NODE
||
397 n
->GetType() == wxXML_CDATA_SECTION_NODE
)
398 return n
->GetContent();
401 return wxEmptyString
;
405 wxString
wxRichTextXMLHandler::GetParamValue(wxXmlNode
*node
, const wxString
& param
)
408 return GetNodeContent(node
);
410 return GetNodeContent(GetParamNode(node
, param
));
413 wxString
wxRichTextXMLHandler::GetText(wxXmlNode
*node
, const wxString
& param
, bool WXUNUSED(translate
))
415 wxXmlNode
*parNode
= GetParamNode(node
, param
);
418 wxString
str1(GetNodeContent(parNode
));
422 wxXmlNode
* wxRichTextXMLHandler::FindNode(wxXmlNode
* node
, const wxString
& name
)
424 if (node
->GetName() == name
&& name
== wxT("stylesheet"))
427 wxXmlNode
* child
= node
->GetChildren();
430 if (child
->GetName() == name
)
432 child
= child
->GetNext();
437 // For use with earlier versions of wxWidgets
438 #ifndef WXUNUSED_IN_UNICODE
440 #define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
442 #define WXUNUSED_IN_UNICODE(x) x
446 // write string to output
447 inline static void OutputString(wxOutputStream
& stream
, const wxString
& str
,
448 wxMBConv
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv
*convFile
)
450 if (str
.empty()) return;
454 const wxWX2MBbuf
buf(str
.mb_str(*convFile
));
455 stream
.Write((const char*)buf
, strlen((const char*)buf
));
459 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
460 stream
.Write((const char*)buf
, strlen((const char*)buf
));
463 if ( convFile
== NULL
)
464 stream
.Write(str
.mb_str(), str
.Len());
467 wxString
str2(str
.wc_str(*convMem
), *convFile
);
468 stream
.Write(str2
.mb_str(), str2
.Len());
473 static void OutputIndentation(wxOutputStream
& stream
, int indent
)
475 wxString str
= wxT("\n");
476 for (int i
= 0; i
< indent
; i
++)
477 str
<< wxT(' ') << wxT(' ');
478 ::OutputString(stream
, str
, NULL
, NULL
);
481 // Same as above, but create entities first.
482 // Translates '<' to "<", '>' to ">" and '&' to "&"
483 static void OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
,
484 wxMBConv
*convMem
= NULL
, wxMBConv
*convFile
= NULL
)
492 for (i
= 0; i
< len
; i
++)
496 // Original code excluded "&" but we _do_ want to convert
497 // the ampersand beginning & because otherwise when read in,
498 // the original "&" becomes "&".
500 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
501 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
503 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
507 OutputString(stream
, wxT("<"), NULL
, NULL
);
510 OutputString(stream
, wxT(">"), NULL
, NULL
);
513 OutputString(stream
, wxT("&"), NULL
, NULL
);
516 OutputString(stream
, wxT("""), NULL
, NULL
);
522 else if (wxUChar(c
) > 127)
524 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
526 wxString
s(wxT("&#"));
530 s
<< (int) wxUChar(c
);
533 OutputString(stream
, s
, NULL
, NULL
);
537 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
540 void wxRichTextXMLHandler::OutputString(wxOutputStream
& stream
, const wxString
& str
)
542 ::OutputString(stream
, str
, m_convMem
, m_convFile
);
545 void wxRichTextXMLHandler::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
)
547 ::OutputStringEnt(stream
, str
, m_convMem
, m_convFile
);
550 void wxRichTextXMLHandler::OutputIndentation(wxOutputStream
& stream
, int indent
)
552 wxString str
= wxT("\n");
553 for (int i
= 0; i
< indent
; i
++)
554 str
<< wxT(' ') << wxT(' ');
555 ::OutputString(stream
, str
, NULL
, NULL
);
558 wxString
wxRichTextXMLHandler::AttributeToXML(const wxString
& str
)
566 for (i
= 0; i
< len
; i
++)
570 // Original code excluded "&" but we _do_ want to convert
571 // the ampersand beginning & because otherwise when read in,
572 // the original "&" becomes "&".
574 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
575 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
577 str1
+= str
.Mid(last
, i
- last
);
587 str1
+= wxT("&");
590 str1
+= wxT(""");
596 else if (wxUChar(c
) > 127)
598 str1
+= str
.Mid(last
, i
- last
);
600 wxString
s(wxT("&#"));
604 s
<< (int) wxUChar(c
);
611 str1
+= str
.Mid(last
, i
- last
);
615 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
617 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const int& v
)
619 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\"");
622 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const long& v
)
624 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\"");
627 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const double& v
)
629 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\"");
632 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxChar
* s
)
634 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
637 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxString
& s
)
639 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
642 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxColour
& col
)
644 str
<< wxT(" ") << name
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\"");
647 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxTextAttrDimension
& dim
)
651 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags());
652 str
<< wxT(" ") << name
<< wxT("=\"");
658 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
660 if (dims
.GetLeft().IsValid())
661 AddAttribute(str
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
662 if (dims
.GetRight().IsValid())
663 AddAttribute(str
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
664 if (dims
.GetTop().IsValid())
665 AddAttribute(str
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
666 if (dims
.GetBottom().IsValid())
667 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
670 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
672 if (border
.HasStyle())
673 AddAttribute(str
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
674 if (border
.HasColour())
675 AddAttribute(str
, rootName
+ wxString(wxT("-color")), border
.GetColour());
676 if (border
.HasWidth())
677 AddAttribute(str
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
680 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
682 AddAttribute(str
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
683 AddAttribute(str
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
684 AddAttribute(str
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
685 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
689 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
691 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
693 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const int& v
)
695 node
->AddAttribute(name
, MakeString(v
));
698 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const long& v
)
700 node
->AddAttribute(name
, MakeString(v
));
703 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const double& v
)
705 node
->AddAttribute(name
, MakeString(v
));
708 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxString
& s
)
710 node
->AddAttribute(name
, s
);
713 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxColour
& col
)
715 node
->AddAttribute(name
, MakeString(col
));
718 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxTextAttrDimension
& dim
)
722 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags());
723 AddAttribute(node
, name
, value
);
727 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
729 if (dims
.GetLeft().IsValid())
730 AddAttribute(node
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
731 if (dims
.GetRight().IsValid())
732 AddAttribute(node
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
733 if (dims
.GetTop().IsValid())
734 AddAttribute(node
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
735 if (dims
.GetBottom().IsValid())
736 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
739 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
741 if (border
.HasStyle())
742 AddAttribute(node
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
743 if (border
.HasColour())
744 AddAttribute(node
, rootName
+ wxString(wxT("-color")), border
.GetColour());
745 if (border
.HasWidth())
746 AddAttribute(node
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
749 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
751 AddAttribute(node
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
752 AddAttribute(node
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
753 AddAttribute(node
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
754 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
757 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
759 bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer
*buffer
, wxOutputStream
& stream
)
764 wxString
version(wxT("1.0") ) ;
766 bool deleteConvFile
= false;
767 wxString fileEncoding
;
768 //wxMBConv* convFile = NULL;
771 fileEncoding
= wxT("UTF-8");
772 m_convFile
= & wxConvUTF8
;
774 fileEncoding
= wxT("ISO-8859-1");
775 m_convFile
= & wxConvISO8859_1
;
778 // If SetEncoding has been called, change the output encoding.
779 if (!m_encoding
.empty() && m_encoding
.Lower() != fileEncoding
.Lower())
781 if (m_encoding
== wxT("<System>"))
784 fileEncoding
= wxLocale::GetSystemEncodingName();
785 // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below
790 fileEncoding
= m_encoding
;
793 // GetSystemEncodingName may not have returned a name
794 if (fileEncoding
.empty())
796 fileEncoding
= wxT("UTF-8");
798 fileEncoding
= wxT("ISO-8859-1");
800 m_convFile
= new wxCSConv(fileEncoding
);
801 deleteConvFile
= true;
804 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT
805 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
806 wxStopWatch stopwatch
;
808 wxXmlDocument
* doc
= new wxXmlDocument
;
809 doc
->SetFileEncoding(fileEncoding
);
811 wxXmlNode
* rootNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("richtext"));
812 doc
->SetRoot(rootNode
);
813 rootNode
->AddAttribute(wxT("version"), wxT("1.0.0.0"));
814 rootNode
->AddAttribute(wxT("xmlns"), wxT("http://www.wxwidgets.org"));
816 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
818 wxXmlNode
* styleSheetNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("stylesheet"));
819 rootNode
->AddChild(styleSheetNode
);
821 wxString nameAndDescr
;
823 if (!buffer
->GetStyleSheet()->GetName().empty())
824 styleSheetNode
->AddAttribute(wxT("name"), buffer
->GetStyleSheet()->GetName());
826 if (!buffer
->GetStyleSheet()->GetDescription().empty())
827 styleSheetNode
->AddAttribute(wxT("description"), buffer
->GetStyleSheet()->GetDescription());
830 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
832 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
833 ExportStyleDefinition(styleSheetNode
, def
);
836 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
838 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
839 ExportStyleDefinition(styleSheetNode
, def
);
842 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
844 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
845 ExportStyleDefinition(styleSheetNode
, def
);
848 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
850 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
851 ExportStyleDefinition(styleSheetNode
, def
);
854 WriteProperties(styleSheetNode
, buffer
->GetStyleSheet()->GetProperties());
856 bool success
= ExportXML(rootNode
, *buffer
);
857 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
858 long t
= stopwatch
.Time();
859 wxLogDebug(wxT("Creating the document took %ldms"), t
);
860 wxMessageBox(wxString::Format(wxT("Creating the document took %ldms"), t
));
864 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
867 success
= doc
->Save(stream
);
868 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
870 wxLogDebug(wxT("Save() took %ldms"), t2
);
871 wxMessageBox(wxString::Format(wxT("Save() took %ldms"), t2
));
878 // !(wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT)
881 m_convMem
= wxConvCurrent
;
887 s
.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"),
888 version
, fileEncoding
);
889 OutputString(stream
, s
);
890 OutputString(stream
, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">"));
894 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
896 OutputIndentation(stream
, level
);
897 wxString nameAndDescr
;
898 if (!buffer
->GetStyleSheet()->GetName().empty())
899 nameAndDescr
<< wxT(" name=\"") << buffer
->GetStyleSheet()->GetName() << wxT("\"");
900 if (!buffer
->GetStyleSheet()->GetDescription().empty())
901 nameAndDescr
<< wxT(" description=\"") << buffer
->GetStyleSheet()->GetDescription() << wxT("\"");
902 OutputString(stream
, wxString(wxT("<stylesheet")) + nameAndDescr
+ wxT(">"));
906 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
908 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
909 ExportStyleDefinition(stream
, def
, level
+ 1);
912 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
914 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
915 ExportStyleDefinition(stream
, def
, level
+ 1);
918 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
920 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
921 ExportStyleDefinition(stream
, def
, level
+ 1);
924 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
926 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
927 ExportStyleDefinition(stream
, def
, level
+ 1);
930 WriteProperties(stream
, buffer
->GetStyleSheet()->GetProperties(), level
);
932 OutputIndentation(stream
, level
);
933 OutputString(stream
, wxT("</stylesheet>"));
937 bool success
= ExportXML(stream
, *buffer
, level
);
939 OutputString(stream
, wxT("\n</richtext>"));
940 OutputString(stream
, wxT("\n"));
951 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
953 /// Recursively export an object
954 bool wxRichTextXMLHandler::ExportXML(wxOutputStream
& stream
, wxRichTextObject
& obj
, int indent
)
956 obj
.ExportXML(stream
, indent
, this);
961 bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
)
963 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
964 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
965 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
966 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
968 wxString name
= def
->GetName();
971 nameProp
= wxT(" name=\"") + AttributeToXML(name
) + wxT("\"");
973 wxString baseStyle
= def
->GetBaseStyle();
974 wxString baseStyleProp
;
975 if (!baseStyle
.empty())
976 baseStyleProp
= wxT(" basestyle=\"") + AttributeToXML(baseStyle
) + wxT("\"");
978 wxString descr
= def
->GetDescription();
981 descrProp
= wxT(" description=\"") + AttributeToXML(descr
) + wxT("\"");
985 OutputIndentation(stream
, level
);
986 OutputString(stream
, wxT("<characterstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
990 wxString style
= AddAttributes(def
->GetStyle(), false);
992 OutputIndentation(stream
, level
);
993 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
995 OutputIndentation(stream
, level
);
996 OutputString(stream
, wxT("</style>"));
1000 OutputIndentation(stream
, level
);
1001 OutputString(stream
, wxT("</characterstyle>"));
1005 OutputIndentation(stream
, level
);
1007 if (!listDef
->GetNextStyle().empty())
1008 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(listDef
->GetNextStyle()) << wxT("\"");
1010 OutputString(stream
, wxT("<liststyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1014 wxString style
= AddAttributes(def
->GetStyle(), true);
1016 OutputIndentation(stream
, level
);
1017 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1019 OutputIndentation(stream
, level
);
1020 OutputString(stream
, wxT("</style>"));
1023 for (i
= 0; i
< 10; i
++)
1025 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1028 wxString style
= AddAttributes(def
->GetStyle(), true);
1029 wxString levelStr
= wxString::Format(wxT(" level=\"%d\" "), (i
+1));
1031 OutputIndentation(stream
, level
);
1032 OutputString(stream
, wxT("<style ") + levelStr
+ style
+ wxT(">"));
1034 OutputIndentation(stream
, level
);
1035 OutputString(stream
, wxT("</style>"));
1041 OutputIndentation(stream
, level
);
1042 OutputString(stream
, wxT("</liststyle>"));
1046 OutputIndentation(stream
, level
);
1048 if (!paraDef
->GetNextStyle().empty())
1049 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(paraDef
->GetNextStyle()) << wxT("\"");
1051 OutputString(stream
, wxT("<paragraphstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1055 wxString style
= AddAttributes(def
->GetStyle(), true);
1057 OutputIndentation(stream
, level
);
1058 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1060 OutputIndentation(stream
, level
);
1061 OutputString(stream
, wxT("</style>"));
1065 OutputIndentation(stream
, level
);
1066 OutputString(stream
, wxT("</paragraphstyle>"));
1070 OutputIndentation(stream
, level
);
1072 OutputString(stream
, wxT("<boxstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1076 wxString style
= AddAttributes(def
->GetStyle(), true);
1078 OutputIndentation(stream
, level
);
1079 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1081 OutputIndentation(stream
, level
);
1082 OutputString(stream
, wxT("</style>"));
1086 OutputIndentation(stream
, level
);
1087 OutputString(stream
, wxT("</boxstyle>"));
1090 WriteProperties(stream
, def
->GetProperties(), level
);
1095 /// Create a string containing style attributes
1096 wxString
wxRichTextXMLHandler::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
)
1099 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1100 AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour());
1102 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1103 AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour());
1105 if (attr
.HasFontSize())
1106 AddAttribute(str
, wxT("fontsize"), attr
.GetFontSize());
1108 if (attr
.HasFontFamily())
1109 AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily());
1111 if (attr
.HasFontItalic())
1112 AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle());
1114 if (attr
.HasFontWeight())
1115 AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight());
1117 if (attr
.HasFontUnderlined())
1118 AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined());
1120 if (attr
.HasFontFaceName())
1121 AddAttribute(str
, wxT("fontface"), AttributeToXML(attr
.GetFontFaceName()));
1123 if (attr
.HasTextEffects())
1125 AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects());
1126 AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags());
1129 if (!attr
.GetCharacterStyleName().empty())
1130 AddAttribute(str
, wxT("characterstyle"), AttributeToXML(attr
.GetCharacterStyleName()));
1133 AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL()));
1137 if (attr
.HasAlignment())
1138 AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment());
1140 if (attr
.HasLeftIndent())
1142 AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent());
1143 AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent());
1146 if (attr
.HasRightIndent())
1147 AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent());
1149 if (attr
.HasParagraphSpacingAfter())
1150 AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter());
1152 if (attr
.HasParagraphSpacingBefore())
1153 AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore());
1155 if (attr
.HasLineSpacing())
1156 AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing());
1158 if (attr
.HasBulletStyle())
1159 AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle());
1161 if (attr
.HasBulletNumber())
1162 AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber());
1164 if (attr
.HasBulletText())
1166 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1167 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1168 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1169 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0]));
1171 AddAttribute(str
, wxT("bullettext"), AttributeToXML(attr
.GetBulletText()));
1173 AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont());
1176 if (attr
.HasBulletName())
1177 AddAttribute(str
, wxT("bulletname"), AttributeToXML(attr
.GetBulletName()));
1179 if (!attr
.GetParagraphStyleName().empty())
1180 AddAttribute(str
, wxT("parstyle"), AttributeToXML(attr
.GetParagraphStyleName()));
1182 if (!attr
.GetListStyleName().empty())
1183 AddAttribute(str
, wxT("liststyle"), AttributeToXML(attr
.GetListStyleName()));
1185 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1186 AddAttribute(str
, wxT("boxstyle"), AttributeToXML(attr
.GetTextBoxAttr().GetBoxStyleName()));
1192 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1194 if (i
> 0) strTabs
<< wxT(",");
1195 strTabs
<< attr
.GetTabs()[i
];
1197 AddAttribute(str
, wxT("tabs"), strTabs
);
1200 if (attr
.HasPageBreak())
1202 AddAttribute(str
, wxT("pagebreak"), 1);
1205 if (attr
.HasOutlineLevel())
1206 AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel());
1209 AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1210 AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1211 AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1212 AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1213 AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1214 AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1215 AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1216 AddAttribute(str
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1217 AddAttribute(str
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1218 AddAttribute(str
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1219 AddAttribute(str
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1221 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1224 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1226 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1227 value
= wxT("centre");
1228 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1229 value
= wxT("bottom");
1231 value
= wxT("none");
1232 AddAttribute(str
, wxT("verticalalignment"), value
);
1235 if (attr
.GetTextBoxAttr().HasFloatMode())
1238 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1239 value
= wxT("left");
1240 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1241 value
= wxT("right");
1243 value
= wxT("none");
1244 AddAttribute(str
, wxT("float"), value
);
1247 if (attr
.GetTextBoxAttr().HasClearMode())
1250 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1251 value
= wxT("left");
1252 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1253 value
= wxT("right");
1254 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1255 value
= wxT("both");
1257 value
= wxT("none");
1258 AddAttribute(str
, wxT("clear"), value
);
1261 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1262 AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1267 // Make a string from the given property. This can be overridden for custom variants.
1268 wxString
wxRichTextXMLHandler::MakeStringFromProperty(const wxVariant
& var
)
1270 return var
.MakeString();
1273 // Create a proprty from the string read from the XML file.
1274 wxVariant
wxRichTextXMLHandler::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
))
1276 wxVariant
var(value
, name
);
1277 // TODO: use type to create using common types
1281 // Write the properties
1282 bool wxRichTextXMLHandler::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
)
1284 if (properties
.GetCount() > 0)
1288 OutputIndentation(stream
, level
);
1289 OutputString(stream
, wxT("<properties>"));
1294 for (i
= 0; i
< properties
.GetCount(); i
++)
1296 const wxVariant
& var
= properties
[i
];
1299 const wxString
& name
= var
.GetName();
1300 wxString value
= MakeStringFromProperty(var
);
1302 OutputIndentation(stream
, level
);
1303 OutputString(stream
, wxT("<property name=\"") + name
+
1304 wxT("\" type=\"") + var
.GetType() + wxT("\" value=\""));
1305 OutputStringEnt(stream
, value
);
1306 OutputString(stream
, wxT("\"/>"));
1312 OutputIndentation(stream
, level
);
1313 OutputString(stream
, wxT("</properties>"));
1323 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
1325 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1326 bool wxRichTextXMLHandler::ExportXML(wxXmlNode
* parent
, wxRichTextObject
& obj
)
1328 obj
.ExportXML(parent
, this);
1333 bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
)
1335 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
1336 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
1337 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
1338 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
1340 wxString baseStyle
= def
->GetBaseStyle();
1341 wxString descr
= def
->GetDescription();
1343 wxXmlNode
* defNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
);
1344 parent
->AddChild(defNode
);
1345 if (!baseStyle
.empty())
1346 defNode
->AddAttribute(wxT("basestyle"), baseStyle
);
1348 defNode
->AddAttribute(wxT("description"), descr
);
1350 wxXmlNode
* styleNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1351 defNode
->AddChild(styleNode
);
1355 defNode
->SetName(wxT("characterstyle"));
1356 AddAttributes(styleNode
, def
->GetStyle(), false);
1360 defNode
->SetName(wxT("liststyle"));
1362 if (!listDef
->GetNextStyle().empty())
1363 defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle());
1365 AddAttributes(styleNode
, def
->GetStyle(), true);
1368 for (i
= 0; i
< 10; i
++)
1370 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1373 wxXmlNode
* levelNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1374 defNode
->AddChild(levelNode
);
1375 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1));
1376 AddAttributes(levelNode
, * levelAttr
, true);
1382 defNode
->SetName(wxT("boxstyle"));
1384 AddAttributes(styleNode
, def
->GetStyle(), true);
1388 defNode
->SetName(wxT("paragraphstyle"));
1390 if (!paraDef
->GetNextStyle().empty())
1391 defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle());
1393 AddAttributes(styleNode
, def
->GetStyle(), true);
1396 WriteProperties(defNode
, def
->GetProperties());
1401 bool wxRichTextXMLHandler::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
)
1403 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1404 node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour()));
1405 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1406 node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour()));
1408 if (attr
.HasFontSize())
1409 node
->AddAttribute(wxT("fontsize"), MakeString(attr
.GetFontSize()));
1410 if (attr
.HasFontFamily())
1411 node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily()));
1412 if (attr
.HasFontItalic())
1413 node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle()));
1414 if (attr
.HasFontWeight())
1415 node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight()));
1416 if (attr
.HasFontUnderlined())
1417 node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined()));
1418 if (attr
.HasFontFaceName())
1419 node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName());
1421 if (attr
.HasTextEffects())
1423 node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects()));
1424 node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags()));
1426 if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty())
1427 node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName());
1430 node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML?
1434 if (attr
.HasAlignment())
1435 node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment()));
1437 if (attr
.HasLeftIndent())
1439 node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent()));
1440 node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent()));
1443 if (attr
.HasRightIndent())
1444 node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent()));
1446 if (attr
.HasParagraphSpacingAfter())
1447 node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter()));
1449 if (attr
.HasParagraphSpacingBefore())
1450 node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore()));
1452 if (attr
.HasLineSpacing())
1453 node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing()));
1455 if (attr
.HasBulletStyle())
1456 node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle()));
1458 if (attr
.HasBulletNumber())
1459 node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber()));
1461 if (attr
.HasBulletText())
1463 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1464 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1465 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1466 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0])));
1468 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText());
1470 if (!attr
.GetBulletFont().empty())
1471 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont());
1474 if (attr
.HasBulletName())
1475 node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName());
1477 if (!attr
.GetParagraphStyleName().empty())
1478 node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName());
1480 if (!attr
.GetListStyleName().empty())
1481 node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName());
1483 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1484 node
->AddAttribute(wxT("boxstyle"), attr
.GetTextBoxAttr().GetBoxStyleName());
1490 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1494 tabs
<< attr
.GetTabs()[i
];
1496 node
->AddAttribute(wxT("tabs"), tabs
);
1499 if (attr
.HasPageBreak())
1500 node
->AddAttribute(wxT("pagebreak"), wxT("1"));
1502 if (attr
.HasOutlineLevel())
1503 node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel()));
1506 AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1507 AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1508 AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1509 AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1510 AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1511 AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1512 AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1513 AddAttribute(node
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1514 AddAttribute(node
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1515 AddAttribute(node
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1516 AddAttribute(node
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1518 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1521 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1523 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1524 value
= wxT("centre");
1525 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1526 value
= wxT("bottom");
1528 value
= wxT("none");
1529 AddAttribute(node
, wxT("verticalalignment"), value
);
1532 if (attr
.GetTextBoxAttr().HasFloatMode())
1535 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1536 value
= wxT("left");
1537 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1538 value
= wxT("right");
1540 value
= wxT("none");
1541 AddAttribute(node
, wxT("float"), value
);
1544 if (attr
.GetTextBoxAttr().HasClearMode())
1547 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1548 value
= wxT("left");
1549 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1550 value
= wxT("right");
1551 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1552 value
= wxT("both");
1554 value
= wxT("none");
1555 AddAttribute(node
, wxT("clear"), value
);
1558 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1559 AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1564 bool wxRichTextXMLHandler::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
)
1566 if (properties
.GetCount() > 0)
1568 wxXmlNode
* propertiesNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties"));
1569 node
->AddChild(propertiesNode
);
1571 for (i
= 0; i
< properties
.GetCount(); i
++)
1573 const wxVariant
& var
= properties
[i
];
1576 wxXmlNode
* propertyNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property"));
1577 propertiesNode
->AddChild(propertyNode
);
1579 const wxString
& name
= var
.GetName();
1580 wxString value
= MakeStringFromProperty(var
);
1582 AddAttribute(propertyNode
, wxT("name"), name
);
1583 AddAttribute(propertyNode
, wxT("type"), var
.GetType());
1584 AddAttribute(propertyNode
, wxT("value"), value
);
1592 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1594 /// Replace face name with current name for platform.
1595 /// TODO: introduce a virtual function or settable table to
1596 /// do this comprehensively.
1597 bool wxRichTextFixFaceName(wxString
& facename
)
1599 if (facename
.empty())
1603 if (facename
== wxT("Times"))
1605 facename
= wxT("Times New Roman");
1608 else if (facename
== wxT("Helvetica"))
1610 facename
= wxT("Arial");
1613 else if (facename
== wxT("Courier"))
1615 facename
= wxT("Courier New");
1621 if (facename
== wxT("Times New Roman"))
1623 facename
= wxT("Times");
1626 else if (facename
== wxT("Arial"))
1628 facename
= wxT("Helvetica");
1631 else if (facename
== wxT("Courier New"))
1633 facename
= wxT("Courier");
1641 static inline long wxRichTextColourStringToLong(const wxString
& colStr
)
1643 if (!colStr
.IsEmpty())
1645 wxColour
col(colStr
);
1646 return col
.GetRGB();
1652 static inline wxTextAttrDimension
wxRichTextParseDimension(const wxString
& dimStr
)
1654 wxString valuePart
= dimStr
.BeforeFirst(wxT(','));
1656 if (dimStr
.Contains(wxT(",")))
1657 flagsPart
= dimStr
.AfterFirst(wxT(','));
1658 wxTextAttrDimension dim
;
1659 dim
.SetValue(wxAtoi(valuePart
));
1660 dim
.SetFlags(wxAtoi(flagsPart
));
1665 /// Import style parameters
1666 bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
)
1668 wxXmlAttribute
* xmlAttr
= node
->GetAttributes();
1672 const wxString
& name
= xmlAttr
->GetName();
1673 const wxString
& value
= xmlAttr
->GetValue();
1676 if (name
== wxT("fontface"))
1681 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
)
1682 wxRichTextFixFaceName(v
);
1683 attr
.SetFontFaceName(v
);
1686 else if (name
== wxT("fontfamily"))
1689 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
));
1691 else if (name
== wxT("fontstyle"))
1694 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
));
1696 else if (name
== wxT("fontsize"))
1699 attr
.SetFontSize(wxAtoi(value
));
1701 else if (name
== wxT("fontweight"))
1704 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
));
1706 else if (name
== wxT("fontunderlined"))
1709 attr
.SetFontUnderlined(wxAtoi(value
) != 0);
1711 else if (name
== wxT("textcolor"))
1715 if (value
[0] == wxT('#'))
1716 attr
.SetTextColour(HexStringToColour(value
.Mid(1)));
1718 attr
.SetTextColour(value
);
1721 else if (name
== wxT("bgcolor"))
1725 if (value
[0] == wxT('#'))
1726 attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1)));
1728 attr
.SetBackgroundColour(value
);
1731 else if (name
== wxT("characterstyle"))
1734 attr
.SetCharacterStyleName(value
);
1736 else if (name
== wxT("texteffects"))
1739 attr
.SetTextEffects(wxAtoi(value
));
1741 else if (name
== wxT("texteffectflags"))
1744 attr
.SetTextEffectFlags(wxAtoi(value
));
1746 else if (name
== wxT("url"))
1753 if (name
== wxT("alignment"))
1756 attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
));
1758 else if (name
== wxT("leftindent"))
1761 attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent());
1763 else if (name
== wxT("leftsubindent"))
1766 attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
));
1768 else if (name
== wxT("rightindent"))
1771 attr
.SetRightIndent(wxAtoi(value
));
1773 else if (name
== wxT("parspacingbefore"))
1776 attr
.SetParagraphSpacingBefore(wxAtoi(value
));
1778 else if (name
== wxT("parspacingafter"))
1781 attr
.SetParagraphSpacingAfter(wxAtoi(value
));
1783 else if (name
== wxT("linespacing"))
1786 attr
.SetLineSpacing(wxAtoi(value
));
1788 else if (name
== wxT("bulletstyle"))
1791 attr
.SetBulletStyle(wxAtoi(value
));
1793 else if (name
== wxT("bulletnumber"))
1796 attr
.SetBulletNumber(wxAtoi(value
));
1798 else if (name
== wxT("bulletsymbol"))
1802 wxChar ch
= wxAtoi(value
);
1805 attr
.SetBulletText(s
);
1808 else if (name
== wxT("bullettext"))
1812 attr
.SetBulletText(value
);
1815 else if (name
== wxT("bulletfont"))
1819 attr
.SetBulletFont(value
);
1822 else if (name
== wxT("bulletname"))
1826 attr
.SetBulletName(value
);
1829 else if (name
== wxT("parstyle"))
1833 attr
.SetParagraphStyleName(value
);
1836 else if (name
== wxT("liststyle"))
1840 attr
.SetListStyleName(value
);
1843 else if (name
== wxT("boxstyle"))
1847 attr
.GetTextBoxAttr().SetBoxStyleName(value
);
1850 else if (name
== wxT("tabs"))
1855 wxStringTokenizer
tkz(value
, wxT(","));
1856 while (tkz
.HasMoreTokens())
1858 wxString token
= tkz
.GetNextToken();
1859 tabs
.Add(wxAtoi(token
));
1864 else if (name
== wxT("pagebreak"))
1868 attr
.SetPageBreak(wxAtoi(value
) != 0);
1871 else if (name
== wxT("outlinelevel"))
1875 attr
.SetOutlineLevel(wxAtoi(value
));
1888 if (name
== wxT("width"))
1890 attr
.GetTextBoxAttr().GetWidth().SetValue(wxRichTextParseDimension(value
));
1892 else if (name
== wxT("height"))
1894 attr
.GetTextBoxAttr().GetHeight().SetValue(wxRichTextParseDimension(value
));
1896 else if (name
== wxT("minwidth"))
1898 attr
.GetTextBoxAttr().GetMinSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1900 else if (name
== wxT("minheight"))
1902 attr
.GetTextBoxAttr().GetMinSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1904 else if (name
== wxT("maxwidth"))
1906 attr
.GetTextBoxAttr().GetMaxSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1908 else if (name
== wxT("maxheight"))
1910 attr
.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1913 else if (name
== wxT("verticalalignment"))
1915 if (value
== wxT("top"))
1916 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
);
1917 else if (value
== wxT("centre"))
1918 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
);
1919 else if (value
== wxT("bottom"))
1920 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
);
1921 else if (value
== wxT("none"))
1922 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
);
1924 else if (name
== wxT("float"))
1926 if (value
== wxT("left"))
1927 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
);
1928 else if (value
== wxT("right"))
1929 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
);
1930 else if (value
== wxT("none"))
1931 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
);
1933 else if (name
== wxT("clear"))
1935 if (value
== wxT("left"))
1936 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
);
1937 else if (value
== wxT("right"))
1938 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
);
1939 else if (value
== wxT("both"))
1940 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
);
1941 else if (value
== wxT("none"))
1942 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
);
1944 else if (name
== wxT("collapse-borders"))
1945 attr
.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode
) wxAtoi(value
));
1947 else if (name
.Contains(wxT("border-")))
1949 if (name
== wxT("border-left-style"))
1950 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
));
1951 else if (name
== wxT("border-right-style"))
1952 attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
));
1953 else if (name
== wxT("border-top-style"))
1954 attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
));
1955 else if (name
== wxT("border-bottom-style"))
1956 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
));
1958 else if (name
== wxT("border-left-colour"))
1959 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1960 else if (name
== wxT("border-right-colour"))
1961 attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1962 else if (name
== wxT("border-top-colour"))
1963 attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1964 else if (name
== wxT("border-bottom-colour"))
1965 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1967 else if (name
== wxT("border-left-width"))
1968 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1969 else if (name
== wxT("border-right-width"))
1970 attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(wxRichTextParseDimension(value
));
1971 else if (name
== wxT("border-top-width"))
1972 attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(wxRichTextParseDimension(value
));
1973 else if (name
== wxT("border-bottom-width"))
1974 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(wxRichTextParseDimension(value
));
1976 else if (name
.Contains(wxT("outline-")))
1978 if (name
== wxT("outline-left-style"))
1979 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
));
1980 else if (name
== wxT("outline-right-style"))
1981 attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
));
1982 else if (name
== wxT("outline-top-style"))
1983 attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
));
1984 else if (name
== wxT("outline-bottom-style"))
1985 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
));
1987 else if (name
== wxT("outline-left-colour"))
1988 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1989 else if (name
== wxT("outline-right-colour"))
1990 attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1991 else if (name
== wxT("outline-top-colour"))
1992 attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1993 else if (name
== wxT("outline-bottom-colour"))
1994 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1996 else if (name
== wxT("outline-left-width"))
1997 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1998 else if (name
== wxT("outline-right-width"))
1999 attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(wxRichTextParseDimension(value
));
2000 else if (name
== wxT("outline-top-width"))
2001 attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(wxRichTextParseDimension(value
));
2002 else if (name
== wxT("outline-bottom-width"))
2003 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(wxRichTextParseDimension(value
));
2005 else if (name
.Contains(wxT("margin-")))
2007 if (name
== wxT("margin-left"))
2008 attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(wxRichTextParseDimension(value
));
2009 else if (name
== wxT("margin-right"))
2010 attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(wxRichTextParseDimension(value
));
2011 else if (name
== wxT("margin-top"))
2012 attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(wxRichTextParseDimension(value
));
2013 else if (name
== wxT("margin-bottom"))
2014 attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(wxRichTextParseDimension(value
));
2016 else if (name
.Contains(wxT("padding-")))
2018 if (name
== wxT("padding-left"))
2019 attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(wxRichTextParseDimension(value
));
2020 else if (name
== wxT("padding-right"))
2021 attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(wxRichTextParseDimension(value
));
2022 else if (name
== wxT("padding-top"))
2023 attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(wxRichTextParseDimension(value
));
2024 else if (name
== wxT("padding-bottom"))
2025 attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(wxRichTextParseDimension(value
));
2027 else if (name
.Contains(wxT("position-")))
2029 if (name
== wxT("position-left"))
2030 attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(wxRichTextParseDimension(value
));
2031 else if (name
== wxT("position-right"))
2032 attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(wxRichTextParseDimension(value
));
2033 else if (name
== wxT("position-top"))
2034 attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(wxRichTextParseDimension(value
));
2035 else if (name
== wxT("position-bottom"))
2036 attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(wxRichTextParseDimension(value
));
2040 xmlAttr
= xmlAttr
->GetNext();
2049 // Import this object from XML
2050 bool wxRichTextObject::ImportFromXML(wxRichTextBuffer
* WXUNUSED(buffer
), wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2052 handler
->ImportProperties(this, node
);
2053 handler
->ImportStyle(GetAttributes(), node
, UsesParagraphAttributes());
2060 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2061 // Export this object directly to the given stream.
2062 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2064 ::OutputIndentation(stream
, indent
);
2065 ::OutputString(stream
, wxT("<") + GetXMLNodeName(), handler
->GetConvMem(), handler
->GetConvFile());
2067 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2069 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2071 if (GetProperties().GetCount() > 0)
2073 handler
->WriteProperties(stream
, GetProperties(), indent
);
2076 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2080 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2082 wxRichTextObject
* child
= composite
->GetChild(i
);
2083 child
->ExportXML(stream
, indent
+1, handler
);
2087 ::OutputIndentation(stream
, indent
);
2088 ::OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2093 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2094 // Export this object to the given parent node, usually creating at least one child node.
2095 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2097 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2098 parent
->AddChild(elementNode
);
2099 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2100 handler
->WriteProperties(elementNode
, GetProperties());
2102 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2106 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2108 wxRichTextObject
* child
= composite
->GetChild(i
);
2109 child
->ExportXML(elementNode
, handler
);
2117 // Import this object from XML
2118 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2120 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2122 if (node
->GetName() == wxT("text"))
2125 wxXmlNode
* textChild
= node
->GetChildren();
2128 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2129 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2131 wxString text2
= textChild
->GetContent();
2133 // Strip whitespace from end
2134 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n'))
2135 text2
= text2
.Mid(0, text2
.length()-1);
2137 if (!text2
.empty() && text2
[0] == wxT('"'))
2138 text2
= text2
.Mid(1);
2139 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"'))
2140 text2
= text2
.Mid(0, text2
.length() - 1);
2144 textChild
= textChild
->GetNext();
2149 else if (node
->GetName() == wxT("symbol"))
2151 // This is a symbol that XML can't read in the normal way
2153 wxXmlNode
* textChild
= node
->GetChildren();
2156 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2157 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2159 wxString text2
= textChild
->GetContent();
2162 textChild
= textChild
->GetNext();
2165 wxString actualText
;
2166 actualText
<< (wxChar
) wxAtoi(text
);
2167 SetText(actualText
);
2175 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2176 // Export this object directly to the given stream.
2177 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2179 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2183 const wxString
& text
= GetText();
2184 int len
= (int) text
.Length();
2189 ::OutputIndentation(stream
, indent
);
2190 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2191 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2192 if (GetProperties().GetCount() > 0)
2194 handler
->WriteProperties(stream
, GetProperties(), indent
);
2195 ::OutputIndentation(stream
, indent
);
2197 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2199 else for (i
= 0; i
< len
; i
++)
2202 int c
= (int) text
[i
];
2204 int c
= (int) wxUChar(text
[i
]);
2206 if ((c
< 32 || c
== 34) && /* c != 9 && */ c
!= 10 && c
!= 13)
2210 wxString
fragment(text
.Mid(last
, i
-last
));
2211 if (!fragment
.empty())
2213 ::OutputIndentation(stream
, indent
);
2214 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2216 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2218 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2220 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2221 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2222 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2225 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2227 if (GetProperties().GetCount() > 0)
2229 handler
->WriteProperties(stream
, GetProperties(), indent
);
2230 ::OutputIndentation(stream
, indent
);
2232 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2237 // Output this character as a number in a separate tag, because XML can't cope
2238 // with entities below 32 except for 10 and 13
2240 ::OutputIndentation(stream
, indent
);
2241 ::OutputString(stream
, wxT("<symbol"), handler
->GetConvMem(), handler
->GetConvFile());
2243 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2244 ::OutputString(stream
, wxString::Format(wxT("%d"), c
), handler
->GetConvMem(), handler
->GetConvFile());
2246 if (GetProperties().GetCount() > 0)
2248 handler
->WriteProperties(stream
, GetProperties(), indent
);
2249 ::OutputIndentation(stream
, indent
);
2251 ::OutputString(stream
, wxT("</symbol>"), handler
->GetConvMem(), handler
->GetConvFile());
2259 fragment
= text
.Mid(last
, i
-last
);
2263 ::OutputIndentation(stream
, indent
);
2264 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2266 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2268 if (GetProperties().GetCount() > 0)
2270 handler
->WriteProperties(stream
, GetProperties(), indent
);
2271 ::OutputIndentation(stream
, indent
);
2274 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2276 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2277 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2278 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2281 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2283 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2289 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2290 // Export this object to the given parent node, usually creating at least one child node.
2291 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2295 const wxString
& text
= GetText();
2296 int len
= (int) text
.Length();
2302 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2303 parent
->AddChild(elementNode
);
2305 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2306 handler
->WriteProperties(elementNode
, GetProperties());
2308 else for (i
= 0; i
< len
; i
++)
2311 int c
= (int) text
[i
];
2313 int c
= (int) wxUChar(text
[i
]);
2315 if ((c
< 32 || c
== 34) && c
!= 10 && c
!= 13)
2319 wxString
fragment(text
.Mid(last
, i
-last
));
2320 if (!fragment
.empty())
2322 // TODO: I'm assuming wxXmlDocument will output quotes if necessary
2323 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2324 parent
->AddChild(elementNode
);
2325 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2326 handler
->WriteProperties(elementNode
, GetProperties());
2328 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2329 elementNode
->AddChild(textNode
);
2331 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2332 fragment
= wxT("\"") + fragment
+ wxT("\"");
2334 textNode
->SetContent(fragment
);
2339 // Output this character as a number in a separate tag, because XML can't cope
2340 // with entities below 32 except for 10 and 13
2342 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol"));
2343 parent
->AddChild(elementNode
);
2345 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2346 handler
->WriteProperties(elementNode
, GetProperties());
2348 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2349 elementNode
->AddChild(textNode
);
2350 textNode
->SetContent(wxString::Format(wxT("%d"), c
));
2360 fragment
= text
.Mid(last
, i
-last
);
2364 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2365 parent
->AddChild(elementNode
);
2366 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2368 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2369 elementNode
->AddChild(textNode
);
2371 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2372 fragment
= wxT("\"") + fragment
+ wxT("\"");
2374 textNode
->SetContent(fragment
);
2381 // Import this object from XML
2382 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2384 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2386 wxBitmapType imageType
= wxBITMAP_TYPE_PNG
;
2387 wxString value
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
);
2390 int type
= wxAtoi(value
);
2392 // note: 0 == wxBITMAP_TYPE_INVALID
2393 if (type
<= 0 || type
>= wxBITMAP_TYPE_MAX
)
2395 wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
);
2399 imageType
= (wxBitmapType
)type
;
2405 wxXmlNode
* imageChild
= node
->GetChildren();
2408 wxString childName
= imageChild
->GetName();
2409 if (childName
== wxT("data"))
2411 wxXmlNode
* dataChild
= imageChild
->GetChildren();
2414 data
= dataChild
->GetContent();
2415 // wxLogDebug(data);
2416 dataChild
= dataChild
->GetNext();
2420 imageChild
= imageChild
->GetNext();
2425 wxStringInputStream
strStream(data
);
2427 GetImageBlock().ReadHex(strStream
, data
.length(), imageType
);
2435 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2436 // Export this object directly to the given stream.
2437 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2439 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2441 ::OutputIndentation(stream
, indent
);
2442 ::OutputString(stream
, wxT("<image"), handler
->GetConvMem(), handler
->GetConvFile());
2443 if (!GetImageBlock().IsOk())
2446 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2450 ::OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2452 if (GetProperties().GetCount() > 0)
2454 handler
->WriteProperties(stream
, GetProperties(), indent
);
2455 ::OutputIndentation(stream
, indent
);
2458 ::OutputIndentation(stream
, indent
+1);
2459 ::OutputString(stream
, wxT("<data>"), handler
->GetConvMem(), handler
->GetConvFile());
2461 // wxStopWatch stopwatch;
2463 GetImageBlock().WriteHex(stream
);
2465 // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time());
2467 ::OutputString(stream
, wxT("</data>\n"), handler
->GetConvMem(), handler
->GetConvFile());
2468 ::OutputIndentation(stream
, indent
);
2469 ::OutputString(stream
, wxT("</image>"), handler
->GetConvMem(), handler
->GetConvFile());
2474 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2475 // Export this object to the given parent node, usually creating at least one child node.
2476 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2478 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image"));
2479 parent
->AddChild(elementNode
);
2481 if (GetImageBlock().IsOk())
2482 elementNode
->AddAttribute(wxT("imagetype"), MakeString((int) GetImageBlock().GetImageType()));
2484 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2485 handler
->WriteProperties(elementNode
, GetProperties());
2487 wxXmlNode
* dataNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data"));
2488 elementNode
->AddChild(dataNode
);
2489 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2490 dataNode
->AddChild(textNode
);
2495 wxMemoryOutputStream stream
;
2496 if (GetImageBlock().WriteHex(stream
))
2498 if (stream
.GetSize() > 0)
2500 int size
= stream
.GetSize();
2502 int size2
= stream
.GetOutputStreamBuffer()->GetIntPosition();
2503 wxASSERT(size
== size2
);
2505 unsigned char* data
= new unsigned char[size
];
2506 stream
.CopyTo(data
, size
);
2507 strData
= wxString((const char*) data
, wxConvUTF8
, size
);
2511 strData
= wxEmptyString
;
2517 wxStringOutputStream
strStream(& strData
);
2518 GetImageBlock().WriteHex(strStream
);
2522 textNode
->SetContent(strData
);
2523 textNode
->SetNoConversion(true); // optimize speed
2530 // Import this object from XML
2531 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2533 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2537 wxString partial
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
);
2538 if (partial
== wxT("true"))
2539 SetPartialParagraph(true);
2541 wxXmlNode
* child
= wxRichTextXMLHandler::FindNode(node
, wxT("stylesheet"));
2542 if (child
&& (handler
->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
2544 wxRichTextStyleSheet
* sheet
= new wxRichTextStyleSheet
;
2545 wxString sheetName
= child
->GetAttribute(wxT("name"), wxEmptyString
);
2546 wxString sheetDescription
= child
->GetAttribute(wxT("description"), wxEmptyString
);
2547 sheet
->SetName(sheetName
);
2548 sheet
->SetDescription(sheetDescription
);
2550 wxXmlNode
* child2
= child
->GetChildren();
2553 handler
->ImportStyleDefinition(sheet
, child2
);
2555 child2
= child2
->GetNext();
2557 handler
->ImportProperties(sheet
->GetProperties(), child
);
2559 // Notify that styles have changed. If this is vetoed by the app,
2560 // the new sheet will be deleted. If it is not vetoed, the
2561 // old sheet will be deleted and replaced with the new one.
2562 buffer
->SetStyleSheetAndNotify(sheet
);
2568 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2569 // Export this object directly to the given stream.
2570 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2572 ::OutputIndentation(stream
, indent
);
2573 wxString nodeName
= GetXMLNodeName();
2574 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2576 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2578 if (GetPartialParagraph())
2579 style
<< wxT(" partialparagraph=\"true\"");
2581 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2583 if (GetProperties().GetCount() > 0)
2585 handler
->WriteProperties(stream
, GetProperties(), indent
);
2589 for (i
= 0; i
< GetChildCount(); i
++)
2591 wxRichTextObject
* child
= GetChild(i
);
2592 child
->ExportXML(stream
, indent
+1, handler
);
2595 ::OutputIndentation(stream
, indent
);
2596 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2601 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2602 // Export this object to the given parent node, usually creating at least one child node.
2603 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2605 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2606 parent
->AddChild(elementNode
);
2607 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2608 handler
->WriteProperties(elementNode
, GetProperties());
2610 if (GetPartialParagraph())
2611 elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true"));
2614 for (i
= 0; i
< GetChildCount(); i
++)
2616 wxRichTextObject
* child
= GetChild(i
);
2617 child
->ExportXML(elementNode
, handler
);
2624 // Import this object from XML
2625 bool wxRichTextTable::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2627 wxRichTextBox::ImportFromXML(buffer
, node
, handler
, recurse
);
2631 m_rowCount
= wxAtoi(node
->GetAttribute(wxT("rows"), wxEmptyString
));
2632 m_colCount
= wxAtoi(node
->GetAttribute(wxT("cols"), wxEmptyString
));
2634 wxXmlNode
* child
= node
->GetChildren();
2637 wxRichTextObject
* childObj
= handler
->CreateObjectForXMLName(this, child
->GetName());
2640 AppendChild(childObj
);
2641 handler
->ImportXML(buffer
, childObj
, child
);
2643 child
= child
->GetNext();
2646 m_cells
.Add(wxRichTextObjectPtrArray(), m_rowCount
);
2648 for (i
= 0; i
< m_rowCount
; i
++)
2650 wxRichTextObjectPtrArray
& colArray
= m_cells
[i
];
2651 for (j
= 0; j
< m_colCount
; j
++)
2653 int idx
= i
* m_colCount
+ j
;
2654 if (idx
< (int) GetChildren().GetCount())
2656 wxRichTextCell
* cell
= wxDynamicCast(GetChildren().Item(idx
)->GetData(), wxRichTextCell
);
2666 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2667 // Export this object directly to the given stream.
2668 bool wxRichTextTable::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2670 ::OutputIndentation(stream
, indent
);
2671 wxString nodeName
= GetXMLNodeName();
2672 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2674 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2676 style
<< wxT(" rows=\"") << m_rowCount
<< wxT("\"");
2677 style
<< wxT(" cols=\"") << m_colCount
<< wxT("\"");
2679 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2681 if (GetProperties().GetCount() > 0)
2683 handler
->WriteProperties(stream
, GetProperties(), indent
);
2687 for (i
= 0; i
< m_rowCount
; i
++)
2689 for (j
= 0; j
< m_colCount
; j
++)
2691 wxRichTextCell
* cell
= GetCell(i
, j
);
2692 cell
->ExportXML(stream
, indent
+1, handler
);
2696 ::OutputIndentation(stream
, indent
);
2697 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2703 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2704 // Export this object to the given parent node, usually creating at least one child node.
2705 bool wxRichTextTable::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2707 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2708 parent
->AddChild(elementNode
);
2709 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2710 handler
->WriteProperties(elementNode
, GetProperties());
2712 elementNode
->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount
));
2713 elementNode
->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount
));
2716 for (i
= 0; i
< m_rowCount
; i
++)
2718 for (j
= 0; j
< m_colCount
; j
++)
2720 wxRichTextCell
* cell
= GetCell(i
, j
);
2721 cell
->ExportXML(elementNode
, handler
);
2731 // wxUSE_RICHTEXT && wxUSE_XML