Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/xmloff/source/text/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 164 kB image not shown  

Quelle  txtparae.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <sal/config.h>

#include <o3tl/any.hxx>
#include <xmloff/unointerfacetouniqueidentifiermapper.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/types.h>
#include <sal/log.hxx>
#include <osl/diagnose.h>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/container/XEnumerationAccess.hpp>
#include <com/sun/star/container/XEnumeration.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/beans/UnknownPropertyException.hpp>
#include <com/sun/star/graphic/XGraphic.hpp>
#include <com/sun/star/text/XTextSectionsSupplier.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
#include <com/sun/star/text/XNumberingRulesSupplier.hpp>
#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextContent.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <com/sun/star/text/XTextFramesSupplier.hpp>
#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/document/XEventsSupplier.hpp>
#include <com/sun/star/document/XRedlinesSupplier.hpp>
#include <com/sun/star/text/XFormField.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/drawing/XShape.hpp>
#include <com/sun/star/style/XAutoStylesSupplier.hpp>
#include <com/sun/star/style/XAutoStyleFamily.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/drawing/XControlShape.hpp>

#include <sax/tools/converter.hxx>

#include <xmloff/xmlnamespace.hxx>
#include <xmloff/xmlaustp.hxx>
#include <xmloff/families.hxx>
#include "txtexppr.hxx"
#include <xmloff/xmluconv.hxx>
#include "XMLAnchorTypePropHdl.hxx"
#include <xexptran.hxx>
#include <xmloff/ProgressBarHelper.hxx>
#include <xmloff/namespacemap.hxx>
#include <xmloff/xmlexp.hxx>
#include <txtflde.hxx>
#include <xmloff/txtprmap.hxx>
#include <XMLImageMapExport.hxx>
#include "XMLTextNumRuleInfo.hxx"
#include <xmloff/XMLTextListAutoStylePool.hxx>
#include <xmloff/txtparae.hxx>
#include "XMLSectionExport.hxx"
#include "XMLIndexMarkExport.hxx"
#include <xmloff/XMLEventExport.hxx>
#include "XMLRedlineExport.hxx"
#include <MultiPropertySetHelper.hxx>
#include <xmloff/formlayerexport.hxx>
#include "XMLTextCharStyleNamesElementExport.hxx"
#include <xmloff/odffields.hxx>
#include <xmloff/maptype.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/document/XStorageBasedDocument.hpp>
#include <txtlists.hxx>
#include <com/sun/star/rdf/XMetadatable.hpp>
#include <list>
#include <unordered_map>
#include <memory>
#include <vector>
#include <algorithm>
#include <iterator>
#include <officecfg/Office/Common.hxx>
#include <o3tl/safeint.hxx>
#include <comphelper/scopeguard.hxx>
#include <comphelper/sequenceashashmap.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::graphic;
using namespace ::xmloff;
using namespace ::xmloff::token;

// Implement Title/Description Elements UI (#i73249#)
constexpr OUString gsTitle(u"Title"_ustr);
constexpr OUString gsDescription(u"Description"_ustr);
constexpr OUString gsAnchorPageNo(u"AnchorPageNo"_ustr);
constexpr OUString gsAnchorType(u"AnchorType"_ustr);
constexpr OUString gsBookmark(u"Bookmark"_ustr);
constexpr OUString gsChainNextName(u"ChainNextName"_ustr);
constexpr OUString gsContourPolyPolygon(u"ContourPolyPolygon"_ustr);
constexpr OUString gsDocumentIndexMark(u"DocumentIndexMark"_ustr);
constexpr OUString gsFrame(u"Frame"_ustr);
constexpr OUString gsGraphicFilter(u"GraphicFilter"_ustr);
constexpr OUString gsGraphicRotation(u"GraphicRotation"_ustr);
constexpr OUString gsHeight(u"Height"_ustr);
constexpr OUString gsHoriOrient(u"HoriOrient"_ustr);
constexpr OUString gsHoriOrientPosition(u"HoriOrientPosition"_ustr);
constexpr OUString gsHyperLinkName(u"HyperLinkName"_ustr);
constexpr OUString gsHyperLinkTarget(u"HyperLinkTarget"_ustr);
constexpr OUString gsHyperLinkURL(u"HyperLinkURL"_ustr);
constexpr OUString gsIsAutomaticContour(u"IsAutomaticContour"_ustr);
constexpr OUString gsIsCollapsed(u"IsCollapsed"_ustr);
constexpr OUString gsIsPixelContour(u"IsPixelContour"_ustr);
constexpr OUString gsIsStart(u"IsStart"_ustr);
constexpr OUString gsIsSyncHeightToWidth(u"IsSyncHeightToWidth"_ustr);
constexpr OUString gsIsSyncWidthToHeight(u"IsSyncWidthToHeight"_ustr);
constexpr OUString gsNumberingRules(u"NumberingRules"_ustr);
constexpr OUString gsParaConditionalStyleName(u"ParaConditionalStyleName"_ustr);
constexpr OUString gsParagraphService(u"com.sun.star.text.Paragraph"_ustr);
constexpr OUString gsRedline(u"Redline"_ustr);
constexpr OUString gsReferenceMark(u"ReferenceMark"_ustr);
constexpr OUString gsRelativeHeight(u"RelativeHeight"_ustr);
constexpr OUString gsRelativeWidth(u"RelativeWidth"_ustr);
constexpr OUString gsRuby(u"Ruby"_ustr);
constexpr OUString gsRubyCharStyleName(u"RubyCharStyleName"_ustr);
constexpr OUString gsRubyText(u"RubyText"_ustr);
constexpr OUString gsServerMap(u"ServerMap"_ustr);
constexpr OUString gsShapeService(u"com.sun.star.drawing.Shape"_ustr);
constexpr OUString gsSizeType(u"SizeType"_ustr);
constexpr OUString gsSoftPageBreak(u"SoftPageBreak"_ustr);
constexpr OUString gsTableService(u"com.sun.star.text.TextTable"_ustr);
constexpr OUString gsText(u"Text"_ustr);
constexpr OUString gsTextContentService(u"com.sun.star.text.TextContent"_ustr);
constexpr OUString gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject"_ustr);
constexpr OUString gsTextField(u"TextField"_ustr);
constexpr OUString gsTextFieldService(u"com.sun.star.text.TextField"_ustr);
constexpr OUString gsTextFrameService(u"com.sun.star.text.TextFrame"_ustr);
constexpr OUString gsTextGraphicService(u"com.sun.star.text.TextGraphicObject"_ustr);
constexpr OUString gsTextPortionType(u"TextPortionType"_ustr);
constexpr OUString gsUnvisitedCharStyleName(u"UnvisitedCharStyleName"_ustr);
constexpr OUString gsVertOrient(u"VertOrient"_ustr);
constexpr OUString gsVertOrientPosition(u"VertOrientPosition"_ustr);
constexpr OUString gsVisitedCharStyleName(u"VisitedCharStyleName"_ustr);
constexpr OUString gsWidth(u"Width"_ustr);
constexpr OUString gsWidthType( u"WidthType"_ustr  );
constexpr OUString gsTextFieldStart(u"TextFieldStart"_ustr);
constexpr OUString gsTextFieldSep(u"TextFieldSeparator"_ustr);
constexpr OUString gsTextFieldEnd(u"TextFieldEnd"_ustr);
constexpr OUString gsTextFieldStartEnd(u"TextFieldStartEnd"_ustr);
constexpr OUString gsPropertyCharStyleNames(u"CharStyleNames"_ustr);

