1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/richtext/richtextxml.cpp 
   3 // Purpose:     XML and HTML I/O for wxRichTextCtrl 
   4 // Author:      Julian Smart 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx.h". 
  13 #include "wx/wxprec.h" 
  19 #if wxUSE_RICHTEXT && wxUSE_XML 
  21 #include "wx/richtext/richtextxml.h" 
  25     #include "wx/module.h" 
  29 #include "wx/filename.h" 
  30 #include "wx/clipbrd.h" 
  31 #include "wx/wfstream.h" 
  32 #include "wx/sstream.h" 
  33 #include "wx/txtstrm.h" 
  34 #include "wx/mstream.h" 
  35 #include "wx/tokenzr.h" 
  36 #include "wx/stopwatch.h" 
  37 #include "wx/xml/xml.h" 
  39 // Set to 1 for slower wxXmlDocument method, 0 for faster direct method. 
  40 // If we make wxXmlDocument::Save more efficient, we might switch to this 
  42 #define wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT 0 
  44 #if wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
  45 #   error Must define wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT in richtextxml.h to use this method. 
  48 #if !wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT && !wxRICHTEXT_HAVE_DIRECT_OUTPUT 
  49 #   error Must define wxRICHTEXT_HAVE_DIRECT_OUTPUT in richtextxml.h to use this method. 
  52 // Set to 1 to time file saving 
  53 #define wxRICHTEXT_USE_OUTPUT_TIMINGS 0 
  55 // Convert a colour to a 6-digit hex string 
  56 static wxString 
ColourToHexString(const wxColour
& col
) 
  60     hex 
+= wxDecToHex(col
.Red()); 
  61     hex 
+= wxDecToHex(col
.Green()); 
  62     hex 
+= wxDecToHex(col
.Blue()); 
  67 // Convert 6-digit hex string to a colour 
  68 static wxColour 
HexStringToColour(const wxString
& hex
) 
  70     unsigned char r 
= (unsigned char)wxHexToDec(hex
.Mid(0, 2)); 
  71     unsigned char g 
= (unsigned char)wxHexToDec(hex
.Mid(2, 2)); 
  72     unsigned char b 
= (unsigned char)wxHexToDec(hex
.Mid(4, 2)); 
  74     return wxColour(r
, g
, b
); 
  77 static inline wxString 
MakeString(const int& v
) { return wxString::Format(wxT("%d"), v
); } 
  78 static inline wxString 
MakeString(const long& v
) { return wxString::Format(wxT("%ld"), v
); } 
  79 static inline wxString 
MakeString(const double& v
) { return wxString::Format(wxT("%.2f"), (float) v
); } 
  80 static inline wxString 
MakeString(const wxString
& s
) { return s
; } 
  81 static inline wxString 
MakeString(const wxColour
& col
) { return wxT("#") + ColourToHexString(col
); } 
  83 static inline void AddString(wxString
& str
, const int& v
) { str 
<< wxString::Format(wxT("%d"), v
); } 
  84 static inline void AddString(wxString
& str
, const long& v
) { str 
<< wxString::Format(wxT("%ld"), v
); } 
  85 static inline void AddString(wxString
& str
, const double& v
) { str 
<< wxString::Format(wxT("%.2f"), (float) v
); } 
  86 static inline void AddString(wxString
& str
, const wxChar
* s
) { str 
<< s
; } 
  87 static inline void AddString(wxString
& str
, const wxString
& s
) { str 
<< s
; } 
  88 static inline void AddString(wxString
& str
, const wxColour
& col
) { str 
<< wxT("#") << ColourToHexString(col
); } 
  90 IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler
, wxRichTextFileHandler
) 
  92 void wxRichTextXMLHandler::Init() 
  94 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
 102 bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer 
*buffer
, wxInputStream
& stream
) 
 107     buffer
->ResetAndClearCommands(); 
 110     wxXmlDocument
* xmlDoc 
= new wxXmlDocument
; 
 113     // This is the encoding to convert to (memory encoding rather than file encoding) 
 114     wxString 
encoding(wxT("UTF-8")); 
 116 #if !wxUSE_UNICODE && wxUSE_INTL 
 117     encoding 
= wxLocale::GetSystemEncodingName(); 
 120     if (!xmlDoc
->Load(stream
, encoding
)) 
 122         buffer
->ResetAndClearCommands(); 
 127         if (xmlDoc
->GetRoot() && xmlDoc
->GetRoot()->GetType() == wxXML_ELEMENT_NODE 
&& xmlDoc
->GetRoot()->GetName() == wxT("richtext")) 
 129             wxXmlNode
* child 
= xmlDoc
->GetRoot()->GetChildren(); 
 132                 if (child
->GetType() == wxXML_ELEMENT_NODE
) 
 134                     wxString name 
= child
->GetName(); 
 135                     if (name 
== wxT("richtext-version")) 
 139                         ImportXML(buffer
, buffer
, child
); 
 142                 child 
= child
->GetNext(); 
 153     buffer
->UpdateRanges(); 
 158 /// Creates an object given an XML element name 
 159 wxRichTextObject
* wxRichTextXMLHandler::CreateObjectForXMLName(wxRichTextObject
* WXUNUSED(parent
), const wxString
& name
) const 
 161     if (name 
== wxT("text") || name 
== wxT("symbol")) 
 162         return new wxRichTextPlainText
; 
 163     else if (name 
== wxT("image")) 
 164         return new wxRichTextImage
; 
 165     else if (name 
== wxT("paragraph")) 
 166         return new wxRichTextParagraph
; 
 167     else if (name 
== wxT("paragraphlayout")) 
 168         return new wxRichTextParagraphLayoutBox
; 
 173 /// Recursively import an object 
 174 bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer
* buffer
, wxRichTextObject
* obj
, wxXmlNode
* node
) 
 176     obj
->ImportFromXML(buffer
, node
, this); 
 178     wxRichTextCompositeObject
* compositeParent 
= wxDynamicCast(obj
, wxRichTextCompositeObject
); 
 181         wxXmlNode
* child 
= node
->GetChildren(); 
 184             if (child
->GetName() == wxT("stylesheet")) 
 186                 if (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
) 
 188                     wxRichTextStyleSheet
* sheet 
= new wxRichTextStyleSheet
; 
 189                     wxString sheetName 
= child
->GetAttribute(wxT("name"), wxEmptyString
); 
 190                     wxString sheetDescription 
= child
->GetAttribute(wxT("description"), wxEmptyString
); 
 191                     sheet
->SetName(sheetName
); 
 192                     sheet
->SetDescription(sheetDescription
); 
 194                     wxXmlNode
* child2 
= child
->GetChildren(); 
 197                         ImportStyleDefinition(sheet
, child2
); 
 199                         child2 
= child2
->GetNext(); 
 202                     // Notify that styles have changed. If this is vetoed by the app, 
 203                     // the new sheet will be deleted. If it is not vetoed, the 
 204                     // old sheet will be deleted and replaced with the new one. 
 205                     buffer
->SetStyleSheetAndNotify(sheet
); 
 210                 wxRichTextObject
* childObj 
= CreateObjectForXMLName(obj
, child
->GetName()); 
 213                     compositeParent
->AppendChild(childObj
); 
 214                     ImportXML(buffer
, childObj
, child
); 
 217             child 
= child
->GetNext(); 
 224 bool wxRichTextXMLHandler::ImportProperties(wxRichTextObject
* obj
, wxXmlNode
* node
) 
 226     wxXmlNode
* child 
= node
->GetChildren(); 
 229         if (child
->GetName() == wxT("properties")) 
 231             wxXmlNode
* propertyChild 
= child
->GetChildren(); 
 232             while (propertyChild
) 
 234                 if (propertyChild
->GetName() == wxT("property")) 
 236                     wxString name 
= propertyChild
->GetAttribute(wxT("name"), wxEmptyString
); 
 237                     wxString value 
= propertyChild
->GetAttribute(wxT("value"), wxEmptyString
); 
 238                     wxString type 
= propertyChild
->GetAttribute(wxT("type"), wxEmptyString
); 
 240                     wxVariant var 
= MakePropertyFromString(name
, value
, type
); 
 243                         obj
->GetProperties().SetProperty(var
); 
 246                 propertyChild 
= propertyChild
->GetNext(); 
 249         child 
= child
->GetNext(); 
 254 bool wxRichTextXMLHandler::ImportStyleDefinition(wxRichTextStyleSheet
* sheet
, wxXmlNode
* node
) 
 256     wxString styleType 
= node
->GetName(); 
 257     wxString styleName 
= node
->GetAttribute(wxT("name"), wxEmptyString
); 
 258     wxString baseStyleName 
= node
->GetAttribute(wxT("basestyle"), wxEmptyString
); 
 260     if (styleName
.empty()) 
 263     if (styleType 
== wxT("characterstyle")) 
 265         wxRichTextCharacterStyleDefinition
* def 
= new wxRichTextCharacterStyleDefinition(styleName
); 
 266         def
->SetBaseStyle(baseStyleName
); 
 268         wxXmlNode
* child 
= node
->GetChildren(); 
 271             if (child
->GetName() == wxT("style")) 
 274                 ImportStyle(attr
, child
, false); 
 277             child 
= child
->GetNext(); 
 280         sheet
->AddCharacterStyle(def
); 
 282     else if (styleType 
== wxT("paragraphstyle")) 
 284         wxRichTextParagraphStyleDefinition
* def 
= new wxRichTextParagraphStyleDefinition(styleName
); 
 286         wxString nextStyleName 
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
); 
 287         def
->SetNextStyle(nextStyleName
); 
 288         def
->SetBaseStyle(baseStyleName
); 
 290         wxXmlNode
* child 
= node
->GetChildren(); 
 293             if (child
->GetName() == wxT("style")) 
 296                 ImportStyle(attr
, child
, true); 
 299             child 
= child
->GetNext(); 
 302         sheet
->AddParagraphStyle(def
); 
 304     else if (styleType 
== wxT("liststyle")) 
 306         wxRichTextListStyleDefinition
* def 
= new wxRichTextListStyleDefinition(styleName
); 
 308         wxString nextStyleName 
= node
->GetAttribute(wxT("nextstyle"), wxEmptyString
); 
 309         def
->SetNextStyle(nextStyleName
); 
 310         def
->SetBaseStyle(baseStyleName
); 
 312         wxXmlNode
* child 
= node
->GetChildren(); 
 315             if (child
->GetName() == wxT("style")) 
 318                 ImportStyle(attr
, child
, true); 
 320                 wxString styleLevel 
