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 // For use with earlier versions of wxWidgets
39 #ifndef WXUNUSED_IN_UNICODE
41 #define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
43 #define WXUNUSED_IN_UNICODE(x) x
47 // Set to 1 for slower wxXmlDocument method, 0 for faster direct method.
48 // If we make wxXmlDocument::Save more efficient, we might switch to this
50 #define wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT 0
52 #if wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
53 # error Must define wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT in richtextxml.h to use this method.
56 #if !wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_DIRECT_OUTPUT
57 # error Must define wxRICHTEXT_HAVE_DIRECT_OUTPUT in richtextxml.h to use this method.
60 // Set to 1 to time file saving
61 #define wxRICHTEXT_USE_OUTPUT_TIMINGS 0
63 IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler
, wxRichTextFileHandler
)
65 wxStringToStringHashMap
wxRichTextXMLHandler::sm_nodeNameToClassMap
;
67 void wxRichTextXMLHandler::Init()
72 bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer
*buffer
, wxInputStream
& stream
)
77 m_helper
.SetFlags(GetFlags());
79 buffer
->ResetAndClearCommands();
82 wxXmlDocument
* xmlDoc
= new wxXmlDocument
;
85 // This is the encoding to convert to (memory encoding rather than file encoding)
86 wxString
encoding(wxT("UTF-8"));
88 #if !wxUSE_UNICODE && wxUSE_INTL
89 encoding
= wxLocale::GetSystemEncodingName();
92 if (!xmlDoc
->Load(stream
, encoding
))
94 buffer
->ResetAndClearCommands();
99 if (xmlDoc
->GetRoot() && xmlDoc
->GetRoot()->GetType() == wxXML_ELEMENT_NODE
&& xmlDoc
->GetRoot()->GetName() == wxT("richtext"))
101 wxXmlNode
* child
= xmlDoc
->GetRoot()->GetChildren();
104 if (child
->GetType() == wxXML_ELEMENT_NODE
)
106 wxString name
= child
->GetName();
107 if (name
== wxT("richtext-version"))
111 ImportXML(buffer
, buffer
, child
);
114 child
= child
->GetNext();
125 buffer
->UpdateRanges();
130 /// Creates an object given an XML element name
131 wxRichTextObject
* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject
* WXUNUSED(parent
), const wxString
& name
) const
133 // The standard node to class mappings are added in wxRichTextModule::OnInit in richtextbuffer.cpp
134 wxStringToStringHashMap::const_iterator it
= sm_nodeNameToClassMap
.find(name
);
135 if (it
== sm_nodeNameToClassMap
.end())
138 return wxDynamicCast(wxCreateDynamicObject(it
->second
), wxRichTextObject
);
141 /// Recursively import an object
142 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer
* buffer
, wxRichTextObject
* obj
, wxXmlNode
* node
)
144 bool recurse
= false;
145 obj
->ImportFromXML(buffer
, node
, this, & recurse
);
147 // TODO: how to control whether to import children.
149 wxRichTextCompositeObject
* compositeParent
= wxDynamicCast(obj
, wxRichTextCompositeObject
);
150 if (recurse
&& compositeParent
)
152 wxXmlNode
* child
= node
->GetChildren();
155 if (child
->GetName() != wxT("stylesheet"))
157 wxRichTextObject
* childObj
= CreateObjectForXMLName(obj
, child
->GetName());
160 compositeParent
->AppendChild(childObj
);
161 ImportXML(buffer
, childObj
, child
);
164 child
= child
->GetNext();
171 bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer
*buffer
, wxOutputStream
& stream
)
176 m_helper
.SetupForSaving(m_encoding
);
177 m_helper
.SetFlags(GetFlags());
179 wxString
version(wxT("1.0") ) ;
181 wxString fileEncoding
= m_helper
.GetFileEncoding();
183 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT
184 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
185 wxStopWatch stopwatch
;
187 wxXmlDocument
* doc
= new wxXmlDocument
;
188 doc
->SetFileEncoding(fileEncoding
);
190 wxXmlNode
* rootNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("richtext"));
191 doc
->SetRoot(rootNode
);
192 rootNode
->AddAttribute(wxT("version"), wxT("1.0.0.0"));
193 rootNode
->AddAttribute(wxT("xmlns"), wxT("http://www.wxwidgets.org"));
195 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
197 wxXmlNode
* styleSheetNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("stylesheet"));
198 rootNode
->AddChild(styleSheetNode
);
200 wxString nameAndDescr
;
202 if (!buffer
->GetStyleSheet()->GetName().empty())
203 styleSheetNode
->AddAttribute(wxT("name"), buffer
->GetStyleSheet()->GetName());
205 if (!buffer
->GetStyleSheet()->GetDescription().empty())
206 styleSheetNode
->AddAttribute(wxT("description"), buffer
->GetStyleSheet()->GetDescription());
209 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
211 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
212 m_helper
.ExportStyleDefinition(styleSheetNode
, def
);
215 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
217 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
218 m_helper
.ExportStyleDefinition(styleSheetNode
, def
);
221 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
223 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
224 m_helper
.ExportStyleDefinition(styleSheetNode
, def
);
227 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
229 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
230 m_helper
.ExportStyleDefinition(styleSheetNode
, def
);
233 m_helper
.WriteProperties(styleSheetNode
, buffer
->GetStyleSheet()->GetProperties());
235 bool success
= ExportXML(rootNode
, *buffer
);
236 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
237 long t
= stopwatch
.Time();
238 wxLogDebug(wxT("Creating the document took %ldms"), t
);
239 wxMessageBox(wxString::Format(wxT("Creating the document took %ldms"), t
));
243 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
246 success
= doc
->Save(stream
);
247 #if wxRICHTEXT_USE_OUTPUT_TIMINGS
249 wxLogDebug(wxT("Save() took %ldms"), t2
);
250 wxMessageBox(wxString::Format(wxT("Save() took %ldms"), t2
));
257 // !(wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT)
260 s
.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"),
261 version
.c_str(), fileEncoding
.c_str());
262 m_helper
.OutputString(stream
, s
);
263 m_helper
.OutputString(stream
, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">"));
267 if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
269 m_helper
.OutputIndentation(stream
, level
);
270 wxString nameAndDescr
;
271 if (!buffer
->GetStyleSheet()->GetName().empty())
272 nameAndDescr
<< wxT(" name=\"") << buffer
->GetStyleSheet()->GetName() << wxT("\"");
273 if (!buffer
->GetStyleSheet()->GetDescription().empty())
274 nameAndDescr
<< wxT(" description=\"") << buffer
->GetStyleSheet()->GetDescription() << wxT("\"");
275 m_helper
.OutputString(stream
, wxString(wxT("<stylesheet")) + nameAndDescr
+ wxT(">"));
279 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++)
281 wxRichTextCharacterStyleDefinition
* def
= buffer
->GetStyleSheet()->GetCharacterStyle(i
);
282 m_helper
.ExportStyleDefinition(stream
, def
, level
+ 1);
285 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++)
287 wxRichTextParagraphStyleDefinition
* def
= buffer
->GetStyleSheet()->GetParagraphStyle(i
);
288 m_helper
.ExportStyleDefinition(stream
, def
, level
+ 1);
291 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++)
293 wxRichTextListStyleDefinition
* def
= buffer
->GetStyleSheet()->GetListStyle(i
);
294 m_helper
.ExportStyleDefinition(stream
, def
, level
+ 1);
297 for (i
= 0; i
< (int) buffer
->GetStyleSheet()->GetBoxStyleCount(); i
++)
299 wxRichTextBoxStyleDefinition
* def
= buffer
->GetStyleSheet()->GetBoxStyle(i
);
300 m_helper
.ExportStyleDefinition(stream
, def
, level
+ 1);
303 m_helper
.WriteProperties(stream
, buffer
->GetStyleSheet()->GetProperties(), level
);
305 m_helper
.OutputIndentation(stream
, level
);
306 m_helper
.OutputString(stream
, wxT("</stylesheet>"));
310 bool success
= ExportXML(stream
, *buffer
, level
);
312 m_helper
.OutputString(stream
, wxT("\n</richtext>"));
313 m_helper
.OutputString(stream
, wxT("\n"));
319 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
321 /// Recursively export an object
322 bool wxRichTextXMLHandler::ExportXML(wxOutputStream
& stream
, wxRichTextObject
& obj
, int indent
)
324 obj
.ExportXML(stream
, indent
, this);
330 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
332 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
333 bool wxRichTextXMLHandler::ExportXML(wxXmlNode
* parent
, wxRichTextObject
& obj
)
335 obj
.ExportXML(parent
, this);
341 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
346 // Import this object from XML
347 bool wxRichTextObject::ImportFromXML(wxRichTextBuffer
* WXUNUSED(buffer
), wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
349 handler
->GetHelper().ImportProperties(GetProperties(), node
);
350 handler
->GetHelper().ImportStyle(GetAttributes(), node
, UsesParagraphAttributes());
352 wxString value
= node
->GetAttribute(wxT("show"), wxEmptyString
);
353 if (!value
.IsEmpty())
354 Show(value
== wxT("1"));
361 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
362 // Export this object directly to the given stream.
363 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
365 handler
->GetHelper().OutputIndentation(stream
, indent
);
366 handler
->GetHelper().OutputString(stream
, wxT("<") + GetXMLNodeName());
368 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
370 style
<< wxT(" show=\"0\"");
372 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
374 if (GetProperties().GetCount() > 0)
376 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
379 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
383 for (i
= 0; i
< composite
->GetChildCount(); i
++)
385 wxRichTextObject
* child
= composite
->GetChild(i
);
386 child
->ExportXML(stream
, indent
+1, handler
);
390 handler
->GetHelper().OutputIndentation(stream
, indent
);
391 handler
->GetHelper().OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"));
396 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
397 // Export this object to the given parent node, usually creating at least one child node.
398 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
400 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
401 parent
->AddChild(elementNode
);
402 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
403 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
405 elementNode
->AddAttribute(wxT("show"), wxT("0"));
407 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
411 for (i
= 0; i
< composite
->GetChildCount(); i
++)
413 wxRichTextObject
* child
= composite
->GetChild(i
);
414 child
->ExportXML(elementNode
, handler
);
421 // Import this object from XML
422 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
424 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
426 if (node
->GetName() == wxT("text"))
429 wxXmlNode
* textChild
= node
->GetChildren();
432 if (textChild
->GetType() == wxXML_TEXT_NODE
||
433 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
435 wxString text2
= textChild
->GetContent();
437 // Strip whitespace from end
438 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n'))
439 text2
= text2
.Mid(0, text2
.length()-1);
441 if (!text2
.empty() && text2
[0] == wxT('"'))
442 text2
= text2
.Mid(1);
443 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"'))
444 text2
= text2
.Mid(0, text2
.length() - 1);
448 textChild
= textChild
->GetNext();
453 else if (node
->GetName() == wxT("symbol"))
455 // This is a symbol that XML can't read in the normal way
457 wxXmlNode
* textChild
= node
->GetChildren();
460 if (textChild
->GetType() == wxXML_TEXT_NODE
||
461 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
463 wxString text2
= textChild
->GetContent();
466 textChild
= textChild
->GetNext();
470 actualText
<< (wxChar
) wxAtoi(text
);
479 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
480 // Export this object directly to the given stream.
481 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
483 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), false);
487 const wxString
& text
= GetText();
488 int len
= (int) text
.Length();
493 handler
->GetHelper().OutputIndentation(stream
, indent
);
494 handler
->GetHelper().OutputString(stream
, wxT("<text"));
495 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
496 if (GetProperties().GetCount() > 0)
498 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
499 handler
->GetHelper().OutputIndentation(stream
, indent
);
501 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
503 else for (i
= 0; i
< len
; i
++)
506 int c
= (int) text
[i
];
508 int c
= (int) wxUChar(text
[i
]);
510 if ((c
< 32 || c
== 34) && /* c != 9 && */ c
!= 10 && c
!= 13)
514 wxString
fragment(text
.Mid(last
, i
-last
));
515 if (!fragment
.empty())
517 handler
->GetHelper().OutputIndentation(stream
, indent
);
518 handler
->GetHelper().OutputString(stream
, wxT("<text"));
520 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
522 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
524 handler
->GetHelper().OutputString(stream
, wxT("\""));
525 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
526 handler
->GetHelper().OutputString(stream
, wxT("\""));
529 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
531 if (GetProperties().GetCount() > 0)
533 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
534 handler
->GetHelper().OutputIndentation(stream
, indent
);
536 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
540 // Output this character as a number in a separate tag, because XML can't cope
541 // with entities below 32 except for 10 and 13
543 handler
->GetHelper().OutputIndentation(stream
, indent
);
544 handler
->GetHelper().OutputString(stream
, wxT("<symbol"));
546 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
547 handler
->GetHelper().OutputString(stream
, wxString::Format(wxT("%d"), c
));
549 if (GetProperties().GetCount() > 0)
551 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
552 handler
->GetHelper().OutputIndentation(stream
, indent
);
554 handler
->GetHelper().OutputString(stream
, wxT("</symbol>"));
562 fragment
= text
.Mid(last
, i
-last
);
566 handler
->GetHelper().OutputIndentation(stream
, indent
);
567 handler
->GetHelper().OutputString(stream
, wxT("<text"));
569 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
571 if (GetProperties().GetCount() > 0)
573 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
574 handler
->GetHelper().OutputIndentation(stream
, indent
);
577 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
579 handler
->GetHelper().OutputString(stream
, wxT("\""));
580 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
581 handler
->GetHelper().OutputString(stream
, wxT("\""));
584 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
586 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
592 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
593 // Export this object to the given parent node, usually creating at least one child node.
594 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
598 const wxString
& text
= GetText();
599 int len
= (int) text
.Length();
605 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
606 parent
->AddChild(elementNode
);
608 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
609 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
611 else for (i
= 0; i
< len
; i
++)
614 int c
= (int) text
[i
];
616 int c
= (int) wxUChar(text
[i
]);
618 if ((c
< 32 || c
== 34) && c
!= 10 && c
!= 13)
622 wxString
fragment(text
.Mid(last
, i
-last
));
623 if (!fragment
.empty())
625 // TODO: I'm assuming wxXmlDocument will output quotes if necessary
626 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
627 parent
->AddChild(elementNode
);
628 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
629 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
631 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
632 elementNode
->AddChild(textNode
);
634 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
635 fragment
= wxT("\"") + fragment
+ wxT("\"");
637 textNode
->SetContent(fragment
);
641 // Output this character as a number in a separate tag, because XML can't cope
642 // with entities below 32 except for 10 and 13
644 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol"));
645 parent
->AddChild(elementNode
);
647 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
648 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
650 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
651 elementNode
->AddChild(textNode
);
652 textNode
->SetContent(wxString::Format(wxT("%d"), c
));
662 fragment
= text
.Mid(last
, i
-last
);
666 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
667 parent
->AddChild(elementNode
);
668 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
670 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
671 elementNode
->AddChild(textNode
);
673 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
674 fragment
= wxT("\"") + fragment
+ wxT("\"");
676 textNode
->SetContent(fragment
);
682 // Import this object from XML
683 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
685 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
687 wxBitmapType imageType
= wxBITMAP_TYPE_PNG
;
688 wxString value
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
);
691 int type
= wxAtoi(value
);
693 // note: 0 == wxBITMAP_TYPE_INVALID
694 if (type
<= 0 || type
>= wxBITMAP_TYPE_MAX
)
696 wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
);
700 imageType
= (wxBitmapType
)type
;
706 wxXmlNode
* imageChild
= node
->GetChildren();
709 wxString childName
= imageChild
->GetName();
710 if (childName
== wxT("data"))
712 wxXmlNode
* dataChild
= imageChild
->GetChildren();
715 data
= dataChild
->GetContent();
717 dataChild
= dataChild
->GetNext();
721 imageChild
= imageChild
->GetNext();
726 wxStringInputStream
strStream(data
);
728 GetImageBlock().ReadHex(strStream
, data
.length(), imageType
);
736 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
737 // Export this object directly to the given stream.
738 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
740 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), false);
742 handler
->GetHelper().OutputIndentation(stream
, indent
);
743 handler
->GetHelper().OutputString(stream
, wxT("<image"));
744 if (!GetImageBlock().IsOk())
747 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
751 handler
->GetHelper().OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style
+ wxT(">"));
753 if (GetProperties().GetCount() > 0)
755 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
756 handler
->GetHelper().OutputIndentation(stream
, indent
);
759 handler
->GetHelper().OutputIndentation(stream
, indent
+1);
760 handler
->GetHelper().OutputString(stream
, wxT("<data>"));
762 // wxStopWatch stopwatch;
764 GetImageBlock().WriteHex(stream
);
766 // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time());
768 handler
->GetHelper().OutputString(stream
, wxT("</data>\n"));
769 handler
->GetHelper().OutputIndentation(stream
, indent
);
770 handler
->GetHelper().OutputString(stream
, wxT("</image>"));
775 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
776 // Export this object to the given parent node, usually creating at least one child node.
777 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
779 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image"));
780 parent
->AddChild(elementNode
);
782 if (GetImageBlock().IsOk())
783 elementNode
->AddAttribute(wxT("imagetype"), wxRichTextXMLHelper::MakeString((int) GetImageBlock().GetImageType()));
785 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
786 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
788 wxXmlNode
* dataNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data"));
789 elementNode
->AddChild(dataNode
);
790 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
791 dataNode
->AddChild(textNode
);
796 wxMemoryOutputStream stream
;
797 if (GetImageBlock().WriteHex(stream
))
799 if (stream
.GetSize() > 0)
801 int size
= stream
.GetSize();
803 int size2
= stream
.GetOutputStreamBuffer()->GetIntPosition();
804 wxASSERT(size
== size2
);
806 unsigned char* data
= new unsigned char[size
];
807 stream
.CopyTo(data
, size
);
808 strData
= wxString((const char*) data
, wxConvUTF8
, size
);
812 strData
= wxEmptyString
;
818 wxStringOutputStream
strStream(& strData
);
819 GetImageBlock().WriteHex(strStream
);
823 textNode
->SetContent(strData
);
824 #if wxCHECK_VERSION(2,9,0)
825 textNode
->SetNoConversion(true); // optimize speed
832 // Import this object from XML
833 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
835 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
839 wxString partial
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
);
840 if (partial
== wxT("true"))
841 SetPartialParagraph(true);
843 wxXmlNode
* child
= handler
->GetHelper().FindNode(node
, wxT("stylesheet"));
844 if (child
&& (handler
->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
846 wxRichTextStyleSheet
* sheet
= new wxRichTextStyleSheet
;
847 wxString sheetName
= child
->GetAttribute(wxT("name"), wxEmptyString
);
848 wxString sheetDescription
= child
->GetAttribute(wxT("description"), wxEmptyString
);
849 sheet
->SetName(sheetName
);
850 sheet
->SetDescription(sheetDescription
);
852 wxXmlNode
* child2
= child
->GetChildren();
855 handler
->GetHelper().ImportStyleDefinition(sheet
, child2
);
857 child2
= child2
->GetNext();
859 handler
->GetHelper().ImportProperties(sheet
->GetProperties(), child
);
861 // Notify that styles have changed. If this is vetoed by the app,
862 // the new sheet will be deleted. If it is not vetoed, the
863 // old sheet will be deleted and replaced with the new one.
864 buffer
->SetStyleSheetAndNotify(sheet
);
870 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
871 // Export this object directly to the given stream.
872 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
874 handler
->GetHelper().OutputIndentation(stream
, indent
);
875 wxString nodeName
= GetXMLNodeName();
876 handler
->GetHelper().OutputString(stream
, wxT("<") + nodeName
);
878 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
880 if (GetPartialParagraph())
881 style
<< wxT(" partialparagraph=\"true\"");
883 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
885 if (GetProperties().GetCount() > 0)
887 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
891 for (i
= 0; i
< GetChildCount(); i
++)
893 wxRichTextObject
* child
= GetChild(i
);
894 child
->ExportXML(stream
, indent
+1, handler
);
897 handler
->GetHelper().OutputIndentation(stream
, indent
);
898 handler
->GetHelper().OutputString(stream
, wxT("</") + nodeName
+ wxT(">"));
903 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
904 // Export this object to the given parent node, usually creating at least one child node.
905 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
907 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
908 parent
->AddChild(elementNode
);
909 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
910 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
912 if (GetPartialParagraph())
913 elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true"));
916 for (i
= 0; i
< GetChildCount(); i
++)
918 wxRichTextObject
* child
= GetChild(i
);
919 child
->ExportXML(elementNode
, handler
);
926 // Import this object from XML
927 bool wxRichTextTable::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
929 wxRichTextBox::ImportFromXML(buffer
, node
, handler
, recurse
);
933 m_rowCount
= wxAtoi(node
->GetAttribute(wxT("rows"), wxEmptyString
));
934 m_colCount
= wxAtoi(node
->GetAttribute(wxT("cols"), wxEmptyString
));
936 wxXmlNode
* child
= node
->GetChildren();
939 wxRichTextObject
* childObj
= handler
->CreateObjectForXMLName(this, child
->GetName());
942 AppendChild(childObj
);
943 handler
->ImportXML(buffer
, childObj
, child
);
945 child
= child
->GetNext();
948 m_cells
.Add(wxRichTextObjectPtrArray(), m_rowCount
);
950 for (i
= 0; i
< m_rowCount
; i
++)
952 wxRichTextObjectPtrArray
& colArray
= m_cells
[i
];
953 for (j
= 0; j
< m_colCount
; j
++)
955 int idx
= i
* m_colCount
+ j
;
956 if (idx
< (int) GetChildren().GetCount())
958 wxRichTextCell
* cell
= wxDynamicCast(GetChildren().Item(idx
)->GetData(), wxRichTextCell
);
968 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
969 // Export this object directly to the given stream.
970 bool wxRichTextTable::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
972 handler
->GetHelper().OutputIndentation(stream
, indent
);
973 wxString nodeName
= GetXMLNodeName();
974 handler
->GetHelper().OutputString(stream
, wxT("<") + nodeName
);
976 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
978 style
<< wxT(" rows=\"") << m_rowCount
<< wxT("\"");
979 style
<< wxT(" cols=\"") << m_colCount
<< wxT("\"");
981 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
983 if (GetProperties().GetCount() > 0)
985 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
989 for (i
= 0; i
< m_rowCount
; i
++)
991 for (j
= 0; j
< m_colCount
; j
++)
993 wxRichTextCell
* cell
= GetCell(i
, j
);
994 cell
->ExportXML(stream
, indent
+1, handler
);
998 handler
->GetHelper().OutputIndentation(stream
, indent
);
999 handler
->GetHelper().OutputString(stream
, wxT("</") + nodeName
+ wxT(">"));
1005 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
1006 // Export this object to the given parent node, usually creating at least one child node.
1007 bool wxRichTextTable::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
1009 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
1010 parent
->AddChild(elementNode
);
1011 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
1012 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
1014 elementNode
->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount
));
1015 elementNode
->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount
));
1018 for (i
= 0; i
< m_rowCount
; i
++)
1020 for (j
= 0; j
< m_colCount
; j
++)
1022 wxRichTextCell
* cell
= GetCell(i
, j
);
1023 cell
->ExportXML(elementNode
, handler
);
1031 wxRichTextXMLHelper::~wxRichTextXMLHelper()
1036 void wxRichTextXMLHelper::Init()
1038 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1039 m_deleteConvFile
= false;
1046 void wxRichTextXMLHelper::Clear()
1048 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1049 if (m_deleteConvFile
)
1053 m_deleteConvFile
= false;
1055 m_fileEncoding
= wxEmptyString
;
1058 void wxRichTextXMLHelper::SetupForSaving(const wxString
& enc
)
1063 m_fileEncoding
= wxT("UTF-8");
1064 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1065 m_convFile
= & wxConvUTF8
;
1068 m_fileEncoding
= wxT("ISO-8859-1");
1069 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1070 m_convFile
= & wxConvISO8859_1
;
1074 // If we pass an explicit encoding, change the output encoding.
1075 if (!enc
.empty() && enc
.Lower() != m_fileEncoding
.Lower())
1077 if (enc
== wxT("<System>"))
1080 m_fileEncoding
= wxLocale::GetSystemEncodingName();
1081 // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below
1086 m_fileEncoding
= enc
;
1089 // GetSystemEncodingName may not have returned a name
1090 if (m_fileEncoding
.empty())
1092 m_fileEncoding
= wxT("UTF-8");
1094 m_fileEncoding
= wxT("ISO-8859-1");
1096 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1097 m_convFile
= new wxCSConv(m_fileEncoding
);
1098 m_deleteConvFile
= true;
1102 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1104 m_convMem
= wxConvCurrent
;
1111 // Convert a colour to a 6-digit hex string
1112 wxString
wxRichTextXMLHelper::ColourToHexString(const wxColour
& col
)
1116 hex
+= wxDecToHex(col
.Red());
1117 hex
+= wxDecToHex(col
.Green());
1118 hex
+= wxDecToHex(col
.Blue());
1123 // Convert 6-digit hex string to a colour
1124 wxColour
wxRichTextXMLHelper::HexStringToColour(const wxString
& hex
)
1126 unsigned char r
= (unsigned char)wxHexToDec(hex
.Mid(0, 2));
1127 unsigned char g
= (unsigned char)wxHexToDec(hex
.Mid(2, 2));
1128 unsigned char b
= (unsigned char)wxHexToDec(hex
.Mid(4, 2));
1130 return wxColour(r
, g
, b
);
1133 //-----------------------------------------------------------------------------
1134 // xml support routines
1135 //-----------------------------------------------------------------------------
1137 bool wxRichTextXMLHelper::HasParam(wxXmlNode
* node
, const wxString
& param
)
1139 return (GetParamNode(node
, param
) != NULL
);
1142 wxXmlNode
*wxRichTextXMLHelper::GetParamNode(wxXmlNode
* node
, const wxString
& param
)
1144 wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!"));
1146 wxXmlNode
*n
= node
->GetChildren();
1150 if (n
->GetType() == wxXML_ELEMENT_NODE
&& n
->GetName() == param
)
1157 wxString
wxRichTextXMLHelper::GetNodeContent(wxXmlNode
*node
)
1159 wxXmlNode
*n
= node
;
1160 if (n
== NULL
) return wxEmptyString
;
1161 n
= n
->GetChildren();
1165 if (n
->GetType() == wxXML_TEXT_NODE
||
1166 n
->GetType() == wxXML_CDATA_SECTION_NODE
)
1167 return n
->GetContent();
1170 return wxEmptyString
;
1173 wxString
wxRichTextXMLHelper::GetParamValue(wxXmlNode
*node
, const wxString
& param
)
1176 return GetNodeContent(node
);
1178 return GetNodeContent(GetParamNode(node
, param
));
1181 wxString
wxRichTextXMLHelper::GetText(wxXmlNode
*node
, const wxString
& param
)
1183 wxXmlNode
*parNode
= GetParamNode(node
, param
);
1186 wxString
str1(GetNodeContent(parNode
));
1190 wxXmlNode
* wxRichTextXMLHelper::FindNode(wxXmlNode
* node
, const wxString
& name
)
1192 if (node
->GetName() == name
&& name
== wxT("stylesheet"))
1195 wxXmlNode
* child
= node
->GetChildren();
1198 if (child
->GetName() == name
)
1200 child
= child
->GetNext();
1205 wxString
wxRichTextXMLHelper::AttributeToXML(const wxString
& str
)
1208 size_t i
, last
, len
;
1213 for (i
= 0; i
< len
; i
++)
1217 // Original code excluded "&" but we _do_ want to convert
1218 // the ampersand beginning & because otherwise when read in,
1219 // the original "&" becomes "&".
1221 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
1222 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
1224 str1
+= str
.Mid(last
, i
- last
);
1228 str1
+= wxT("<");
1231 str1
+= wxT(">");
1234 str1
+= wxT("&");
1237 str1
+= wxT(""");
1243 else if (wxUChar(c
) > 127)
1245 str1
+= str
.Mid(last
, i
- last
);
1247 wxString
s(wxT("&#"));
1251 s
<< (int) wxUChar(c
);
1258 str1
+= str
.Mid(last
, i
- last
);
1262 // Make a string from the given property. This can be overridden for custom variants.
1263 wxString
wxRichTextXMLHelper::MakeStringFromProperty(const wxVariant
& var
)
1265 return var
.MakeString();
1268 // Create a proprty from the string read from the XML file.
1269 wxVariant
wxRichTextXMLHelper::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
))
1271 wxVariant
var(value
, name
);
1272 // TODO: use type to create using common types
1276 /// Replace face name with current name for platform.
1277 /// TODO: introduce a virtual function or settable table to
1278 /// do this comprehensively.
1279 bool wxRichTextXMLHelper::RichTextFixFaceName(wxString
& facename
)
1281 if (facename
.empty())
1285 if (facename
== wxT("Times"))
1287 facename
= wxT("Times New Roman");
1290 else if (facename
== wxT("Helvetica"))
1292 facename
= wxT("Arial");
1295 else if (facename
== wxT("Courier"))
1297 facename
= wxT("Courier New");
1303 if (facename
== wxT("Times New Roman"))
1305 facename
= wxT("Times");
1308 else if (facename
== wxT("Arial"))
1310 facename
= wxT("Helvetica");
1313 else if (facename
== wxT("Courier New"))
1315 facename
= wxT("Courier");
1323 long wxRichTextXMLHelper::ColourStringToLong(const wxString
& colStr
)
1325 if (!colStr
.IsEmpty())
1327 wxColour
col(colStr
);
1328 #if wxCHECK_VERSION(2,9,0)
1329 return col
.GetRGB();
1331 return (col
.Red() | (col
.Green() << 8) | (col
.Blue() << 16));
1338 wxTextAttrDimension
wxRichTextXMLHelper::ParseDimension(const wxString
& dimStr
)
1340 wxString valuePart
= dimStr
.BeforeFirst(wxT(','));
1342 if (dimStr
.Contains(wxT(",")))
1343 flagsPart
= dimStr
.AfterFirst(wxT(','));
1344 wxTextAttrDimension dim
;
1345 dim
.SetValue(wxAtoi(valuePart
));
1346 dim
.SetFlags(wxAtoi(flagsPart
));
1351 /// Import style parameters
1352 bool wxRichTextXMLHelper::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
)
1354 wxXmlAttribute
* xmlAttr
= node
->GetAttributes();
1358 const wxString
& name
= xmlAttr
->GetName();
1359 const wxString
& value
= xmlAttr
->GetValue();
1362 if (name
== wxT("fontface"))
1367 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
)
1368 RichTextFixFaceName(v
);
1369 attr
.SetFontFaceName(v
);
1372 else if (name
== wxT("fontfamily"))
1375 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
));
1377 else if (name
== wxT("fontstyle"))
1380 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
));
1382 else if (name
== wxT("fontsize") || name
== wxT("fontpointsize"))
1385 attr
.SetFontPointSize(wxAtoi(value
));
1387 else if (name
== wxT("fontpixelsize"))
1390 attr
.SetFontPixelSize(wxAtoi(value
));
1392 else if (name
== wxT("fontweight"))
1395 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
));
1397 else if (name
== wxT("fontunderlined"))
1400 attr
.SetFontUnderlined(wxAtoi(value
) != 0);
1402 else if (name
== wxT("textcolor"))
1406 if (value
[0] == wxT('#'))
1407 attr
.SetTextColour(HexStringToColour(value
.Mid(1)));
1409 attr
.SetTextColour(value
);
1412 else if (name
== wxT("bgcolor"))
1416 if (value
[0] == wxT('#'))
1417 attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1)));
1419 attr
.SetBackgroundColour(value
);
1422 else if (name
== wxT("characterstyle"))
1425 attr
.SetCharacterStyleName(value
);
1427 else if (name
== wxT("texteffects"))
1430 attr
.SetTextEffects(wxAtoi(value
));
1432 else if (name
== wxT("texteffectflags"))
1435 attr
.SetTextEffectFlags(wxAtoi(value
));
1437 else if (name
== wxT("url"))
1444 if (name
== wxT("alignment"))
1447 attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
));
1449 else if (name
== wxT("leftindent"))
1452 attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent());
1454 else if (name
== wxT("leftsubindent"))
1457 attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
));
1459 else if (name
== wxT("rightindent"))
1462 attr
.SetRightIndent(wxAtoi(value
));
1464 else if (name
== wxT("parspacingbefore"))
1467 attr
.SetParagraphSpacingBefore(wxAtoi(value
));
1469 else if (name
== wxT("parspacingafter"))
1472 attr
.SetParagraphSpacingAfter(wxAtoi(value
));
1474 else if (name
== wxT("linespacing"))
1477 attr
.SetLineSpacing(wxAtoi(value
));
1479 else if (name
== wxT("bulletstyle"))
1482 attr
.SetBulletStyle(wxAtoi(value
));
1484 else if (name
== wxT("bulletnumber"))
1487 attr
.SetBulletNumber(wxAtoi(value
));
1489 else if (name
== wxT("bulletsymbol"))
1493 wxChar ch
= wxAtoi(value
);
1496 attr
.SetBulletText(s
);
1499 else if (name
== wxT("bullettext"))
1503 attr
.SetBulletText(value
);
1506 else if (name
== wxT("bulletfont"))
1510 attr
.SetBulletFont(value
);
1513 else if (name
== wxT("bulletname"))
1517 attr
.SetBulletName(value
);
1520 else if (name
== wxT("parstyle"))
1524 attr
.SetParagraphStyleName(value
);
1527 else if (name
== wxT("liststyle"))
1531 attr
.SetListStyleName(value
);
1534 else if (name
== wxT("boxstyle"))
1538 attr
.GetTextBoxAttr().SetBoxStyleName(value
);
1541 else if (name
== wxT("tabs"))
1546 wxStringTokenizer
tkz(value
, wxT(","));
1547 while (tkz
.HasMoreTokens())
1549 wxString token
= tkz
.GetNextToken();
1550 tabs
.Add(wxAtoi(token
));
1555 else if (name
== wxT("pagebreak"))
1559 attr
.SetPageBreak(wxAtoi(value
) != 0);
1562 else if (name
== wxT("outlinelevel"))
1566 attr
.SetOutlineLevel(wxAtoi(value
));
1579 if (name
== wxT("width"))
1581 attr
.GetTextBoxAttr().GetWidth().SetValue(ParseDimension(value
));
1583 else if (name
== wxT("height"))
1585 attr
.GetTextBoxAttr().GetHeight().SetValue(ParseDimension(value
));
1587 else if (name
== wxT("minwidth"))
1589 attr
.GetTextBoxAttr().GetMinSize().GetWidth().SetValue(ParseDimension(value
));
1591 else if (name
== wxT("minheight"))
1593 attr
.GetTextBoxAttr().GetMinSize().GetHeight().SetValue(ParseDimension(value
));
1595 else if (name
== wxT("maxwidth"))
1597 attr
.GetTextBoxAttr().GetMaxSize().GetWidth().SetValue(ParseDimension(value
));
1599 else if (name
== wxT("maxheight"))
1601 attr
.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(ParseDimension(value
));
1604 else if (name
== wxT("verticalalignment"))
1606 if (value
== wxT("top"))
1607 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
);
1608 else if (value
== wxT("centre"))
1609 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
);
1610 else if (value
== wxT("bottom"))
1611 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
);
1612 else if (value
== wxT("none"))
1613 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
);
1615 else if (name
== wxT("float"))
1617 if (value
== wxT("left"))
1618 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
);
1619 else if (value
== wxT("right"))
1620 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
);
1621 else if (value
== wxT("none"))
1622 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
);
1624 else if (name
== wxT("clear"))
1626 if (value
== wxT("left"))
1627 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
);
1628 else if (value
== wxT("right"))
1629 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
);
1630 else if (value
== wxT("both"))
1631 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
);
1632 else if (value
== wxT("none"))
1633 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
);
1635 else if (name
== wxT("collapse-borders"))
1636 attr
.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode
) wxAtoi(value
));
1638 else if (name
.Contains(wxT("border-")))
1640 if (name
== wxT("border-left-style"))
1641 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
));
1642 else if (name
== wxT("border-right-style"))
1643 attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
));
1644 else if (name
== wxT("border-top-style"))
1645 attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
));
1646 else if (name
== wxT("border-bottom-style"))
1647 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
));
1649 else if (name
== wxT("border-left-colour"))
1650 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(ColourStringToLong(value
));
1651 else if (name
== wxT("border-right-colour"))
1652 attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(ColourStringToLong(value
));
1653 else if (name
== wxT("border-top-colour"))
1654 attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(ColourStringToLong(value
));
1655 else if (name
== wxT("border-bottom-colour"))
1656 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(ColourStringToLong(value
));
1658 else if (name
== wxT("border-left-width"))
1659 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(ParseDimension(value
));
1660 else if (name
== wxT("border-right-width"))
1661 attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(ParseDimension(value
));
1662 else if (name
== wxT("border-top-width"))
1663 attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(ParseDimension(value
));
1664 else if (name
== wxT("border-bottom-width"))
1665 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(ParseDimension(value
));
1667 else if (name
.Contains(wxT("outline-")))
1669 if (name
== wxT("outline-left-style"))
1670 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
));
1671 else if (name
== wxT("outline-right-style"))
1672 attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
));
1673 else if (name
== wxT("outline-top-style"))
1674 attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
));
1675 else if (name
== wxT("outline-bottom-style"))
1676 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
));
1678 else if (name
== wxT("outline-left-colour"))
1679 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(ColourStringToLong(value
));
1680 else if (name
== wxT("outline-right-colour"))
1681 attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(ColourStringToLong(value
));
1682 else if (name
== wxT("outline-top-colour"))
1683 attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(ColourStringToLong(value
));
1684 else if (name
== wxT("outline-bottom-colour"))
1685 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(ColourStringToLong(value
));
1687 else if (name
== wxT("outline-left-width"))
1688 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(ParseDimension(value
));
1689 else if (name
== wxT("outline-right-width"))
1690 attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(ParseDimension(value
));
1691 else if (name
== wxT("outline-top-width"))
1692 attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(ParseDimension(value
));
1693 else if (name
== wxT("outline-bottom-width"))
1694 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(ParseDimension(value
));
1696 else if (name
.Contains(wxT("margin-")))
1698 if (name
== wxT("margin-left"))
1699 attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(ParseDimension(value
));
1700 else if (name
== wxT("margin-right"))
1701 attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(ParseDimension(value
));
1702 else if (name
== wxT("margin-top"))
1703 attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(ParseDimension(value
));
1704 else if (name
== wxT("margin-bottom"))
1705 attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(ParseDimension(value
));
1707 else if (name
.Contains(wxT("padding-")))
1709 if (name
== wxT("padding-left"))
1710 attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(ParseDimension(value
));
1711 else if (name
== wxT("padding-right"))
1712 attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(ParseDimension(value
));
1713 else if (name
== wxT("padding-top"))
1714 attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(ParseDimension(value
));
1715 else if (name
== wxT("padding-bottom"))
1716 attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(ParseDimension(value
));
1718 else if (name
.Contains(wxT("position-")))
1720 if (name
== wxT("position-left"))
1721 attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(ParseDimension(value
));
1722 else if (name
== wxT("position-right"))
1723 attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(ParseDimension(value
));
1724 else if (name
== wxT("position-top"))
1725 attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(ParseDimension(value
));
1726 else if (name
== wxT("position-bottom"))
1727 attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(ParseDimension(value
));
1731 xmlAttr
= xmlAttr
->GetNext();
1737 bool wxRichTextXMLHelper::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
)
1739 wxString styleType
= node
->GetName();
1740 wxString styleName
= node
->GetAttribute(wxT("name"), wxEmptyString
);
1741 wxString baseStyleName
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
);
1743 if (styleName
.empty())
1746 if (styleType
== wxT("characterstyle"))
1748 wxRichTextCharacterStyleDefinition
* def
= new wxRichTextCharacterStyleDefinition(styleName
);
1749 def
->SetBaseStyle(baseStyleName
);
1751 wxXmlNode
* child
= node
->GetChildren();
1754 if (child
->GetName() == wxT("style"))
1756 wxRichTextAttr attr
;
1757 ImportStyle(attr
, child
, false);
1758 def
->SetStyle(attr
);
1760 child
= child
->GetNext();
1763 ImportProperties(def
->GetProperties(), node
);
1765 sheet
->AddCharacterStyle(def
);
1767 else if (styleType
== wxT("paragraphstyle"))
1769 wxRichTextParagraphStyleDefinition
* def
= new wxRichTextParagraphStyleDefinition(styleName
);
1771 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
1772 def
->SetNextStyle(nextStyleName
);
1773 def
->SetBaseStyle(baseStyleName
);
1775 wxXmlNode
* child
= node
->GetChildren();
1778 if (child
->GetName() == wxT("style"))
1780 wxRichTextAttr attr
;
1781 ImportStyle(attr
, child
, true);
1782 def
->SetStyle(attr
);
1784 child
= child
->GetNext();
1787 ImportProperties(def
->GetProperties(), node
);
1789 sheet
->AddParagraphStyle(def
);
1791 else if (styleType
== wxT("boxstyle"))
1793 wxRichTextBoxStyleDefinition
* def
= new wxRichTextBoxStyleDefinition(styleName
);
1795 def
->SetBaseStyle(baseStyleName
);
1797 wxXmlNode
* child
= node
->GetChildren();
1800 if (child
->GetName() == wxT("style"))
1802 wxRichTextAttr attr
;
1803 ImportStyle(attr
, child
, true);
1804 def
->SetStyle(attr
);
1806 child
= child
->GetNext();
1809 ImportProperties(def
->GetProperties(), node
);
1811 sheet
->AddBoxStyle(def
);
1813 else if (styleType
== wxT("liststyle"))
1815 wxRichTextListStyleDefinition
* def
= new wxRichTextListStyleDefinition(styleName
);
1817 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
1818 def
->SetNextStyle(nextStyleName
);
1819 def
->SetBaseStyle(baseStyleName
);
1821 wxXmlNode
* child
= node
->GetChildren();
1824 if (child
->GetName() == wxT("style"))
1826 wxRichTextAttr attr
;
1827 ImportStyle(attr
, child
, true);
1829 wxString styleLevel
= child
->GetAttribute(wxT("level"), wxEmptyString
);
1830 if (styleLevel
.empty())
1832 def
->SetStyle(attr
);
1836 int level
= wxAtoi(styleLevel
);
1837 if (level
> 0 && level
<= 10)
1839 def
->SetLevelAttributes(level
-1, attr
);
1843 child
= child
->GetNext();
1846 ImportProperties(def
->GetProperties(), node
);
1848 sheet
->AddListStyle(def
);
1854 bool wxRichTextXMLHelper::ImportProperties(wxRichTextProperties
& properties
, wxXmlNode
* node
)
1856 wxXmlNode
* child
= node
->GetChildren();
1859 if (child
->GetName() == wxT("properties"))
1861 wxXmlNode
* propertyChild
= child
->GetChildren();
1862 while (propertyChild
)
1864 if (propertyChild
->GetName() == wxT("property"))
1866 wxString name
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
);
1867 wxString value
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
);
1868 wxString type
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
);
1870 wxVariant var
= MakePropertyFromString(name
, value
, type
);
1873 properties
.SetProperty(var
);
1876 propertyChild
= propertyChild
->GetNext();
1879 child
= child
->GetNext();
1884 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1885 // write string to output
1886 void wxRichTextXMLHelper::OutputString(wxOutputStream
& stream
, const wxString
& str
,
1887 wxMBConv
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv
*convFile
)
1889 if (str
.empty()) return;
1893 const wxWX2MBbuf
buf(str
.mb_str(*convFile
));
1894 stream
.Write((const char*)buf
, strlen((const char*)buf
));
1898 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
1899 stream
.Write((const char*)buf
, strlen((const char*)buf
));
1902 if ( convFile
== NULL
)
1903 stream
.Write(str
.mb_str(), str
.Len());
1906 wxString
str2(str
.wc_str(*convMem
), *convFile
);
1907 stream
.Write(str2
.mb_str(), str2
.Len());
1912 void wxRichTextXMLHelper::OutputIndentation(wxOutputStream
& stream
, int indent
)
1914 wxString str
= wxT("\n");
1915 for (int i
= 0; i
< indent
; i
++)
1916 str
<< wxT(' ') << wxT(' ');
1917 OutputString(stream
, str
, NULL
, NULL
);
1920 // Same as above, but create entities first.
1921 // Translates '<' to "<", '>' to ">" and '&' to "&"
1922 void wxRichTextXMLHelper::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
,
1923 wxMBConv
*convMem
, wxMBConv
*convFile
)
1926 size_t i
, last
, len
;
1931 for (i
= 0; i
< len
; i
++)
1935 // Original code excluded "&" but we _do_ want to convert
1936 // the ampersand beginning & because otherwise when read in,
1937 // the original "&" becomes "&".
1939 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
1940 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
1942 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1946 OutputString(stream
, wxT("<"), NULL
, NULL
);
1949 OutputString(stream
, wxT(">"), NULL
, NULL
);
1952 OutputString(stream
, wxT("&"), NULL
, NULL
);
1955 OutputString(stream
, wxT("""), NULL
, NULL
);
1961 else if (wxUChar(c
) > 127)
1963 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1965 wxString
s(wxT("&#"));
1969 s
<< (int) wxUChar(c
);
1972 OutputString(stream
, s
, NULL
, NULL
);
1976 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1979 void wxRichTextXMLHelper::OutputString(wxOutputStream
& stream
, const wxString
& str
)
1981 OutputString(stream
, str
, m_convMem
, m_convFile
);
1984 void wxRichTextXMLHelper::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
)
1986 OutputStringEnt(stream
, str
, m_convMem
, m_convFile
);
1989 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const int& v
)
1991 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\"");
1994 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const long& v
)
1996 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\"");
1999 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const double& v
)
2001 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\"");
2004 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxChar
* s
)
2006 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
2009 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxString
& s
)
2011 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
2014 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxColour
& col
)
2016 str
<< wxT(" ") << name
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\"");
2019 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxTextAttrDimension
& dim
)
2023 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags());
2024 str
<< wxT(" ") << name
<< wxT("=\"");
2030 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
2032 if (dims
.GetLeft().IsValid())
2033 AddAttribute(str
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
2034 if (dims
.GetRight().IsValid())
2035 AddAttribute(str
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
2036 if (dims
.GetTop().IsValid())
2037 AddAttribute(str
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
2038 if (dims
.GetBottom().IsValid())
2039 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
2042 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
2044 if (border
.HasStyle())
2045 AddAttribute(str
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
2046 if (border
.HasColour())
2047 AddAttribute(str
, rootName
+ wxString(wxT("-color")), border
.GetColour());
2048 if (border
.HasWidth())
2049 AddAttribute(str
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
2052 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
2054 AddAttribute(str
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
2055 AddAttribute(str
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
2056 AddAttribute(str
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
2057 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
2060 /// Create a string containing style attributes
2061 wxString
wxRichTextXMLHelper::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
)
2064 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
2065 AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour());
2067 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
2068 AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour());
2070 if (attr
.HasFontPointSize())
2071 AddAttribute(str
, wxT("fontpointsize"), attr
.GetFontSize());
2072 else if (attr
.HasFontPixelSize())
2073 AddAttribute(str
, wxT("fontpixelsize"), attr
.GetFontSize());
2075 if (attr
.HasFontFamily())
2076 AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily());
2078 if (attr
.HasFontItalic())
2079 AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle());
2081 if (attr
.HasFontWeight())
2082 AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight());
2084 if (attr
.HasFontUnderlined())
2085 AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined());
2087 if (attr
.HasFontFaceName())
2088 AddAttribute(str
, wxT("fontface"), AttributeToXML(attr
.GetFontFaceName()));
2090 if (attr
.HasTextEffects())
2092 AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects());
2093 AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags());
2096 if (!attr
.GetCharacterStyleName().empty())
2097 AddAttribute(str
, wxT("characterstyle"), AttributeToXML(attr
.GetCharacterStyleName()));
2100 AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL()));
2104 if (attr
.HasAlignment())
2105 AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment());
2107 if (attr
.HasLeftIndent())
2109 AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent());
2110 AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent());
2113 if (attr
.HasRightIndent())
2114 AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent());
2116 if (attr
.HasParagraphSpacingAfter())
2117 AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter());
2119 if (attr
.HasParagraphSpacingBefore())
2120 AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore());
2122 if (attr
.HasLineSpacing())
2123 AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing());
2125 if (attr
.HasBulletStyle())
2126 AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle());
2128 if (attr
.HasBulletNumber())
2129 AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber());
2131 if (attr
.HasBulletText())
2133 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
2134 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
2135 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
2136 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0]));
2138 AddAttribute(str
, wxT("bullettext"), AttributeToXML(attr
.GetBulletText()));
2140 AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont());
2143 if (attr
.HasBulletName())
2144 AddAttribute(str
, wxT("bulletname"), AttributeToXML(attr
.GetBulletName()));
2146 if (!attr
.GetParagraphStyleName().empty())
2147 AddAttribute(str
, wxT("parstyle"), AttributeToXML(attr
.GetParagraphStyleName()));
2149 if (!attr
.GetListStyleName().empty())
2150 AddAttribute(str
, wxT("liststyle"), AttributeToXML(attr
.GetListStyleName()));
2152 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
2153 AddAttribute(str
, wxT("boxstyle"), AttributeToXML(attr
.GetTextBoxAttr().GetBoxStyleName()));
2159 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
2161 if (i
> 0) strTabs
<< wxT(",");
2162 strTabs
<< attr
.GetTabs()[i
];
2164 AddAttribute(str
, wxT("tabs"), strTabs
);
2167 if (attr
.HasPageBreak())
2169 AddAttribute(str
, wxT("pagebreak"), 1);
2172 if (attr
.HasOutlineLevel())
2173 AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel());
2176 AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
2177 AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
2178 AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
2179 AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
2180 AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
2181 AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
2182 AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
2183 AddAttribute(str
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
2184 AddAttribute(str
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
2185 AddAttribute(str
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
2186 AddAttribute(str
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
2188 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
2191 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
2193 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
2194 value
= wxT("centre");
2195 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
2196 value
= wxT("bottom");
2198 value
= wxT("none");
2199 AddAttribute(str
, wxT("verticalalignment"), value
);
2202 if (attr
.GetTextBoxAttr().HasFloatMode())
2205 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
2206 value
= wxT("left");
2207 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
2208 value
= wxT("right");
2210 value
= wxT("none");
2211 AddAttribute(str
, wxT("float"), value
);
2214 if (attr
.GetTextBoxAttr().HasClearMode())
2217 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
2218 value
= wxT("left");
2219 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
2220 value
= wxT("right");
2221 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
2222 value
= wxT("both");
2224 value
= wxT("none");
2225 AddAttribute(str
, wxT("clear"), value
);
2228 if (attr
.GetTextBoxAttr().HasCollapseBorders())
2229 AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
2234 // Write the properties
2235 bool wxRichTextXMLHelper::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
)
2237 if (properties
.GetCount() > 0)
2241 OutputIndentation(stream
, level
);
2242 OutputString(stream
, wxT("<properties>"));
2247 for (i
= 0; i
< properties
.GetCount(); i
++)
2249 const wxVariant
& var
= properties
[i
];
2252 const wxString
& name
= var
.GetName();
2253 wxString value
= MakeStringFromProperty(var
);
2255 OutputIndentation(stream
, level
);
2256 OutputString(stream
, wxT("<property name=\"") + name
+
2257 wxT("\" type=\"") + var
.GetType() + wxT("\" value=\""));
2258 OutputStringEnt(stream
, value
);
2259 OutputString(stream
, wxT("\"/>"));
2265 OutputIndentation(stream
, level
);
2266 OutputString(stream
, wxT("</properties>"));
2274 bool wxRichTextXMLHelper::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
)
2276 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
2277 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
2278 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
2279 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
2281 wxString name
= def
->GetName();
2284 nameProp
= wxT(" name=\"") + AttributeToXML(name
) + wxT("\"");
2286 wxString baseStyle
= def
->GetBaseStyle();
2287 wxString baseStyleProp
;
2288 if (!baseStyle
.empty())
2289 baseStyleProp
= wxT(" basestyle=\"") + AttributeToXML(baseStyle
) + wxT("\"");
2291 wxString descr
= def
->GetDescription();
2294 descrProp
= wxT(" description=\"") + AttributeToXML(descr
) + wxT("\"");
2298 OutputIndentation(stream
, level
);
2299 OutputString(stream
, wxT("<characterstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2303 wxString style
= AddAttributes(def
->GetStyle(), false);
2305 OutputIndentation(stream
, level
);
2306 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2308 OutputIndentation(stream
, level
);
2309 OutputString(stream
, wxT("</style>"));
2313 OutputIndentation(stream
, level
);
2314 OutputString(stream
, wxT("</characterstyle>"));
2318 OutputIndentation(stream
, level
);
2320 if (!listDef
->GetNextStyle().empty())
2321 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(listDef
->GetNextStyle()) << wxT("\"");
2323 OutputString(stream
, wxT("<liststyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2327 wxString style
= AddAttributes(def
->GetStyle(), true);
2329 OutputIndentation(stream
, level
);
2330 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2332 OutputIndentation(stream
, level
);
2333 OutputString(stream
, wxT("</style>"));
2336 for (i
= 0; i
< 10; i
++)
2338 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
2341 wxString style
= AddAttributes(def
->GetStyle(), true);
2342 wxString levelStr
= wxString::Format(wxT(" level=\"%d\" "), (i
+1));
2344 OutputIndentation(stream
, level
);
2345 OutputString(stream
, wxT("<style ") + levelStr
+ style
+ wxT(">"));
2347 OutputIndentation(stream
, level
);
2348 OutputString(stream
, wxT("</style>"));
2354 OutputIndentation(stream
, level
);
2355 OutputString(stream
, wxT("</liststyle>"));
2359 OutputIndentation(stream
, level
);
2361 if (!paraDef
->GetNextStyle().empty())
2362 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(paraDef
->GetNextStyle()) << wxT("\"");
2364 OutputString(stream
, wxT("<paragraphstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2368 wxString style
= AddAttributes(def
->GetStyle(), true);
2370 OutputIndentation(stream
, level
);
2371 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2373 OutputIndentation(stream
, level
);
2374 OutputString(stream
, wxT("</style>"));
2378 OutputIndentation(stream
, level
);
2379 OutputString(stream
, wxT("</paragraphstyle>"));
2383 OutputIndentation(stream
, level
);
2385 OutputString(stream
, wxT("<boxstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2389 wxString style
= AddAttributes(def
->GetStyle(), true);
2391 OutputIndentation(stream
, level
);
2392 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2394 OutputIndentation(stream
, level
);
2395 OutputString(stream
, wxT("</style>"));
2399 OutputIndentation(stream
, level
);
2400 OutputString(stream
, wxT("</boxstyle>"));
2403 WriteProperties(stream
, def
->GetProperties(), level
);
2409 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
2412 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2414 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const int& v
)
2416 node
->AddAttribute(name
, MakeString(v
));
2419 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const long& v
)
2421 node
->AddAttribute(name
, MakeString(v
));
2424 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const double& v
)
2426 node
->AddAttribute(name
, MakeString(v
));
2429 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxString
& s
)
2431 node
->AddAttribute(name
, s
);
2434 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxColour
& col
)
2436 node
->AddAttribute(name
, MakeString(col
));
2439 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxTextAttrDimension
& dim
)
2443 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags());
2444 AddAttribute(node
, name
, value
);
2448 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
2450 if (dims
.GetLeft().IsValid())
2451 AddAttribute(node
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
2452 if (dims
.GetRight().IsValid())
2453 AddAttribute(node
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
2454 if (dims
.GetTop().IsValid())
2455 AddAttribute(node
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
2456 if (dims
.GetBottom().IsValid())
2457 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
2460 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
2462 if (border
.HasStyle())
2463 AddAttribute(node
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
2464 if (border
.HasColour())
2465 AddAttribute(node
, rootName
+ wxString(wxT("-color")), border
.GetColour());
2466 if (border
.HasWidth())
2467 AddAttribute(node
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
2470 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
2472 AddAttribute(node
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
2473 AddAttribute(node
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
2474 AddAttribute(node
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
2475 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
2478 bool wxRichTextXMLHelper::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
)
2480 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
2481 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
2482 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
2483 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
2485 wxString baseStyle
= def
->GetBaseStyle();
2486 wxString descr
= def
->GetDescription();
2488 wxXmlNode
* defNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
);
2489 parent
->AddChild(defNode
);
2490 if (!baseStyle
.empty())
2491 defNode
->AddAttribute(wxT("basestyle"), baseStyle
);
2493 defNode
->AddAttribute(wxT("description"), descr
);
2495 wxXmlNode
* styleNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
2496 defNode
->AddChild(styleNode
);
2500 defNode
->SetName(wxT("characterstyle"));
2501 AddAttributes(styleNode
, def
->GetStyle(), false);
2505 defNode
->SetName(wxT("liststyle"));
2507 if (!listDef
->GetNextStyle().empty())
2508 defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle());
2510 AddAttributes(styleNode
, def
->GetStyle(), true);
2513 for (i
= 0; i
< 10; i
++)
2515 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
2518 wxXmlNode
* levelNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
2519 defNode
->AddChild(levelNode
);
2520 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1));
2521 AddAttributes(levelNode
, * levelAttr
, true);
2527 defNode
->SetName(wxT("boxstyle"));
2529 AddAttributes(styleNode
, def
->GetStyle(), true);
2533 defNode
->SetName(wxT("paragraphstyle"));
2535 if (!paraDef
->GetNextStyle().empty())
2536 defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle());
2538 AddAttributes(styleNode
, def
->GetStyle(), true);
2541 WriteProperties(defNode
, def
->GetProperties());
2546 bool wxRichTextXMLHelper::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
)
2548 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
2549 node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour()));
2550 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
2551 node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour()));
2553 if (attr
.HasFontPointSize())
2554 node
->AddAttribute(wxT("fontpointsize"), MakeString(attr
.GetFontSize()));
2555 else if (attr
.HasFontPixelSize())
2556 node
->AddAttribute(wxT("fontpixelsize"), MakeString(attr
.GetFontSize()));
2557 if (attr
.HasFontFamily())
2558 node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily()));
2559 if (attr
.HasFontItalic())
2560 node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle()));
2561 if (attr
.HasFontWeight())
2562 node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight()));
2563 if (attr
.HasFontUnderlined())
2564 node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined()));
2565 if (attr
.HasFontFaceName())
2566 node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName());
2568 if (attr
.HasTextEffects())
2570 node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects()));
2571 node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags()));
2573 if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty())
2574 node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName());
2577 node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML?
2581 if (attr
.HasAlignment())
2582 node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment()));
2584 if (attr
.HasLeftIndent())
2586 node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent()));
2587 node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent()));
2590 if (attr
.HasRightIndent())
2591 node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent()));
2593 if (attr
.HasParagraphSpacingAfter())
2594 node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter()));
2596 if (attr
.HasParagraphSpacingBefore())
2597 node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore()));
2599 if (attr
.HasLineSpacing())
2600 node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing()));
2602 if (attr
.HasBulletStyle())
2603 node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle()));
2605 if (attr
.HasBulletNumber())
2606 node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber()));
2608 if (attr
.HasBulletText())
2610 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
2611 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
2612 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
2613 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0])));
2615 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText());
2617 if (!attr
.GetBulletFont().empty())
2618 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont());
2621 if (attr
.HasBulletName())
2622 node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName());
2624 if (!attr
.GetParagraphStyleName().empty())
2625 node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName());
2627 if (!attr
.GetListStyleName().empty())
2628 node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName());
2630 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
2631 node
->AddAttribute(wxT("boxstyle"), attr
.GetTextBoxAttr().GetBoxStyleName());
2637 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
2641 tabs
<< attr
.GetTabs()[i
];
2643 node
->AddAttribute(wxT("tabs"), tabs
);
2646 if (attr
.HasPageBreak())
2647 node
->AddAttribute(wxT("pagebreak"), wxT("1"));
2649 if (attr
.HasOutlineLevel())
2650 node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel()));
2653 AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
2654 AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
2655 AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
2656 AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
2657 AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
2658 AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
2659 AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
2660 AddAttribute(node
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
2661 AddAttribute(node
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
2662 AddAttribute(node
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
2663 AddAttribute(node
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
2665 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
2668 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
2670 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
2671 value
= wxT("centre");
2672 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
2673 value
= wxT("bottom");
2675 value
= wxT("none");
2676 AddAttribute(node
, wxT("verticalalignment"), value
);
2679 if (attr
.GetTextBoxAttr().HasFloatMode())
2682 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
2683 value
= wxT("left");
2684 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
2685 value
= wxT("right");
2687 value
= wxT("none");
2688 AddAttribute(node
, wxT("float"), value
);
2691 if (attr
.GetTextBoxAttr().HasClearMode())
2694 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
2695 value
= wxT("left");
2696 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
2697 value
= wxT("right");
2698 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
2699 value
= wxT("both");
2701 value
= wxT("none");
2702 AddAttribute(node
, wxT("clear"), value
);
2705 if (attr
.GetTextBoxAttr().HasCollapseBorders())
2706 AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
2711 bool wxRichTextXMLHelper::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
)
2713 if (properties
.GetCount() > 0)
2715 wxXmlNode
* propertiesNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties"));
2716 node
->AddChild(propertiesNode
);
2718 for (i
= 0; i
< properties
.GetCount(); i
++)
2720 const wxVariant
& var
= properties
[i
];
2723 wxXmlNode
* propertyNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property"));
2724 propertiesNode
->AddChild(propertyNode
);
2726 const wxString
& name
= var
.GetName();
2727 wxString value
= MakeStringFromProperty(var
);
2729 AddAttribute(propertyNode
, wxT("name"), name
);
2730 AddAttribute(propertyNode
, wxT("type"), var
.GetType());
2731 AddAttribute(propertyNode
, wxT("value"), value
);
2739 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2742 // wxUSE_RICHTEXT && wxUSE_XML