namespace
{
    class TextContentSet
    {
        public:
            typedef std::list<Reference<XTextContent>> contents_t;
            typedef std::back_insert_iterator<contents_t> inserter_t;
            typedef contents_t::const_iterator const_iterator_t;

            inserter_t getInserter()
                { return std::back_insert_iterator<contents_t>(m_vTextContents); };
            const_iterator_t getBegin() const
                { return m_vTextContents.begin(); };
            const_iterator_t getEnd() const
                { return m_vTextContents.end(); };

        private:
            contents_t m_vTextContents;
    };

    struct FrameRefHash
    {
        size_t operator()(const Reference<XTextFrame>& rFrame) const
            { return sal::static_int_cast<size_t>(reinterpret_cast<sal_uIntPtr>(rFrame.get())); }
    };

    bool lcl_TextContentsUnfiltered(const Reference<XTextContent>&)
        { return true; };

    bool lcl_ShapeFilter(const Reference<XTextContent>& xTxtContent)
    {
        Reference<XShape> xShape(xTxtContent, UNO_QUERY);
        if(!xShape.is())
            return false;
        Reference<XServiceInfo> xServiceInfo(xTxtContent, UNO_QUERY);
        return !xServiceInfo->supportsService(u"com.sun.star.text.TextFrame"_ustr) &&
               !xServiceInfo->supportsService(u"com.sun.star.text.TextGraphicObject"_ustr) &&
               !xServiceInfo->supportsService(u"com.sun.star.text.TextEmbeddedObject"_ustr);
    };

    class BoundFrames
    {
        public:
            typedef bool (*filter_t)(const Reference<XTextContent>&);
            BoundFrames(
                const Reference<XEnumerationAccess>& rEnumAccess,
                const filter_t& rFilter)
                : m_xEnumAccess(rEnumAccess)
            {
                Fill(rFilter);
            };
            BoundFrames()
                {};
            const TextContentSet& GetPageBoundContents() const
                { return m_vPageBounds; };
            const TextContentSet* GetFrameBoundContents(const Reference<XTextFrame>& rParentFrame) const
            {
                framebound_map_t::const_iterator it = m_vFrameBoundsOf.find(rParentFrame);
                if(it == m_vFrameBoundsOf.end())
                    return nullptr;
                return &(it->second);
            };
            Reference<XEnumeration> createEnumeration() const
            {
                if(!m_xEnumAccess.is())
                    return Reference<XEnumeration>();
                return m_xEnumAccess->createEnumeration();
            };

        private:
            typedef std::unordered_map<
                Reference<XTextFrame>,
                TextContentSet,
                FrameRefHash> framebound_map_t;
            TextContentSet m_vPageBounds;
            framebound_map_t m_vFrameBoundsOf;
            const Reference<XEnumerationAccess> m_xEnumAccess;
            void Fill(const filter_t& rFilter);
    };

    class FieldParamExporter
    {
        public:
            FieldParamExporter(SvXMLExport* const pExport, Reference<XNameContainer> const & xFieldParams)
                : m_pExport(pExport)
                , m_xFieldParams(xFieldParams)
                { };
            void Export();

        private:
            SvXMLExport* const m_pExport;
            const Reference<XNameContainer> m_xFieldParams;

            void ExportParameter(const OUString& sKey, const OUString& sValue);
    };

    struct HyperlinkData
    {
        OUString href, name, targetFrame, ustyleName, vstyleName;
        bool serverMap = false;
        css::uno::Reference<css::container::XNameReplace> events;

        HyperlinkData() = default;
        HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>& rPropSet);

        bool operator==(const HyperlinkData&);
        bool operator!=(const HyperlinkData& rOther) { return !operator==(rOther); }

        bool addHyperlinkAttributes(SvXMLExport& rExport);
        void exportEvents(SvXMLExport& rExport);
    };

    HyperlinkData::HyperlinkData(const css::uno::Reference<css::beans::XPropertySet>&&nbsp;rPropSet)
    {
        const css::uno::Reference<css::beans::XPropertyState> xPropState(rPropSet, UNO_QUERY);
        const auto xPropSetInfo(rPropSet->getPropertySetInfo());

        if (xPropSetInfo->hasPropertyByName(gsTextPortionType))
        {
            // No hyperlink for Ruby portions; the hyperlink will be added for their inner Text
            if (OUString type;
                (rPropSet->getPropertyValue(gsTextPortionType) >>= type) && type == gsRuby)
                return;
        }

        if (xPropSetInfo->hasPropertyByName(gsHyperLinkURL)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkURL)))
        {
            rPropSet->getPropertyValue(gsHyperLinkURL) >>= href;
        }

        if (href.isEmpty())
            return;

        if (xPropSetInfo->hasPropertyByName(gsHyperLinkName)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkName)))
        {
            rPropSet->getPropertyValue(gsHyperLinkName) >>= name;
        }

        if (xPropSetInfo->hasPropertyByName(gsHyperLinkTarget)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsHyperLinkTarget)))
        {
            rPropSet->getPropertyValue(gsHyperLinkTarget) >>= targetFrame;
        }

        if (xPropSetInfo->hasPropertyByName(gsServerMap)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE == xPropState->getPropertyState(gsServerMap)))
        {
            serverMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsServerMap));
        }

        if (xPropSetInfo->hasPropertyByName(gsUnvisitedCharStyleName)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE
                       == xPropState->getPropertyState(gsUnvisitedCharStyleName)))
        {
            rPropSet->getPropertyValue(gsUnvisitedCharStyleName) >>= ustyleName;
        }

        if (xPropSetInfo->hasPropertyByName(gsVisitedCharStyleName)
            && (!xPropState.is()
                || PropertyState_DIRECT_VALUE
                       == xPropState->getPropertyState(gsVisitedCharStyleName)))
        {
            rPropSet->getPropertyValue(gsVisitedCharStyleName) >>= vstyleName;
        }

        static constexpr OUString sHyperLinkEvents(u"HyperLinkEvents"_ustr);
        if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
        {
            events.set(rPropSet->getPropertyValue(sHyperLinkEvents), uno::UNO_QUERY);
        }
    }

    bool HyperlinkData::operator==(const HyperlinkData& rOther)
    {
        if (href != rOther.href || name != rOther.name || targetFrame != rOther.targetFrame
            || ustyleName != rOther.ustyleName || vstyleName != rOther.vstyleName
            || serverMap != rOther.serverMap)
            return false;

        if (events == rOther.events)
            return true;
        if (!events || !rOther.events)
            return false;

        const css::uno::Sequence<OUString> aNames = events->getElementNames();
        if (aNames != rOther.events->getElementNames())
            return false;
        for (const auto& rName : aNames)
        {
            const css::uno::Any aAny = events->getByName(rName);
            const css::uno::Any aOtherAny = rOther.events->getByName(rName);
            if (aAny != aOtherAny)
                return false;
        }
        return true;
    }

    bool HyperlinkData::addHyperlinkAttributes(SvXMLExport& rExport)
    {
        if (href.isEmpty())
        {
            // hyperlink without a URL does not make sense
            OSL_ENSURE(false"hyperlink without a URL --> no export to ODF");
            return false;
        }

        rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
        rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, rExport.GetRelativeReference(href));

        if (!name.isEmpty())
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, name);

        if (!targetFrame.isEmpty())
        {
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_TARGET_FRAME_NAME, targetFrame);
            enum XMLTokenEnum eTok = targetFrame == "_blank" ? XML_NEW : XML_REPLACE;
            rExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, eTok);
        }

        if (serverMap)
            rExport.AddAttribute(XML_NAMESPACE_OFFICE, XML_SERVER_MAP, XML_TRUE);

        if (!ustyleName.isEmpty())
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                                 rExport.EncodeStyleName(ustyleName));

        if (!vstyleName.isEmpty())
            rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_VISITED_STYLE_NAME,
                                 rExport.EncodeStyleName(vstyleName));

        return true;
    }

    void HyperlinkData::exportEvents(SvXMLExport& rExport)
    {
        // export events (if supported)
        if (events)
            rExport.GetEventExport().Export(events, false);
    }
}

namespace xmloff
{
    class BoundFrameSets
    {
        public:
            explicit BoundFrameSets(const Reference<XInterface>& rModel);
            const BoundFrames* GetTexts() const
                { return m_pTexts.get(); };
            const BoundFrames* GetGraphics() const
                { return m_pGraphics.get(); };
            const BoundFrames* GetEmbeddeds() const
                { return m_pEmbeddeds.get(); };
            const BoundFrames* GetShapes() const
                { return m_pShapes.get(); };
        private:
            std::unique_ptr<BoundFrames> m_pTexts;
            std::unique_ptr<BoundFrames> m_pGraphics;
            std::unique_ptr<BoundFrames> m_pEmbeddeds;
            std::unique_ptr<BoundFrames> m_pShapes;
    };
}

#ifdef DBG_UTIL
static bool txtparae_bContainsIllegalCharacters = false;
#endif

// The following map shows which property values are required:

// property                     auto style pass     export

// ParaStyleName                if style exists     always
// ParaConditionalStyleName     if style exists     always
// NumberingRules               if style exists     always
// TextSection                  always              always
// ParaChapterNumberingLevel    never               always
// NumberingIsNumber            never               always

// The conclusion is that for auto styles the first three properties
// should be queried using a multi property set if, and only if, an
// auto style needs to be exported. TextSection should be queried by
// an individual call to getPropertyvalue, because this seems to be
// less expensive than querying the first three properties if they aren't
// required.

// For the export pass all properties can be queried using a multi property
// set.

constexpr OUString aParagraphPropertyNamesAuto[] =
{
    u"NumberingRules"_ustr,
    u"ParaConditionalStyleName"_ustr,
    u"ParaStyleName"_ustr
};

namespace {

enum eParagraphPropertyNamesEnumAuto
{
    NUMBERING_RULES_AUTO = 0,
    PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
    PARA_STYLE_NAME_AUTO = 2
};

}

constexpr OUString aParagraphPropertyNames[] =
{
    u"NumberingIsNumber"_ustr,
    u"NumberingStyleName"_ustr,
    u"OutlineLevel"_ustr,
    u"ParaConditionalStyleName"_ustr,
    u"ParaStyleName"_ustr,
    u"TextSection"_ustr,
    u"OutlineContentVisible"_ustr
};

namespace {

enum eParagraphPropertyNamesEnum
{
    NUMBERING_IS_NUMBER = 0,
    PARA_NUMBERING_STYLENAME = 1,
    PARA_OUTLINE_LEVEL=2,
    PARA_CONDITIONAL_STYLE_NAME = 3,
    PARA_STYLE_NAME = 4,
    TEXT_SECTION = 5,
    PARA_OUTLINE_CONTENT_VISIBLE = 6
};

}

void BoundFrames::Fill(const filter_t& rFilter)
{
    if(!m_xEnumAccess.is())
        return;
    const Reference< XEnumeration > xEnum = m_xEnumAccess->createEnumeration();
    if(!xEnum.is())
        return;
    static constexpr OUString our_sAnchorType(u"AnchorType"_ustr);
    static constexpr OUString our_sAnchorFrame(u"AnchorFrame"_ustr);
    while(xEnum->hasMoreElements())
    {
        Reference<XPropertySet> xPropSet(xEnum->nextElement(), UNO_QUERY);
        Reference<XTextContent> xTextContent(xPropSet, UNO_QUERY);
        if(!xPropSet.is() || !xTextContent.is())
            continue;
        TextContentAnchorType eAnchor;
        xPropSet->getPropertyValue(our_sAnchorType) >>= eAnchor;
        if(TextContentAnchorType_AT_PAGE != eAnchor && TextContentAnchorType_AT_FRAME != eAnchor)
            continue;
        if(!rFilter(xTextContent))
            continue;

        TextContentSet::inserter_t pInserter = m_vPageBounds.getInserter();
        if(TextContentAnchorType_AT_FRAME == eAnchor)
        {
            Reference<XTextFrame> xAnchorTxtFrame(
                xPropSet->getPropertyValue(our_sAnchorFrame),
                uno::UNO_QUERY);
            pInserter = m_vFrameBoundsOf[xAnchorTxtFrame].getInserter();
        }
        *pInserter++ = xTextContent;
    }
}

BoundFrameSets::BoundFrameSets(const Reference<XInterface>& rModel)
    : m_pTexts(new BoundFrames())
    , m_pGraphics(new BoundFrames())
    , m_pEmbeddeds(new BoundFrames())
    , m_pShapes(new BoundFrames())
{
    const Reference<XTextFramesSupplier> xTFS(rModel, UNO_QUERY);
    const Reference<XTextGraphicObjectsSupplier> xGOS(rModel, UNO_QUERY);
    const Reference<XTextEmbeddedObjectsSupplier> xEOS(rModel, UNO_QUERY);
    const Reference<XDrawPageSupplier> xDPS(rModel, UNO_QUERY);
    if(xTFS.is())
        m_pTexts.reset(new BoundFrames(
            Reference<XEnumerationAccess>(xTFS->getTextFrames(), UNO_QUERY),
            &lcl_TextContentsUnfiltered));
    if(xGOS.is())
        m_pGraphics.reset(new BoundFrames(
            Reference<XEnumerationAccess>(xGOS->getGraphicObjects(), UNO_QUERY),
            &lcl_TextContentsUnfiltered));
    if(xEOS.is())
        m_pEmbeddeds.reset(new BoundFrames(
            Reference<XEnumerationAccess>(xEOS->getEmbeddedObjects(), UNO_QUERY),
            &lcl_TextContentsUnfiltered));
    if(xDPS.is())
        m_pShapes.reset(new BoundFrames(
            Reference<XEnumerationAccess>(xDPS->getDrawPage(), UNO_QUERY),
            &lcl_ShapeFilter));
};

void FieldParamExporter::Export()
{
    const Type aStringType = ::cppu::UnoType<OUString>::get();
    const Type aBoolType = cppu::UnoType<sal_Bool>::get();
    const Type aSeqType = cppu::UnoType<Sequence<OUString>>::get();
    const Type aIntType = ::cppu::UnoType<sal_Int32>::get();
    const Sequence<OUString> vParameters(m_xFieldParams->getElementNames());
    for(const auto & rParameter : vParameters)
    {
        const Any aValue = m_xFieldParams->getByName(rParameter);
        const Type& aValueType = aValue.getValueType();
        if(aValueType == aStringType)
        {
            OUString sValue;
            aValue >>= sValue;
            ExportParameter(rParameter,sValue);

            if ( rParameter == ODF_OLE_PARAM )
            {
                // Save the OLE object
                Reference< embed::XStorage > xTargetStg = m_pExport->GetTargetStorage();
                if (xTargetStg.is()) {
                    Reference< embed::XStorage > xDstStg = xTargetStg->openStorageElement(
                        u"OLELinks"_ustr, embed::ElementModes::WRITE );

                    if ( !xDstStg->hasByName( sValue ) ) {
                        Reference< XStorageBasedDocument > xStgDoc (
                            m_pExport->GetModel( ), UNO_QUERY );
                        Reference< embed::XStorage > xDocStg = xStgDoc->getDocumentStorage();
                        Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
                            u"OLELinks"_ustr, embed::ElementModes::READ );

                        xOleStg->copyElementTo( sValue, xDstStg, sValue );
                        Reference< embed::XTransactedObject > xTransact( xDstStg, UNO_QUERY );
                        if ( xTransact.is( ) )
                            xTransact->commit( );
                    }
                } else {
                    SAL_WARN("xmloff""no target storage");
                }
            }
        }
        else if(aValueType == aBoolType)
        {
            bool bValue = false;
            aValue >>= bValue;
            ExportParameter(rParameter, OUString::boolean(bValue) );
        }
        else if(aValueType == aSeqType)
        {
            Sequence<OUString> vValue;
            aValue >>= vValue;
            for (const OUString& i : vValue)
            {
                ExportParameter(rParameter, i);
            }
        }
        else if(aValueType == aIntType)
        {
            sal_Int32 nValue = 0;
            aValue >>= nValue;
            ExportParameter(rParameter, OUString::number(nValue));
        }
    }
}

void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& ;sValue)
{
    m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_NAME, sKey);
    m_pExport->AddAttribute(XML_NAMESPACE_FIELD, XML_VALUE, sValue);
    m_pExport->StartElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
    m_pExport->EndElement(XML_NAMESPACE_FIELD, XML_PARAM, false);
}

void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
                                  const Reference < XPropertySet > & rPropSet,
                                  const std::span<const XMLPropertyState> aAddStates,
                                  bool bCheckParent )
{
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XmlStyleFamily::TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    case XmlStyleFamily::TEXT_TEXT:
        xPropMapper = GetTextPropMapper();
        break;
    case XmlStyleFamily::TEXT_FRAME:
        xPropMapper = GetAutoFramePropMapper();
        break;
    case XmlStyleFamily::TEXT_SECTION:
        xPropMapper = GetSectionPropMapper();
        break;
    case XmlStyleFamily::TEXT_RUBY:
        xPropMapper = GetRubyPropMapper();
        break;
    defaultbreak;
    }
    SAL_WARN_IF( !xPropMapper.is(), "xmloff""There is the property mapper?" );

    std::vector< XMLPropertyState > aPropStates =
            xPropMapper->Filter(GetExport(), rPropSet);

    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );

    if( aPropStates.empty() )
        return;

    Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
    OUString sParent, sCondParent;
    switch( nFamily )
    {
    case XmlStyleFamily::TEXT_PARAGRAPH:
        if( xPropSetInfo->hasPropertyByName( gsParaStyleName ) )
        {
            rPropSet->getPropertyValue( gsParaStyleName ) >>= sParent;
        }
        if( xPropSetInfo->hasPropertyByName( gsParaConditionalStyleName ) )
        {
            rPropSet->getPropertyValue( gsParaConditionalStyleName ) >>= sCondParent;
        }
        if( xPropSetInfo->hasPropertyByName( gsNumberingRules ) )
        {
            Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( gsNumberingRules ), uno::UNO_QUERY);
            if( xNumRule.is() && xNumRule->getCount() )
            {
                Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
                OUString sName;
                if( xNamed.is() )
                    sName = xNamed->getName();
                bool bAdd = sName.isEmpty();
                if( !bAdd )
                {
                    Reference < XPropertySet > xNumPropSet( xNumRule,
                                                            UNO_QUERY );
                    if( xNumPropSet.is() &&
                        xNumPropSet->getPropertySetInfo()
                                   ->hasPropertyByName( u"IsAutomatic"_ustr ) )
                    {
                        bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"IsAutomatic"_ustr ));
                        // Check on outline style (#i73361#)
                        if ( bAdd &&
                             xNumPropSet->getPropertySetInfo()
                                       ->hasPropertyByName( u"NumberingIsOutline"_ustr ) )
                        {
                            bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"NumberingIsOutline"_ustr )));
                        }
                    }
                    else
                    {
                        bAdd = true;
                    }
                }
                if( bAdd )
                    maListAutoPool.Add( xNumRule );
            }
        }
        break;
    case XmlStyleFamily::TEXT_TEXT:
        {
            if (bCheckParent && xPropSetInfo->hasPropertyByName(gsCharStyleName))
            {
                rPropSet->getPropertyValue(gsCharStyleName) >>= sParent;
            }

            // Get parent and remove hyperlinks (they aren't of interest)
            rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
            sal_uInt16 nIgnoreProps = 0;
            for( ::std::vector< XMLPropertyState >::iterator i(aPropStates.begin());
                  nIgnoreProps < 2 && i != aPropStates.end(); )
            {
                if( i->mnIndex == -1 )
                {
                    ++i;
                    continue;
                }

                switch( xPM->GetEntryContextId(i->mnIndex) )
                {
                case CTF_CHAR_STYLE_NAME:
                case CTF_HYPERLINK_URL:
                    i->mnIndex = -1;
                    nIgnoreProps++;
                    i = aPropStates.erase( i );
                    break;
                default:
                    ++i;
                    break;
                }
            }
        }
        break;
    case XmlStyleFamily::TEXT_FRAME:
        if( xPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
        {
            rPropSet->getPropertyValue( gsFrameStyleName ) >>= sParent;
        }
        break;
    case XmlStyleFamily::TEXT_SECTION:
    case XmlStyleFamily::TEXT_RUBY:
        ; // section styles have no parents
        break;
    defaultbreak;
    }
    if (aPropStates.size()) // could change after the previous check
    {
        GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates), /*bDontSeek*/false );
        if( !sCondParent.isEmpty() && sParent != sCondParent )
            GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
    }
}

