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