]> git.saurik.com Git - wxWidgets.git/blame - src/richtext/richtextxml.cpp
Better temporary fix.
[wxWidgets.git] / src / richtext / richtextxml.cpp
CommitLineData
5d7836c4 1/////////////////////////////////////////////////////////////////////////////
88a7a4e1 2// Name: src/richtext/richtextxml.cpp
5d7836c4
JS
3// Purpose: XML and HTML I/O for wxRichTextCtrl
4// Author: Julian Smart
7fe8059f 5// Modified by:
5d7836c4 6// Created: 2005-09-30
7fe8059f 7// RCS-ID: $Id$
5d7836c4
JS
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
fcdbeefa 19#if wxUSE_RICHTEXT && wxUSE_XML
b01ca8b6
JS
20
21#include "wx/richtext/richtextxml.h"
22
5d7836c4 23#ifndef WX_PRECOMP
88a7a4e1
WS
24 #include "wx/wx.h"
25 #include "wx/intl.h"
5d7836c4
JS
26#endif
27
5d7836c4
JS
28#include "wx/filename.h"
29#include "wx/clipbrd.h"
30#include "wx/wfstream.h"
31#include "wx/sstream.h"
32#include "wx/module.h"
33#include "wx/txtstrm.h"
34#include "wx/xml/xml.h"
35
5d7836c4
JS
36IMPLEMENT_DYNAMIC_CLASS(wxRichTextXMLHandler, wxRichTextFileHandler)
37
38#if wxUSE_STREAMS
7fe8059f 39bool wxRichTextXMLHandler::DoLoadFile(wxRichTextBuffer *buffer, wxInputStream& stream)
5d7836c4
JS
40{
41 if (!stream.IsOk())
42 return false;
43
44 buffer->Clear();
45
46 wxXmlDocument* xmlDoc = new wxXmlDocument;
47 bool success = true;
48
b71e9aa4
JS
49 // This is the encoding to convert to (memory encoding rather than file encoding)
50 wxString encoding(wxT("UTF-8"));
51
52#if !wxUSE_UNICODE && wxUSE_INTL
53 encoding = wxLocale::GetSystemEncodingName();
54#endif
55
56 if (!xmlDoc->Load(stream, encoding))
5d7836c4
JS
57 {
58 success = false;
59 }
60 else
61 {
62 if (xmlDoc->GetRoot() && xmlDoc->GetRoot()->GetType() == wxXML_ELEMENT_NODE && xmlDoc->GetRoot()->GetName() == wxT("richtext"))
63 {
64 wxXmlNode* child = xmlDoc->GetRoot()->GetChildren();
65 while (child)
66 {
67 if (child->GetType() == wxXML_ELEMENT_NODE)
68 {
69 wxString name = child->GetName();
70 if (name == wxT("richtext-version"))
71 {
72 }
73 else
74 ImportXML(buffer, child);
75 }
7fe8059f 76
5d7836c4
JS
77 child = child->GetNext();
78 }
79 }
80 else
81 {
82 success = false;
83 }
84 }
7fe8059f 85
5d7836c4
JS
86 delete xmlDoc;
87
88 buffer->UpdateRanges();
89
90 return success;
91}
92
93/// Recursively import an object
94bool wxRichTextXMLHandler::ImportXML(wxRichTextBuffer* buffer, wxXmlNode* node)
95{
96 wxString name = node->GetName();
97
98 bool doneChildren = false;
99
100 if (name == wxT("paragraphlayout"))
101 {
102 }
103 else if (name == wxT("paragraph"))
104 {
105 wxRichTextParagraph* para = new wxRichTextParagraph(buffer);
106 buffer->AppendChild(para);
107
108 GetStyle(para->GetAttributes(), node, true);
109
110 wxXmlNode* child = node->GetChildren();
111 while (child)
112 {
113 wxString childName = child->GetName();
114 if (childName == wxT("text"))
115 {
116 wxString text;
117 wxXmlNode* textChild = child->GetChildren();
118 while (textChild)
119 {
120 if (textChild->GetType() == wxXML_TEXT_NODE ||
121 textChild->GetType() == wxXML_CDATA_SECTION_NODE)
122 {
123 wxString text2 = textChild->GetContent();
124
125 // Strip whitespace from end
88a7a4e1
WS
126 if (!text2.empty() && text2[text2.length()-1] == wxT('\n'))
127 text2 = text2.Mid(0, text2.length()-1);
5d7836c4 128
88a7a4e1 129 if (!text2.empty() && text2[0] == wxT('"'))
5d7836c4 130 text2 = text2.Mid(1);
88a7a4e1
WS
131 if (!text2.empty() && text2[text2.length()-1] == wxT('"'))
132 text2 = text2.Mid(0, text2.length() - 1);
5d7836c4 133
5d7836c4
JS
134 text += text2;
135 }
136 textChild = textChild->GetNext();
137 }
138
139 wxRichTextPlainText* textObject = new wxRichTextPlainText(text, para);
140 GetStyle(textObject->GetAttributes(), child, false);
141
142 para->AppendChild(textObject);
143 }
144 else if (childName == wxT("image"))
145 {
146 int imageType = wxBITMAP_TYPE_PNG;
147 wxString value = node->GetPropVal(wxT("imagetype"), wxEmptyString);
7fe8059f 148 if (!value.empty())
5d7836c4
JS
149 imageType = wxAtoi(value);
150
151 wxString data;
152
153 wxXmlNode* imageChild = child->GetChildren();
154 while (imageChild)
155 {
156 wxString childName = imageChild->GetName();
157 if (childName == wxT("data"))
158 {
159 wxXmlNode* dataChild = imageChild->GetChildren();
160 while (dataChild)
161 {
162 data = dataChild->GetContent();
163 // wxLogDebug(data);
164 dataChild = dataChild->GetNext();
165 }
7fe8059f 166
5d7836c4
JS
167 }
168 imageChild = imageChild->GetNext();
169 }
170
7fe8059f 171 if (!data.empty())
5d7836c4
JS
172 {
173 wxRichTextImage* imageObj = new wxRichTextImage(para);
174 para->AppendChild(imageObj);
175
176 wxStringInputStream strStream(data);
177
88a7a4e1 178 imageObj->GetImageBlock().ReadHex(strStream, data.length(), imageType);
5d7836c4
JS
179 }
180 }
181 child = child->GetNext();
182 }
183
184 doneChildren = true;
185 }
186
187 if (!doneChildren)
188 {
189 wxXmlNode* child = node->GetChildren();
190 while (child)
191 {
192 ImportXML(buffer, child);
193 child = child->GetNext();
194 }
7fe8059f 195 }
5d7836c4
JS
196
197 return true;
198}
199
200
201//-----------------------------------------------------------------------------
202// xml support routines
203//-----------------------------------------------------------------------------
204
205bool wxRichTextXMLHandler::HasParam(wxXmlNode* node, const wxString& param)
206{
207 return (GetParamNode(node, param) != NULL);
208}
209
210wxXmlNode *wxRichTextXMLHandler::GetParamNode(wxXmlNode* node, const wxString& param)
211{
212 wxCHECK_MSG(node, NULL, wxT("You can't access node data before it was initialized!"));
213
214 wxXmlNode *n = node->GetChildren();
215
216 while (n)
217 {
218 if (n->GetType() == wxXML_ELEMENT_NODE && n->GetName() == param)
219 return n;
220 n = n->GetNext();
221 }
222 return NULL;
223}
224
225
226wxString wxRichTextXMLHandler::GetNodeContent(wxXmlNode *node)
227{
228 wxXmlNode *n = node;
229 if (n == NULL) return wxEmptyString;
230 n = n->GetChildren();
231
232 while (n)
233 {
234 if (n->GetType() == wxXML_TEXT_NODE ||
235 n->GetType() == wxXML_CDATA_SECTION_NODE)
236 return n->GetContent();
237 n = n->GetNext();
238 }
239 return wxEmptyString;
240}
241
242
243wxString wxRichTextXMLHandler::GetParamValue(wxXmlNode *node, const wxString& param)
244{
7fe8059f 245 if (param.empty())
5d7836c4
JS
246 return GetNodeContent(node);
247 else
248 return GetNodeContent(GetParamNode(node, param));
249}
250
251wxString wxRichTextXMLHandler::GetText(wxXmlNode *node, const wxString& param, bool WXUNUSED(translate))
252{
253 wxXmlNode *parNode = GetParamNode(node, param);
254 if (!parNode)
255 parNode = node;
256 wxString str1(GetNodeContent(parNode));
257 return str1;
258}
259
1e967276
JS
260// For use with earlier versions of wxWidgets
261#ifndef WXUNUSED_IN_UNICODE
262#if wxUSE_UNICODE
263#define WXUNUSED_IN_UNICODE(x) WXUNUSED(x)
264#else
265#define WXUNUSED_IN_UNICODE(x) x
266#endif
267#endif
268
5d7836c4
JS
269// write string to output:
270inline static void OutputString(wxOutputStream& stream, const wxString& str,
7fe8059f 271 wxMBConv *WXUNUSED_IN_UNICODE(convMem) = NULL, wxMBConv *convFile = NULL)
5d7836c4 272{
7fe8059f 273 if (str.empty()) return;
5d7836c4 274#if wxUSE_UNICODE
0bab774b
JS
275 if (convFile)
276 {
277 const wxWX2MBbuf buf(str.mb_str(*convFile));
278 stream.Write((const char*)buf, strlen((const char*)buf));
279 }
280 else
281 {
282 const wxWX2MBbuf buf(str.mb_str(wxConvUTF8));
283 stream.Write((const char*)buf, strlen((const char*)buf));
284 }
5d7836c4
JS
285#else
286 if ( convFile == NULL )
287 stream.Write(str.mb_str(), str.Len());
288 else
289 {
290 wxString str2(str.wc_str(*convMem), *convFile);
291 stream.Write(str2.mb_str(), str2.Len());
292 }
293#endif
294}
295
296// Same as above, but create entities first.
297// Translates '<' to "&lt;", '>' to "&gt;" and '&' to "&amp;"
298static void OutputStringEnt(wxOutputStream& stream, const wxString& str,
299 wxMBConv *convMem = NULL, wxMBConv *convFile = NULL)
300{
301 wxString buf;
302 size_t i, last, len;
303 wxChar c;
7fe8059f 304
5d7836c4
JS
305 len = str.Len();
306 last = 0;
307 for (i = 0; i < len; i++)
308 {
309 c = str.GetChar(i);
88a7a4e1 310
b71e9aa4
JS
311 // Original code excluded "&amp;" but we _do_ want to convert
312 // the ampersand beginning &amp; because otherwise when read in,
313 // the original "&amp;" becomes "&".
314
5d7836c4 315 if (c == wxT('<') || c == wxT('>') || c == wxT('"') ||
b71e9aa4 316 (c == wxT('&') /* && (str.Mid(i+1, 4) != wxT("amp;")) */ ))
5d7836c4
JS
317 {
318 OutputString(stream, str.Mid(last, i - last), convMem, convFile);
319 switch (c)
320 {
321 case wxT('<'):
322 OutputString(stream, wxT("&lt;"), NULL, NULL);
323 break;
324 case wxT('>'):
325 OutputString(stream, wxT("&gt;"), NULL, NULL);
326 break;
327 case wxT('&'):
328 OutputString(stream, wxT("&amp;"), NULL, NULL);
329 break;
330 case wxT('"'):
331 OutputString(stream, wxT("&quot;"), NULL, NULL);
332 break;
333 default: break;
334 }
335 last = i + 1;
336 }
337 }
338 OutputString(stream, str.Mid(last, i - last), convMem, convFile);
339}
340
341inline static void OutputIndentation(wxOutputStream& stream, int indent)
342{
343 wxString str = wxT("\n");
344 for (int i = 0; i < indent; i++)
345 str << wxT(' ') << wxT(' ');
346 OutputString(stream, str, NULL, NULL);
347}
348
5d7836c4
JS
349// Convert a colour to a 6-digit hex string
350static wxString ColourToHexString(const wxColour& col)
351{
352 wxString hex;
353
354 hex += wxDecToHex(col.Red());
355 hex += wxDecToHex(col.Green());
356 hex += wxDecToHex(col.Blue());
357
358 return hex;
359}
360
361// Convert 6-digit hex string to a colour
b71e9aa4 362static wxColour HexStringToColour(const wxString& hex)
5d7836c4 363{
7fe8059f
WS
364 unsigned char r = (unsigned char)wxHexToDec(hex.Mid(0, 2));
365 unsigned char g = (unsigned char)wxHexToDec(hex.Mid(2, 2));
366 unsigned char b = (unsigned char)wxHexToDec(hex.Mid(4, 2));
5d7836c4
JS
367
368 return wxColour(r, g, b);
369}
370
7fe8059f 371bool wxRichTextXMLHandler::DoSaveFile(wxRichTextBuffer *buffer, wxOutputStream& stream)
5d7836c4
JS
372{
373 if (!stream.IsOk())
374 return false;
375
376 wxString version(wxT("1.0") ) ;
b71e9aa4
JS
377
378 bool deleteConvFile = false;
379 wxString fileEncoding;
380 wxMBConv* convFile = NULL;
381
5d7836c4 382#if wxUSE_UNICODE
b71e9aa4
JS
383 fileEncoding = wxT("UTF-8");
384 convFile = & wxConvUTF8;
5d7836c4 385#else
b71e9aa4
JS
386 fileEncoding = wxT("ISO-8859-1");
387 convFile = & wxConvISO8859_1;
5d7836c4 388#endif
7fe8059f 389
b71e9aa4 390 // If SetEncoding has been called, change the output encoding.
88a7a4e1 391 if (!m_encoding.empty() && m_encoding.Lower() != fileEncoding.Lower())
b71e9aa4
JS
392 {
393 if (m_encoding == wxT("<System>"))
394 {
395 fileEncoding = wxLocale::GetSystemEncodingName();
396 }
397 else
398 {
399 fileEncoding = m_encoding;
400 }
401
402 // GetSystemEncodingName may not have returned a name
88a7a4e1 403 if (fileEncoding.empty())
5d7836c4 404#if wxUSE_UNICODE
b71e9aa4 405 fileEncoding = wxT("UTF-8");
5d7836c4 406#else
b71e9aa4
JS
407 fileEncoding = wxT("ISO-8859-1");
408#endif
409 convFile = new wxCSConv(fileEncoding);
410 deleteConvFile = true;
5d7836c4 411 }
b71e9aa4
JS
412
413#if !wxUSE_UNICODE
414 wxMBConv* convMem = wxConvCurrent;
415#else
416 wxMBConv* convMem = NULL;
5d7836c4 417#endif
7fe8059f 418
b71e9aa4 419 wxString s ;
5d7836c4 420 s.Printf(wxT("<?xml version=\"%s\" encoding=\"%s\"?>\n"),
b71e9aa4 421 (const wxChar*) version, (const wxChar*) fileEncoding );
5d7836c4
JS
422 OutputString(stream, s, NULL, NULL);
423 OutputString(stream, wxT("<richtext version=\"1.0.0.0\" xmlns=\"http://www.wxwidgets.org\">") , NULL, NULL);
424
425 int level = 1;
b71e9aa4 426 bool success = ExportXML(stream, convMem, convFile, *buffer, level);
5d7836c4
JS
427
428 OutputString(stream, wxT("\n</richtext>") , NULL, NULL);
429 OutputString(stream, wxT("\n"), NULL, NULL);
7fe8059f 430
b71e9aa4
JS
431 if (deleteConvFile)
432 delete convFile;
88a7a4e1 433
b71e9aa4 434 return success;
5d7836c4
JS
435}
436
437/// Recursively export an object
438bool wxRichTextXMLHandler::ExportXML(wxOutputStream& stream, wxMBConv* convMem, wxMBConv* convFile, wxRichTextObject& obj, int indent)
439{
440 wxString objectName;
441 if (obj.IsKindOf(CLASSINFO(wxRichTextParagraphLayoutBox)))
442 objectName = wxT("paragraphlayout");
443 else if (obj.IsKindOf(CLASSINFO(wxRichTextParagraph)))
444 objectName = wxT("paragraph");
445 else if (obj.IsKindOf(CLASSINFO(wxRichTextPlainText)))
446 objectName = wxT("text");
447 else if (obj.IsKindOf(CLASSINFO(wxRichTextImage)))
448 objectName = wxT("image");
449 else
450 objectName = wxT("object");
451
452 if (obj.IsKindOf(CLASSINFO(wxRichTextPlainText)))
453 {
454 wxRichTextPlainText& text = (wxRichTextPlainText&) obj;
455
456 OutputIndentation(stream, indent);
b71e9aa4 457 OutputString(stream, wxT("<") + objectName, convMem, convFile);
7fe8059f 458
5d7836c4 459 wxString style = CreateStyle(obj.GetAttributes(), false);
7fe8059f 460
b71e9aa4 461 OutputString(stream, style + wxT(">"), convMem, convFile);
7fe8059f 462
5d7836c4 463 wxString str = text.GetText();
88a7a4e1 464 if (!str.empty() && (str[0] == wxT(' ') || str[str.length()-1] == wxT(' ')))
5d7836c4 465 {
b71e9aa4 466 OutputString(stream, wxT("\""), convMem, convFile);
5d7836c4 467 OutputStringEnt(stream, str, convMem, convFile);
b71e9aa4 468 OutputString(stream, wxT("\""), convMem, convFile);
5d7836c4
JS
469 }
470 else
471 OutputStringEnt(stream, str, convMem, convFile);
472 }
473 else if (obj.IsKindOf(CLASSINFO(wxRichTextImage)))
474 {
475 wxRichTextImage& imageObj = (wxRichTextImage&) obj;
476
477 if (imageObj.GetImage().Ok() && !imageObj.GetImageBlock().Ok())
478 imageObj.MakeBlock();
479
480 OutputIndentation(stream, indent);
b71e9aa4 481 OutputString(stream, wxT("<") + objectName, convMem, convFile);
5d7836c4
JS
482 if (!imageObj.GetImageBlock().Ok())
483 {
484 // No data
b71e9aa4 485 OutputString(stream, wxT(">"), convMem, convFile);
5d7836c4
JS
486 }
487 else
488 {
b71e9aa4 489 OutputString(stream, wxString::Format(wxT(" imagetype=\"%d\">"), (int) imageObj.GetImageBlock().GetImageType()));
5d7836c4
JS
490 }
491
492 OutputIndentation(stream, indent+1);
b71e9aa4 493 OutputString(stream, wxT("<data>"), convMem, convFile);
5d7836c4
JS
494
495 imageObj.GetImageBlock().WriteHex(stream);
496
b71e9aa4 497 OutputString(stream, wxT("</data>"), convMem, convFile);
5d7836c4
JS
498 }
499 else if (obj.IsKindOf(CLASSINFO(wxRichTextCompositeObject)))
500 {
501 OutputIndentation(stream, indent);
b71e9aa4 502 OutputString(stream, wxT("<") + objectName, convMem, convFile);
7fe8059f 503
5d7836c4
JS
504 bool isPara = false;
505 if (objectName == wxT("paragraph") || objectName == wxT("paragraphlayout"))
506 isPara = true;
507
508 wxString style = CreateStyle(obj.GetAttributes(), isPara);
7fe8059f 509
b71e9aa4 510 OutputString(stream, style + wxT(">"), convMem, convFile);
7fe8059f 511
5d7836c4
JS
512 wxRichTextCompositeObject& composite = (wxRichTextCompositeObject&) obj;
513 size_t i;
514 for (i = 0; i < composite.GetChildCount(); i++)
515 {
516 wxRichTextObject* child = composite.GetChild(i);
517 ExportXML(stream, convMem, convFile, *child, indent+1);
518 }
519 }
520
521 if (objectName != wxT("text"))
522 OutputIndentation(stream, indent);
523
b71e9aa4 524 OutputString(stream, wxT("</") + objectName + wxT(">"), convMem, convFile);
5d7836c4
JS
525
526 return true;
527}
528
529/// Create style parameters
530wxString wxRichTextXMLHandler::CreateStyle(const wxTextAttrEx& attr, bool isPara)
531{
532 wxString str;
533 if (attr.GetTextColour().Ok())
534 {
535 str << wxT(" textcolor=\"#") << ColourToHexString(attr.GetTextColour()) << wxT("\"");
536 }
537 if (attr.GetBackgroundColour().Ok())
538 {
539 str << wxT(" bgcolor=\"#") << ColourToHexString(attr.GetBackgroundColour()) << wxT("\"");
540 }
541
542 if (attr.GetFont().Ok())
543 {
544 str << wxT(" fontsize=\"") << attr.GetFont().GetPointSize() << wxT("\"");
545 str << wxT(" fontfamily=\"") << attr.GetFont().GetFamily() << wxT("\"");
546 str << wxT(" fontstyle=\"") << attr.GetFont().GetStyle() << wxT("\"");
547 str << wxT(" fontweight=\"") << attr.GetFont().GetWeight() << wxT("\"");
548 str << wxT(" fontunderlined=\"") << (int) attr.GetFont().GetUnderlined() << wxT("\"");
549 str << wxT(" fontface=\"") << attr.GetFont().GetFaceName() << wxT("\"");
550 }
551
7fe8059f 552 if (!attr.GetCharacterStyleName().empty())
5d7836c4
JS
553 str << wxT(" charactertyle=\"") << wxString(attr.GetCharacterStyleName()) << wxT("\"");
554
555 if (isPara)
556 {
557 str << wxT(" alignment=\"") << (int) attr.GetAlignment() << wxT("\"");
558 str << wxT(" leftindent=\"") << (int) attr.GetLeftIndent() << wxT("\"");
559 str << wxT(" leftsubindent=\"") << (int) attr.GetLeftSubIndent() << wxT("\"");
560 str << wxT(" rightindent=\"") << (int) attr.GetRightIndent() << wxT("\"");
561 str << wxT(" parspacingafter=\"") << (int) attr.GetParagraphSpacingAfter() << wxT("\"");
562 str << wxT(" parspacingbefore=\"") << (int) attr.GetParagraphSpacingBefore() << wxT("\"");
563 str << wxT(" linespacing=\"") << (int) attr.GetLineSpacing() << wxT("\"");
564 str << wxT(" bulletstyle=\"") << (int) attr.GetBulletStyle() << wxT("\"");
565 str << wxT(" bulletnumber=\"") << (int) attr.GetBulletNumber() << wxT("\"");
566 str << wxT(" bulletsymbol=\"") << wxString(attr.GetBulletSymbol()) << wxT("\"");
567
7fe8059f 568 if (!attr.GetParagraphStyleName().empty())
5d7836c4
JS
569 str << wxT(" parstyle=\"") << wxString(attr.GetParagraphStyleName()) << wxT("\"");
570 }
571
572 return str;
573}
574
575/// Get style parameters
576bool wxRichTextXMLHandler::GetStyle(wxTextAttrEx& attr, wxXmlNode* node, bool isPara)
577{
578 wxString fontFacename;
579 int fontSize = 12;
580 int fontFamily = wxDEFAULT;
581 int fontWeight = wxNORMAL;
582 int fontStyle = wxNORMAL;
583 bool fontUnderlined = false;
584
585 fontFacename = node->GetPropVal(wxT("fontface"), wxEmptyString);
586
587 wxString value = node->GetPropVal(wxT("fontfamily"), wxEmptyString);
7fe8059f 588 if (!value.empty())
5d7836c4
JS
589 fontFamily = wxAtoi(value);
590
591 value = node->GetPropVal(wxT("fontstyle"), wxEmptyString);
7fe8059f 592 if (!value.empty())
5d7836c4
JS
593 fontStyle = wxAtoi(value);
594
595 value = node->GetPropVal(wxT("fontsize"), wxEmptyString);
7fe8059f 596 if (!value.empty())
5d7836c4
JS
597 fontSize = wxAtoi(value);
598
599 value = node->GetPropVal(wxT("fontweight"), wxEmptyString);
7fe8059f 600 if (!value.empty())
5d7836c4
JS
601 fontWeight = wxAtoi(value);
602
603 value = node->GetPropVal(wxT("fontunderlined"), wxEmptyString);
7fe8059f 604 if (!value.empty())
5d7836c4
JS
605 fontUnderlined = wxAtoi(value) != 0;
606
607 attr.SetFont(* wxTheFontList->FindOrCreateFont(fontSize, fontFamily, fontStyle, fontWeight, fontUnderlined, fontFacename));
608
609 value = node->GetPropVal(wxT("textcolor"), wxEmptyString);
7fe8059f 610 if (!value.empty())
5d7836c4
JS
611 {
612 if (value[0] == wxT('#'))
613 attr.SetTextColour(HexStringToColour(value.Mid(1)));
614 else
615 attr.SetTextColour(value);
616 }
617
618 value = node->GetPropVal(wxT("backgroundcolor"), wxEmptyString);
7fe8059f 619 if (!value.empty())
5d7836c4
JS
620 {
621 if (value[0] == wxT('#'))
622 attr.SetBackgroundColour(HexStringToColour(value.Mid(1)));
623 else
624 attr.SetBackgroundColour(value);
625 }
626
627 value = node->GetPropVal(wxT("characterstyle"), wxEmptyString);
7fe8059f 628 if (!value.empty())
5d7836c4
JS
629 attr.SetCharacterStyleName(value);
630
631 // Set paragraph attributes
632 if (isPara)
633 {
634 value = node->GetPropVal(wxT("alignment"), wxEmptyString);
7fe8059f 635 if (!value.empty())
5d7836c4
JS
636 attr.SetAlignment((wxTextAttrAlignment) wxAtoi(value));
637
638 int leftSubIndent = 0;
639 int leftIndent = 0;
640 value = node->GetPropVal(wxT("leftindent"), wxEmptyString);
7fe8059f 641 if (!value.empty())
5d7836c4
JS
642 leftIndent = wxAtoi(value);
643 value = node->GetPropVal(wxT("leftsubindent"), wxEmptyString);
7fe8059f 644 if (!value.empty())
5d7836c4
JS
645 leftSubIndent = wxAtoi(value);
646 attr.SetLeftIndent(leftIndent, leftSubIndent);
647
648 value = node->GetPropVal(wxT("rightindent"), wxEmptyString);
7fe8059f 649 if (!value.empty())
5d7836c4
JS
650 attr.SetRightIndent(wxAtoi(value));
651
652 value = node->GetPropVal(wxT("parspacingbefore"), wxEmptyString);
7fe8059f 653 if (!value.empty())
5d7836c4
JS
654 attr.SetParagraphSpacingBefore(wxAtoi(value));
655
656 value = node->GetPropVal(wxT("parspacingafter"), wxEmptyString);
7fe8059f 657 if (!value.empty())
5d7836c4
JS
658 attr.SetParagraphSpacingAfter(wxAtoi(value));
659
660 value = node->GetPropVal(wxT("linespacing"), wxEmptyString);
7fe8059f 661 if (!value.empty())
5d7836c4
JS
662 attr.SetLineSpacing(wxAtoi(value));
663
664 value = node->GetPropVal(wxT("bulletstyle"), wxEmptyString);
7fe8059f 665 if (!value.empty())
5d7836c4
JS
666 attr.SetBulletStyle(wxAtoi(value));
667
668 value = node->GetPropVal(wxT("bulletnumber"), wxEmptyString);
7fe8059f 669 if (!value.empty())
5d7836c4
JS
670 attr.SetBulletNumber(wxAtoi(value));
671
672 value = node->GetPropVal(wxT("bulletsymbol"), wxEmptyString);
7fe8059f 673 if (!value.empty())
5d7836c4
JS
674 attr.SetBulletSymbol(value[0]);
675
676 value = node->GetPropVal(wxT("parstyle"), wxEmptyString);
7fe8059f 677 if (!value.empty())
5d7836c4
JS
678 attr.SetParagraphStyleName(value);
679 }
680
681 return true;
682}
683
684#endif
b71e9aa4 685 // wxUSE_STREAMS
88a7a4e1 686
5d7836c4 687#endif
fcdbeefa 688 // wxUSE_RICHTEXT && wxUSE_XML