static bool lcl_validPropState( const XMLPropertyState& rState )
{
    return rState.mnIndex != -1;
}

void XMLTextParagraphExport::Add( XmlStyleFamily nFamily,
                                  MultiPropertySetHelper& rPropSetHelper,
                                  const Reference < XPropertySet > & rPropSet)
{
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XmlStyleFamily::TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    defaultbreak;
    }
    SAL_WARN_IF( !xPropMapper.is(), "xmloff""There is the property mapper?" );

    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));

    if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
    {
        Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
            rPropSet, true ), uno::UNO_QUERY);
        if( xNumRule.is() && xNumRule->getCount() )
        {
            Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
            OUString sName;
            if( xNamed.is() )
                sName = xNamed->getName();
            bool bAdd = sName.isEmpty();
            if( !bAdd )
            {
                Reference < XPropertySet > xNumPropSet( xNumRule,
                                                        UNO_QUERY );
                if( xNumPropSet.is() &&
                    xNumPropSet->getPropertySetInfo()
                               ->hasPropertyByName( u"IsAutomatic"_ustr ) )
                {
                    bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"IsAutomatic"_ustr ));
                    // Check on outline style (#i73361#)
                    if ( bAdd &&
                         xNumPropSet->getPropertySetInfo()
                                   ->hasPropertyByName( u"NumberingIsOutline"_ustr ) )
                    {
                        bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( u"NumberingIsOutline"_ustr )));
                    }
                }
                else
                {
                    bAdd = true;
                }
            }
            if( bAdd )
                maListAutoPool.Add( xNumRule );
        }
    }

    if( aPropStates.empty() )
        return;

    OUString sParent, sCondParent;
    switch( nFamily )
    {
    case XmlStyleFamily::TEXT_PARAGRAPH:
        if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
        {
            rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
                                            true ) >>= sParent;
        }
        if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
        {
            rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
                                             rPropSet, true ) >>= sCondParent;
        }

        break;
    defaultbreak;
    }

    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
    {
        GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates) );
        if( !sCondParent.isEmpty() && sParent != sCondParent )
            GetAutoStylePool().Add( nFamily, sCondParent, std::move(aPropStates) );
    }
}

OUString XMLTextParagraphExport::Find(
        XmlStyleFamily nFamily,
        const Reference < XPropertySet > & rPropSet,
        const OUString& rParent,
        const std::span<const XMLPropertyState> aAddStates) const
{
    OUString sName( rParent );
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XmlStyleFamily::TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    case XmlStyleFamily::TEXT_FRAME:
        xPropMapper = GetAutoFramePropMapper();
        break;
    case XmlStyleFamily::TEXT_SECTION:
        xPropMapper = GetSectionPropMapper();
        break;
    case XmlStyleFamily::TEXT_RUBY:
        xPropMapper = GetRubyPropMapper();
        break;
    defaultbreak;
    }
    SAL_WARN_IF( !xPropMapper.is(), "xmloff""There is the property mapper?" );
    if( !xPropMapper.is() )
        return sName;
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
    aPropStates.insert( aPropStates.end(), aAddStates.begin(), aAddStates.end() );
    if( std::any_of( aPropStates.begin(), aPropStates.end(), lcl_validPropState ) )
        sName = GetAutoStylePool().Find( nFamily, sName, aPropStates );

    return sName;
}

OUString XMLTextParagraphExport::FindTextStyle(
           const Reference < XPropertySet > & rPropSet,
        bool& rbHasCharStyle,
        bool& rbHasAutoStyle,
        const XMLPropertyState** ppAddStates,
        const OUString* pParentName) const
{
    rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
    std::vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));

    // Get parent and remove hyperlinks (they aren't of interest)
    OUString sName;
    rbHasCharStyle = rbHasAutoStyle = false;
    sal_uInt16 nIgnoreProps = 0;
    rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
    ::std::vector< XMLPropertyState >::iterator aFirstDel = aPropStates.end();
    ::std::vector< XMLPropertyState >::iterator aSecondDel = aPropStates.end();

    for( ::std::vector< XMLPropertyState >::iterator
            i = aPropStates.begin();
         nIgnoreProps < 2 && i != aPropStates.end();
         ++i )
    {
        if( i->mnIndex == -1 )
            continue;

        switch( xPM->GetEntryContextId(i->mnIndex) )
        {
        case CTF_CHAR_STYLE_NAME:
            i->maValue >>= sName;
            i->mnIndex = -1;
            rbHasCharStyle = !sName.isEmpty();
            if( nIgnoreProps )
                aSecondDel = i;
            else
                aFirstDel = i;
            nIgnoreProps++;
            break;
        case CTF_HYPERLINK_URL:
            i->mnIndex = -1;
            if( nIgnoreProps )
                aSecondDel = i;
            else
                aFirstDel = i;
            nIgnoreProps++;
            break;
        }
    }
    if( ppAddStates )
    {
        while( *ppAddStates )
        {
            aPropStates.push_back( **ppAddStates );
            ppAddStates++;
        }
    }
    if (aPropStates.size() - nIgnoreProps)
    {
        // erase the character style, otherwise the autostyle cannot be found!
        // erase the hyperlink, otherwise the autostyle cannot be found!
        if ( nIgnoreProps )
        {
            // If two elements of a vector have to be deleted,
            // we should delete the second one first.
            if( --nIgnoreProps )
                aPropStates.erase( aSecondDel );
            aPropStates.erase( aFirstDel );
        }
        OUString aParentName;
        if (pParentName)
        {
            // Format redlines can have an autostyle with a parent.
            aParentName = *pParentName;
        }
        sName = GetAutoStylePool().Find(
            XmlStyleFamily::TEXT_TEXT,
            aParentName,
            aPropStates );
        rbHasAutoStyle = true;
    }

    return sName;
}

