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