= child
->GetAttribute(wxT("level"), wxEmptyString
); 
 321                 if (styleLevel
.empty()) 
 327                     int level 
= wxAtoi(styleLevel
); 
 328                     if (level 
> 0 && level 
<= 10) 
 330                         def
->SetLevelAttributes(level
-1, attr
); 
 334             child 
= child
->GetNext(); 
 337         sheet
->AddListStyle(def
); 
 343 //----------------------------------------------------------------------------- 
 344 //  xml support routines 
 345 //----------------------------------------------------------------------------- 
 347 bool wxRichTextXMLHandler::HasParam(wxXmlNode
* node
, const wxString
& param
) 
 349     return (GetParamNode(node
, param
) != NULL
); 
 352 wxXmlNode 
*wxRichTextXMLHandler::GetParamNode(wxXmlNode
* node
, const wxString
& param
) 
 354     wxCHECK_MSG(node
, NULL
, wxT("You can't access node data before it was initialized!")); 
 356     wxXmlNode 
*n 
= node
->GetChildren(); 
 360         if (n
->GetType() == wxXML_ELEMENT_NODE 
&& n
->GetName() == param
) 
 368 wxString 
wxRichTextXMLHandler::GetNodeContent(wxXmlNode 
*node
) 
 371     if (n 
== NULL
) return wxEmptyString
; 
 372     n 
= n
->GetChildren(); 
 376         if (n
->GetType() == wxXML_TEXT_NODE 
|| 
 377             n
->GetType() == wxXML_CDATA_SECTION_NODE
) 
 378             return n
->GetContent(); 
 381     return wxEmptyString
; 
 385 wxString 
wxRichTextXMLHandler::GetParamValue(wxXmlNode 
*node
, const wxString
& param
) 
 388         return GetNodeContent(node
); 
 390         return GetNodeContent(GetParamNode(node
, param
)); 
 393 wxString 
wxRichTextXMLHandler::GetText(wxXmlNode 
*node
, const wxString
& param
, bool WXUNUSED(translate
)) 
 395     wxXmlNode 
*parNode 
= GetParamNode(node
, param
); 
 398     wxString 
str1(GetNodeContent(parNode
)); 
 402 // For use with earlier versions of wxWidgets 
 403 #ifndef WXUNUSED_IN_UNICODE 
 405 #define WXUNUSED_IN_UNICODE(x) WXUNUSED(x) 
 407 #define WXUNUSED_IN_UNICODE(x) x 
 411 // write string to output 
 412 inline static void OutputString(wxOutputStream
& stream
, const wxString
& str
, 
 413                                 wxMBConv 
*WXUNUSED_IN_UNICODE(convMem
), wxMBConv 
*convFile
) 
 415     if (str
.empty()) return; 
 419         const wxWX2MBbuf 
buf(str
.mb_str(*convFile
)); 
 420         stream
.Write((const char*)buf
, strlen((const char*)buf
)); 
 424         const wxWX2MBbuf 
buf(str
.mb_str(wxConvUTF8
)); 
 425         stream
.Write((const char*)buf
, strlen((const char*)buf
)); 
 428     if ( convFile 
== NULL 
) 
 429         stream
.Write(str
.mb_str(), str
.Len()); 
 432         wxString 
str2(str
.wc_str(*convMem
), *convFile
); 
 433         stream
.Write(str2
.mb_str(), str2
.Len()); 
 438 static void OutputIndentation(wxOutputStream
& stream
, int indent
) 
 440     wxString str 
= wxT("\n"); 
 441     for (int i 
= 0; i 
< indent
; i
++) 
 442         str 
<< wxT(' ') << wxT(' '); 
 443     ::OutputString(stream
, str
, NULL
, NULL
); 
 446 // Same as above, but create entities first. 
 447 // Translates '<' to "<", '>' to ">" and '&' to "&" 
 448 static void OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
, 
 449                             wxMBConv 
*convMem 
= NULL
, wxMBConv 
*convFile 
= NULL
) 
 457     for (i 
= 0; i 
< len
; i
++) 
 461         // Original code excluded "&" but we _do_ want to convert 
 462         // the ampersand beginning & because otherwise when read in, 
 463         // the original "&" becomes "&". 
 465         if (c 
== wxT('<') || c 
== wxT('>') || c 
== wxT('"') || 
 466             (c 
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ )) 
 468             OutputString(stream
, str
.Mid(last
, i 
- last
), convMem
, convFile
); 
 472                 OutputString(stream
, wxT("<"), NULL
, NULL
); 
 475                 OutputString(stream
, wxT(">"), NULL
, NULL
); 
 478                 OutputString(stream
, wxT("&"), NULL
, NULL
); 
 481                 OutputString(stream
, wxT("""), NULL
, NULL
); 
 487         else if (wxUChar(c
) > 127) 
 489             OutputString(stream
, str
.Mid(last
, i 
- last
), convMem
, convFile
); 
 491             wxString 
s(wxT("&#")); 
 495             s 
<< (int) wxUChar(c
); 
 498             OutputString(stream
, s
, NULL
, NULL
); 
 502     OutputString(stream
, str
.Mid(last
, i 
- last
), convMem
, convFile
); 
 505 void wxRichTextXMLHandler::OutputString(wxOutputStream
& stream
, const wxString
& str
) 
 507     ::OutputString(stream
, str
, m_convMem
, m_convFile
); 
 510 void wxRichTextXMLHandler::OutputStringEnt(wxOutputStream
& stream
, const wxString
& str
) 
 512     ::OutputStringEnt(stream
, str
, m_convMem
, m_convFile
); 
 515 void wxRichTextXMLHandler::OutputIndentation(wxOutputStream
& stream
, int indent
) 
 517     wxString str 
= wxT("\n"); 
 518     for (int i 
= 0; i 
< indent
; i
++) 
 519         str 
<< wxT(' ') << wxT(' '); 
 520     ::OutputString(stream
, str
, NULL
, NULL
); 
 523 wxString 
wxRichTextXMLHandler::AttributeToXML(const wxString
& str
) 
 531     for (i 
= 0; i 
< len
; i
++) 
 535         // Original code excluded "&" but we _do_ want to convert 
 536         // the ampersand beginning & because otherwise when read in, 
 537         // the original "&" becomes "&". 
 539         if (c 
== wxT('<') || c 
== wxT('>') || c 
== wxT('"') || 
 540             (c 
== wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ )) 
 542             str1 
+= str
.Mid(last
, i 
- last
); 
 552                 str1 
+= wxT("&"); 
 555                 str1 
+= wxT("""); 
 561         else if (wxUChar(c
) > 127) 
 563             str1 
+= str
.Mid(last
, i 
- last
); 
 565             wxString 
s(wxT("&#")); 
 569             s 
<< (int) wxUChar(c
); 
 576     str1 
+= str
.Mid(last
, i 
- last
); 
 580 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
 582 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const int& v
) 
 584     str 
<< wxT(" ") << name 
<< wxT("=\"") << wxString::Format(wxT("%d"), v
) << wxT("\""); 
 587 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const long& v
) 
 589     str 
<< wxT(" ") << name 
<< wxT("=\"") << wxString::Format(wxT("%ld"), v
) << wxT("\""); 
 592 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const double& v
) 
 594     str 
<< wxT(" ") << name 
<< wxT("=\"") << wxString::Format(wxT("%.2f"), (float) v
) << wxT("\""); 
 597 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const wxChar
* s
) 
 599     str 
<< wxT(" ") << name 
<< wxT("=\"") << s 
<< wxT("\""); 
 602 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const wxString
& s
) 
 604     str 
<< wxT(" ") << name 
<< wxT("=\"") << s 
<< wxT("\""); 
 607 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const wxColour
& col
) 
 609     str 
<< wxT(" ") << name 
<< wxT("=\"") << wxT("#") << ColourToHexString(col
) << wxT("\""); 
 612 static inline void AddAttribute(wxString
& str
, const wxChar
* name
, const wxTextAttrDimension
& dim
) 
 616         wxString value 
= MakeString(dim
.GetValue()) + wxT(",") + MakeString((int) dim
.GetFlags()); 
 617         str 
<< wxT(" ") << name 
<< wxT("=\""); 
 623 static inline void AddAttribute(wxString
& str
, const wxChar
* rootName
, const wxTextAttrDimensions
& dims
) 
 625     if (dims
.GetLeft().IsPresent()) 
 626         AddAttribute(str
, rootName 
+ wxString(wxT("-left")), dims
.GetLeft()); 
 627     if (dims
.GetRight().IsPresent()) 
 628         AddAttribute(str
, rootName 
+ wxString(wxT("-right")), dims
.GetRight()); 
 629     if (dims
.GetTop().IsPresent()) 
 630         AddAttribute(str
, rootName 
+ wxString(wxT("-top")), dims
.GetTop()); 
 631     if (dims
.GetBottom().IsPresent()) 
 632         AddAttribute(str
, rootName 
+ wxString(wxT("-bottom")), dims
.GetBottom()); 
 635 static inline void AddAttribute(wxString
& str
, const wxChar
* rootName
, const wxTextAttrBorder
& border
) 
 637     if (border
.HasStyle()) 
 638         AddAttribute(str
, rootName 
+ wxString(wxT("-style")), border
.GetStyle()); 
 639     if (border
.HasColour()) 
 640         AddAttribute(str
, rootName 
+ wxString(wxT("-color")), border
.GetColour()); 
 641     if (border
.HasWidth()) 
 642         AddAttribute(str
, rootName 
+ wxString(wxT("-width")), border
.GetWidth()); 
 645 static inline void AddAttribute(wxString
& str
, const wxChar
* rootName
, const wxTextAttrBorders
& borders
) 
 647     AddAttribute(str
, rootName 
+ wxString(wxT("-left")), borders
.GetLeft()); 
 648     AddAttribute(str
, rootName 
+ wxString(wxT("-right")), borders
.GetRight()); 
 649     AddAttribute(str
, rootName 
+ wxString(wxT("-top")), borders
.GetTop()); 
 650     AddAttribute(str
, rootName 
+ wxString(wxT("-bottom")), borders
.GetBottom()); 
 654     // wxRICHTEXT_HAVE_DIRECT_OUTPUT 
 656 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
 658 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const int& v
) 
 660     node
->AddAttribute(name
, MakeString(v
)); 
 663 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const long& v
) 
 665     node
->AddAttribute(name
, MakeString(v
)); 
 668 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const double& v
) 
 670     node
->AddAttribute(name
, MakeString(v
)); 
 673 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const wxString
& s
) 
 675     node
->AddAttribute(name
, s
); 
 678 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const wxColour
& col
) 
 680     node
->AddAttribute(name
, MakeString(col
)); 
 683 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* name
, const wxTextAttrDimension
& dim
) 
 687         wxString value 
= MakeString(dim
.GetValue()) + wxT(",") + MakeString(dim
.GetFlags()); 
 688         AddAttribute(node
, name
, value
); 
 692 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* rootName
, const wxTextAttrDimensions
& dims
) 
 694     if (dims
.GetLeft().IsPresent()) 
 695         AddAttribute(node
, rootName 
+ wxString(wxT("-left")), dims
.GetLeft()); 
 696     if (dims
.GetRight().IsPresent()) 
 697         AddAttribute(node
, rootName 
+ wxString(wxT("-right")), dims
.GetRight()); 
 698     if (dims
.GetTop().IsPresent()) 
 699         AddAttribute(node
, rootName 
+ wxString(wxT("-top")), dims
.GetTop()); 
 700     if (dims
.GetBottom().IsPresent()) 
 701         AddAttribute(node
, rootName 
+ wxString(wxT("-bottom")), dims
.GetBottom()); 
 704 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* rootName
, const wxTextAttrBorder
& border
) 
 706     if (border
.HasStyle()) 
 707         AddAttribute(node
, rootName 
+ wxString(wxT("-style")), border
.GetStyle()); 
 708     if (border
.HasColour()) 
 709         AddAttribute(node
, rootName 
+ wxString(wxT("-color")), border
.GetColour()); 
 710     if (border
.HasWidth()) 
 711         AddAttribute(node
, rootName 
+ wxString(wxT("-width")), border
.GetWidth()); 
 714 static inline void AddAttribute(wxXmlNode
* node
, const wxChar
* rootName
, const wxTextAttrBorders
& borders
) 
 716     AddAttribute(node
, rootName 
+ wxString(wxT("-left")), borders
.GetLeft()); 
 717     AddAttribute(node
, rootName 
+ wxString(wxT("-right")), borders
.GetRight()); 
 718     AddAttribute(node
, rootName 
+ wxString(wxT("-top")), borders
.GetTop()); 
 719     AddAttribute(node
, rootName 
+ wxString(wxT("-bottom")), borders
.GetBottom()); 
 722     // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
 724 bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer 
*buffer
, wxOutputStream
& stream
) 
 729     wxString 
version(wxT("1.0") ) ; 
 731     bool deleteConvFile 
= false; 
 732     wxString fileEncoding
; 
 733     //wxMBConv* convFile = NULL; 
 736     fileEncoding 
= wxT("UTF-8"); 
 737     m_convFile 
= & wxConvUTF8
; 
 739     fileEncoding 
= wxT("ISO-8859-1"); 
 740     m_convFile 
= & wxConvISO8859_1
; 
 743     // If SetEncoding has been called, change the output encoding. 
 744     if (!m_encoding
.empty() && m_encoding
.Lower() != fileEncoding
.Lower()) 
 746         if (m_encoding 
== wxT("<System>")) 
 749             fileEncoding 
= wxLocale::GetSystemEncodingName(); 
 750             // if !wxUSE_INTL, we fall back to UTF-8 or ISO-8859-1 below 
 755             fileEncoding 
= m_encoding
; 
 758         // GetSystemEncodingName may not have returned a name 
 759         if (fileEncoding
.empty()) 
 761             fileEncoding 
= wxT("UTF-8"); 
 763             fileEncoding 
= wxT("ISO-8859-1"); 
 765         m_convFile 
= new wxCSConv(fileEncoding
); 
 766         deleteConvFile 
= true; 
 769 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT 
 770 #if wxRICHTEXT_USE_OUTPUT_TIMINGS 
 771     wxStopWatch stopwatch
; 
 773     wxXmlDocument
* doc 
= new wxXmlDocument
; 
 774     doc
->SetFileEncoding(fileEncoding
); 
 776     wxXmlNode
* rootNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("richtext")); 
 777     doc
->SetRoot(rootNode
); 
 778     rootNode
->AddAttribute(wxT("version"), wxT("1.0.0.0")); 
 779     rootNode
->AddAttribute(wxT("xmlns"), wxT("http://www.wxwidgets.org")); 
 781     if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
)) 
 783         wxXmlNode
* styleSheetNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("stylesheet")); 
 784         rootNode
->AddChild(styleSheetNode
); 
 786         wxString nameAndDescr
; 
 788         if (!buffer
->GetStyleSheet()->GetName().empty()) 
 789             styleSheetNode
->AddAttribute(wxT("name"), buffer
->GetStyleSheet()->GetName()); 
 791         if (!buffer
->GetStyleSheet()->GetDescription().empty()) 
 792             styleSheetNode
->AddAttribute(wxT("description"), buffer
->GetStyleSheet()->GetDescription()); 
 795         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++) 
 797             wxRichTextCharacterStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetCharacterStyle(i
); 
 798             ExportStyleDefinition(styleSheetNode
, def
); 
 801         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++) 
 803             wxRichTextParagraphStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetParagraphStyle(i
); 
 804             ExportStyleDefinition(styleSheetNode
, def
); 
 807         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++) 
 809             wxRichTextListStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetListStyle(i
); 
 810             ExportStyleDefinition(styleSheetNode
, def
); 
 813     bool success 
= ExportXML(rootNode
, *buffer
); 
 814 #if wxRICHTEXT_USE_OUTPUT_TIMINGS 
 815     long t 
= stopwatch
.Time(); 
 816     wxLogDebug(wxT("Creating the document took %ldms"), t
); 
 817     wxMessageBox(wxString::Format(wxT("Creating the document took %ldms"), t
)); 
 821 #if wxRICHTEXT_USE_OUTPUT_TIMINGS 
 824         success 
= doc
->Save(stream
); 
 825 #if wxRICHTEXT_USE_OUTPUT_TIMINGS 
 827         wxLogDebug(wxT("Save() took %ldms"), t2
); 
 828         wxMessageBox(wxString::Format(wxT("Save() took %ldms"), t2
)); 
 835     // !(wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT && wxRICHTEXT_USE_XMLDOCUMENT_OUTPUT) 
 838     m_convMem 
= wxConvCurrent
; 
 844     s
.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"), 
 845              version
, fileEncoding
); 
 846     OutputString(stream
, s
); 
 847     OutputString(stream
, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">")); 
 851     if (buffer
->GetStyleSheet() && (GetFlags() & wxRICHTEXT_HANDLER_INCLUDE_STYLESHEET
)) 
 853         OutputIndentation(stream
, level
); 
 854         wxString nameAndDescr
; 
 855         if (!buffer
->GetStyleSheet()->GetName().empty()) 
 856             nameAndDescr 
<< wxT(" name=\"") << buffer
->GetStyleSheet()->GetName() << wxT("\""); 
 857         if (!buffer
->GetStyleSheet()->GetDescription().empty()) 
 858             nameAndDescr 
<< wxT(" description=\"") << buffer
->GetStyleSheet()->GetDescription() << wxT("\""); 
 859         OutputString(stream
, wxString(wxT("<stylesheet")) + nameAndDescr 
+ wxT(">")); 
 863         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetCharacterStyleCount(); i
++) 
 865             wxRichTextCharacterStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetCharacterStyle(i
); 
 866             ExportStyleDefinition(stream
, def
, level 
+ 1); 
 869         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetParagraphStyleCount(); i
++) 
 871             wxRichTextParagraphStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetParagraphStyle(i
); 
 872             ExportStyleDefinition(stream
, def
, level 
+ 1); 
 875         for (i 
= 0; i 
< (int) buffer
->GetStyleSheet()->GetListStyleCount(); i
++) 
 877             wxRichTextListStyleDefinition
* def 
= buffer
->GetStyleSheet()->GetListStyle(i
); 
 878             ExportStyleDefinition(stream
, def
, level 
+ 1); 
 881         OutputIndentation(stream
, level
); 
 882         OutputString(stream
, wxT("</stylesheet>")); 
 886     bool success 
= ExportXML(stream
, *buffer
, level
); 
 888     OutputString(stream
, wxT("\n</richtext>")); 
 889     OutputString(stream
, wxT("\n")); 
 900 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
 902 /// Recursively export an object 
 903 bool wxRichTextXMLHandler::ExportXML(wxOutputStream
& stream
, wxRichTextObject
& obj
, int indent
) 
 905     obj
.ExportXML(stream
, indent
, this); 
 910 bool wxRichTextXMLHandler::ExportStyleDefinition(wxOutputStream
& stream
, wxRichTextStyleDefinition
* def
, int level
) 
 912     wxRichTextCharacterStyleDefinition
* charDef 
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
); 
 913     wxRichTextParagraphStyleDefinition
* paraDef 
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
); 
 914     wxRichTextListStyleDefinition
* listDef 
= wxDynamicCast(def
, wxRichTextListStyleDefinition
); 
 916     wxString baseStyle 
= def
->GetBaseStyle(); 
 917     wxString baseStyleProp
; 
 918     if (!baseStyle
.empty()) 
 919         baseStyleProp 
= wxT(" basestyle=\"") + baseStyle 
+ wxT("\""); 
 921     wxString descr 
= def
->GetDescription(); 
 924         descrProp 
= wxT(" description=\"") + descr 
+ wxT("\""); 
 928         OutputIndentation(stream
, level
); 
 929         OutputString(stream
, wxT("<characterstyle") + baseStyleProp 
+ descrProp 
+ wxT(">")); 
 933         wxString style 
= AddAttributes(def
->GetStyle(), false); 
 935         OutputIndentation(stream
, level
); 
 936         OutputString(stream
, wxT("<style ") + style 
+ wxT(">")); 
 938         OutputIndentation(stream
, level
); 
 939         OutputString(stream
, wxT("</style>")); 
 943         OutputIndentation(stream
, level
); 
 944         OutputString(stream
, wxT("</characterstyle>")); 
 948         OutputIndentation(stream
, level
); 
 950         if (!listDef
->GetNextStyle().empty()) 
 951             baseStyleProp 
<< wxT(" nextstyle=\"") << listDef
->GetNextStyle() << wxT("\""); 
 953         OutputString(stream
, wxT("<liststyle") + baseStyleProp 
+ descrProp 
+ wxT(">")); 
 957         wxString style 