// adjustments to support lists independent from list style
void XMLTextParagraphExport::exportListChange(
        const XMLTextNumRuleInfo& rPrevInfo,
        const XMLTextNumRuleInfo& rNextInfo )
{
    // end a list
    if ( rPrevInfo.GetLevel() > 0 )
    {
        sal_uInt32 nListLevelsToBeClosed = 0; // unsigned larger type to safely multiply and compare
        if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
             rNextInfo.GetLevel() <= 0 )
        {
            // close complete previous list
            nListLevelsToBeClosed = rPrevInfo.GetLevel();
        }
        else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
        {
            // close corresponding sub lists
            nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
        }

        if ( nListLevelsToBeClosed > 0 &&
             maListElements.size() >= 2 * nListLevelsToBeClosed )
        {
            do {
                for(size_t j = 0; j < 2; ++j)
                {
                    OUString aElem(maListElements.back());
                    maListElements.pop_back();
                    GetExport().EndElement(aElem, true);
                }

                // remove closed list from list stack
                mpTextListsHelper->PopListFromStack();

                --nListLevelsToBeClosed;
            } while ( nListLevelsToBeClosed > 0 );
        }
    }

    // start a new list
    if ( rNextInfo.GetLevel() > 0 )
    {
        bool bRootListToBeStarted = false;
        sal_Int16 nListLevelsToBeOpened = 0;
        if ( !rPrevInfo.BelongsToSameList( rNextInfo ) ||
             rPrevInfo.GetLevel() <= 0 )
        {
            // new root list
            bRootListToBeStarted = true;
            nListLevelsToBeOpened = rNextInfo.GetLevel();
        }
        else if ( rNextInfo.GetLevel() > rPrevInfo.GetLevel() )
        {
            // open corresponding sub lists
            nListLevelsToBeOpened = rNextInfo.GetLevel() - rPrevInfo.GetLevel();
        }

        if ( nListLevelsToBeOpened > 0 )
        {
            const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
            // Currently only the text documents support <ListId>.
            // Thus, for other document types <sListId> is empty.
            const OUString& sListId( rNextInfo.GetListId() );
            bool bExportListStyle( true );
            bool bRestartNumberingAtContinuedList( false );
            sal_Int32 nRestartValueForContinuedList( -1 );
            bool bContinueingPreviousSubList = !bRootListToBeStarted &&
                                               rNextInfo.IsContinueingPreviousSubTree();
            do {
                GetExport().CheckAttrList();

                if ( bRootListToBeStarted )
                {
                    if ( !mpTextListsHelper->IsListProcessed( sListId ) )
                    {
                        if ( ExportListId() &&
                             !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
                        {
                            /* Property text:id at element <text:list> has to be
                               replaced by property xml:id (#i92221#)
                            */

                            GetExport().AddAttribute( XML_NAMESPACE_XML,
                                                      XML_ID,
                                                      sListId );
                        }
                        mpTextListsHelper->KeepListAsProcessed( sListId,
                                                                sListStyleName,
                                                                OUString() );
                    }
                    else
                    {
                        const OUString sNewListId(
                                        mpTextListsHelper->GenerateNewListId() );
                        if ( ExportListId() &&
                             !sListId.isEmpty() && !rNextInfo.IsListIdDefault() )
                        {
                            /* Property text:id at element <text:list> has to be
                               replaced by property xml:id (#i92221#)
                            */

                            GetExport().AddAttribute( XML_NAMESPACE_XML,
                                                      XML_ID,
                                                      sNewListId );
                        }

                        const OUString sContinueListId =
                            mpTextListsHelper->GetLastContinuingListId( sListId );
                        // store that list with list id <sNewListId> is last list,
                        // which has continued list with list id <sListId>
                        mpTextListsHelper->StoreLastContinuingList( sListId,
                                                                    sNewListId );
                        if ( sListStyleName ==
                                mpTextListsHelper->GetListStyleOfLastProcessedList() &&
                             // Inconsistent behavior regarding lists (#i92811#)
                             sContinueListId ==
                                mpTextListsHelper->GetLastProcessedListId() )
                        {
                            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                                      XML_CONTINUE_NUMBERING,
                                                      XML_TRUE );
                        }
                        else
                        {
                            if ( ExportListId() &&
                                 !sListId.isEmpty() )
                            {
                                GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                                          XML_CONTINUE_LIST,
                                                          sContinueListId );
                            }
                        }

                        if ( rNextInfo.IsRestart() &&
                             ( nListLevelsToBeOpened != 1 ||
                               !rNextInfo.HasStartValue() ) )
                        {
                            bRestartNumberingAtContinuedList = true;
                            nRestartValueForContinuedList =
                                        rNextInfo.GetListLevelStartValue();
                        }

                        mpTextListsHelper->KeepListAsProcessed( sNewListId,
                                                                sListStyleName,
                                                                sContinueListId );
                    }

                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                            GetExport().EncodeStyleName( sListStyleName ) );
                    bExportListStyle = false;

                    bRootListToBeStarted = false;
                }
                else if ( bExportListStyle &&
                          !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
                {
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                            GetExport().EncodeStyleName( sListStyleName ) );
                    bExportListStyle = false;

                }
                else
                {
                    // rhbz#746174: also export list restart for non root list
                    if (rNextInfo.IsRestart() && !rNextInfo.HasStartValue())
                    {
                        bRestartNumberingAtContinuedList = true;
                        nRestartValueForContinuedList =
                                        rNextInfo.GetListLevelStartValue();
                    }
                }

                if ( bContinueingPreviousSubList )
                {
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                              XML_CONTINUE_NUMBERING, XML_TRUE );
                    bContinueingPreviousSubList = false;
                }

                enum XMLTokenEnum eLName = XML_LIST;

                OUString aElem(GetExport().GetNamespaceMap().GetQNameByKey(
                                            XML_NAMESPACE_TEXT,
                                            GetXMLToken(eLName) ) );
                GetExport().IgnorableWhitespace();
                GetExport().StartElement(aElem, false);

                maListElements.push_back(aElem);

                mpTextListsHelper->PushListOnStack( sListId,
                                                    sListStyleName );

                // <text:list-header> or <text:list-item>
                GetExport().CheckAttrList();

                /* Export start value at correct list item (#i97309#) */
                if ( nListLevelsToBeOpened == 1 )
                {
                    if ( rNextInfo.HasStartValue() )
                    {
                        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
                                      aTmp );
                    }
                    else if (bRestartNumberingAtContinuedList)
                    {
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                                  XML_START_VALUE,
                                                  OUString::number(nRestartValueForContinuedList) );
                        bRestartNumberingAtContinuedList = false;
                    }
                }

                eLName = ( rNextInfo.IsNumbered() || nListLevelsToBeOpened > 1 )
                         ? XML_LIST_ITEM
                         : XML_LIST_HEADER;
                aElem = GetExport().GetNamespaceMap().GetQNameByKey(
                                            XML_NAMESPACE_TEXT,
                                            GetXMLToken(eLName) );
                GetExport().IgnorableWhitespace();
                GetExport().StartElement(aElem, false);
                maListElements.push_back(aElem);

                // export of <text:number> element for last opened <text:list-item>, if requested
                if ( GetExport().exportTextNumberElement() &&
                     eLName == XML_LIST_ITEM && nListLevelsToBeOpened == 1 && // last iteration --> last opened <text:list-item>
                     !rNextInfo.ListLabelString().isEmpty() )
                {
                    const OUString aTextNumberElem =
                            GetExport().GetNamespaceMap().GetQNameByKey(
                                      XML_NAMESPACE_TEXT,
                                      GetXMLToken(XML_NUMBER) );
                    GetExport().IgnorableWhitespace();
                    GetExport().StartElement( aTextNumberElem, false );
                    GetExport().Characters( rNextInfo.ListLabelString() );
                    GetExport().EndElement( aTextNumberElem, true );
                }
                --nListLevelsToBeOpened;
            } while ( nListLevelsToBeOpened > 0 );
        }
    }

    bool bEndElement = false;

    if ( rNextInfo.GetLevel() > 0 &&
         rNextInfo.IsNumbered() &&
         rPrevInfo.BelongsToSameList( rNextInfo ) &&
         rPrevInfo.GetLevel() >= rNextInfo.GetLevel() )
    {
        assert(maListElements.size() >= 2 && "list elements missing");
        bEndElement = maListElements.size() >= 2;
    }

    if (!bEndElement)
        return;

    // close previous list-item
    GetExport().EndElement(maListElements.back(), true );
    maListElements.pop_back();

    // Only for sub lists (#i103745#)
    if ( rNextInfo.IsRestart() && !rNextInfo.HasStartValue() &&
         rNextInfo.GetLevel() != 1 )
    {
        // start new sub list respectively list on same list level
        GetExport().EndElement(maListElements.back(), true );
        GetExport().IgnorableWhitespace();
        GetExport().StartElement(maListElements.back(), false);
    }

    // open new list-item
    GetExport().CheckAttrList();
    if( rNextInfo.HasStartValue() )
    {
        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
    }
    // Handle restart without start value on list level 1 (#i103745#)
    else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
              rNextInfo.GetLevel() == 1 )
    {
        OUString aTmp = OUString::number( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE, aTmp );
    }
    if ( ( GetExport().getExportFlags() & SvXMLExportFlags::OASIS ) &&
        GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
    {
        const OUString& sListStyleName( rNextInfo.GetNumRulesName() );
        if ( !mpTextListsHelper->EqualsToTopListStyleOnStack( sListStyleName ) )
        {
            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                      XML_STYLE_OVERRIDE,
                                      GetExport().EncodeStyleName( sListStyleName ) );
        }
    }
    OUString aElem( GetExport().GetNamespaceMap().GetQNameByKey(
                            XML_NAMESPACE_TEXT,
                            GetXMLToken(XML_LIST_ITEM) ) );
    GetExport().IgnorableWhitespace();
    GetExport().StartElement(aElem, false );
    maListElements.push_back(aElem);

    // export of <text:number> element for <text:list-item>, if requested
    if ( GetExport().exportTextNumberElement() &&
         !rNextInfo.ListLabelString().isEmpty() )
    {
        const OUString aTextNumberElem =
                GetExport().GetNamespaceMap().GetQNameByKey(
                          XML_NAMESPACE_TEXT,
                          GetXMLToken(XML_NUMBER) );
        GetExport().IgnorableWhitespace();
        GetExport().StartElement( aTextNumberElem, false );
        GetExport().Characters( rNextInfo.ListLabelString() );
        GetExport().EndElement( aTextNumberElem, true );
    }

}

