1f9468fc29
because it will pre-allocate space and often is optimised to memcpy Change-Id: I03ed7915f2762d3d27e378638052a47a28bbf096 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123588 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
3872 lines
149 KiB
C++
3872 lines
149 KiB
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/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/graphic/XGraphic.hpp>
|
|
#include <com/sun/star/text/XTextDocument.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/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/XEmbeddedObjectSupplier.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 <com/sun/star/util/DateTime.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>
|
|
|
|
using namespace ::std;
|
|
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::util;
|
|
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 OUStringLiteral gsTitle(u"Title");
|
|
constexpr OUStringLiteral gsDescription(u"Description");
|
|
constexpr OUStringLiteral gsAnchorPageNo(u"AnchorPageNo");
|
|
constexpr OUStringLiteral gsAnchorType(u"AnchorType");
|
|
constexpr OUStringLiteral gsBookmark(u"Bookmark");
|
|
constexpr OUStringLiteral gsChainNextName(u"ChainNextName");
|
|
constexpr OUStringLiteral gsContourPolyPolygon(u"ContourPolyPolygon");
|
|
constexpr OUStringLiteral gsDocumentIndexMark(u"DocumentIndexMark");
|
|
constexpr OUStringLiteral gsFrame(u"Frame");
|
|
constexpr OUStringLiteral gsGraphicFilter(u"GraphicFilter");
|
|
constexpr OUStringLiteral gsGraphicRotation(u"GraphicRotation");
|
|
constexpr OUStringLiteral gsHeight(u"Height");
|
|
constexpr OUStringLiteral gsHoriOrient(u"HoriOrient");
|
|
constexpr OUStringLiteral gsHoriOrientPosition(u"HoriOrientPosition");
|
|
constexpr OUStringLiteral gsHyperLinkName(u"HyperLinkName");
|
|
constexpr OUStringLiteral gsHyperLinkTarget(u"HyperLinkTarget");
|
|
constexpr OUStringLiteral gsHyperLinkURL(u"HyperLinkURL");
|
|
constexpr OUStringLiteral gsIsAutomaticContour(u"IsAutomaticContour");
|
|
constexpr OUStringLiteral gsIsCollapsed(u"IsCollapsed");
|
|
constexpr OUStringLiteral gsIsPixelContour(u"IsPixelContour");
|
|
constexpr OUStringLiteral gsIsStart(u"IsStart");
|
|
constexpr OUStringLiteral gsIsSyncHeightToWidth(u"IsSyncHeightToWidth");
|
|
constexpr OUStringLiteral gsIsSyncWidthToHeight(u"IsSyncWidthToHeight");
|
|
constexpr OUStringLiteral gsNumberingRules(u"NumberingRules");
|
|
constexpr OUStringLiteral gsParaConditionalStyleName(u"ParaConditionalStyleName");
|
|
constexpr OUStringLiteral gsParagraphService(u"com.sun.star.text.Paragraph");
|
|
constexpr OUStringLiteral gsRedline(u"Redline");
|
|
constexpr OUStringLiteral gsReferenceMark(u"ReferenceMark");
|
|
constexpr OUStringLiteral gsRelativeHeight(u"RelativeHeight");
|
|
constexpr OUStringLiteral gsRelativeWidth(u"RelativeWidth");
|
|
constexpr OUStringLiteral gsRuby(u"Ruby");
|
|
constexpr OUStringLiteral gsRubyCharStyleName(u"RubyCharStyleName");
|
|
constexpr OUStringLiteral gsRubyText(u"RubyText");
|
|
constexpr OUStringLiteral gsServerMap(u"ServerMap");
|
|
constexpr OUStringLiteral gsShapeService(u"com.sun.star.drawing.Shape");
|
|
constexpr OUStringLiteral gsSizeType(u"SizeType");
|
|
constexpr OUStringLiteral gsSoftPageBreak( u"SoftPageBreak" );
|
|
constexpr OUStringLiteral gsTableService(u"com.sun.star.text.TextTable");
|
|
constexpr OUStringLiteral gsText(u"Text");
|
|
constexpr OUStringLiteral gsTextContentService(u"com.sun.star.text.TextContent");
|
|
constexpr OUStringLiteral gsTextEmbeddedService(u"com.sun.star.text.TextEmbeddedObject");
|
|
constexpr OUStringLiteral gsTextField(u"TextField");
|
|
constexpr OUStringLiteral gsTextFieldService(u"com.sun.star.text.TextField");
|
|
constexpr OUStringLiteral gsTextFrameService(u"com.sun.star.text.TextFrame");
|
|
constexpr OUStringLiteral gsTextGraphicService(u"com.sun.star.text.TextGraphicObject");
|
|
constexpr OUStringLiteral gsTextPortionType(u"TextPortionType");
|
|
constexpr OUStringLiteral gsUnvisitedCharStyleName(u"UnvisitedCharStyleName");
|
|
constexpr OUStringLiteral gsVertOrient(u"VertOrient");
|
|
constexpr OUStringLiteral gsVertOrientPosition(u"VertOrientPosition");
|
|
constexpr OUStringLiteral gsVisitedCharStyleName(u"VisitedCharStyleName");
|
|
constexpr OUStringLiteral gsWidth(u"Width");
|
|
constexpr OUStringLiteral gsWidthType( u"WidthType" );
|
|
constexpr OUStringLiteral gsTextFieldStart( u"TextFieldStart" );
|
|
constexpr OUStringLiteral gsTextFieldEnd( u"TextFieldEnd" );
|
|
constexpr OUStringLiteral gsTextFieldStartEnd( u"TextFieldStartEnd" );
|
|
|
|
namespace
|
|
{
|
|
class TextContentSet
|
|
{
|
|
public:
|
|
typedef list<Reference<XTextContent>> contents_t;
|
|
typedef back_insert_iterator<contents_t> inserter_t;
|
|
typedef contents_t::const_iterator const_iterator_t;
|
|
|
|
inserter_t getInserter()
|
|
{ return 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("com.sun.star.text.TextFrame") &&
|
|
!xServiceInfo->supportsService("com.sun.star.text.TextGraphicObject") &&
|
|
!xServiceInfo->supportsService("com.sun.star.text.TextEmbeddedObject");
|
|
};
|
|
|
|
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);
|
|
};
|
|
}
|
|
|
|
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:
|
|
unique_ptr<BoundFrames> m_pTexts;
|
|
unique_ptr<BoundFrames> m_pGraphics;
|
|
unique_ptr<BoundFrames> m_pEmbeddeds;
|
|
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.
|
|
|
|
static const char* aParagraphPropertyNamesAuto[] =
|
|
{
|
|
"NumberingRules",
|
|
"ParaConditionalStyleName",
|
|
"ParaStyleName",
|
|
nullptr
|
|
};
|
|
|
|
namespace {
|
|
|
|
enum eParagraphPropertyNamesEnumAuto
|
|
{
|
|
NUMBERING_RULES_AUTO = 0,
|
|
PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
|
|
PARA_STYLE_NAME_AUTO = 2
|
|
};
|
|
|
|
}
|
|
|
|
static const char* aParagraphPropertyNames[] =
|
|
{
|
|
"NumberingIsNumber",
|
|
"NumberingStyleName",
|
|
"OutlineLevel",
|
|
"ParaConditionalStyleName",
|
|
"ParaStyleName",
|
|
"TextSection",
|
|
"OutlineContentVisible",
|
|
nullptr
|
|
};
|
|
|
|
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 const OUStringLiteral our_sAnchorType(u"AnchorType");
|
|
static const OUStringLiteral our_sAnchorFrame(u"AnchorFrame");
|
|
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(
|
|
"OLELinks", 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(
|
|
"OLELinks", 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 : std::as_const(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 o3tl::span<XMLPropertyState> aAddStates, bool bDontSeek )
|
|
{
|
|
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;
|
|
default: break;
|
|
}
|
|
SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
|
|
|
|
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;
|
|
sal_uInt16 nIgnoreProps = 0;
|
|
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( "IsAutomatic" ) )
|
|
{
|
|
bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
|
|
// Check on outline style (#i73361#)
|
|
if ( bAdd &&
|
|
xNumPropSet->getPropertySetInfo()
|
|
->hasPropertyByName( "NumberingIsOutline" ) )
|
|
{
|
|
bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bAdd = true;
|
|
}
|
|
}
|
|
if( bAdd )
|
|
maListAutoPool.Add( xNumRule );
|
|
}
|
|
}
|
|
break;
|
|
case XmlStyleFamily::TEXT_TEXT:
|
|
{
|
|
// Get parent and remove hyperlinks (they aren't of interest)
|
|
rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
|
|
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;
|
|
default: break;
|
|
}
|
|
if (aPropStates.size() - nIgnoreProps)
|
|
{
|
|
GetAutoStylePool().Add( nFamily, sParent, std::vector(aPropStates), bDontSeek );
|
|
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;
|
|
default: break;
|
|
}
|
|
SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
|
|
|
|
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( "IsAutomatic" ) )
|
|
{
|
|
bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
|
|
// Check on outline style (#i73361#)
|
|
if ( bAdd &&
|
|
xNumPropSet->getPropertySetInfo()
|
|
->hasPropertyByName( "NumberingIsOutline" ) )
|
|
{
|
|
bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
|
|
}
|
|
}
|
|
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;
|
|
default: break;
|
|
}
|
|
|
|
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 o3tl::span<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;
|
|
default: break;
|
|
}
|
|
SAL_WARN_IF( !xPropMapper.is(), "xmloff", "There is the property mapper?" );
|
|
if( !xPropMapper.is() )
|
|
return sName;
|
|
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::FindTextStyleAndHyperlink(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
bool& rbHyperlink,
|
|
bool& rbHasCharStyle,
|
|
bool& rbHasAutoStyle,
|
|
const XMLPropertyState** ppAddStates ) const
|
|
{
|
|
rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
|
|
vector<XMLPropertyState> aPropStates(xPropMapper->Filter(GetExport(), rPropSet));
|
|
|
|
// Get parent and remove hyperlinks (they aren't of interest)
|
|
OUString sName;
|
|
rbHyperlink = 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:
|
|
rbHyperlink = true;
|
|
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 );
|
|
}
|
|
sName = GetAutoStylePool().Find(
|
|
XmlStyleFamily::TEXT_TEXT,
|
|
OUString(), // AutoStyles should not have parents!
|
|
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_Int16 nListLevelsToBeClosed = 0;
|
|
if ( !rNextInfo.BelongsToSameList( rPrevInfo ) ||
|
|
rNextInfo.GetLevel() <= 0 )
|
|
{
|
|
// close complete previous list
|
|
nListLevelsToBeClosed = rPrevInfo.GetLevel();
|
|
}
|
|
else if ( rPrevInfo.GetLevel() > rNextInfo.GetLevel() )
|
|
{
|
|
// close corresponding sub lists
|
|
SAL_WARN_IF( rNextInfo.GetLevel() <= 0, "xmloff",
|
|
"<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
|
|
nListLevelsToBeClosed = rPrevInfo.GetLevel() - rNextInfo.GetLevel();
|
|
}
|
|
|
|
if ( nListLevelsToBeClosed > 0 &&
|
|
maListElements.size() >= sal::static_int_cast< sal_uInt32 >( 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 );
|
|
}
|
|
}
|
|
|
|
const bool bExportODF =
|
|
bool( GetExport().getExportFlags() & SvXMLExportFlags::OASIS );
|
|
const SvtSaveOptions::ODFSaneDefaultVersion eODFDefaultVersion =
|
|
GetExport().getSaneDefaultVersion();
|
|
|
|
// 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
|
|
SAL_WARN_IF( rPrevInfo.GetLevel() <= 0, "xmloff",
|
|
"<rPrevInfo.GetLevel() > 0> not hold. Serious defect." );
|
|
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 ( bExportODF &&
|
|
eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
|
|
!sListId.isEmpty() )
|
|
{
|
|
/* 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 ( bExportODF &&
|
|
eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
|
|
!sListId.isEmpty() )
|
|
{
|
|
/* 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() &&
|
|
!rNextInfo.IsRestart() )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_CONTINUE_NUMBERING,
|
|
XML_TRUE );
|
|
}
|
|
else
|
|
{
|
|
if ( bExportODF &&
|
|
eODFDefaultVersion >= SvtSaveOptions::ODFSVER_012 &&
|
|
!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() )
|
|
{
|
|
OUStringBuffer aBuffer;
|
|
aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
|
|
aBuffer.makeStringAndClear() );
|
|
}
|
|
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() )
|
|
{
|
|
OUStringBuffer aBuffer;
|
|
aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetStartValue()) );
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
|
|
aBuffer.makeStringAndClear() );
|
|
}
|
|
// Handle restart without start value on list level 1 (#i103745#)
|
|
else if ( rNextInfo.IsRestart() && /*!rNextInfo.HasStartValue() &&*/
|
|
rNextInfo.GetLevel() == 1 )
|
|
{
|
|
OUStringBuffer aBuffer;
|
|
aBuffer.append( static_cast<sal_Int32>(rNextInfo.GetListLevelStartValue()) );
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
|
|
aBuffer.makeStringAndClear() );
|
|
}
|
|
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;
|
|
}
|
|
};
|
|
|
|
XMLTextParagraphExport::XMLTextParagraphExport(
|
|
SvXMLExport& rExp,
|
|
SvXMLAutoStylePoolP & rASP
|
|
) :
|
|
XMLStyleExport( rExp, &rASP ),
|
|
m_xImpl(new Impl),
|
|
rAutoStylePool( rASP ),
|
|
pBoundFrameSets(new BoundFrameSets(GetExport().GetModel())),
|
|
maListAutoPool( GetExport() ),
|
|
bProgress( false ),
|
|
bBlock( false ),
|
|
bOpenRuby( false ),
|
|
mpTextListsHelper( nullptr ),
|
|
mbCollected(false),
|
|
aCharStyleNamesPropInfoCache( gsCharStyleNames )
|
|
{
|
|
rtl::Reference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TextPropMap::PARA, true ));
|
|
xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
|
|
GetExport() );
|
|
|
|
OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
|
|
OUString aPrefix(u'P');
|
|
rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_PARAGRAPH, sFamily,
|
|
xParaPropMapper, aPrefix );
|
|
|
|
xPropMapper = new XMLTextPropertySetMapper( TextPropMap::TEXT, true );
|
|
xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
|
|
GetExport() );
|
|
sFamily = GetXMLToken(XML_TEXT);
|
|
aPrefix = "T";
|
|
rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_TEXT, sFamily,
|
|
xTextPropMapper, aPrefix );
|
|
|
|
xPropMapper = new XMLTextPropertySetMapper( TextPropMap::AUTO_FRAME, true );
|
|
xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
|
|
GetExport() );
|
|
sFamily = XML_STYLE_FAMILY_SD_GRAPHICS_NAME;
|
|
aPrefix = "fr";
|
|
rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_FRAME, sFamily,
|
|
xAutoFramePropMapper, aPrefix );
|
|
|
|
xPropMapper = new XMLTextPropertySetMapper( TextPropMap::SECTION, true );
|
|
xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
|
|
GetExport() );
|
|
sFamily = GetXMLToken( XML_SECTION );
|
|
aPrefix = "Sect" ;
|
|
rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_SECTION, sFamily,
|
|
xSectionPropMapper, aPrefix );
|
|
|
|
xPropMapper = new XMLTextPropertySetMapper( TextPropMap::RUBY, true );
|
|
xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
|
|
sFamily = GetXMLToken( XML_RUBY );
|
|
aPrefix = "Ru";
|
|
rAutoStylePool.AddFamily( XmlStyleFamily::TEXT_RUBY, sFamily,
|
|
xRubyPropMapper, aPrefix );
|
|
|
|
xPropMapper = new XMLTextPropertySetMapper( TextPropMap::FRAME, true );
|
|
xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
|
|
GetExport() );
|
|
|
|
pSectionExport.reset( new XMLSectionExport( rExp, *this ) );
|
|
pIndexMarkExport.reset( new XMLIndexMarkExport( rExp ) );
|
|
|
|
if( ! IsBlockMode() &&
|
|
Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
|
|
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 = xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
|
|
"", XML_NAMESPACE_STYLE,
|
|
GetXMLToken(XML_TEXT_COMBINE));
|
|
pFieldExport.reset( new XMLTextFieldExport( rExp, std::make_unique<XMLPropertyState>( nIndex, uno::makeAny(true) ) ) );
|
|
PushNewTextListsHelper();
|
|
}
|
|
|
|
XMLTextParagraphExport::~XMLTextParagraphExport()
|
|
{
|
|
pRedlineExport.reset();
|
|
pIndexMarkExport.reset();
|
|
pSectionExport.reset();
|
|
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 = pBoundFrameSets->GetTexts()->GetPageBoundContents();
|
|
const TextContentSet& rGraphics = pBoundFrameSets->GetGraphics()->GetPageBoundContents();
|
|
const TextContentSet& rEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetPageBoundContents();
|
|
const TextContentSet& rShapes = 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 > *pParentTxtFrame )
|
|
{
|
|
const TextContentSet* const pTexts = pBoundFrameSets->GetTexts()->GetFrameBoundContents(*pParentTxtFrame);
|
|
if(pTexts)
|
|
for(TextContentSet::const_iterator_t it = pTexts->getBegin();
|
|
it != pTexts->getEnd();
|
|
++it)
|
|
exportTextFrame(*it, bAutoStyles, bIsProgress, true);
|
|
const TextContentSet* const pGraphics = pBoundFrameSets->GetGraphics()->GetFrameBoundContents(*pParentTxtFrame);
|
|
if(pGraphics)
|
|
for(TextContentSet::const_iterator_t it = pGraphics->getBegin();
|
|
it != pGraphics->getEnd();
|
|
++it)
|
|
exportTextGraphic(*it, bAutoStyles);
|
|
const TextContentSet* const pEmbeddeds = pBoundFrameSets->GetEmbeddeds()->GetFrameBoundContents(*pParentTxtFrame);
|
|
if(pEmbeddeds)
|
|
for(TextContentSet::const_iterator_t it = pEmbeddeds->getBegin();
|
|
it != pEmbeddeds->getEnd();
|
|
++it)
|
|
exportTextEmbedded(*it, bAutoStyles);
|
|
const TextContentSet* const pShapes = pBoundFrameSets->GetShapes()->GetFrameBoundContents(*pParentTxtFrame);
|
|
if(pShapes)
|
|
for(TextContentSet::const_iterator_t it = pShapes->getBegin();
|
|
it != pShapes->getEnd();
|
|
++it)
|
|
exportShape(*it, bAutoStyles);
|
|
}
|
|
|
|
// bookmarks, reference marks (and TOC marks) are the same except for the
|
|
// element names. We use the same method for export and it an array with
|
|
// the proper element names
|
|
const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
|
|
XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
|
|
const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
|
|
XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };
|
|
|
|
// This function replaces the text portion iteration during auto style
|
|
// collection.
|
|
void XMLTextParagraphExport::collectTextAutoStylesOptimized( bool bIsProgress )
|
|
{
|
|
GetExport().GetShapeExport(); // make sure the graphics styles family is added
|
|
|
|
if (mbCollected)
|
|
return;
|
|
|
|
const bool bAutoStyles = true;
|
|
const bool bExportContent = false;
|
|
|
|
// Export AutoStyles:
|
|
Reference< XAutoStylesSupplier > xAutoStylesSupp( GetExport().GetModel(), UNO_QUERY );
|
|
if ( xAutoStylesSupp.is() )
|
|
{
|
|
Reference< XAutoStyles > xAutoStyleFamilies = xAutoStylesSupp->getAutoStyles();
|
|
const auto collectFamily = [this, &xAutoStyleFamilies](const OUString& sName,
|
|
XmlStyleFamily nFamily) {
|
|
Any aAny = xAutoStyleFamilies->getByName( sName );
|
|
Reference< XAutoStyleFamily > xAutoStyles = *o3tl::doAccess<Reference<XAutoStyleFamily>>(aAny);
|
|
Reference < XEnumeration > xAutoStylesEnum( xAutoStyles->createEnumeration() );
|
|
|
|
while ( xAutoStylesEnum->hasMoreElements() )
|
|
{
|
|
aAny = xAutoStylesEnum->nextElement();
|
|
Reference< XAutoStyle > xAutoStyle = *o3tl::doAccess<Reference<XAutoStyle>>(aAny);
|
|
Reference < XPropertySet > xPSet( xAutoStyle, uno::UNO_QUERY );
|
|
Add( nFamily, xPSet, {}, true );
|
|
}
|
|
};
|
|
collectFamily("CharacterStyles", XmlStyleFamily::TEXT_TEXT);
|
|
collectFamily("RubyStyles", XmlStyleFamily::TEXT_RUBY);
|
|
collectFamily("ParagraphStyles", XmlStyleFamily::TEXT_PARAGRAPH);
|
|
}
|
|
|
|
// Export Field AutoStyles:
|
|
Reference< XTextFieldsSupplier > xTextFieldsSupp( GetExport().GetModel(), UNO_QUERY );
|
|
if ( xTextFieldsSupp.is() )
|
|
{
|
|
Reference< XEnumerationAccess > xTextFields = xTextFieldsSupp->getTextFields();
|
|
Reference < XEnumeration > xTextFieldsEnum( xTextFields->createEnumeration() );
|
|
|
|
while ( xTextFieldsEnum->hasMoreElements() )
|
|
{
|
|
Any aAny = xTextFieldsEnum->nextElement();
|
|
Reference< XTextField > xTextField = *o3tl::doAccess<Reference<XTextField>>(aAny);
|
|
exportTextField( xTextField, bAutoStyles, bIsProgress,
|
|
!xAutoStylesSupp.is(), nullptr );
|
|
try
|
|
{
|
|
Reference < XPropertySet > xSet( xTextField, UNO_QUERY );
|
|
Reference < XText > xText;
|
|
Any a = xSet->getPropertyValue("TextRange");
|
|
a >>= xText;
|
|
if ( xText.is() )
|
|
{
|
|
exportText( xText, true, bIsProgress, bExportContent );
|
|
GetExport().GetTextParagraphExport()
|
|
->collectTextAutoStyles( xText );
|
|
}
|
|
}
|
|
catch (Exception&)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
// Export text frames:
|
|
Reference<XEnumeration> xTextFramesEnum = pBoundFrameSets->GetTexts()->createEnumeration();
|
|
if(xTextFramesEnum.is())
|
|
while(xTextFramesEnum->hasMoreElements())
|
|
{
|
|
Reference<XTextContent> xTxtCntnt(xTextFramesEnum->nextElement(), UNO_QUERY);
|
|
if(xTxtCntnt.is())
|
|
exportTextFrame(xTxtCntnt, bAutoStyles, bIsProgress, bExportContent);
|
|
}
|
|
|
|
// Export graphic objects:
|
|
Reference<XEnumeration> xGraphicsEnum = pBoundFrameSets->GetGraphics()->createEnumeration();
|
|
if(xGraphicsEnum.is())
|
|
while(xGraphicsEnum->hasMoreElements())
|
|
{
|
|
Reference<XTextContent> xTxtCntnt(xGraphicsEnum->nextElement(), UNO_QUERY);
|
|
if(xTxtCntnt.is())
|
|
exportTextGraphic(xTxtCntnt, true);
|
|
}
|
|
|
|
// Export embedded objects:
|
|
Reference<XEnumeration> xEmbeddedsEnum = pBoundFrameSets->GetEmbeddeds()->createEnumeration();
|
|
if(xEmbeddedsEnum.is())
|
|
while(xEmbeddedsEnum->hasMoreElements())
|
|
{
|
|
Reference<XTextContent> xTxtCntnt(xEmbeddedsEnum->nextElement(), UNO_QUERY);
|
|
if(xTxtCntnt.is())
|
|
exportTextEmbedded(xTxtCntnt, true);
|
|
}
|
|
|
|
// Export shapes:
|
|
Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
|
|
if(xShapesEnum.is())
|
|
while(xShapesEnum->hasMoreElements())
|
|
{
|
|
Reference<XTextContent> xTxtCntnt(xShapesEnum->nextElement(), UNO_QUERY);
|
|
if(xTxtCntnt.is())
|
|
{
|
|
Reference<XServiceInfo> xServiceInfo(xTxtCntnt, UNO_QUERY);
|
|
if( xServiceInfo->supportsService(gsShapeService))
|
|
exportShape(xTxtCntnt, true);
|
|
}
|
|
}
|
|
|
|
sal_Int32 nCount;
|
|
// AutoStyles for sections
|
|
Reference< XTextSectionsSupplier > xSectionsSupp( GetExport().GetModel(), UNO_QUERY );
|
|
if ( xSectionsSupp.is() )
|
|
{
|
|
Reference< XIndexAccess > xSections( xSectionsSupp->getTextSections(), UNO_QUERY );
|
|
if ( xSections.is() )
|
|
{
|
|
nCount = xSections->getCount();
|
|
for( sal_Int32 i = 0; i < nCount; ++i )
|
|
{
|
|
Any aAny = xSections->getByIndex( i );
|
|
Reference< XTextSection > xSection = *o3tl::doAccess<Reference<XTextSection>>(aAny);
|
|
Reference < XPropertySet > xPSet( xSection, uno::UNO_QUERY );
|
|
Add( XmlStyleFamily::TEXT_SECTION, xPSet );
|
|
}
|
|
}
|
|
}
|
|
|
|
// AutoStyles for tables (Note: suppress autostyle collection for paragraphs in exportTable)
|
|
Reference< XTextTablesSupplier > xTablesSupp( GetExport().GetModel(), UNO_QUERY );
|
|
if ( xTablesSupp.is() )
|
|
{
|
|
Reference< XIndexAccess > xTables( xTablesSupp->getTextTables(), UNO_QUERY );
|
|
if ( xTables.is() )
|
|
{
|
|
nCount = xTables->getCount();
|
|
for( sal_Int32 i = 0; i < nCount; ++i )
|
|
{
|
|
Any aAny = xTables->getByIndex( i );
|
|
Reference< XTextTable > xTable = *o3tl::doAccess<Reference<XTextTable>>(aAny);
|
|
exportTable( xTable, true, true );
|
|
}
|
|
}
|
|
}
|
|
|
|
Reference< XNumberingRulesSupplier > xNumberingRulesSupp( GetExport().GetModel(), UNO_QUERY );
|
|
if ( xNumberingRulesSupp.is() )
|
|
{
|
|
Reference< XIndexAccess > xNumberingRules = xNumberingRulesSupp->getNumberingRules();
|
|
nCount = xNumberingRules->getCount();
|
|
// Custom outline assignment lost after re-importing sxw (#i73361#)
|
|
for( sal_Int32 i = 0; i < nCount; ++i )
|
|
{
|
|
Reference< XIndexReplace > xNumRule( xNumberingRules->getByIndex( i ), 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( "IsAutomatic" ) )
|
|
{
|
|
bAdd = *o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "IsAutomatic" ));
|
|
// Check on outline style (#i73361#)
|
|
if ( bAdd &&
|
|
xNumPropSet->getPropertySetInfo()
|
|
->hasPropertyByName( "NumberingIsOutline" ) )
|
|
{
|
|
bAdd = !(*o3tl::doAccess<bool>(xNumPropSet->getPropertyValue( "NumberingIsOutline" )));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bAdd = true;
|
|
}
|
|
}
|
|
if( bAdd )
|
|
maListAutoPool.Add( xNumRule );
|
|
}
|
|
}
|
|
}
|
|
mbCollected = true;
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportText(
|
|
const Reference < XText > & rText,
|
|
bool bAutoStyles,
|
|
bool bIsProgress,
|
|
bool bExportParagraph,
|
|
TextPNS eExtensionNS)
|
|
{
|
|
if( bAutoStyles )
|
|
GetExport().GetShapeExport(); // make sure the graphics styles family
|
|
// is added
|
|
Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
|
|
if( ! xEA.is() )
|
|
return;
|
|
|
|
Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
|
|
Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
|
|
Reference < XTextSection > xBaseSection;
|
|
|
|
// #97718# footnotes don't supply paragraph enumerations in some cases
|
|
// This is always a bug, but at least we don't want to crash.
|
|
SAL_WARN_IF( !xParaEnum.is(), "xmloff", "We need a paragraph enumeration" );
|
|
if( ! xParaEnum.is() )
|
|
return;
|
|
|
|
if (xPropertySet.is())
|
|
{
|
|
Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );
|
|
|
|
if( xInfo.is() )
|
|
{
|
|
if (xInfo->hasPropertyByName( gsTextSection ))
|
|
{
|
|
xPropertySet->getPropertyValue(gsTextSection) >>= xBaseSection ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// #96530# Export redlines at start & end of XText before & after
|
|
// exporting the text content enumeration
|
|
if( !bAutoStyles && (pRedlineExport != nullptr) )
|
|
pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
|
|
exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
|
|
bIsProgress, bExportParagraph, nullptr, eExtensionNS );
|
|
if( !bAutoStyles && (pRedlineExport != nullptr) )
|
|
pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportText(
|
|
const Reference < XText > & rText,
|
|
const Reference < XTextSection > & rBaseSection,
|
|
bool bAutoStyles,
|
|
bool bIsProgress,
|
|
bool bExportParagraph)
|
|
{
|
|
if( bAutoStyles )
|
|
GetExport().GetShapeExport(); // make sure the graphics styles family
|
|
// is added
|
|
Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
|
|
Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
|
|
|
|
// #98165# don't continue without a paragraph enumeration
|
|
if( ! xParaEnum.is() )
|
|
return;
|
|
|
|
// #96530# Export redlines at start & end of XText before & after
|
|
// exporting the text content enumeration
|
|
Reference<XPropertySet> xPropertySet;
|
|
if( !bAutoStyles && (pRedlineExport != nullptr) )
|
|
{
|
|
xPropertySet.set(rText, uno::UNO_QUERY );
|
|
pRedlineExport->ExportStartOrEndRedline( xPropertySet, true );
|
|
}
|
|
exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
|
|
bIsProgress, bExportParagraph );
|
|
if( !bAutoStyles && (pRedlineExport != nullptr) )
|
|
pRedlineExport->ExportStartOrEndRedline( xPropertySet, false );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextContentEnumeration(
|
|
const Reference < XEnumeration > & rContEnum,
|
|
bool bAutoStyles,
|
|
const Reference < XTextSection > & rBaseSection,
|
|
bool bIsProgress,
|
|
bool bExportParagraph,
|
|
const Reference < XPropertySet > *pRangePropSet,
|
|
TextPNS eExtensionNS )
|
|
{
|
|
SAL_WARN_IF( !rContEnum.is(), "xmloff", "No enumeration to export!" );
|
|
bool bHasMoreElements = rContEnum->hasMoreElements();
|
|
if( !bHasMoreElements )
|
|
return;
|
|
|
|
XMLTextNumRuleInfo aPrevNumInfo;
|
|
XMLTextNumRuleInfo aNextNumInfo;
|
|
|
|
bool bHasContent = false;
|
|
Reference<XTextSection> xCurrentTextSection(rBaseSection);
|
|
|
|
MultiPropertySetHelper aPropSetHelper(
|
|
bAutoStyles ? aParagraphPropertyNamesAuto :
|
|
aParagraphPropertyNames );
|
|
|
|
bool bHoldElement = false;
|
|
Reference < XTextContent > xTxtCntnt;
|
|
while( bHoldElement || bHasMoreElements )
|
|
{
|
|
if (bHoldElement)
|
|
{
|
|
bHoldElement = false;
|
|
}
|
|
else
|
|
{
|
|
xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
|
|
|
|
aPropSetHelper.resetValues();
|
|
|
|
}
|
|
|
|
Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
|
|
if( xServiceInfo->supportsService( gsParagraphService ) )
|
|
{
|
|
if( bAutoStyles )
|
|
{
|
|
exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
|
|
aPrevNumInfo, aNextNumInfo,
|
|
bAutoStyles );
|
|
}
|
|
else
|
|
{
|
|
/* Pass list auto style pool to <XMLTextNumRuleInfo> instance
|
|
Pass info about request to export <text:number> element
|
|
to <XMLTextNumRuleInfo> instance (#i69627#)
|
|
*/
|
|
aNextNumInfo.Set( xTxtCntnt,
|
|
GetExport().writeOutlineStyleAsNormalListStyle(),
|
|
GetListAutoStylePool(),
|
|
GetExport().exportTextNumberElement() );
|
|
|
|
exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
|
|
TEXT_SECTION, xTxtCntnt,
|
|
aPrevNumInfo, aNextNumInfo,
|
|
bAutoStyles );
|
|
}
|
|
|
|
// if we found a mute section: skip all section content
|
|
if (pSectionExport->IsMuteSection(xCurrentTextSection))
|
|
{
|
|
// Make sure headings are exported anyway.
|
|
if( !bAutoStyles )
|
|
pSectionExport->ExportMasterDocHeadingDummies();
|
|
|
|
while (rContEnum->hasMoreElements() &&
|
|
XMLSectionExport::IsInSection( xCurrentTextSection,
|
|
xTxtCntnt, true ))
|
|
{
|
|
xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
|
|
aPropSetHelper.resetValues();
|
|
aNextNumInfo.Reset();
|
|
}
|
|
// the first non-mute element still needs to be processed
|
|
bHoldElement =
|
|
! XMLSectionExport::IsInSection( xCurrentTextSection,
|
|
xTxtCntnt, false );
|
|
}
|
|
else
|
|
exportParagraph( xTxtCntnt, bAutoStyles, bIsProgress,
|
|
bExportParagraph, aPropSetHelper, eExtensionNS );
|
|
bHasContent = true;
|
|
}
|
|
else if( xServiceInfo->supportsService( gsTableService ) )
|
|
{
|
|
if( !bAutoStyles )
|
|
{
|
|
aNextNumInfo.Reset();
|
|
}
|
|
|
|
exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
|
|
aPrevNumInfo, aNextNumInfo,
|
|
bAutoStyles );
|
|
|
|
if (! pSectionExport->IsMuteSection(xCurrentTextSection))
|
|
{
|
|
// export start + end redlines (for wholly redlined tables)
|
|
if ((! bAutoStyles) && (nullptr != pRedlineExport))
|
|
pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, true);
|
|
|
|
exportTable( xTxtCntnt, bAutoStyles, bIsProgress );
|
|
|
|
if ((! bAutoStyles) && (nullptr != pRedlineExport))
|
|
pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, false);
|
|
}
|
|
else if( !bAutoStyles )
|
|
{
|
|
// Make sure headings are exported anyway.
|
|
pSectionExport->ExportMasterDocHeadingDummies();
|
|
}
|
|
|
|
bHasContent = true;
|
|
}
|
|
else if( xServiceInfo->supportsService( gsTextFrameService ) )
|
|
{
|
|
exportTextFrame( xTxtCntnt, bAutoStyles, bIsProgress, true, pRangePropSet );
|
|
}
|
|
else if( xServiceInfo->supportsService( gsTextGraphicService ) )
|
|
{
|
|
exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
|
|
}
|
|
else if( xServiceInfo->supportsService( gsTextEmbeddedService ) )
|
|
{
|
|
exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
|
|
}
|
|
else if( xServiceInfo->supportsService( gsShapeService ) )
|
|
{
|
|
exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
|
|
}
|
|
else
|
|
{
|
|
SAL_WARN_IF( xTxtCntnt.is(), "xmloff", "unknown text content" );
|
|
}
|
|
|
|
if( !bAutoStyles )
|
|
{
|
|
aPrevNumInfo = aNextNumInfo;
|
|
}
|
|
|
|
bHasMoreElements = rContEnum->hasMoreElements();
|
|
}
|
|
|
|
if( bHasContent && !bAutoStyles )
|
|
{
|
|
aNextNumInfo.Reset();
|
|
|
|
// close open lists and sections; no new styles
|
|
exportListAndSectionChange( xCurrentTextSection, rBaseSection,
|
|
aPrevNumInfo, aNextNumInfo,
|
|
bAutoStyles );
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportParagraph(
|
|
const Reference < XTextContent > & rTextContent,
|
|
bool bAutoStyles, bool bIsProgress, bool bExportParagraph,
|
|
MultiPropertySetHelper& rPropSetHelper, TextPNS eExtensionNS)
|
|
{
|
|
sal_Int16 nOutlineLevel = -1;
|
|
|
|
if( bIsProgress )
|
|
{
|
|
ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
|
|
pProgress->SetValue( pProgress->GetValue()+1 );
|
|
}
|
|
|
|
// get property set or multi property set and initialize helper
|
|
Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
|
|
Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );
|
|
|
|
// check for supported properties
|
|
if( !rPropSetHelper.checkedProperties() )
|
|
rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );
|
|
|
|
// if( xMultiPropSet.is() )
|
|
// rPropSetHelper.getValues( xMultiPropSet );
|
|
// else
|
|
// rPropSetHelper.getValues( xPropSet );
|
|
|
|
if( bExportParagraph )
|
|
{
|
|
if( bAutoStyles )
|
|
{
|
|
Add( XmlStyleFamily::TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
|
|
}
|
|
else
|
|
{
|
|
// xml:id for RDF metadata
|
|
GetExport().AddAttributeXmlId(rTextContent);
|
|
GetExport().AddAttributesRDFa(rTextContent);
|
|
|
|
OUString sStyle;
|
|
if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
|
|
{
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue( PARA_STYLE_NAME,
|
|
xMultiPropSet ) >>= sStyle;
|
|
else
|
|
rPropSetHelper.getValue( PARA_STYLE_NAME,
|
|
xPropSet ) >>= sStyle;
|
|
}
|
|
|
|
if( rTextContent.is() )
|
|
{
|
|
const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( rTextContent );
|
|
if( !rIdentifier.isEmpty() )
|
|
{
|
|
// FIXME: this is just temporary until EditEngine
|
|
// paragraphs implement XMetadatable.
|
|
// then that must be used and not the mapper, because
|
|
// when both can be used we get two xml:id!
|
|
uno::Reference<rdf::XMetadatable> const xMeta(rTextContent,
|
|
uno::UNO_QUERY);
|
|
OSL_ENSURE(!xMeta.is(), "paragraph that implements "
|
|
"XMetadatable used in interfaceToIdentifierMapper?");
|
|
GetExport().AddAttributeIdLegacy(XML_NAMESPACE_TEXT,
|
|
rIdentifier);
|
|
}
|
|
}
|
|
|
|
OUString sAutoStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet, sStyle );
|
|
if ( sAutoStyle.isEmpty() )
|
|
sAutoStyle = sStyle;
|
|
if( !sAutoStyle.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sAutoStyle ) );
|
|
|
|
if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
|
|
{
|
|
OUString sCondStyle;
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
|
|
xMultiPropSet ) >>= sCondStyle;
|
|
else
|
|
rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
|
|
xPropSet ) >>= sCondStyle;
|
|
if( sCondStyle != sStyle )
|
|
{
|
|
sCondStyle = Find( XmlStyleFamily::TEXT_PARAGRAPH, xPropSet,
|
|
sCondStyle );
|
|
if( !sCondStyle.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_COND_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sCondStyle ) );
|
|
}
|
|
}
|
|
|
|
if( rPropSetHelper.hasProperty( PARA_OUTLINE_LEVEL ) )
|
|
{
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
|
|
xMultiPropSet ) >>= nOutlineLevel;
|
|
else
|
|
rPropSetHelper.getValue( PARA_OUTLINE_LEVEL,
|
|
xPropSet ) >>= nOutlineLevel;
|
|
|
|
if( 0 < nOutlineLevel )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_OUTLINE_LEVEL,
|
|
OUString::number( sal_Int32( nOutlineLevel) ) );
|
|
|
|
if ( rPropSetHelper.hasProperty( PARA_OUTLINE_CONTENT_VISIBLE ) )
|
|
{
|
|
uno::Sequence<beans::PropertyValue> propList;
|
|
bool bIsOutlineContentVisible = true;
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue(
|
|
PARA_OUTLINE_CONTENT_VISIBLE, xMultiPropSet ) >>= propList;
|
|
else
|
|
rPropSetHelper.getValue(
|
|
PARA_OUTLINE_CONTENT_VISIBLE, xPropSet ) >>= propList;
|
|
for (const auto& rProp : std::as_const(propList))
|
|
{
|
|
OUString propName = rProp.Name;
|
|
if (propName == "OutlineContentVisibleAttr")
|
|
{
|
|
rProp.Value >>= bIsOutlineContentVisible;
|
|
break;
|
|
}
|
|
}
|
|
if (!bIsOutlineContentVisible)
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_LO_EXT,
|
|
XML_OUTLINE_CONTENT_VISIBLE,
|
|
XML_FALSE);
|
|
}
|
|
}
|
|
|
|
if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
|
|
{
|
|
bool bIsNumber = false;
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue(
|
|
NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
|
|
else
|
|
rPropSetHelper.getValue(
|
|
NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;
|
|
|
|
OUString sListStyleName;
|
|
if( xMultiPropSet.is() )
|
|
rPropSetHelper.getValue(
|
|
PARA_NUMBERING_STYLENAME, xMultiPropSet ) >>= sListStyleName;
|
|
else
|
|
rPropSetHelper.getValue(
|
|
PARA_NUMBERING_STYLENAME, xPropSet ) >>= sListStyleName;
|
|
|
|
bool bAssignedtoOutlineStyle = false;
|
|
{
|
|
Reference< XChapterNumberingSupplier > xCNSupplier( GetExport().GetModel(), UNO_QUERY );
|
|
|
|
if (xCNSupplier.is())
|
|
{
|
|
Reference< XIndexReplace > xNumRule ( xCNSupplier->getChapterNumberingRules() );
|
|
SAL_WARN_IF( !xNumRule.is(), "xmloff", "no chapter numbering rules" );
|
|
|
|
if (xNumRule.is())
|
|
{
|
|
Reference< XPropertySet > xNumRulePropSet( xNumRule, UNO_QUERY );
|
|
OUString sOutlineName;
|
|
xNumRulePropSet->getPropertyValue(
|
|
"Name" ) >>= sOutlineName;
|
|
bAssignedtoOutlineStyle = ( sListStyleName == sOutlineName );
|
|
}
|
|
}
|
|
}
|
|
|
|
if( ! bIsNumber && bAssignedtoOutlineStyle )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_IS_LIST_HEADER,
|
|
XML_TRUE );
|
|
}
|
|
|
|
{
|
|
bool bIsRestartNumbering = false;
|
|
|
|
Reference< XPropertySetInfo >
|
|
xPropSetInfo(xMultiPropSet.is() ?
|
|
xMultiPropSet->getPropertySetInfo():
|
|
xPropSet->getPropertySetInfo());
|
|
|
|
if (xPropSetInfo->
|
|
hasPropertyByName("ParaIsNumberingRestart"))
|
|
{
|
|
xPropSet->getPropertyValue("ParaIsNumberingRestart")
|
|
>>= bIsRestartNumbering;
|
|
}
|
|
|
|
if (bIsRestartNumbering)
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
|
|
XML_RESTART_NUMBERING,
|
|
XML_TRUE);
|
|
|
|
if (xPropSetInfo->
|
|
hasPropertyByName("NumberingStartValue"))
|
|
{
|
|
sal_Int32 nStartValue = 0;
|
|
|
|
xPropSet->getPropertyValue("NumberingStartValue")
|
|
>>= nStartValue;
|
|
|
|
GetExport().
|
|
AddAttribute(XML_NAMESPACE_TEXT,
|
|
XML_START_VALUE,
|
|
OUString::number(nStartValue));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
|
|
Reference < XEnumeration > xTextEnum = xEA->createEnumeration();
|
|
const bool bHasPortions = xTextEnum.is();
|
|
|
|
Reference < XEnumeration> xContentEnum;
|
|
Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
|
|
if( xCEA.is() )
|
|
xContentEnum.set(xCEA->createContentEnumeration( gsTextContentService ));
|
|
const bool bHasContentEnum = xContentEnum.is() &&
|
|
xContentEnum->hasMoreElements();
|
|
|
|
Reference < XTextSection > xSection;
|
|
if( bHasContentEnum )
|
|
{
|
|
// For the auto styles, the multi property set helper is only used
|
|
// if hard attributes are existing. Therefore, it seems to be a better
|
|
// strategy to have the TextSection property separate, because otherwise
|
|
// we always retrieve the style names even if they are not required.
|
|
if( bAutoStyles )
|
|
{
|
|
if( xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextSection ) )
|
|
{
|
|
xSection.set(xPropSet->getPropertyValue( gsTextSection ), uno::UNO_QUERY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
|
|
{
|
|
xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool bPrevCharIsSpace(true); // true because whitespace at start is ignored
|
|
|
|
if( bAutoStyles )
|
|
{
|
|
if( bHasContentEnum )
|
|
exportTextContentEnumeration(
|
|
xContentEnum, bAutoStyles, xSection,
|
|
bIsProgress );
|
|
if ( bHasPortions )
|
|
{
|
|
exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
enum XMLTokenEnum eElem =
|
|
0 < nOutlineLevel ? XML_H : XML_P;
|
|
SvXMLElementExport aElem( GetExport(), eExtensionNS == TextPNS::EXTENSION ? XML_NAMESPACE_LO_EXT : XML_NAMESPACE_TEXT, eElem,
|
|
true, false );
|
|
if( bHasContentEnum )
|
|
{
|
|
exportTextContentEnumeration(
|
|
xContentEnum, bAutoStyles, xSection,
|
|
bIsProgress );
|
|
}
|
|
exportTextRangeEnumeration(xTextEnum, bAutoStyles, bIsProgress, bPrevCharIsSpace);
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextRangeEnumeration(
|
|
const Reference < XEnumeration > & rTextEnum,
|
|
bool bAutoStyles, bool bIsProgress,
|
|
bool & rPrevCharIsSpace)
|
|
{
|
|
static const char sFieldMarkName[] = "__FieldMark_";
|
|
|
|
/* This is used for exporting to strict OpenDocument 1.2, in which case traditional
|
|
* bookmarks are used instead of fieldmarks. */
|
|
FieldmarkType openFieldMark = NONE;
|
|
|
|
while( rTextEnum->hasMoreElements() )
|
|
{
|
|
Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
|
|
Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
|
|
Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());
|
|
|
|
if (xPropInfo->hasPropertyByName(gsTextPortionType))
|
|
{
|
|
OUString sType;
|
|
xPropSet->getPropertyValue(gsTextPortionType) >>= sType;
|
|
|
|
if( sType == gsText)
|
|
{
|
|
exportTextRange( xTxtRange, bAutoStyles,
|
|
rPrevCharIsSpace, openFieldMark);
|
|
}
|
|
else if( sType == gsTextField)
|
|
{
|
|
exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
|
|
}
|
|
else if ( sType == "Annotation" )
|
|
{
|
|
exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
|
|
}
|
|
else if ( sType == "AnnotationEnd" )
|
|
{
|
|
if (!bAutoStyles)
|
|
{
|
|
Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
const OUString& rName = xBookmark->getName();
|
|
if (!rName.isEmpty())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, rName);
|
|
}
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_OFFICE, XML_ANNOTATION_END, false, false );
|
|
}
|
|
}
|
|
else if( sType == gsFrame )
|
|
{
|
|
Reference < XEnumeration> xContentEnum;
|
|
Reference < XContentEnumerationAccess > xCEA( xTxtRange,
|
|
UNO_QUERY );
|
|
if( xCEA.is() )
|
|
xContentEnum.set(xCEA->createContentEnumeration(
|
|
gsTextContentService ));
|
|
// frames are never in sections
|
|
Reference<XTextSection> xSection;
|
|
if( xContentEnum.is() )
|
|
exportTextContentEnumeration( xContentEnum,
|
|
bAutoStyles,
|
|
xSection, bIsProgress, true,
|
|
&xPropSet );
|
|
|
|
}
|
|
else if (sType == gsFootnote)
|
|
{
|
|
exportTextFootnote(xPropSet,
|
|
xTxtRange->getString(),
|
|
bAutoStyles, bIsProgress );
|
|
}
|
|
else if (sType == gsBookmark)
|
|
{
|
|
exportTextMark(xPropSet,
|
|
gsBookmark,
|
|
lcl_XmlBookmarkElements,
|
|
bAutoStyles);
|
|
}
|
|
else if (sType == gsReferenceMark)
|
|
{
|
|
exportTextMark(xPropSet,
|
|
gsReferenceMark,
|
|
lcl_XmlReferenceElements,
|
|
bAutoStyles);
|
|
}
|
|
else if (sType == gsDocumentIndexMark)
|
|
{
|
|
pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
|
|
}
|
|
else if (sType == gsRedline)
|
|
{
|
|
if (nullptr != pRedlineExport)
|
|
pRedlineExport->ExportChange(xPropSet, bAutoStyles);
|
|
}
|
|
else if (sType == gsRuby)
|
|
{
|
|
exportRuby(xPropSet, bAutoStyles);
|
|
}
|
|
else if (sType == "InContentMetadata")
|
|
{
|
|
exportMeta(xPropSet, bAutoStyles, bIsProgress, rPrevCharIsSpace);
|
|
}
|
|
else if (sType == gsTextFieldStart)
|
|
{
|
|
Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
|
|
/* As of now, textmarks are a proposed extension to the OpenDocument standard. */
|
|
if (!bAutoStyles)
|
|
{
|
|
if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
|
|
{
|
|
Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
if (xBookmark.is())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
|
|
}
|
|
|
|
if (xFormField.is())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
|
|
}
|
|
|
|
GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
|
|
if (xFormField.is())
|
|
{
|
|
FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
|
|
}
|
|
GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK_START, false);
|
|
}
|
|
/* The OpenDocument standard does not include support for TextMarks for now, so use bookmarks instead. */
|
|
else
|
|
{
|
|
if (xFormField.is())
|
|
{
|
|
OUString sName;
|
|
Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
|
|
if (xParameters.is() && xParameters->hasByName("Name"))
|
|
{
|
|
const Any aValue = xParameters->getByName("Name");
|
|
aValue >>= sName;
|
|
}
|
|
if (sName.isEmpty())
|
|
{ // name attribute is mandatory, so have to pull a
|
|
// rabbit out of the hat here
|
|
sName = sFieldMarkName + OUString::number(
|
|
m_xImpl->AddFieldMarkStart(xFormField));
|
|
}
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
|
|
sName);
|
|
SvXMLElementExport aElem( GetExport(), !bAutoStyles,
|
|
XML_NAMESPACE_TEXT, XML_BOOKMARK_START,
|
|
false, false );
|
|
const OUString sFieldType = xFormField->getFieldType();
|
|
if (sFieldType == ODF_FORMTEXT)
|
|
{
|
|
openFieldMark = TEXT;
|
|
}
|
|
else if (sFieldType == ODF_FORMCHECKBOX)
|
|
{
|
|
openFieldMark = CHECK;
|
|
}
|
|
else
|
|
{
|
|
openFieldMark = NONE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (sType == gsTextFieldEnd)
|
|
{
|
|
if (!bAutoStyles)
|
|
{
|
|
Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
|
|
if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), !bAutoStyles,
|
|
XML_NAMESPACE_FIELD, XML_FIELDMARK_END,
|
|
false, false );
|
|
}
|
|
else
|
|
{
|
|
if (xFormField.is())
|
|
{
|
|
OUString sName;
|
|
Reference< css::container::XNameAccess > xParameters = xFormField->getParameters();
|
|
if (xParameters.is() && xParameters->hasByName("Name"))
|
|
{
|
|
const Any aValue = xParameters->getByName("Name");
|
|
aValue >>= sName;
|
|
}
|
|
if (sName.isEmpty())
|
|
{ // name attribute is mandatory, so have to pull a
|
|
// rabbit out of the hat here
|
|
sName = sFieldMarkName + OUString::number(
|
|
m_xImpl->GetFieldMarkIndex(xFormField));
|
|
}
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
|
|
sName);
|
|
SvXMLElementExport aElem( GetExport(), !bAutoStyles,
|
|
XML_NAMESPACE_TEXT, XML_BOOKMARK_END,
|
|
false, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (sType == gsTextFieldStartEnd)
|
|
{
|
|
if (!bAutoStyles)
|
|
{
|
|
if (GetExport().getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED)
|
|
{
|
|
Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
if (xBookmark.is())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
|
|
}
|
|
Reference< css::text::XFormField > xFormField(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
if (xFormField.is())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_FIELD, XML_TYPE, xFormField->getFieldType());
|
|
}
|
|
GetExport().StartElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
|
|
if (xFormField.is())
|
|
{
|
|
FieldParamExporter(&GetExport(), xFormField->getParameters()).Export();
|
|
}
|
|
GetExport().EndElement(XML_NAMESPACE_FIELD, XML_FIELDMARK, false);
|
|
}
|
|
else
|
|
{
|
|
Reference<XNamed> xBookmark(xPropSet->getPropertyValue(gsBookmark), UNO_QUERY);
|
|
if (xBookmark.is())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xBookmark->getName());
|
|
SvXMLElementExport aElem( GetExport(), !bAutoStyles,
|
|
XML_NAMESPACE_TEXT, XML_BOOKMARK,
|
|
false, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (sType == gsSoftPageBreak)
|
|
{
|
|
exportSoftPageBreak();
|
|
}
|
|
else {
|
|
OSL_FAIL("unknown text portion type");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
|
|
if( xServiceInfo->supportsService( gsTextFieldService ) )
|
|
{
|
|
exportTextField(xTxtRange, bAutoStyles, bIsProgress, &rPrevCharIsSpace);
|
|
}
|
|
else
|
|
{
|
|
// no TextPortionType property -> non-Writer app -> text
|
|
exportTextRange(xTxtRange, bAutoStyles, rPrevCharIsSpace, openFieldMark);
|
|
}
|
|
}
|
|
}
|
|
|
|
// now that there are nested enumerations for meta(-field), this may be valid!
|
|
// SAL_WARN_IF( bOpenRuby, "xmloff", "Red Alert: Ruby still open!" );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTable(
|
|
const Reference < XTextContent > &,
|
|
bool /*bAutoStyles*/, bool /*bIsProgress*/ )
|
|
{
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextField(
|
|
const Reference < XTextRange > & rTextRange,
|
|
bool bAutoStyles, bool bIsProgress, bool *const pPrevCharIsSpace)
|
|
{
|
|
Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
|
|
// non-Writer apps need not support Property TextField, so test first
|
|
if (!xPropSet->getPropertySetInfo()->hasPropertyByName( gsTextField ))
|
|
return;
|
|
|
|
Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( gsTextField ), uno::UNO_QUERY);
|
|
SAL_WARN_IF( !xTxtFld.is(), "xmloff", "text field missing" );
|
|
if( xTxtFld.is() )
|
|
{
|
|
exportTextField(xTxtFld, bAutoStyles, bIsProgress, true, pPrevCharIsSpace);
|
|
}
|
|
else
|
|
{
|
|
// write only characters
|
|
GetExport().Characters(rTextRange->getString());
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextField(
|
|
const Reference < XTextField > & xTextField,
|
|
const bool bAutoStyles, const bool bIsProgress,
|
|
const bool bRecursive, bool *const pPrevCharIsSpace)
|
|
{
|
|
if ( bAutoStyles )
|
|
{
|
|
pFieldExport->ExportFieldAutoStyle( xTextField, bIsProgress,
|
|
bRecursive );
|
|
}
|
|
else
|
|
{
|
|
assert(pPrevCharIsSpace);
|
|
pFieldExport->ExportField(xTextField, bIsProgress, *pPrevCharIsSpace);
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportSoftPageBreak()
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
|
|
XML_SOFT_PAGE_BREAK, false,
|
|
false );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextMark(
|
|
const Reference<XPropertySet> & rPropSet,
|
|
const OUString& rProperty,
|
|
const ::xmloff::token::XMLTokenEnum pElements[],
|
|
bool bAutoStyles)
|
|
{
|
|
// mib said: "Hau wech!"
|
|
|
|
// (Originally, I'd export a span element in case the (book|reference)mark
|
|
// was formatted. This actually makes a difference in case some pervert
|
|
// sets a point reference mark in the document and, say, formats it bold.
|
|
// This basically meaningless formatting will now been thrown away
|
|
// (aka cleaned up), since mib said: ... dvo
|
|
|
|
if (bAutoStyles)
|
|
return;
|
|
|
|
// name element
|
|
Reference<XNamed> xName(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
|
|
xName->getName());
|
|
|
|
// start, end, or point-reference?
|
|
sal_Int8 nElement;
|
|
if( *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)) )
|
|
{
|
|
nElement = 0;
|
|
}
|
|
else
|
|
{
|
|
nElement = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart)) ? 1 : 2;
|
|
}
|
|
|
|
// bookmark, bookmark-start: xml:id and RDFa for RDF metadata
|
|
if( nElement < 2 ) {
|
|
GetExport().AddAttributeXmlId(xName);
|
|
const uno::Reference<text::XTextContent> xTextContent(
|
|
xName, uno::UNO_QUERY_THROW);
|
|
GetExport().AddAttributesRDFa(xTextContent);
|
|
}
|
|
|
|
// bookmark-start: add attributes hidden and condition
|
|
if (nElement == 1)
|
|
{
|
|
Reference<XPropertySet> bkmkProps(rPropSet->getPropertyValue(rProperty), UNO_QUERY);
|
|
Reference<XPropertySetInfo> bkmkPropInfo = bkmkProps->getPropertySetInfo();
|
|
OUString sHidden("BookmarkHidden");
|
|
if (bkmkPropInfo->hasPropertyByName(sHidden))
|
|
{
|
|
bool bHidden = false;
|
|
bkmkProps->getPropertyValue(sHidden) >>= bHidden;
|
|
if (bHidden)
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "hidden", "true");
|
|
OUString sCondition("BookmarkCondition");
|
|
if (bkmkPropInfo->hasPropertyByName(sCondition))
|
|
{
|
|
OUString sBookmarkCondition;
|
|
bkmkProps->getPropertyValue(sCondition) >>= sBookmarkCondition;
|
|
GetExport().AddAttribute(XML_NAMESPACE_LO_EXT, "condition", sBookmarkCondition);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// export element
|
|
assert(pElements != nullptr);
|
|
assert(0 <= nElement && nElement <= 2);
|
|
SvXMLElementExport aElem(GetExport(),
|
|
XML_NAMESPACE_TEXT, pElements[nElement],
|
|
false, false);
|
|
// else: no styles. (see above)
|
|
}
|
|
|
|
static bool lcl_txtpara_isBoundAsChar(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
const Reference < XPropertySetInfo > & rPropSetInfo )
|
|
{
|
|
bool bIsBoundAsChar = false;
|
|
OUString sAnchorType( "AnchorType" );
|
|
if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
|
|
{
|
|
TextContentAnchorType eAnchor;
|
|
rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
|
|
bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
|
|
}
|
|
|
|
return bIsBoundAsChar;
|
|
}
|
|
|
|
XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes(
|
|
const Reference < XPropertySet >& rPropSet,
|
|
bool bShape,
|
|
basegfx::B2DPoint* pCenter,
|
|
OUString* pMinHeightValue,
|
|
OUString* pMinWidthValue)
|
|
{
|
|
XMLShapeExportFlags nShapeFeatures = SEF_DEFAULT;
|
|
|
|
// draw:name (#97662#: not for shapes, since those names will be
|
|
// treated in the shape export)
|
|
if( !bShape )
|
|
{
|
|
Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
|
|
if( xNamed.is() )
|
|
{
|
|
OUString sName( xNamed->getName() );
|
|
if( !sName.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
|
|
xNamed->getName() );
|
|
}
|
|
}
|
|
|
|
OUStringBuffer sValue;
|
|
|
|
// text:anchor-type
|
|
TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
|
|
rPropSet->getPropertyValue( gsAnchorType ) >>= eAnchor;
|
|
{
|
|
XMLAnchorTypePropHdl aAnchorTypeHdl;
|
|
OUString sTmp;
|
|
aAnchorTypeHdl.exportXML( sTmp, uno::makeAny(eAnchor),
|
|
GetExport().GetMM100UnitConverter() );
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
|
|
}
|
|
|
|
// text:anchor-page-number
|
|
if( TextContentAnchorType_AT_PAGE == eAnchor )
|
|
{
|
|
sal_Int16 nPage = 0;
|
|
rPropSet->getPropertyValue( gsAnchorPageNo ) >>= nPage;
|
|
SAL_WARN_IF(nPage <= 0, "xmloff",
|
|
"ERROR: writing invalid anchor-page-number 0");
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
|
|
OUString::number( nPage ) );
|
|
}
|
|
else
|
|
{
|
|
nShapeFeatures |= XMLShapeExportFlags::NO_WS;
|
|
}
|
|
|
|
// OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
|
|
// is anchored as-character.
|
|
if ( !bShape &&
|
|
eAnchor != TextContentAnchorType_AS_CHARACTER )
|
|
{
|
|
// svg:x
|
|
sal_Int16 nHoriOrient = HoriOrientation::NONE;
|
|
rPropSet->getPropertyValue( gsHoriOrient ) >>= nHoriOrient;
|
|
if( HoriOrientation::NONE == nHoriOrient )
|
|
{
|
|
sal_Int32 nPos = 0;
|
|
rPropSet->getPropertyValue( gsHoriOrientPosition ) >>= nPos;
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML(
|
|
sValue, nPos );
|
|
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
|
|
sValue.makeStringAndClear() );
|
|
if(nullptr != pCenter)
|
|
{
|
|
// add left edge to Center
|
|
pCenter->setX(pCenter->getX() + nPos);
|
|
}
|
|
}
|
|
}
|
|
else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
|
|
nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::X);
|
|
|
|
if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor )
|
|
{
|
|
// svg:y
|
|
sal_Int16 nVertOrient = VertOrientation::NONE;
|
|
rPropSet->getPropertyValue( gsVertOrient ) >>= nVertOrient;
|
|
if( VertOrientation::NONE == nVertOrient )
|
|
{
|
|
sal_Int32 nPos = 0;
|
|
rPropSet->getPropertyValue( gsVertOrientPosition ) >>= nPos;
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML(
|
|
sValue, nPos );
|
|
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
|
|
sValue.makeStringAndClear() );
|
|
if(nullptr != pCenter)
|
|
{
|
|
// add top edge to Center
|
|
pCenter->setY(pCenter->getY() + nPos);
|
|
}
|
|
}
|
|
if( bShape )
|
|
nShapeFeatures = (nShapeFeatures & ~XMLShapeExportFlags::Y);
|
|
}
|
|
|
|
Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
|
|
|
|
// svg:width
|
|
sal_Int16 nWidthType = SizeType::FIX;
|
|
if( xPropSetInfo->hasPropertyByName( gsWidthType ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsWidthType ) >>= nWidthType;
|
|
}
|
|
if( xPropSetInfo->hasPropertyByName( gsWidth ) )
|
|
{
|
|
sal_Int32 nWidth = 0;
|
|
// VAR size will be written as zero min-size
|
|
if( SizeType::VARIABLE != nWidthType )
|
|
{
|
|
rPropSet->getPropertyValue( gsWidth ) >>= nWidth;
|
|
}
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, nWidth);
|
|
if( SizeType::FIX != nWidthType )
|
|
{
|
|
assert(pMinWidthValue);
|
|
if (pMinWidthValue)
|
|
{
|
|
*pMinWidthValue = sValue.makeStringAndClear();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
|
|
sValue.makeStringAndClear() );
|
|
if(nullptr != pCenter)
|
|
{
|
|
// add half width to Center
|
|
pCenter->setX(pCenter->getX() + (0.5 * nWidth));
|
|
}
|
|
}
|
|
}
|
|
bool bSyncWidth = false;
|
|
if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) )
|
|
{
|
|
bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncWidthToHeight ));
|
|
if( bSyncWidth )
|
|
GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
|
|
XML_SCALE );
|
|
}
|
|
if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) )
|
|
{
|
|
sal_Int16 nRelWidth = 0;
|
|
rPropSet->getPropertyValue( gsRelativeWidth ) >>= nRelWidth;
|
|
SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff",
|
|
"Got illegal relative width from API" );
|
|
if( nRelWidth > 0 )
|
|
{
|
|
::sax::Converter::convertPercent( sValue, nRelWidth );
|
|
GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
|
|
sValue.makeStringAndClear() );
|
|
}
|
|
}
|
|
|
|
// svg:height, fo:min-height or style:rel-height
|
|
sal_Int16 nSizeType = SizeType::FIX;
|
|
if( xPropSetInfo->hasPropertyByName( gsSizeType ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType;
|
|
}
|
|
bool bSyncHeight = false;
|
|
if( xPropSetInfo->hasPropertyByName( gsIsSyncHeightToWidth ) )
|
|
{
|
|
bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncHeightToWidth ));
|
|
}
|
|
sal_Int16 nRelHeight = 0;
|
|
if( !bSyncHeight && xPropSetInfo->hasPropertyByName( gsRelativeHeight ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsRelativeHeight ) >>= nRelHeight;
|
|
}
|
|
if( xPropSetInfo->hasPropertyByName( gsHeight ) )
|
|
{
|
|
sal_Int32 nHeight = 0;
|
|
if( SizeType::VARIABLE != nSizeType )
|
|
{
|
|
rPropSet->getPropertyValue( gsHeight ) >>= nHeight;
|
|
}
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML( sValue,
|
|
nHeight );
|
|
if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
|
|
pMinHeightValue )
|
|
{
|
|
*pMinHeightValue = sValue.makeStringAndClear();
|
|
}
|
|
else
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
|
|
sValue.makeStringAndClear() );
|
|
if(nullptr != pCenter)
|
|
{
|
|
// add half height to Center
|
|
pCenter->setY(pCenter->getY() + (0.5 * nHeight));
|
|
}
|
|
}
|
|
}
|
|
if( bSyncHeight )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
|
|
SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );
|
|
|
|
}
|
|
else if( nRelHeight > 0 )
|
|
{
|
|
::sax::Converter::convertPercent( sValue, nRelHeight );
|
|
if( SizeType::MIN == nSizeType )
|
|
{
|
|
assert(pMinHeightValue);
|
|
if (pMinHeightValue)
|
|
{
|
|
*pMinHeightValue = sValue.makeStringAndClear();
|
|
}
|
|
}
|
|
else
|
|
GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
|
|
sValue.makeStringAndClear() );
|
|
}
|
|
|
|
OUString sZOrder( "ZOrder" );
|
|
if( xPropSetInfo->hasPropertyByName( sZOrder ) )
|
|
{
|
|
sal_Int32 nZIndex = 0;
|
|
rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
|
|
if( -1 != nZIndex )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
|
|
OUString::number( nZIndex ) );
|
|
}
|
|
}
|
|
|
|
return nShapeFeatures;
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportAnyTextFrame(
|
|
const Reference < XTextContent > & rTxtCntnt,
|
|
FrameType eType,
|
|
bool bAutoStyles,
|
|
bool bIsProgress,
|
|
bool bExportContent,
|
|
const Reference < XPropertySet > *pRangePropSet)
|
|
{
|
|
Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );
|
|
|
|
if( bAutoStyles )
|
|
{
|
|
if( FrameType::Embedded == eType )
|
|
_collectTextEmbeddedAutoStyles( xPropSet );
|
|
// No text frame style for shapes (#i28745#)
|
|
else if ( FrameType::Shape != eType )
|
|
Add( XmlStyleFamily::TEXT_FRAME, xPropSet );
|
|
|
|
if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
|
|
xPropSet->getPropertySetInfo() ) )
|
|
Add( XmlStyleFamily::TEXT_TEXT, *pRangePropSet );
|
|
|
|
switch( eType )
|
|
{
|
|
case FrameType::Text:
|
|
{
|
|
// frame bound frames
|
|
if ( bExportContent )
|
|
{
|
|
Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
|
|
Reference < XText > xTxt(xTxtFrame->getText());
|
|
exportFrameFrames( true, bIsProgress, &xTxtFrame );
|
|
exportText( xTxt, bAutoStyles, bIsProgress, true );
|
|
}
|
|
}
|
|
break;
|
|
case FrameType::Shape:
|
|
{
|
|
Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
|
|
GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
|
|
Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
|
|
{
|
|
bool bAddCharStyles = pRangePropSet &&
|
|
lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
|
|
|
|
bool bIsUICharStyle;
|
|
bool bHasAutoStyle = false;
|
|
|
|
OUString sStyle;
|
|
|
|
if( bAddCharStyles )
|
|
{
|
|
bool bDummy;
|
|
sStyle = FindTextStyleAndHyperlink( *pRangePropSet, bDummy, bIsUICharStyle, bHasAutoStyle );
|
|
}
|
|
else
|
|
bIsUICharStyle = false;
|
|
|
|
bool bDoSomething = bIsUICharStyle
|
|
&& aCharStyleNamesPropInfoCache.hasProperty( *pRangePropSet );
|
|
XMLTextCharStyleNamesElementExport aCharStylesExport(
|
|
GetExport(), bDoSomething, bHasAutoStyle,
|
|
bDoSomething ? *pRangePropSet : Reference<XPropertySet>(),
|
|
gsCharStyleNames );
|
|
|
|
if( !sStyle.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sStyle ) );
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), !sStyle.isEmpty(),
|
|
XML_NAMESPACE_TEXT, XML_SPAN, false, false );
|
|
{
|
|
SvXMLElementExport aElement( GetExport(),
|
|
FrameType::Shape != eType &&
|
|
addHyperlinkAttributes( xPropSet,
|
|
xPropState,xPropSetInfo ),
|
|
XML_NAMESPACE_DRAW, XML_A, false, false );
|
|
switch( eType )
|
|
{
|
|
case FrameType::Text:
|
|
_exportTextFrame( xPropSet, xPropSetInfo, bIsProgress );
|
|
break;
|
|
case FrameType::Graphic:
|
|
_exportTextGraphic( xPropSet, xPropSetInfo );
|
|
break;
|
|
case FrameType::Embedded:
|
|
_exportTextEmbedded( xPropSet, xPropSetInfo );
|
|
break;
|
|
case FrameType::Shape:
|
|
{
|
|
Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
|
|
XMLShapeExportFlags nFeatures =
|
|
addTextFrameAttributes( xPropSet, true );
|
|
GetExport().GetShapeExport()
|
|
->exportShape( xShape, nFeatures );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::_exportTextFrame(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
const Reference < XPropertySetInfo > & rPropSetInfo,
|
|
bool bIsProgress )
|
|
{
|
|
Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
|
|
Reference < XText > xTxt(xTxtFrame->getText());
|
|
|
|
OUString sStyle;
|
|
if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
|
|
}
|
|
|
|
OUString aMinHeightValue;
|
|
OUString sMinWidthValue;
|
|
OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
|
|
if ( sAutoStyle.isEmpty() )
|
|
sAutoStyle = sStyle;
|
|
if( !sAutoStyle.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sAutoStyle ) );
|
|
addTextFrameAttributes(rPropSet, false, nullptr, &aMinHeightValue, &sMinWidthValue);
|
|
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
|
|
XML_FRAME, false, true );
|
|
|
|
if( !aMinHeightValue.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
|
|
aMinHeightValue );
|
|
|
|
if (!sMinWidthValue.isEmpty())
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
|
|
sMinWidthValue );
|
|
}
|
|
|
|
// draw:chain-next-name
|
|
if( rPropSetInfo->hasPropertyByName( gsChainNextName ) )
|
|
{
|
|
OUString sNext;
|
|
if( (rPropSet->getPropertyValue( gsChainNextName ) >>= sNext) && !sNext.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW,
|
|
XML_CHAIN_NEXT_NAME,
|
|
sNext );
|
|
}
|
|
|
|
{
|
|
SvXMLElementExport aElement( GetExport(), XML_NAMESPACE_DRAW,
|
|
XML_TEXT_BOX, true, true );
|
|
|
|
// frames bound to frame
|
|
exportFrameFrames( false, bIsProgress, &xTxtFrame );
|
|
|
|
exportText( xTxt, false, bIsProgress, true );
|
|
}
|
|
|
|
// script:events
|
|
Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
|
|
GetExport().GetEventExport().Export(xEventsSupp);
|
|
|
|
// image map
|
|
GetExport().GetImageMapExport().Export( rPropSet );
|
|
|
|
// svg:title and svg:desc (#i73249#)
|
|
exportTitleAndDescription( rPropSet, rPropSetInfo );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportContour(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
const Reference < XPropertySetInfo > & rPropSetInfo )
|
|
{
|
|
if( !rPropSetInfo->hasPropertyByName( gsContourPolyPolygon ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
PointSequenceSequence aSourcePolyPolygon;
|
|
rPropSet->getPropertyValue( gsContourPolyPolygon ) >>= aSourcePolyPolygon;
|
|
const basegfx::B2DPolyPolygon aPolyPolygon(
|
|
basegfx::utils::UnoPointSequenceSequenceToB2DPolyPolygon(
|
|
aSourcePolyPolygon));
|
|
const sal_uInt32 nPolygonCount(aPolyPolygon.count());
|
|
|
|
if(!nPolygonCount)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const basegfx::B2DRange aPolyPolygonRange(aPolyPolygon.getB2DRange());
|
|
bool bPixel(false);
|
|
|
|
if( rPropSetInfo->hasPropertyByName( gsIsPixelContour ) )
|
|
{
|
|
bPixel = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsPixelContour ));
|
|
}
|
|
|
|
// svg: width
|
|
OUStringBuffer aStringBuffer( 10 );
|
|
|
|
if(bPixel)
|
|
{
|
|
::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
|
|
}
|
|
else
|
|
{
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getWidth()));
|
|
}
|
|
|
|
GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_WIDTH, aStringBuffer.makeStringAndClear());
|
|
|
|
// svg: height
|
|
if(bPixel)
|
|
{
|
|
::sax::Converter::convertMeasurePx(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
|
|
}
|
|
else
|
|
{
|
|
GetExport().GetMM100UnitConverter().convertMeasureToXML(aStringBuffer, basegfx::fround(aPolyPolygonRange.getHeight()));
|
|
}
|
|
|
|
GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_HEIGHT, aStringBuffer.makeStringAndClear());
|
|
|
|
// svg:viewbox
|
|
SdXMLImExViewBox aViewBox(0.0, 0.0, aPolyPolygonRange.getWidth(), aPolyPolygonRange.getHeight());
|
|
GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX, aViewBox.GetExportString());
|
|
enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
|
|
|
|
if(1 == nPolygonCount )
|
|
{
|
|
// simple polygon shape, can be written as svg:points sequence
|
|
const OUString aPointString(
|
|
basegfx::utils::exportToSvgPoints(
|
|
aPolyPolygon.getB2DPolygon(0)));
|
|
|
|
// write point array
|
|
GetExport().AddAttribute(XML_NAMESPACE_DRAW, XML_POINTS, aPointString);
|
|
eElem = XML_CONTOUR_POLYGON;
|
|
}
|
|
else
|
|
{
|
|
// polypolygon, needs to be written as a svg:path sequence
|
|
const OUString aPolygonString(
|
|
basegfx::utils::exportToSvgD(
|
|
aPolyPolygon,
|
|
true, // bUseRelativeCoordinates
|
|
false, // bDetectQuadraticBeziers: not used in old, but maybe activated now
|
|
true)); // bHandleRelativeNextPointCompatible
|
|
|
|
// write point array
|
|
GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D, aPolygonString);
|
|
eElem = XML_CONTOUR_PATH;
|
|
}
|
|
|
|
if( rPropSetInfo->hasPropertyByName( gsIsAutomaticContour ) )
|
|
{
|
|
bool bTmp = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(
|
|
gsIsAutomaticContour ));
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW,
|
|
XML_RECREATE_ON_EDIT, bTmp ? XML_TRUE : XML_FALSE );
|
|
}
|
|
|
|
// write object now
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
|
|
true, true );
|
|
}
|
|
|
|
void XMLTextParagraphExport::_exportTextGraphic(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
const Reference < XPropertySetInfo > & rPropSetInfo )
|
|
{
|
|
OUString sStyle;
|
|
if( rPropSetInfo->hasPropertyByName( gsFrameStyleName ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsFrameStyleName ) >>= sStyle;
|
|
}
|
|
|
|
OUString sAutoStyle = Find( XmlStyleFamily::TEXT_FRAME, rPropSet, sStyle );
|
|
if ( sAutoStyle.isEmpty() )
|
|
sAutoStyle = sStyle;
|
|
if( !sAutoStyle.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sAutoStyle ) );
|
|
|
|
// check if we need to use svg:transform
|
|
sal_Int16 nRotation(0);
|
|
rPropSet->getPropertyValue( gsGraphicRotation ) >>= nRotation;
|
|
const bool bUseRotation(0 != nRotation);
|
|
basegfx::B2DPoint aCenter(0.0, 0.0);
|
|
|
|
// add TextFrame attributes like svg:x/y/width/height, also get back
|
|
// object's center point if rotation is used and has to be exported
|
|
addTextFrameAttributes(rPropSet, false, bUseRotation ? &aCenter : nullptr);
|
|
|
|
// svg:transform
|
|
if(bUseRotation)
|
|
{
|
|
// RotateFlyFrameFix: im/export full 'draw:transform' using existing tooling.
|
|
// Currently only rotation is used, but combinations with 'draw:transform'
|
|
// may be necessary in the future, so that svg:x/svg:y/svg:width/svg:height
|
|
// may be extended/replaced with 'draw:transform' (see draw objects)
|
|
SdXMLImExTransform2D aSdXMLImExTransform2D;
|
|
|
|
// Convert from 10th degree integer to deg.
|
|
// CAUTION: internal rotation is classically mathematically 'wrong' defined by ignoring that
|
|
// we have a right-handed coordinate system, so need to correct this by mirroring
|
|
// the rotation to get the correct transformation. See also case XML_TOK_TEXT_FRAME_TRANSFORM
|
|
// in XMLTextFrameContext_Impl::XMLTextFrameContext_Impl and #i78696#
|
|
// CAUTION-II: due to tdf#115782 it is better for current ODF to indeed write it with the wrong
|
|
// orientation as in all other cases - ARGH! We will need to correct this in future ODF ASAP!
|
|
const double fRotate(static_cast< double >(nRotation) * (F_PI/1800.0));
|
|
|
|
// transform to rotation center which is the object's center
|
|
aSdXMLImExTransform2D.AddTranslate(-aCenter);
|
|
|
|
// add rotation itself
|
|
// tdf#115529 but correct value modulo 2PI to have it positive and in the range of [0.0 .. 2PI[
|
|
aSdXMLImExTransform2D.AddRotate(basegfx::normalizeToRange(fRotate, F_2PI));
|
|
|
|
// back-transform after rotation
|
|
aSdXMLImExTransform2D.AddTranslate(aCenter);
|
|
|
|
// Note: using GetTwipUnitConverter instead of GetMM100UnitConverter may be needed,
|
|
// but is not generally available (as it should be, a 'current' UnitConverter should
|
|
// be available at GetExport() - and maybe was once). May have to be addressed as soon
|
|
// as translate transformations are used here.
|
|
GetExport().AddAttribute(
|
|
XML_NAMESPACE_DRAW,
|
|
XML_TRANSFORM,
|
|
aSdXMLImExTransform2D.GetExportString(GetExport().GetMM100UnitConverter()));
|
|
}
|
|
|
|
// original content
|
|
SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_DRAW, XML_FRAME, false, true);
|
|
|
|
{
|
|
// xlink:href
|
|
uno::Reference<graphic::XGraphic> xGraphic;
|
|
rPropSet->getPropertyValue("Graphic") >>= xGraphic;
|
|
|
|
OUString sInternalURL;
|
|
OUString sOutMimeType;
|
|
|
|
if (xGraphic.is())
|
|
{
|
|
sInternalURL = GetExport().AddEmbeddedXGraphic(xGraphic, sOutMimeType);
|
|
}
|
|
|
|
// If there still is no url, then graphic is empty
|
|
if (!sInternalURL.isEmpty())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
|
|
}
|
|
|
|
// draw:filter-name
|
|
OUString sGrfFilter;
|
|
rPropSet->getPropertyValue( gsGraphicFilter ) >>= sGrfFilter;
|
|
if( !sGrfFilter.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
|
|
sGrfFilter );
|
|
|
|
if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
|
|
{
|
|
if (sOutMimeType.isEmpty())
|
|
{
|
|
GetExport().GetGraphicMimeTypeFromStream(xGraphic, sOutMimeType);
|
|
}
|
|
if (!sOutMimeType.isEmpty())
|
|
{ // ODF 1.3 OFFICE-3943
|
|
GetExport().AddAttribute(
|
|
SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
|
|
? XML_NAMESPACE_DRAW
|
|
: XML_NAMESPACE_LO_EXT,
|
|
"mime-type", sOutMimeType);
|
|
}
|
|
}
|
|
|
|
|
|
// optional office:binary-data
|
|
if (xGraphic.is())
|
|
{
|
|
SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, false, true );
|
|
GetExport().AddEmbeddedXGraphicAsBase64(xGraphic);
|
|
}
|
|
}
|
|
|
|
const bool bAddReplacementImages = officecfg::Office::Common::Save::Graphic::AddReplacementImages::get();
|
|
if (bAddReplacementImages)
|
|
{
|
|
// replacement graphic for backwards compatibility, but
|
|
// only for SVG and metafiles currently
|
|
uno::Reference<graphic::XGraphic> xReplacementGraphic;
|
|
rPropSet->getPropertyValue("ReplacementGraphic") >>= xReplacementGraphic;
|
|
|
|
OUString sInternalURL;
|
|
OUString sOutMimeType;
|
|
|
|
//Resolves: fdo#62461 put preferred image first above, followed by
|
|
//fallback here
|
|
if (xReplacementGraphic.is())
|
|
{
|
|
sInternalURL = GetExport().AddEmbeddedXGraphic(xReplacementGraphic, sOutMimeType);
|
|
}
|
|
|
|
// If there is no url, then graphic is empty
|
|
if (!sInternalURL.isEmpty())
|
|
{
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sInternalURL);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED);
|
|
GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD);
|
|
}
|
|
|
|
if (GetExport().getSaneDefaultVersion() > SvtSaveOptions::ODFSVER_012)
|
|
{
|
|
if (sOutMimeType.isEmpty())
|
|
{
|
|
GetExport().GetGraphicMimeTypeFromStream(xReplacementGraphic, sOutMimeType);
|
|
}
|
|
if (!sOutMimeType.isEmpty())
|
|
{ // ODF 1.3 OFFICE-3943
|
|
GetExport().AddAttribute(
|
|
SvtSaveOptions::ODFSVER_013 <= GetExport().getSaneDefaultVersion()
|
|
? XML_NAMESPACE_DRAW
|
|
: XML_NAMESPACE_LO_EXT,
|
|
"mime-type", sOutMimeType);
|
|
}
|
|
}
|
|
|
|
|
|
// optional office:binary-data
|
|
if (xReplacementGraphic.is())
|
|
{
|
|
SvXMLElementExport aElement(GetExport(), XML_NAMESPACE_DRAW, XML_IMAGE, true, true);
|
|
GetExport().AddEmbeddedXGraphicAsBase64(xReplacementGraphic);
|
|
}
|
|
}
|
|
|
|
// script:events
|
|
Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
|
|
GetExport().GetEventExport().Export(xEventsSupp);
|
|
|
|
// image map
|
|
GetExport().GetImageMapExport().Export( rPropSet );
|
|
|
|
// svg:title and svg:desc (#i73249#)
|
|
exportTitleAndDescription( rPropSet, rPropSetInfo );
|
|
|
|
// draw:contour
|
|
exportContour( rPropSet, rPropSetInfo );
|
|
}
|
|
|
|
void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(const Reference < XPropertySet > & )
|
|
{
|
|
SAL_WARN( "xmloff", "no API implementation available" );
|
|
}
|
|
|
|
void XMLTextParagraphExport::_exportTextEmbedded(
|
|
const Reference < XPropertySet > &,
|
|
const Reference < XPropertySetInfo > & )
|
|
{
|
|
SAL_WARN( "xmloff", "no API implementation available" );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
|
|
{
|
|
// script:events
|
|
Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
|
|
GetExport().GetEventExport().Export(xEventsSupp);
|
|
|
|
// image map
|
|
if (rPropSet->getPropertySetInfo()->hasPropertyByName("ImageMap"))
|
|
GetExport().GetImageMapExport().Export( rPropSet );
|
|
}
|
|
|
|
// Implement Title/Description Elements UI (#i73249#)
|
|
void XMLTextParagraphExport::exportTitleAndDescription(
|
|
const Reference < XPropertySet > & rPropSet,
|
|
const Reference < XPropertySetInfo > & rPropSetInfo )
|
|
{
|
|
// svg:title
|
|
if( rPropSetInfo->hasPropertyByName( gsTitle ) )
|
|
{
|
|
OUString sObjTitle;
|
|
rPropSet->getPropertyValue( gsTitle ) >>= sObjTitle;
|
|
if( !sObjTitle.isEmpty() )
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
|
|
XML_TITLE, true, false );
|
|
GetExport().Characters( sObjTitle );
|
|
}
|
|
}
|
|
|
|
// svg:description
|
|
if( rPropSetInfo->hasPropertyByName( gsDescription ) )
|
|
{
|
|
OUString sObjDesc;
|
|
rPropSet->getPropertyValue( gsDescription ) >>= sObjDesc;
|
|
if( !sObjDesc.isEmpty() )
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
|
|
XML_DESC, true, false );
|
|
GetExport().Characters( sObjDesc );
|
|
}
|
|
}
|
|
}
|
|
|
|
bool XMLTextParagraphExport::addHyperlinkAttributes(
|
|
const Reference< XPropertySet > & rPropSet,
|
|
const Reference< XPropertyState > & rPropState,
|
|
const Reference< XPropertySetInfo > & rPropSetInfo )
|
|
{
|
|
bool bExport = false;
|
|
OUString sHRef, sName, sTargetFrame, sUStyleName, sVStyleName;
|
|
bool bServerMap = false;
|
|
|
|
if( rPropSetInfo->hasPropertyByName( gsHyperLinkURL ) &&
|
|
( !rPropState.is() || PropertyState_DIRECT_VALUE ==
|
|
rPropState->getPropertyState( gsHyperLinkURL ) ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsHyperLinkURL ) >>= sHRef;
|
|
|
|
if( !sHRef.isEmpty() )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( sHRef.isEmpty() )
|
|
{
|
|
// hyperlink without a URL does not make sense
|
|
OSL_ENSURE( false, "hyperlink without a URL --> no export to ODF" );
|
|
return false;
|
|
}
|
|
|
|
if ( rPropSetInfo->hasPropertyByName( gsHyperLinkName )
|
|
&& ( !rPropState.is()
|
|
|| PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkName ) ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsHyperLinkName ) >>= sName;
|
|
if( !sName.isEmpty() )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( rPropSetInfo->hasPropertyByName( gsHyperLinkTarget )
|
|
&& ( !rPropState.is()
|
|
|| PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsHyperLinkTarget ) ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsHyperLinkTarget ) >>= sTargetFrame;
|
|
if( !sTargetFrame.isEmpty() )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( rPropSetInfo->hasPropertyByName( gsServerMap )
|
|
&& ( !rPropState.is()
|
|
|| PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsServerMap ) ) )
|
|
{
|
|
bServerMap = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsServerMap ));
|
|
if ( bServerMap )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( rPropSetInfo->hasPropertyByName( gsUnvisitedCharStyleName )
|
|
&& ( !rPropState.is()
|
|
|| PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsUnvisitedCharStyleName ) ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsUnvisitedCharStyleName ) >>= sUStyleName;
|
|
if( !sUStyleName.isEmpty() )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( rPropSetInfo->hasPropertyByName( gsVisitedCharStyleName )
|
|
&& ( !rPropState.is()
|
|
|| PropertyState_DIRECT_VALUE == rPropState->getPropertyState( gsVisitedCharStyleName ) ) )
|
|
{
|
|
rPropSet->getPropertyValue( gsVisitedCharStyleName ) >>= sVStyleName;
|
|
if( !sVStyleName.isEmpty() )
|
|
bExport = true;
|
|
}
|
|
|
|
if ( bExport )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
|
|
GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( sHRef ) );
|
|
|
|
if( !sName.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, sName );
|
|
|
|
if( !sTargetFrame.isEmpty() )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
|
|
XML_TARGET_FRAME_NAME, sTargetFrame );
|
|
enum XMLTokenEnum eTok = sTargetFrame == "_blank" ? XML_NEW : XML_REPLACE;
|
|
GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eTok );
|
|
}
|
|
|
|
if( bServerMap )
|
|
GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
|
|
XML_SERVER_MAP, XML_TRUE );
|
|
|
|
if( !sUStyleName.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_STYLE_NAME, GetExport().EncodeStyleName( sUStyleName ) );
|
|
|
|
if( !sVStyleName.isEmpty() )
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT,
|
|
XML_VISITED_STYLE_NAME, GetExport().EncodeStyleName( sVStyleName ) );
|
|
}
|
|
|
|
return bExport;
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextRangeSpan(
|
|
const css::uno::Reference< css::text::XTextRange > & rTextRange,
|
|
Reference< XPropertySet > const & xPropSet,
|
|
Reference < XPropertySetInfo > & xPropSetInfo,
|
|
const bool bIsUICharStyle,
|
|
const bool bHasAutoStyle,
|
|
const OUString& sStyle,
|
|
bool& rPrevCharIsSpace,
|
|
FieldmarkType& openFieldMark )
|
|
{
|
|
XMLTextCharStyleNamesElementExport aCharStylesExport(
|
|
GetExport(),
|
|
bIsUICharStyle && aCharStyleNamesPropInfoCache.hasProperty( xPropSet, xPropSetInfo ),
|
|
bHasAutoStyle,
|
|
xPropSet,
|
|
gsCharStyleNames );
|
|
|
|
if ( !sStyle.isEmpty() )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) );
|
|
}
|
|
{
|
|
SvXMLElementExport aElement( GetExport(), !sStyle.isEmpty(), XML_NAMESPACE_TEXT, XML_SPAN, false, false );
|
|
const OUString aText( rTextRange->getString() );
|
|
SvXMLElementExport aElem2( GetExport(), TEXT == openFieldMark,
|
|
XML_NAMESPACE_TEXT, XML_TEXT_INPUT,
|
|
false, false );
|
|
exportCharacterData(aText, rPrevCharIsSpace);
|
|
openFieldMark = NONE;
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextRange(
|
|
const Reference< XTextRange > & rTextRange,
|
|
bool bAutoStyles,
|
|
bool& rPrevCharIsSpace,
|
|
FieldmarkType& openFieldMark )
|
|
{
|
|
Reference< XPropertySet > xPropSet( rTextRange, UNO_QUERY );
|
|
if ( bAutoStyles )
|
|
{
|
|
Add( XmlStyleFamily::TEXT_TEXT, xPropSet );
|
|
}
|
|
else
|
|
{
|
|
bool bHyperlink = false;
|
|
bool bIsUICharStyle = false;
|
|
bool bHasAutoStyle = false;
|
|
const OUString sStyle(
|
|
FindTextStyleAndHyperlink( xPropSet, bHyperlink, bIsUICharStyle, bHasAutoStyle ) );
|
|
|
|
Reference < XPropertySetInfo > xPropSetInfo;
|
|
bool bHyperlinkAttrsAdded = false;
|
|
if ( bHyperlink )
|
|
{
|
|
Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
|
|
xPropSetInfo.set( xPropSet->getPropertySetInfo() );
|
|
bHyperlinkAttrsAdded = addHyperlinkAttributes( xPropSet, xPropState, xPropSetInfo );
|
|
}
|
|
|
|
if ( bHyperlink && bHyperlinkAttrsAdded )
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), true, XML_NAMESPACE_TEXT, XML_A, false, false );
|
|
|
|
// export events (if supported)
|
|
OUString sHyperLinkEvents(
|
|
"HyperLinkEvents");
|
|
if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
|
|
{
|
|
Reference< XNameReplace > xName( xPropSet->getPropertyValue( sHyperLinkEvents ), uno::UNO_QUERY );
|
|
GetExport().GetEventExport().Export( xName, false );
|
|
}
|
|
|
|
exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
|
|
}
|
|
else
|
|
{
|
|
exportTextRangeSpan( rTextRange, xPropSet, xPropSetInfo, bIsUICharStyle, bHasAutoStyle, sStyle, rPrevCharIsSpace, openFieldMark );
|
|
}
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportCharacterData(const OUString& rText,
|
|
bool& rPrevCharIsSpace )
|
|
{
|
|
sal_Int32 nExpStartPos = 0;
|
|
sal_Int32 nEndPos = rText.getLength();
|
|
sal_Int32 nSpaceChars = 0;
|
|
for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
|
|
{
|
|
sal_Unicode cChar = rText[nPos];
|
|
bool bExpCharAsText = true;
|
|
bool bExpCharAsElement = false;
|
|
bool bCurrCharIsSpace = false;
|
|
switch( cChar )
|
|
{
|
|
case 0x0009: // Tab
|
|
case 0x000A: // LF
|
|
// These characters are exported as text.
|
|
bExpCharAsElement = true;
|
|
bExpCharAsText = false;
|
|
break;
|
|
case 0x000D:
|
|
break; // legal character
|
|
case 0x0020: // Blank
|
|
if( rPrevCharIsSpace )
|
|
{
|
|
// If the previous character is a space character,
|
|
// too, export a special space element.
|
|
bExpCharAsText = false;
|
|
}
|
|
bCurrCharIsSpace = true;
|
|
break;
|
|
default:
|
|
if( cChar < 0x0020 )
|
|
{
|
|
#ifdef DBG_UTIL
|
|
OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
|
|
cChar >= 0x0020,
|
|
"illegal character in text content" );
|
|
txtparae_bContainsIllegalCharacters = true;
|
|
#endif
|
|
bExpCharAsText = false;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// If the current character is not exported as text
|
|
// the text that has not been exported by now has to be exported now.
|
|
if( nPos > nExpStartPos && !bExpCharAsText )
|
|
{
|
|
SAL_WARN_IF( 0 != nSpaceChars, "xmloff", "pending spaces" );
|
|
OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
|
|
GetExport().Characters( sExp );
|
|
nExpStartPos = nPos;
|
|
}
|
|
|
|
// If there are spaces left that have not been exported and the
|
|
// current character is not a space , the pending spaces have to be
|
|
// exported now.
|
|
if( nSpaceChars > 0 && !bCurrCharIsSpace )
|
|
{
|
|
SAL_WARN_IF( nExpStartPos != nPos, "xmloff", " pending characters" );
|
|
|
|
if( nSpaceChars > 1 )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
|
|
OUString::number(nSpaceChars) );
|
|
}
|
|
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
|
|
XML_S, false, false );
|
|
|
|
nSpaceChars = 0;
|
|
}
|
|
|
|
// If the current character has to be exported as a special
|
|
// element, the element will be exported now.
|
|
if( bExpCharAsElement )
|
|
{
|
|
switch( cChar )
|
|
{
|
|
case 0x0009: // Tab
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
|
|
XML_TAB, false,
|
|
false );
|
|
}
|
|
break;
|
|
case 0x000A: // LF
|
|
{
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
|
|
XML_LINE_BREAK, false,
|
|
false );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If the current character is a space, and the previous one
|
|
// is a space, too, the number of pending spaces is incremented
|
|
// only.
|
|
if( bCurrCharIsSpace && rPrevCharIsSpace )
|
|
nSpaceChars++;
|
|
rPrevCharIsSpace = bCurrCharIsSpace;
|
|
|
|
// If the current character is not exported as text, the start
|
|
// position for text is the position behind the current position.
|
|
if( !bExpCharAsText )
|
|
{
|
|
SAL_WARN_IF( nExpStartPos != nPos, "xmloff", "wrong export start pos" );
|
|
nExpStartPos = nPos+1;
|
|
}
|
|
}
|
|
|
|
if( nExpStartPos < nEndPos )
|
|
{
|
|
SAL_WARN_IF( 0 != nSpaceChars, "xmloff", " pending spaces " );
|
|
OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
|
|
GetExport().Characters( sExp );
|
|
}
|
|
|
|
// If there are some spaces left, they have to be exported now.
|
|
if( nSpaceChars > 0 )
|
|
{
|
|
if( nSpaceChars > 1 )
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
|
|
OUString::number(nSpaceChars) );
|
|
}
|
|
|
|
SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
|
|
false, false );
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextDeclarations()
|
|
{
|
|
pFieldExport->ExportFieldDeclarations();
|
|
|
|
// get XPropertySet from the document and ask for AutoMarkFileURL.
|
|
// If it exists, export the auto-mark-file element.
|
|
Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
|
|
if (!xPropertySet.is())
|
|
return;
|
|
|
|
OUString sUrl;
|
|
OUString sIndexAutoMarkFileURL(
|
|
"IndexAutoMarkFileURL");
|
|
if (!xPropertySet->getPropertySetInfo()->hasPropertyByName(
|
|
sIndexAutoMarkFileURL))
|
|
return;
|
|
|
|
xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
|
|
if (!sUrl.isEmpty())
|
|
{
|
|
GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
|
|
GetExport().GetRelativeReference(sUrl) );
|
|
SvXMLElementExport aAutoMarkElement(
|
|
GetExport(), XML_NAMESPACE_TEXT,
|
|
XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
|
|
true, true );
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTextDeclarations(
|
|
const Reference<XText> & rText )
|
|
{
|
|
pFieldExport->ExportFieldDeclarations(rText);
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportUsedDeclarations()
|
|
{
|
|
pFieldExport->SetExportOnlyUsedFieldDeclarations( false/*bOnlyUsed*/ );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTrackedChanges(bool bAutoStyles)
|
|
{
|
|
if (nullptr != pRedlineExport)
|
|
pRedlineExport->ExportChangesList( bAutoStyles );
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTrackedChanges(
|
|
const Reference<XText> & rText,
|
|
bool bAutoStyle)
|
|
{
|
|
if (nullptr != pRedlineExport)
|
|
pRedlineExport->ExportChangesList(rText, bAutoStyle);
|
|
}
|
|
|
|
void XMLTextParagraphExport::recordTrackedChangesForXText(
|
|
const Reference<XText> & rText )
|
|
{
|
|
if (nullptr != pRedlineExport)
|
|
pRedlineExport->SetCurrentXText(rText);
|
|
}
|
|
|
|
void XMLTextParagraphExport::recordTrackedChangesNoXText()
|
|
{
|
|
if (nullptr != pRedlineExport)
|
|
pRedlineExport->SetCurrentXText();
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportTableAutoStyles() {}
|
|
|
|
void XMLTextParagraphExport::exportTextAutoStyles()
|
|
{
|
|
// tdf#135942: do not collect styles during their export: this may modify iterated containers
|
|
mbCollected = true;
|
|
exportTableAutoStyles();
|
|
|
|
GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_PARAGRAPH );
|
|
|
|
GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_TEXT );
|
|
|
|
GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_FRAME );
|
|
|
|
GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_SECTION );
|
|
|
|
GetAutoStylePool().exportXML( XmlStyleFamily::TEXT_RUBY );
|
|
|
|
maListAutoPool.exportXML();
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportRuby(
|
|
const Reference<XPropertySet> & rPropSet,
|
|
bool bAutoStyles )
|
|
{
|
|
// early out: a collapsed ruby makes no sense
|
|
if (*o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsCollapsed)))
|
|
return;
|
|
|
|
// start value ?
|
|
bool bStart = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsStart));
|
|
|
|
if (bAutoStyles)
|
|
{
|
|
// ruby auto styles
|
|
if (bStart)
|
|
Add( XmlStyleFamily::TEXT_RUBY, rPropSet );
|
|
}
|
|
else
|
|
{
|
|
if (bStart)
|
|
{
|
|
// ruby start
|
|
|
|
// we can only start a ruby if none is open
|
|
assert(!bOpenRuby && "Can't open a ruby inside of ruby!");
|
|
if( bOpenRuby )
|
|
return;
|
|
|
|
// save ruby text + ruby char style
|
|
rPropSet->getPropertyValue(gsRubyText) >>= sOpenRubyText;
|
|
rPropSet->getPropertyValue(gsRubyCharStyleName) >>= sOpenRubyCharStyle;
|
|
|
|
// ruby style
|
|
GetExport().CheckAttrList();
|
|
OUString sStyleName(Find(XmlStyleFamily::TEXT_RUBY, rPropSet, ""));
|
|
SAL_WARN_IF(sStyleName.isEmpty(), "xmloff", "Can't find ruby style!");
|
|
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
|
|
XML_STYLE_NAME, sStyleName);
|
|
|
|
// export <text:ruby> and <text:ruby-base> start elements
|
|
GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, false);
|
|
GetExport().ClearAttrList();
|
|
GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
|
|
false );
|
|
bOpenRuby = true;
|
|
}
|
|
else
|
|
{
|
|
// ruby end
|
|
|
|
// check for an open ruby
|
|
assert(bOpenRuby && "Can't close a ruby if none is open!");
|
|
if( !bOpenRuby )
|
|
return;
|
|
|
|
// close <text:ruby-base>
|
|
GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
|
|
false);
|
|
|
|
// write the ruby text (with char style)
|
|
{
|
|
if (!sOpenRubyCharStyle.isEmpty())
|
|
GetExport().AddAttribute(
|
|
XML_NAMESPACE_TEXT, XML_STYLE_NAME,
|
|
GetExport().EncodeStyleName( sOpenRubyCharStyle) );
|
|
|
|
SvXMLElementExport aRubyElement(
|
|
GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
|
|
false, false);
|
|
|
|
GetExport().Characters(sOpenRubyText);
|
|
}
|
|
|
|
// and finally, close the ruby
|
|
GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, false);
|
|
bOpenRuby = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::exportMeta(
|
|
const Reference<XPropertySet> & i_xPortion,
|
|
bool i_bAutoStyles, bool i_isProgress, bool & rPrevCharIsSpace)
|
|
{
|
|
bool doExport(!i_bAutoStyles); // do not export element if autostyles
|
|
// check version >= 1.2
|
|
switch (GetExport().getSaneDefaultVersion()) {
|
|
case SvtSaveOptions::ODFSVER_011: // fall through
|
|
case SvtSaveOptions::ODFSVER_010: doExport = false; break;
|
|
default: break;
|
|
}
|
|
|
|
const Reference< XTextContent > xTextContent(
|
|
i_xPortion->getPropertyValue("InContentMetadata"), UNO_QUERY_THROW);
|
|
const Reference< XEnumerationAccess > xEA( xTextContent, UNO_QUERY_THROW );
|
|
const Reference< XEnumeration > xTextEnum( xEA->createEnumeration() );
|
|
|
|
if (doExport)
|
|
{
|
|
const Reference<rdf::XMetadatable> xMeta(xTextContent, UNO_QUERY_THROW);
|
|
|
|
// text:meta with neither xml:id nor RDFa is invalid
|
|
xMeta->ensureMetadataReference();
|
|
|
|
// xml:id and RDFa for RDF metadata
|
|
GetExport().AddAttributeXmlId(xMeta);
|
|
GetExport().AddAttributesRDFa(xTextContent);
|
|
}
|
|
|
|
SvXMLElementExport aElem( GetExport(), doExport,
|
|
XML_NAMESPACE_TEXT, XML_META, false, false );
|
|
|
|
// recurse to export content
|
|
exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_isProgress, rPrevCharIsSpace);
|
|
}
|
|
|
|
void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
|
|
const Reference<XIndexAccess> & rShapes,
|
|
const rtl::Reference<xmloff::OFormLayerXMLExport>& xFormExport )
|
|
{
|
|
// check parameters ad pre-conditions
|
|
if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
|
|
{
|
|
// if we don't have shapes or a form export, there's nothing to do
|
|
return;
|
|
}
|
|
SAL_WARN_IF( pSectionExport == nullptr, "xmloff", "We need the section export." );
|
|
|
|
Reference<XEnumeration> xShapesEnum = pBoundFrameSets->GetShapes()->createEnumeration();
|
|
if(!xShapesEnum.is())
|
|
return;
|
|
while( xShapesEnum->hasMoreElements() )
|
|
{
|
|
// now we need to check
|
|
// 1) if this is a control shape, and
|
|
// 2) if it's in a mute section
|
|
// if both answers are 'yes', notify the form layer export
|
|
|
|
// we join accessing the shape and testing for control
|
|
Reference<XControlShape> xControlShape(xShapesEnum->nextElement(), UNO_QUERY);
|
|
if( xControlShape.is() )
|
|
{
|
|
// Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
|
|
// Reference<XTextContent> xTextContent;
|
|
// xPropSet->getPropertyValue("TextRange") >>= xTextContent;
|
|
|
|
Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
|
|
if( xTextContent.is() )
|
|
{
|
|
if( pSectionExport->IsMuteSection( xTextContent, false ) )
|
|
{
|
|
// Ah, we've found a shape that
|
|
// 1) is a control shape
|
|
// 2) is anchored in a mute section
|
|
// so: don't export it!
|
|
xFormExport->excludeFromExport(
|
|
xControlShape->getControl() );
|
|
}
|
|
// else: not in mute section -> should be exported -> nothing
|
|
// to do
|
|
}
|
|
// else: no anchor -> ignore
|
|
}
|
|
// else: no control shape -> nothing to do
|
|
}
|
|
}
|
|
|
|
void XMLTextParagraphExport::PushNewTextListsHelper()
|
|
{
|
|
maTextListsHelperStack.emplace_back( new XMLTextListsHelper() );
|
|
mpTextListsHelper = maTextListsHelperStack.back().get();
|
|
}
|
|
|
|
void XMLTextParagraphExport::PopTextListsHelper()
|
|
{
|
|
mpTextListsHelper = nullptr;
|
|
maTextListsHelperStack.pop_back();
|
|
if ( !maTextListsHelperStack.empty() )
|
|
{
|
|
mpTextListsHelper = maTextListsHelperStack.back().get();
|
|
}
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|