= AddAttributes(def
->GetStyle(), true); 
 959         OutputIndentation(stream
, level
); 
 960         OutputString(stream
, wxT("<style ") + style 
+ wxT(">")); 
 962         OutputIndentation(stream
, level
); 
 963         OutputString(stream
, wxT("</style>")); 
 966         for (i 
= 0; i 
< 10; i 
++) 
 968             wxRichTextAttr
* levelAttr 
= listDef
->GetLevelAttributes(i
); 
 971                 wxString style 
= AddAttributes(def
->GetStyle(), true); 
 972                 wxString levelStr 
= wxString::Format(wxT(" level=\"%d\" "), (i
+1)); 
 974                 OutputIndentation(stream
, level
); 
 975                 OutputString(stream
, wxT("<style ") + levelStr 
+ style 
+ wxT(">")); 
 977                 OutputIndentation(stream
, level
); 
 978                 OutputString(stream
, wxT("</style>")); 
 984         OutputIndentation(stream
, level
); 
 985         OutputString(stream
, wxT("</liststyle>")); 
 989         OutputIndentation(stream
, level
); 
 991         if (!paraDef
->GetNextStyle().empty()) 
 992             baseStyleProp 
<< wxT(" nextstyle=\"") << paraDef
->GetNextStyle() << wxT("\""); 
 994         OutputString(stream
, wxT("<paragraphstyle") + baseStyleProp 
+ descrProp 
+ wxT(">")); 
 998         wxString style 
