Avoid potential negative array index access to cached text.
[LibreOffice.git] / xmloff / source / text / txtparai.cxx
blobc777fa0c292905ce9343c0177db0cdf04922f369
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
22 #include <memory>
23 #include <string_view>
24 #include <vector>
26 #include <rtl/ustring.hxx>
27 #include <rtl/ustrbuf.hxx>
28 #include <sal/log.hxx>
29 #include <comphelper/diagnose_ex.hxx>
30 #include <com/sun/star/frame/XModel.hpp>
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/text/XTextFrame.hpp>
33 #include <com/sun/star/text/XTextCursor.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/beans/XPropertySetInfo.hpp>
36 #include <com/sun/star/text/ControlCharacter.hpp>
37 #include <com/sun/star/text/XTextRangeCompare.hpp>
38 #include <com/sun/star/container/XIndexReplace.hpp>
39 #include <com/sun/star/drawing/XShapes.hpp>
40 #include <com/sun/star/container/XEnumerationAccess.hpp>
41 #include <com/sun/star/rdf/XMetadatable.hpp>
43 #include <sax/tools/converter.hxx>
45 #include <xmloff/prstylei.hxx>
46 #include <xmloff/xmlictxt.hxx>
47 #include <xmloff/xmlimp.hxx>
48 #include <xmloff/xmltoken.hxx>
49 #include <xmloff/namespacemap.hxx>
50 #include <xmloff/xmlnamespace.hxx>
51 #include <xmloff/txtimp.hxx>
52 #include "txtparai.hxx"
53 #include <txtfldi.hxx>
54 #include "XMLFootnoteImportContext.hxx"
55 #include "XMLTextMarkImportContext.hxx"
56 #include "XMLTextFrameContext.hxx"
57 #include <xmloff/XMLCharContext.hxx>
58 #include "XMLTextFrameHyperlinkContext.hxx"
59 #include <xmloff/XMLEventsImportContext.hxx>
60 #include "XMLChangeImportContext.hxx"
61 #include <txtlists.hxx>
63 #include "txtparaimphint.hxx"
64 #include "xmllinebreakcontext.hxx"
65 #include "xmlcontentcontrolcontext.hxx"
67 using namespace ::com::sun::star;
68 using namespace ::com::sun::star::uno;
69 using namespace ::com::sun::star::text;
70 using namespace ::com::sun::star::drawing;
71 using namespace ::com::sun::star::beans;
72 using namespace ::xmloff::token;
73 using ::com::sun::star::container::XEnumerationAccess;
74 using ::com::sun::star::container::XEnumeration;
76 class XMLHints_Impl
78 private:
80 std::vector<std::unique_ptr<XMLHint_Impl>> m_Hints;
81 std::unordered_map<OUString, XMLIndexMarkHint_Impl*> m_IndexHintsById;
82 uno::Reference<uno::XInterface> m_xCrossRefHeadingBookmark;
84 public:
85 void push_back(std::unique_ptr<XMLHint_Impl> pHint)
87 m_Hints.push_back(std::move(pHint));
90 void push_back(std::unique_ptr<XMLIndexMarkHint_Impl> pHint)
92 m_IndexHintsById.emplace(pHint->GetID(), pHint.get());
93 m_Hints.push_back(std::move(pHint));
96 std::vector<std::unique_ptr<XMLHint_Impl>> const& GetHints() const
98 return m_Hints;
101 XMLIndexMarkHint_Impl* GetIndexHintById(const OUString& sID)
103 auto it = m_IndexHintsById.find(sID);
104 return it == m_IndexHintsById.end() ? nullptr : it->second;
107 uno::Reference<uno::XInterface> & GetCrossRefHeadingBookmark()
109 return m_xCrossRefHeadingBookmark;
114 XMLCharContext::XMLCharContext(
115 SvXMLImport& rImport,
116 const Reference< xml::sax::XFastAttributeList > & xAttrList,
117 sal_Unicode c,
118 bool bCount ) :
119 SvXMLImportContext( rImport )
120 ,m_nControl(0)
121 ,m_nCount(1)
122 ,m_c(c)
124 if( !bCount )
125 return;
127 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
129 if( aIter.getToken() == XML_ELEMENT(TEXT, XML_C) )
131 sal_Int32 nTmp = aIter.toInt32();
132 if( nTmp > 0 )
134 if( nTmp > SAL_MAX_UINT16 )
135 m_nCount = SAL_MAX_UINT16;
136 else
137 m_nCount = static_cast<sal_uInt16>(nTmp);
140 else
141 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
145 XMLCharContext::XMLCharContext(
146 SvXMLImport& rImp,
147 sal_Int16 nControl ) :
148 SvXMLImportContext( rImp )
149 ,m_nControl(nControl)
150 ,m_nCount(0)
151 ,m_c(0)
155 XMLCharContext::~XMLCharContext()
158 void XMLCharContext::endFastElement(sal_Int32 )
160 if ( !m_nCount )
161 InsertControlCharacter( m_nControl );
162 else
164 if( 1U == m_nCount )
166 OUString sBuff( &m_c, 1 );
167 InsertString(sBuff);
169 else
171 OUStringBuffer sBuff(static_cast<int>(m_nCount));
172 while( m_nCount-- )
173 sBuff.append( &m_c, 1 );
175 InsertString(sBuff.makeStringAndClear() );
179 void XMLCharContext::InsertControlCharacter(sal_Int16 _nControl)
181 GetImport().GetTextImport()->InsertControlCharacter( _nControl );
183 void XMLCharContext::InsertString(const OUString& _sString)
185 GetImport().GetTextImport()->InsertString( _sString );
188 namespace {
190 /** import start of reference (<text:reference-start>) */
191 class XMLStartReferenceContext_Impl : public SvXMLImportContext
193 public:
195 // Do everything in constructor. Well ...
196 XMLStartReferenceContext_Impl (
197 SvXMLImport& rImport,
198 XMLHints_Impl& rHints,
199 const Reference<xml::sax::XFastAttributeList> & xAttrList);
201 static bool FindName(
202 const Reference<xml::sax::XFastAttributeList> & xAttrList,
203 OUString& rName);
208 XMLStartReferenceContext_Impl::XMLStartReferenceContext_Impl(
209 SvXMLImport& rImport,
210 XMLHints_Impl& rHints,
211 const Reference<xml::sax::XFastAttributeList> & xAttrList) :
212 SvXMLImportContext(rImport)
214 OUString sName;
216 if (FindName(xAttrList, sName))
218 std::unique_ptr<XMLHint_Impl> pHint(new XMLReferenceHint_Impl(
219 sName, rImport.GetTextImport()->GetCursor()->getStart()));
221 // degenerates to point reference, if no end is found!
222 pHint->SetEnd(rImport.GetTextImport()->GetCursor()->getStart() );
224 rHints.push_back(std::move(pHint));
228 bool XMLStartReferenceContext_Impl::FindName(
229 const Reference<xml::sax::XFastAttributeList> & xAttrList,
230 OUString& rName)
232 bool bNameOK( false );
234 // find name attribute first
235 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
237 if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_NAME) )
239 rName = aIter.toString();
240 bNameOK = true;
241 break;
245 return bNameOK;
248 namespace {
250 /** import end of reference (<text:reference-end>) */
251 class XMLEndReferenceContext_Impl : public SvXMLImportContext
253 public:
255 // Do everything in constructor. Well ...
256 XMLEndReferenceContext_Impl(
257 SvXMLImport& rImport,
258 const XMLHints_Impl& rHints,
259 const Reference<xml::sax::XFastAttributeList> & xAttrList);
264 XMLEndReferenceContext_Impl::XMLEndReferenceContext_Impl(
265 SvXMLImport& rImport,
266 const XMLHints_Impl& rHints,
267 const Reference<xml::sax::XFastAttributeList> & xAttrList) :
268 SvXMLImportContext(rImport)
270 OUString sName;
272 // borrow from XMLStartReferenceContext_Impl
273 if (!XMLStartReferenceContext_Impl::FindName(xAttrList, sName))
274 return;
276 // search for reference start
277 for (const auto& rHintPtr : rHints.GetHints())
279 XMLHint_Impl *const pHint = rHintPtr.get();
280 if ( pHint->IsReference() &&
281 sName == static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName() )
283 // set end and stop searching
284 pHint->SetEnd(GetImport().GetTextImport()->
285 GetCursor()->getStart() );
286 break;
289 // else: no start (in this paragraph) -> ignore
292 namespace {
294 class XMLImpHyperlinkContext_Impl : public SvXMLImportContext
296 XMLHints_Impl& m_rHints;
297 XMLHyperlinkHint_Impl *mpHint;
299 bool& mrbIgnoreLeadingSpace;
301 public:
304 XMLImpHyperlinkContext_Impl(
305 SvXMLImport& rImport,
306 sal_Int32 nElement,
307 const Reference< xml::sax::XFastAttributeList > & xAttrList,
308 XMLHints_Impl& rHints,
309 bool& rIgnLeadSpace );
311 virtual ~XMLImpHyperlinkContext_Impl() override;
313 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
314 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
316 virtual void SAL_CALL characters( const OUString& rChars ) override;
321 XMLImpHyperlinkContext_Impl::XMLImpHyperlinkContext_Impl(
322 SvXMLImport& rImport,
323 sal_Int32 /*nElement*/,
324 const Reference< xml::sax::XFastAttributeList > & xAttrList,
325 XMLHints_Impl& rHints,
326 bool& rIgnLeadSpace )
327 : SvXMLImportContext( rImport )
328 , m_rHints( rHints )
329 , mpHint( new XMLHyperlinkHint_Impl( GetImport().GetTextImport()->GetCursorAsRange()->getStart() ) )
330 , mrbIgnoreLeadingSpace( rIgnLeadSpace )
332 OUString sShow;
334 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
336 OUString sValue = aIter.toString();
337 switch (aIter.getToken())
339 case XML_ELEMENT(XLINK, XML_HREF):
340 mpHint->SetHRef( GetImport().GetAbsoluteReference( sValue ) );
341 break;
342 case XML_ELEMENT(OFFICE, XML_NAME):
343 mpHint->SetName( sValue );
344 break;
345 case XML_ELEMENT(OFFICE, XML_TARGET_FRAME_NAME):
346 mpHint->SetTargetFrameName( sValue );
347 break;
348 case XML_ELEMENT(XLINK, XML_SHOW):
349 sShow = sValue;
350 break;
351 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
352 mpHint->SetStyleName( sValue );
353 break;
354 case XML_ELEMENT(TEXT, XML_VISITED_STYLE_NAME):
355 mpHint->SetVisitedStyleName( sValue );
356 break;
357 default:
358 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
362 if( !sShow.isEmpty() && mpHint->GetTargetFrameName().isEmpty() )
364 if( IsXMLToken( sShow, XML_NEW ) )
365 mpHint->SetTargetFrameName(
366 "_blank" );
367 else if( IsXMLToken( sShow, XML_REPLACE ) )
368 mpHint->SetTargetFrameName(
369 "_self" );
372 if ( mpHint->GetHRef().isEmpty() )
374 // hyperlink without a URL is not imported.
375 delete mpHint;
376 mpHint = nullptr;
378 else
380 m_rHints.push_back(std::unique_ptr<XMLHyperlinkHint_Impl>(mpHint));
384 XMLImpHyperlinkContext_Impl::~XMLImpHyperlinkContext_Impl()
386 if (mpHint)
387 mpHint->SetEnd( GetImport().GetTextImport()
388 ->GetCursorAsRange()->getStart() );
391 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpHyperlinkContext_Impl::createFastChildContext(
392 sal_Int32 nElement,
393 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
395 if ( nElement == XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS) )
397 XMLEventsImportContext* pCtxt = new XMLEventsImportContext(GetImport());
398 if (mpHint)
399 mpHint->SetEventsContext(pCtxt);
400 return pCtxt;
402 else
404 return XMLImpSpanContext_Impl::CreateSpanContext(
405 GetImport(), nElement, xAttrList,
406 m_rHints, mrbIgnoreLeadingSpace );
410 void XMLImpHyperlinkContext_Impl::characters( const OUString& rChars )
412 GetImport().GetTextImport()->InsertString( rChars, mrbIgnoreLeadingSpace );
415 namespace {
417 class XMLImpRubyBaseContext_Impl : public SvXMLImportContext
419 XMLHints_Impl& m_rHints;
421 bool& rIgnoreLeadingSpace;
423 public:
426 XMLImpRubyBaseContext_Impl(
427 SvXMLImport& rImport,
428 sal_Int32 nElement,
429 const Reference< xml::sax::XFastAttributeList > & xAttrList,
430 XMLHints_Impl& rHints,
431 bool& rIgnLeadSpace );
433 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
434 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
436 virtual void SAL_CALL characters( const OUString& rChars ) override;
441 XMLImpRubyBaseContext_Impl::XMLImpRubyBaseContext_Impl(
442 SvXMLImport& rImport,
443 sal_Int32 /*nElement*/,
444 const Reference< xml::sax::XFastAttributeList > &,
445 XMLHints_Impl& rHints,
446 bool& rIgnLeadSpace )
447 : SvXMLImportContext( rImport )
448 , m_rHints( rHints )
449 , rIgnoreLeadingSpace( rIgnLeadSpace )
453 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyBaseContext_Impl::createFastChildContext(
454 sal_Int32 nElement,
455 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
457 return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement, xAttrList,
458 m_rHints, rIgnoreLeadingSpace );
461 void XMLImpRubyBaseContext_Impl::characters( const OUString& rChars )
463 GetImport().GetTextImport()->InsertString( rChars, rIgnoreLeadingSpace );
466 namespace {
468 class XMLImpRubyContext_Impl : public SvXMLImportContext
470 XMLHints_Impl& m_rHints;
472 bool& rIgnoreLeadingSpace;
474 Reference < XTextRange > m_xStart;
475 OUString m_sStyleName;
476 OUString m_sTextStyleName;
477 OUString m_sText;
479 public:
482 XMLImpRubyContext_Impl(
483 SvXMLImport& rImport,
484 sal_Int32 nElement,
485 const Reference< xml::sax::XFastAttributeList > & xAttrList,
486 XMLHints_Impl& rHints,
487 bool& rIgnLeadSpace );
489 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
491 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
492 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
494 void SetTextStyleName( const OUString& s ) { m_sTextStyleName = s; }
495 void AppendText( std::u16string_view s ) { m_sText += s; }
498 class XMLImpRubyTextContext_Impl : public SvXMLImportContext
500 XMLImpRubyContext_Impl & m_rRubyContext;
502 public:
505 XMLImpRubyTextContext_Impl(
506 SvXMLImport& rImport,
507 sal_Int32 nElement,
508 const Reference< xml::sax::XFastAttributeList > & xAttrList,
509 XMLImpRubyContext_Impl & rParent );
511 virtual void SAL_CALL characters( const OUString& rChars ) override;
516 XMLImpRubyTextContext_Impl::XMLImpRubyTextContext_Impl(
517 SvXMLImport& rImport,
518 sal_Int32 /*nElement*/,
519 const Reference< xml::sax::XFastAttributeList > & xAttrList,
520 XMLImpRubyContext_Impl & rParent )
521 : SvXMLImportContext( rImport )
522 , m_rRubyContext( rParent )
524 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
526 if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
528 m_rRubyContext.SetTextStyleName( aIter.toString() );
529 break;
534 void XMLImpRubyTextContext_Impl::characters( const OUString& rChars )
536 m_rRubyContext.AppendText( rChars );
540 XMLImpRubyContext_Impl::XMLImpRubyContext_Impl(
541 SvXMLImport& rImport,
542 sal_Int32 /*nElement*/,
543 const Reference< xml::sax::XFastAttributeList > & xAttrList,
544 XMLHints_Impl& rHints,
545 bool& rIgnLeadSpace )
546 : SvXMLImportContext( rImport )
547 , m_rHints( rHints )
548 , rIgnoreLeadingSpace( rIgnLeadSpace )
549 , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
551 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
553 if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
555 m_sStyleName = aIter.toString();
556 break;
561 void XMLImpRubyContext_Impl::endFastElement(sal_Int32 )
563 const rtl::Reference < XMLTextImportHelper > xTextImport(
564 GetImport().GetTextImport());
565 const Reference < XTextCursor > xAttrCursor(
566 xTextImport->GetText()->createTextCursorByRange( m_xStart ));
567 if (!xAttrCursor.is())
569 SAL_WARN("xmloff.text", "cannot insert ruby");
570 return;
572 xAttrCursor->gotoRange(xTextImport->GetCursorAsRange()->getStart(),
573 true);
574 xTextImport->SetRuby( GetImport(), xAttrCursor,
575 m_sStyleName, m_sTextStyleName, m_sText );
578 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpRubyContext_Impl::createFastChildContext(
579 sal_Int32 nElement,
580 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
582 if( nElement == XML_ELEMENT(TEXT, XML_RUBY_BASE) )
583 return new XMLImpRubyBaseContext_Impl( GetImport(), nElement,
584 xAttrList,
585 m_rHints,
586 rIgnoreLeadingSpace );
587 else if( nElement == XML_ELEMENT(TEXT, XML_RUBY_TEXT) )
588 return new XMLImpRubyTextContext_Impl( GetImport(), nElement,
589 xAttrList,
590 *this );
591 else
592 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
594 return nullptr;
597 namespace {
599 /** for text:meta and text:meta-field
601 class XMLMetaImportContextBase : public SvXMLImportContext
603 XMLHints_Impl& m_rHints;
605 bool& m_rIgnoreLeadingSpace;
607 /// start position
608 Reference<XTextRange> m_xStart;
610 protected:
611 OUString m_XmlId;
613 public:
615 XMLMetaImportContextBase(
616 SvXMLImport& i_rImport,
617 const sal_Int32 nElement,
618 XMLHints_Impl& i_rHints,
619 bool & i_rIgnoreLeadingSpace );
621 virtual void SAL_CALL startFastElement(
622 sal_Int32 nElement,
623 const Reference<xml::sax::XFastAttributeList> & i_xAttrList) override;
625 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
627 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
628 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
630 virtual void SAL_CALL characters( const OUString& i_rChars ) override;
632 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter);
634 virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange)
635 = 0;
640 XMLMetaImportContextBase::XMLMetaImportContextBase(
641 SvXMLImport& i_rImport,
642 const sal_Int32 /*i_nElement*/,
643 XMLHints_Impl& i_rHints,
644 bool & i_rIgnoreLeadingSpace )
645 : SvXMLImportContext( i_rImport )
646 , m_rHints( i_rHints )
647 , m_rIgnoreLeadingSpace( i_rIgnoreLeadingSpace )
648 , m_xStart( GetImport().GetTextImport()->GetCursorAsRange()->getStart() )
652 void XMLMetaImportContextBase::startFastElement(
653 sal_Int32 /*nElement*/,
654 const Reference<xml::sax::XFastAttributeList> & xAttrList)
656 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
657 ProcessAttribute(aIter);
660 void XMLMetaImportContextBase::endFastElement(sal_Int32 )
662 SAL_WARN_IF(!m_xStart.is(), "xmloff.text", "no mxStart?");
663 if (!m_xStart.is()) return;
665 const Reference<XTextRange> xEndRange(
666 GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
668 // create range for insertion
669 const Reference<XTextCursor> xInsertionCursor(
670 GetImport().GetTextImport()->GetText()->createTextCursorByRange(
671 xEndRange) );
672 xInsertionCursor->gotoRange(m_xStart, true);
674 InsertMeta(xInsertionCursor);
677 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLMetaImportContextBase::createFastChildContext(
678 sal_Int32 nElement,
679 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
681 return XMLImpSpanContext_Impl::CreateSpanContext( GetImport(), nElement,
682 xAttrList, m_rHints, m_rIgnoreLeadingSpace );
685 void XMLMetaImportContextBase::characters( const OUString& i_rChars )
687 GetImport().GetTextImport()->InsertString(i_rChars, m_rIgnoreLeadingSpace);
690 void XMLMetaImportContextBase::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
692 if ( aIter.getToken() == XML_ELEMENT(XML, XML_ID) )
693 m_XmlId = aIter.toString();
694 else
695 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
698 namespace {
700 /** text:meta */
701 class XMLMetaImportContext : public XMLMetaImportContextBase
703 // RDFa
704 bool m_bHaveAbout;
705 OUString m_sAbout;
706 OUString m_sProperty;
707 OUString m_sContent;
708 OUString m_sDatatype;
710 public:
712 XMLMetaImportContext(
713 SvXMLImport& i_rImport,
714 sal_Int32 nElement,
715 XMLHints_Impl& i_rHints,
716 bool & i_rIgnoreLeadingSpace );
718 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
720 virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
725 XMLMetaImportContext::XMLMetaImportContext(
726 SvXMLImport& i_rImport,
727 sal_Int32 nElement,
728 XMLHints_Impl& i_rHints,
729 bool & i_rIgnoreLeadingSpace )
730 : XMLMetaImportContextBase( i_rImport, nElement,
731 i_rHints, i_rIgnoreLeadingSpace )
732 , m_bHaveAbout(false)
736 void XMLMetaImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
738 switch (aIter.getToken())
740 // RDFa
741 case XML_ELEMENT(XHTML, XML_ABOUT):
742 m_sAbout = aIter.toString();
743 m_bHaveAbout = true;
744 break;
745 case XML_ELEMENT(XHTML, XML_PROPERTY):
746 m_sProperty = aIter.toString();
747 break;
748 case XML_ELEMENT(XHTML, XML_CONTENT):
749 m_sContent = aIter.toString();
750 break;
751 case XML_ELEMENT(XHTML, XML_DATATYPE):
752 m_sDatatype = aIter.toString();
753 break;
754 default:
755 XMLMetaImportContextBase::ProcessAttribute(aIter);
759 void XMLMetaImportContext::InsertMeta(
760 const Reference<XTextRange> & i_xInsertionRange)
762 SAL_WARN_IF(m_bHaveAbout == m_sProperty.isEmpty(), "xmloff.text", "XMLMetaImportContext::InsertMeta: invalid RDFa?");
763 if (!m_XmlId.isEmpty() || (m_bHaveAbout && !m_sProperty.isEmpty()))
765 // insert mark
766 const uno::Reference<rdf::XMetadatable> xMeta(
767 XMLTextMarkImportContext::CreateAndInsertMark(
768 GetImport(),
769 "com.sun.star.text.InContentMetadata",
770 OUString(),
771 i_xInsertionRange, m_XmlId),
772 uno::UNO_QUERY);
773 SAL_WARN_IF(!xMeta.is(), "xmloff.text", "cannot insert Meta?");
775 if (xMeta.is() && m_bHaveAbout)
777 GetImport().AddRDFa(xMeta,
778 m_sAbout, m_sProperty, m_sContent, m_sDatatype);
781 else
783 SAL_INFO("xmloff.text", "invalid <text:meta>: no xml:id, no valid RDFa");
787 namespace {
789 /** text:meta-field */
790 class XMLMetaFieldImportContext : public XMLMetaImportContextBase
792 OUString m_DataStyleName;
794 public:
796 XMLMetaFieldImportContext(
797 SvXMLImport& i_rImport,
798 sal_Int32 nElement,
799 XMLHints_Impl& i_rHints,
800 bool & i_rIgnoreLeadingSpace );
802 virtual void ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter) override;
804 virtual void InsertMeta(const Reference<XTextRange> & i_xInsertionRange) override;
809 XMLMetaFieldImportContext::XMLMetaFieldImportContext(
810 SvXMLImport& i_rImport,
811 sal_Int32 nElement,
812 XMLHints_Impl& i_rHints,
813 bool & i_rIgnoreLeadingSpace )
814 : XMLMetaImportContextBase( i_rImport, nElement,
815 i_rHints, i_rIgnoreLeadingSpace )
819 void XMLMetaFieldImportContext::ProcessAttribute(const sax_fastparser::FastAttributeList::FastAttributeIter & aIter)
821 switch (aIter.getToken())
823 case XML_ELEMENT(STYLE, XML_DATA_STYLE_NAME):
824 m_DataStyleName = aIter.toString();
825 break;
826 default:
827 XMLMetaImportContextBase::ProcessAttribute(aIter);
831 void XMLMetaFieldImportContext::InsertMeta(
832 const Reference<XTextRange> & i_xInsertionRange)
834 if (!m_XmlId.isEmpty()) // valid?
836 // insert mark
837 const Reference<XPropertySet> xPropertySet(
838 XMLTextMarkImportContext::CreateAndInsertMark(
839 GetImport(),
840 "com.sun.star.text.textfield.MetadataField",
841 OUString(),
842 i_xInsertionRange, m_XmlId),
843 UNO_QUERY);
844 SAL_WARN_IF(!xPropertySet.is(), "xmloff.text", "cannot insert MetaField?");
845 if (!xPropertySet.is()) return;
847 if (!m_DataStyleName.isEmpty())
849 bool isDefaultLanguage(true);
851 const sal_Int32 nKey( GetImport().GetTextImport()->GetDataStyleKey(
852 m_DataStyleName, & isDefaultLanguage) );
854 if (-1 != nKey)
856 OUString sPropertyIsFixedLanguage("IsFixedLanguage");
857 xPropertySet->setPropertyValue("NumberFormat", Any(nKey));
858 if ( xPropertySet->getPropertySetInfo()->
859 hasPropertyByName( sPropertyIsFixedLanguage ) )
861 xPropertySet->setPropertyValue( sPropertyIsFixedLanguage,
862 Any(!isDefaultLanguage) );
867 else
869 SAL_INFO("xmloff.text", "invalid <text:meta-field>: no xml:id");
873 namespace {
876 * Process index marks.
878 * All *-mark-end index marks should instantiate *this* class (because
879 * it doesn't process attributes other than ID), while the *-mark and
880 * *-mark-start classes should instantiate the appropriate subclasses.
882 class XMLIndexMarkImportContext_Impl : public SvXMLImportContext
884 XMLHints_Impl& m_rHints;
885 OUString sID;
887 public:
889 XMLIndexMarkImportContext_Impl(
890 SvXMLImport& rImport,
891 XMLHints_Impl& rHints);
893 void SAL_CALL startFastElement(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList) override;
895 protected:
897 /// process all attributes
898 void ProcessAttributes(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList,
899 Reference<beans::XPropertySet>& rPropSet);
902 * All marks can be created immediately. Since we don't care about
903 * the element content, ProcessAttribute should set the properties
904 * immediately.
906 * This method tolerates an empty PropertySet; subclasses however
907 * are not expected to.
909 virtual void ProcessAttribute(sal_Int32 nElement,
910 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
911 Reference<beans::XPropertySet>& rPropSet);
913 static void GetServiceName(OUString& sServiceName,
914 sal_Int32 nElement);
916 bool CreateMark(Reference<beans::XPropertySet>& rPropSet,
917 const OUString& rServiceName);
922 XMLIndexMarkImportContext_Impl::XMLIndexMarkImportContext_Impl(
923 SvXMLImport& rImport,
924 XMLHints_Impl& rHints)
925 : SvXMLImportContext(rImport)
926 , m_rHints(rHints)
930 void XMLIndexMarkImportContext_Impl::startFastElement(
931 sal_Int32 nElement,
932 const Reference<xml::sax::XFastAttributeList> & xAttrList)
934 // get Cursor position (needed for all cases)
935 Reference<XTextRange> xPos(
936 GetImport().GetTextImport()->GetCursor()->getStart());
937 Reference<beans::XPropertySet> xMark;
939 switch (nElement)
941 case XML_ELEMENT(TEXT, XML_TOC_MARK):
942 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
943 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
945 // single mark: create mark and insert
946 OUString sService;
947 GetServiceName(sService, nElement);
948 if (CreateMark(xMark, sService))
950 ProcessAttributes(nElement, xAttrList, xMark);
951 m_rHints.push_back(
952 std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos));
954 // else: can't create mark -> ignore
955 break;
958 case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
959 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
960 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
962 // start: create mark and insert (if ID is found)
963 OUString sService;
964 GetServiceName(sService, nElement);
965 if (CreateMark(xMark, sService))
967 ProcessAttributes(nElement, xAttrList, xMark);
968 if (!sID.isEmpty())
970 // process only if we find an ID
971 m_rHints.push_back(
972 std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos, sID));
974 // else: no ID -> we'll never find the end -> ignore
976 // else: can't create mark -> ignore
977 break;
980 case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
981 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
982 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
984 // end: search for ID and set end of mark
986 // call process attributes with empty XPropertySet:
987 ProcessAttributes(nElement, xAttrList, xMark);
988 if (!sID.isEmpty())
990 // if we have an ID, find the hint and set the end position
991 XMLIndexMarkHint_Impl *const pHint = m_rHints.GetIndexHintById(sID);
992 if (pHint)
993 // set end and stop searching
994 pHint->SetEnd(xPos);
996 // else: no ID -> ignore
997 break;
1000 default:
1001 SAL_WARN("xmloff.text", "unknown index mark type!");
1002 break;
1006 void XMLIndexMarkImportContext_Impl::ProcessAttributes(
1007 sal_Int32 nElement,
1008 const Reference<xml::sax::XFastAttributeList> & xAttrList,
1009 Reference<beans::XPropertySet>& rPropSet)
1011 // process attributes
1012 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
1014 ProcessAttribute(nElement, aIter, rPropSet);
1018 void XMLIndexMarkImportContext_Impl::ProcessAttribute(
1019 sal_Int32 nElement,
1020 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1021 Reference<beans::XPropertySet>& rPropSet)
1023 // we only know ID + string-value attribute;
1024 // (former: marks, latter: -start + -end-marks)
1025 // the remainder is handled in sub-classes
1026 switch (nElement)
1028 case XML_ELEMENT(TEXT, XML_TOC_MARK):
1029 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1030 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1031 if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STRING_VALUE) )
1033 rPropSet->setPropertyValue("AlternativeText", uno::Any(aIter.toString()));
1035 // else: ignore!
1036 break;
1038 case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1039 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1040 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1041 case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1042 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1043 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1044 if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
1046 sID = aIter.toString();
1048 // else: ignore
1049 break;
1051 default:
1052 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1053 break;
1058 void XMLIndexMarkImportContext_Impl::GetServiceName(
1059 OUString& sServiceName,
1060 sal_Int32 nElement)
1062 switch (nElement)
1064 case XML_ELEMENT(TEXT, XML_TOC_MARK):
1065 case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1066 case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1068 sServiceName = "com.sun.star.text.ContentIndexMark";
1069 break;
1072 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1073 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1074 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1076 sServiceName = "com.sun.star.text.UserIndexMark";
1077 break;
1080 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1081 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1082 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1084 sServiceName = "com.sun.star.text.DocumentIndexMark";
1085 break;
1088 default:
1090 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1091 sServiceName.clear();
1092 break;
1097 bool XMLIndexMarkImportContext_Impl::CreateMark(
1098 Reference<beans::XPropertySet>& rPropSet,
1099 const OUString& rServiceName)
1101 Reference<lang::XMultiServiceFactory>
1102 xFactory(GetImport().GetModel(), UNO_QUERY);
1104 if( xFactory.is() )
1106 Reference<beans::XPropertySet> xPropSet( xFactory->createInstance(rServiceName), UNO_QUERY );
1107 if (xPropSet.is())
1108 rPropSet = xPropSet;
1109 return true;
1112 return false;
1115 namespace {
1117 class XMLTOCMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1119 public:
1121 XMLTOCMarkImportContext_Impl(
1122 SvXMLImport& rImport,
1123 XMLHints_Impl& rHints);
1125 protected:
1127 /** process outline level */
1128 virtual void ProcessAttribute(sal_Int32 nElement,
1129 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1130 Reference<beans::XPropertySet>& rPropSet) override;
1135 XMLTOCMarkImportContext_Impl::XMLTOCMarkImportContext_Impl(
1136 SvXMLImport& rImport, XMLHints_Impl& rHints) :
1137 XMLIndexMarkImportContext_Impl(rImport, rHints)
1141 void XMLTOCMarkImportContext_Impl::ProcessAttribute(
1142 sal_Int32 nElement,
1143 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1144 Reference<beans::XPropertySet>& rPropSet)
1146 SAL_WARN_IF(!rPropSet.is(), "xmloff.text", "need PropertySet");
1148 switch (aIter.getToken())
1150 case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1152 // outline level: set Level property
1153 sal_Int32 nTmp;
1154 if (::sax::Converter::convertNumber( nTmp, aIter.toView() )
1155 && nTmp >= 1
1156 && nTmp < GetImport().GetTextImport()->
1157 GetChapterNumbering()->getCount() )
1159 rPropSet->setPropertyValue("Level", uno::Any(static_cast<sal_Int16>(nTmp - 1)));
1161 // else: value out of range -> ignore
1162 break;
1164 default:
1165 // else: delegate to superclass
1166 XMLIndexMarkImportContext_Impl::ProcessAttribute(
1167 nElement, aIter, rPropSet);
1171 namespace {
1173 class XMLUserIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1175 public:
1177 XMLUserIndexMarkImportContext_Impl(
1178 SvXMLImport& rImport,
1179 XMLHints_Impl& rHints);
1181 protected:
1183 /** process index name */
1184 virtual void ProcessAttribute(sal_Int32 nElement,
1185 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1186 Reference<beans::XPropertySet>& rPropSet) override;
1191 XMLUserIndexMarkImportContext_Impl::XMLUserIndexMarkImportContext_Impl(
1192 SvXMLImport& rImport, XMLHints_Impl& rHints) :
1193 XMLIndexMarkImportContext_Impl(rImport, rHints)
1197 void XMLUserIndexMarkImportContext_Impl::ProcessAttribute(
1198 sal_Int32 nElement,
1199 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1200 Reference<beans::XPropertySet>& rPropSet)
1202 switch (aIter.getToken())
1204 case XML_ELEMENT(TEXT, XML_INDEX_NAME):
1205 rPropSet->setPropertyValue("UserIndexName", uno::Any(aIter.toString()));
1206 break;
1207 case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1209 // outline level: set Level property
1210 sal_Int32 nTmp;
1211 if (::sax::Converter::convertNumber(
1212 nTmp, aIter.toView(), 0,
1213 GetImport().GetTextImport()->GetChapterNumbering()->getCount()))
1215 rPropSet->setPropertyValue("Level", uno::Any(static_cast<sal_Int16>(nTmp - 1)));
1217 // else: value out of range -> ignore
1218 break;
1220 default:
1221 // else: unknown text property: delegate to super class
1222 XMLIndexMarkImportContext_Impl::ProcessAttribute(
1223 nElement, aIter, rPropSet);
1227 namespace {
1229 class XMLAlphaIndexMarkImportContext_Impl : public XMLIndexMarkImportContext_Impl
1231 public:
1233 XMLAlphaIndexMarkImportContext_Impl(
1234 SvXMLImport& rImport,
1235 XMLHints_Impl& rHints);
1237 protected:
1239 /** process primary + secondary keys */
1240 virtual void ProcessAttribute(sal_Int32 nElement,
1241 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1242 Reference<beans::XPropertySet>& rPropSet) override;
1247 XMLAlphaIndexMarkImportContext_Impl::XMLAlphaIndexMarkImportContext_Impl(
1248 SvXMLImport& rImport, XMLHints_Impl& rHints) :
1249 XMLIndexMarkImportContext_Impl(rImport, rHints)
1253 void XMLAlphaIndexMarkImportContext_Impl::ProcessAttribute(
1254 sal_Int32 nElement,
1255 const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
1256 Reference<beans::XPropertySet>& rPropSet)
1258 switch (aIter.getToken())
1260 case XML_ELEMENT(TEXT, XML_KEY1):
1261 rPropSet->setPropertyValue("PrimaryKey", uno::Any(aIter.toString()));
1262 break;
1263 case XML_ELEMENT(TEXT, XML_KEY2):
1264 rPropSet->setPropertyValue("SecondaryKey", uno::Any(aIter.toString()));
1265 break;
1266 case XML_ELEMENT(TEXT, XML_KEY1_PHONETIC):
1267 rPropSet->setPropertyValue("PrimaryKeyReading", uno::Any(aIter.toString()));
1268 break;
1269 case XML_ELEMENT(TEXT, XML_KEY2_PHONETIC):
1270 rPropSet->setPropertyValue("SecondaryKeyReading", uno::Any(aIter.toString()));
1271 break;
1272 case XML_ELEMENT(TEXT, XML_STRING_VALUE_PHONETIC):
1273 rPropSet->setPropertyValue("TextReading", uno::Any(aIter.toString()));
1274 break;
1275 case XML_ELEMENT(TEXT, XML_MAIN_ENTRY):
1277 bool bMainEntry = false;
1278 bool bTmp(false);
1280 if (::sax::Converter::convertBool(bTmp, aIter.toView()))
1281 bMainEntry = bTmp;
1283 rPropSet->setPropertyValue("IsMainEntry", uno::Any(bMainEntry));
1284 break;
1286 default:
1287 XMLIndexMarkImportContext_Impl::ProcessAttribute(
1288 nElement, aIter, rPropSet);
1293 XMLImpSpanContext_Impl::XMLImpSpanContext_Impl(
1294 SvXMLImport& rImport,
1295 sal_Int32 /*nElement*/,
1296 const Reference< xml::sax::XFastAttributeList > & xAttrList,
1297 XMLHints_Impl& rHints,
1298 bool& rIgnLeadSpace,
1299 sal_uInt8 nSFConvFlags)
1300 : SvXMLImportContext( rImport )
1301 , m_rHints( rHints )
1302 , pHint( nullptr )
1303 , rIgnoreLeadingSpace( rIgnLeadSpace )
1304 , nStarFontsConvFlags( nSFConvFlags & (CONV_FROM_STAR_BATS|CONV_FROM_STAR_MATH) )
1306 OUString aStyleName;
1308 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1310 if( aIter.getToken() == XML_ELEMENT(TEXT, XML_STYLE_NAME) )
1312 aStyleName = aIter.toString();
1313 break;
1317 if( !aStyleName.isEmpty() )
1319 pHint = new XMLStyleHint_Impl( aStyleName,
1320 GetImport().GetTextImport()->GetCursorAsRange()->getStart() );
1321 m_rHints.push_back(std::unique_ptr<XMLStyleHint_Impl>(pHint));
1325 void XMLImpSpanContext_Impl::endFastElement(sal_Int32 )
1327 if (!pHint)
1328 return;
1330 Reference<XTextRange> xCrsrRange(GetImport().GetTextImport()->GetCursorAsRange());
1331 if (!xCrsrRange.is())
1332 return; // Robust (defective file)
1334 pHint->SetEnd(xCrsrRange->getStart());
1337 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::CreateSpanContext(
1338 SvXMLImport& rImport,
1339 sal_Int32 nElement,
1340 const Reference< xml::sax::XFastAttributeList > & xAttrList,
1341 XMLHints_Impl& rHints,
1342 bool& rIgnoreLeadingSpace,
1343 sal_uInt8 nStarFontsConvFlags
1346 SvXMLImportContext *pContext = nullptr;
1348 switch( nElement )
1350 case XML_ELEMENT(TEXT, XML_SPAN):
1351 pContext = new XMLImpSpanContext_Impl( rImport, nElement,
1352 xAttrList,
1353 rHints,
1354 rIgnoreLeadingSpace
1355 ,nStarFontsConvFlags
1357 break;
1359 case XML_ELEMENT(TEXT, XML_TAB):
1360 pContext = new XMLCharContext( rImport, xAttrList,
1361 0x0009, false );
1362 rIgnoreLeadingSpace = false;
1363 break;
1365 case XML_ELEMENT(TEXT, XML_LINE_BREAK):
1366 if (xAttrList->hasAttribute(XML_ELEMENT(LO_EXT, XML_CLEAR)))
1368 pContext = new SvXMLLineBreakContext(rImport, *rImport.GetTextImport());
1370 else
1372 pContext = new XMLCharContext(rImport, ControlCharacter::LINE_BREAK);
1374 rIgnoreLeadingSpace = false;
1375 break;
1377 case XML_ELEMENT(TEXT, XML_S):
1378 pContext = new XMLCharContext( rImport, xAttrList, 0x0020, true );
1379 rIgnoreLeadingSpace = false;
1380 break;
1382 case XML_ELEMENT(TEXT, XML_A):
1384 // test for HyperLinkURL property. If present, insert link as
1385 // text property (StarWriter), else try to insert as text
1386 // field (StarCalc, StarDraw, ...)
1387 Reference< beans::XPropertySet > xPropSet( rImport.GetTextImport()->GetCursor(), UNO_QUERY );
1389 if ( xPropSet->getPropertySetInfo()->hasPropertyByName( "HyperLinkURL" ) )
1391 pContext = new XMLImpHyperlinkContext_Impl(
1392 rImport,
1393 nElement,
1394 xAttrList,
1395 rHints,
1396 rIgnoreLeadingSpace );
1398 else
1400 pContext = new XMLUrlFieldImportContext(rImport, *rImport.GetTextImport());
1401 //whitespace handling like other fields
1402 rIgnoreLeadingSpace = false;
1405 break;
1408 case XML_ELEMENT(TEXT, XML_RUBY):
1409 pContext = new XMLImpRubyContext_Impl( rImport, nElement,
1410 xAttrList,
1411 rHints,
1412 rIgnoreLeadingSpace );
1413 break;
1415 case XML_ELEMENT(TEXT, XML_NOTE):
1416 if (rImport.GetTextImport()->IsInFrame())
1418 // we must not insert footnotes into text frames
1419 pContext = new SvXMLImportContext( rImport );
1421 else
1423 pContext = new XMLFootnoteImportContext(rImport, *rImport.GetTextImport());
1425 rIgnoreLeadingSpace = false;
1426 break;
1428 case XML_ELEMENT(TEXT, XML_REFERENCE_MARK):
1429 case XML_ELEMENT(TEXT, XML_BOOKMARK):
1430 case XML_ELEMENT(TEXT, XML_BOOKMARK_START):
1431 case XML_ELEMENT(TEXT, XML_BOOKMARK_END):
1432 pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
1433 rHints.GetCrossRefHeadingBookmark());
1434 break;
1436 case XML_ELEMENT(FIELD, XML_FIELDMARK):
1437 case XML_ELEMENT(FIELD, XML_FIELDMARK_START):
1438 case XML_ELEMENT(FIELD, XML_FIELDMARK_SEPARATOR):
1439 case XML_ELEMENT(FIELD, XML_FIELDMARK_END):
1440 pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
1441 rHints.GetCrossRefHeadingBookmark());
1442 break;
1444 case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_START):
1445 pContext = new XMLStartReferenceContext_Impl( rImport,
1446 rHints, xAttrList );
1447 break;
1449 case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_END):
1450 pContext = new XMLEndReferenceContext_Impl( rImport,
1451 rHints, xAttrList );
1452 break;
1454 case XML_ELEMENT(DRAW, XML_FRAME):
1456 Reference < XTextRange > xAnchorPos =
1457 rImport.GetTextImport()->GetCursor()->getStart();
1458 XMLTextFrameContext *pTextFrameContext =
1459 new XMLTextFrameContext(rImport,
1460 xAttrList,
1461 TextContentAnchorType_AS_CHARACTER );
1462 // Remove check for text content. (#i33242#)
1463 // Check for text content is done on the processing of the hint
1464 if( TextContentAnchorType_AT_CHARACTER ==
1465 pTextFrameContext->GetAnchorType() )
1467 rHints.push_back(std::make_unique<XMLTextFrameHint_Impl>(
1468 pTextFrameContext, xAnchorPos));
1470 pContext = pTextFrameContext;
1471 rIgnoreLeadingSpace = false;
1473 break;
1474 case XML_ELEMENT(DRAW, XML_A):
1476 Reference < XTextRange > xAnchorPos(rImport.GetTextImport()->GetCursor()->getStart());
1477 pContext =
1478 new XMLTextFrameHyperlinkContext( rImport, nElement,
1479 xAttrList,
1480 TextContentAnchorType_AS_CHARACTER );
1481 rHints.push_back(
1482 std::make_unique<XMLTextFrameHint_Impl>(pContext, xAnchorPos));
1484 break;
1486 case XML_ELEMENT(TEXT, XML_TOC_MARK):
1487 case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
1488 pContext = new XMLTOCMarkImportContext_Impl(
1489 rImport, rHints);
1490 break;
1492 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK):
1493 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
1494 pContext = new XMLUserIndexMarkImportContext_Impl(
1495 rImport, rHints);
1496 break;
1498 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
1499 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
1500 pContext = new XMLAlphaIndexMarkImportContext_Impl(
1501 rImport, rHints);
1502 break;
1504 case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
1505 case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
1506 case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
1507 pContext = new XMLIndexMarkImportContext_Impl(
1508 rImport, rHints);
1509 break;
1511 case XML_ELEMENT(TEXT, XML_CHANGE_START):
1512 case XML_ELEMENT(TEXT, XML_CHANGE_END):
1513 case XML_ELEMENT(TEXT, XML_CHANGE):
1514 pContext = new XMLChangeImportContext(
1515 rImport,
1516 ((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
1517 ? XMLChangeImportContext::Element::END
1518 : (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
1519 ? XMLChangeImportContext::Element::START
1520 : XMLChangeImportContext::Element::POINT),
1521 false);
1522 break;
1524 case XML_ELEMENT(TEXT, XML_META):
1525 pContext = new XMLMetaImportContext(rImport, nElement,
1526 rHints, rIgnoreLeadingSpace );
1527 break;
1529 case XML_ELEMENT(TEXT, XML_META_FIELD):
1530 pContext = new XMLMetaFieldImportContext(rImport, nElement,
1531 rHints, rIgnoreLeadingSpace );
1532 break;
1534 case XML_ELEMENT(LO_EXT, XML_CONTENT_CONTROL):
1535 pContext = new XMLContentControlContext(rImport, nElement, rHints, rIgnoreLeadingSpace);
1536 break;
1538 default:
1539 // none of the above? then it's probably a text field!
1540 pContext = XMLTextFieldImportContext::CreateTextFieldImportContext(
1541 rImport, *rImport.GetTextImport(), nElement);
1542 // #108784# import draw elements (except control shapes in headers)
1543 if( pContext == nullptr &&
1544 !( rImport.GetTextImport()->IsInHeaderFooter() &&
1545 nElement == XML_ELEMENT(DRAW, XML_CONTROL ) ) )
1547 Reference < XShapes > xShapes;
1548 SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateGroupChildContext(
1549 rImport, nElement, xAttrList, xShapes );
1550 pContext = pShapeContext;
1551 // OD 2004-04-20 #i26791# - keep shape in a text frame hint to
1552 // adjust its anchor position, if it's at-character anchored
1553 Reference < XTextRange > xAnchorPos =
1554 rImport.GetTextImport()->GetCursor()->getStart();
1555 rHints.push_back(
1556 std::make_unique<XMLDrawHint_Impl>(pShapeContext, xAnchorPos));
1558 // Behind fields, shapes and any unknown content blanks aren't ignored
1559 rIgnoreLeadingSpace = false;
1562 if (!pContext)
1563 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
1564 return pContext;
1567 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLImpSpanContext_Impl::createFastChildContext(
1568 sal_Int32 nElement,
1569 const uno::Reference< xml::sax::XFastAttributeList>& xAttrList )
1571 return CreateSpanContext( GetImport(), nElement, xAttrList,
1572 m_rHints, rIgnoreLeadingSpace
1573 ,nStarFontsConvFlags
1577 void XMLImpSpanContext_Impl::characters( const OUString& rChars )
1579 OUString sStyleName;
1580 if( pHint )
1581 sStyleName = pHint->GetStyleName();
1582 OUString sChars =
1583 GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
1584 nStarFontsConvFlags,
1585 false, GetImport() );
1586 GetImport().GetTextImport()->InsertString( sChars, rIgnoreLeadingSpace );
1590 XMLParaContext::XMLParaContext(
1591 SvXMLImport& rImport,
1592 sal_Int32 nElement,
1593 const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
1594 SvXMLImportContext( rImport ),
1595 xStart( rImport.GetTextImport()->GetCursorAsRange()->getStart() ),
1596 m_bHaveAbout(false),
1597 nOutlineLevel( (nElement & TOKEN_MASK) == XML_H ? 1 : -1 ),
1598 // Lost outline numbering in master document (#i73509#)
1599 mbOutlineLevelAttrFound( false ),
1600 mbOutlineContentVisible(true),
1601 bIgnoreLeadingSpace( true ),
1602 bHeading( (nElement & TOKEN_MASK) == XML_H ),
1603 bIsListHeader( false ),
1604 bIsRestart (false),
1605 nStartValue(0),
1606 nStarFontsConvFlags( 0 )
1608 bool bHaveXmlId( false );
1609 OUString aCondStyleName;
1611 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
1613 switch( aIter.getToken() )
1615 case XML_ELEMENT(XML, XML_ID):
1616 m_sXmlId = aIter.toString();
1617 bHaveXmlId = true;
1618 break;
1619 case XML_ELEMENT(XHTML, XML_ABOUT):
1620 m_sAbout = aIter.toString();
1621 m_bHaveAbout = true;
1622 break;
1623 case XML_ELEMENT(XHTML, XML_PROPERTY):
1624 m_sProperty = aIter.toString();
1625 break;
1626 case XML_ELEMENT(XHTML, XML_CONTENT):
1627 m_sContent = aIter.toString();
1628 break;
1629 case XML_ELEMENT(XHTML, XML_DATATYPE):
1630 m_sDatatype = aIter.toString();
1631 break;
1632 case XML_ELEMENT(TEXT, XML_ID):
1633 if (!bHaveXmlId) { m_sXmlId = aIter.toString(); }
1634 break;
1635 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
1636 sStyleName = aIter.toString();
1637 break;
1638 case XML_ELEMENT(TEXT, XML_COND_STYLE_NAME):
1639 aCondStyleName = aIter.toString();
1640 break;
1641 case XML_ELEMENT(TEXT, XML_OUTLINE_LEVEL):
1643 sal_Int32 nTmp = aIter.toInt32();
1644 if( nTmp > 0 )
1646 if( nTmp > 127 )
1647 nTmp = 127;
1648 nOutlineLevel = static_cast<sal_Int8>(nTmp);
1650 // Lost outline numbering in master document (#i73509#)
1651 mbOutlineLevelAttrFound = true;
1653 break;
1654 case XML_ELEMENT(LO_EXT, XML_OUTLINE_CONTENT_VISIBLE):
1656 bool bBool(false);
1657 if (::sax::Converter::convertBool(bBool, aIter.toView()))
1658 mbOutlineContentVisible = bBool;
1660 break;
1661 case XML_ELEMENT(TEXT, XML_IS_LIST_HEADER):
1663 bool bBool(false);
1664 if (::sax::Converter::convertBool(bBool, aIter.toView()))
1665 bIsListHeader = bBool;
1667 break;
1668 case XML_ELEMENT(TEXT, XML_RESTART_NUMBERING):
1670 bool bBool(false);
1671 if (::sax::Converter::convertBool(bBool, aIter.toView()))
1672 bIsRestart = bBool;
1674 break;
1675 case XML_ELEMENT(TEXT, XML_START_VALUE):
1677 nStartValue = sal::static_int_cast< sal_Int16 >(aIter.toInt32());
1679 break;
1680 case XML_ELEMENT(LO_EXT, XML_MARKER_STYLE_NAME):
1681 if (auto pStyle = rImport.GetTextImport()->FindAutoCharStyle(aIter.toString()))
1682 m_aMarkerStyleName = pStyle->GetAutoName();
1683 break;
1684 default:
1685 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
1689 if( !aCondStyleName.isEmpty() )
1690 sStyleName = aCondStyleName;
1693 void XMLParaContext::endFastElement(sal_Int32 )
1695 rtl::Reference < XMLTextImportHelper > xTxtImport(
1696 GetImport().GetTextImport());
1697 Reference<XTextRange> xEnd;
1700 Reference<XTextRange> const xCrsrRange(xTxtImport->GetCursorAsRange());
1701 if (!xCrsrRange.is())
1702 return; // Robust (defective file)
1703 xEnd = xCrsrRange->getStart();
1705 catch (uno::Exception const&)
1707 SAL_INFO("xmloff.text", "XMLParaContext: cursor disposed?");
1708 return;
1711 // if we have an id set for this paragraph, get a cursor for this
1712 // paragraph and register it with the given identifier
1713 // FIXME: this is just temporary, and should be removed when
1714 // EditEngine paragraphs implement XMetadatable!
1715 if (!m_sXmlId.isEmpty())
1717 Reference < XTextCursor > xIdCursor( xTxtImport->GetText()->createTextCursorByRange( xStart ) );
1718 if( xIdCursor.is() )
1720 xIdCursor->gotoRange( xEnd, true );
1721 GetImport().getInterfaceToIdentifierMapper().registerReference(
1722 m_sXmlId, Reference<XInterface>( xIdCursor, UNO_QUERY ));
1726 // insert a paragraph break
1727 xTxtImport->InsertControlCharacter( ControlCharacter::APPEND_PARAGRAPH );
1729 // create a cursor that select the whole last paragraph
1730 Reference < XTextCursor > xAttrCursor;
1731 try {
1732 xAttrCursor = xTxtImport->GetText()->createTextCursorByRange( xStart );
1733 if( !xAttrCursor.is() )
1734 return; // Robust (defective file)
1735 } catch (const uno::Exception &) {
1736 // createTextCursorByRange() likes to throw runtime exception, even
1737 // though it just means 'we were unable to create the cursor'
1738 return;
1740 xAttrCursor->gotoRange( xEnd, true );
1742 // xml:id for RDF metadata
1743 if (!m_sXmlId.isEmpty() || m_bHaveAbout || !m_sProperty.isEmpty())
1745 try {
1746 const uno::Reference<container::XEnumerationAccess> xEA
1747 (xAttrCursor, uno::UNO_QUERY_THROW);
1748 const uno::Reference<container::XEnumeration> xEnum(
1749 xEA->createEnumeration(), uno::UNO_SET_THROW);
1750 SAL_WARN_IF(!xEnum->hasMoreElements(), "xmloff.text", "xml:id: no paragraph?");
1751 if (xEnum->hasMoreElements()) {
1752 uno::Reference<rdf::XMetadatable> xMeta;
1753 xEnum->nextElement() >>= xMeta;
1754 SAL_WARN_IF(!xMeta.is(), "xmloff.text", "xml:id: not XMetadatable");
1755 GetImport().SetXmlId(xMeta, m_sXmlId);
1756 if (m_bHaveAbout)
1758 GetImport().AddRDFa(xMeta,
1759 m_sAbout, m_sProperty, m_sContent, m_sDatatype);
1761 SAL_WARN_IF(xEnum->hasMoreElements(), "xmloff.text", "xml:id: > 1 paragraph?");
1763 } catch (const uno::Exception &) {
1764 SAL_INFO("xmloff.text", "XMLParaContext::~XMLParaContext: exception");
1768 OUString const sCellParaStyleName(xTxtImport->GetCellParaStyleDefault());
1769 if( !sCellParaStyleName.isEmpty() )
1771 /* Suppress handling of outline and list attributes,
1772 because of side effects of method <SetStyleAndAttrs(..)> (#i80724#)
1774 xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
1775 sCellParaStyleName,
1776 true,
1777 false, -1, // suppress outline handling
1778 false ); // suppress list attributes handling
1781 // #103445# for headings without style name, find the proper style
1782 if( bHeading && sStyleName.isEmpty() )
1783 xTxtImport->FindOutlineStyleName( sStyleName, nOutlineLevel );
1785 // set style and hard attributes at the previous paragraph
1786 // Add parameter <mbOutlineLevelAttrFound> (#i73509#)
1787 sStyleName = xTxtImport->SetStyleAndAttrs( GetImport(), xAttrCursor,
1788 sStyleName,
1789 true,
1790 mbOutlineLevelAttrFound,
1791 bHeading ? nOutlineLevel : -1,
1792 true,
1793 mbOutlineContentVisible);
1795 if (m_aMarkerStyleName.hasValue())
1797 if (auto xPropSet = xStart.query<css::beans::XPropertySet>())
1801 xPropSet->setPropertyValue("ListAutoFormat", m_aMarkerStyleName);
1803 catch (const css::beans::UnknownPropertyException&)
1805 // no problem
1810 // handle list style header
1811 if (bHeading && (bIsListHeader || bIsRestart))
1813 Reference<XPropertySet> xPropSet( xAttrCursor, UNO_QUERY );
1815 if (xPropSet.is())
1817 if (bIsListHeader)
1819 OUString sNumberingIsNumber
1820 ("NumberingIsNumber");
1821 if(xPropSet->getPropertySetInfo()->
1822 hasPropertyByName(sNumberingIsNumber))
1824 xPropSet->setPropertyValue
1825 (sNumberingIsNumber, Any( false ) );
1828 if (bIsRestart)
1830 OUString sParaIsNumberingRestart
1831 ("ParaIsNumberingRestart");
1832 OUString sNumberingStartValue
1833 ("NumberingStartValue");
1834 if (xPropSet->getPropertySetInfo()->
1835 hasPropertyByName(sParaIsNumberingRestart))
1837 xPropSet->setPropertyValue
1838 (sParaIsNumberingRestart, Any(true));
1841 if (xPropSet->getPropertySetInfo()->
1842 hasPropertyByName(sNumberingStartValue))
1844 xPropSet->setPropertyValue
1845 (sNumberingStartValue, Any(nStartValue));
1852 if (m_xHints)
1854 bool bSetNoFormatAttr = false;
1855 uno::Reference<beans::XPropertySet> xCursorProps(xAttrCursor, uno::UNO_QUERY);
1856 int nEmptyHints = 0;
1857 uno::Reference<text::XTextRangeCompare> xCompare(xTxtImport->GetText(), uno::UNO_QUERY);
1858 if (xCompare.is())
1862 for (const auto& pHint : m_xHints->GetHints())
1864 if (xCompare->compareRegionStarts(pHint->GetStart(), pHint->GetEnd()) == 0)
1866 ++nEmptyHints;
1870 catch (const uno::Exception&)
1872 TOOLS_WARN_EXCEPTION("xmloff.text", "");
1875 if (nEmptyHints > 0 || m_aMarkerStyleName.hasValue())
1877 // We have at least one empty hint, then make try to ask the cursor to not upgrade our character
1878 // attributes to paragraph-level formatting, which would lead to incorrect rendering.
1879 uno::Reference<beans::XPropertySetInfo> xCursorPropsInfo = xCursorProps->getPropertySetInfo();
1880 bSetNoFormatAttr = xCursorPropsInfo->hasPropertyByName("NoFormatAttr");
1882 if (bSetNoFormatAttr)
1884 xCursorProps->setPropertyValue("NoFormatAttr", uno::Any(true));
1886 for (const auto & i : m_xHints->GetHints())
1888 XMLHint_Impl *const pHint = i.get();
1889 xAttrCursor->gotoRange( pHint->GetStart(), false );
1890 xAttrCursor->gotoRange( pHint->GetEnd(), true );
1891 switch( pHint->GetType() )
1893 case XMLHintType::XML_HINT_STYLE:
1895 const OUString& rStyleName =
1896 static_cast<XMLStyleHint_Impl *>(pHint)->GetStyleName();
1897 if( !rStyleName.isEmpty() )
1898 xTxtImport->SetStyleAndAttrs( GetImport(),
1899 xAttrCursor, rStyleName,
1900 false );
1902 break;
1903 case XMLHintType::XML_HINT_REFERENCE:
1905 const OUString& rRefName =
1906 static_cast<XMLReferenceHint_Impl *>(pHint)->GetRefName();
1907 if( !rRefName.isEmpty() )
1909 if( !pHint->GetEnd().is() )
1910 pHint->SetEnd(xEnd);
1912 // reference name uses rStyleName member
1913 // borrow from XMLTextMarkImportContext
1914 XMLTextMarkImportContext::CreateAndInsertMark(
1915 GetImport(),
1916 "com.sun.star.text.ReferenceMark",
1917 rRefName,
1918 xAttrCursor);
1921 break;
1922 case XMLHintType::XML_HINT_HYPERLINK:
1924 const XMLHyperlinkHint_Impl *pHHint =
1925 static_cast<const XMLHyperlinkHint_Impl *>(pHint);
1926 xTxtImport->SetHyperlink( GetImport(),
1927 xAttrCursor,
1928 pHHint->GetHRef(),
1929 pHHint->GetName(),
1930 pHHint->GetTargetFrameName(),
1931 pHHint->GetStyleName(),
1932 pHHint->GetVisitedStyleName(),
1933 pHHint->GetEventsContext() );
1935 break;
1936 case XMLHintType::XML_HINT_INDEX_MARK:
1938 Reference<beans::XPropertySet> xMark(
1939 static_cast<const XMLIndexMarkHint_Impl *>(pHint)->GetMark());
1940 Reference<XTextContent> xContent(xMark, UNO_QUERY);
1943 xTxtImport->GetText()->insertTextContent(
1944 xAttrCursor, xContent, true );
1946 catch (uno::RuntimeException const&)
1948 TOOLS_INFO_EXCEPTION("xmloff.text", "could not insert index mark, presumably in editengine text");
1951 break;
1952 case XMLHintType::XML_HINT_TEXT_FRAME:
1954 const XMLTextFrameHint_Impl *pFHint =
1955 static_cast<const XMLTextFrameHint_Impl *>(pHint);
1956 // Check for text content (#i33242#)
1957 Reference < XTextContent > xTextContent =
1958 pFHint->GetTextContent();
1959 if ( xTextContent.is() )
1961 /* Core impl. of the unification of drawing objects and
1962 Writer fly frames (#i26791#)
1964 if ( pFHint->IsBoundAtChar() )
1966 xTextContent->attach( xAttrCursor );
1969 /* Consider, that hint can also contain a shape -
1970 e.g. drawing object of type 'Text'. (#i33242#)
1972 else
1974 Reference < XShape > xShape = pFHint->GetShape();
1975 if ( xShape.is() )
1977 // determine anchor type
1978 Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
1979 TextContentAnchorType eAnchorType =
1980 TextContentAnchorType_AT_PARAGRAPH;
1982 Any aAny = xPropSet->getPropertyValue( "AnchorType" );
1983 aAny >>= eAnchorType;
1985 if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
1987 // set anchor position for at-character anchored objects
1988 xPropSet->setPropertyValue("TextRange", Any(xAttrCursor));
1993 break;
1994 /* Core impl. of the unification of drawing objects and
1995 Writer fly frames (#i26791#)
1997 case XMLHintType::XML_HINT_DRAW:
1999 const XMLDrawHint_Impl *pDHint =
2000 static_cast<const XMLDrawHint_Impl*>(pHint);
2001 // Improvement: hint directly provides the shape. (#i33242#)
2002 const Reference < XShape >& xShape = pDHint->GetShape();
2003 if ( xShape.is() )
2005 // determine anchor type
2006 Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );
2007 TextContentAnchorType eAnchorType = TextContentAnchorType_AT_PARAGRAPH;
2009 Any aAny = xPropSet->getPropertyValue( "AnchorType" );
2010 aAny >>= eAnchorType;
2012 if ( TextContentAnchorType_AT_CHARACTER == eAnchorType )
2014 // set anchor position for at-character anchored objects
2015 xPropSet->setPropertyValue("TextRange", Any(xAttrCursor));
2019 break;
2020 default:
2021 SAL_WARN( "xmloff.text", "What's this" );
2022 break;
2025 if (bSetNoFormatAttr)
2027 xCursorProps->setPropertyValue("NoFormatAttr", uno::Any(false));
2030 m_xHints.reset();
2033 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLParaContext::createFastChildContext(
2034 sal_Int32 nElement,
2035 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2037 if (!m_xHints)
2038 m_xHints.reset(new XMLHints_Impl);
2039 return XMLImpSpanContext_Impl::CreateSpanContext(
2040 GetImport(), nElement, xAttrList,
2041 *m_xHints, bIgnoreLeadingSpace,
2042 nStarFontsConvFlags);
2045 void XMLParaContext::characters( const OUString& rChars )
2047 OUString sChars =
2048 GetImport().GetTextImport()->ConvertStarFonts( rChars, sStyleName,
2049 nStarFontsConvFlags,
2050 true, GetImport() );
2051 GetImport().GetTextImport()->InsertString( sChars, bIgnoreLeadingSpace );
2055 XMLNumberedParaContext::XMLNumberedParaContext(
2056 SvXMLImport& i_rImport,
2057 sal_Int32 /*nElement*/,
2058 const Reference< xml::sax::XFastAttributeList > & xAttrList ) :
2059 SvXMLImportContext( i_rImport ),
2060 m_Level(0),
2061 m_StartValue(-1)
2063 OUString StyleName;
2065 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
2067 switch( aIter.getToken() )
2069 case XML_ELEMENT(XML, XML_ID):
2070 //FIXME: there is no UNO API for lists
2071 break;
2072 case XML_ELEMENT(TEXT, XML_LIST_ID):
2073 m_ListId = aIter.toString();
2074 break;
2075 case XML_ELEMENT(TEXT, XML_LEVEL):
2077 sal_Int32 nTmp = aIter.toInt32();
2078 if ( nTmp >= 1 && nTmp <= SHRT_MAX ) {
2079 m_Level = static_cast<sal_uInt16>(nTmp) - 1;
2082 break;
2083 case XML_ELEMENT(TEXT, XML_STYLE_NAME):
2084 StyleName = aIter.toString();
2085 break;
2086 case XML_ELEMENT(TEXT, XML_CONTINUE_NUMBERING):
2087 // this attribute is deprecated
2088 // ContinueNumbering = IsXMLToken(sValue, XML_TRUE);
2089 break;
2090 case XML_ELEMENT(TEXT, XML_START_VALUE):
2092 sal_Int32 nTmp = aIter.toInt32();
2093 if ( nTmp >= 0 && nTmp <= SHRT_MAX ) {
2094 m_StartValue = static_cast<sal_Int16>(nTmp);
2097 break;
2098 default:
2099 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
2103 XMLTextListsHelper& rTextListsHelper(
2104 i_rImport.GetTextImport()->GetTextListHelper() );
2105 if (m_ListId.isEmpty())
2107 SAL_WARN_IF(0 <= i_rImport.GetODFVersion().compareTo(u"1.2"), "xmloff.text", "invalid numbered-paragraph: no list-id (1.2)");
2108 m_ListId = rTextListsHelper.GetNumberedParagraphListId(m_Level,
2109 StyleName);
2110 SAL_WARN_IF(m_ListId.isEmpty(), "xmloff.text", "numbered-paragraph: no ListId");
2111 if (m_ListId.isEmpty()) {
2112 return;
2115 m_xNumRules = rTextListsHelper.EnsureNumberedParagraph( i_rImport,
2116 m_ListId, m_Level, StyleName);
2118 SAL_WARN_IF(!m_xNumRules.is(), "xmloff.text", "numbered-paragraph: no NumRules");
2120 i_rImport.GetTextImport()->GetTextListHelper().PushListContext( this );
2123 void XMLNumberedParaContext::endFastElement(sal_Int32 )
2125 if (!m_ListId.isEmpty()) {
2126 GetImport().GetTextImport()->PopListContext();
2130 css::uno::Reference< css::xml::sax::XFastContextHandler > XMLNumberedParaContext::createFastChildContext(
2131 sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
2133 switch (nElement)
2135 case XML_ELEMENT(TEXT, XML_H):
2136 case XML_ELEMENT(LO_EXT, XML_H):
2137 case XML_ELEMENT(TEXT, XML_P):
2138 case XML_ELEMENT(LO_EXT, XML_P):
2139 return new XMLParaContext( GetImport(), nElement, xAttrList );
2140 default:
2141 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
2144 return nullptr;
2147 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */