1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #include <sal/config.h>
11 
12 #include "txtparai.hxx"
13 
14 #include <string_view>
15 
16 #include "XMLFootnoteImportContext.hxx"
17 #include "XMLTextFrameContext.hxx"
18 #include "xmlimp.hxx"
19 
20 #include <sal/log.hxx>
21 
22 using namespace com::sun::star;
23 
24 namespace
25 {
26 /// Looks for rName in rStyles and fills rPropertyList based on that
27 /// (rAutomaticStyles and rNamedStyles are a list of possible parents).
FillStyle(const OUString & rName,std::map<OUString,librevenge::RVNGPropertyList> & rStyles,std::map<OUString,librevenge::RVNGPropertyList> & rAutomaticStyles,std::map<OUString,librevenge::RVNGPropertyList> & rNamedStyles,librevenge::RVNGPropertyList & rPropertyList)28 void FillStyle(const OUString& rName, std::map<OUString, librevenge::RVNGPropertyList>& rStyles,
29                std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
30                std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
31                librevenge::RVNGPropertyList& rPropertyList)
32 {
33     auto itStyle = rStyles.find(rName);
34     if (itStyle == rStyles.end())
35         return;
36 
37     const librevenge::RVNGPropertyList& rStyle = itStyle->second;
38     if (rStyle["style:parent-style-name"])
39     {
40         // The style has a parent.
41         OUString aParent = OStringToOUString(rStyle["style:parent-style-name"]->getStr().cstr(),
42                                              RTL_TEXTENCODING_UTF8);
43         if (!aParent.isEmpty())
44             writerperfect::exp::FillStyles(aParent, rAutomaticStyles, rNamedStyles, rPropertyList);
45     }
46 
47     // Apply properties from named style.
48     librevenge::RVNGPropertyList::Iter itProp(rStyle);
49     for (itProp.rewind(); itProp.next();)
50     {
51         if (std::string_view("style:parent-style-name") != itProp.key())
52             rPropertyList.insert(itProp.key(), itProp()->clone());
53     }
54 }
55 }
56 
57 namespace writerperfect::exp
58 {
59 namespace
60 {
61 /// Handler for <text:sequence>.
62 class XMLTextSequenceContext : public XMLImportContext
63 {
64 public:
65     XMLTextSequenceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
66 
67     void SAL_CALL characters(const OUString& rChars) override;
68 
69 private:
70     librevenge::RVNGPropertyList m_aPropertyList;
71 };
72 }
73 
XMLTextSequenceContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)74 XMLTextSequenceContext::XMLTextSequenceContext(XMLImport& rImport,
75                                                const librevenge::RVNGPropertyList& rPropertyList)
76     : XMLImportContext(rImport)
77 {
78     // Inherit properties from parent.
79     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
80     for (itProp.rewind(); itProp.next();)
81         m_aPropertyList.insert(itProp.key(), itProp()->clone());
82 }
83 
characters(const OUString & rChars)84 void XMLTextSequenceContext::characters(const OUString& rChars)
85 {
86     GetImport().GetGenerator().openSpan(m_aPropertyList);
87 
88     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
89     GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
90 
91     GetImport().GetGenerator().closeSpan();
92 }
93 
94 namespace
95 {
96 /// Handler for <text:span>.
97 class XMLSpanContext : public XMLImportContext
98 {
99 public:
100     XMLSpanContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
101 
102     rtl::Reference<XMLImportContext>
103     CreateChildContext(const OUString& rName,
104                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
105 
106     void SAL_CALL
107     startElement(const OUString& rName,
108                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
109     void SAL_CALL characters(const OUString& rChars) override;
110 
111 private:
112     librevenge::RVNGPropertyList m_aPropertyList;
113 };
114 }
115 
XMLSpanContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)116 XMLSpanContext::XMLSpanContext(XMLImport& rImport,
117                                const librevenge::RVNGPropertyList& rPropertyList)
118     : XMLImportContext(rImport)
119 {
120     // Inherit properties from parent.
121     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
122     for (itProp.rewind(); itProp.next();)
123         m_aPropertyList.insert(itProp.key(), itProp()->clone());
124 }
125 
CreateChildContext(const OUString & rName,const css::uno::Reference<css::xml::sax::XAttributeList> &)126 rtl::Reference<XMLImportContext> XMLSpanContext::CreateChildContext(
127     const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
128 {
129     return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
130 }
131 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttribs)132 void XMLSpanContext::startElement(
133     const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
134 {
135     for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
136     {
137         const OUString& rAttributeName = xAttribs->getNameByIndex(i);
138         const OUString& rAttributeValue = xAttribs->getValueByIndex(i);
139         if (rAttributeName == "text:style-name")
140             FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(),
141                        GetImport().GetTextStyles(), m_aPropertyList);
142         else
143         {
144             OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
145             OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
146             m_aPropertyList.insert(sName.getStr(), sValue.getStr());
147         }
148     }
149 }
150 
characters(const OUString & rChars)151 void XMLSpanContext::characters(const OUString& rChars)
152 {
153     GetImport().GetGenerator().openSpan(m_aPropertyList);
154 
155     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
156     GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
157 
158     GetImport().GetGenerator().closeSpan();
159 }
160 
161 namespace
162 {
163 /// Handler for <text:ruby>.
164 class XMLRubyContext : public XMLImportContext
165 {
166 public:
167     XMLRubyContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
168 
169     rtl::Reference<XMLImportContext>
170     CreateChildContext(const OUString& rName,
171                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
172 
173     void SAL_CALL endElement(const OUString& rName) override;
174 
SetRubyText(const OUString & rRubyText)175     void SetRubyText(const OUString& rRubyText) { m_sRubyText = rRubyText; }
176 
GetRubyBase()177     OUString& GetRubyBase() { return m_sRubyBase; }
178 
179 private:
180     OUString m_sRubyText;
181     OUString m_sRubyBase;
182     librevenge::RVNGPropertyList m_aPropertyList;
183 };
184 
185 /// Handler for <text:ruby-text>.
186 class XMLRubyTextContext : public XMLImportContext
187 {
188 public:
XMLRubyTextContext(XMLImport & rImport,XMLRubyContext & rParent)189     XMLRubyTextContext(XMLImport& rImport, XMLRubyContext& rParent)
190         : XMLImportContext(rImport)
191         , m_rParent(rParent)
192     {
193     }
194 
characters(const OUString & rChars)195     void SAL_CALL characters(const OUString& rChars) override { m_rParent.SetRubyText(rChars); }
196 
197 private:
198     XMLRubyContext& m_rParent;
199 };
200 
201 /// Handler for <text:ruby-base>.
202 class XMLRubyBaseContext : public XMLImportContext
203 {
204 public:
XMLRubyBaseContext(XMLImport & rImport,XMLRubyContext & rParent)205     XMLRubyBaseContext(XMLImport& rImport, XMLRubyContext& rParent)
206         : XMLImportContext(rImport)
207         , m_rParent(rParent)
208     {
209     }
210 
characters(const OUString & rChars)211     void SAL_CALL characters(const OUString& rChars) override { m_rParent.GetRubyBase() += rChars; }
212 
213 private:
214     XMLRubyContext& m_rParent;
215 };
216 }
217 
XMLRubyContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)218 XMLRubyContext::XMLRubyContext(XMLImport& rImport,
219                                const librevenge::RVNGPropertyList& rPropertyList)
220     : XMLImportContext(rImport)
221 {
222     // Inherit properties from parent.
223     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
224     for (itProp.rewind(); itProp.next();)
225         m_aPropertyList.insert(itProp.key(), itProp()->clone());
226 }
227 
CreateChildContext(const OUString & rName,const css::uno::Reference<css::xml::sax::XAttributeList> &)228 rtl::Reference<XMLImportContext> XMLRubyContext::CreateChildContext(
229     const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
230 {
231     if (rName == "text:ruby-base")
232         return new XMLRubyBaseContext(GetImport(), *this);
233     if (rName == "text:ruby-text")
234         return new XMLRubyTextContext(GetImport(), *this);
235     return nullptr;
236 }
237 
endElement(const OUString &)238 void XMLRubyContext::endElement(const OUString& /*rName*/)
239 {
240     OString sRubyText = OUStringToOString(m_sRubyText, RTL_TEXTENCODING_UTF8);
241     OString sRubyBase = OUStringToOString(m_sRubyBase, RTL_TEXTENCODING_UTF8);
242     if (sRubyText.getLength())
243         m_aPropertyList.insert("text:ruby-text", sRubyText.getStr());
244     GetImport().GetGenerator().openSpan(m_aPropertyList);
245     GetImport().GetGenerator().insertText(sRubyBase.getStr());
246     GetImport().GetGenerator().closeSpan();
247 }
248 
249 namespace
250 {
251 /// Base class for contexts that represent a single character only.
252 class XMLCharContext : public XMLImportContext
253 {
254 public:
255     XMLCharContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
256 
GetPropertyList() const257     const librevenge::RVNGPropertyList& GetPropertyList() const { return m_aPropertyList; }
258 
259 private:
260     librevenge::RVNGPropertyList m_aPropertyList;
261 };
262 }
263 
XMLCharContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)264 XMLCharContext::XMLCharContext(XMLImport& rImport,
265                                const librevenge::RVNGPropertyList& rPropertyList)
266     : XMLImportContext(rImport)
267 {
268     // Inherit properties from parent.
269     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
270     for (itProp.rewind(); itProp.next();)
271         m_aPropertyList.insert(itProp.key(), itProp()->clone());
272 }
273 
274 namespace
275 {
276 /// Handler for <text:line-break>.
277 class XMLLineBreakContext : public XMLCharContext
278 {
279 public:
280     XMLLineBreakContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
281 
282     void SAL_CALL
283     startElement(const OUString& rName,
284                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
285 };
286 }
287 
XMLLineBreakContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)288 XMLLineBreakContext::XMLLineBreakContext(XMLImport& rImport,
289                                          const librevenge::RVNGPropertyList& rPropertyList)
290     : XMLCharContext(rImport, rPropertyList)
291 {
292 }
293 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> &)294 void XMLLineBreakContext::startElement(
295     const OUString& /*rName*/,
296     const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
297 {
298     GetImport().GetGenerator().openSpan(GetPropertyList());
299     GetImport().GetGenerator().insertLineBreak();
300     GetImport().GetGenerator().closeSpan();
301 }
302 
303 namespace
304 {
305 /// Handler for <text:s>.
306 class XMLSpaceContext : public XMLCharContext
307 {
308 public:
309     XMLSpaceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
310 
311     void SAL_CALL
312     startElement(const OUString& rName,
313                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
314 };
315 }
316 
XMLSpaceContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)317 XMLSpaceContext::XMLSpaceContext(XMLImport& rImport,
318                                  const librevenge::RVNGPropertyList& rPropertyList)
319     : XMLCharContext(rImport, rPropertyList)
320 {
321 }
322 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> &)323 void XMLSpaceContext::startElement(
324     const OUString& /*rName*/,
325     const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
326 {
327     GetImport().GetGenerator().openSpan(GetPropertyList());
328     GetImport().GetGenerator().insertSpace();
329     GetImport().GetGenerator().closeSpan();
330 }
331 
332 namespace
333 {
334 /// Handler for <text:tab>.
335 class XMLTabContext : public XMLCharContext
336 {
337 public:
338     XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
339 
340     void SAL_CALL
341     startElement(const OUString& rName,
342                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
343 };
344 }
345 
XMLTabContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)346 XMLTabContext::XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
347     : XMLCharContext(rImport, rPropertyList)
348 {
349 }
350 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> &)351 void XMLTabContext::startElement(
352     const OUString& /*rName*/,
353     const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
354 {
355     GetImport().GetGenerator().openSpan(GetPropertyList());
356     GetImport().GetGenerator().insertTab();
357     GetImport().GetGenerator().closeSpan();
358 }
359 
360 namespace
361 {
362 /// Handler for <draw:a>.
363 class XMLTextFrameHyperlinkContext : public XMLImportContext
364 {
365 public:
366     XMLTextFrameHyperlinkContext(XMLImport& rImport,
367                                  const librevenge::RVNGPropertyList& rPropertyList);
368     rtl::Reference<XMLImportContext>
369     CreateChildContext(const OUString& rName,
370                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
371 
372     void SAL_CALL
373     startElement(const OUString& rName,
374                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
375     void SAL_CALL endElement(const OUString& rName) override;
376     void SAL_CALL characters(const OUString& rChars) override;
377 
378 private:
379     librevenge::RVNGPropertyList m_aPropertyList;
380     PopupState m_ePopupState = PopupState::NONE;
381 };
382 }
383 
XMLTextFrameHyperlinkContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)384 XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
385     XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
386     : XMLImportContext(rImport)
387 {
388     // Inherit properties from parent.
389     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
390     for (itProp.rewind(); itProp.next();)
391         m_aPropertyList.insert(itProp.key(), itProp()->clone());
392 }
393 
CreateChildContext(const OUString & rName,const css::uno::Reference<css::xml::sax::XAttributeList> &)394 rtl::Reference<XMLImportContext> XMLTextFrameHyperlinkContext::CreateChildContext(
395     const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
396 {
397     return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
398 }
399 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttribs)400 void XMLTextFrameHyperlinkContext::startElement(
401     const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
402 {
403     librevenge::RVNGPropertyList aPropertyList;
404     for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
405     {
406         const OUString& rAttributeName = xAttribs->getNameByIndex(i);
407         const OUString& rAttributeValue = xAttribs->getValueByIndex(i);
408         if (rAttributeName == "text:style-name")
409             // This affects the nested span's properties.
410             FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(),
411                        GetImport().GetTextStyles(), m_aPropertyList);
412         else
413         {
414             if (rAttributeName == "xlink:href")
415             {
416                 m_ePopupState = GetImport().FillPopupData(rAttributeValue, aPropertyList);
417                 if (m_ePopupState != PopupState::NotConsumed)
418                     continue;
419             }
420 
421             // This affects the link's properties.
422             OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
423             OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
424             aPropertyList.insert(sName.getStr(), sValue.getStr());
425         }
426     }
427 
428     if (m_ePopupState != PopupState::Ignore)
429         GetImport().GetGenerator().openLink(aPropertyList);
430 }
431 
endElement(const OUString &)432 void XMLTextFrameHyperlinkContext::endElement(const OUString& /*rName*/)
433 {
434     if (m_ePopupState != PopupState::Ignore)
435         GetImport().GetGenerator().closeLink();
436 }
437 
characters(const OUString & rChars)438 void XMLTextFrameHyperlinkContext::characters(const OUString& rChars)
439 {
440     GetImport().GetGenerator().openSpan(m_aPropertyList);
441 
442     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
443     GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
444 
445     GetImport().GetGenerator().closeSpan();
446 }
447 
448 namespace
449 {
450 /// Handler for <text:a>.
451 class XMLHyperlinkContext : public XMLImportContext
452 {
453 public:
454     XMLHyperlinkContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
455     rtl::Reference<XMLImportContext>
456     CreateChildContext(const OUString& rName,
457                        const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
458 
459     void SAL_CALL
460     startElement(const OUString& rName,
461                  const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
462     void SAL_CALL endElement(const OUString& rName) override;
463     void SAL_CALL characters(const OUString& rChars) override;
464 
465 private:
466     librevenge::RVNGPropertyList m_aPropertyList;
467     PopupState m_ePopupState = PopupState::NONE;
468 };
469 }
470 
XMLHyperlinkContext(XMLImport & rImport,const librevenge::RVNGPropertyList & rPropertyList)471 XMLHyperlinkContext::XMLHyperlinkContext(XMLImport& rImport,
472                                          const librevenge::RVNGPropertyList& rPropertyList)
473     : XMLImportContext(rImport)
474 {
475     // Inherit properties from parent.
476     librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
477     for (itProp.rewind(); itProp.next();)
478         m_aPropertyList.insert(itProp.key(), itProp()->clone());
479 }
480 
CreateChildContext(const OUString & rName,const css::uno::Reference<css::xml::sax::XAttributeList> &)481 rtl::Reference<XMLImportContext> XMLHyperlinkContext::CreateChildContext(
482     const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
483 {
484     return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
485 }
486 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttribs)487 void XMLHyperlinkContext::startElement(
488     const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
489 {
490     librevenge::RVNGPropertyList aPropertyList;
491     for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
492     {
493         const OUString& rAttributeName = xAttribs->getNameByIndex(i);
494         const OUString& rAttributeValue = xAttribs->getValueByIndex(i);
495         if (rAttributeName == "text:style-name")
496             // This affects the nested span's properties.
497             FillStyles(rAttributeValue, GetImport().GetAutomaticTextStyles(),
498                        GetImport().GetTextStyles(), m_aPropertyList);
499         else
500         {
501             if (rAttributeName == "xlink:href")
502             {
503                 m_ePopupState = GetImport().FillPopupData(rAttributeValue, aPropertyList);
504                 if (m_ePopupState != PopupState::NotConsumed)
505                     continue;
506             }
507 
508             // This affects the link's properties.
509             OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
510             OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
511             aPropertyList.insert(sName.getStr(), sValue.getStr());
512         }
513     }
514 
515     if (m_ePopupState != PopupState::Ignore)
516         GetImport().GetGenerator().openLink(aPropertyList);
517 }
518 
endElement(const OUString &)519 void XMLHyperlinkContext::endElement(const OUString& /*rName*/)
520 {
521     if (m_ePopupState != PopupState::Ignore)
522         GetImport().GetGenerator().closeLink();
523 }
524 
characters(const OUString & rChars)525 void XMLHyperlinkContext::characters(const OUString& rChars)
526 {
527     GetImport().GetGenerator().openSpan(m_aPropertyList);
528 
529     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
530     GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
531 
532     GetImport().GetGenerator().closeSpan();
533 }
534 
XMLParaContext(XMLImport & rImport,bool bTopLevel)535 XMLParaContext::XMLParaContext(XMLImport& rImport, bool bTopLevel)
536     : XMLImportContext(rImport)
537     , m_bTopLevel(bTopLevel)
538 {
539 }
540 
CreateChildContext(const OUString & rName,const css::uno::Reference<css::xml::sax::XAttributeList> &)541 rtl::Reference<XMLImportContext> XMLParaContext::CreateChildContext(
542     const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
543 {
544     if (rName == "text:a")
545         return new XMLHyperlinkContext(GetImport(), m_aTextPropertyList);
546     if (rName == "draw:a")
547         return new XMLTextFrameHyperlinkContext(GetImport(), m_aTextPropertyList);
548     if (rName == "text:ruby")
549         return new XMLRubyContext(GetImport(), m_aTextPropertyList);
550     return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aTextPropertyList);
551 }
552 
startElement(const OUString &,const css::uno::Reference<css::xml::sax::XAttributeList> & xAttribs)553 void XMLParaContext::startElement(
554     const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
555 {
556     librevenge::RVNGPropertyList aPropertyList;
557     for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
558     {
559         const OUString& rAttributeName = xAttribs->getNameByIndex(i);
560         const OUString& rAttributeValue = xAttribs->getValueByIndex(i);
561         if (rAttributeName == "text:style-name")
562         {
563             m_aStyleName = rAttributeValue;
564             FillStyles(m_aStyleName, GetImport().GetAutomaticParagraphStyles(),
565                        GetImport().GetParagraphStyles(), aPropertyList);
566             FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(),
567                        GetImport().GetTextStyles(), m_aTextPropertyList);
568             if (m_bTopLevel)
569                 GetImport().HandlePageSpan(aPropertyList);
570         }
571         else
572         {
573             OString sName = OUStringToOString(rAttributeName, RTL_TEXTENCODING_UTF8);
574             OString sValue = OUStringToOString(rAttributeValue, RTL_TEXTENCODING_UTF8);
575             aPropertyList.insert(sName.getStr(), sValue.getStr());
576         }
577     }
578 
579     GetImport().GetGenerator().openParagraph(aPropertyList);
580 }
581 
endElement(const OUString &)582 void XMLParaContext::endElement(const OUString& /*rName*/)
583 {
584     GetImport().GetGenerator().closeParagraph();
585 }
586 
characters(const OUString & rChars)587 void XMLParaContext::characters(const OUString& rChars)
588 {
589     librevenge::RVNGPropertyList aPropertyList;
590     if (!m_aStyleName.isEmpty())
591         FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(), GetImport().GetTextStyles(),
592                    aPropertyList);
593     GetImport().GetGenerator().openSpan(aPropertyList);
594 
595     OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
596     GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));
597 
598     GetImport().GetGenerator().closeSpan();
599 }
600 
601 rtl::Reference<XMLImportContext>
CreateParagraphOrSpanChildContext(XMLImport & rImport,const OUString & rName,const librevenge::RVNGPropertyList & rTextPropertyList)602 CreateParagraphOrSpanChildContext(XMLImport& rImport, const OUString& rName,
603                                   const librevenge::RVNGPropertyList& rTextPropertyList)
604 {
605     if (rName == "text:span")
606         return new XMLSpanContext(rImport, rTextPropertyList);
607     if (rName == "text:line-break")
608         return new XMLLineBreakContext(rImport, rTextPropertyList);
609     if (rName == "text:s")
610         return new XMLSpaceContext(rImport, rTextPropertyList);
611     if (rName == "text:tab")
612         return new XMLTabContext(rImport, rTextPropertyList);
613     if (rName == "draw:frame")
614         return new XMLTextFrameContext(rImport);
615     if (rName == "text:sequence")
616         return new XMLTextSequenceContext(rImport, rTextPropertyList);
617     if (rName == "text:note")
618         return new XMLFootnoteImportContext(rImport);
619     SAL_WARN("writerperfect", "CreateParagraphOrSpanChildContext: unhandled " << rName);
620     return nullptr;
621 }
622 
FillStyles(const OUString & rName,std::map<OUString,librevenge::RVNGPropertyList> & rAutomaticStyles,std::map<OUString,librevenge::RVNGPropertyList> & rNamedStyles,librevenge::RVNGPropertyList & rPropertyList)623 void FillStyles(const OUString& rName,
624                 std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
625                 std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
626                 librevenge::RVNGPropertyList& rPropertyList)
627 {
628     FillStyle(rName, rAutomaticStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
629     FillStyle(rName, rNamedStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
630 }
631 
632 } // namespace writerperfect
633 
634 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
635