1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/richtext/richtextxml.cpp
3 // Purpose: XML and HTML I/O for wxRichTextCtrl
4 // Author: Julian Smart
7 // Copyright: (c) Julian Smart
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
18 #if wxUSE_RICHTEXT && wxUSE_XML
20 #include "wx/richtext/richtextxml.h"
24 #include "wx/module.h"
28 #include "wx/filename.h"
29 #include "wx/clipbrd.h"
30 #include "wx/wfstream.h"
31 #include "wx/sstream.h"
32 #include "wx/txtstrm.h"
33 #include "wx/mstream.h"
34 #include "wx/tokenzr.h"
35 #include "wx/stopwatch.h"
36 #include "wx/xml/xml.h"
38 // Set to 1 for slower wxXmlDocument method, 0 for faster direct method.
39 // If we make wxXmlDocument::Save more efficient, we might switch to this
41 #define wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT 0
43 #if wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
44 # error Must define wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT in richtextxml.h to use this method.
47 #if !wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_DIRECT_OUTPUT
48 # error Must define wxRICHTEXT_HAVE_DIRECT_OUTPUT in richtextxml.h to use this method.
51 // Set to 1 to time file saving
52 #define wxRICHTEXT_USE_OUTPUT_TIMINGS 0
54 // Convert a colour to a 6-digit hex string
55 static wxString
ColourToHexString(const wxColour
& col
)
59 hex
+= wxDecToHex(col
.Red());
60 hex
+= wxDecToHex(col
.Green());
61 hex
+= wxDecToHex(col
.Blue());
66 // Convert 6-digit hex string to a colour
67 static wxColour
HexStringToColour(const wxString
& hex
)
69 unsigned char r
= (unsigned char)wxHexToDec(hex
.Mid(0, 2));
70 unsigned char g
= (unsigned char)wxHexToDec(hex
.Mid(2, 2));
71 unsigned char b
= (unsigned char)wxHexToDec(hex
.Mid(4, 2));
73 return wxColour(r
, g
, b
);
76 static inline wxString
MakeString(const int& v
) { return wxString::Format(wxT("%d"), v
); }
77 static inline wxString
MakeString(const long& v
) { return wxString::Format(wxT("%ld"), v
); }
78 static inline wxString
MakeString(const double& v
) { return wxString::Format(wxT("%.2f"), (float) v
); }
79 static inline wxString
MakeString(const wxString
& s
) { return s
; }
80 static inline wxString
MakeString(const wxColour
& col
) { return wxT("#") + ColourToHexString(col
); }
82 static inline void AddString(wxString
& str
, const int& v
) { str
<< wxString::Format(wxT("%d"), v
); }
83 static inline void AddString(wxString
& str
, const long& v
) { str
<< wxString::Format(wxT("%ld"), v
); }
84 static inline void AddString(wxString
& str
, const double& v
) { str
<< wxString::Format(wxT("%.2f"), (float) v
); }
85 static inline void AddString(wxString
& str
, const wxChar
* s
) { str
<< s
; }
86 static inline void AddString(wxString
& str
, const wxString
& s
) { str
<< s
; }
87 static inline void AddString(wxString
& str
, const wxColour
& col
) { str
<< wxT("#") << ColourToHexString(col
); }
89 IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler
, wxRichTextFileHandler
)
91 wxStringToStringHashMap
wxRichTextXMLHandler::sm_nodeNameToClassMap
;
93 void wxRichTextXMLHandler::Init()
95 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
103 bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer
*buffer
, wxInputStream
& stream
)
108 buffer
->ResetAndClearCommands();
111 wxXmlDocument
* xmlDoc
= new wxXmlDocument
;
114 // This is the encoding to convert to (memory encoding rather than file encoding)
115 wxString
encoding(wxT("UTF-8"));
117 #if !wxUSE_UNICODE && wxUSE_INTL
118 encoding
= wxLocale::GetSystemEncodingName();
121 if (!xmlDoc
->Load(stream
, encoding
))
123 buffer
->ResetAndClearCommands();
128 if (xmlDoc
->GetRoot() && xmlDoc
->GetRoot()->GetType() == wxXML_ELEMENT_NODE
&& xmlDoc
->GetRoot()->GetName() == wxT("richtext"))
130 wxXmlNode
* child
= xmlDoc
->GetRoot()->GetChildren();
133 if (child
->GetType() == wxXML_ELEMENT_NODE
)
135 wxString name
= child
->GetName();
136 if (name
== wxT("richtext-version"))
140 ImportXML(buffer
, buffer
, child
);
143 child
= child
->GetNext();
154 buffer
->UpdateRanges();
159 /// Creates an object given an XML element name
160 wxRichTextObject
* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject
* WXUNUSED(parent
), const wxString
& name
) const
162 // The standard node to class mappings are added in wxRichTextModule::OnInit in richtextbuffer.cpp
163 wxStringToStringHashMap::const_iterator it
= sm_nodeNameToClassMap
.find(name
);
164 if (it
== sm_nodeNameToClassMap
.end())
167 return wxDynamicCast(wxCreateDynamicObject(it
->second
), wxRichTextObject
);
170 /// Recursively import an object
171 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer
* buffer
, wxRichTextObject
* obj
, wxXmlNode
* node
)
173 bool recurse
= false;
174 obj
->ImportFromXML(buffer
, node
, this, & recurse
);
176 // TODO: how to control whether to import children.
178 wxRichTextCompositeObject
* compositeParent
= wxDynamicCast(obj
, wxRichTextCompositeObject
);
179 if (recurse
&& compositeParent
)
181 wxXmlNode
* child
= node
->GetChildren();
184 if (child
->GetName() != wxT("stylesheet"))
186 wxRichTextObject
* childObj
= CreateObjectForXMLName(obj
, child
->GetName());
189 compositeParent
->AppendChild(childObj
);
190 ImportXML(buffer
, childObj
, child
);
193 child
= child
->GetNext();
200 bool wxRichTextXMLHandler::ImportProperties(wxRichTextObject
* obj
, wxXmlNode
* node
)
202 return ImportProperties(obj
->GetProperties(), node
);
205 bool wxRichTextXMLHandler::ImportProperties(wxRichTextProperties
& properties
, wxXmlNode
* node
)
207 wxXmlNode
* child
= node
->GetChildren();
210 if (child
->GetName() == wxT("properties"))
212 wxXmlNode
* propertyChild
= child
->GetChildren();
213 while (propertyChild
)
215 if (propertyChild
->GetName() == wxT("property"))
217 wxString name
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
);
218 wxString value
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
);
219 wxString type
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
);
221 wxVariant var
= MakePropertyFromString(name
, value
, type
);
224 properties
.SetProperty(var
);
227 propertyChild
= propertyChild
->GetNext();
230 child
= child
->GetNext();
235 bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
)
237 wxString styleType
= node
->GetName();
238 wxString styleName
= node
->GetAttribute(wxT("name"), wxEmptyString
);
239 wxString baseStyleName
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
);
241 if (styleName
.empty())
244 if (styleType
== wxT("characterstyle"))
246 wxRichTextCharacterStyleDefinition
* def
= new wxRichTextCharacterStyleDefinition(styleName
);
247 def
->SetBaseStyle(baseStyleName
);
249 wxXmlNode
* child
= node
->GetChildren();
252 if (child
->GetName() == wxT("style"))
255 ImportStyle(attr
, child
, false);
258 child
= child
->GetNext();
261 ImportProperties(def
->GetProperties(), node
);
263 sheet
->AddCharacterStyle(def
);
265 else if (styleType
== wxT("paragraphstyle"))
267 wxRichTextParagraphStyleDefinition
* def
= new wxRichTextParagraphStyleDefinition(styleName
);
269 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
270 def
->SetNextStyle(nextStyleName
);
271 def
->SetBaseStyle(baseStyleName
);
273 wxXmlNode
* child
= node
->GetChildren();
276 if (child
->GetName() == wxT("style"))
279 ImportStyle(attr
, child
, true);
282 child
= child
->GetNext();
285 ImportProperties(def
->GetProperties(), node
);
287 sheet
->AddParagraphStyle(def
);
289 else if (styleType
== wxT("boxstyle"))
291 wxRichTextBoxStyleDefinition
* def
= new wxRichTextBoxStyleDefinition(styleName
);
293 def
->SetBaseStyle(baseStyleName
);
295 wxXmlNode
* child
= node
->GetChildren();
298 if (child
->GetName() == wxT("style"))
301 ImportStyle(attr
, child
, true);
304 child
= child
->GetNext();
307 ImportProperties(def
->GetProperties(), node
);
309 sheet
->AddBoxStyle(def
);
311 else if (styleType
== wxT("liststyle"))
313 wxRichTextListStyleDefinition
* def
= new wxRichTextListStyleDefinition(styleName
);
315 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
316 def
->SetNextStyle(nextStyleName
);
317 def
->SetBaseStyle(baseStyleName
);
319 wxXmlNode
* child
= node
->GetChildren();
322 if (child
->GetName() == wxT("style"))
325 ImportStyle(attr
, child
, true);
327 wxString styleLevel
= child
->GetAttribute(wxT("level"), wxEmptyString
);
328 if (styleLevel
.empty())
334 int level
= wxAtoi(styleLevel
);
335 if (level
> 0 && level
<= 10)
337 def
->SetLevelAttributes(level
-1, attr
);
341 child
= child
->GetNext();
344 ImportProperties(def
->GetProperties(), node
);
346 sheet
->AddListStyle(def
);
352 //-----------------------------------------------------------------------------
353 // xml support routines
354 //-----------------------------------------------------------------------------
356 bool wxRichTextXMLHandler::HasParam(wxXmlNode
* node
, const wxString
& param
)
358 return (GetParamNode(node
, param
) != NULL
);
361 wxXmlNode
*wxRichTextXMLHandler::GetParamNode(wxXmlNode
* node
, const wxString
& param
)
363 wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!"));
365 wxXmlNode
*n
= node
->GetChildren();
369 if (n
->GetType() == wxXML_ELEMENT_NODE
&& n
->GetName() == param
)
377 wxString
wxRichTextXMLHandler::GetNodeContent(wxXmlNode
*node
)
380 if (n
== NULL
) return wxEmptyString
;
381 n
= n
->GetChildren();
385 if (n
->GetType() == wxXML_TEXT_NODE
||
386 n
->GetType() == wxXML_CDATA_SECTION_NODE
)
387 return n
->GetContent();
390 return wxEmptyString
;
394 wxString
wxRichTextXMLHandler::GetParamValue(wxXmlNode
*node
, const wxString
& param
)
397 return GetNodeContent(node
);
399 return GetNodeContent(GetParamNode(node
, param
));
402 wxString
wxRichTextXMLHandler::GetText(wxXmlNode
*node
, const wxString
& param
, bool WXUNUSED(translate
))
404 wxXmlNode
*parNode
= GetParamNode(node
, param
);
407 wxString
str1(GetNodeContent(parNode
));
411 wxXmlNode
* wxRichTextXMLHandler::FindNode(wxXmlNode
* node
, const wxString
& name
)
413 if (node
->GetName() == name
&& name
== wxT("stylesheet"))
416 wxXmlNode
* child
= node
->GetChildren();
419 if (child
->GetName() == name
)
421 child
= child
->GetNext();
426 // For use with earlier versions of wxWidgets
427 #ifndef WXUNUSED_IN_UNICODE
429 #define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
431 #define WXUNUSED_IN_UNICODE(x) x
435 // write string to output
436 inline static void OutputString(wxOutputStream
& stream
, const wxString
& str
,
437 wxMBConv
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv
*convFile
)
439 if (str
.empty()) return;
443 const wxWX2MBbuf
buf(str
.mb_str(*convFile
));
444 stream
.Write((const char*)buf
, strlen((const char*)buf
));
448 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
449 stream
.Write((const char*)buf
, strlen((const char*)buf
));
452 if ( convFile
== NULL
)
453 stream
.Write(str
.mb_str(), str
.Len());
456 wxString
str2(str
.wc_str(*convMem
), *convFile
);
457 stream
.Write(str2
.mb_str(), str2
.Len());
462 static void OutputIndentation(wxOutputStream
& stream
, int indent
)
464 wxString str
= wxT("\n");
465 for (int i
= 0; i
< indent
; i
++)
466 str
<< wxT(' ') << wxT(' ');
467 ::OutputString(stream
, str
, NULL
, NULL
);
470 // Same as above, but create entities first.
471 // Translates '<' to "<", '>' to ">" and '&' to "&"
472 static void OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
,
473 wxMBConv
*convMem
= NULL
, wxMBConv
*convFile
= NULL
)
481 for (i
= 0; i
< len
; i
++)
485 // Original code excluded "&" but we _do_ want to convert
486 // the ampersand beginning & because otherwise when read in,
487 // the original "&" becomes "&".
489 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
490 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
492 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
496 OutputString(stream
, wxT("<"), NULL
, NULL
);
499 OutputString(stream
, wxT(">"), NULL
, NULL
);
502 OutputString(stream
, wxT("&"), NULL
, NULL
);
505 OutputString(stream
, wxT("""), NULL
, NULL
);
511 else if (wxUChar(c
) > 127)
513 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
515 wxString
s(wxT("&#"));
519 s
<< (int) wxUChar(c
);
522 OutputString(stream
, s
, NULL
, NULL
);
526 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
529 void wxRichTextXMLHandler::OutputString(wxOutputStream
& stream
, const wxString
& str
)
531 ::OutputString(stream
, str
, m_convMem
, m_convFile
);
534 void wxRichTextXMLHandler::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
)
536 ::OutputStringEnt(stream
, str
, m_convMem
, m_convFile
);
539 void wxRichTextXMLHandler::OutputIndentation(wxOutputStream
& stream
, int indent
)
541 wxString str
= wxT("\n");
542 for (int i
= 0; i
< indent
; i
++)
543 str
<< wxT(' ') << wxT(' ');
544 ::OutputString(stream
, str
, NULL
, NULL
);
547 wxString
wxRichTextXMLHandler::AttributeToXML(const wxString
& str
)
555 for (i
= 0; i
< len
; i
++)
559 // Original code excluded "&" but we _do_ want to convert
560 // the ampersand beginning & because otherwise when read in,
561 // the original "&" becomes "&".
563 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
564 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
566 str1
+= str
.Mid(last
, i
- last
);
576 str1
+= wxT("&");
579 str1
+= wxT(""");
585 else if (wxUChar(c
) > 127)
587 str1
+= str
.Mid(last
, i
- last
);
589 wxString
s(wxT("&#"));
593 s
<< (int) wxUChar(c
);
600 str1
+= str
.Mid(last
, i
- last
);
604 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
606 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const int& v
)
608 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\"");
611 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const long& v
)
613 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\"");
616 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const double& v
)
618 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\"");
621 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxChar
* s
)
623 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
626 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxString
& s
)
628 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
631 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxColour
& col
)
633 str
<< wxT(" ") << name
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\"");
636 static inline void AddAttribute(wxString
& str
, const wxString
& name
, const wxTextAttrDimension
& dim
)
640 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags());
641 str
<< wxT(" ") << name
<< wxT("=\"");
647 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
649 if (dims
.GetLeft().IsValid())
650 AddAttribute(str
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
651 if (dims
.GetRight().IsValid())
652 AddAttribute(str
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
653 if (dims
.GetTop().IsValid())
654 AddAttribute(str
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
655 if (dims
.GetBottom().IsValid())
656 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
659 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
661 if (border
.HasStyle())
662 AddAttribute(str
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
663 if (border
.HasColour())
664 AddAttribute(str
, rootName
+ wxString(wxT("-color")), border
.GetColour());
665 if (border
.HasWidth())
666 AddAttribute(str
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
669 static inline void AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
671 AddAttribute(str
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
672 AddAttribute(str
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
673 AddAttribute(str
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
674 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
678 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
680 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
682 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const int& v
)
684 node
->AddAttribute(name
, MakeString(v
));
687 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const long& v
)
689 node
->AddAttribute(name
, MakeString(v
));
692 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const double& v
)
694 node
->AddAttribute(name
, MakeString(v
));
697 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxString
& s
)
699 node
->AddAttribute(name
, s
);
702 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxColour
& col
)
704 node
->AddAttribute(name
, MakeString(col
));
707 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxTextAttrDimension
& dim
)
711 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags());
712 AddAttribute(node
, name
, value
);
716 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
718 if (dims
.GetLeft().IsValid())
719 AddAttribute(node
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
720 if (dims
.GetRight().IsValid())
721 AddAttribute(node
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
722 if (dims
.GetTop().IsValid())
723 AddAttribute(node
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
724 if (dims
.GetBottom().IsValid())
725 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
728 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
730 if (border
.HasStyle())
731 AddAttribute(node
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
732 if (border
.HasColour())
733 AddAttribute(node
, rootName
+ wxString(wxT("-color")), border
.GetColour());
734 if (border
.HasWidth())
735 AddAttribute(node
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
738 static inline void AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
740 AddAttribute(node
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
741 AddAttribute(node
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
742 AddAttribute(node
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
743 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
746 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
748 bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer
*buffer
, wxOutputStream
& stream
)
753 wxString
version(wxT("1.0") ) ;
755 bool deleteConvFile
= false;
756 wxString fileEncoding
;
757 //wxMBConv* convFile = NULL;
760 fileEncoding
= wxT("UTF-8");
761 m_convFile
= & wxConvUTF8
;
763 fileEncoding
= wxT("ISO-8859-1");
764 m_convFile
= & wxConvISO8859_1
;
767 // If SetEncoding has been called, change the output encoding.
768 if (!m_encoding
.empty() && m_encoding
.Lower() != fileEncoding
.Lower())
770 if (m_encoding
== wxT("<System>"))
773 fileEncoding
= wxLocale::GetSystemEncodingName();
774 // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below
779 fileEncoding
= m_encoding
;
782 // GetSystemEncodingName may not have returned a name
783 if (fileEncoding
.empty())
785 fileEncoding
= wxT("UTF-8");
787 fileEncoding
= wxT("ISO-8859-1");
789 m_convFile
= new wxCSConv(fileEncoding
);
790 deleteConvFile
= true;
793 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT
794 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
795 wxStopWatch stopwatch
;
797 wxXmlDocument
* doc
= new wxXmlDocument
;
798 doc
->SetFileEncoding(fileEncoding
);
800 wxXmlNode
* rootNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("richtext"));
801 doc
->SetRoot(rootNode
);
802 rootNode
->AddAttribute(wxT("version"), wxT("1.0.0.0"));
803 rootNode
->AddAttribute(wxT("xmlns"), wxT("http://www.wxwidgets.org"));
805 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
807 wxXmlNode
* styleSheetNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("stylesheet"));
808 rootNode
->AddChild(styleSheetNode
);
810 wxString nameAndDescr
;
812 if (!buffer
->GetStyleSheet()->GetName().empty())
813 styleSheetNode
->AddAttribute(wxT("name"), buffer
->GetStyleSheet()->GetName());
815 if (!buffer
->GetStyleSheet()->GetDescription().empty())
816 styleSheetNode
->AddAttribute(wxT("description"), buffer
->GetStyleSheet()->GetDescription());
819 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
821 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
822 ExportStyleDefinition(styleSheetNode
, def
);
825 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
827 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
828 ExportStyleDefinition(styleSheetNode
, def
);
831 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
833 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
834 ExportStyleDefinition(styleSheetNode
, def
);
837 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
839 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
840 ExportStyleDefinition(styleSheetNode
, def
);
843 WriteProperties(styleSheetNode
, buffer
->GetStyleSheet()->GetProperties());
845 bool success
= ExportXML(rootNode
, *buffer
);
846 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
847 long t
= stopwatch
.Time();
848 wxLogDebug(wxT("Creating the document took %ldms"), t
);
849 wxMessageBox(wxString::Format(wxT("Creating the document took %ldms"), t
));
853 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
856 success
= doc
->Save(stream
);
857 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
859 wxLogDebug(wxT("Save() took %ldms"), t2
);
860 wxMessageBox(wxString::Format(wxT("Save() took %ldms"), t2
));
867 // !(wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT)
870 m_convMem
= wxConvCurrent
;
876 s
.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"),
877 version
, fileEncoding
);
878 OutputString(stream
, s
);
879 OutputString(stream
, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">"));
883 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
885 OutputIndentation(stream
, level
);
886 wxString nameAndDescr
;
887 if (!buffer
->GetStyleSheet()->GetName().empty())
888 nameAndDescr
<< wxT(" name=\"") << buffer
->GetStyleSheet()->GetName() << wxT("\"");
889 if (!buffer
->GetStyleSheet()->GetDescription().empty())
890 nameAndDescr
<< wxT(" description=\"") << buffer
->GetStyleSheet()->GetDescription() << wxT("\"");
891 OutputString(stream
, wxString(wxT("<stylesheet")) + nameAndDescr
+ wxT(">"));
895 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
897 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
898 ExportStyleDefinition(stream
, def
, level
+ 1);
901 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
903 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
904 ExportStyleDefinition(stream
, def
, level
+ 1);
907 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
909 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
910 ExportStyleDefinition(stream
, def
, level
+ 1);
913 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
915 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
916 ExportStyleDefinition(stream
, def
, level
+ 1);
919 WriteProperties(stream
, buffer
->GetStyleSheet()->GetProperties(), level
);
921 OutputIndentation(stream
, level
);
922 OutputString(stream
, wxT("</stylesheet>"));
926 bool success
= ExportXML(stream
, *buffer
, level
);
928 OutputString(stream
, wxT("\n</richtext>"));
929 OutputString(stream
, wxT("\n"));
940 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
942 /// Recursively export an object
943 bool wxRichTextXMLHandler::ExportXML(wxOutputStream
& stream
, wxRichTextObject
& obj
, int indent
)
945 obj
.ExportXML(stream
, indent
, this);
950 bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
)
952 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
953 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
954 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
955 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
957 wxString name
= def
->GetName();
960 nameProp
= wxT(" name=\"") + AttributeToXML(name
) + wxT("\"");
962 wxString baseStyle
= def
->GetBaseStyle();
963 wxString baseStyleProp
;
964 if (!baseStyle
.empty())
965 baseStyleProp
= wxT(" basestyle=\"") + AttributeToXML(baseStyle
) + wxT("\"");
967 wxString descr
= def
->GetDescription();
970 descrProp
= wxT(" description=\"") + AttributeToXML(descr
) + wxT("\"");
974 OutputIndentation(stream
, level
);
975 OutputString(stream
, wxT("<characterstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
979 wxString style
= AddAttributes(def
->GetStyle(), false);
981 OutputIndentation(stream
, level
);
982 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
984 OutputIndentation(stream
, level
);
985 OutputString(stream
, wxT("</style>"));
989 OutputIndentation(stream
, level
);
990 OutputString(stream
, wxT("</characterstyle>"));
994 OutputIndentation(stream
, level
);
996 if (!listDef
->GetNextStyle().empty())
997 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(listDef
->GetNextStyle()) << wxT("\"");
999 OutputString(stream
, wxT("<liststyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1003 wxString style
= AddAttributes(def
->GetStyle(), true);
1005 OutputIndentation(stream
, level
);
1006 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1008 OutputIndentation(stream
, level
);
1009 OutputString(stream
, wxT("</style>"));
1012 for (i
= 0; i
< 10; i
++)
1014 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1017 wxString style
= AddAttributes(def
->GetStyle(), true);
1018 wxString levelStr
= wxString::Format(wxT(" level=\"%d\" "), (i
+1));
1020 OutputIndentation(stream
, level
);
1021 OutputString(stream
, wxT("<style ") + levelStr
+ style
+ wxT(">"));
1023 OutputIndentation(stream
, level
);
1024 OutputString(stream
, wxT("</style>"));
1030 OutputIndentation(stream
, level
);
1031 OutputString(stream
, wxT("</liststyle>"));
1035 OutputIndentation(stream
, level
);
1037 if (!paraDef
->GetNextStyle().empty())
1038 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(paraDef
->GetNextStyle()) << wxT("\"");
1040 OutputString(stream
, wxT("<paragraphstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1044 wxString style
= AddAttributes(def
->GetStyle(), true);
1046 OutputIndentation(stream
, level
);
1047 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1049 OutputIndentation(stream
, level
);
1050 OutputString(stream
, wxT("</style>"));
1054 OutputIndentation(stream
, level
);
1055 OutputString(stream
, wxT("</paragraphstyle>"));
1059 OutputIndentation(stream
, level
);
1061 OutputString(stream
, wxT("<boxstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
1065 wxString style
= AddAttributes(def
->GetStyle(), true);
1067 OutputIndentation(stream
, level
);
1068 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
1070 OutputIndentation(stream
, level
);
1071 OutputString(stream
, wxT("</style>"));
1075 OutputIndentation(stream
, level
);
1076 OutputString(stream
, wxT("</boxstyle>"));
1079 WriteProperties(stream
, def
->GetProperties(), level
);
1084 /// Create a string containing style attributes
1085 wxString
wxRichTextXMLHandler::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
)
1088 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1089 AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour());
1091 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1092 AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour());
1094 if (attr
.HasFontPointSize())
1095 AddAttribute(str
, wxT("fontpointsize"), attr
.GetFontSize());
1096 else if (attr
.HasFontPixelSize())
1097 AddAttribute(str
, wxT("fontpixelsize"), attr
.GetFontSize());
1099 if (attr
.HasFontFamily())
1100 AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily());
1102 if (attr
.HasFontItalic())
1103 AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle());
1105 if (attr
.HasFontWeight())
1106 AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight());
1108 if (attr
.HasFontUnderlined())
1109 AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined());
1111 if (attr
.HasFontFaceName())
1112 AddAttribute(str
, wxT("fontface"), AttributeToXML(attr
.GetFontFaceName()));
1114 if (attr
.HasTextEffects())
1116 AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects());
1117 AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags());
1120 if (!attr
.GetCharacterStyleName().empty())
1121 AddAttribute(str
, wxT("characterstyle"), AttributeToXML(attr
.GetCharacterStyleName()));
1124 AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL()));
1128 if (attr
.HasAlignment())
1129 AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment());
1131 if (attr
.HasLeftIndent())
1133 AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent());
1134 AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent());
1137 if (attr
.HasRightIndent())
1138 AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent());
1140 if (attr
.HasParagraphSpacingAfter())
1141 AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter());
1143 if (attr
.HasParagraphSpacingBefore())
1144 AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore());
1146 if (attr
.HasLineSpacing())
1147 AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing());
1149 if (attr
.HasBulletStyle())
1150 AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle());
1152 if (attr
.HasBulletNumber())
1153 AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber());
1155 if (attr
.HasBulletText())
1157 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1158 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1159 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1160 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0]));
1162 AddAttribute(str
, wxT("bullettext"), AttributeToXML(attr
.GetBulletText()));
1164 AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont());
1167 if (attr
.HasBulletName())
1168 AddAttribute(str
, wxT("bulletname"), AttributeToXML(attr
.GetBulletName()));
1170 if (!attr
.GetParagraphStyleName().empty())
1171 AddAttribute(str
, wxT("parstyle"), AttributeToXML(attr
.GetParagraphStyleName()));
1173 if (!attr
.GetListStyleName().empty())
1174 AddAttribute(str
, wxT("liststyle"), AttributeToXML(attr
.GetListStyleName()));
1176 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1177 AddAttribute(str
, wxT("boxstyle"), AttributeToXML(attr
.GetTextBoxAttr().GetBoxStyleName()));
1183 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1185 if (i
> 0) strTabs
<< wxT(",");
1186 strTabs
<< attr
.GetTabs()[i
];
1188 AddAttribute(str
, wxT("tabs"), strTabs
);
1191 if (attr
.HasPageBreak())
1193 AddAttribute(str
, wxT("pagebreak"), 1);
1196 if (attr
.HasOutlineLevel())
1197 AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel());
1200 AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1201 AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1202 AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1203 AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1204 AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1205 AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1206 AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1207 AddAttribute(str
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1208 AddAttribute(str
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1209 AddAttribute(str
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1210 AddAttribute(str
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1212 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1215 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1217 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1218 value
= wxT("centre");
1219 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1220 value
= wxT("bottom");
1222 value
= wxT("none");
1223 AddAttribute(str
, wxT("verticalalignment"), value
);
1226 if (attr
.GetTextBoxAttr().HasFloatMode())
1229 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1230 value
= wxT("left");
1231 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1232 value
= wxT("right");
1234 value
= wxT("none");
1235 AddAttribute(str
, wxT("float"), value
);
1238 if (attr
.GetTextBoxAttr().HasClearMode())
1241 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1242 value
= wxT("left");
1243 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1244 value
= wxT("right");
1245 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1246 value
= wxT("both");
1248 value
= wxT("none");
1249 AddAttribute(str
, wxT("clear"), value
);
1252 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1253 AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1258 // Make a string from the given property. This can be overridden for custom variants.
1259 wxString
wxRichTextXMLHandler::MakeStringFromProperty(const wxVariant
& var
)
1261 return var
.MakeString();
1264 // Create a proprty from the string read from the XML file.
1265 wxVariant
wxRichTextXMLHandler::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
))
1267 wxVariant
var(value
, name
);
1268 // TODO: use type to create using common types
1272 // Write the properties
1273 bool wxRichTextXMLHandler::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
)
1275 if (properties
.GetCount() > 0)
1279 OutputIndentation(stream
, level
);
1280 OutputString(stream
, wxT("<properties>"));
1285 for (i
= 0; i
< properties
.GetCount(); i
++)
1287 const wxVariant
& var
= properties
[i
];
1290 const wxString
& name
= var
.GetName();
1291 wxString value
= MakeStringFromProperty(var
);
1293 OutputIndentation(stream
, level
);
1294 OutputString(stream
, wxT("<property name=\"") + name
+
1295 wxT("\" type=\"") + var
.GetType() + wxT("\" value=\""));
1296 OutputStringEnt(stream
, value
);
1297 OutputString(stream
, wxT("\"/>"));
1303 OutputIndentation(stream
, level
);
1304 OutputString(stream
, wxT("</properties>"));
1314 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
1316 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1317 bool wxRichTextXMLHandler::ExportXML(wxXmlNode
* parent
, wxRichTextObject
& obj
)
1319 obj
.ExportXML(parent
, this);
1324 bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
)
1326 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
1327 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
1328 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
1329 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
1331 wxString baseStyle
= def
->GetBaseStyle();
1332 wxString descr
= def
->GetDescription();
1334 wxXmlNode
* defNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
);
1335 parent
->AddChild(defNode
);
1336 if (!baseStyle
.empty())
1337 defNode
->AddAttribute(wxT("basestyle"), baseStyle
);
1339 defNode
->AddAttribute(wxT("description"), descr
);
1341 wxXmlNode
* styleNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1342 defNode
->AddChild(styleNode
);
1346 defNode
->SetName(wxT("characterstyle"));
1347 AddAttributes(styleNode
, def
->GetStyle(), false);
1351 defNode
->SetName(wxT("liststyle"));
1353 if (!listDef
->GetNextStyle().empty())
1354 defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle());
1356 AddAttributes(styleNode
, def
->GetStyle(), true);
1359 for (i
= 0; i
< 10; i
++)
1361 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
1364 wxXmlNode
* levelNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
1365 defNode
->AddChild(levelNode
);
1366 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1));
1367 AddAttributes(levelNode
, * levelAttr
, true);
1373 defNode
->SetName(wxT("boxstyle"));
1375 AddAttributes(styleNode
, def
->GetStyle(), true);
1379 defNode
->SetName(wxT("paragraphstyle"));
1381 if (!paraDef
->GetNextStyle().empty())
1382 defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle());
1384 AddAttributes(styleNode
, def
->GetStyle(), true);
1387 WriteProperties(defNode
, def
->GetProperties());
1392 bool wxRichTextXMLHandler::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
)
1394 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
1395 node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour()));
1396 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
1397 node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour()));
1399 if (attr
.HasFontPointSize())
1400 node
->AddAttribute(wxT("fontpointsize"), MakeString(attr
.GetFontSize()));
1401 else if (attr
.HasFontPixelSize())
1402 node
->AddAttribute(wxT("fontpixelsize"), MakeString(attr
.GetFontSize()));
1403 if (attr
.HasFontFamily())
1404 node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily()));
1405 if (attr
.HasFontItalic())
1406 node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle()));
1407 if (attr
.HasFontWeight())
1408 node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight()));
1409 if (attr
.HasFontUnderlined())
1410 node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined()));
1411 if (attr
.HasFontFaceName())
1412 node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName());
1414 if (attr
.HasTextEffects())
1416 node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects()));
1417 node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags()));
1419 if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty())
1420 node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName());
1423 node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML?
1427 if (attr
.HasAlignment())
1428 node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment()));
1430 if (attr
.HasLeftIndent())
1432 node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent()));
1433 node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent()));
1436 if (attr
.HasRightIndent())
1437 node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent()));
1439 if (attr
.HasParagraphSpacingAfter())
1440 node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter()));
1442 if (attr
.HasParagraphSpacingBefore())
1443 node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore()));
1445 if (attr
.HasLineSpacing())
1446 node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing()));
1448 if (attr
.HasBulletStyle())
1449 node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle()));
1451 if (attr
.HasBulletNumber())
1452 node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber()));
1454 if (attr
.HasBulletText())
1456 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
1457 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
1458 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
1459 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0])));
1461 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText());
1463 if (!attr
.GetBulletFont().empty())
1464 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont());
1467 if (attr
.HasBulletName())
1468 node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName());
1470 if (!attr
.GetParagraphStyleName().empty())
1471 node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName());
1473 if (!attr
.GetListStyleName().empty())
1474 node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName());
1476 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
1477 node
->AddAttribute(wxT("boxstyle"), attr
.GetTextBoxAttr().GetBoxStyleName());
1483 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
1487 tabs
<< attr
.GetTabs()[i
];
1489 node
->AddAttribute(wxT("tabs"), tabs
);
1492 if (attr
.HasPageBreak())
1493 node
->AddAttribute(wxT("pagebreak"), wxT("1"));
1495 if (attr
.HasOutlineLevel())
1496 node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel()));
1499 AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
1500 AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
1501 AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
1502 AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
1503 AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
1504 AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
1505 AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
1506 AddAttribute(node
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
1507 AddAttribute(node
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
1508 AddAttribute(node
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
1509 AddAttribute(node
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
1511 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
1514 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
1516 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
1517 value
= wxT("centre");
1518 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
1519 value
= wxT("bottom");
1521 value
= wxT("none");
1522 AddAttribute(node
, wxT("verticalalignment"), value
);
1525 if (attr
.GetTextBoxAttr().HasFloatMode())
1528 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
1529 value
= wxT("left");
1530 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
1531 value
= wxT("right");
1533 value
= wxT("none");
1534 AddAttribute(node
, wxT("float"), value
);
1537 if (attr
.GetTextBoxAttr().HasClearMode())
1540 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
1541 value
= wxT("left");
1542 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
1543 value
= wxT("right");
1544 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
1545 value
= wxT("both");
1547 value
= wxT("none");
1548 AddAttribute(node
, wxT("clear"), value
);
1551 if (attr
.GetTextBoxAttr().HasCollapseBorders())
1552 AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
1557 bool wxRichTextXMLHandler::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
)
1559 if (properties
.GetCount() > 0)
1561 wxXmlNode
* propertiesNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties"));
1562 node
->AddChild(propertiesNode
);
1564 for (i
= 0; i
< properties
.GetCount(); i
++)
1566 const wxVariant
& var
= properties
[i
];
1569 wxXmlNode
* propertyNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property"));
1570 propertiesNode
->AddChild(propertyNode
);
1572 const wxString
& name
= var
.GetName();
1573 wxString value
= MakeStringFromProperty(var
);
1575 AddAttribute(propertyNode
, wxT("name"), name
);
1576 AddAttribute(propertyNode
, wxT("type"), var
.GetType());
1577 AddAttribute(propertyNode
, wxT("value"), value
);
1585 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1587 /// Replace face name with current name for platform.
1588 /// TODO: introduce a virtual function or settable table to
1589 /// do this comprehensively.
1590 bool wxRichTextFixFaceName(wxString
& facename
)
1592 if (facename
.empty())
1596 if (facename
== wxT("Times"))
1598 facename
= wxT("Times New Roman");
1601 else if (facename
== wxT("Helvetica"))
1603 facename
= wxT("Arial");
1606 else if (facename
== wxT("Courier"))
1608 facename
= wxT("Courier New");
1614 if (facename
== wxT("Times New Roman"))
1616 facename
= wxT("Times");
1619 else if (facename
== wxT("Arial"))
1621 facename
= wxT("Helvetica");
1624 else if (facename
== wxT("Courier New"))
1626 facename
= wxT("Courier");
1634 static inline long wxRichTextColourStringToLong(const wxString
& colStr
)
1636 if (!colStr
.IsEmpty())
1638 wxColour
col(colStr
);
1639 return col
.GetRGB();
1645 static inline wxTextAttrDimension
wxRichTextParseDimension(const wxString
& dimStr
)
1647 wxString valuePart
= dimStr
.BeforeFirst(wxT(','));
1649 if (dimStr
.Contains(wxT(",")))
1650 flagsPart
= dimStr
.AfterFirst(wxT(','));
1651 wxTextAttrDimension dim
;
1652 dim
.SetValue(wxAtoi(valuePart
));
1653 dim
.SetFlags(wxAtoi(flagsPart
));
1658 /// Import style parameters
1659 bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
)
1661 wxXmlAttribute
* xmlAttr
= node
->GetAttributes();
1665 const wxString
& name
= xmlAttr
->GetName();
1666 const wxString
& value
= xmlAttr
->GetValue();
1669 if (name
== wxT("fontface"))
1674 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
)
1675 wxRichTextFixFaceName(v
);
1676 attr
.SetFontFaceName(v
);
1679 else if (name
== wxT("fontfamily"))
1682 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
));
1684 else if (name
== wxT("fontstyle"))
1687 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
));
1689 else if (name
== wxT("fontsize") || name
== wxT("fontpointsize"))
1692 attr
.SetFontPointSize(wxAtoi(value
));
1694 else if (name
== wxT("fontpixelsize"))
1697 attr
.SetFontPixelSize(wxAtoi(value
));
1699 else if (name
== wxT("fontweight"))
1702 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
));
1704 else if (name
== wxT("fontunderlined"))
1707 attr
.SetFontUnderlined(wxAtoi(value
) != 0);
1709 else if (name
== wxT("textcolor"))
1713 if (value
[0] == wxT('#'))
1714 attr
.SetTextColour(HexStringToColour(value
.Mid(1)));
1716 attr
.SetTextColour(value
);
1719 else if (name
== wxT("bgcolor"))
1723 if (value
[0] == wxT('#'))
1724 attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1)));
1726 attr
.SetBackgroundColour(value
);
1729 else if (name
== wxT("characterstyle"))
1732 attr
.SetCharacterStyleName(value
);
1734 else if (name
== wxT("texteffects"))
1737 attr
.SetTextEffects(wxAtoi(value
));
1739 else if (name
== wxT("texteffectflags"))
1742 attr
.SetTextEffectFlags(wxAtoi(value
));
1744 else if (name
== wxT("url"))
1751 if (name
== wxT("alignment"))
1754 attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
));
1756 else if (name
== wxT("leftindent"))
1759 attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent());
1761 else if (name
== wxT("leftsubindent"))
1764 attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
));
1766 else if (name
== wxT("rightindent"))
1769 attr
.SetRightIndent(wxAtoi(value
));
1771 else if (name
== wxT("parspacingbefore"))
1774 attr
.SetParagraphSpacingBefore(wxAtoi(value
));
1776 else if (name
== wxT("parspacingafter"))
1779 attr
.SetParagraphSpacingAfter(wxAtoi(value
));
1781 else if (name
== wxT("linespacing"))
1784 attr
.SetLineSpacing(wxAtoi(value
));
1786 else if (name
== wxT("bulletstyle"))
1789 attr
.SetBulletStyle(wxAtoi(value
));
1791 else if (name
== wxT("bulletnumber"))
1794 attr
.SetBulletNumber(wxAtoi(value
));
1796 else if (name
== wxT("bulletsymbol"))
1800 wxChar ch
= wxAtoi(value
);
1803 attr
.SetBulletText(s
);
1806 else if (name
== wxT("bullettext"))
1810 attr
.SetBulletText(value
);
1813 else if (name
== wxT("bulletfont"))
1817 attr
.SetBulletFont(value
);
1820 else if (name
== wxT("bulletname"))
1824 attr
.SetBulletName(value
);
1827 else if (name
== wxT("parstyle"))
1831 attr
.SetParagraphStyleName(value
);
1834 else if (name
== wxT("liststyle"))
1838 attr
.SetListStyleName(value
);
1841 else if (name
== wxT("boxstyle"))
1845 attr
.GetTextBoxAttr().SetBoxStyleName(value
);
1848 else if (name
== wxT("tabs"))
1853 wxStringTokenizer
tkz(value
, wxT(","));
1854 while (tkz
.HasMoreTokens())
1856 wxString token
= tkz
.GetNextToken();
1857 tabs
.Add(wxAtoi(token
));
1862 else if (name
== wxT("pagebreak"))
1866 attr
.SetPageBreak(wxAtoi(value
) != 0);
1869 else if (name
== wxT("outlinelevel"))
1873 attr
.SetOutlineLevel(wxAtoi(value
));
1886 if (name
== wxT("width"))
1888 attr
.GetTextBoxAttr().GetWidth().SetValue(wxRichTextParseDimension(value
));
1890 else if (name
== wxT("height"))
1892 attr
.GetTextBoxAttr().GetHeight().SetValue(wxRichTextParseDimension(value
));
1894 else if (name
== wxT("minwidth"))
1896 attr
.GetTextBoxAttr().GetMinSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1898 else if (name
== wxT("minheight"))
1900 attr
.GetTextBoxAttr().GetMinSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1902 else if (name
== wxT("maxwidth"))
1904 attr
.GetTextBoxAttr().GetMaxSize().GetWidth().SetValue(wxRichTextParseDimension(value
));
1906 else if (name
== wxT("maxheight"))
1908 attr
.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(wxRichTextParseDimension(value
));
1911 else if (name
== wxT("verticalalignment"))
1913 if (value
== wxT("top"))
1914 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
);
1915 else if (value
== wxT("centre"))
1916 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
);
1917 else if (value
== wxT("bottom"))
1918 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
);
1919 else if (value
== wxT("none"))
1920 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
);
1922 else if (name
== wxT("float"))
1924 if (value
== wxT("left"))
1925 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
);
1926 else if (value
== wxT("right"))
1927 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
);
1928 else if (value
== wxT("none"))
1929 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
);
1931 else if (name
== wxT("clear"))
1933 if (value
== wxT("left"))
1934 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
);
1935 else if (value
== wxT("right"))
1936 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
);
1937 else if (value
== wxT("both"))
1938 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
);
1939 else if (value
== wxT("none"))
1940 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
);
1942 else if (name
== wxT("collapse-borders"))
1943 attr
.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode
) wxAtoi(value
));
1945 else if (name
.Contains(wxT("border-")))
1947 if (name
== wxT("border-left-style"))
1948 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
));
1949 else if (name
== wxT("border-right-style"))
1950 attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
));
1951 else if (name
== wxT("border-top-style"))
1952 attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
));
1953 else if (name
== wxT("border-bottom-style"))
1954 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
));
1956 else if (name
== wxT("border-left-colour"))
1957 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1958 else if (name
== wxT("border-right-colour"))
1959 attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1960 else if (name
== wxT("border-top-colour"))
1961 attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1962 else if (name
== wxT("border-bottom-colour"))
1963 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1965 else if (name
== wxT("border-left-width"))
1966 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1967 else if (name
== wxT("border-right-width"))
1968 attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(wxRichTextParseDimension(value
));
1969 else if (name
== wxT("border-top-width"))
1970 attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(wxRichTextParseDimension(value
));
1971 else if (name
== wxT("border-bottom-width"))
1972 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(wxRichTextParseDimension(value
));
1974 else if (name
.Contains(wxT("outline-")))
1976 if (name
== wxT("outline-left-style"))
1977 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
));
1978 else if (name
== wxT("outline-right-style"))
1979 attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
));
1980 else if (name
== wxT("outline-top-style"))
1981 attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
));
1982 else if (name
== wxT("outline-bottom-style"))
1983 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
));
1985 else if (name
== wxT("outline-left-colour"))
1986 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(wxRichTextColourStringToLong(value
));
1987 else if (name
== wxT("outline-right-colour"))
1988 attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(wxRichTextColourStringToLong(value
));
1989 else if (name
== wxT("outline-top-colour"))
1990 attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(wxRichTextColourStringToLong(value
));
1991 else if (name
== wxT("outline-bottom-colour"))
1992 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(wxRichTextColourStringToLong(value
));
1994 else if (name
== wxT("outline-left-width"))
1995 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(wxRichTextParseDimension(value
));
1996 else if (name
== wxT("outline-right-width"))
1997 attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(wxRichTextParseDimension(value
));
1998 else if (name
== wxT("outline-top-width"))
1999 attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(wxRichTextParseDimension(value
));
2000 else if (name
== wxT("outline-bottom-width"))
2001 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(wxRichTextParseDimension(value
));
2003 else if (name
.Contains(wxT("margin-")))
2005 if (name
== wxT("margin-left"))
2006 attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(wxRichTextParseDimension(value
));
2007 else if (name
== wxT("margin-right"))
2008 attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(wxRichTextParseDimension(value
));
2009 else if (name
== wxT("margin-top"))
2010 attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(wxRichTextParseDimension(value
));
2011 else if (name
== wxT("margin-bottom"))
2012 attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(wxRichTextParseDimension(value
));
2014 else if (name
.Contains(wxT("padding-")))
2016 if (name
== wxT("padding-left"))
2017 attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(wxRichTextParseDimension(value
));
2018 else if (name
== wxT("padding-right"))
2019 attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(wxRichTextParseDimension(value
));
2020 else if (name
== wxT("padding-top"))
2021 attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(wxRichTextParseDimension(value
));
2022 else if (name
== wxT("padding-bottom"))
2023 attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(wxRichTextParseDimension(value
));
2025 else if (name
.Contains(wxT("position-")))
2027 if (name
== wxT("position-left"))
2028 attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(wxRichTextParseDimension(value
));
2029 else if (name
== wxT("position-right"))
2030 attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(wxRichTextParseDimension(value
));
2031 else if (name
== wxT("position-top"))
2032 attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(wxRichTextParseDimension(value
));
2033 else if (name
== wxT("position-bottom"))
2034 attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(wxRichTextParseDimension(value
));
2038 xmlAttr
= xmlAttr
->GetNext();
2047 // Import this object from XML
2048 bool wxRichTextObject::ImportFromXML(wxRichTextBuffer
* WXUNUSED(buffer
), wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2050 handler
->ImportProperties(this, node
);
2051 handler
->ImportStyle(GetAttributes(), node
, UsesParagraphAttributes());
2058 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2059 // Export this object directly to the given stream.
2060 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2062 ::OutputIndentation(stream
, indent
);
2063 ::OutputString(stream
, wxT("<") + GetXMLNodeName(), handler
->GetConvMem(), handler
->GetConvFile());
2065 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2067 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2069 if (GetProperties().GetCount() > 0)
2071 handler
->WriteProperties(stream
, GetProperties(), indent
);
2074 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2078 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2080 wxRichTextObject
* child
= composite
->GetChild(i
);
2081 child
->ExportXML(stream
, indent
+1, handler
);
2085 ::OutputIndentation(stream
, indent
);
2086 ::OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2091 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2092 // Export this object to the given parent node, usually creating at least one child node.
2093 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2095 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2096 parent
->AddChild(elementNode
);
2097 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2098 handler
->WriteProperties(elementNode
, GetProperties());
2100 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
2104 for (i
= 0; i
< composite
->GetChildCount(); i
++)
2106 wxRichTextObject
* child
= composite
->GetChild(i
);
2107 child
->ExportXML(elementNode
, handler
);
2115 // Import this object from XML
2116 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2118 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2120 if (node
->GetName() == wxT("text"))
2123 wxXmlNode
* textChild
= node
->GetChildren();
2126 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2127 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2129 wxString text2
= textChild
->GetContent();
2131 // Strip whitespace from end
2132 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n'))
2133 text2
= text2
.Mid(0, text2
.length()-1);
2135 if (!text2
.empty() && text2
[0] == wxT('"'))
2136 text2
= text2
.Mid(1);
2137 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"'))
2138 text2
= text2
.Mid(0, text2
.length() - 1);
2142 textChild
= textChild
->GetNext();
2147 else if (node
->GetName() == wxT("symbol"))
2149 // This is a symbol that XML can't read in the normal way
2151 wxXmlNode
* textChild
= node
->GetChildren();
2154 if (textChild
->GetType() == wxXML_TEXT_NODE
||
2155 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
2157 wxString text2
= textChild
->GetContent();
2160 textChild
= textChild
->GetNext();
2163 wxString actualText
;
2164 actualText
<< (wxChar
) wxAtoi(text
);
2165 SetText(actualText
);
2173 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2174 // Export this object directly to the given stream.
2175 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2177 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2181 const wxString
& text
= GetText();
2182 int len
= (int) text
.Length();
2187 ::OutputIndentation(stream
, indent
);
2188 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2189 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2190 if (GetProperties().GetCount() > 0)
2192 handler
->WriteProperties(stream
, GetProperties(), indent
);
2193 ::OutputIndentation(stream
, indent
);
2195 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2197 else for (i
= 0; i
< len
; i
++)
2200 int c
= (int) text
[i
];
2202 int c
= (int) wxUChar(text
[i
]);
2204 if ((c
< 32 || c
== 34) && /* c != 9 && */ c
!= 10 && c
!= 13)
2208 wxString
fragment(text
.Mid(last
, i
-last
));
2209 if (!fragment
.empty())
2211 ::OutputIndentation(stream
, indent
);
2212 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2214 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2216 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2218 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2219 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2220 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2223 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2225 if (GetProperties().GetCount() > 0)
2227 handler
->WriteProperties(stream
, GetProperties(), indent
);
2228 ::OutputIndentation(stream
, indent
);
2230 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2235 // Output this character as a number in a separate tag, because XML can't cope
2236 // with entities below 32 except for 10 and 13
2238 ::OutputIndentation(stream
, indent
);
2239 ::OutputString(stream
, wxT("<symbol"), handler
->GetConvMem(), handler
->GetConvFile());
2241 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2242 ::OutputString(stream
, wxString::Format(wxT("%d"), c
), handler
->GetConvMem(), handler
->GetConvFile());
2244 if (GetProperties().GetCount() > 0)
2246 handler
->WriteProperties(stream
, GetProperties(), indent
);
2247 ::OutputIndentation(stream
, indent
);
2249 ::OutputString(stream
, wxT("</symbol>"), handler
->GetConvMem(), handler
->GetConvFile());
2257 fragment
= text
.Mid(last
, i
-last
);
2261 ::OutputIndentation(stream
, indent
);
2262 ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile());
2264 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2266 if (GetProperties().GetCount() > 0)
2268 handler
->WriteProperties(stream
, GetProperties(), indent
);
2269 ::OutputIndentation(stream
, indent
);
2272 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
2274 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2275 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2276 ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile());
2279 ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile());
2281 ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile());
2287 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2288 // Export this object to the given parent node, usually creating at least one child node.
2289 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2293 const wxString
& text
= GetText();
2294 int len
= (int) text
.Length();
2300 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2301 parent
->AddChild(elementNode
);
2303 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2304 handler
->WriteProperties(elementNode
, GetProperties());
2306 else for (i
= 0; i
< len
; i
++)
2309 int c
= (int) text
[i
];
2311 int c
= (int) wxUChar(text
[i
]);
2313 if ((c
< 32 || c
== 34) && c
!= 10 && c
!= 13)
2317 wxString
fragment(text
.Mid(last
, i
-last
));
2318 if (!fragment
.empty())
2320 // TODO: I'm assuming wxXmlDocument will output quotes if necessary
2321 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2322 parent
->AddChild(elementNode
);
2323 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2324 handler
->WriteProperties(elementNode
, GetProperties());
2326 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2327 elementNode
->AddChild(textNode
);
2329 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2330 fragment
= wxT("\"") + fragment
+ wxT("\"");
2332 textNode
->SetContent(fragment
);
2337 // Output this character as a number in a separate tag, because XML can't cope
2338 // with entities below 32 except for 10 and 13
2340 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol"));
2341 parent
->AddChild(elementNode
);
2343 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2344 handler
->WriteProperties(elementNode
, GetProperties());
2346 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2347 elementNode
->AddChild(textNode
);
2348 textNode
->SetContent(wxString::Format(wxT("%d"), c
));
2358 fragment
= text
.Mid(last
, i
-last
);
2362 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
2363 parent
->AddChild(elementNode
);
2364 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2366 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2367 elementNode
->AddChild(textNode
);
2369 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
2370 fragment
= wxT("\"") + fragment
+ wxT("\"");
2372 textNode
->SetContent(fragment
);
2379 // Import this object from XML
2380 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2382 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2384 wxBitmapType imageType
= wxBITMAP_TYPE_PNG
;
2385 wxString value
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
);
2388 int type
= wxAtoi(value
);
2390 // note: 0 == wxBITMAP_TYPE_INVALID
2391 if (type
<= 0 || type
>= wxBITMAP_TYPE_MAX
)
2393 wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
);
2397 imageType
= (wxBitmapType
)type
;
2403 wxXmlNode
* imageChild
= node
->GetChildren();
2406 wxString childName
= imageChild
->GetName();
2407 if (childName
== wxT("data"))
2409 wxXmlNode
* dataChild
= imageChild
->GetChildren();
2412 data
= dataChild
->GetContent();
2413 // wxLogDebug(data);
2414 dataChild
= dataChild
->GetNext();
2418 imageChild
= imageChild
->GetNext();
2423 wxStringInputStream
strStream(data
);
2425 GetImageBlock().ReadHex(strStream
, data
.length(), imageType
);
2433 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2434 // Export this object directly to the given stream.
2435 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2437 wxString style
= handler
->AddAttributes(GetAttributes(), false);
2439 ::OutputIndentation(stream
, indent
);
2440 ::OutputString(stream
, wxT("<image"), handler
->GetConvMem(), handler
->GetConvFile());
2441 if (!GetImageBlock().IsOk())
2444 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2448 ::OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2450 if (GetProperties().GetCount() > 0)
2452 handler
->WriteProperties(stream
, GetProperties(), indent
);
2453 ::OutputIndentation(stream
, indent
);
2456 ::OutputIndentation(stream
, indent
+1);
2457 ::OutputString(stream
, wxT("<data>"), handler
->GetConvMem(), handler
->GetConvFile());
2459 // wxStopWatch stopwatch;
2461 GetImageBlock().WriteHex(stream
);
2463 // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time());
2465 ::OutputString(stream
, wxT("</data>\n"), handler
->GetConvMem(), handler
->GetConvFile());
2466 ::OutputIndentation(stream
, indent
);
2467 ::OutputString(stream
, wxT("</image>"), handler
->GetConvMem(), handler
->GetConvFile());
2472 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2473 // Export this object to the given parent node, usually creating at least one child node.
2474 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2476 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image"));
2477 parent
->AddChild(elementNode
);
2479 if (GetImageBlock().IsOk())
2480 elementNode
->AddAttribute(wxT("imagetype"), MakeString((int) GetImageBlock().GetImageType()));
2482 handler
->AddAttributes(elementNode
, GetAttributes(), false);
2483 handler
->WriteProperties(elementNode
, GetProperties());
2485 wxXmlNode
* dataNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data"));
2486 elementNode
->AddChild(dataNode
);
2487 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
2488 dataNode
->AddChild(textNode
);
2493 wxMemoryOutputStream stream
;
2494 if (GetImageBlock().WriteHex(stream
))
2496 if (stream
.GetSize() > 0)
2498 int size
= stream
.GetSize();
2500 int size2
= stream
.GetOutputStreamBuffer()->GetIntPosition();
2501 wxASSERT(size
== size2
);
2503 unsigned char* data
= new unsigned char[size
];
2504 stream
.CopyTo(data
, size
);
2505 strData
= wxString((const char*) data
, wxConvUTF8
, size
);
2509 strData
= wxEmptyString
;
2515 wxStringOutputStream
strStream(& strData
);
2516 GetImageBlock().WriteHex(strStream
);
2520 textNode
->SetContent(strData
);
2521 textNode
->SetNoConversion(true); // optimize speed
2528 // Import this object from XML
2529 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2531 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
2535 wxString partial
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
);
2536 if (partial
== wxT("true"))
2537 SetPartialParagraph(true);
2539 wxXmlNode
* child
= wxRichTextXMLHandler::FindNode(node
, wxT("stylesheet"));
2540 if (child
&& (handler
->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
2542 wxRichTextStyleSheet
* sheet
= new wxRichTextStyleSheet
;
2543 wxString sheetName
= child
->GetAttribute(wxT("name"), wxEmptyString
);
2544 wxString sheetDescription
= child
->GetAttribute(wxT("description"), wxEmptyString
);
2545 sheet
->SetName(sheetName
);
2546 sheet
->SetDescription(sheetDescription
);
2548 wxXmlNode
* child2
= child
->GetChildren();
2551 handler
->ImportStyleDefinition(sheet
, child2
);
2553 child2
= child2
->GetNext();
2555 handler
->ImportProperties(sheet
->GetProperties(), child
);
2557 // Notify that styles have changed. If this is vetoed by the app,
2558 // the new sheet will be deleted. If it is not vetoed, the
2559 // old sheet will be deleted and replaced with the new one.
2560 buffer
->SetStyleSheetAndNotify(sheet
);
2566 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2567 // Export this object directly to the given stream.
2568 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2570 ::OutputIndentation(stream
, indent
);
2571 wxString nodeName
= GetXMLNodeName();
2572 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2574 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2576 if (GetPartialParagraph())
2577 style
<< wxT(" partialparagraph=\"true\"");
2579 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2581 if (GetProperties().GetCount() > 0)
2583 handler
->WriteProperties(stream
, GetProperties(), indent
);
2587 for (i
= 0; i
< GetChildCount(); i
++)
2589 wxRichTextObject
* child
= GetChild(i
);
2590 child
->ExportXML(stream
, indent
+1, handler
);
2593 ::OutputIndentation(stream
, indent
);
2594 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2599 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2600 // Export this object to the given parent node, usually creating at least one child node.
2601 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2603 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2604 parent
->AddChild(elementNode
);
2605 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2606 handler
->WriteProperties(elementNode
, GetProperties());
2608 if (GetPartialParagraph())
2609 elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true"));
2612 for (i
= 0; i
< GetChildCount(); i
++)
2614 wxRichTextObject
* child
= GetChild(i
);
2615 child
->ExportXML(elementNode
, handler
);
2622 // Import this object from XML
2623 bool wxRichTextTable::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
2625 wxRichTextBox::ImportFromXML(buffer
, node
, handler
, recurse
);
2629 m_rowCount
= wxAtoi(node
->GetAttribute(wxT("rows"), wxEmptyString
));
2630 m_colCount
= wxAtoi(node
->GetAttribute(wxT("cols"), wxEmptyString
));
2632 wxXmlNode
* child
= node
->GetChildren();
2635 wxRichTextObject
* childObj
= handler
->CreateObjectForXMLName(this, child
->GetName());
2638 AppendChild(childObj
);
2639 handler
->ImportXML(buffer
, childObj
, child
);
2641 child
= child
->GetNext();
2644 m_cells
.Add(wxRichTextObjectPtrArray(), m_rowCount
);
2646 for (i
= 0; i
< m_rowCount
; i
++)
2648 wxRichTextObjectPtrArray
& colArray
= m_cells
[i
];
2649 for (j
= 0; j
< m_colCount
; j
++)
2651 int idx
= i
* m_colCount
+ j
;
2652 if (idx
< (int) GetChildren().GetCount())
2654 wxRichTextCell
* cell
= wxDynamicCast(GetChildren().Item(idx
)->GetData(), wxRichTextCell
);
2664 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
2665 // Export this object directly to the given stream.
2666 bool wxRichTextTable::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
2668 ::OutputIndentation(stream
, indent
);
2669 wxString nodeName
= GetXMLNodeName();
2670 ::OutputString(stream
, wxT("<") + nodeName
, handler
->GetConvMem(), handler
->GetConvFile());
2672 wxString style
= handler
->AddAttributes(GetAttributes(), true);
2674 style
<< wxT(" rows=\"") << m_rowCount
<< wxT("\"");
2675 style
<< wxT(" cols=\"") << m_colCount
<< wxT("\"");
2677 ::OutputString(stream
, style
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2679 if (GetProperties().GetCount() > 0)
2681 handler
->WriteProperties(stream
, GetProperties(), indent
);
2685 for (i
= 0; i
< m_rowCount
; i
++)
2687 for (j
= 0; j
< m_colCount
; j
++)
2689 wxRichTextCell
* cell
= GetCell(i
, j
);
2690 cell
->ExportXML(stream
, indent
+1, handler
);
2694 ::OutputIndentation(stream
, indent
);
2695 ::OutputString(stream
, wxT("</") + nodeName
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile());
2701 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2702 // Export this object to the given parent node, usually creating at least one child node.
2703 bool wxRichTextTable::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
2705 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
2706 parent
->AddChild(elementNode
);
2707 handler
->AddAttributes(elementNode
, GetAttributes(), true);
2708 handler
->WriteProperties(elementNode
, GetProperties());
2710 elementNode
->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount
));
2711 elementNode
->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount
));
2714 for (i
= 0; i
< m_rowCount
; i
++)
2716 for (j
= 0; j
< m_colCount
; j
++)
2718 wxRichTextCell
* cell
= GetCell(i
, j
);
2719 cell
->ExportXML(elementNode
, handler
);
2729 // wxUSE_RICHTEXT && wxUSE_XML