struct XMLTextParagraphExport::Impl
{
    typedef ::std::map<Reference<XFormField>, sal_Int32> FieldMarkMap_t;
    FieldMarkMap_t m_FieldMarkMap;

    explicit Impl() {}
    sal_Int32 AddFieldMarkStart(Reference<XFormField> const& i_xFieldMark)
    {
        assert(m_FieldMarkMap.find(i_xFieldMark) == m_FieldMarkMap.end());
        sal_Int32 const ret(m_FieldMarkMap.size());
        m_FieldMarkMap.insert(::std::make_pair(i_xFieldMark, ret));
        return ret;
    }
    sal_Int32 GetFieldMarkIndex(Reference<XFormField> const& i_xFieldMark)
    {
        FieldMarkMap_t::const_iterator const it(
                m_FieldMarkMap.find(i_xFieldMark));
        // rely on SwXFieldmark::CreateXFieldmark returning the same instance
        // because the Reference in m_FieldMarkMap will keep it alive
        assert(it != m_FieldMarkMap.end());
        return it->second;
    }
};

struct XMLTextParagraphExport::DocumentListNodes
{
    struct NodeData
    {
        std::ptrdiff_t order;
        sal_Int32 index; // see SwNode::GetIndex and SwNodeOffset
        sal_uInt64 style_id; // actually a pointer to NumRule
        OUString list_id;
    };
    std::vector<NodeData> docListNodes;
    DocumentListNodes(const css::uno::Reference<css::frame::XModel>& xModel,
                      const std::vector<sal_Int32>& aDocumentNodeOrder)
    {
        // Sequence of nodes, each of them represented by three-element sequence,
        // corresponding to NodeData members
        css::uno::Sequence<css::uno::Sequence<css::uno::Any>> nodes;
        if (auto xPropSet = xModel.query<css::beans::XPropertySet>())
        {
            try
            {
                // See SwXTextDocument::getPropertyValue
                xPropSet->getPropertyValue(u"ODFExport_ListNodes"_ustr) >>= nodes;
            }
            catch (css::beans::UnknownPropertyException&)
            {
                // That's absolutely fine!
            }
        }

        docListNodes.reserve(nodes.getLength());
        for (const auto& node : nodes)
        {
            assert(node.getLength() == 3);
            sal_Int32 nodeIndex = node[0].get<sal_Int32>();
            auto nodeOrder = std::distance(
                aDocumentNodeOrder.begin(),
                std::find(aDocumentNodeOrder.begin(), aDocumentNodeOrder.end(), nodeIndex));
            docListNodes.push_back({ .order = nodeOrder,
                                     .index = nodeIndex,
                                     .style_id = node[1].get<sal_uInt64>(),
                                     .list_id = node[2].get<OUString>() });
        }

        std::sort(docListNodes.begin(), docListNodes.end(),
                  [](const NodeData& lhs, const NodeData& rhs) { return lhs.order < rhs.order; });
    }
    bool ShouldSkipListId(const Reference<XTextContent>& xTextContent) const
    {
        if (docListNodes.empty())
            return false;

        if (auto xPropSet = xTextContent.query<css::beans::XPropertySet>())
        {
            sal_Int32 index = 0;
            try
            {
                // See SwXParagraph::Impl::GetPropertyValues_Impl
                xPropSet->getPropertyValue(u"ODFExport_NodeIndex"_ustr) >>= index;
            }
            catch (css::beans::UnknownPropertyException&)
            {
                // That's absolutely fine!
                return false;
            }

            auto it = std::find_if(docListNodes.begin(), docListNodes.end(),
                                   [index](const NodeData& el) { return el.index == index; });
            if (it == docListNodes.end())
                return false;

            // We need to write the id, when there will be continuation of the list either with
            // a different list style, or after another list.

            for (auto next = it + 1; next != docListNodes.end(); ++next)
            {
                if (it->list_id != next->list_id)
                {
                    // List changed. We will have to refer to this id, only if there will
                    // appear a continuation of this list
                    return std::find_if(next + 1, docListNodes.end(),
                                        [list_id = it->list_id](const NodeData& data)
                                        { return data.list_id == list_id; })
                           == docListNodes.end();
                }

                if (it->style_id != next->style_id)
                {
                    // Same list, new style -> this "next" will refer to the id, no skipping
                    return false;
                }
                if (it->index + 1 != next->index)
                {
                    // we have a gap before the next node with the same list and style,
                    // with no other lists in between. There will be a continuation with a
                    // simple 'text:continue-numbering="true"'.
                    return true;
                }
                it = next; // walk through adjacent nodes of the same list
            }
            // all nodes were adjacent and of the same list and style -> no continuation, skip id
            return true;
        }

        return false;
    }
};

