1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
10 #include <sal/config.h>
12 #include "txtparai.hxx"
14 #include <string_view>
16 #include "XMLFootnoteImportContext.hxx"
17 #include "XMLTextFrameContext.hxx"
20 #include <sal/log.hxx>
22 using namespace com::sun::star
;
26 /// Looks for rName in rStyles and fills rPropertyList based on that
27 /// (rAutomaticStyles and rNamedStyles are a list of possible parents).
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
)
33 auto itStyle
= rStyles
.find(rName
);
34 if (itStyle
== rStyles
.end())
37 const librevenge::RVNGPropertyList
& rStyle
= itStyle
->second
;
38 if (rStyle
["style:parent-style-name"])
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
);
47 // Apply properties from named style.
48 librevenge::RVNGPropertyList::Iter
itProp(rStyle
);
49 for (itProp
.rewind(); itProp
.next();)
51 if (std::string_view("style:parent-style-name") != itProp
.key())
52 rPropertyList
.insert(itProp
.key(), itProp()->clone());
57 namespace writerperfect::exp
61 /// Handler for <text:sequence>.
62 class XMLTextSequenceContext
: public XMLImportContext
65 XMLTextSequenceContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
67 void SAL_CALL
characters(const OUString
& rChars
) override
;
70 librevenge::RVNGPropertyList m_aPropertyList
;
74 XMLTextSequenceContext::XMLTextSequenceContext(XMLImport
& rImport
,
75 const librevenge::RVNGPropertyList
& rPropertyList
)
76 : XMLImportContext(rImport
)
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());
84 void XMLTextSequenceContext::characters(const OUString
& rChars
)
86 GetImport().GetGenerator().openSpan(m_aPropertyList
);
88 OString sCharU8
= OUStringToOString(rChars
, RTL_TEXTENCODING_UTF8
);
89 GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8
.getStr()));
91 GetImport().GetGenerator().closeSpan();
96 /// Handler for <text:span>.
97 class XMLSpanContext
: public XMLImportContext
100 XMLSpanContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
102 rtl::Reference
<XMLImportContext
>
103 CreateChildContext(const OUString
& rName
,
104 const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
) override
;
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
;
112 librevenge::RVNGPropertyList m_aPropertyList
;
116 XMLSpanContext::XMLSpanContext(XMLImport
& rImport
,
117 const librevenge::RVNGPropertyList
& rPropertyList
)
118 : XMLImportContext(rImport
)
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());
126 rtl::Reference
<XMLImportContext
> XMLSpanContext::CreateChildContext(
127 const OUString
& rName
, const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
129 return CreateParagraphOrSpanChildContext(GetImport(), rName
, m_aPropertyList
);
132 void XMLSpanContext::startElement(
133 const OUString
& /*rName*/, const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
)
135 for (sal_Int16 i
= 0; i
< xAttribs
->getLength(); ++i
)
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
);
144 OString sName
= OUStringToOString(rAttributeName
, RTL_TEXTENCODING_UTF8
);
145 OString sValue
= OUStringToOString(rAttributeValue
, RTL_TEXTENCODING_UTF8
);
146 m_aPropertyList
.insert(sName
.getStr(), sValue
.getStr());
151 void XMLSpanContext::characters(const OUString
& rChars
)
153 GetImport().GetGenerator().openSpan(m_aPropertyList
);
155 OString sCharU8
= OUStringToOString(rChars
, RTL_TEXTENCODING_UTF8
);
156 GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8
.getStr()));
158 GetImport().GetGenerator().closeSpan();
163 /// Handler for <text:ruby>.
164 class XMLRubyContext
: public XMLImportContext
167 XMLRubyContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
169 rtl::Reference
<XMLImportContext
>
170 CreateChildContext(const OUString
& rName
,
171 const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
) override
;
173 void SAL_CALL
endElement(const OUString
& rName
) override
;
175 void SetRubyText(const OUString
& rRubyText
) { m_sRubyText
= rRubyText
; }
177 OUString
& GetRubyBase() { return m_sRubyBase
; }
180 OUString m_sRubyText
;
181 OUString m_sRubyBase
;
182 librevenge::RVNGPropertyList m_aPropertyList
;
185 /// Handler for <text:ruby-text>.
186 class XMLRubyTextContext
: public XMLImportContext
189 XMLRubyTextContext(XMLImport
& rImport
, XMLRubyContext
& rParent
)
190 : XMLImportContext(rImport
)
195 void SAL_CALL
characters(const OUString
& rChars
) override
{ m_rParent
.SetRubyText(rChars
); }
198 XMLRubyContext
& m_rParent
;
201 /// Handler for <text:ruby-base>.
202 class XMLRubyBaseContext
: public XMLImportContext
205 XMLRubyBaseContext(XMLImport
& rImport
, XMLRubyContext
& rParent
)
206 : XMLImportContext(rImport
)
211 void SAL_CALL
characters(const OUString
& rChars
) override
{ m_rParent
.GetRubyBase() += rChars
; }
214 XMLRubyContext
& m_rParent
;
218 XMLRubyContext::XMLRubyContext(XMLImport
& rImport
,
219 const librevenge::RVNGPropertyList
& rPropertyList
)
220 : XMLImportContext(rImport
)
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());
228 rtl::Reference
<XMLImportContext
> XMLRubyContext::CreateChildContext(
229 const OUString
& rName
, const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
231 if (rName
== "text:ruby-base")
232 return new XMLRubyBaseContext(GetImport(), *this);
233 if (rName
== "text:ruby-text")
234 return new XMLRubyTextContext(GetImport(), *this);
238 void XMLRubyContext::endElement(const OUString
& /*rName*/)
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();
251 /// Base class for contexts that represent a single character only.
252 class XMLCharContext
: public XMLImportContext
255 XMLCharContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
257 const librevenge::RVNGPropertyList
& GetPropertyList() const { return m_aPropertyList
; }
260 librevenge::RVNGPropertyList m_aPropertyList
;
264 XMLCharContext::XMLCharContext(XMLImport
& rImport
,
265 const librevenge::RVNGPropertyList
& rPropertyList
)
266 : XMLImportContext(rImport
)
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());
276 /// Handler for <text:line-break>.
277 class XMLLineBreakContext
: public XMLCharContext
280 XMLLineBreakContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
283 startElement(const OUString
& rName
,
284 const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
) override
;
288 XMLLineBreakContext::XMLLineBreakContext(XMLImport
& rImport
,
289 const librevenge::RVNGPropertyList
& rPropertyList
)
290 : XMLCharContext(rImport
, rPropertyList
)
294 void XMLLineBreakContext::startElement(
295 const OUString
& /*rName*/,
296 const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
298 GetImport().GetGenerator().openSpan(GetPropertyList());
299 GetImport().GetGenerator().insertLineBreak();
300 GetImport().GetGenerator().closeSpan();
305 /// Handler for <text:s>.
306 class XMLSpaceContext
: public XMLCharContext
309 XMLSpaceContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
312 startElement(const OUString
& rName
,
313 const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
) override
;
317 XMLSpaceContext::XMLSpaceContext(XMLImport
& rImport
,
318 const librevenge::RVNGPropertyList
& rPropertyList
)
319 : XMLCharContext(rImport
, rPropertyList
)
323 void XMLSpaceContext::startElement(
324 const OUString
& /*rName*/,
325 const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
327 GetImport().GetGenerator().openSpan(GetPropertyList());
328 GetImport().GetGenerator().insertSpace();
329 GetImport().GetGenerator().closeSpan();
334 /// Handler for <text:tab>.
335 class XMLTabContext
: public XMLCharContext
338 XMLTabContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
);
341 startElement(const OUString
& rName
,
342 const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
) override
;
346 XMLTabContext::XMLTabContext(XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
)
347 : XMLCharContext(rImport
, rPropertyList
)
351 void XMLTabContext::startElement(
352 const OUString
& /*rName*/,
353 const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
355 GetImport().GetGenerator().openSpan(GetPropertyList());
356 GetImport().GetGenerator().insertTab();
357 GetImport().GetGenerator().closeSpan();
362 /// Handler for <draw:a>.
363 class XMLTextFrameHyperlinkContext
: public XMLImportContext
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
;
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
;
379 librevenge::RVNGPropertyList m_aPropertyList
;
380 PopupState m_ePopupState
= PopupState::NONE
;
384 XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
385 XMLImport
& rImport
, const librevenge::RVNGPropertyList
& rPropertyList
)
386 : XMLImportContext(rImport
)
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());
394 rtl::Reference
<XMLImportContext
> XMLTextFrameHyperlinkContext::CreateChildContext(
395 const OUString
& rName
, const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
397 return CreateParagraphOrSpanChildContext(GetImport(), rName
, m_aPropertyList
);
400 void XMLTextFrameHyperlinkContext::startElement(
401 const OUString
& /*rName*/, const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
)
403 librevenge::RVNGPropertyList aPropertyList
;
404 for (sal_Int16 i
= 0; i
< xAttribs
->getLength(); ++i
)
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
);
414 if (rAttributeName
== "xlink:href")
416 m_ePopupState
= GetImport().FillPopupData(rAttributeValue
, aPropertyList
);
417 if (m_ePopupState
!= PopupState::NotConsumed
)
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());
428 if (m_ePopupState
!= PopupState::Ignore
)
429 GetImport().GetGenerator().openLink(aPropertyList
);
432 void XMLTextFrameHyperlinkContext::endElement(const OUString
& /*rName*/)
434 if (m_ePopupState
!= PopupState::Ignore
)
435 GetImport().GetGenerator().closeLink();
438 void XMLTextFrameHyperlinkContext::characters(const OUString
& rChars
)
440 GetImport().GetGenerator().openSpan(m_aPropertyList
);
442 OString sCharU8
= OUStringToOString(rChars
, RTL_TEXTENCODING_UTF8
);
443 GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8
.getStr()));
445 GetImport().GetGenerator().closeSpan();
450 /// Handler for <text:a>.
451 class XMLHyperlinkContext
: public XMLImportContext
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
;
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
;
466 librevenge::RVNGPropertyList m_aPropertyList
;
467 PopupState m_ePopupState
= PopupState::NONE
;
471 XMLHyperlinkContext::XMLHyperlinkContext(XMLImport
& rImport
,
472 const librevenge::RVNGPropertyList
& rPropertyList
)
473 : XMLImportContext(rImport
)
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());
481 rtl::Reference
<XMLImportContext
> XMLHyperlinkContext::CreateChildContext(
482 const OUString
& rName
, const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
484 return CreateParagraphOrSpanChildContext(GetImport(), rName
, m_aPropertyList
);
487 void XMLHyperlinkContext::startElement(
488 const OUString
& /*rName*/, const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
)
490 librevenge::RVNGPropertyList aPropertyList
;
491 for (sal_Int16 i
= 0; i
< xAttribs
->getLength(); ++i
)
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
);
501 if (rAttributeName
== "xlink:href")
503 m_ePopupState
= GetImport().FillPopupData(rAttributeValue
, aPropertyList
);
504 if (m_ePopupState
!= PopupState::NotConsumed
)
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());
515 if (m_ePopupState
!= PopupState::Ignore
)
516 GetImport().GetGenerator().openLink(aPropertyList
);
519 void XMLHyperlinkContext::endElement(const OUString
& /*rName*/)
521 if (m_ePopupState
!= PopupState::Ignore
)
522 GetImport().GetGenerator().closeLink();
525 void XMLHyperlinkContext::characters(const OUString
& rChars
)
527 GetImport().GetGenerator().openSpan(m_aPropertyList
);
529 OString sCharU8
= OUStringToOString(rChars
, RTL_TEXTENCODING_UTF8
);
530 GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8
.getStr()));
532 GetImport().GetGenerator().closeSpan();
535 XMLParaContext::XMLParaContext(XMLImport
& rImport
, bool bTopLevel
)
536 : XMLImportContext(rImport
)
537 , m_bTopLevel(bTopLevel
)
541 rtl::Reference
<XMLImportContext
> XMLParaContext::CreateChildContext(
542 const OUString
& rName
, const css::uno::Reference
<css::xml::sax::XAttributeList
>& /*xAttribs*/)
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
);
553 void XMLParaContext::startElement(
554 const OUString
& /*rName*/, const css::uno::Reference
<css::xml::sax::XAttributeList
>& xAttribs
)
556 librevenge::RVNGPropertyList aPropertyList
;
557 for (sal_Int16 i
= 0; i
< xAttribs
->getLength(); ++i
)
559 const OUString
& rAttributeName
= xAttribs
->getNameByIndex(i
);
560 const OUString
& rAttributeValue
= xAttribs
->getValueByIndex(i
);
561 if (rAttributeName
== "text:style-name")
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
);
569 GetImport().HandlePageSpan(aPropertyList
);
573 OString sName
= OUStringToOString(rAttributeName
, RTL_TEXTENCODING_UTF8
);
574 OString sValue
= OUStringToOString(rAttributeValue
, RTL_TEXTENCODING_UTF8
);
575 aPropertyList
.insert(sName
.getStr(), sValue
.getStr());
579 GetImport().GetGenerator().openParagraph(aPropertyList
);
582 void XMLParaContext::endElement(const OUString
& /*rName*/)
584 GetImport().GetGenerator().closeParagraph();
587 void XMLParaContext::characters(const OUString
& rChars
)
589 librevenge::RVNGPropertyList aPropertyList
;
590 if (!m_aStyleName
.isEmpty())
591 FillStyles(m_aStyleName
, GetImport().GetAutomaticTextStyles(), GetImport().GetTextStyles(),
593 GetImport().GetGenerator().openSpan(aPropertyList
);
595 OString sCharU8
= OUStringToOString(rChars
, RTL_TEXTENCODING_UTF8
);
596 GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8
.getStr()));
598 GetImport().GetGenerator().closeSpan();
601 rtl::Reference
<XMLImportContext
>
602 CreateParagraphOrSpanChildContext(XMLImport
& rImport
, const OUString
& rName
,
603 const librevenge::RVNGPropertyList
& rTextPropertyList
)
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
);
623 void FillStyles(const OUString
& rName
,
624 std::map
<OUString
, librevenge::RVNGPropertyList
>& rAutomaticStyles
,
625 std::map
<OUString
, librevenge::RVNGPropertyList
>& rNamedStyles
,
626 librevenge::RVNGPropertyList
& rPropertyList
)
628 FillStyle(rName
, rAutomaticStyles
, rAutomaticStyles
, rNamedStyles
, rPropertyList
);
629 FillStyle(rName
, rNamedStyles
, rAutomaticStyles
, rNamedStyles
, rPropertyList
);
632 } // namespace writerperfect
634 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */