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());
357 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
358 // Export this object directly to the given stream.
359 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
361 handler
->GetHelper().OutputIndentation(stream
, indent
);
362 handler
->GetHelper().OutputString(stream
, wxT("<") + GetXMLNodeName());
364 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
366 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
368 if (GetProperties().GetCount() > 0)
370 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
373 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
377 for (i
= 0; i
< composite
->GetChildCount(); i
++)
379 wxRichTextObject
* child
= composite
->GetChild(i
);
380 child
->ExportXML(stream
, indent
+1, handler
);
384 handler
->GetHelper().OutputIndentation(stream
, indent
);
385 handler
->GetHelper().OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"));
390 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
391 // Export this object to the given parent node, usually creating at least one child node.
392 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
394 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
395 parent
->AddChild(elementNode
);
396 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
397 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
399 wxRichTextCompositeObject
* composite
= wxDynamicCast(this, wxRichTextCompositeObject
);
403 for (i
= 0; i
< composite
->GetChildCount(); i
++)
405 wxRichTextObject
* child
= composite
->GetChild(i
);
406 child
->ExportXML(elementNode
, handler
);
413 // Import this object from XML
414 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
416 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
418 if (node
->GetName() == wxT("text"))
421 wxXmlNode
* textChild
= node
->GetChildren();
424 if (textChild
->GetType() == wxXML_TEXT_NODE
||
425 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
427 wxString text2
= textChild
->GetContent();
429 // Strip whitespace from end
430 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n'))
431 text2
= text2
.Mid(0, text2
.length()-1);
433 if (!text2
.empty() && text2
[0] == wxT('"'))
434 text2
= text2
.Mid(1);
435 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"'))
436 text2
= text2
.Mid(0, text2
.length() - 1);
440 textChild
= textChild
->GetNext();
445 else if (node
->GetName() == wxT("symbol"))
447 // This is a symbol that XML can't read in the normal way
449 wxXmlNode
* textChild
= node
->GetChildren();
452 if (textChild
->GetType() == wxXML_TEXT_NODE
||
453 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
)
455 wxString text2
= textChild
->GetContent();
458 textChild
= textChild
->GetNext();
462 actualText
<< (wxChar
) wxAtoi(text
);
471 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
472 // Export this object directly to the given stream.
473 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
475 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), false);
479 const wxString
& text
= GetText();
480 int len
= (int) text
.Length();
485 handler
->GetHelper().OutputIndentation(stream
, indent
);
486 handler
->GetHelper().OutputString(stream
, wxT("<text"));
487 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
488 if (GetProperties().GetCount() > 0)
490 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
491 handler
->GetHelper().OutputIndentation(stream
, indent
);
493 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
495 else for (i
= 0; i
< len
; i
++)
498 int c
= (int) text
[i
];
500 int c
= (int) wxUChar(text
[i
]);
502 if ((c
< 32 || c
== 34) && /* c != 9 && */ c
!= 10 && c
!= 13)
506 wxString
fragment(text
.Mid(last
, i
-last
));
507 if (!fragment
.empty())
509 handler
->GetHelper().OutputIndentation(stream
, indent
);
510 handler
->GetHelper().OutputString(stream
, wxT("<text"));
512 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
514 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
516 handler
->GetHelper().OutputString(stream
, wxT("\""));
517 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
518 handler
->GetHelper().OutputString(stream
, wxT("\""));
521 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
523 if (GetProperties().GetCount() > 0)
525 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
526 handler
->GetHelper().OutputIndentation(stream
, indent
);
528 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
532 // Output this character as a number in a separate tag, because XML can't cope
533 // with entities below 32 except for 10 and 13
535 handler
->GetHelper().OutputIndentation(stream
, indent
);
536 handler
->GetHelper().OutputString(stream
, wxT("<symbol"));
538 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
539 handler
->GetHelper().OutputString(stream
, wxString::Format(wxT("%d"), c
));
541 if (GetProperties().GetCount() > 0)
543 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
544 handler
->GetHelper().OutputIndentation(stream
, indent
);
546 handler
->GetHelper().OutputString(stream
, wxT("</symbol>"));
554 fragment
= text
.Mid(last
, i
-last
);
558 handler
->GetHelper().OutputIndentation(stream
, indent
);
559 handler
->GetHelper().OutputString(stream
, wxT("<text"));
561 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
563 if (GetProperties().GetCount() > 0)
565 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
566 handler
->GetHelper().OutputIndentation(stream
, indent
);
569 if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')))
571 handler
->GetHelper().OutputString(stream
, wxT("\""));
572 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
573 handler
->GetHelper().OutputString(stream
, wxT("\""));
576 handler
->GetHelper().OutputStringEnt(stream
, fragment
);
578 handler
->GetHelper().OutputString(stream
, wxT("</text>"));
584 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
585 // Export this object to the given parent node, usually creating at least one child node.
586 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
590 const wxString
& text
= GetText();
591 int len
= (int) text
.Length();
597 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
598 parent
->AddChild(elementNode
);
600 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
601 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
603 else for (i
= 0; i
< len
; i
++)
606 int c
= (int) text
[i
];
608 int c
= (int) wxUChar(text
[i
]);
610 if ((c
< 32 || c
== 34) && c
!= 10 && c
!= 13)
614 wxString
fragment(text
.Mid(last
, i
-last
));
615 if (!fragment
.empty())
617 // TODO: I'm assuming wxXmlDocument will output quotes if necessary
618 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
619 parent
->AddChild(elementNode
);
620 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
621 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
623 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
624 elementNode
->AddChild(textNode
);
626 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
627 fragment
= wxT("\"") + fragment
+ wxT("\"");
629 textNode
->SetContent(fragment
);
633 // Output this character as a number in a separate tag, because XML can't cope
634 // with entities below 32 except for 10 and 13
636 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol"));
637 parent
->AddChild(elementNode
);
639 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
640 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
642 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
643 elementNode
->AddChild(textNode
);
644 textNode
->SetContent(wxString::Format(wxT("%d"), c
));
654 fragment
= text
.Mid(last
, i
-last
);
658 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text"));
659 parent
->AddChild(elementNode
);
660 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
662 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
663 elementNode
->AddChild(textNode
);
665 if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))
666 fragment
= wxT("\"") + fragment
+ wxT("\"");
668 textNode
->SetContent(fragment
);
674 // Import this object from XML
675 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
677 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
679 wxBitmapType imageType
= wxBITMAP_TYPE_PNG
;
680 wxString value
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
);
683 int type
= wxAtoi(value
);
685 // note: 0 == wxBITMAP_TYPE_INVALID
686 if (type
<= 0 || type
>= wxBITMAP_TYPE_MAX
)
688 wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
);
692 imageType
= (wxBitmapType
)type
;
698 wxXmlNode
* imageChild
= node
->GetChildren();
701 wxString childName
= imageChild
->GetName();
702 if (childName
== wxT("data"))
704 wxXmlNode
* dataChild
= imageChild
->GetChildren();
707 data
= dataChild
->GetContent();
709 dataChild
= dataChild
->GetNext();
713 imageChild
= imageChild
->GetNext();
718 wxStringInputStream
strStream(data
);
720 GetImageBlock().ReadHex(strStream
, data
.length(), imageType
);
728 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
729 // Export this object directly to the given stream.
730 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
732 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), false);
734 handler
->GetHelper().OutputIndentation(stream
, indent
);
735 handler
->GetHelper().OutputString(stream
, wxT("<image"));
736 if (!GetImageBlock().IsOk())
739 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
743 handler
->GetHelper().OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style
+ wxT(">"));
745 if (GetProperties().GetCount() > 0)
747 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
748 handler
->GetHelper().OutputIndentation(stream
, indent
);
751 handler
->GetHelper().OutputIndentation(stream
, indent
+1);
752 handler
->GetHelper().OutputString(stream
, wxT("<data>"));
754 // wxStopWatch stopwatch;
756 GetImageBlock().WriteHex(stream
);
758 // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time());
760 handler
->GetHelper().OutputString(stream
, wxT("</data>\n"));
761 handler
->GetHelper().OutputIndentation(stream
, indent
);
762 handler
->GetHelper().OutputString(stream
, wxT("</image>"));
767 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
768 // Export this object to the given parent node, usually creating at least one child node.
769 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
771 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image"));
772 parent
->AddChild(elementNode
);
774 if (GetImageBlock().IsOk())
775 elementNode
->AddAttribute(wxT("imagetype"), wxRichTextXMLHelper::MakeString((int) GetImageBlock().GetImageType()));
777 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), false);
778 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
780 wxXmlNode
* dataNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data"));
781 elementNode
->AddChild(dataNode
);
782 wxXmlNode
* textNode
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text"));
783 dataNode
->AddChild(textNode
);
788 wxMemoryOutputStream stream
;
789 if (GetImageBlock().WriteHex(stream
))
791 if (stream
.GetSize() > 0)
793 int size
= stream
.GetSize();
795 int size2
= stream
.GetOutputStreamBuffer()->GetIntPosition();
796 wxASSERT(size
== size2
);
798 unsigned char* data
= new unsigned char[size
];
799 stream
.CopyTo(data
, size
);
800 strData
= wxString((const char*) data
, wxConvUTF8
, size
);
804 strData
= wxEmptyString
;
810 wxStringOutputStream
strStream(& strData
);
811 GetImageBlock().WriteHex(strStream
);
815 textNode
->SetContent(strData
);
816 #if wxCHECK_VERSION(2,9,0)
817 textNode
->SetNoConversion(true); // optimize speed
824 // Import this object from XML
825 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
827 wxRichTextObject::ImportFromXML(buffer
, node
, handler
, recurse
);
831 wxString partial
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
);
832 if (partial
== wxT("true"))
833 SetPartialParagraph(true);
835 wxXmlNode
* child
= handler
->GetHelper().FindNode(node
, wxT("stylesheet"));
836 if (child
&& (handler
->GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
))
838 wxRichTextStyleSheet
* sheet
= new wxRichTextStyleSheet
;
839 wxString sheetName
= child
->GetAttribute(wxT("name"), wxEmptyString
);
840 wxString sheetDescription
= child
->GetAttribute(wxT("description"), wxEmptyString
);
841 sheet
->SetName(sheetName
);
842 sheet
->SetDescription(sheetDescription
);
844 wxXmlNode
* child2
= child
->GetChildren();
847 handler
->GetHelper().ImportStyleDefinition(sheet
, child2
);
849 child2
= child2
->GetNext();
851 handler
->GetHelper().ImportProperties(sheet
->GetProperties(), child
);
853 // Notify that styles have changed. If this is vetoed by the app,
854 // the new sheet will be deleted. If it is not vetoed, the
855 // old sheet will be deleted and replaced with the new one.
856 buffer
->SetStyleSheetAndNotify(sheet
);
862 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
863 // Export this object directly to the given stream.
864 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
866 handler
->GetHelper().OutputIndentation(stream
, indent
);
867 wxString nodeName
= GetXMLNodeName();
868 handler
->GetHelper().OutputString(stream
, wxT("<") + nodeName
);
870 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
872 if (GetPartialParagraph())
873 style
<< wxT(" partialparagraph=\"true\"");
875 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
877 if (GetProperties().GetCount() > 0)
879 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
883 for (i
= 0; i
< GetChildCount(); i
++)
885 wxRichTextObject
* child
= GetChild(i
);
886 child
->ExportXML(stream
, indent
+1, handler
);
889 handler
->GetHelper().OutputIndentation(stream
, indent
);
890 handler
->GetHelper().OutputString(stream
, wxT("</") + nodeName
+ wxT(">"));
895 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
896 // Export this object to the given parent node, usually creating at least one child node.
897 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
899 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
900 parent
->AddChild(elementNode
);
901 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
902 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
904 if (GetPartialParagraph())
905 elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true"));
908 for (i
= 0; i
< GetChildCount(); i
++)
910 wxRichTextObject
* child
= GetChild(i
);
911 child
->ExportXML(elementNode
, handler
);
918 // Import this object from XML
919 bool wxRichTextTable::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
, bool* recurse
)
921 wxRichTextBox::ImportFromXML(buffer
, node
, handler
, recurse
);
925 m_rowCount
= wxAtoi(node
->GetAttribute(wxT("rows"), wxEmptyString
));
926 m_colCount
= wxAtoi(node
->GetAttribute(wxT("cols"), wxEmptyString
));
928 wxXmlNode
* child
= node
->GetChildren();
931 wxRichTextObject
* childObj
= handler
->CreateObjectForXMLName(this, child
->GetName());
934 AppendChild(childObj
);
935 handler
->ImportXML(buffer
, childObj
, child
);
937 child
= child
->GetNext();
940 m_cells
.Add(wxRichTextObjectPtrArray(), m_rowCount
);
942 for (i
= 0; i
< m_rowCount
; i
++)
944 wxRichTextObjectPtrArray
& colArray
= m_cells
[i
];
945 for (j
= 0; j
< m_colCount
; j
++)
947 int idx
= i
* m_colCount
+ j
;
948 if (idx
< (int) GetChildren().GetCount())
950 wxRichTextCell
* cell
= wxDynamicCast(GetChildren().Item(idx
)->GetData(), wxRichTextCell
);
960 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
961 // Export this object directly to the given stream.
962 bool wxRichTextTable::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
)
964 handler
->GetHelper().OutputIndentation(stream
, indent
);
965 wxString nodeName
= GetXMLNodeName();
966 handler
->GetHelper().OutputString(stream
, wxT("<") + nodeName
);
968 wxString style
= handler
->GetHelper().AddAttributes(GetAttributes(), true);
970 style
<< wxT(" rows=\"") << m_rowCount
<< wxT("\"");
971 style
<< wxT(" cols=\"") << m_colCount
<< wxT("\"");
973 handler
->GetHelper().OutputString(stream
, style
+ wxT(">"));
975 if (GetProperties().GetCount() > 0)
977 handler
->GetHelper().WriteProperties(stream
, GetProperties(), indent
);
981 for (i
= 0; i
< m_rowCount
; i
++)
983 for (j
= 0; j
< m_colCount
; j
++)
985 wxRichTextCell
* cell
= GetCell(i
, j
);
986 cell
->ExportXML(stream
, indent
+1, handler
);
990 handler
->GetHelper().OutputIndentation(stream
, indent
);
991 handler
->GetHelper().OutputString(stream
, wxT("</") + nodeName
+ wxT(">"));
997 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
998 // Export this object to the given parent node, usually creating at least one child node.
999 bool wxRichTextTable::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
)
1001 wxXmlNode
* elementNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName());
1002 parent
->AddChild(elementNode
);
1003 handler
->GetHelper().AddAttributes(elementNode
, GetAttributes(), true);
1004 handler
->GetHelper().WriteProperties(elementNode
, GetProperties());
1006 elementNode
->AddAttribute(wxT("rows"), wxString::Format(wxT("%d"), m_rowCount
));
1007 elementNode
->AddAttribute(wxT("cols"), wxString::Format(wxT("%d"), m_colCount
));
1010 for (i
= 0; i
< m_rowCount
; i
++)
1012 for (j
= 0; j
< m_colCount
; j
++)
1014 wxRichTextCell
* cell
= GetCell(i
, j
);
1015 cell
->ExportXML(elementNode
, handler
);
1023 wxRichTextXMLHelper::~wxRichTextXMLHelper()
1028 void wxRichTextXMLHelper::Init()
1030 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1031 m_deleteConvFile
= false;
1038 void wxRichTextXMLHelper::Clear()
1040 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1041 if (m_deleteConvFile
)
1045 m_deleteConvFile
= false;
1047 m_fileEncoding
= wxEmptyString
;
1050 void wxRichTextXMLHelper::SetupForSaving(const wxString
& enc
)
1055 m_fileEncoding
= wxT("UTF-8");
1056 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1057 m_convFile
= & wxConvUTF8
;
1060 m_fileEncoding
= wxT("ISO-8859-1");
1061 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1062 m_convFile
= & wxConvISO8859_1
;
1066 // If we pass an explicit encoding, change the output encoding.
1067 if (!enc
.empty() && enc
.Lower() != m_fileEncoding
.Lower())
1069 if (enc
== wxT("<System>"))
1072 m_fileEncoding
= wxLocale::GetSystemEncodingName();
1073 // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below
1078 m_fileEncoding
= enc
;
1081 // GetSystemEncodingName may not have returned a name
1082 if (m_fileEncoding
.empty())
1084 m_fileEncoding
= wxT("UTF-8");
1086 m_fileEncoding
= wxT("ISO-8859-1");
1088 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1089 m_convFile
= new wxCSConv(m_fileEncoding
);
1090 m_deleteConvFile
= true;
1094 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1096 m_convMem
= wxConvCurrent
;
1103 // Convert a colour to a 6-digit hex string
1104 wxString
wxRichTextXMLHelper::ColourToHexString(const wxColour
& col
)
1108 hex
+= wxDecToHex(col
.Red());
1109 hex
+= wxDecToHex(col
.Green());
1110 hex
+= wxDecToHex(col
.Blue());
1115 // Convert 6-digit hex string to a colour
1116 wxColour
wxRichTextXMLHelper::HexStringToColour(const wxString
& hex
)
1118 unsigned char r
= (unsigned char)wxHexToDec(hex
.Mid(0, 2));
1119 unsigned char g
= (unsigned char)wxHexToDec(hex
.Mid(2, 2));
1120 unsigned char b
= (unsigned char)wxHexToDec(hex
.Mid(4, 2));
1122 return wxColour(r
, g
, b
);
1125 //-----------------------------------------------------------------------------
1126 // xml support routines
1127 //-----------------------------------------------------------------------------
1129 bool wxRichTextXMLHelper::HasParam(wxXmlNode
* node
, const wxString
& param
)
1131 return (GetParamNode(node
, param
) != NULL
);
1134 wxXmlNode
*wxRichTextXMLHelper::GetParamNode(wxXmlNode
* node
, const wxString
& param
)
1136 wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!"));
1138 wxXmlNode
*n
= node
->GetChildren();
1142 if (n
->GetType() == wxXML_ELEMENT_NODE
&& n
->GetName() == param
)
1149 wxString
wxRichTextXMLHelper::GetNodeContent(wxXmlNode
*node
)
1151 wxXmlNode
*n
= node
;
1152 if (n
== NULL
) return wxEmptyString
;
1153 n
= n
->GetChildren();
1157 if (n
->GetType() == wxXML_TEXT_NODE
||
1158 n
->GetType() == wxXML_CDATA_SECTION_NODE
)
1159 return n
->GetContent();
1162 return wxEmptyString
;
1165 wxString
wxRichTextXMLHelper::GetParamValue(wxXmlNode
*node
, const wxString
& param
)
1168 return GetNodeContent(node
);
1170 return GetNodeContent(GetParamNode(node
, param
));
1173 wxString
wxRichTextXMLHelper::GetText(wxXmlNode
*node
, const wxString
& param
)
1175 wxXmlNode
*parNode
= GetParamNode(node
, param
);
1178 wxString
str1(GetNodeContent(parNode
));
1182 wxXmlNode
* wxRichTextXMLHelper::FindNode(wxXmlNode
* node
, const wxString
& name
)
1184 if (node
->GetName() == name
&& name
== wxT("stylesheet"))
1187 wxXmlNode
* child
= node
->GetChildren();
1190 if (child
->GetName() == name
)
1192 child
= child
->GetNext();
1197 wxString
wxRichTextXMLHelper::AttributeToXML(const wxString
& str
)
1200 size_t i
, last
, len
;
1205 for (i
= 0; i
< len
; i
++)
1209 // Original code excluded "&" but we _do_ want to convert
1210 // the ampersand beginning & because otherwise when read in,
1211 // the original "&" becomes "&".
1213 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
1214 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
1216 str1
+= str
.Mid(last
, i
- last
);
1220 str1
+= wxT("<");
1223 str1
+= wxT(">");
1226 str1
+= wxT("&");
1229 str1
+= wxT(""");
1235 else if (wxUChar(c
) > 127)
1237 str1
+= str
.Mid(last
, i
- last
);
1239 wxString
s(wxT("&#"));
1243 s
<< (int) wxUChar(c
);
1250 str1
+= str
.Mid(last
, i
- last
);
1254 // Make a string from the given property. This can be overridden for custom variants.
1255 wxString
wxRichTextXMLHelper::MakeStringFromProperty(const wxVariant
& var
)
1257 return var
.MakeString();
1260 // Create a proprty from the string read from the XML file.
1261 wxVariant
wxRichTextXMLHelper::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
))
1263 wxVariant
var(value
, name
);
1264 // TODO: use type to create using common types
1268 /// Replace face name with current name for platform.
1269 /// TODO: introduce a virtual function or settable table to
1270 /// do this comprehensively.
1271 bool wxRichTextXMLHelper::RichTextFixFaceName(wxString
& facename
)
1273 if (facename
.empty())
1277 if (facename
== wxT("Times"))
1279 facename
= wxT("Times New Roman");
1282 else if (facename
== wxT("Helvetica"))
1284 facename
= wxT("Arial");
1287 else if (facename
== wxT("Courier"))
1289 facename
= wxT("Courier New");
1295 if (facename
== wxT("Times New Roman"))
1297 facename
= wxT("Times");
1300 else if (facename
== wxT("Arial"))
1302 facename
= wxT("Helvetica");
1305 else if (facename
== wxT("Courier New"))
1307 facename
= wxT("Courier");
1315 long wxRichTextXMLHelper::ColourStringToLong(const wxString
& colStr
)
1317 if (!colStr
.IsEmpty())
1319 wxColour
col(colStr
);
1320 #if wxCHECK_VERSION(2,9,0)
1321 return col
.GetRGB();
1323 return (col
.Red() | (col
.Green() << 8) | (col
.Blue() << 16));
1330 wxTextAttrDimension
wxRichTextXMLHelper::ParseDimension(const wxString
& dimStr
)
1332 wxString valuePart
= dimStr
.BeforeFirst(wxT(','));
1334 if (dimStr
.Contains(wxT(",")))
1335 flagsPart
= dimStr
.AfterFirst(wxT(','));
1336 wxTextAttrDimension dim
;
1337 dim
.SetValue(wxAtoi(valuePart
));
1338 dim
.SetFlags(wxAtoi(flagsPart
));
1343 /// Import style parameters
1344 bool wxRichTextXMLHelper::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
)
1346 wxXmlAttribute
* xmlAttr
= node
->GetAttributes();
1350 const wxString
& name
= xmlAttr
->GetName();
1351 const wxString
& value
= xmlAttr
->GetValue();
1354 if (name
== wxT("fontface"))
1359 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
)
1360 RichTextFixFaceName(v
);
1361 attr
.SetFontFaceName(v
);
1364 else if (name
== wxT("fontfamily"))
1367 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
));
1369 else if (name
== wxT("fontstyle"))
1372 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
));
1374 else if (name
== wxT("fontsize") || name
== wxT("fontpointsize"))
1377 attr
.SetFontPointSize(wxAtoi(value
));
1379 else if (name
== wxT("fontpixelsize"))
1382 attr
.SetFontPixelSize(wxAtoi(value
));
1384 else if (name
== wxT("fontweight"))
1387 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
));
1389 else if (name
== wxT("fontunderlined"))
1392 attr
.SetFontUnderlined(wxAtoi(value
) != 0);
1394 else if (name
== wxT("textcolor"))
1398 if (value
[0] == wxT('#'))
1399 attr
.SetTextColour(HexStringToColour(value
.Mid(1)));
1401 attr
.SetTextColour(value
);
1404 else if (name
== wxT("bgcolor"))
1408 if (value
[0] == wxT('#'))
1409 attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1)));
1411 attr
.SetBackgroundColour(value
);
1414 else if (name
== wxT("characterstyle"))
1417 attr
.SetCharacterStyleName(value
);
1419 else if (name
== wxT("texteffects"))
1422 attr
.SetTextEffects(wxAtoi(value
));
1424 else if (name
== wxT("texteffectflags"))
1427 attr
.SetTextEffectFlags(wxAtoi(value
));
1429 else if (name
== wxT("url"))
1436 if (name
== wxT("alignment"))
1439 attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
));
1441 else if (name
== wxT("leftindent"))
1444 attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent());
1446 else if (name
== wxT("leftsubindent"))
1449 attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
));
1451 else if (name
== wxT("rightindent"))
1454 attr
.SetRightIndent(wxAtoi(value
));
1456 else if (name
== wxT("parspacingbefore"))
1459 attr
.SetParagraphSpacingBefore(wxAtoi(value
));
1461 else if (name
== wxT("parspacingafter"))
1464 attr
.SetParagraphSpacingAfter(wxAtoi(value
));
1466 else if (name
== wxT("linespacing"))
1469 attr
.SetLineSpacing(wxAtoi(value
));
1471 else if (name
== wxT("bulletstyle"))
1474 attr
.SetBulletStyle(wxAtoi(value
));
1476 else if (name
== wxT("bulletnumber"))
1479 attr
.SetBulletNumber(wxAtoi(value
));
1481 else if (name
== wxT("bulletsymbol"))
1485 wxChar ch
= wxAtoi(value
);
1488 attr
.SetBulletText(s
);
1491 else if (name
== wxT("bullettext"))
1495 attr
.SetBulletText(value
);
1498 else if (name
== wxT("bulletfont"))
1502 attr
.SetBulletFont(value
);
1505 else if (name
== wxT("bulletname"))
1509 attr
.SetBulletName(value
);
1512 else if (name
== wxT("parstyle"))
1516 attr
.SetParagraphStyleName(value
);
1519 else if (name
== wxT("liststyle"))
1523 attr
.SetListStyleName(value
);
1526 else if (name
== wxT("boxstyle"))
1530 attr
.GetTextBoxAttr().SetBoxStyleName(value
);
1533 else if (name
== wxT("tabs"))
1538 wxStringTokenizer
tkz(value
, wxT(","));
1539 while (tkz
.HasMoreTokens())
1541 wxString token
= tkz
.GetNextToken();
1542 tabs
.Add(wxAtoi(token
));
1547 else if (name
== wxT("pagebreak"))
1551 attr
.SetPageBreak(wxAtoi(value
) != 0);
1554 else if (name
== wxT("outlinelevel"))
1558 attr
.SetOutlineLevel(wxAtoi(value
));
1571 if (name
== wxT("width"))
1573 attr
.GetTextBoxAttr().GetWidth().SetValue(ParseDimension(value
));
1575 else if (name
== wxT("height"))
1577 attr
.GetTextBoxAttr().GetHeight().SetValue(ParseDimension(value
));
1579 else if (name
== wxT("minwidth"))
1581 attr
.GetTextBoxAttr().GetMinSize().GetWidth().SetValue(ParseDimension(value
));
1583 else if (name
== wxT("minheight"))
1585 attr
.GetTextBoxAttr().GetMinSize().GetHeight().SetValue(ParseDimension(value
));
1587 else if (name
== wxT("maxwidth"))
1589 attr
.GetTextBoxAttr().GetMaxSize().GetWidth().SetValue(ParseDimension(value
));
1591 else if (name
== wxT("maxheight"))
1593 attr
.GetTextBoxAttr().GetMaxSize().GetHeight().SetValue(ParseDimension(value
));
1596 else if (name
== wxT("verticalalignment"))
1598 if (value
== wxT("top"))
1599 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
);
1600 else if (value
== wxT("centre"))
1601 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
);
1602 else if (value
== wxT("bottom"))
1603 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
);
1604 else if (value
== wxT("none"))
1605 attr
.GetTextBoxAttr().SetVerticalAlignment(wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_NONE
);
1607 else if (name
== wxT("float"))
1609 if (value
== wxT("left"))
1610 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
);
1611 else if (value
== wxT("right"))
1612 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
);
1613 else if (value
== wxT("none"))
1614 attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
);
1616 else if (name
== wxT("clear"))
1618 if (value
== wxT("left"))
1619 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
);
1620 else if (value
== wxT("right"))
1621 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
);
1622 else if (value
== wxT("both"))
1623 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
);
1624 else if (value
== wxT("none"))
1625 attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
);
1627 else if (name
== wxT("collapse-borders"))
1628 attr
.GetTextBoxAttr().SetCollapseBorders((wxTextBoxAttrCollapseMode
) wxAtoi(value
));
1630 else if (name
.Contains(wxT("border-")))
1632 if (name
== wxT("border-left-style"))
1633 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
));
1634 else if (name
== wxT("border-right-style"))
1635 attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
));
1636 else if (name
== wxT("border-top-style"))
1637 attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
));
1638 else if (name
== wxT("border-bottom-style"))
1639 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
));
1641 else if (name
== wxT("border-left-colour"))
1642 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(ColourStringToLong(value
));
1643 else if (name
== wxT("border-right-colour"))
1644 attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(ColourStringToLong(value
));
1645 else if (name
== wxT("border-top-colour"))
1646 attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(ColourStringToLong(value
));
1647 else if (name
== wxT("border-bottom-colour"))
1648 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(ColourStringToLong(value
));
1650 else if (name
== wxT("border-left-width"))
1651 attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(ParseDimension(value
));
1652 else if (name
== wxT("border-right-width"))
1653 attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(ParseDimension(value
));
1654 else if (name
== wxT("border-top-width"))
1655 attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(ParseDimension(value
));
1656 else if (name
== wxT("border-bottom-width"))
1657 attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(ParseDimension(value
));
1659 else if (name
.Contains(wxT("outline-")))
1661 if (name
== wxT("outline-left-style"))
1662 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
));
1663 else if (name
== wxT("outline-right-style"))
1664 attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
));
1665 else if (name
== wxT("outline-top-style"))
1666 attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
));
1667 else if (name
== wxT("outline-bottom-style"))
1668 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
));
1670 else if (name
== wxT("outline-left-colour"))
1671 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(ColourStringToLong(value
));
1672 else if (name
== wxT("outline-right-colour"))
1673 attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(ColourStringToLong(value
));
1674 else if (name
== wxT("outline-top-colour"))
1675 attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(ColourStringToLong(value
));
1676 else if (name
== wxT("outline-bottom-colour"))
1677 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(ColourStringToLong(value
));
1679 else if (name
== wxT("outline-left-width"))
1680 attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(ParseDimension(value
));
1681 else if (name
== wxT("outline-right-width"))
1682 attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(ParseDimension(value
));
1683 else if (name
== wxT("outline-top-width"))
1684 attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(ParseDimension(value
));
1685 else if (name
== wxT("outline-bottom-width"))
1686 attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(ParseDimension(value
));
1688 else if (name
.Contains(wxT("margin-")))
1690 if (name
== wxT("margin-left"))
1691 attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(ParseDimension(value
));
1692 else if (name
== wxT("margin-right"))
1693 attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(ParseDimension(value
));
1694 else if (name
== wxT("margin-top"))
1695 attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(ParseDimension(value
));
1696 else if (name
== wxT("margin-bottom"))
1697 attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(ParseDimension(value
));
1699 else if (name
.Contains(wxT("padding-")))
1701 if (name
== wxT("padding-left"))
1702 attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(ParseDimension(value
));
1703 else if (name
== wxT("padding-right"))
1704 attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(ParseDimension(value
));
1705 else if (name
== wxT("padding-top"))
1706 attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(ParseDimension(value
));
1707 else if (name
== wxT("padding-bottom"))
1708 attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(ParseDimension(value
));
1710 else if (name
.Contains(wxT("position-")))
1712 if (name
== wxT("position-left"))
1713 attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(ParseDimension(value
));
1714 else if (name
== wxT("position-right"))
1715 attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(ParseDimension(value
));
1716 else if (name
== wxT("position-top"))
1717 attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(ParseDimension(value
));
1718 else if (name
== wxT("position-bottom"))
1719 attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(ParseDimension(value
));
1723 xmlAttr
= xmlAttr
->GetNext();
1729 bool wxRichTextXMLHelper::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
)
1731 wxString styleType
= node
->GetName();
1732 wxString styleName
= node
->GetAttribute(wxT("name"), wxEmptyString
);
1733 wxString baseStyleName
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
);
1735 if (styleName
.empty())
1738 if (styleType
== wxT("characterstyle"))
1740 wxRichTextCharacterStyleDefinition
* def
= new wxRichTextCharacterStyleDefinition(styleName
);
1741 def
->SetBaseStyle(baseStyleName
);
1743 wxXmlNode
* child
= node
->GetChildren();
1746 if (child
->GetName() == wxT("style"))
1748 wxRichTextAttr attr
;
1749 ImportStyle(attr
, child
, false);
1750 def
->SetStyle(attr
);
1752 child
= child
->GetNext();
1755 ImportProperties(def
->GetProperties(), node
);
1757 sheet
->AddCharacterStyle(def
);
1759 else if (styleType
== wxT("paragraphstyle"))
1761 wxRichTextParagraphStyleDefinition
* def
= new wxRichTextParagraphStyleDefinition(styleName
);
1763 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
1764 def
->SetNextStyle(nextStyleName
);
1765 def
->SetBaseStyle(baseStyleName
);
1767 wxXmlNode
* child
= node
->GetChildren();
1770 if (child
->GetName() == wxT("style"))
1772 wxRichTextAttr attr
;
1773 ImportStyle(attr
, child
, true);
1774 def
->SetStyle(attr
);
1776 child
= child
->GetNext();
1779 ImportProperties(def
->GetProperties(), node
);
1781 sheet
->AddParagraphStyle(def
);
1783 else if (styleType
== wxT("boxstyle"))
1785 wxRichTextBoxStyleDefinition
* def
= new wxRichTextBoxStyleDefinition(styleName
);
1787 def
->SetBaseStyle(baseStyleName
);
1789 wxXmlNode
* child
= node
->GetChildren();
1792 if (child
->GetName() == wxT("style"))
1794 wxRichTextAttr attr
;
1795 ImportStyle(attr
, child
, true);
1796 def
->SetStyle(attr
);
1798 child
= child
->GetNext();
1801 ImportProperties(def
->GetProperties(), node
);
1803 sheet
->AddBoxStyle(def
);
1805 else if (styleType
== wxT("liststyle"))
1807 wxRichTextListStyleDefinition
* def
= new wxRichTextListStyleDefinition(styleName
);
1809 wxString nextStyleName
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
);
1810 def
->SetNextStyle(nextStyleName
);
1811 def
->SetBaseStyle(baseStyleName
);
1813 wxXmlNode
* child
= node
->GetChildren();
1816 if (child
->GetName() == wxT("style"))
1818 wxRichTextAttr attr
;
1819 ImportStyle(attr
, child
, true);
1821 wxString styleLevel
= child
->GetAttribute(wxT("level"), wxEmptyString
);
1822 if (styleLevel
.empty())
1824 def
->SetStyle(attr
);
1828 int level
= wxAtoi(styleLevel
);
1829 if (level
> 0 && level
<= 10)
1831 def
->SetLevelAttributes(level
-1, attr
);
1835 child
= child
->GetNext();
1838 ImportProperties(def
->GetProperties(), node
);
1840 sheet
->AddListStyle(def
);
1846 bool wxRichTextXMLHelper::ImportProperties(wxRichTextProperties
& properties
, wxXmlNode
* node
)
1848 wxXmlNode
* child
= node
->GetChildren();
1851 if (child
->GetName() == wxT("properties"))
1853 wxXmlNode
* propertyChild
= child
->GetChildren();
1854 while (propertyChild
)
1856 if (propertyChild
->GetName() == wxT("property"))
1858 wxString name
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
);
1859 wxString value
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
);
1860 wxString type
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
);
1862 wxVariant var
= MakePropertyFromString(name
, value
, type
);
1865 properties
.SetProperty(var
);
1868 propertyChild
= propertyChild
->GetNext();
1871 child
= child
->GetNext();
1876 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT
1877 // write string to output
1878 void wxRichTextXMLHelper::OutputString(wxOutputStream
& stream
, const wxString
& str
,
1879 wxMBConv
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv
*convFile
)
1881 if (str
.empty()) return;
1885 const wxWX2MBbuf
buf(str
.mb_str(*convFile
));
1886 stream
.Write((const char*)buf
, strlen((const char*)buf
));
1890 const wxWX2MBbuf
buf(str
.mb_str(wxConvUTF8
));
1891 stream
.Write((const char*)buf
, strlen((const char*)buf
));
1894 if ( convFile
== NULL
)
1895 stream
.Write(str
.mb_str(), str
.Len());
1898 wxString
str2(str
.wc_str(*convMem
), *convFile
);
1899 stream
.Write(str2
.mb_str(), str2
.Len());
1904 void wxRichTextXMLHelper::OutputIndentation(wxOutputStream
& stream
, int indent
)
1906 wxString str
= wxT("\n");
1907 for (int i
= 0; i
< indent
; i
++)
1908 str
<< wxT(' ') << wxT(' ');
1909 OutputString(stream
, str
, NULL
, NULL
);
1912 // Same as above, but create entities first.
1913 // Translates '<' to "<", '>' to ">" and '&' to "&"
1914 void wxRichTextXMLHelper::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
,
1915 wxMBConv
*convMem
, wxMBConv
*convFile
)
1918 size_t i
, last
, len
;
1923 for (i
= 0; i
< len
; i
++)
1927 // Original code excluded "&" but we _do_ want to convert
1928 // the ampersand beginning & because otherwise when read in,
1929 // the original "&" becomes "&".
1931 if (c
== wxT('<') || c
== wxT('>') || c
== wxT('"') ||
1932 (c
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
1934 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1938 OutputString(stream
, wxT("<"), NULL
, NULL
);
1941 OutputString(stream
, wxT(">"), NULL
, NULL
);
1944 OutputString(stream
, wxT("&"), NULL
, NULL
);
1947 OutputString(stream
, wxT("""), NULL
, NULL
);
1953 else if (wxUChar(c
) > 127)
1955 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1957 wxString
s(wxT("&#"));
1961 s
<< (int) wxUChar(c
);
1964 OutputString(stream
, s
, NULL
, NULL
);
1968 OutputString(stream
, str
.Mid(last
, i
- last
), convMem
, convFile
);
1971 void wxRichTextXMLHelper::OutputString(wxOutputStream
& stream
, const wxString
& str
)
1973 OutputString(stream
, str
, m_convMem
, m_convFile
);
1976 void wxRichTextXMLHelper::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
)
1978 OutputStringEnt(stream
, str
, m_convMem
, m_convFile
);
1981 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const int& v
)
1983 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\"");
1986 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const long& v
)
1988 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\"");
1991 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const double& v
)
1993 str
<< wxT(" ") << name
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\"");
1996 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxChar
* s
)
1998 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
2001 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxString
& s
)
2003 str
<< wxT(" ") << name
<< wxT("=\"") << s
<< wxT("\"");
2006 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxColour
& col
)
2008 str
<< wxT(" ") << name
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\"");
2011 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& name
, const wxTextAttrDimension
& dim
)
2015 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags());
2016 str
<< wxT(" ") << name
<< wxT("=\"");
2022 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
2024 if (dims
.GetLeft().IsValid())
2025 AddAttribute(str
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
2026 if (dims
.GetRight().IsValid())
2027 AddAttribute(str
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
2028 if (dims
.GetTop().IsValid())
2029 AddAttribute(str
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
2030 if (dims
.GetBottom().IsValid())
2031 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
2034 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
2036 if (border
.HasStyle())
2037 AddAttribute(str
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
2038 if (border
.HasColour())
2039 AddAttribute(str
, rootName
+ wxString(wxT("-color")), border
.GetColour());
2040 if (border
.HasWidth())
2041 AddAttribute(str
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
2044 void wxRichTextXMLHelper::AddAttribute(wxString
& str
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
2046 AddAttribute(str
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
2047 AddAttribute(str
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
2048 AddAttribute(str
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
2049 AddAttribute(str
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
2052 /// Create a string containing style attributes
2053 wxString
wxRichTextXMLHelper::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
)
2056 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
2057 AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour());
2059 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
2060 AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour());
2062 if (attr
.HasFontPointSize())
2063 AddAttribute(str
, wxT("fontpointsize"), attr
.GetFontSize());
2064 else if (attr
.HasFontPixelSize())
2065 AddAttribute(str
, wxT("fontpixelsize"), attr
.GetFontSize());
2067 if (attr
.HasFontFamily())
2068 AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily());
2070 if (attr
.HasFontItalic())
2071 AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle());
2073 if (attr
.HasFontWeight())
2074 AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight());
2076 if (attr
.HasFontUnderlined())
2077 AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined());
2079 if (attr
.HasFontFaceName())
2080 AddAttribute(str
, wxT("fontface"), AttributeToXML(attr
.GetFontFaceName()));
2082 if (attr
.HasTextEffects())
2084 AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects());
2085 AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags());
2088 if (!attr
.GetCharacterStyleName().empty())
2089 AddAttribute(str
, wxT("characterstyle"), AttributeToXML(attr
.GetCharacterStyleName()));
2092 AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL()));
2096 if (attr
.HasAlignment())
2097 AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment());
2099 if (attr
.HasLeftIndent())
2101 AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent());
2102 AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent());
2105 if (attr
.HasRightIndent())
2106 AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent());
2108 if (attr
.HasParagraphSpacingAfter())
2109 AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter());
2111 if (attr
.HasParagraphSpacingBefore())
2112 AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore());
2114 if (attr
.HasLineSpacing())
2115 AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing());
2117 if (attr
.HasBulletStyle())
2118 AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle());
2120 if (attr
.HasBulletNumber())
2121 AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber());
2123 if (attr
.HasBulletText())
2125 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
2126 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
2127 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
2128 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0]));
2130 AddAttribute(str
, wxT("bullettext"), AttributeToXML(attr
.GetBulletText()));
2132 AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont());
2135 if (attr
.HasBulletName())
2136 AddAttribute(str
, wxT("bulletname"), AttributeToXML(attr
.GetBulletName()));
2138 if (!attr
.GetParagraphStyleName().empty())
2139 AddAttribute(str
, wxT("parstyle"), AttributeToXML(attr
.GetParagraphStyleName()));
2141 if (!attr
.GetListStyleName().empty())
2142 AddAttribute(str
, wxT("liststyle"), AttributeToXML(attr
.GetListStyleName()));
2144 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
2145 AddAttribute(str
, wxT("boxstyle"), AttributeToXML(attr
.GetTextBoxAttr().GetBoxStyleName()));
2151 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
2153 if (i
> 0) strTabs
<< wxT(",");
2154 strTabs
<< attr
.GetTabs()[i
];
2156 AddAttribute(str
, wxT("tabs"), strTabs
);
2159 if (attr
.HasPageBreak())
2161 AddAttribute(str
, wxT("pagebreak"), 1);
2164 if (attr
.HasOutlineLevel())
2165 AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel());
2168 AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
2169 AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
2170 AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
2171 AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
2172 AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
2173 AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
2174 AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
2175 AddAttribute(str
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
2176 AddAttribute(str
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
2177 AddAttribute(str
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
2178 AddAttribute(str
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
2180 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
2183 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
2185 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
2186 value
= wxT("centre");
2187 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
2188 value
= wxT("bottom");
2190 value
= wxT("none");
2191 AddAttribute(str
, wxT("verticalalignment"), value
);
2194 if (attr
.GetTextBoxAttr().HasFloatMode())
2197 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
2198 value
= wxT("left");
2199 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
2200 value
= wxT("right");
2202 value
= wxT("none");
2203 AddAttribute(str
, wxT("float"), value
);
2206 if (attr
.GetTextBoxAttr().HasClearMode())
2209 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
2210 value
= wxT("left");
2211 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
2212 value
= wxT("right");
2213 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
2214 value
= wxT("both");
2216 value
= wxT("none");
2217 AddAttribute(str
, wxT("clear"), value
);
2220 if (attr
.GetTextBoxAttr().HasCollapseBorders())
2221 AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
2226 // Write the properties
2227 bool wxRichTextXMLHelper::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
)
2229 if (properties
.GetCount() > 0)
2233 OutputIndentation(stream
, level
);
2234 OutputString(stream
, wxT("<properties>"));
2239 for (i
= 0; i
< properties
.GetCount(); i
++)
2241 const wxVariant
& var
= properties
[i
];
2244 const wxString
& name
= var
.GetName();
2245 wxString value
= MakeStringFromProperty(var
);
2247 OutputIndentation(stream
, level
);
2248 OutputString(stream
, wxT("<property name=\"") + name
+
2249 wxT("\" type=\"") + var
.GetType() + wxT("\" value=\""));
2250 OutputStringEnt(stream
, value
);
2251 OutputString(stream
, wxT("\"/>"));
2257 OutputIndentation(stream
, level
);
2258 OutputString(stream
, wxT("</properties>"));
2266 bool wxRichTextXMLHelper::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
)
2268 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
2269 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
2270 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
2271 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
2273 wxString name
= def
->GetName();
2276 nameProp
= wxT(" name=\"") + AttributeToXML(name
) + wxT("\"");
2278 wxString baseStyle
= def
->GetBaseStyle();
2279 wxString baseStyleProp
;
2280 if (!baseStyle
.empty())
2281 baseStyleProp
= wxT(" basestyle=\"") + AttributeToXML(baseStyle
) + wxT("\"");
2283 wxString descr
= def
->GetDescription();
2286 descrProp
= wxT(" description=\"") + AttributeToXML(descr
) + wxT("\"");
2290 OutputIndentation(stream
, level
);
2291 OutputString(stream
, wxT("<characterstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2295 wxString style
= AddAttributes(def
->GetStyle(), false);
2297 OutputIndentation(stream
, level
);
2298 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2300 OutputIndentation(stream
, level
);
2301 OutputString(stream
, wxT("</style>"));
2305 OutputIndentation(stream
, level
);
2306 OutputString(stream
, wxT("</characterstyle>"));
2310 OutputIndentation(stream
, level
);
2312 if (!listDef
->GetNextStyle().empty())
2313 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(listDef
->GetNextStyle()) << wxT("\"");
2315 OutputString(stream
, wxT("<liststyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2319 wxString style
= AddAttributes(def
->GetStyle(), true);
2321 OutputIndentation(stream
, level
);
2322 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2324 OutputIndentation(stream
, level
);
2325 OutputString(stream
, wxT("</style>"));
2328 for (i
= 0; i
< 10; i
++)
2330 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
2333 wxString style
= AddAttributes(def
->GetStyle(), true);
2334 wxString levelStr
= wxString::Format(wxT(" level=\"%d\" "), (i
+1));
2336 OutputIndentation(stream
, level
);
2337 OutputString(stream
, wxT("<style ") + levelStr
+ style
+ wxT(">"));
2339 OutputIndentation(stream
, level
);
2340 OutputString(stream
, wxT("</style>"));
2346 OutputIndentation(stream
, level
);
2347 OutputString(stream
, wxT("</liststyle>"));
2351 OutputIndentation(stream
, level
);
2353 if (!paraDef
->GetNextStyle().empty())
2354 baseStyleProp
<< wxT(" nextstyle=\"") << AttributeToXML(paraDef
->GetNextStyle()) << wxT("\"");
2356 OutputString(stream
, wxT("<paragraphstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2360 wxString style
= AddAttributes(def
->GetStyle(), true);
2362 OutputIndentation(stream
, level
);
2363 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2365 OutputIndentation(stream
, level
);
2366 OutputString(stream
, wxT("</style>"));
2370 OutputIndentation(stream
, level
);
2371 OutputString(stream
, wxT("</paragraphstyle>"));
2375 OutputIndentation(stream
, level
);
2377 OutputString(stream
, wxT("<boxstyle") + nameProp
+ baseStyleProp
+ descrProp
+ wxT(">"));
2381 wxString style
= AddAttributes(def
->GetStyle(), true);
2383 OutputIndentation(stream
, level
);
2384 OutputString(stream
, wxT("<style ") + style
+ wxT(">"));
2386 OutputIndentation(stream
, level
);
2387 OutputString(stream
, wxT("</style>"));
2391 OutputIndentation(stream
, level
);
2392 OutputString(stream
, wxT("</boxstyle>"));
2395 WriteProperties(stream
, def
->GetProperties(), level
);
2401 // wxRICHTEXT_HAVE_DIRECT_OUTPUT
2404 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2406 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const int& v
)
2408 node
->AddAttribute(name
, MakeString(v
));
2411 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const long& v
)
2413 node
->AddAttribute(name
, MakeString(v
));
2416 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const double& v
)
2418 node
->AddAttribute(name
, MakeString(v
));
2421 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxString
& s
)
2423 node
->AddAttribute(name
, s
);
2426 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxColour
& col
)
2428 node
->AddAttribute(name
, MakeString(col
));
2431 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& name
, const wxTextAttrDimension
& dim
)
2435 wxString value
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags());
2436 AddAttribute(node
, name
, value
);
2440 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrDimensions
& dims
)
2442 if (dims
.GetLeft().IsValid())
2443 AddAttribute(node
, rootName
+ wxString(wxT("-left")), dims
.GetLeft());
2444 if (dims
.GetRight().IsValid())
2445 AddAttribute(node
, rootName
+ wxString(wxT("-right")), dims
.GetRight());
2446 if (dims
.GetTop().IsValid())
2447 AddAttribute(node
, rootName
+ wxString(wxT("-top")), dims
.GetTop());
2448 if (dims
.GetBottom().IsValid())
2449 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), dims
.GetBottom());
2452 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorder
& border
)
2454 if (border
.HasStyle())
2455 AddAttribute(node
, rootName
+ wxString(wxT("-style")), border
.GetStyle());
2456 if (border
.HasColour())
2457 AddAttribute(node
, rootName
+ wxString(wxT("-color")), border
.GetColour());
2458 if (border
.HasWidth())
2459 AddAttribute(node
, rootName
+ wxString(wxT("-width")), border
.GetWidth());
2462 void wxRichTextXMLHelper::AddAttribute(wxXmlNode
* node
, const wxString
& rootName
, const wxTextAttrBorders
& borders
)
2464 AddAttribute(node
, rootName
+ wxString(wxT("-left")), borders
.GetLeft());
2465 AddAttribute(node
, rootName
+ wxString(wxT("-right")), borders
.GetRight());
2466 AddAttribute(node
, rootName
+ wxString(wxT("-top")), borders
.GetTop());
2467 AddAttribute(node
, rootName
+ wxString(wxT("-bottom")), borders
.GetBottom());
2470 bool wxRichTextXMLHelper::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
)
2472 wxRichTextCharacterStyleDefinition
* charDef
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
);
2473 wxRichTextParagraphStyleDefinition
* paraDef
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
);
2474 wxRichTextBoxStyleDefinition
* boxDef
= wxDynamicCast(def
, wxRichTextBoxStyleDefinition
);
2475 wxRichTextListStyleDefinition
* listDef
= wxDynamicCast(def
, wxRichTextListStyleDefinition
);
2477 wxString baseStyle
= def
->GetBaseStyle();
2478 wxString descr
= def
->GetDescription();
2480 wxXmlNode
* defNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
);
2481 parent
->AddChild(defNode
);
2482 if (!baseStyle
.empty())
2483 defNode
->AddAttribute(wxT("basestyle"), baseStyle
);
2485 defNode
->AddAttribute(wxT("description"), descr
);
2487 wxXmlNode
* styleNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
2488 defNode
->AddChild(styleNode
);
2492 defNode
->SetName(wxT("characterstyle"));
2493 AddAttributes(styleNode
, def
->GetStyle(), false);
2497 defNode
->SetName(wxT("liststyle"));
2499 if (!listDef
->GetNextStyle().empty())
2500 defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle());
2502 AddAttributes(styleNode
, def
->GetStyle(), true);
2505 for (i
= 0; i
< 10; i
++)
2507 wxRichTextAttr
* levelAttr
= listDef
->GetLevelAttributes(i
);
2510 wxXmlNode
* levelNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style"));
2511 defNode
->AddChild(levelNode
);
2512 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1));
2513 AddAttributes(levelNode
, * levelAttr
, true);
2519 defNode
->SetName(wxT("boxstyle"));
2521 AddAttributes(styleNode
, def
->GetStyle(), true);
2525 defNode
->SetName(wxT("paragraphstyle"));
2527 if (!paraDef
->GetNextStyle().empty())
2528 defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle());
2530 AddAttributes(styleNode
, def
->GetStyle(), true);
2533 WriteProperties(defNode
, def
->GetProperties());
2538 bool wxRichTextXMLHelper::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
)
2540 if (attr
.HasTextColour() && attr
.GetTextColour().IsOk())
2541 node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour()));
2542 if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().IsOk())
2543 node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour()));
2545 if (attr
.HasFontPointSize())
2546 node
->AddAttribute(wxT("fontpointsize"), MakeString(attr
.GetFontSize()));
2547 else if (attr
.HasFontPixelSize())
2548 node
->AddAttribute(wxT("fontpixelsize"), MakeString(attr
.GetFontSize()));
2549 if (attr
.HasFontFamily())
2550 node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily()));
2551 if (attr
.HasFontItalic())
2552 node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle()));
2553 if (attr
.HasFontWeight())
2554 node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight()));
2555 if (attr
.HasFontUnderlined())
2556 node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined()));
2557 if (attr
.HasFontFaceName())
2558 node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName());
2560 if (attr
.HasTextEffects())
2562 node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects()));
2563 node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags()));
2565 if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty())
2566 node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName());
2569 node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML?
2573 if (attr
.HasAlignment())
2574 node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment()));
2576 if (attr
.HasLeftIndent())
2578 node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent()));
2579 node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent()));
2582 if (attr
.HasRightIndent())
2583 node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent()));
2585 if (attr
.HasParagraphSpacingAfter())
2586 node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter()));
2588 if (attr
.HasParagraphSpacingBefore())
2589 node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore()));
2591 if (attr
.HasLineSpacing())
2592 node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing()));
2594 if (attr
.HasBulletStyle())
2595 node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle()));
2597 if (attr
.HasBulletNumber())
2598 node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber()));
2600 if (attr
.HasBulletText())
2602 // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character.
2603 // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1
2604 if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
))
2605 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0])));
2607 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText());
2609 if (!attr
.GetBulletFont().empty())
2610 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont());
2613 if (attr
.HasBulletName())
2614 node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName());
2616 if (!attr
.GetParagraphStyleName().empty())
2617 node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName());
2619 if (!attr
.GetListStyleName().empty())
2620 node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName());
2622 if (!attr
.GetTextBoxAttr().GetBoxStyleName().empty())
2623 node
->AddAttribute(wxT("boxstyle"), attr
.GetTextBoxAttr().GetBoxStyleName());
2629 for (i
= 0; i
< attr
.GetTabs().GetCount(); i
++)
2633 tabs
<< attr
.GetTabs()[i
];
2635 node
->AddAttribute(wxT("tabs"), tabs
);
2638 if (attr
.HasPageBreak())
2639 node
->AddAttribute(wxT("pagebreak"), wxT("1"));
2641 if (attr
.HasOutlineLevel())
2642 node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel()));
2645 AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins());
2646 AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding());
2647 AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition());
2648 AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder());
2649 AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline());
2650 AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth());
2651 AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetHeight());
2652 AddAttribute(node
, wxT("minwidth"), attr
.GetTextBoxAttr().GetMinSize().GetWidth());
2653 AddAttribute(node
, wxT("minheight"), attr
.GetTextBoxAttr().GetMinSize().GetHeight());
2654 AddAttribute(node
, wxT("maxwidth"), attr
.GetTextBoxAttr().GetMaxSize().GetWidth());
2655 AddAttribute(node
, wxT("maxheight"), attr
.GetTextBoxAttr().GetMaxSize().GetHeight());
2657 if (attr
.GetTextBoxAttr().HasVerticalAlignment())
2660 if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_TOP
)
2662 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_CENTRE
)
2663 value
= wxT("centre");
2664 else if (attr
.GetTextBoxAttr().GetVerticalAlignment() == wxTEXT_BOX_ATTR_VERTICAL_ALIGNMENT_BOTTOM
)
2665 value
= wxT("bottom");
2667 value
= wxT("none");
2668 AddAttribute(node
, wxT("verticalalignment"), value
);
2671 if (attr
.GetTextBoxAttr().HasFloatMode())
2674 if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
)
2675 value
= wxT("left");
2676 else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
)
2677 value
= wxT("right");
2679 value
= wxT("none");
2680 AddAttribute(node
, wxT("float"), value
);
2683 if (attr
.GetTextBoxAttr().HasClearMode())
2686 if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
)
2687 value
= wxT("left");
2688 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
)
2689 value
= wxT("right");
2690 else if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
)
2691 value
= wxT("both");
2693 value
= wxT("none");
2694 AddAttribute(node
, wxT("clear"), value
);
2697 if (attr
.GetTextBoxAttr().HasCollapseBorders())
2698 AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders());
2703 bool wxRichTextXMLHelper::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
)
2705 if (properties
.GetCount() > 0)
2707 wxXmlNode
* propertiesNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties"));
2708 node
->AddChild(propertiesNode
);
2710 for (i
= 0; i
< properties
.GetCount(); i
++)
2712 const wxVariant
& var
= properties
[i
];
2715 wxXmlNode
* propertyNode
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property"));
2716 propertiesNode
->AddChild(propertyNode
);
2718 const wxString
& name
= var
.GetName();
2719 wxString value
= MakeStringFromProperty(var
);
2721 AddAttribute(propertyNode
, wxT("name"), name
);
2722 AddAttribute(propertyNode
, wxT("type"), var
.GetType());
2723 AddAttribute(propertyNode
, wxT("value"), value
);
2731 // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT
2734 // wxUSE_RICHTEXT && wxUSE_XML