XMLTextParagraphExport::XMLTextParagraphExport(
        SvXMLExport& rExp,
        SvXMLAutoStylePoolP & rASP
        ) :
    XMLStyleExport( rExp, &rASP ),
    m_xImpl(new Impl),
    m_rAutoStylePool( rASP ),
    m_pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
    maListAutoPool( GetExport() ),
    m_bProgress( false ),
    m_bBlock( false ),
    m_bOpenRuby( false ),
    mpTextListsHelper( nullptr ),
    mbCollected(false),
    m_aCharStyleNamesPropInfoCache( gsCharStyleNames )
{
    rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
    m_xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );

    OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
    OUString aPrefix(u'P');
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
                              m_xParaPropMapper, aPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
    m_xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );
    sFamily = GetXMLToken(XML_TEXT);
    aPrefix = "T";
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
                              m_xTextPropMapper, aPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
    m_xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                                  GetExport() );
    sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
    aPrefix = "fr";
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
                              m_xAutoFramePropMapper, aPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
    m_xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );
    sFamily = GetXMLToken( XML_SECTION );
    aPrefix = "Sect" ;
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
                              m_xSectionPropMapper, aPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
    m_xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
    sFamily = GetXMLToken( XML_RUBY );
    aPrefix = "Ru";
    m_rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
                              m_xRubyPropMapper, aPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
    m_xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                              GetExport() );

    m_pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
    m_pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );

    if( ! IsBlockMode() &&
        Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
        m_pRedlineExport.reset( new XMLRedlineExport( rExp ) );

    // The text field helper needs a pre-constructed XMLPropertyState
    // to export the combined characters field. We construct that
    // here, because we need the text property mapper to do it.

    // construct Any value, then find index
    sal_Int32 nIndex = m_xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
                                "", XML_NAMESPACE_STYLE,
                                GetXMLToken(XML_TEXT_COMBINE));
    m_pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::Any(true) ) ) );
    PushNewTextListsHelper();
}

XMLTextParagraphExport::~XMLTextParagraphExport()
{
    m_pRedlineExport.reset();
    m_pIndexMarkExport.reset();
    m_pSectionExport.reset();
    m_pFieldExport.reset();
#ifdef DBG_UTIL
    txtparae_bContainsIllegalCharacters = false;
#endif
    PopTextListsHelper();
    SAL_WARN_IF( !maTextListsHelperStack.empty(), "xmloff",
                "misusage of text lists helper stack - it is not empty. Serious defect" );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
        SvXMLExport& rExport )
{
    rtl::Reference < XMLPropertySetMapper > xPropMapper =
        new XMLTextPropertySetMapper( TextPropMap::SHAPE, true );
    return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TextPropMap::SHAPE_PARA, true );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TextPropMap::TEXT_ADDITIONAL_DEFAULTS, true );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

void XMLTextParagraphExport::exportPageFrames( bool bIsProgress )
{
    const TextContentSet& rTexts = m_pBoundFrameSets->GetTexts()->GetPageBoundContents();
    const TextContentSet& rGraphics = m_pBoundFrameSets->GetGraphics()->GetPageBoundContents();
    const TextContentSet& rEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
    const TextContentSet& rShapes = m_pBoundFrameSets->GetShapes()->GetPageBoundContents();
    for(TextContentSet::const_iterator_t it = rTexts.getBegin();
        it != rTexts.getEnd();
        ++it)
        exportTextFrame(*it, false/*bAutoStyles*/, bIsProgress, true);
    for(TextContentSet::const_iterator_t it = rGraphics.getBegin();
        it != rGraphics.getEnd();
        ++it)
        exportTextGraphic(*it, false/*bAutoStyles*/);
    for(TextContentSet::const_iterator_t it = rEmbeddeds.getBegin();
        it != rEmbeddeds.getEnd();
        ++it)
        exportTextEmbedded(*it, false/*bAutoStyles*/);
    for(TextContentSet::const_iterator_t it = rShapes.getBegin();
        it != rShapes.getEnd();
        ++it)
        exportShape(*it, false/*bAutoStyles*/);
}

void XMLTextParagraphExport::exportFrameFrames(
        bool bAutoStyles,
        bool bIsProgress,
        const Reference < XTextFrame >& rParentTxtFrame )
{
    const TextContentSet* const pTexts = m_pBoundFrameSets->GetTexts()->GetFrameBoundContents(rParentTxtFrame);
    if(pTexts)
        for(TextContentSet::const_iterator_t it = pTexts->getBegin();
            it != pTexts->getEnd();
            ++it)
            exportTextFrame(*it, bAutoStyles, bIsProgress, true);
    const TextContentSet* const pGraphics = m_pBoundFrameSets->GetGraphics()->GetFrameBoundContents(rParentTxtFrame);
    if(pGraphics)
        for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
            it != pGraphics->getEnd();
            ++it)
            exportTextGraphic(*it, bAutoStyles);
    const TextContentSet* const pEmbeddeds = m_pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(rParentTxtFrame);
    if(pEmbeddeds)
        for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
            it != pEmbeddeds->getEnd();
            ++it)
            exportTextEmbedded(*it, bAutoStyles);
    const TextContentSet* const pShapes = m_pBoundFrameSets->GetShapes()->GetFrameBoundContents(rParentTxtFrame);
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.