= AddAttributes(def
->GetStyle(), false); 
1000         OutputIndentation(stream
, level
); 
1001         OutputString(stream
, wxT("<style ") + style 
+ wxT(">")); 
1003         OutputIndentation(stream
, level
); 
1004         OutputString(stream
, wxT("</style>")); 
1008         OutputIndentation(stream
, level
); 
1009         OutputString(stream
, wxT("</paragraphstyle>")); 
1015 /// Create a string containing style attributes 
1016 wxString 
wxRichTextXMLHandler::AddAttributes(const wxRichTextAttr
& attr
, bool isPara
) 
1019     if (attr
.HasTextColour() && attr
.GetTextColour().Ok()) 
1020         AddAttribute(str
, wxT("textcolor"), attr
.GetTextColour()); 
1022     if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().Ok()) 
1023         AddAttribute(str
, wxT("bgcolor"), attr
.GetBackgroundColour()); 
1025     if (attr
.HasFontSize()) 
1026         AddAttribute(str
, wxT("fontsize"), attr
.GetFontSize()); 
1028     if (attr
.HasFontFamily()) 
1029         AddAttribute(str
, wxT("fontfamily"), attr
.GetFontFamily()); 
1031     if (attr
.HasFontItalic()) 
1032         AddAttribute(str
, wxT("fontstyle"), attr
.GetFontStyle()); 
1034     if (attr
.HasFontWeight()) 
1035         AddAttribute(str
, wxT("fontweight"), attr
.GetFontWeight()); 
1037     if (attr
.HasFontUnderlined()) 
1038         AddAttribute(str
, wxT("fontunderlined"), (int) attr
.GetFontUnderlined()); 
1040     if (attr
.HasFontFaceName()) 
1041         AddAttribute(str
, wxT("fontface"), attr
.GetFontFaceName()); 
1043     if (attr
.HasTextEffects()) 
1045         AddAttribute(str
, wxT("texteffects"), attr
.GetTextEffects()); 
1046         AddAttribute(str
, wxT("texteffectflags"), attr
.GetTextEffectFlags()); 
1049     if (!attr
.GetCharacterStyleName().empty()) 
1050         AddAttribute(str
, wxT("characterstyle"), attr
.GetCharacterStyleName()); 
1053         AddAttribute(str
, wxT("url"), AttributeToXML(attr
.GetURL())); 
1057         if (attr
.HasAlignment()) 
1058             AddAttribute(str
, wxT("alignment"), (int) attr
.GetAlignment()); 
1060         if (attr
.HasLeftIndent()) 
1062             AddAttribute(str
, wxT("leftindent"), (int) attr
.GetLeftIndent()); 
1063             AddAttribute(str
, wxT("leftsubindent"), (int) attr
.GetLeftSubIndent()); 
1066         if (attr
.HasRightIndent()) 
1067             AddAttribute(str
, wxT("rightindent"), (int) attr
.GetRightIndent()); 
1069         if (attr
.HasParagraphSpacingAfter()) 
1070             AddAttribute(str
, wxT("parspacingafter"), (int) attr
.GetParagraphSpacingAfter()); 
1072         if (attr
.HasParagraphSpacingBefore()) 
1073             AddAttribute(str
, wxT("parspacingbefore"), (int) attr
.GetParagraphSpacingBefore()); 
1075         if (attr
.HasLineSpacing()) 
1076             AddAttribute(str
, wxT("linespacing"), (int) attr
.GetLineSpacing()); 
1078         if (attr
.HasBulletStyle()) 
1079             AddAttribute(str
, wxT("bulletstyle"), (int) attr
.GetBulletStyle()); 
1081         if (attr
.HasBulletNumber()) 
1082             AddAttribute(str
, wxT("bulletnumber"), (int) attr
.GetBulletNumber()); 
1084         if (attr
.HasBulletText()) 
1086             // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character. 
1087             // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1 
1088             if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)) 
1089                 AddAttribute(str
, wxT("bulletsymbol"), (int) (attr
.GetBulletText()[0])); 
1091                 AddAttribute(str
, wxT("bullettext"), attr
.GetBulletText()); 
1093             AddAttribute(str
, wxT("bulletfont"), attr
.GetBulletFont()); 
1096         if (attr
.HasBulletName()) 
1097             AddAttribute(str
, wxT("bulletname"), attr
.GetBulletName()); 
1099         if (!attr
.GetParagraphStyleName().empty()) 
1100             AddAttribute(str
, wxT("parstyle"), attr
.GetParagraphStyleName()); 
1102         if (!attr
.GetListStyleName().empty()) 
1103             AddAttribute(str
, wxT("liststyle"), attr
.GetListStyleName()); 
1109             for (i 
= 0; i 
< attr
.GetTabs().GetCount(); i
++) 
1111                 if (i 
> 0) strTabs 
<< wxT(","); 
1112                 strTabs 
<< attr
.GetTabs()[i
]; 
1114             AddAttribute(str
, wxT("tabs"), strTabs
); 
1117         if (attr
.HasPageBreak()) 
1119             AddAttribute(str
, wxT("pagebreak"), 1); 
1122         if (attr
.HasOutlineLevel()) 
1123             AddAttribute(str
, wxT("outlinelevel"), (int) attr
.GetOutlineLevel()); 
1126     AddAttribute(str
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins()); 
1127     AddAttribute(str
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding()); 
1128     AddAttribute(str
, wxT("position"), attr
.GetTextBoxAttr().GetPosition()); 
1129     AddAttribute(str
, wxT("border"), attr
.GetTextBoxAttr().GetBorder()); 
1130     AddAttribute(str
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline()); 
1131     AddAttribute(str
, wxT("width"), attr
.GetTextBoxAttr().GetWidth()); 
1132     AddAttribute(str
, wxT("height"), attr
.GetTextBoxAttr().GetWidth()); 
1134     if (attr
.GetTextBoxAttr().HasFloatMode()) 
1137         if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
) 
1138             value 
= wxT("left"); 
1139         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
) 
1140             value 
= wxT("right"); 
1142             value 
= wxT("none"); 
1143         AddAttribute(str
, wxT("float"), value
); 
1146     if (attr
.GetTextBoxAttr().HasClearMode()) 
1149         if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
) 
1150             value 
= wxT("left"); 
1151         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
) 
1152             value 
= wxT("right"); 
1153         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
) 
1154             value 
= wxT("both"); 
1156             value 
= wxT("none"); 
1157         AddAttribute(str
, wxT("clear"), value
); 
1160     if (attr
.GetTextBoxAttr().HasCollapseBorders()) 
1161         AddAttribute(str
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders()); 
1166 // Make a string from the given property. This can be overridden for custom variants. 
1167 wxString 
wxRichTextXMLHandler::MakeStringFromProperty(const wxVariant
& var
) 
1169     return var
.MakeString(); 
1172 // Create a proprty from the string read from the XML file. 
1173 wxVariant 
wxRichTextXMLHandler::MakePropertyFromString(const wxString
& name
, const wxString
& value
, const wxString
& WXUNUSED(type
)) 
1175     wxVariant 
var(value
, name
); 
1176     // TODO: use type to create using common types 
1180 // Write the properties 
1181 bool wxRichTextXMLHandler::WriteProperties(wxOutputStream
& stream
, const wxRichTextProperties
& properties
, int level
) 
1183     if (properties
.GetCount() > 0) 
1187         OutputIndentation(stream
, level
); 
1188         OutputString(stream
, wxT("<properties")); 
1193         for (i 
= 0; i 
< properties
.GetCount(); i
++) 
1195             const wxVariant
& var 
= properties
[i
]; 
1198                 const wxString
& name 
= var
.GetName(); 
1199                 wxString value 
= MakeStringFromProperty(var
); 
1201                 OutputIndentation(stream
, level
); 
1202                 OutputString(stream
, wxT("<property name=\"") + name 
+ 
1203                     wxT("\" type=\"") + var
.GetType() + wxT("\" value=\"")); 
1204                 OutputStringEnt(stream
, value
); 
1205                 OutputString(stream
, wxT("\"/>\n")); 
1211         OutputIndentation(stream
, level
); 
1212         OutputString(stream
, wxT("</properties>\n")); 
1222     // wxRICHTEXT_HAVE_DIRECT_OUTPUT 
1224 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
1225 bool wxRichTextXMLHandler::ExportXML(wxXmlNode
* parent
, wxRichTextObject
& obj
) 
1227     obj
.ExportXML(parent
, this); 
1232 bool wxRichTextXMLHandler::ExportStyleDefinition(wxXmlNode
* parent
, wxRichTextStyleDefinition
* def
) 
1234     wxRichTextCharacterStyleDefinition
* charDef 
= wxDynamicCast(def
, wxRichTextCharacterStyleDefinition
); 
1235     wxRichTextParagraphStyleDefinition
* paraDef 
= wxDynamicCast(def
, wxRichTextParagraphStyleDefinition
); 
1236     wxRichTextListStyleDefinition
* listDef 
= wxDynamicCast(def
, wxRichTextListStyleDefinition
); 
1238     wxString baseStyle 
= def
->GetBaseStyle(); 
1239     wxString descr 
= def
->GetDescription(); 
1241     wxXmlNode
* defNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxEmptyString
); 
1242     parent
->AddChild(defNode
); 
1243     if (!baseStyle
.empty()) 
1244         defNode
->AddAttribute(wxT("basestyle"), baseStyle
); 
1246         defNode
->AddAttribute(wxT("description"), descr
); 
1248     wxXmlNode
* styleNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style")); 
1249     defNode
->AddChild(styleNode
); 
1253         defNode
->SetName(wxT("characterstyle")); 
1254         AddAttributes(styleNode
, def
->GetStyle(), false); 
1258         defNode
->SetName(wxT("liststyle")); 
1260         if (!listDef
->GetNextStyle().empty()) 
1261             defNode
->AddAttribute(wxT("nextstyle"), listDef
->GetNextStyle()); 
1263         AddAttributes(styleNode
, def
->GetStyle(), true); 
1266         for (i 
= 0; i 
< 10; i 
++) 
1268             wxRichTextAttr
* levelAttr 
= listDef
->GetLevelAttributes(i
); 
1271                 wxXmlNode
* levelNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("style")); 
1272                 defNode
->AddChild(levelNode
); 
1273                 levelNode
->AddAttribute(wxT("level"), MakeString(i
+1)); 
1274                 AddAttributes(levelNode
, * levelAttr
, true); 
1280         defNode
->SetName(wxT("paragraphstyle")); 
1282         if (!paraDef
->GetNextStyle().empty()) 
1283             defNode
->AddAttribute(wxT("nextstyle"), paraDef
->GetNextStyle()); 
1285         AddAttributes(styleNode
, def
->GetStyle(), true); 
1291 bool wxRichTextXMLHandler::AddAttributes(wxXmlNode
* node
, wxRichTextAttr
& attr
, bool isPara
) 
1293     if (attr
.HasTextColour() && attr
.GetTextColour().Ok()) 
1294         node
->AddAttribute(wxT("textcolor"), MakeString(attr
.GetTextColour())); 
1295     if (attr
.HasBackgroundColour() && attr
.GetBackgroundColour().Ok()) 
1296         node
->AddAttribute(wxT("bgcolor"), MakeString(attr
.GetBackgroundColour())); 
1298     if (attr
.HasFontSize()) 
1299         node
->AddAttribute(wxT("fontsize"), MakeString(attr
.GetFontSize())); 
1300     if (attr
.HasFontFamily()) 
1301         node
->AddAttribute(wxT("fontfamily"), MakeString(attr
.GetFontFamily())); 
1302     if (attr
.HasFontItalic()) 
1303         node
->AddAttribute(wxT("fontstyle"), MakeString(attr
.GetFontStyle())); 
1304     if (attr
.HasFontWeight()) 
1305         node
->AddAttribute(wxT("fontweight"), MakeString(attr
.GetFontWeight())); 
1306     if (attr
.HasFontUnderlined()) 
1307         node
->AddAttribute(wxT("fontunderlined"), MakeString((int) attr
.GetFontUnderlined())); 
1308     if (attr
.HasFontFaceName()) 
1309         node
->AddAttribute(wxT("fontface"), attr
.GetFontFaceName()); 
1311     if (attr
.HasTextEffects()) 
1313         node
->AddAttribute(wxT("texteffects"), MakeString(attr
.GetTextEffects())); 
1314         node
->AddAttribute(wxT("texteffectflags"), MakeString(attr
.GetTextEffectFlags())); 
1316     if (attr
.HasCharacterStyleName() && !attr
.GetCharacterStyleName().empty()) 
1317         node
->AddAttribute(wxT("characterstyle"), attr
.GetCharacterStyleName()); 
1320         node
->AddAttribute(wxT("url"), attr
.GetURL()); // TODO: do we need to wrap this in AttributeToXML? 
1324         if (attr
.HasAlignment()) 
1325             node
->AddAttribute(wxT("alignment"), MakeString((int) attr
.GetAlignment())); 
1327         if (attr
.HasLeftIndent()) 
1329             node
->AddAttribute(wxT("leftindent"), MakeString((int) attr
.GetLeftIndent())); 
1330             node
->AddAttribute(wxT("leftsubindent"), MakeString((int) attr
.GetLeftSubIndent())); 
1333         if (attr
.HasRightIndent()) 
1334             node
->AddAttribute(wxT("rightindent"), MakeString((int) attr
.GetRightIndent())); 
1336         if (attr
.HasParagraphSpacingAfter()) 
1337             node
->AddAttribute(wxT("parspacingafter"), MakeString((int) attr
.GetParagraphSpacingAfter())); 
1339         if (attr
.HasParagraphSpacingBefore()) 
1340             node
->AddAttribute(wxT("parspacingbefore"), MakeString((int) attr
.GetParagraphSpacingBefore())); 
1342         if (attr
.HasLineSpacing()) 
1343             node
->AddAttribute(wxT("linespacing"), MakeString((int) attr
.GetLineSpacing())); 
1345         if (attr
.HasBulletStyle()) 
1346             node
->AddAttribute(wxT("bulletstyle"), MakeString((int) attr
.GetBulletStyle())); 
1348         if (attr
.HasBulletNumber()) 
1349             node
->AddAttribute(wxT("bulletnumber"), MakeString((int) attr
.GetBulletNumber())); 
1351         if (attr
.HasBulletText()) 
1353             // If using a bullet symbol, convert to integer in case it's a non-XML-friendly character. 
1354             // Otherwise, assume it's XML-friendly text such as outline numbering, e.g. 1.2.3.1 
1355             if (!attr
.GetBulletText().empty() && (attr
.GetBulletStyle() & wxTEXT_ATTR_BULLET_STYLE_SYMBOL
)) 
1356                 node
->AddAttribute(wxT("bulletsymbol"), MakeString((int) (attr
.GetBulletText()[0]))); 
1358                 node
->AddAttribute(wxT("bullettext"), attr
.GetBulletText()); 
1360             if (!attr
.GetBulletFont().empty()) 
1361                 node
->AddAttribute(wxT("bulletfont"), attr
.GetBulletFont()); 
1364         if (attr
.HasBulletName()) 
1365             node
->AddAttribute(wxT("bulletname"), attr
.GetBulletName()); 
1367         if (!attr
.GetParagraphStyleName().empty()) 
1368             node
->AddAttribute(wxT("parstyle"), attr
.GetParagraphStyleName()); 
1370         if (!attr
.GetListStyleName().empty()) 
1371             node
->AddAttribute(wxT("liststyle"), attr
.GetListStyleName()); 
1377             for (i 
= 0; i 
< attr
.GetTabs().GetCount(); i
++) 
1381                 tabs 
<< attr
.GetTabs()[i
]; 
1383             node
->AddAttribute(wxT("tabs"), tabs
); 
1386         if (attr
.HasPageBreak()) 
1387             node
->AddAttribute(wxT("pagebreak"), wxT("1")); 
1389         if (attr
.HasOutlineLevel()) 
1390             node
->AddAttribute(wxT("outlinelevel"), MakeString((int) attr
.GetOutlineLevel())); 
1393     AddAttribute(node
, wxT("margin"), attr
.GetTextBoxAttr().GetMargins()); 
1394     AddAttribute(node
, wxT("padding"), attr
.GetTextBoxAttr().GetPadding()); 
1395     AddAttribute(node
, wxT("position"), attr
.GetTextBoxAttr().GetPosition()); 
1396     AddAttribute(node
, wxT("border"), attr
.GetTextBoxAttr().GetBorder()); 
1397     AddAttribute(node
, wxT("outline"), attr
.GetTextBoxAttr().GetOutline()); 
1398     AddAttribute(node
, wxT("width"), attr
.GetTextBoxAttr().GetWidth()); 
1399     AddAttribute(node
, wxT("height"), attr
.GetTextBoxAttr().GetWidth()); 
1401     if (attr
.GetTextBoxAttr().HasFloatMode()) 
1404         if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_LEFT
) 
1405             value 
= wxT("left"); 
1406         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_FLOAT_RIGHT
) 
1407             value 
= wxT("right"); 
1409             value 
= wxT("none"); 
1410         AddAttribute(node
, wxT("float"), value
); 
1413     if (attr
.GetTextBoxAttr().HasClearMode()) 
1416         if (attr
.GetTextBoxAttr().GetClearMode() == wxTEXT_BOX_ATTR_CLEAR_LEFT
) 
1417             value 
= wxT("left"); 
1418         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_RIGHT
) 
1419             value 
= wxT("right"); 
1420         else if (attr
.GetTextBoxAttr().GetFloatMode() == wxTEXT_BOX_ATTR_CLEAR_BOTH
) 
1421             value 
= wxT("both"); 
1423             value 
= wxT("none"); 
1424         AddAttribute(node
, wxT("clear"), value
); 
1427     if (attr
.GetTextBoxAttr().HasCollapseBorders()) 
1428         AddAttribute(node
, wxT("collapse-borders"), (int) attr
.GetTextBoxAttr().GetCollapseBorders()); 
1433 bool wxRichTextXMLHandler::WriteProperties(wxXmlNode
* node
, const wxRichTextProperties
& properties
) 
1435     if (properties
.GetCount() > 0) 
1437         wxXmlNode
* propertiesNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("properties")); 
1438         node
->AddChild(propertiesNode
); 
1440         for (i 
= 0; i 
< properties
.GetCount(); i
++) 
1442             const wxVariant
& var 
= properties
[i
]; 
1445                 wxXmlNode
* propertyNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("property")); 
1446                 propertiesNode
->AddChild(propertyNode
); 
1448                 const wxString
& name 
= var
.GetName(); 
1449                 wxString value 
= MakeStringFromProperty(var
); 
1451                 AddAttribute(propertyNode
, wxT("name"), name
); 
1452                 AddAttribute(propertyNode
, wxT("type"), var
.GetType()); 
1453                 AddAttribute(propertyNode
, wxT("value"), value
); 
1461     // wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
1463 /// Replace face name with current name for platform. 
1464 /// TODO: introduce a virtual function or settable table to 
1465 /// do this comprehensively. 
1466 bool wxRichTextFixFaceName(wxString
& facename
) 
1468     if (facename
.empty()) 
1472     if (facename 
== wxT("Times")) 
1474         facename 
= wxT("Times New Roman"); 
1477     else if (facename 
== wxT("Helvetica")) 
1479         facename 
= wxT("Arial"); 
1482     else if (facename 
== wxT("Courier")) 
1484         facename 
= wxT("Courier New"); 
1490     if (facename 
== wxT("Times New Roman")) 
1492         facename 
= wxT("Times"); 
1495     else if (facename 
== wxT("Arial")) 
1497         facename 
= wxT("Helvetica"); 
1500     else if (facename 
== wxT("Courier New")) 
1502         facename 
= wxT("Courier"); 
1510 static inline long wxRichTextColourStringToLong(const wxString
& colStr
) 
1512     if (!colStr
.IsEmpty()) 
1514         wxColour 
col(colStr
); 
1515         return col
.GetRGB(); 
1521 static inline wxTextAttrDimension 
wxRichTextParseDimension(const wxString
& dimStr
) 
1523     wxString valuePart 
= dimStr
.BeforeFirst(wxT(',')); 
1525     if (dimStr
.Contains(wxT(","))) 
1526         flagsPart 
= dimStr
.AfterFirst(wxT(',')); 
1527     wxTextAttrDimension dim
; 
1528     dim
.SetValue(wxAtoi(valuePart
)); 
1529     dim
.SetFlags(wxAtoi(flagsPart
)); 
1534 /// Import style parameters 
1535 bool wxRichTextXMLHandler::ImportStyle(wxRichTextAttr
& attr
, wxXmlNode
* node
, bool isPara
) 
1537     wxXmlAttribute
* xmlAttr 
= node
->GetAttributes(); 
1541         const wxString
& name 
= xmlAttr
->GetName(); 
1542         const wxString
& value 
= xmlAttr
->GetValue(); 
1545         if (name 
== wxT("fontface")) 
1550                 if (GetFlags() & wxRICHTEXT_HANDLER_CONVERT_FACENAMES
) 
1551                     wxRichTextFixFaceName(v
); 
1552                 attr
.SetFontFaceName(v
); 
1555         else if (name 
== wxT("fontfamily")) 
1558                 attr
.SetFontFamily((wxFontFamily
)wxAtoi(value
)); 
1560         else if (name 
== wxT("fontstyle")) 
1563                 attr
.SetFontStyle((wxFontStyle
)wxAtoi(value
)); 
1565         else if (name 
== wxT("fontsize")) 
1568                 attr
.SetFontSize(wxAtoi(value
)); 
1570         else if (name 
== wxT("fontweight")) 
1573                 attr
.SetFontWeight((wxFontWeight
) wxAtoi(value
)); 
1575         else if (name 
== wxT("fontunderlined")) 
1578                 attr
.SetFontUnderlined(wxAtoi(value
) != 0); 
1580         else if (name 
== wxT("textcolor")) 
1584                 if (value
[0] == wxT('#')) 
1585                     attr
.SetTextColour(HexStringToColour(value
.Mid(1))); 
1587                     attr
.SetTextColour(value
); 
1590         else if (name 
== wxT("bgcolor")) 
1594                 if (value
[0] == wxT('#')) 
1595                     attr
.SetBackgroundColour(HexStringToColour(value
.Mid(1))); 
1597                     attr
.SetBackgroundColour(value
); 
1600         else if (name 
== wxT("characterstyle")) 
1603                 attr
.SetCharacterStyleName(value
); 
1605         else if (name 
== wxT("texteffects")) 
1608                 attr
.SetTextEffects(wxAtoi(value
)); 
1610         else if (name 
== wxT("texteffectflags")) 
1613                 attr
.SetTextEffectFlags(wxAtoi(value
)); 
1615         else if (name 
== wxT("url")) 
1622             if (name 
== wxT("alignment")) 
1625                     attr
.SetAlignment((wxTextAttrAlignment
) wxAtoi(value
)); 
1627             else if (name 
== wxT("leftindent")) 
1630                     attr
.SetLeftIndent(wxAtoi(value
), attr
.GetLeftSubIndent()); 
1632             else if (name 
== wxT("leftsubindent")) 
1635                     attr
.SetLeftIndent(attr
.GetLeftIndent(), wxAtoi(value
)); 
1637             else if (name 
== wxT("rightindent")) 
1640                     attr
.SetRightIndent(wxAtoi(value
)); 
1642             else if (name 
== wxT("parspacingbefore")) 
1645                     attr
.SetParagraphSpacingBefore(wxAtoi(value
)); 
1647             else if (name 
== wxT("parspacingafter")) 
1650                     attr
.SetParagraphSpacingAfter(wxAtoi(value
)); 
1652             else if (name 
== wxT("linespacing")) 
1655                     attr
.SetLineSpacing(wxAtoi(value
)); 
1657             else if (name 
== wxT("bulletstyle")) 
1660                     attr
.SetBulletStyle(wxAtoi(value
)); 
1662             else if (name 
== wxT("bulletnumber")) 
1665                     attr
.SetBulletNumber(wxAtoi(value
)); 
1667             else if (name 
== wxT("bulletsymbol")) 
1671                     wxChar ch 
= wxAtoi(value
); 
1674                     attr
.SetBulletText(s
); 
1677             else if (name 
== wxT("bullettext")) 
1681                     attr
.SetBulletText(value
); 
1684             else if (name 
== wxT("bulletfont")) 
1688                     attr
.SetBulletFont(value
); 
1691             else if (name 
== wxT("bulletname")) 
1695                     attr
.SetBulletName(value
); 
1698             else if (name 
== wxT("parstyle")) 
1702                     attr
.SetParagraphStyleName(value
); 
1705             else if (name 
== wxT("liststyle")) 
1709                     attr
.SetListStyleName(value
); 
1712             else if (name 
== wxT("tabs")) 
1717                     wxStringTokenizer 
tkz(value
, wxT(",")); 
1718                     while (tkz
.HasMoreTokens()) 
1720                         wxString token 
= tkz
.GetNextToken(); 
1721                         tabs
.Add(wxAtoi(token
)); 
1726             else if (name 
== wxT("pagebreak")) 
1730                     attr
.SetPageBreak(wxAtoi(value
) != 0); 
1733             else if (name 
== wxT("outlinelevel")) 
1737                     attr
.SetOutlineLevel(wxAtoi(value
)); 
1750             if (name 
== wxT("width")) 
1752                 attr
.GetTextBoxAttr().GetWidth().SetValue(wxRichTextParseDimension(value
)); 
1754             else if (name 
== wxT("height")) 
1756                 attr
.GetTextBoxAttr().GetHeight().SetValue(wxRichTextParseDimension(value
)); 
1759             else if (name 
== wxT("float")) 
1761                 if (value 
== wxT("left")) 
1762                     attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_LEFT
); 
1763                 else if (value 
== wxT("right")) 
1764                     attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_RIGHT
); 
1765                 else if (value 
== wxT("none")) 
1766                     attr
.GetTextBoxAttr().SetFloatMode(wxTEXT_BOX_ATTR_FLOAT_NONE
); 
1768             else if (name 
== wxT("clear")) 
1770                 if (value 
== wxT("left")) 
1771                     attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_LEFT
); 
1772                 else if (value 
== wxT("right")) 
1773                     attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_RIGHT
); 
1774                 else if (value 
== wxT("both")) 
1775                     attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_BOTH
); 
1776                 else if (value 
== wxT("none")) 
1777                     attr
.GetTextBoxAttr().SetClearMode(wxTEXT_BOX_ATTR_CLEAR_NONE
); 
1779             else if (name 
== wxT("collapse-borders")) 
1780                 attr
.GetTextBoxAttr().SetCollapseBorders(value 
== wxT("1")); 
1782             else if (name
.Contains(wxT("border-"))) 
1784                 if (name 
== wxT("border-left-style")) 
1785                     attr
.GetTextBoxAttr().GetBorder().GetLeft().SetStyle(wxAtoi(value
)); 
1786                 else if (name 
== wxT("border-right-style")) 
1787                     attr
.GetTextBoxAttr().GetBorder().GetRight().SetStyle(wxAtoi(value
)); 
1788                 else if (name 
== wxT("border-top-style")) 
1789                     attr
.GetTextBoxAttr().GetBorder().GetTop().SetStyle(wxAtoi(value
)); 
1790                 else if (name 
== wxT("border-bottom-style")) 
1791                     attr
.GetTextBoxAttr().GetBorder().GetBottom().SetStyle(wxAtoi(value
)); 
1793                 else if (name 
== wxT("border-left-colour")) 
1794                     attr
.GetTextBoxAttr().GetBorder().GetLeft().SetColour(wxRichTextColourStringToLong(value
)); 
1795                 else if (name 
== wxT("border-right-colour")) 
1796                     attr
.GetTextBoxAttr().GetBorder().GetRight().SetColour(wxRichTextColourStringToLong(value
)); 
1797                 else if (name 
== wxT("border-top-colour")) 
1798                     attr
.GetTextBoxAttr().GetBorder().GetTop().SetColour(wxRichTextColourStringToLong(value
)); 
1799                 else if (name 
== wxT("border-bottom-colour")) 
1800                     attr
.GetTextBoxAttr().GetBorder().GetBottom().SetColour(wxRichTextColourStringToLong(value
)); 
1802                 else if (name 
== wxT("border-left-width")) 
1803                     attr
.GetTextBoxAttr().GetBorder().GetLeft().SetWidth(wxRichTextParseDimension(value
)); 
1804                 else if (name 
== wxT("border-right-width")) 
1805                     attr
.GetTextBoxAttr().GetBorder().GetRight().SetWidth(wxRichTextParseDimension(value
)); 
1806                 else if (name 
== wxT("border-top-width")) 
1807                     attr
.GetTextBoxAttr().GetBorder().GetTop().SetWidth(wxRichTextParseDimension(value
)); 
1808                 else if (name 
== wxT("border-bottom-width")) 
1809                     attr
.GetTextBoxAttr().GetBorder().GetBottom().SetWidth(wxRichTextParseDimension(value
)); 
1811             else if (name
.Contains(wxT("outline-"))) 
1813                 if (name 
== wxT("outline-left-style")) 
1814                     attr
.GetTextBoxAttr().GetOutline().GetLeft().SetStyle(wxAtoi(value
)); 
1815                 else if (name 
== wxT("outline-right-style")) 
1816                     attr
.GetTextBoxAttr().GetOutline().GetRight().SetStyle(wxAtoi(value
)); 
1817                 else if (name 
== wxT("outline-top-style")) 
1818                     attr
.GetTextBoxAttr().GetOutline().GetTop().SetStyle(wxAtoi(value
)); 
1819                 else if (name 
== wxT("outline-bottom-style")) 
1820                     attr
.GetTextBoxAttr().GetOutline().GetBottom().SetStyle(wxAtoi(value
)); 
1822                 else if (name 
== wxT("outline-left-colour")) 
1823                     attr
.GetTextBoxAttr().GetOutline().GetLeft().SetColour(wxRichTextColourStringToLong(value
)); 
1824                 else if (name 
== wxT("outline-right-colour")) 
1825                     attr
.GetTextBoxAttr().GetOutline().GetRight().SetColour(wxRichTextColourStringToLong(value
)); 
1826                 else if (name 
== wxT("outline-top-colour")) 
1827                     attr
.GetTextBoxAttr().GetOutline().GetTop().SetColour(wxRichTextColourStringToLong(value
)); 
1828                 else if (name 
== wxT("outline-bottom-colour")) 
1829                     attr
.GetTextBoxAttr().GetOutline().GetBottom().SetColour(wxRichTextColourStringToLong(value
)); 
1831                 else if (name 
== wxT("outline-left-width")) 
1832                     attr
.GetTextBoxAttr().GetOutline().GetLeft().SetWidth(wxRichTextParseDimension(value
)); 
1833                 else if (name 
== wxT("outline-right-width")) 
1834                     attr
.GetTextBoxAttr().GetOutline().GetRight().SetWidth(wxRichTextParseDimension(value
)); 
1835                 else if (name 
== wxT("outline-top-width")) 
1836                     attr
.GetTextBoxAttr().GetOutline().GetTop().SetWidth(wxRichTextParseDimension(value
)); 
1837                 else if (name 
== wxT("outline-bottom-width")) 
1838                     attr
.GetTextBoxAttr().GetOutline().GetBottom().SetWidth(wxRichTextParseDimension(value
)); 
1840             else if (name
.Contains(wxT("margin-"))) 
1842                 if (name 
== wxT("margin-left")) 
1843                     attr
.GetTextBoxAttr().GetMargins().GetLeft().SetValue(wxRichTextParseDimension(value
)); 
1844                 else if (name 
== wxT("margin-right")) 
1845                     attr
.GetTextBoxAttr().GetMargins().GetRight().SetValue(wxRichTextParseDimension(value
)); 
1846                 else if (name 
== wxT("margin-top")) 
1847                     attr
.GetTextBoxAttr().GetMargins().GetTop().SetValue(wxRichTextParseDimension(value
)); 
1848                 else if (name 
== wxT("margin-bottom")) 
1849                     attr
.GetTextBoxAttr().GetMargins().GetBottom().SetValue(wxRichTextParseDimension(value
)); 
1851             else if (name
.Contains(wxT("padding-"))) 
1853                 if (name 
== wxT("padding-left")) 
1854                     attr
.GetTextBoxAttr().GetPadding().GetLeft().SetValue(wxRichTextParseDimension(value
)); 
1855                 else if (name 
== wxT("padding-right")) 
1856                     attr
.GetTextBoxAttr().GetPadding().GetRight().SetValue(wxRichTextParseDimension(value
)); 
1857                 else if (name 
== wxT("padding-top")) 
1858                     attr
.GetTextBoxAttr().GetPadding().GetTop().SetValue(wxRichTextParseDimension(value
)); 
1859                 else if (name 
== wxT("padding-bottom")) 
1860                     attr
.GetTextBoxAttr().GetPadding().GetBottom().SetValue(wxRichTextParseDimension(value
)); 
1862             else if (name
.Contains(wxT("position-"))) 
1864                 if (name 
== wxT("position-left")) 
1865                     attr
.GetTextBoxAttr().GetPosition().GetLeft().SetValue(wxRichTextParseDimension(value
)); 
1866                 else if (name 
== wxT("position-right")) 
1867                     attr
.GetTextBoxAttr().GetPosition().GetRight().SetValue(wxRichTextParseDimension(value
)); 
1868                 else if (name 
== wxT("position-top")) 
1869                     attr
.GetTextBoxAttr().GetPosition().GetTop().SetValue(wxRichTextParseDimension(value
)); 
1870                 else if (name 
== wxT("position-bottom")) 
1871                     attr
.GetTextBoxAttr().GetPosition().GetBottom().SetValue(wxRichTextParseDimension(value
)); 
1875         xmlAttr 
= xmlAttr
->GetNext(); 
1884 // Import this object from XML 
1885 bool wxRichTextObject::ImportFromXML(wxRichTextBuffer
* WXUNUSED(buffer
), wxXmlNode
* node
, wxRichTextXMLHandler
* handler
) 
1887     handler
->ImportProperties(this, node
); 
1888     handler
->ImportStyle(GetAttributes(), node
, UsesParagraphAttributes()); 
1893 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
1894 // Export this object directly to the given stream. 
1895 bool wxRichTextObject::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
) 
1897     ::OutputIndentation(stream
, indent
); 
1898     ::OutputString(stream
, wxT("<") + GetXMLNodeName(), handler
->GetConvMem(), handler
->GetConvFile()); 
1900     wxString style 
= handler
->AddAttributes(GetAttributes(), true); 
1902     ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
1904     if (GetProperties().GetCount() > 0) 
1906         handler
->WriteProperties(stream
, GetProperties(), indent
); 
1909     wxRichTextCompositeObject
* composite 
= wxDynamicCast(this, wxRichTextCompositeObject
); 
1913         for (i 
= 0; i 
< composite
->GetChildCount(); i
++) 
1915             wxRichTextObject
* child 
= composite
->GetChild(i
); 
1916             child
->ExportXML(stream
, indent
+1, handler
); 
1920     ::OutputIndentation(stream
, indent
); 
1921     ::OutputString(stream
, wxT("</") + GetXMLNodeName() + wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
1926 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
1927 // Export this object to the given parent node, usually creating at least one child node. 
1928 bool wxRichTextObject::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
) 
1930     wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, GetXMLNodeName()); 
1931     parent
->AddChild(elementNode
); 
1932     handler
->AddAttributes(elementNode
, GetAttributes(), true); 
1933     handler
->WriteProperties(elementNode
, GetProperties()); 
1935     wxRichTextCompositeObject
* composite 
= wxDynamicCast(this, wxRichTextCompositeObject
); 
1939         for (i 
= 0; i 
< composite
->GetChildCount(); i
++) 
1941             wxRichTextObject
* child 
= composite
->GetChild(i
); 
1942             child
->ExportXML(elementNode
, handler
); 
1950 // Import this object from XML 
1951 bool wxRichTextPlainText::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
) 
1953     wxRichTextObject::ImportFromXML(buffer
, node
, handler
); 
1955     if (node
->GetName() == wxT("text")) 
1958         wxXmlNode
* textChild 
= node
->GetChildren(); 
1961             if (textChild
->GetType() == wxXML_TEXT_NODE 
|| 
1962                 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
) 
1964                 wxString text2 
= textChild
->GetContent(); 
1966                 // Strip whitespace from end 
1967                 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('\n')) 
1968                     text2 
= text2
.Mid(0, text2
.length()-1); 
1970                 if (!text2
.empty() && text2
[0] == wxT('"')) 
1971                     text2 
= text2
.Mid(1); 
1972                 if (!text2
.empty() && text2
[text2
.length()-1] == wxT('"')) 
1973                     text2 
= text2
.Mid(0, text2
.length() - 1); 
1977             textChild 
= textChild
->GetNext(); 
1982     else if (node
->GetName() == wxT("symbol")) 
1984         // This is a symbol that XML can't read in the normal way 
1986         wxXmlNode
* textChild 
= node
->GetChildren(); 
1989             if (textChild
->GetType() == wxXML_TEXT_NODE 
|| 
1990                 textChild
->GetType() == wxXML_CDATA_SECTION_NODE
) 
1992                 wxString text2 
= textChild
->GetContent(); 
1995             textChild 
= textChild
->GetNext(); 
1998         wxString actualText
; 
1999         actualText 
<< (wxChar
) wxAtoi(text
); 
2000         SetText(actualText
); 
2008 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
2009 // Export this object directly to the given stream. 
2010 bool wxRichTextPlainText::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
) 
2012     wxString style 
= handler
->AddAttributes(GetAttributes(), false); 
2016     const wxString
& text 
= GetText(); 
2017     int len 
= (int) text
.Length(); 
2022         ::OutputIndentation(stream
, indent
); 
2023         ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile()); 
2024         ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2025         if (GetProperties().GetCount() > 0) 
2027             handler
->WriteProperties(stream
, GetProperties(), indent
); 
2028             ::OutputIndentation(stream
, indent
); 
2030         ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2032     else for (i 
= 0; i 
< len
; i
++) 
2035         int c 
= (int) text
[i
]; 
2037         int c 
= (int) wxUChar(text
[i
]); 
2039         if ((c 
< 32 || c 
== 34) && /* c != 9 && */ c 
!= 10 && c 
!= 13) 
2043                 wxString 
fragment(text
.Mid(last
, i
-last
)); 
2044                 if (!fragment
.empty()) 
2046                     ::OutputIndentation(stream
, indent
); 
2047                     ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile()); 
2049                     ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2051                     if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))) 
2053                         ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile()); 
2054                         ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile()); 
2055                         ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile()); 
2058                         ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile()); 
2060                     if (GetProperties().GetCount() > 0) 
2062                         handler
->WriteProperties(stream
, GetProperties(), indent
); 
2063                         ::OutputIndentation(stream
, indent
); 
2065                     ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2070             // Output this character as a number in a separate tag, because XML can't cope 
2071             // with entities below 32 except for 10 and 13 
2073             ::OutputIndentation(stream
, indent
); 
2074             ::OutputString(stream
, wxT("<symbol"), handler
->GetConvMem(), handler
->GetConvFile()); 
2076             ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2077             ::OutputString(stream
, wxString::Format(wxT("%d"), c
), handler
->GetConvMem(), handler
->GetConvFile()); 
2079             if (GetProperties().GetCount() > 0) 
2081                 handler
->WriteProperties(stream
, GetProperties(), indent
); 
2082                 ::OutputIndentation(stream
, indent
); 
2084             ::OutputString(stream
, wxT("</symbol>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2092         fragment 
= text
.Mid(last
, i
-last
); 
2096         ::OutputIndentation(stream
, indent
); 
2097         ::OutputString(stream
, wxT("<text"), handler
->GetConvMem(), handler
->GetConvFile()); 
2099         ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2101         if (GetProperties().GetCount() > 0) 
2103             handler
->WriteProperties(stream
, GetProperties(), indent
); 
2104             ::OutputIndentation(stream
, indent
); 
2107         if (!fragment
.empty() && (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' '))) 
2109             ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile()); 
2110             ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile()); 
2111             ::OutputString(stream
, wxT("\""), handler
->GetConvMem(), handler
->GetConvFile()); 
2114             ::OutputStringEnt(stream
, fragment
, handler
->GetConvMem(), handler
->GetConvFile()); 
2116         ::OutputString(stream
, wxT("</text>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2122 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
2123 // Export this object to the given parent node, usually creating at least one child node. 
2124 bool wxRichTextPlainText::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
) 
2128     const wxString
& text 
= GetText(); 
2129     int len 
= (int) text
.Length(); 
2135         wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text")); 
2136         parent
->AddChild(elementNode
); 
2138         handler
->AddAttributes(elementNode
, GetAttributes(), false); 
2139         handler
->WriteProperties(elementNode
, GetProperties()); 
2141     else for (i 
= 0; i 
< len
; i
++) 
2144         int c 
= (int) text
[i
]; 
2146         int c 
= (int) wxUChar(text
[i
]); 
2148         if ((c 
< 32 || c 
== 34) && c 
!= 10 && c 
!= 13) 
2152                 wxString 
fragment(text
.Mid(last
, i
-last
)); 
2153                 if (!fragment
.empty()) 
2155                     // TODO: I'm assuming wxXmlDocument will output quotes if necessary 
2156                     wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text")); 
2157                     parent
->AddChild(elementNode
); 
2158                     handler
->AddAttributes(elementNode
, GetAttributes(), false); 
2159                     handler
->WriteProperties(elementNode
, GetProperties()); 
2161                     wxXmlNode
* textNode 
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text")); 
2162                     elementNode
->AddChild(textNode
); 
2164                     if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')) 
2165                         fragment 
= wxT("\"") + fragment 
+ wxT("\""); 
2167                     textNode
->SetContent(fragment
); 
2172             // Output this character as a number in a separate tag, because XML can't cope 
2173             // with entities below 32 except for 10 and 13 
2175             wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("symbol")); 
2176             parent
->AddChild(elementNode
); 
2178             handler
->AddAttributes(elementNode
, GetAttributes(), false); 
2179             handler
->WriteProperties(elementNode
, GetProperties()); 
2181             wxXmlNode
* textNode 
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text")); 
2182             elementNode
->AddChild(textNode
); 
2183             textNode
->SetContent(wxString::Format(wxT("%d"), c
)); 
2193         fragment 
= text
.Mid(last
, i
-last
); 
2197         wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("text")); 
2198         parent
->AddChild(elementNode
); 
2199         handler
->AddAttributes(elementNode
, GetAttributes(), false); 
2201         wxXmlNode
* textNode 
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text")); 
2202         elementNode
->AddChild(textNode
); 
2204         if (fragment
[0] == wxT(' ') || fragment
[fragment
.length()-1] == wxT(' ')) 
2205             fragment 
= wxT("\"") + fragment 
+ wxT("\""); 
2207         textNode
->SetContent(fragment
);             
2214 // Import this object from XML 
2215 bool wxRichTextImage::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
) 
2217     wxRichTextObject::ImportFromXML(buffer
, node
, handler
); 
2219     wxBitmapType imageType 
= wxBITMAP_TYPE_PNG
; 
2220     wxString value 
= node
->GetAttribute(wxT("imagetype"), wxEmptyString
); 
2223         int type 
= wxAtoi(value
); 
2225         // note: 0 == wxBITMAP_TYPE_INVALID 
2226         if (type 
<= 0 || type 
>= wxBITMAP_TYPE_MAX
) 
2228             wxLogWarning("Invalid bitmap type specified for <image> tag: %d", type
); 
2232             imageType 
= (wxBitmapType
)type
; 
2238     wxXmlNode
* imageChild 
= node
->GetChildren(); 
2241         wxString childName 
= imageChild
->GetName(); 
2242         if (childName 
== wxT("data")) 
2244             wxXmlNode
* dataChild 
= imageChild
->GetChildren(); 
2247                 data 
= dataChild
->GetContent(); 
2248                 // wxLogDebug(data); 
2249                 dataChild 
= dataChild
->GetNext(); 
2253         imageChild 
= imageChild
->GetNext(); 
2258         wxStringInputStream 
strStream(data
); 
2260         GetImageBlock().ReadHex(strStream
, data
.length(), imageType
); 
2268 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
2269 // Export this object directly to the given stream. 
2270 bool wxRichTextImage::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
) 
2272     wxString style 
= handler
->AddAttributes(GetAttributes(), false); 
2274     ::OutputIndentation(stream
, indent
); 
2275     ::OutputString(stream
, wxT("<image"), handler
->GetConvMem(), handler
->GetConvFile()); 
2276     if (!GetImageBlock().Ok()) 
2279         ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2283         ::OutputString(stream
, wxString::Format(wxT(" imagetype=\"%d\""), (int) GetImageBlock().GetImageType()) + style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2285     if (GetProperties().GetCount() > 0) 
2287         handler
->WriteProperties(stream
, GetProperties(), indent
); 
2288         ::OutputIndentation(stream
, indent
); 
2291     ::OutputIndentation(stream
, indent
+1); 
2292     ::OutputString(stream
, wxT("<data>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2294     // wxStopWatch stopwatch; 
2296     GetImageBlock().WriteHex(stream
); 
2298     // wxLogDebug(wxT("Image conversion to hex took %ldms"), stopwatch.Time()); 
2300     ::OutputString(stream
, wxT("</data>\n"), handler
->GetConvMem(), handler
->GetConvFile()); 
2301     ::OutputIndentation(stream
, indent
); 
2302     ::OutputString(stream
, wxT("</image>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2307 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
2308 // Export this object to the given parent node, usually creating at least one child node. 
2309 bool wxRichTextImage::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
) 
2311     wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("image")); 
2312     parent
->AddChild(elementNode
); 
2314     if (GetImageBlock().Ok()) 
2315         elementNode
->AddAttribute(wxT("imagetype"), MakeString((int) GetImageBlock().GetImageType())); 
2317     handler
->AddAttributes(elementNode
, GetAttributes(), false); 
2318     handler
->WriteProperties(elementNode
, GetProperties()); 
2320     wxXmlNode
* dataNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("data")); 
2321     elementNode
->AddChild(dataNode
); 
2322     wxXmlNode
* textNode 
= new wxXmlNode(wxXML_TEXT_NODE
, wxT("text")); 
2323     dataNode
->AddChild(textNode
); 
2328         wxMemoryOutputStream stream
; 
2329         if (GetImageBlock().WriteHex(stream
)) 
2331             if (stream
.GetSize() > 0) 
2333                 int size 
= stream
.GetSize(); 
2334                 int size2 
= stream
.GetOutputStreamBuffer()->GetIntPosition(); 
2335                 wxASSERT(size 
== size2
); 
2337                 unsigned char* data 
= new unsigned char[size
]; 
2338                 stream
.CopyTo(data
, size
); 
2339                 strData 
= wxString((const char*) data
, wxConvUTF8
, size
); 
2343                 strData 
= wxEmptyString
; 
2349         wxStringOutputStream 
strStream(& strData
); 
2350         GetImageBlock().WriteHex(strStream
);         
2354     textNode
->SetContent(strData
); 
2355     textNode
->SetNoConversion(true); // optimize speed 
2362 // Import this object from XML 
2363 bool wxRichTextParagraphLayoutBox::ImportFromXML(wxRichTextBuffer
* buffer
, wxXmlNode
* node
, wxRichTextXMLHandler
* handler
) 
2365     wxRichTextObject::ImportFromXML(buffer
, node
, handler
); 
2367     wxString partial 
= node
->GetAttribute(wxT("partialparagraph"), wxEmptyString
); 
2368     if (partial 
== wxT("true")) 
2369         SetPartialParagraph(true); 
2374 #if wxRICHTEXT_HAVE_DIRECT_OUTPUT 
2375 // Export this object directly to the given stream. 
2376 bool wxRichTextParagraphLayoutBox::ExportXML(wxOutputStream
& stream
, int indent
, wxRichTextXMLHandler
* handler
) 
2378     ::OutputIndentation(stream
, indent
); 
2379     ::OutputString(stream
, wxT("<paragraphlayout"), handler
->GetConvMem(), handler
->GetConvFile()); 
2381     wxString style 
= handler
->AddAttributes(GetAttributes(), true); 
2383     if (GetPartialParagraph()) 
2384         style 
<< wxT(" partialparagraph=\"true\""); 
2386     ::OutputString(stream
, style 
+ wxT(">"), handler
->GetConvMem(), handler
->GetConvFile()); 
2388     if (GetProperties().GetCount() > 0) 
2390         handler
->WriteProperties(stream
, GetProperties(), indent
); 
2394     for (i 
= 0; i 
< GetChildCount(); i
++) 
2396         wxRichTextObject
* child 
= GetChild(i
); 
2397         child
->ExportXML(stream
, indent
+1, handler
); 
2400     ::OutputIndentation(stream
, indent
); 
2401     ::OutputString(stream
, wxT("</paragraphlayout>"), handler
->GetConvMem(), handler
->GetConvFile()); 
2406 #if wxRICHTEXT_HAVE_XMLDOCUMENT_OUTPUT 
2407 // Export this object to the given parent node, usually creating at least one child node. 
2408 bool wxRichTextParagraphLayoutBox::ExportXML(wxXmlNode
* parent
, wxRichTextXMLHandler
* handler
) 
2410     wxXmlNode
* elementNode 
= new wxXmlNode(wxXML_ELEMENT_NODE
, wxT("paragraphlayout")); 
2411     parent
->AddChild(elementNode
); 
2412     handler
->AddAttributes(elementNode
, GetAttributes(), true); 
2413     handler
->WriteProperties(elementNode
, GetProperties()); 
2415     if (GetPartialParagraph()) 
2416         elementNode
->AddAttribute(wxT("partialparagraph"), wxT("true")); 
2419     for (i 
= 0; i 
< GetChildCount(); i
++) 
2421         wxRichTextObject
* child 
= GetChild(i
); 
2422         child
->ExportXML(elementNode
, handler
); 
2430     // wxUSE_RICHTEXT && wxUSE_XML