diff options
Diffstat (limited to 'writerfilter/source/dmapper/DomainMapper.cxx')
-rw-r--r-- | writerfilter/source/dmapper/DomainMapper.cxx | 4510 |
1 files changed, 4510 insertions, 0 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx new file mode 100644 index 000000000..e4b507957 --- /dev/null +++ b/writerfilter/source/dmapper/DomainMapper.cxx @@ -0,0 +1,4510 @@ +/* -*- 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 "BorderHandler.hxx" +#include "PageBordersHandler.hxx" + +#include "util.hxx" +#include "SdtHelper.hxx" +#include "TagLogger.hxx" +#include "TDefTableHandler.hxx" +#include "DomainMapper_Impl.hxx" +#include "ConversionHelper.hxx" +#include "ModelEventListener.hxx" +#include "MeasureHandler.hxx" +#include <i18nlangtag/languagetag.hxx> +#include <i18nutil/paper.hxx> +#include <ooxml/resourceids.hxx> +#include <oox/token/tokens.hxx> +#include <oox/drawingml/drawingmltypes.hxx> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/document/XOOXMLDocumentPropertiesImporter.hpp> +#include <com/sun/star/drawing/TextVerticalAdjust.hpp> +#include <com/sun/star/table/BorderLineStyle.hpp> +#include <com/sun/star/table/ShadowFormat.hpp> +#include <com/sun/star/text/HoriOrientation.hpp> +#include <com/sun/star/text/RelOrientation.hpp> +#include <com/sun/star/text/VertOrientation.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> +#include <com/sun/star/text/SizeType.hpp> +#include <com/sun/star/text/XEndnotesSupplier.hpp> +#include <com/sun/star/text/XFootnotesSupplier.hpp> +#include <com/sun/star/text/XLineNumberingProperties.hpp> +#include <com/sun/star/awt/FontRelief.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/document/XEventBroadcaster.hpp> +#include <com/sun/star/style/ParagraphAdjust.hpp> +#include <com/sun/star/style/BreakType.hpp> +#include <com/sun/star/style/CaseMap.hpp> +#include <com/sun/star/style/LineSpacing.hpp> +#include <com/sun/star/style/LineSpacingMode.hpp> +#include <com/sun/star/text/FootnoteNumbering.hpp> +#include <com/sun/star/text/TextGridMode.hpp> +#include <com/sun/star/text/XDocumentIndexesSupplier.hpp> +#include <com/sun/star/text/XTextFieldsSupplier.hpp> +#include <com/sun/star/text/WritingMode.hpp> +#include <com/sun/star/text/WritingMode2.hpp> +#include <com/sun/star/text/XFootnote.hpp> +#include <com/sun/star/text/XTextColumns.hpp> +#include <com/sun/star/text/RubyPosition.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/text/FontEmphasis.hpp> +#include <com/sun/star/awt/CharSet.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <comphelper/types.hxx> +#include <comphelper/storagehelper.hxx> +#include <comphelper/sequence.hxx> +#include <editeng/escapementitem.hxx> +#include <filter/msfilter/util.hxx> +#include <sfx2/DocumentMetadataAccess.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/mediadescriptor.hxx> + +#include "TextEffectsHandler.hxx" +#include "CellColorHandler.hxx" +#include "SectionColumnHandler.hxx" +#include "GraphicHelpers.hxx" +#include <dmapper/GraphicZOrderHelper.hxx> +#include <tools/diagnose_ex.h> +#include <sal/log.hxx> +#include <tools/UnitConversion.hxx> + +using namespace ::com::sun::star; +using namespace oox; + +namespace writerfilter::dmapper{ + +struct +{ + sal_Int32 h; + bool orient; + sal_Int32 w; +} CT_PageSz; + + +DomainMapper::DomainMapper( const uno::Reference< uno::XComponentContext >& xContext, + uno::Reference<io::XInputStream> const& xInputStream, + uno::Reference<lang::XComponent> const& xModel, + bool bRepairStorage, + SourceDocumentType eDocumentType, + utl::MediaDescriptor const & rMediaDesc) : + LoggedProperties("DomainMapper"), + LoggedTable("DomainMapper"), + LoggedStream("DomainMapper"), + m_pImpl(new DomainMapper_Impl(*this, xContext, xModel, eDocumentType, rMediaDesc)), + mbIsSplitPara(false), + mbHasControls(false), + mbWasShapeInPara(false) +{ + // #i24363# tab stops relative to indent + m_pImpl->SetDocumentSettingsProperty( + getPropertyName( PROP_TABS_RELATIVE_TO_INDENT ), + uno::Any( false ) ); + m_pImpl->SetDocumentSettingsProperty( + getPropertyName( PROP_SURROUND_TEXT_WRAP_SMALL ), + uno::Any( true ) ); + m_pImpl->SetDocumentSettingsProperty( + getPropertyName( PROP_APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ), + uno::Any( true ) ); + + // Don't load the default style definitions to avoid weird mix + m_pImpl->SetDocumentSettingsProperty("StylesNoDefault", uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("MsWordCompTrailingBlanks", uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("HeaderSpacingBelowLastPara", + uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("FrameAutowidthWithMorePara", uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("FootnoteInColumnToPageEnd", uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("TabAtLeftIndentForParagraphsInList", uno::Any(true)); + m_pImpl->SetDocumentSettingsProperty("NoNumberingShowFollowBy", uno::Any(true)); + + // Initialize RDF metadata, to be able to add statements during the import. + try + { + uno::Reference<rdf::XDocumentMetadataAccess> xDocumentMetadataAccess(xModel, uno::UNO_QUERY_THROW); + uno::Reference<embed::XStorage> xStorage = comphelper::OStorageHelper::GetTemporaryStorage(); + OUString aBaseURL = rMediaDesc.getUnpackedValueOrDefault("URL", OUString()); + const uno::Reference<frame::XModel> xModel_(xModel, + uno::UNO_QUERY_THROW); + const uno::Reference<rdf::XURI> xBaseURI(sfx2::createBaseURI(xContext, xModel_, aBaseURL, u"")); + const uno::Reference<task::XInteractionHandler> xHandler; + xDocumentMetadataAccess->loadMetadataFromStorage(xStorage, xBaseURI, xHandler); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("writerfilter", "failed to initialize RDF metadata"); + } + + if (eDocumentType == SourceDocumentType::OOXML) { + // tdf#108350 + // In Word since version 2007, the default document font is Calibri 11 pt. + // If a DOCX document doesn't contain font information, we should assume + // the intended font to provide best layout match. + try + { + uno::Reference< beans::XPropertySet > xDefProps(GetTextFactory()->createInstance("com.sun.star.text.Defaults"), + uno::UNO_QUERY_THROW); + xDefProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME), css::uno::Any(OUString("Calibri"))); + xDefProps->setPropertyValue(getPropertyName(PROP_CHAR_HEIGHT), css::uno::Any(double(11))); + } + catch (const uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("writerfilter", "failed to initialize default font"); + } + } + + //import document properties + try + { + m_pImpl->m_xDocumentStorage = comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( + OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xContext, bRepairStorage); + + uno::Reference< uno::XInterface > xTemp = xContext->getServiceManager()->createInstanceWithContext( + "com.sun.star.document.OOXMLDocumentPropertiesImporter", + xContext); + + uno::Reference< document::XOOXMLDocumentPropertiesImporter > xImporter( xTemp, uno::UNO_QUERY_THROW ); + uno::Reference< document::XDocumentPropertiesSupplier > xPropSupplier( xModel, uno::UNO_QUERY_THROW); + xImporter->importProperties(m_pImpl->m_xDocumentStorage, + xPropSupplier->getDocumentProperties()); + } + catch( const uno::Exception& ) {} +} + +void DomainMapper::setDocumentReference(writerfilter::ooxml::OOXMLDocument* pDocument) +{ + m_pImpl->setDocumentReference(pDocument); +} + +DomainMapper::~DomainMapper() +{ + try + { + // Remove temporary footnotes and endnotes + m_pImpl->RemoveTemporaryFootOrEndnotes(); + + uno::Reference< text::XDocumentIndexesSupplier> xIndexesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY ); + sal_Int32 nIndexes = 0; + if( xIndexesSupplier.is() ) + { + uno::Reference< container::XIndexAccess > xIndexes = xIndexesSupplier->getDocumentIndexes(); + nIndexes = xIndexes->getCount(); + } + // If we have page references, those need updating as well, similar to the indexes. + uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(m_pImpl->GetTextDocument(), uno::UNO_QUERY); + if(xTextFieldsSupplier.is()) + { + uno::Reference<container::XEnumeration> xEnumeration = xTextFieldsSupplier->getTextFields()->createEnumeration(); + while(xEnumeration->hasMoreElements()) + { + ++nIndexes; + xEnumeration->nextElement(); + } + } + + mbHasControls |= m_pImpl->m_pSdtHelper->hasElements(); + if ( nIndexes || mbHasControls ) + { + //index update has to wait until first view is created + uno::Reference< document::XEventBroadcaster > xBroadcaster(xIndexesSupplier, uno::UNO_QUERY); + if (xBroadcaster.is()) + xBroadcaster->addEventListener(uno::Reference< document::XEventListener >(new ModelEventListener(nIndexes, mbHasControls))); + } + + + // Apply the document settings for both DOCX and RTF after everything else + m_pImpl->GetSettingsTable()->ApplyProperties( m_pImpl->GetTextDocument( ) ); + + // now that importing is finished, re-enable default styles for any that were never defined/imported. + m_pImpl->SetDocumentSettingsProperty("StylesNoDefault", uno::Any(false)); + + // Grab-bag handling + comphelper::SequenceAsHashMap aProperties; + + // Add the saved w:themeFontLang setting + aProperties["ThemeFontLangProps"] <<= m_pImpl->GetSettingsTable()->GetThemeFontLangProperties(); + + // Add the saved compat settings + aProperties["CompatSettings"] <<= m_pImpl->GetSettingsTable()->GetCompatSettings(); + + // Add the saved DocumentProtection settings + aProperties["DocumentProtection"] <<= m_pImpl->GetSettingsTable()->GetDocumentProtectionSettings(); + + // Add the saved w:doNotHyphenateCaps setting + aProperties["NoHyphenateCaps"] <<= m_pImpl->GetSettingsTable()->GetNoHyphenateCaps(); + + uno::Reference<beans::XPropertySet> xDocProps(m_pImpl->GetTextDocument(), uno::UNO_QUERY); + if (xDocProps.is()) + { + comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue("InteropGrabBag")); + aGrabBag.update(aProperties); + xDocProps->setPropertyValue("InteropGrabBag", uno::Any(aGrabBag.getAsConstPropertyValueList())); + } + + // tdf#138782: for docs created in MS Word 2010 and older (compatibilityMode <= 14) + m_pImpl->SetDocumentSettingsProperty( + "AddFrameOffsets", + uno::Any(14 >= m_pImpl->GetSettingsTable()->GetWordCompatibilityMode())); + } + catch( const uno::Exception& ) {} + +#ifdef DBG_UTIL + TagLogger::getInstance().endDocument(); +#endif +} + +void DomainMapper::lcl_attribute(Id nName, Value & val) +{ + if (m_pImpl->hasTableManager() && m_pImpl->getTableManager().attribute(nName, val)) + return; + + static const int nSingleLineSpacing = 240; + sal_Int32 nIntValue = val.getInt(); + OUString sStringValue = val.getString(); + + SectionPropertyMap * pSectionContext = m_pImpl->GetSectionContext(); + switch( nName ) + { + case NS_ooxml::LN_CT_Lvl_start: + break; + case NS_ooxml::LN_CT_Lvl_numFmt: + break; + case NS_ooxml::LN_CT_Lvl_isLgl: + break; + case NS_ooxml::LN_CT_Lvl_legacy: + break; + case NS_ooxml::LN_CT_AbstractNum_nsid: + break; + case NS_ooxml::LN_CT_AbstractNum_tmpl: + break; + case NS_ooxml::LN_CT_Border_sz: + break; + case NS_ooxml::LN_CT_Border_val: + break; + case NS_ooxml::LN_CT_Border_space: + break; + case NS_ooxml::LN_CT_Border_shadow: + break; + case NS_ooxml::LN_CT_Border_frame: + break; + case NS_ooxml::LN_headerr: + break; + case NS_ooxml::LN_footerr: + break; + case NS_ooxml::LN_endnote: + break; + case NS_ooxml::LN_CT_Bookmark_name: + m_pImpl->SetBookmarkName( sStringValue ); + break; + case NS_ooxml::LN_CT_MarkupRangeBookmark_id: + // add a bookmark range -- this remembers a bookmark starting here + // or, if the bookmark was already started or, if the bookmark was + // already started before, writes out the bookmark + m_pImpl->StartOrEndBookmark( sStringValue ); + break; + case NS_ooxml::LN_CT_MarkupRange_displacedByCustomXml: + break; + case NS_ooxml::LN_NUMBERING: + break; + case NS_ooxml::LN_FONTTABLE: + break; + case NS_ooxml::LN_STYLESHEET: + break; + + case NS_ooxml::LN_CT_Sym_char: + m_pImpl->SetSymbolChar(nIntValue); + break; + case NS_ooxml::LN_CT_Sym_font: + m_pImpl->SetSymbolFont(sStringValue); + break; + case NS_ooxml::LN_CT_Underline_val: + if (m_pImpl->GetTopContext()) + handleUnderlineType(nIntValue, m_pImpl->GetTopContext()); + break; + case NS_ooxml::LN_CT_Color_val: + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_COLOR, uno::Any( nIntValue ) ); + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "val", msfilter::util::ConvertColorOU(Color(ColorTransparency,nIntValue))); + break; + case NS_ooxml::LN_CT_Underline_color: + if (m_pImpl->GetTopContext()) + { + m_pImpl->GetTopContext()->Insert(PROP_CHAR_UNDERLINE_HAS_COLOR, uno::Any( true ) ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_UNDERLINE_COLOR, uno::Any( nIntValue ) ); + } + break; + + case NS_ooxml::LN_CT_TabStop_val: + if (sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_TabJc_clear) + { + m_pImpl->m_aCurrentTabStop.bDeleted = true; + } + else + { + m_pImpl->m_aCurrentTabStop.bDeleted = false; + m_pImpl->m_aCurrentTabStop.Alignment = getTabAlignFromValue(nIntValue); + } + break; + case NS_ooxml::LN_CT_TabStop_leader: + m_pImpl->m_aCurrentTabStop.FillChar = getFillCharFromValue(nIntValue); + break; + case NS_ooxml::LN_CT_TabStop_pos: + m_pImpl->m_aCurrentTabStop.Position = ConversionHelper::convertTwipToMM100(nIntValue); + break; + + case NS_ooxml::LN_CT_Fonts_ascii: + if (m_pImpl->GetTopContext()) + { + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME, uno::Any( sStringValue )); + } + break; + case NS_ooxml::LN_CT_Fonts_asciiTheme: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "asciiTheme", ThemeTable::getStringForTheme(nIntValue)); + if (m_pImpl->GetTopContext()) + { + // note: overwrite Fonts_ascii with Fonts_asciiTheme *even if* + // theme font is empty - this is apparently what Word 2013 does + uno::Any aPropValue( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME, aPropValue ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_ASCII, aPropValue, true, CHAR_GRAB_BAG ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_ASCII, uno::Any( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG); + } + break; + case NS_ooxml::LN_CT_Fonts_hAnsi: + break;//unsupported + case NS_ooxml::LN_CT_Fonts_hAnsiTheme: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "hAnsiTheme", ThemeTable::getStringForTheme(nIntValue)); + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_H_ANSI, uno::Any( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG); + break; + case NS_ooxml::LN_CT_Fonts_eastAsia: + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_ASIAN, uno::Any( sStringValue )); + break; + case NS_ooxml::LN_CT_Fonts_eastAsiaTheme: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "eastAsiaTheme", ThemeTable::getStringForTheme(nIntValue)); + if (m_pImpl->GetTopContext()) + { + uno::Any aPropValue( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_ASIAN, aPropValue ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_EAST_ASIA, aPropValue, true, CHAR_GRAB_BAG ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_EAST_ASIA, uno::Any( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG); + } + break; + case NS_ooxml::LN_CT_Fonts_cs: + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_COMPLEX, uno::Any( sStringValue )); + break; + case NS_ooxml::LN_CT_Fonts_cstheme: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "cstheme", ThemeTable::getStringForTheme(nIntValue)); + if (m_pImpl->GetTopContext()) + { + uno::Any aPropValue( m_pImpl->GetThemeTable()->getFontNameForTheme( nIntValue ) ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_FONT_NAME_COMPLEX, aPropValue ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_FONT_NAME_CS, aPropValue, true, CHAR_GRAB_BAG ); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_NAME_CS, uno::Any( ThemeTable::getStringForTheme(nIntValue) ), true, CHAR_GRAB_BAG); + } + break; + case NS_ooxml::LN_CT_Spacing_before: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "before", OUString::number(nIntValue)); + if (m_pImpl->GetTopContext()) + // Don't overwrite NS_ooxml::LN_CT_Spacing_beforeAutospacing. + m_pImpl->GetTopContext()->Insert( + PROP_PARA_TOP_MARGIN, + uno::Any(static_cast<sal_Int32>(convertTwipToMm100(nIntValue))), false); + break; + case NS_ooxml::LN_CT_Spacing_beforeLines: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "beforeLines", OUString::number(nIntValue)); + // We would need to make sure that this doesn't overwrite any + // NS_ooxml::LN_CT_Spacing_before in parent styles before style + // sheet support can be enabled. + if (m_pImpl->GetTopContext() && !IsStyleSheetImport()) + m_pImpl->GetTopContext()->Insert(PROP_PARA_TOP_MARGIN, uno::Any(ConversionHelper::convertTwipToMM100(nIntValue * nSingleLineSpacing / 100)), false); + break; + case NS_ooxml::LN_CT_Spacing_after: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "after", OUString::number(nIntValue)); + if (m_pImpl->GetTopContext()) + { + // Don't overwrite NS_ooxml::LN_CT_Spacing_afterAutospacing. + m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::Any( ConversionHelper::convertTwipToMM100( nIntValue ) ), false); + + uno::Any aContextualSpacingFromStyle = m_pImpl->GetPropertyFromParaStyleSheet(PROP_PARA_CONTEXT_MARGIN); + if (aContextualSpacingFromStyle.hasValue()) + // Setting "after" spacing means Writer doesn't inherit + // contextual spacing anymore from style, but Word does. + m_pImpl->GetTopContext()->Insert(PROP_PARA_CONTEXT_MARGIN, aContextualSpacingFromStyle); + } + break; + case NS_ooxml::LN_CT_Spacing_afterLines: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "afterLines", OUString::number(nIntValue)); + // We would need to make sure that this doesn't overwrite any + // NS_ooxml::LN_CT_Spacing_after in parent styles before style + // sheet support can be enabled. + if (m_pImpl->GetTopContext() && !IsStyleSheetImport()) + m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::Any(ConversionHelper::convertTwipToMM100(nIntValue * nSingleLineSpacing / 100)), false); + break; + case NS_ooxml::LN_CT_Spacing_line: //91434 + case NS_ooxml::LN_CT_Spacing_lineRule: //91435 + { + style::LineSpacing aSpacing; + PropertyMapPtr pTopContext = m_pImpl->GetTopContext(); + std::optional<PropertyMap::Property> aLineSpacingVal; + if (pTopContext && (aLineSpacingVal = pTopContext->getProperty(PROP_PARA_LINE_SPACING)) ) + { + aLineSpacingVal->second >>= aSpacing; + } + else + { + //default to single line spacing + aSpacing.Mode = style::LineSpacingMode::FIX; + aSpacing.Height = sal_Int16(ConversionHelper::convertTwipToMM100( nSingleLineSpacing )); + } + if( nName == NS_ooxml::LN_CT_Spacing_line ) + { + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "line", OUString::number(nIntValue)); + //now set the value depending on the Mode + if( aSpacing.Mode == style::LineSpacingMode::PROP ) + aSpacing.Height = sal_Int16(nIntValue * 100 / nSingleLineSpacing ); + else + aSpacing.Height = sal_Int16(ConversionHelper::convertTwipToMM100( nIntValue )); + } + else //NS_ooxml::LN_CT_Spacing_lineRule: + { + // exactly, atLeast, auto + if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_LineSpacingRule_auto) + { + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "auto"); + if (aSpacing.Height >= 0) + { + aSpacing.Mode = style::LineSpacingMode::PROP; + //reinterpret the already set value + aSpacing.Height = sal_Int16( aSpacing.Height * 100 / ConversionHelper::convertTwipToMM100( nSingleLineSpacing )); + } + else + { + // Negative value still means a positive height, + // just the mode is "exact". + aSpacing.Mode = style::LineSpacingMode::FIX; + aSpacing.Height *= -1; + } + } + else if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_LineSpacingRule_atLeast) + { + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "atLeast"); + aSpacing.Mode = style::LineSpacingMode::MINIMUM; + } + else // NS_ooxml::LN_Value_doc_ST_LineSpacingRule_exact + { + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "lineRule", "exact"); + aSpacing.Mode = style::LineSpacingMode::FIX; + } + } + if (pTopContext) + pTopContext->Insert(PROP_PARA_LINE_SPACING, uno::Any( aSpacing )); + } + break; + case NS_ooxml::LN_CT_Ind_start: + case NS_ooxml::LN_CT_Ind_left: + if (m_pImpl->GetTopContext()) + { + // Word inherits FirstLineIndent property of the numbering, even if ParaLeftMargin is set, Writer does not. + // So copy it explicitly, if necessary. + sal_Int32 nFirstLineIndent = m_pImpl->getCurrentNumberingProperty("FirstLineIndent"); + sal_Int32 nIndentAt = m_pImpl->getCurrentNumberingProperty("IndentAt"); + + sal_Int32 nParaLeftMargin = ConversionHelper::convertTwipToMM100(nIntValue); + if (nParaLeftMargin != 0 && nIndentAt == nParaLeftMargin) + // Avoid direct left margin when it's the same as from the + // numbering. + break; + + if (nFirstLineIndent != 0) + m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::Any(nFirstLineIndent), /*bOverwrite=*/false); + + m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN, + uno::Any(nParaLeftMargin)); + } + break; + case NS_ooxml::LN_CT_Ind_end: + case NS_ooxml::LN_CT_Ind_right: + if (m_pImpl->GetTopContext()) + { + // Word inherits FirstLineIndent/ParaLeftMargin property of the numbering, even if ParaRightMargin is set, Writer does not. + // So copy it explicitly, if necessary. + sal_Int32 nFirstLineIndent = m_pImpl->getCurrentNumberingProperty("FirstLineIndent"); + sal_Int32 nParaLeftMargin = m_pImpl->getCurrentNumberingProperty("IndentAt"); + + if (nFirstLineIndent != 0) + m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, uno::Any(nFirstLineIndent), /*bOverwrite=*/false); + if (nParaLeftMargin != 0) + m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN, uno::Any(nParaLeftMargin), /*bOverwrite=*/false); + + m_pImpl->GetTopContext()->Insert( + PROP_PARA_RIGHT_MARGIN, uno::Any( ConversionHelper::convertTwipToMM100(nIntValue ) )); + } + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "right", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Ind_hanging: + if (m_pImpl->GetTopContext()) + { + sal_Int32 nValue = ConversionHelper::convertTwipToMM100( nIntValue ); + m_pImpl->GetTopContext()->Insert( + PROP_PARA_FIRST_LINE_INDENT, uno::Any( - nValue )); + + // See above, need to inherit left margin from list style when first is set. + sal_Int32 nParaLeftMargin = m_pImpl->getCurrentNumberingProperty("IndentAt"); + if (nParaLeftMargin != 0) + m_pImpl->GetTopContext()->Insert(PROP_PARA_LEFT_MARGIN, uno::Any(nParaLeftMargin), /*bOverwrite=*/false); + } + break; + case NS_ooxml::LN_CT_Ind_firstLine: + if (m_pImpl->GetTopContext()) + { + sal_Int32 nFirstLineIndent + = m_pImpl->getCurrentNumberingProperty("FirstLineIndent"); + sal_Int32 nParaFirstLineIndent = ConversionHelper::convertTwipToMM100(nIntValue); + if (nParaFirstLineIndent != 0 && nFirstLineIndent == nParaFirstLineIndent) + // Avoid direct first margin when it's the same as from the + // numbering. + break; + m_pImpl->GetTopContext()->Insert(PROP_PARA_FIRST_LINE_INDENT, + uno::Any(nParaFirstLineIndent)); + } + break; + case NS_ooxml::LN_CT_Ind_rightChars: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "rightChars", OUString::number(nIntValue)); + break; + + case NS_ooxml::LN_CT_EastAsianLayout_id: + break; + case NS_ooxml::LN_CT_EastAsianLayout_combine: + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_IS_ON, uno::Any ( nIntValue != 0 )); + break; + case NS_ooxml::LN_CT_EastAsianLayout_combineBrackets: + if (m_pImpl->GetTopContext()) + { + OUString sCombinePrefix = getBracketStringFromEnum(nIntValue); + OUString sCombineSuffix = getBracketStringFromEnum(nIntValue, false); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_PREFIX, uno::Any ( sCombinePrefix )); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_COMBINE_SUFFIX, uno::Any ( sCombineSuffix )); + } + break; + case NS_ooxml::LN_CT_EastAsianLayout_vert: + if (m_pImpl->GetTopContext()) + { + sal_Int16 nRotationAngle = (nIntValue ? 900 : 0); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION, uno::Any ( nRotationAngle )); + } + break; + case NS_ooxml::LN_CT_EastAsianLayout_vertCompress: + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(PROP_CHAR_ROTATION_IS_FIT_TO_LINE, uno::Any ( nIntValue != 0 )); + break; + + case NS_ooxml::LN_CT_PageSz_code: + break; + case NS_ooxml::LN_CT_PageSz_h: + { + sal_Int32 nHeight = ConversionHelper::convertTwipToMM100WithoutLimit(nIntValue); + CT_PageSz.h = PaperInfo::sloppyFitPageDimension(nHeight); + } + break; + case NS_ooxml::LN_CT_PageSz_orient: + CT_PageSz.orient = (nIntValue != NS_ooxml::LN_Value_ST_PageOrientation_portrait); + break; + case NS_ooxml::LN_CT_PageSz_w: + { + sal_Int32 nWidth = ConversionHelper::convertTwipToMM100WithoutLimit(nIntValue); + CT_PageSz.w = PaperInfo::sloppyFitPageDimension(nWidth); + } + break; + + case NS_ooxml::LN_CT_PageMar_top: + m_pImpl->SetPageMarginTwip( PAGE_MAR_TOP, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_right: + m_pImpl->SetPageMarginTwip( PAGE_MAR_RIGHT, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_bottom: + m_pImpl->SetPageMarginTwip( PAGE_MAR_BOTTOM, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_left: + m_pImpl->SetPageMarginTwip( PAGE_MAR_LEFT, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_header: + m_pImpl->SetPageMarginTwip( PAGE_MAR_HEADER, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_footer: + m_pImpl->SetPageMarginTwip( PAGE_MAR_FOOTER, nIntValue ); + break; + case NS_ooxml::LN_CT_PageMar_gutter: + m_pImpl->SetPageMarginTwip( PAGE_MAR_GUTTER, nIntValue ); + break; + case NS_ooxml::LN_CT_Language_val: //90314 + case NS_ooxml::LN_CT_Language_eastAsia: //90315 + case NS_ooxml::LN_CT_Language_bidi: //90316 + { + // store decimal symbol associated to the language of the document + if ( m_pImpl->IsDocDefaultsImport() && ( nName == NS_ooxml::LN_CT_Language_val ) ) + { + LanguageTag aLanguageTag( sStringValue ); + LocaleDataWrapper aLocaleWrapper( std::move(aLanguageTag) ); + if ( aLocaleWrapper.getNumDecimalSep() == "," ) + m_pImpl->SetIsDecimalComma(); + + } + if (nName == NS_ooxml::LN_CT_Language_eastAsia) + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "eastAsia", sStringValue); + else if (nName == NS_ooxml::LN_CT_Language_val) + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "val", sStringValue); + else if (nName == NS_ooxml::LN_CT_Language_bidi) + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "bidi", sStringValue); + lang::Locale aLocale; + if (sStringValue.getLength() <= 3 && sStringValue.getLength() >= 1) + { + // Cheesy Google Docs is known to tag language-only even for + // "en" or others that need some region to distinguish language + // variants for spell-checker and hyphenation. Obtain our known + // fallback to clarify and match. The original value/context is + // unknown anyway. + LanguageTag aLanguageTag( sStringValue); + aLanguageTag.makeFallback(); + if (aLanguageTag.getLanguage() == sStringValue) + aLocale = aLanguageTag.getLocale(); + else + { + // Do not fallback for an unknown language, which usually + // results in "en-US", or any other non-matching case. + aLocale = LanguageTag::convertToLocale( sStringValue); + } + } + else + { + aLocale = LanguageTag::convertToLocale( sStringValue); + } + if (m_pImpl->GetTopContext()) + m_pImpl->GetTopContext()->Insert(NS_ooxml::LN_CT_Language_val== nName ? PROP_CHAR_LOCALE : + NS_ooxml::LN_CT_Language_eastAsia == nName ? PROP_CHAR_LOCALE_ASIAN : PROP_CHAR_LOCALE_COMPLEX, + uno::Any( aLocale ) ); + } + break; + // See SwWW8ImplReader::GetParagraphAutoSpace() on why these are 100 and 280 + case NS_ooxml::LN_CT_Spacing_beforeAutospacing: + { + sal_Int32 default_spacing = -1; + if (nIntValue) + { + m_pImpl->SetParaAutoBefore(true); + + default_spacing = 100; + if (!m_pImpl->GetSettingsTable()->GetDoNotUseHTMLParagraphAutoSpacing()) + { + // 49 is just the old value that should be removed, once the + // root cause in SwTabFrm::MakeAll() is fixed. + if (m_pImpl->GetSettingsTable()->GetView() == NS_ooxml::LN_Value_doc_ST_View_web) + default_spacing = 49; + else + default_spacing = 280; + } + // required at export (here mainly for StyleSheets) to determine if the setting has changed from grab_bag + m_pImpl->GetTopContext()->Insert(PROP_PARA_TOP_MARGIN, uno::Any(ConversionHelper::convertTwipToMM100(default_spacing))); + } + m_pImpl->GetTopContext()->Insert( PROP_PARA_TOP_MARGIN_BEFORE_AUTO_SPACING, uno::Any( ConversionHelper::convertTwipToMM100(default_spacing) ),true, PARA_GRAB_BAG ); + } + break; + case NS_ooxml::LN_CT_Spacing_afterAutospacing: + { + sal_Int32 default_spacing = -1; + if (nIntValue) + { + default_spacing = 100; + if (!m_pImpl->GetSettingsTable()->GetDoNotUseHTMLParagraphAutoSpacing()) + { + if (m_pImpl->GetSettingsTable()->GetView() == NS_ooxml::LN_Value_doc_ST_View_web) + default_spacing = 49; + else + default_spacing = 280; + } + m_pImpl->GetTopContext()->Insert(PROP_PARA_BOTTOM_MARGIN, uno::Any(ConversionHelper::convertTwipToMM100(default_spacing))); + } + m_pImpl->GetTopContext()->Insert( PROP_PARA_BOTTOM_MARGIN_AFTER_AUTO_SPACING, uno::Any( ConversionHelper::convertTwipToMM100(default_spacing) ),true, PARA_GRAB_BAG ); + } + break; + case NS_ooxml::LN_CT_SmartTagRun_uri: + m_pImpl->getSmartTagHandler().setURI(val.getString()); + break; + case NS_ooxml::LN_CT_SmartTagRun_element: + m_pImpl->getSmartTagHandler().setElement(val.getString()); + break; + case NS_ooxml::LN_CT_Br_type: + // Handled in the OOXMLBreakHandler dtor. + break; + case NS_ooxml::LN_CT_Br_clear: + m_pImpl->HandleLineBreakClear(val.getInt()); + break; + case NS_ooxml::LN_CT_Fonts_hint : + /* assigns script type to ambiguous characters, values can be: + NS_ooxml::LN_Value_ST_Hint_default + NS_ooxml::LN_Value_ST_Hint_eastAsia + NS_ooxml::LN_Value_ST_Hint_cs + */ + //TODO: unsupported? + break; + case NS_ooxml::LN_CT_TblBorders_right: + case NS_ooxml::LN_CT_TblBorders_top: + case NS_ooxml::LN_CT_TblBorders_left: + case NS_ooxml::LN_CT_TblBorders_bottom: + //todo: handle cell mar + break; + case NS_ooxml::LN_blip: // contains the binary graphic + case NS_ooxml::LN_shape: + { + //looks a bit like a hack - and it is. The graphic import is split into the inline_inline part and + //afterwards the adding of the binary data. + m_pImpl->GetGraphicImport( IMPORT_AS_DETECTED_INLINE )->attribute(nName, val); + m_pImpl->ImportGraphic( val.getProperties(), IMPORT_AS_DETECTED_INLINE ); + } + break; + case NS_ooxml::LN_Value_math_ST_Jc_centerGroup: + case NS_ooxml::LN_Value_math_ST_Jc_center: + m_pImpl->appendStarMath(val); + m_pImpl->adjustLastPara(sal_Int8(style::ParagraphAdjust::ParagraphAdjust_CENTER)); + break; + case NS_ooxml::LN_Value_math_ST_Jc_left: + m_pImpl->appendStarMath(val); + m_pImpl->adjustLastPara(sal_Int8(style::ParagraphAdjust::ParagraphAdjust_LEFT)); + break; + case NS_ooxml::LN_Value_math_ST_Jc_right: + m_pImpl->appendStarMath(val); + m_pImpl->adjustLastPara(sal_Int8(style::ParagraphAdjust::ParagraphAdjust_RIGHT)); + break; + case NS_ooxml::LN_starmath: + m_pImpl->appendStarMath(val); + break; + case NS_ooxml::LN_CT_FramePr_dropCap: + case NS_ooxml::LN_CT_FramePr_lines: + case NS_ooxml::LN_CT_FramePr_hAnchor: + case NS_ooxml::LN_CT_FramePr_vAnchor: + case NS_ooxml::LN_CT_FramePr_x: + case NS_ooxml::LN_CT_FramePr_xAlign: + case NS_ooxml::LN_CT_FramePr_y: + case NS_ooxml::LN_CT_FramePr_yAlign: + case NS_ooxml::LN_CT_FramePr_hRule: + case NS_ooxml::LN_CT_FramePr_w: + case NS_ooxml::LN_CT_FramePr_h: + case NS_ooxml::LN_CT_FramePr_wrap: + case NS_ooxml::LN_CT_FramePr_hSpace: + case NS_ooxml::LN_CT_FramePr_vSpace: + { + ParagraphProperties* pParaProperties = nullptr; + // handle frame properties at styles + if( m_pImpl->GetTopContextType() == CONTEXT_STYLESHEET ) + pParaProperties = dynamic_cast< ParagraphProperties*>( m_pImpl->GetTopContextOfType( CONTEXT_STYLESHEET ).get() ); + else + pParaProperties = dynamic_cast< ParagraphProperties*>( m_pImpl->GetTopContextOfType( CONTEXT_PARAGRAPH ).get() ); + + if( pParaProperties ) + { + switch( nName ) + { + case NS_ooxml::LN_CT_FramePr_dropCap: + pParaProperties->SetDropCap( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_lines: + pParaProperties->SetLines( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_hAnchor: + switch(nIntValue) + { + case NS_ooxml::LN_Value_doc_ST_HAnchor_text: //relative to column + nIntValue = text::RelOrientation::FRAME; break; + case NS_ooxml::LN_Value_doc_ST_HAnchor_margin: nIntValue = text::RelOrientation::PAGE_PRINT_AREA; break; + case NS_ooxml::LN_Value_doc_ST_HAnchor_page: nIntValue = text::RelOrientation::PAGE_FRAME; break; + default:; + } + pParaProperties->SethAnchor( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_vAnchor: + switch(nIntValue) + { + case NS_ooxml::LN_Value_doc_ST_VAnchor_text: //relative to paragraph + nIntValue = text::RelOrientation::FRAME; break; + case NS_ooxml::LN_Value_doc_ST_VAnchor_margin:nIntValue = text::RelOrientation::PAGE_PRINT_AREA ; break; + case NS_ooxml::LN_Value_doc_ST_VAnchor_page: nIntValue = text::RelOrientation::PAGE_FRAME; break; + default:; + } + pParaProperties->SetvAnchor( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_x: + pParaProperties->Setx( ConversionHelper::convertTwipToMM100(nIntValue )); + pParaProperties->SetxAlign( text::HoriOrientation::NONE ); + break; + case NS_ooxml::LN_CT_FramePr_xAlign: + switch( nIntValue ) + { + case NS_ooxml::LN_Value_doc_ST_XAlign_center : nIntValue = text::HoriOrientation::CENTER; break; + case NS_ooxml::LN_Value_doc_ST_XAlign_right : nIntValue = text::HoriOrientation::RIGHT; break; + case NS_ooxml::LN_Value_doc_ST_XAlign_inside : nIntValue = text::HoriOrientation::INSIDE; break; + case NS_ooxml::LN_Value_doc_ST_XAlign_outside : nIntValue = text::HoriOrientation::OUTSIDE; break; + case NS_ooxml::LN_Value_doc_ST_XAlign_left : nIntValue = text::HoriOrientation::LEFT; break; + default: nIntValue = text::HoriOrientation::NONE; + } + pParaProperties->SetxAlign( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_y: + pParaProperties->Sety( ConversionHelper::convertTwipToMM100(nIntValue )); + pParaProperties->SetyAlign( text::VertOrientation::NONE ); + break; + case NS_ooxml::LN_CT_FramePr_yAlign: + switch( nIntValue ) + { + case NS_ooxml::LN_Value_doc_ST_YAlign_top : + case NS_ooxml::LN_Value_doc_ST_YAlign_inside :nIntValue = text::VertOrientation::TOP; break; + case NS_ooxml::LN_Value_doc_ST_YAlign_center :nIntValue = text::VertOrientation::CENTER;break; + case NS_ooxml::LN_Value_doc_ST_YAlign_bottom : + case NS_ooxml::LN_Value_doc_ST_YAlign_outside :nIntValue = text::VertOrientation::BOTTOM;break; + case NS_ooxml::LN_Value_doc_ST_YAlign_inline : + { + // HACK: This is for bnc#780851, where a table has one cell that has w:framePr, + // which causes that paragraph to be converted to a text frame, and the original + // paragraph object no longer exists, which makes table creation fail and furthermore + // it would be missing in the table layout anyway. So actually no letting that paragraph + // be a text frame "fixes" it. I'm not sure what "inline" is supposed to mean in practice + // anyway, so as long as this doesn't cause trouble elsewhere ... + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if( pContext ) + { + ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pContext.get() ); + if (pParaContext) + pParaContext->SetFrameMode(false); + } + nIntValue = text::VertOrientation::NONE; + break; + } + default: + nIntValue = text::VertOrientation::NONE; + break; + } + pParaProperties->SetyAlign( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_hRule: + switch( nIntValue ) + { + case NS_ooxml::LN_Value_doc_ST_HeightRule_exact: + nIntValue = text::SizeType::FIX; + break; + case NS_ooxml::LN_Value_doc_ST_HeightRule_atLeast: + nIntValue = text::SizeType::MIN; + break; + case NS_ooxml::LN_Value_doc_ST_HeightRule_auto: + //no break; + default:; + nIntValue = text::SizeType::VARIABLE; + } + pParaProperties->SethRule( nIntValue ); + break; + case NS_ooxml::LN_CT_FramePr_wrap: + { + //should be either LN_Value_doc_ST_Wrap_notBeside or LN_Value_doc_ST_Wrap_around or LN_Value_doc_ST_Wrap_auto + OSL_ENSURE( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_around || + sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_notBeside || + sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_through || + sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_none || + sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_auto, + "wrap not around, not_Beside, through, none or auto?"); + if( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_through || + sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_auto ) + pParaProperties->SetWrap ( text::WrapTextMode_DYNAMIC ) ; + else if (sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_around) + pParaProperties->SetWrap(text::WrapTextMode_PARALLEL); + else if (sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_doc_ST_Wrap_none) + pParaProperties->SetWrap ( text::WrapTextMode_THROUGH ) ; + else + pParaProperties->SetWrap ( text::WrapTextMode_NONE ) ; + } + break; + case NS_ooxml::LN_CT_FramePr_w: + pParaProperties->Setw(ConversionHelper::convertTwipToMM100(nIntValue)); + break; + case NS_ooxml::LN_CT_FramePr_h: + pParaProperties->Seth(ConversionHelper::convertTwipToMM100(nIntValue)); + break; + case NS_ooxml::LN_CT_FramePr_hSpace: + pParaProperties->SethSpace( ConversionHelper::convertTwipToMM100(nIntValue )); + break; + case NS_ooxml::LN_CT_FramePr_vSpace: + pParaProperties->SetvSpace( ConversionHelper::convertTwipToMM100(nIntValue )); + break; + default:; + } + } + } + break; + case NS_ooxml::LN_CT_TrackChange_author: + m_pImpl->SetCurrentRedlineAuthor( sStringValue ); + break; + case NS_ooxml::LN_CT_TrackChange_date: + m_pImpl->SetCurrentRedlineDate( sStringValue ); + break; + case NS_ooxml::LN_CT_Markup_id: + m_pImpl->SetCurrentRedlineId( nIntValue ); + break; + case NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart: + m_pImpl->AddAnnotationPosition( true, nIntValue ); + break; + case NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd: + m_pImpl->AddAnnotationPosition( false, nIntValue ); + break; + case NS_ooxml::LN_CT_Comment_initials: + m_pImpl->SetCurrentRedlineInitials(sStringValue); + break; + case NS_ooxml::LN_token: + m_pImpl->SetCurrentRedlineToken( nIntValue ); + break; + case NS_ooxml::LN_CT_LineNumber_start: + case NS_ooxml::LN_CT_LineNumber_distance: + case NS_ooxml::LN_CT_LineNumber_countBy: + case NS_ooxml::LN_CT_LineNumber_restart: + { + //line numbering in Writer is a global document setting + //in Word is a section setting + //if line numbering is switched on anywhere in the document it's set at the global settings + LineNumberSettings aSettings = m_pImpl->GetLineNumberSettings(); + switch( nName ) + { + case NS_ooxml::LN_CT_LineNumber_countBy: + aSettings.nInterval = nIntValue; + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if( pSectionContext ) + pSectionContext->SetLnnMod( nIntValue ); + break; + case NS_ooxml::LN_CT_LineNumber_start: + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if( pSectionContext ) + pSectionContext->SetLnnMin( nIntValue ); + break; + case NS_ooxml::LN_CT_LineNumber_distance: + aSettings.nDistance = ConversionHelper::convertTwipToMM100( nIntValue ); + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if( pSectionContext ) + pSectionContext->SetdxaLnn( nIntValue ); + break; + case NS_ooxml::LN_CT_LineNumber_restart: + aSettings.bRestartAtEachPage = nIntValue == NS_ooxml::LN_Value_ST_LineNumberRestart_newPage; + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if( pSectionContext ) + pSectionContext->SetLnc( nIntValue ); + break; + default:; + } + m_pImpl->SetLineNumberSettings( aSettings ); + } + break; + case NS_ooxml::LN_CT_FtnEdnRef_customMarkFollows: + m_pImpl->StartCustomFootnote(m_pImpl->GetTopContext()); + break; + case NS_ooxml::LN_CT_FtnEdnRef_id: + // footnote or endnote reference id - not needed + break; + case NS_ooxml::LN_CT_Color_themeColor: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeColor", TDefTableHandler::getThemeColorTypeString(nIntValue)); + break; + case NS_ooxml::LN_CT_Color_themeTint: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeTint", OUString::number(nIntValue, 16)); + break; + case NS_ooxml::LN_CT_Color_themeShade: + m_pImpl->appendGrabBag(m_pImpl->m_aSubInteropGrabBag, "themeShade", OUString::number(nIntValue, 16)); + break; + case NS_ooxml::LN_CT_DocGrid_linePitch: + { + //see SwWW8ImplReader::SetDocumentGrid + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + pSectionContext->SetGridLinePitch( ConversionHelper::convertTwipToMM100( nIntValue ) ); + } + } + break; + case NS_ooxml::LN_CT_DocGrid_charSpace: + { + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + pSectionContext->SetDxtCharSpace( nIntValue ); + } + } + break; + case NS_ooxml::LN_CT_DocGrid_type: + { + if (pSectionContext != nullptr) + { + switch( nIntValue ) + { + case NS_ooxml::LN_Value_doc_ST_DocGrid_default: + pSectionContext->SetGridType(text::TextGridMode::NONE); + break; + case NS_ooxml::LN_Value_doc_ST_DocGrid_lines: + pSectionContext->SetGridType(text::TextGridMode::LINES); + break; + case NS_ooxml::LN_Value_doc_ST_DocGrid_linesAndChars: + pSectionContext->SetGridType(text::TextGridMode::LINES_AND_CHARS); + pSectionContext->SetGridSnapToChars( false ); + break; + case NS_ooxml::LN_Value_doc_ST_DocGrid_snapToChars: + pSectionContext->SetGridType(text::TextGridMode::LINES_AND_CHARS); + pSectionContext->SetGridSnapToChars( true ); + break; + default : + OSL_FAIL("unknown SwTextGrid value"); + } + } + } + break; + case NS_ooxml::LN_CT_SdtBlock_sdtContent: + case NS_ooxml::LN_CT_SdtRun_sdtContent: + if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::unknown) + { + // Still not determined content type? and it is even not unsupported? Then it is plain text field + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::plainText); + } + if (nName == NS_ooxml::LN_CT_SdtRun_sdtContent) + { + if (m_pImpl->GetSdtStarts().empty() && !m_pImpl->m_pSdtHelper->getSdtTexts().isEmpty()) + { + // A non-inline SDT is already started, first convert that to a field and only + // then map the inline SDT to a content control. + if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + m_pImpl->m_pSdtHelper->createPlainTextControl(); + } + } + + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::richText); + m_pImpl->PushSdt(); + break; + } + m_pImpl->SetSdt(true); + break; + case NS_ooxml::LN_CT_SdtBlock_sdtEndContent: + case NS_ooxml::LN_CT_SdtRun_sdtEndContent: + if (nName == NS_ooxml::LN_CT_SdtRun_sdtEndContent) + { + // Inline SDT. + switch (m_pImpl->m_pSdtHelper->getControlType()) + { + case SdtControlType::richText: + case SdtControlType::checkBox: + case SdtControlType::dropDown: + case SdtControlType::picture: + case SdtControlType::datePicker: + m_pImpl->PopSdt(); + break; + default: + break; + } + } + + m_pImpl->SetSdt(false); + + // It's not possible to insert the relevant property to the character context here: + // the previous, already sent character context may be still active, so the property would be lost. + if (m_pImpl->m_pSdtHelper->isOutsideAParagraph()) + m_pImpl->setParaSdtEndDeferred(true); + else + m_pImpl->setSdtEndDeferred(true); + + switch (m_pImpl->m_pSdtHelper->getControlType()) + { + case SdtControlType::dropDown: + m_pImpl->m_pSdtHelper->createDropDownControl(); + break; + case SdtControlType::plainText: + m_pImpl->m_pSdtHelper->createPlainTextControl(); + break; + case SdtControlType::datePicker: + m_pImpl->m_pSdtHelper->createDateContentControl(); + break; + case SdtControlType::unknown: + default:; + } + break; + case NS_ooxml::LN_CT_SdtListItem_displayText: + m_pImpl->m_pSdtHelper->getDropDownDisplayTexts().push_back(sStringValue); + break; + case NS_ooxml::LN_CT_SdtListItem_value: + m_pImpl->m_pSdtHelper->getDropDownItems().push_back(sStringValue); + break; + case NS_ooxml::LN_CT_SdtDate_fullDate: + m_pImpl->m_pSdtHelper->getDate().append(sStringValue); + break; + case NS_ooxml::LN_CT_Background_color: + if (m_pImpl->GetSettingsTable()->GetDisplayBackgroundShape()) + m_pImpl->m_oBackgroundColor = nIntValue; + break; + case NS_ooxml::LN_CT_PageNumber_start: + if (pSectionContext != nullptr && !m_pImpl->IsAltChunk()) + pSectionContext->SetPageNumber(nIntValue); + break; + case NS_ooxml::LN_CT_PageNumber_fmt: + if (pSectionContext) + { + sal_Int16 nNumberType = ConversionHelper::ConvertNumberingType(nIntValue, -1); + if (nNumberType != -1) + pSectionContext->SetPageNumberType(nNumberType); + } + break; + case NS_ooxml::LN_CT_FtnEdn_type: + // This is the "separator" footnote, ignore its linebreaks/text. + if (static_cast<sal_uInt32>(nIntValue) == NS_ooxml::LN_Value_doc_ST_FtnEdn_separator) + m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::ON ); + else + m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::OFF ); + break; + case NS_ooxml::LN_CT_FtnEdn_id: + { + SkipFootnoteSeparator eSkip = m_pImpl->GetSkipFootnoteState(); + if ( eSkip == SkipFootnoteSeparator::ON ) + m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::SKIPPING ); + else if ( eSkip == SkipFootnoteSeparator::SKIPPING ) + m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::OFF ); + } + break; + case NS_ooxml::LN_CT_DataBinding_prefixMappings: + m_pImpl->m_pSdtHelper->setDataBindingPrefixMapping(sStringValue); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_prefixMappings", sStringValue); + break; + case NS_ooxml::LN_CT_DataBinding_xpath: + m_pImpl->m_pSdtHelper->setDataBindingXPath(sStringValue); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_xpath", sStringValue); + break; + case NS_ooxml::LN_CT_DataBinding_storeItemID: + m_pImpl->m_pSdtHelper->setDataBindingStoreItemID(sStringValue); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_DataBinding_storeItemID", sStringValue); + break; + case NS_ooxml::LN_CT_SdtPlaceholder_docPart_val: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtPlaceholder_docPart_val", sStringValue); + m_pImpl->m_pSdtHelper->SetPlaceholderDocPart(sStringValue); + break; + case NS_ooxml::LN_CT_SdtColor_val: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtColor_val", sStringValue); + m_pImpl->m_pSdtHelper->SetColor(sStringValue); + break; + case NS_ooxml::LN_CT_SdtText_multiLine: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtText_multiLine", sStringValue); + break; + case NS_ooxml::LN_CT_PTab_leader: + case NS_ooxml::LN_CT_PTab_relativeTo: + break; + case NS_ooxml::LN_CT_PTab_alignment: + m_pImpl->HandlePTab(nIntValue); + break; + case NS_ooxml::LN_CT_Cnf_lastRowLastColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRowLastColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_lastRowFirstColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRowFirstColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_firstRowLastColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRowLastColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_oddHBand: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "oddHBand", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_firstRowFirstColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRowFirstColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_evenVBand: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "evenVBand", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_evenHBand: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "evenHBand", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_lastColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_firstColumn: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstColumn", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_oddVBand: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "oddVBand", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_lastRow: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lastRow", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_firstRow: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "firstRow", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_CT_Cnf_val: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "val", sStringValue); + break; + case NS_ooxml::LN_CT_DocPartName_val: + { + m_sGlossaryEntryName = sStringValue; + break; + } + case NS_ooxml::LN_CT_DocPartGallery_val: + { + const OUString& sGlossaryEntryGallery = sStringValue; + if(m_pImpl->GetTopContext()) + { + OUString sName = sGlossaryEntryGallery + ":" + m_sGlossaryEntryName; + // Add glossary entry name as a first paragraph in section + m_pImpl->appendTextPortion(sName, m_pImpl->GetTopContext()); + } + break; + } + case NS_ooxml::LN_CT_PermStart_ed: + { + m_pImpl->setPermissionRangeEd(sStringValue); + break; + } + case NS_ooxml::LN_CT_PermStart_edGrp: + { + m_pImpl->setPermissionRangeEdGrp(sStringValue); + break; + } + case NS_ooxml::LN_CT_PermStart_id: + { + m_pImpl->startOrEndPermissionRange(nIntValue); + break; + } + case NS_ooxml::LN_CT_PermEnd_id: + { + m_pImpl->startOrEndPermissionRange(nIntValue); + break; + } + case NS_ooxml::LN_CT_NumFmt_val: + { + try + { + uno::Reference<beans::XPropertySet> xFtnEdnSettings; + if (m_pImpl->IsInFootnoteProperties()) + { + uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier( + m_pImpl->GetTextDocument(), uno::UNO_QUERY); + if (xFootnotesSupplier.is()) + xFtnEdnSettings = xFootnotesSupplier->getFootnoteSettings(); + } + else + { + uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier( + m_pImpl->GetTextDocument(), uno::UNO_QUERY); + if (xEndnotesSupplier.is()) + xFtnEdnSettings = xEndnotesSupplier->getEndnoteSettings(); + } + if (xFtnEdnSettings.is()) + { + sal_Int16 nNumType = ConversionHelper::ConvertNumberingType(nIntValue); + xFtnEdnSettings->setPropertyValue(getPropertyName(PROP_NUMBERING_TYPE), + uno::Any(nNumType)); + } + } + catch (const uno::Exception&) + { + } + } + break; + case NS_ooxml::LN_CT_AltChunk: + { + m_pImpl->HandleAltChunk(sStringValue); + } + break; + case NS_ooxml::LN_AG_Parids_paraId: + if (ParagraphPropertyMap* pParaContext + = dynamic_cast<ParagraphPropertyMap*>(m_pImpl->GetTopContext().get())) + { + pParaContext->SetParaId(sStringValue); + } + break; + default: + SAL_WARN("writerfilter", "DomainMapper::lcl_attribute: unhandled token: " << nName); + } +} + +void DomainMapper::lcl_sprm(Sprm & rSprm) +{ + if (!m_pImpl->hasTableManager() || !m_pImpl->getTableManager().sprm(rSprm)) + sprmWithProps(rSprm, m_pImpl->GetTopContext()); +} + +// In rtl-paragraphs the meaning of left/right are to be exchanged +static bool ExchangeLeftRight(const PropertyMapPtr& rContext, DomainMapper_Impl& rImpl) +{ + bool bExchangeLeftRight = false; + sal_Int32 aAdjust; + uno::Any aPropPara = rImpl.GetAnyProperty(PROP_WRITING_MODE, rContext); + if( (aPropPara >>= aAdjust) && aAdjust == text::WritingMode2::RL_TB ) + bExchangeLeftRight = true; + return bExchangeLeftRight; +} + +void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext ) +{ + // These SPRM's are not specific to any section, so it's expected that there is no context yet. + switch (rSprm.getId()) + { + case NS_ooxml::LN_background_background: + return; + default: + break; + } + + OSL_ENSURE(rContext, "PropertyMap has to be valid!"); + if(!rContext) + return ; + + sal_uInt32 nSprmId = rSprm.getId(); + //needed for page properties + SectionPropertyMap * pSectionContext = m_pImpl->GetSectionContext(); + Value::Pointer_t pValue = rSprm.getValue(); + sal_Int32 nIntValue = pValue->getInt(); + const OUString sStringValue = pValue->getString(); + + switch(nSprmId) + { + case NS_ooxml::LN_CT_PPrBase_jc: + { + bool bExchangeLeftRight = !IsRTFImport() && ExchangeLeftRight(rContext, *m_pImpl); + handleParaJustification(nIntValue, rContext, bExchangeLeftRight); + break; + } + case NS_ooxml::LN_CT_PPrBase_keepLines: + rContext->Insert(PROP_PARA_SPLIT, uno::Any(nIntValue == 0)); + break; + case NS_ooxml::LN_CT_PPrBase_keepNext: + rContext->Insert(PROP_PARA_KEEP_TOGETHER, uno::Any( nIntValue != 0 ) ); + break; + case NS_ooxml::LN_CT_PPrBase_pageBreakBefore: + rContext->Insert(PROP_BREAK_TYPE, uno::Any(nIntValue ? style::BreakType_PAGE_BEFORE : style::BreakType_NONE), /*bOverwrite=*/bool(nIntValue)); + break; + case NS_ooxml::LN_CT_NumPr_ilvl: + if (nIntValue < 0 || 10 <= nIntValue) + { + SAL_INFO("writerfilter", + "unsupported numbering level " << nIntValue); + break; + } + if( IsStyleSheetImport() ) + { + //style sheets cannot have a numbering rule attached + StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() ); + if (pStyleSheetPropertyMap) + pStyleSheetPropertyMap->SetListLevel( static_cast<sal_Int16>(nIntValue) ); + } + // 0-8 are the 9 levels that Microsoft supports. (LO supports 10 levels). + // 9 indicates "no numbering", for which LO has no corresponding concept, + // and so it will be treated as the 10th level. + // finishParagraph() will convert the 9 into "no numbering" for direct formatting. + // (Styles only use this PROP for round-tripping and UI, but cannot trust it for import) + if (!IsStyleSheetImport() || nIntValue != 9) + rContext->Insert(PROP_NUMBERING_LEVEL, uno::Any(static_cast<sal_Int16>(nIntValue))); + break; + case NS_ooxml::LN_CT_NumPr_numId: + { + //convert the ListTable entry to a NumberingRules property and apply it + ListsManager::Pointer pListTable = m_pImpl->GetListTable(); + ListDef::Pointer pList = pListTable->GetList( nIntValue ); + if( IsStyleSheetImport() ) + { + //style sheets cannot have a numbering rule attached + StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() ); + if (pStyleSheetPropertyMap) + pStyleSheetPropertyMap->SetListId( nIntValue ); + } + if( pList ) + { + if( !IsStyleSheetImport() ) + { + uno::Any aRules( pList->GetNumberingRules( ) ); + rContext->Insert( PROP_NUMBERING_RULES, aRules ); + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if (pContext) + { + assert(dynamic_cast<ParagraphPropertyMap*>(pContext.get())); + static_cast<ParagraphPropertyMap*>(pContext.get())->SetListId(pList->GetId()); + } + + // Indentation can came from: + // 1) Paragraph style's numbering's indentation: the current non-style numId has priority over it. + // 2) Numbering's indentation: Writer handles that natively, so it should not be set on rContext. + // 3) Paragraph style's indentation: ditto. + // 4) Direct paragraph formatting: that will came later. + // So no situation where keeping indentation at this point would make sense -> erase. + rContext->Erase(PROP_PARA_FIRST_LINE_INDENT); + rContext->Erase(PROP_PARA_LEFT_MARGIN); + rContext->Erase(PROP_PARA_RIGHT_MARGIN); + } + } + else + { + if( !IsStyleSheetImport() ) + { + // eg. disabled numbering using non-existent numId "0" + rContext->Insert( PROP_NUMBERING_STYLE_NAME, uno::Any( OUString() ) ); + // disable inheritance of indentation of parent styles + rContext->Insert( PROP_PARA_LEFT_MARGIN, uno::Any( sal_Int32(0) ), /*bOverwrite=*/false); + rContext->Insert( PROP_PARA_FIRST_LINE_INDENT, + uno::Any( sal_Int32(0) ), /*bOverwrite=*/false); + } + } + } + break; + case NS_ooxml::LN_CT_PPrBase_suppressLineNumbers: + rContext->Insert(PROP_PARA_LINE_NUMBER_COUNT, uno::Any( nIntValue == 0 ) ); + break; + case NS_ooxml::LN_inTbl: + break; + case NS_ooxml::LN_tblDepth: + //not handled via sprm but via text( 0x07 ) + break; + case NS_ooxml::LN_CT_FramePr_w: + break; + case NS_ooxml::LN_CT_FramePr_wrap: + break; + + case NS_ooxml::LN_CT_PrBase_pBdr: //paragraph border + resolveSprmProps(*this, rSprm); + break; + case NS_ooxml::LN_CT_PBdr_top: + case NS_ooxml::LN_CT_PBdr_left: + case NS_ooxml::LN_CT_PBdr_bottom: + case NS_ooxml::LN_CT_PBdr_right: + case NS_ooxml::LN_CT_PBdr_between: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + auto pBorderHandler = std::make_shared<BorderHandler>( true ); + pProperties->resolve(*pBorderHandler); + PropertyIds eBorderId = PropertyIds( 0 ); + PropertyIds eBorderDistId = PropertyIds( 0 ); + switch( nSprmId ) + { + case NS_ooxml::LN_CT_PBdr_top: + eBorderId = PROP_TOP_BORDER; + eBorderDistId = PROP_TOP_BORDER_DISTANCE; + break; + case NS_ooxml::LN_CT_PBdr_left: + eBorderId = PROP_LEFT_BORDER; + eBorderDistId = PROP_LEFT_BORDER_DISTANCE; + break; + case NS_ooxml::LN_CT_PBdr_bottom: + eBorderId = PROP_BOTTOM_BORDER ; + eBorderDistId = PROP_BOTTOM_BORDER_DISTANCE; + break; + case NS_ooxml::LN_CT_PBdr_right: + eBorderId = PROP_RIGHT_BORDER; + eBorderDistId = PROP_RIGHT_BORDER_DISTANCE ; + break; + case NS_ooxml::LN_CT_PBdr_between: + if (m_pImpl->handlePreviousParagraphBorderInBetween()) + { + // If previous paragraph also had border in between property + // then it is possible to emulate this border as top border + // for current paragraph + eBorderId = PROP_TOP_BORDER; + eBorderDistId = PROP_TOP_BORDER_DISTANCE; + } + // Since there are borders in between, each paragraph will have own borders. No more joining + rContext->Insert(PROP_PARA_CONNECT_BORDERS, uno::Any(false)); + break; + default:; + } + if( eBorderId ) + rContext->Insert( eBorderId, uno::Any( pBorderHandler->getBorderLine()) ); + if(eBorderDistId) + rContext->Insert(eBorderDistId, uno::Any( pBorderHandler->getLineDistance())); + if ( nSprmId == NS_ooxml::LN_CT_PBdr_right ) + { + table::ShadowFormat aFormat; + // Word only allows shadows on visible borders + if ( pBorderHandler->getShadow() && pBorderHandler->getBorderLine().LineStyle != table::BorderLineStyle::NONE ) + aFormat = writerfilter::dmapper::PropertyMap::getShadowFromBorder(pBorderHandler->getBorderLine()); + rContext->Insert(PROP_PARA_SHADOW_FORMAT, uno::Any(aFormat)); + } + } + } + break; + case NS_ooxml::LN_CT_PBdr_bar: + break; + case NS_ooxml::LN_CT_PPrBase_suppressAutoHyphens: + rContext->Insert(PROP_PARA_IS_HYPHENATION, uno::Any( nIntValue == 0 )); + break; + case NS_ooxml::LN_CT_FramePr_h: + break; + case NS_ooxml::LN_CT_PrBase_shd: + { + //contains fore color, back color and shadow percentage, results in a brush + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + auto pCellColorHandler = std::make_shared<CellColorHandler>(); + pCellColorHandler->setOutputFormat( CellColorHandler::Paragraph ); + bool bEnableTempGrabBag = !pCellColorHandler->isInteropGrabBagEnabled(); + if( bEnableTempGrabBag ) + pCellColorHandler->enableInteropGrabBag( "TempShdPropsGrabBag" ); + + pProperties->resolve(*pCellColorHandler); + rContext->InsertProps(pCellColorHandler->getProperties().get()); + + rContext->Insert(PROP_CHAR_THEME_FILL, pCellColorHandler->getInteropGrabBag().Value, true, PARA_GRAB_BAG); + if(bEnableTempGrabBag) + pCellColorHandler->disableInteropGrabBag(); + } + } + break; + case NS_ooxml::LN_CT_FramePr_vSpace: + break; // sprmPDyaFromText + case NS_ooxml::LN_CT_FramePr_hSpace: + break; // sprmPDxaFromText + case NS_ooxml::LN_CT_FramePr_anchorLock: + break; + case NS_ooxml::LN_CT_PPrBase_widowControl: + { + uno::Any aVal( uno::Any( sal_Int8(nIntValue ? 2 : 0 ))); + rContext->Insert( PROP_PARA_WIDOWS, aVal ); + rContext->Insert( PROP_PARA_ORPHANS, aVal ); + } + break; // sprmPFWidowControl + case NS_ooxml::LN_CT_PPrBase_overflowPunct: + rContext->Insert(PROP_PARA_IS_HANGING_PUNCTUATION, uno::Any( nIntValue == 0 )); + break; + case NS_ooxml::LN_CT_PPrBase_topLinePunct: + break; + case NS_ooxml::LN_CT_PPrBase_autoSpaceDE: + break; + case NS_ooxml::LN_CT_PPrBase_autoSpaceDN: + break; + case NS_ooxml::LN_CT_PPrBase_textAlignment: + { + sal_Int16 nAlignment = 0; + switch (nIntValue) + { + case NS_ooxml::LN_Value_doc_ST_TextAlignment_top: + nAlignment = 2; + break; + case NS_ooxml::LN_Value_doc_ST_TextAlignment_center: + nAlignment = 3; + break; + case NS_ooxml::LN_Value_doc_ST_TextAlignment_baseline: + nAlignment = 1; + break; + case NS_ooxml::LN_Value_doc_ST_TextAlignment_bottom: + nAlignment = 4; + break; + case NS_ooxml::LN_Value_doc_ST_TextAlignment_auto: + default: + break; + } + rContext->Insert( PROP_PARA_VERT_ALIGNMENT, uno::Any( nAlignment) ); + } + break; + case NS_ooxml::LN_CT_PPrBase_textDirection: + { + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_TextDirection_tbRl: + { + m_pImpl->SetFrameDirection(text::WritingMode2::TB_RL); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_btLr: + { + m_pImpl->SetFrameDirection(text::WritingMode2::BT_LR); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_lrTbV: + { + m_pImpl->SetFrameDirection(text::WritingMode2::LR_TB); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_tbRlV: + { + m_pImpl->SetFrameDirection(text::WritingMode2::TB_RL); + break; + } + case NS_ooxml::LN_Value_ST_TextDirection_lrTb: + case NS_ooxml::LN_Value_ST_TextDirection_tbLrV: + default: + SAL_WARN("writerfilter", "DomainMapper::sprmWithProps: unhandled textDirection"); + } + } + break; + case NS_ooxml::LN_CT_PPrBase_outlineLvl: + { + if (nIntValue < WW_OUTLINE_MIN || nIntValue > WW_OUTLINE_MAX) + break; // invalid value is ignored by MS Word + + if( IsStyleSheetImport() ) + { + StyleSheetPropertyMap* pStyleSheetPropertyMap = dynamic_cast< StyleSheetPropertyMap* >( rContext.get() ); + if (pStyleSheetPropertyMap) + pStyleSheetPropertyMap->SetOutlineLevel(nIntValue); + } + else + { + // convert MS body level (9) to LO body level (0) and equivalent outline levels + sal_Int16 nLvl = nIntValue == WW_OUTLINE_MAX ? 0 : nIntValue + 1; + rContext->Insert(PROP_OUTLINE_LEVEL, uno::Any ( nLvl )); + } + } + break; + case NS_ooxml::LN_CT_PPrBase_bidi: + { + // Four situations to handle: + // 1.) bidi same as previous setting: no adjust change + // 2.) no previous adjust: set appropriate default for this bidi + // 3.) previous adjust and bidi different from previous: swap adjusts + // 4.) previous adjust and no previous bidi: RTL swaps adjust + + const sal_Int16 nWritingMode = nIntValue ? text::WritingMode2::RL_TB : text::WritingMode2::LR_TB; + sal_Int16 nParentBidi = -1; + m_pImpl->GetPropertyFromParaStyleSheet(PROP_WRITING_MODE) >>= nParentBidi; + // Paragraph justification reverses its meaning in an RTL context. + // 1. Only make adjustments if the BiDi changes. + if ( nParentBidi != nWritingMode && !IsRTFImport() ) + { + style::ParagraphAdjust eAdjust = style::ParagraphAdjust(-1); + // 2. no adjust property exists yet + if ( !(m_pImpl->GetAnyProperty(PROP_PARA_ADJUST, rContext) >>= eAdjust) ) + { + // RTL defaults to right adjust + eAdjust = nIntValue ? style::ParagraphAdjust_RIGHT : style::ParagraphAdjust_LEFT; + rContext->Insert(PROP_PARA_ADJUST, uno::Any( eAdjust ), /*bOverwrite=*/false); + } + // 3,4. existing adjust: if RTL, then swap. If LTR, but previous was RTL, also swap. + else if ( nIntValue || nParentBidi == sal_Int16(text::WritingMode2::RL_TB) ) + { + if ( eAdjust == style::ParagraphAdjust_RIGHT ) + rContext->Insert(PROP_PARA_ADJUST, uno::Any( style::ParagraphAdjust_LEFT )); + else if ( eAdjust == style::ParagraphAdjust_LEFT ) + rContext->Insert(PROP_PARA_ADJUST, uno::Any( style::ParagraphAdjust_RIGHT )); + } + } + rContext->Insert(PROP_WRITING_MODE, uno::Any( nWritingMode )); + } + + break; + case NS_ooxml::LN_EG_SectPrContents_bidi: + if (pSectionContext != nullptr) + { + const sal_Int16 writingMode = (nIntValue != 0) ? sal_Int16(text::WritingMode2::RL_TB) : sal_Int16(text::WritingMode2::LR_TB); + pSectionContext->Insert(PROP_WRITING_MODE, uno::Any(writingMode)); + } + break; + case NS_ooxml::LN_EG_SectPrContents_rtlGutter: + if (pSectionContext != nullptr) + { + bool bRtlGutter = nIntValue != 0; + pSectionContext->Insert(PROP_RTL_GUTTER, uno::Any(bRtlGutter)); + } + break; + case NS_ooxml::LN_EG_RPrBase_highlight: + { + // MS Word completely ignores character highlighting in character styles. + if ( IsStyleSheetImport() ) + { + const StyleSheetEntryPtr pCurrStyle = GetStyleSheetTable()->GetCurrentEntry(); + if ( pCurrStyle && pCurrStyle->nStyleTypeCode == STYLE_TYPE_CHAR ) + break; + } + + // OOXML import uses an ID + if( IsOOXMLImport() ) + { + sal_Int32 nColor = 0; + if( getColorFromId(nIntValue, nColor) ) + rContext->Insert(PROP_CHAR_HIGHLIGHT, uno::Any( nColor )); + } + // RTF import uses the actual color value + else if( IsRTFImport() ) + { + rContext->Insert(PROP_CHAR_HIGHLIGHT, uno::Any( nIntValue )); + } + } + break; + case NS_ooxml::LN_EG_RPrBase_em: + rContext->Insert(PROP_CHAR_EMPHASIS, uno::Any ( getEmphasisValue (nIntValue))); + break; + case NS_ooxml::LN_EG_RPrBase_emboss: + case NS_ooxml::LN_EG_RPrBase_b: + case NS_ooxml::LN_EG_RPrBase_bCs: + case NS_ooxml::LN_EG_RPrBase_i: + case NS_ooxml::LN_EG_RPrBase_iCs: + case NS_ooxml::LN_EG_RPrBase_strike: + case NS_ooxml::LN_EG_RPrBase_dstrike: + case NS_ooxml::LN_EG_RPrBase_outline: + case NS_ooxml::LN_EG_RPrBase_shadow: + case NS_ooxml::LN_EG_RPrBase_caps: + case NS_ooxml::LN_EG_RPrBase_smallCaps: + case NS_ooxml::LN_EG_RPrBase_vanish: + case NS_ooxml::LN_EG_RPrBase_webHidden: + { + PropertyIds ePropertyId = PROP_CHAR_WEIGHT; //initialized to prevent warning! + switch( nSprmId ) + { + case NS_ooxml::LN_EG_RPrBase_b: + case NS_ooxml::LN_EG_RPrBase_bCs: + ePropertyId = nSprmId != NS_ooxml::LN_EG_RPrBase_bCs ? PROP_CHAR_WEIGHT : PROP_CHAR_WEIGHT_COMPLEX; + break; + case NS_ooxml::LN_EG_RPrBase_i: + case NS_ooxml::LN_EG_RPrBase_iCs: + ePropertyId = nSprmId == NS_ooxml::LN_EG_RPrBase_i ? PROP_CHAR_POSTURE : PROP_CHAR_POSTURE_COMPLEX; + break; + case NS_ooxml::LN_EG_RPrBase_strike: + case NS_ooxml::LN_EG_RPrBase_dstrike: + ePropertyId = PROP_CHAR_STRIKEOUT; + break; + case NS_ooxml::LN_EG_RPrBase_outline: + ePropertyId = PROP_CHAR_CONTOURED; + break; + case NS_ooxml::LN_EG_RPrBase_shadow: + ePropertyId = PROP_CHAR_SHADOWED; + break; + case NS_ooxml::LN_EG_RPrBase_caps: + case NS_ooxml::LN_EG_RPrBase_smallCaps: + ePropertyId = PROP_CHAR_CASE_MAP; + break; + case NS_ooxml::LN_EG_RPrBase_vanish: + case NS_ooxml::LN_EG_RPrBase_webHidden: + ePropertyId = PROP_CHAR_HIDDEN; + break; + case NS_ooxml::LN_EG_RPrBase_emboss: + ePropertyId = PROP_CHAR_RELIEF; + break; + } + //expected: 0,1,128,129 + if(nIntValue != 128) //inherited from paragraph - ignore + { + if( nIntValue == 129) //inverted style sheet value + { + //get value from style sheet and invert it + sal_Int16 nStyleValue = 0; + uno::Any aStyleVal = m_pImpl->GetPropertyFromParaStyleSheet(ePropertyId); + if( !aStyleVal.hasValue() ) + { + nIntValue = NS_ooxml::LN_EG_RPrBase_smallCaps == nSprmId ? + 4 : 1; + } + else if(aStyleVal.getValueTypeClass() == uno::TypeClass_FLOAT ) + { + double fDoubleValue = 0; + //only in case of awt::FontWeight + aStyleVal >>= fDoubleValue; + nIntValue = fDoubleValue > 100. ? 0 : 1; + } + else if((aStyleVal >>= nStyleValue) || + (nStyleValue = static_cast<sal_Int16>(comphelper::getEnumAsINT32(aStyleVal))) >= 0 ) + { + nIntValue = NS_ooxml::LN_EG_RPrBase_smallCaps == nSprmId ? + nStyleValue ? 0 : 4 : + nStyleValue ? 0 : 1; + } + else + { + OSL_FAIL( "what type was it"); + } + } + + switch( nSprmId ) + { + case NS_ooxml::LN_EG_RPrBase_b: + case NS_ooxml::LN_EG_RPrBase_bCs: + { + uno::Any aBold( uno::Any( nIntValue ? awt::FontWeight::BOLD : awt::FontWeight::NORMAL ) ); + + rContext->Insert(ePropertyId, aBold ); + if( nSprmId != NS_ooxml::LN_EG_RPrBase_bCs ) + rContext->Insert(PROP_CHAR_WEIGHT_ASIAN, aBold ); + + if (nSprmId == NS_ooxml::LN_EG_RPrBase_b) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "b", OUString::number(nIntValue)); + else if (nSprmId == NS_ooxml::LN_EG_RPrBase_bCs) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "bCs", OUString::number(nIntValue)); + } + break; + case NS_ooxml::LN_EG_RPrBase_i: + case NS_ooxml::LN_EG_RPrBase_iCs: + { + uno::Any aPosture( uno::Any( nIntValue ? awt::FontSlant_ITALIC : awt::FontSlant_NONE ) ); + rContext->Insert( ePropertyId, aPosture ); + if (nSprmId != NS_ooxml::LN_EG_RPrBase_iCs) + rContext->Insert(PROP_CHAR_POSTURE_ASIAN, aPosture ); + if (nSprmId == NS_ooxml::LN_EG_RPrBase_i) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "i", OUString::number(nIntValue)); + } + break; + case NS_ooxml::LN_EG_RPrBase_strike: + rContext->Insert(ePropertyId, + uno::Any( nIntValue ? awt::FontStrikeout::SINGLE : awt::FontStrikeout::NONE ) ); + break; + case NS_ooxml::LN_EG_RPrBase_dstrike: + rContext->Insert(ePropertyId, + uno::Any( nIntValue ? awt::FontStrikeout::DOUBLE : awt::FontStrikeout::NONE ) ); + break; + case NS_ooxml::LN_EG_RPrBase_outline: + case NS_ooxml::LN_EG_RPrBase_shadow: + case NS_ooxml::LN_EG_RPrBase_vanish: + case NS_ooxml::LN_EG_RPrBase_webHidden: + rContext->Insert(ePropertyId, uno::Any( nIntValue != 0 )); + break; + case NS_ooxml::LN_EG_RPrBase_smallCaps: + // If smallcaps would be just disabled and another casemap is already inserted, don't do anything. + if (nIntValue || !rContext->isSet(ePropertyId) ) + rContext->Insert(ePropertyId, uno::Any( nIntValue ? style::CaseMap::SMALLCAPS : style::CaseMap::NONE)); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "smallCaps", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_EG_RPrBase_caps: + rContext->Insert(ePropertyId, + uno::Any( nIntValue ? style::CaseMap::UPPERCASE : style::CaseMap::NONE)); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "caps", OUString::number(nIntValue)); + break; + case NS_ooxml::LN_EG_RPrBase_emboss: + rContext->Insert(ePropertyId, + uno::Any( nIntValue ? awt::FontRelief::EMBOSSED : awt::FontRelief::NONE )); + break; + + } + } + } + break; + case NS_ooxml::LN_EG_RPrBase_sz: + case NS_ooxml::LN_EG_RPrBase_szCs: + { + //multiples of half points (12pt == 24) + double fVal = double(nIntValue) / 2.; + uno::Any aVal( fVal ); + if( NS_ooxml::LN_EG_RPrBase_szCs == nSprmId ) + { + rContext->Insert( PROP_CHAR_HEIGHT_COMPLEX, aVal ); + } + else + { + const RubyInfo &aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt && aInfo.nHps > 0 ) + { + fVal = double(aInfo.nHps) / 2.; + aVal <<= fVal; + } + else if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase && aInfo.nHpsBaseText > 0 ) + { + fVal = double(aInfo.nHpsBaseText) / 2.; + aVal <<= fVal; + } + //Asian get the same value as Western + rContext->Insert( PROP_CHAR_HEIGHT, aVal ); + rContext->Insert( PROP_CHAR_HEIGHT_ASIAN, aVal ); + } + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, (nSprmId == NS_ooxml::LN_EG_RPrBase_sz ? OUString("sz") : OUString("szCs")), OUString::number(nIntValue)); + } + break; + case NS_ooxml::LN_EG_RPrBase_position: + // The spec says 0 is the same as the lack of the value, so don't parse that. + if ( nIntValue ) + { + if (!IsStyleSheetImport() && !IsNumberingImport()) + m_pImpl->deferCharacterProperty( nSprmId, uno::Any( nIntValue )); + else if (!m_pImpl->IsDocDefaultsImport()) + { + // For some undocumented reason, MS Word seems to ignore this in docDefaults + + // DON'T FIXME: Truly calculating this for Character Styles will be tricky, + // because it depends on the final fontsize - regardless of + // where it is set. So at the style level, + // the escapement value would need to be grabbagged. + // At appendText time the final fontsize needs to be determined, and then + // the escapement can be calculated from the grabbag'd half-point value + // and directly applied. Yuck. + // It seems best to just treat charstyle escapement like + // pre-commit e70df84352d3670508a4666c97df44f82c1ce934 + // which just assigned default values and ignored the actual/given escapement. + sal_Int16 nEscapement = nIntValue > 0 ? DFLT_ESC_AUTO_SUPER : DFLT_ESC_AUTO_SUB; + sal_Int8 nProp = DFLT_ESC_PROP; + rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::Any( nEscapement ) ); + rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::Any( nProp ) ); + } + } + break; + case NS_ooxml::LN_EG_RPrBase_spacing: + { + //Kerning half point values + //TODO: there are two kerning values - + // in ww8par6.cxx NS_sprm::LN_CHpsKern is used as boolean AutoKerning + sal_Int16 nResult = static_cast<sal_Int16>(ConversionHelper::convertTwipToMM100(nIntValue)); + if (m_pImpl->IsInComments()) + { + nResult = static_cast<sal_Int16>(nIntValue); + } + rContext->Insert(PROP_CHAR_CHAR_KERNING, uno::Any(nResult)); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "spacing", OUString::number(nIntValue)); + } + break; + case NS_ooxml::LN_EG_RPrBase_kern: // auto kerning is bound to a minimum font size in Word - but not in Writer :-( + rContext->Insert(PROP_CHAR_AUTO_KERNING, uno::Any( nIntValue != 0 ) ); + break; + case NS_ooxml::LN_EG_RPrBase_w: + // ST_TextScale must fall between 1% and 600% according to spec, otherwise resets to 100% according to experience + if ((1 <= nIntValue) && (nIntValue <= 600)) + { + rContext->Insert(PROP_CHAR_SCALE_WIDTH, + uno::Any( sal_Int16(nIntValue) )); + } + else + { + rContext->Insert(PROP_CHAR_SCALE_WIDTH, + uno::Any( sal_Int16(100) )); + } + break; + case NS_ooxml::LN_EG_RPrBase_imprint: + // FontRelief: NONE, EMBOSSED, ENGRAVED + rContext->Insert(PROP_CHAR_RELIEF, + uno::Any( nIntValue ? awt::FontRelief::ENGRAVED : awt::FontRelief::NONE )); + break; + case NS_ooxml::LN_EG_RPrBase_effect: + // The file-format has many character animations. We have only + // one, so we use it always. Suboptimal solution though. + if (nIntValue != NS_ooxml::LN_Value_ST_TextEffect_none) + rContext->Insert(PROP_CHAR_FLASH, uno::Any( true )); + else + rContext->Insert(PROP_CHAR_FLASH, uno::Any( false )); + break; + case NS_ooxml::LN_EG_RPrBase_rtl: + break; + case NS_ooxml::LN_EG_RPrBase_shd: + { + //contains fore color, back color and shadow percentage, results in a brush + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + auto pCellColorHandler = std::make_shared<CellColorHandler>(); + pCellColorHandler->setOutputFormat( CellColorHandler::Character ); + pProperties->resolve(*pCellColorHandler); + rContext->InsertProps(pCellColorHandler->getProperties().get()); + m_pImpl->GetTopContext()->Insert(PROP_CHAR_SHADING_MARKER, uno::Any(true), true, CHAR_GRAB_BAG ); + } + break; + } + case NS_ooxml::LN_EG_SectPrContents_type: + /* break type + 0 - No break + 1 - New Column + 2 - New page + 3 - Even page + 4 - odd page + */ + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + //continuous break only allowed if it is not the only section break + SectionPropertyMap* pLastContext = m_pImpl->GetLastSectionContext(); + if ( nIntValue != NS_ooxml::LN_Value_ST_SectionMark_continuous || pLastContext || m_pImpl->GetParaSectpr() ) + pSectionContext->SetBreakType( nIntValue ); + } + break; + case NS_ooxml::LN_EG_SectPrContents_titlePg: + { + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + pSectionContext->SetTitlePage( nIntValue > 0 );//section has title page + } + break; + case 165: + { + //page height, rounded to default values, default: 0x3dc0 twip + sal_Int32 nHeight = ConversionHelper::convertTwipToMM100( nIntValue ); + rContext->Insert( PROP_HEIGHT, uno::Any( PaperInfo::sloppyFitPageDimension( nHeight ) ) ); + } + break; + case NS_ooxml::LN_EG_SectPrContents_textDirection: + { + /* 0 HoriLR 1 Vert TR 2 Vert TR 3 Vert TT 4 HoriLT + only 0 and 1 can be imported correctly + */ + text::WritingMode nDirection = text::WritingMode_LR_TB; + switch( nIntValue ) + { + case NS_ooxml::LN_Value_ST_TextDirection_lrTb: + case NS_ooxml::LN_Value_ST_TextDirection_lrTbV: + nDirection = text::WritingMode_LR_TB; + break; + case NS_ooxml::LN_Value_ST_TextDirection_tbRl: + case NS_ooxml::LN_Value_ST_TextDirection_btLr: + nDirection = text::WritingMode_TB_RL; + break; + default:; + } + + PropertyMap * pTargetContext = rContext.get(); + + if (pSectionContext) + { + pTargetContext = pSectionContext; + } + + pTargetContext->Insert(PROP_WRITING_MODE, uno::Any( sal_Int16(nDirection) ) ); + } + break; // sprmSTextFlow + // the following are not part of the official documentation + case NS_ooxml::LN_CT_Tabs_tab: + resolveSprmProps(*this, rSprm); + m_pImpl->IncorporateTabStop(m_pImpl->m_aCurrentTabStop); + m_pImpl->m_aCurrentTabStop = DeletableTabStop(); + break; + case NS_ooxml::LN_CT_PPrBase_tabs: + { + // Initialize tab stop vector from style sheet + // fdo#81033: for RTF, a tab stop is inherited from the style if it + // is also applied to the paragraph directly, and cleared if it is + // not applied to the paragraph directly => don't InitTabStopFromStyle + if ( !IsRTFImport() ) + { + uno::Any aValue = m_pImpl->GetPropertyFromParaStyleSheet(PROP_PARA_TAB_STOPS); + uno::Sequence< style::TabStop > aStyleTabStops; + if(aValue >>= aStyleTabStops) + { + m_pImpl->InitTabStopFromStyle( aStyleTabStops ); + } + } + resolveSprmProps(*this, rSprm); + rContext->Insert(PROP_PARA_TAB_STOPS, uno::Any( m_pImpl->GetCurrentTabStopAndClear())); + } + break; + + case NS_ooxml::LN_CT_DocDefaults_pPrDefault: + case NS_ooxml::LN_CT_DocDefaults_rPrDefault: + GetStyleSheetTable()->sprm( rSprm ); + break; + case NS_ooxml::LN_EG_RPrBase_bdr: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + auto pBorderHandler = std::make_shared<BorderHandler>( true ); + pProperties->resolve(*pBorderHandler); + + rContext->Insert( PROP_CHAR_TOP_BORDER, uno::Any( pBorderHandler->getBorderLine())); + rContext->Insert( PROP_CHAR_BOTTOM_BORDER, uno::Any( pBorderHandler->getBorderLine())); + rContext->Insert( PROP_CHAR_LEFT_BORDER, uno::Any( pBorderHandler->getBorderLine())); + rContext->Insert( PROP_CHAR_RIGHT_BORDER, uno::Any( pBorderHandler->getBorderLine())); + + rContext->Insert( PROP_CHAR_TOP_BORDER_DISTANCE, uno::Any( pBorderHandler->getLineDistance())); + rContext->Insert( PROP_CHAR_BOTTOM_BORDER_DISTANCE, uno::Any( pBorderHandler->getLineDistance())); + rContext->Insert( PROP_CHAR_LEFT_BORDER_DISTANCE, uno::Any( pBorderHandler->getLineDistance())); + rContext->Insert( PROP_CHAR_RIGHT_BORDER_DISTANCE, uno::Any( pBorderHandler->getLineDistance())); + + table::ShadowFormat aFormat; + // Word only allows shadows on visible borders + if ( pBorderHandler->getShadow() && pBorderHandler->getBorderLine().LineStyle != table::BorderLineStyle::NONE ) + aFormat = writerfilter::dmapper::PropertyMap::getShadowFromBorder(pBorderHandler->getBorderLine()); + rContext->Insert(PROP_CHAR_SHADOW_FORMAT, uno::Any(aFormat)); + } + } + break; + case NS_ooxml::LN_CT_PPr_sectPr: + case NS_ooxml::LN_EG_RPrBase_color: + case NS_ooxml::LN_EG_RPrBase_rFonts: + case NS_ooxml::LN_EG_RPrBase_eastAsianLayout: + case NS_ooxml::LN_EG_RPrBase_u: + case NS_ooxml::LN_EG_RPrBase_lang: + case NS_ooxml::LN_CT_PPrBase_spacing: + case NS_ooxml::LN_CT_PPrBase_ind: + case NS_ooxml::LN_CT_RPrDefault_rPr: + case NS_ooxml::LN_CT_PPrDefault_pPr: + case NS_ooxml::LN_CT_Style_pPr: + case NS_ooxml::LN_CT_Style_rPr: + case NS_ooxml::LN_CT_PPr_rPr: + case NS_ooxml::LN_CT_PPrBase_numPr: + { + bool bTempGrabBag = !m_pImpl->isInteropGrabBagEnabled(); + if (nSprmId == NS_ooxml::LN_CT_PPr_sectPr) + m_pImpl->SetParaSectpr(true); + else if (nSprmId == NS_ooxml::LN_EG_RPrBase_color && bTempGrabBag) + // if DomainMapper grab bag is not enabled, enable it temporarily + m_pImpl->enableInteropGrabBag("TempColorPropsGrabBag"); + resolveSprmProps(*this, rSprm); + if (nSprmId == NS_ooxml::LN_CT_PPrBase_spacing) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "spacing", m_pImpl->m_aSubInteropGrabBag); + else if (nSprmId == NS_ooxml::LN_EG_RPrBase_rFonts) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "rFonts", m_pImpl->m_aSubInteropGrabBag); + else if (nSprmId == NS_ooxml::LN_EG_RPrBase_lang) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "lang", m_pImpl->m_aSubInteropGrabBag); + else if (nSprmId == NS_ooxml::LN_EG_RPrBase_color) + { + for (const auto& rItem : m_pImpl->m_aSubInteropGrabBag) + { + if (rItem.Name == "val") + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_ORIGINAL_COLOR, rItem.Value, true, CHAR_GRAB_BAG); + else if (rItem.Name == "themeColor") + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR, rItem.Value, true, CHAR_GRAB_BAG); + else if (rItem.Name == "themeShade") + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR_SHADE, rItem.Value, true, CHAR_GRAB_BAG); + else if (rItem.Name == "themeTint") + m_pImpl->GetTopContext()->Insert(PROP_CHAR_THEME_COLOR_TINT, rItem.Value, true, CHAR_GRAB_BAG); + } + if (bTempGrabBag) + //disable and clear DomainMapper grab bag if it wasn't enabled before + m_pImpl->disableInteropGrabBag(); + + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "color", m_pImpl->m_aSubInteropGrabBag); + } + else if (nSprmId == NS_ooxml::LN_CT_PPrBase_ind) + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ind", m_pImpl->m_aSubInteropGrabBag); + } + break; + case NS_ooxml::LN_CT_PPrBase_wordWrap: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "wordWrap", ""); + break; + case NS_ooxml::LN_EG_SectPrContents_footnotePr: + case NS_ooxml::LN_EG_SectPrContents_endnotePr: + m_pImpl->SetInFootnoteProperties( NS_ooxml::LN_EG_SectPrContents_footnotePr == nSprmId ); + resolveSprmProps(*this, rSprm); + break; + case NS_ooxml::LN_EG_SectPrContents_lnNumType: + { + resolveSprmProps(*this, rSprm); + LineNumberSettings aSettings = m_pImpl->GetLineNumberSettings(); + m_pImpl->SetLineNumberSettings( aSettings ); + //apply settings at XLineNumberingProperties + try + { + uno::Reference< text::XLineNumberingProperties > xLineNumberingProperties( m_pImpl->GetTextDocument(), uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xLineNumberingPropSet = xLineNumberingProperties->getLineNumberingProperties(); + if( aSettings.nInterval == 0 ) + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_IS_ON ), uno::Any(false) ); + else + { + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_IS_ON ), uno::Any(true) ); + if( aSettings.nInterval ) + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_INTERVAL ), uno::Any(static_cast<sal_Int16>(aSettings.nInterval)) ); + if( aSettings.nDistance != -1 ) + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_DISTANCE ), uno::Any(aSettings.nDistance) ); + else + { + // set Auto value (0.5 cm) + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_DISTANCE ), uno::Any(static_cast<sal_Int32>(500)) ); + if( pSectionContext ) + pSectionContext->SetdxaLnn( static_cast<sal_Int32>(283) ); + } + xLineNumberingPropSet->setPropertyValue(getPropertyName( PROP_RESTART_AT_EACH_PAGE ), uno::Any(aSettings.bRestartAtEachPage) ); + } + } + catch( const uno::Exception& ) + { + } + + } + break; + case NS_ooxml::LN_CT_PPrBase_framePr: + // Avoid frames if we're inside a structured document tag, would just cause outer tables fail to create. + if (!m_pImpl->GetSdt()) + { + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if( pContext ) + { + // If there is a deferred page break applied to this framed paragraph, + // create a dummy paragraph without extra properties, + // so that the anchored frame will be on the correct page (similar to shapes). + if (pContext->isSet(PROP_BREAK_TYPE)) + { + pContext->Erase(PROP_BREAK_TYPE); + + lcl_startParagraphGroup(); + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + lcl_startCharacterGroup(); + sal_uInt8 const sBreak[] = { 0xd }; + lcl_text(sBreak, 1); + lcl_endCharacterGroup(); + lcl_endParagraphGroup(); + } + + ParagraphPropertyMap* pParaContext = dynamic_cast< ParagraphPropertyMap* >( pContext.get() ); + if (pParaContext) + pParaContext->SetFrameMode(); + + if (!IsInHeaderFooter()) + m_pImpl->m_bIsActualParagraphFramed = true; + } + else + { + //TODO: What about style sheet import of frame properties + } + m_pImpl->NewFrameDirection(); + resolveSprmProps(*this, rSprm); + } + break; + case NS_ooxml::LN_EG_SectPrContents_pgSz: + { + PaperInfo aLetter(PAPER_LETTER); + CT_PageSz.w = aLetter.getWidth(); + CT_PageSz.h = aLetter.getHeight(); + } + CT_PageSz.orient = false; + resolveSprmProps(*this, rSprm); + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + if (!m_pImpl->IsAltChunk()) + { + pSectionContext->Insert(PROP_HEIGHT, uno::Any(CT_PageSz.h)); + } + pSectionContext->Insert( PROP_IS_LANDSCAPE, uno::Any( CT_PageSz.orient )); + if (!m_pImpl->IsAltChunk()) + { + pSectionContext->Insert(PROP_WIDTH, uno::Any(CT_PageSz.w)); + } + } + break; + + case NS_ooxml::LN_EG_SectPrContents_pgMar: + m_pImpl->InitPageMargins(); + resolveSprmProps(*this, rSprm); + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + const PageMar& rPageMar = m_pImpl->GetPageMargins(); + pSectionContext->SetTopMargin( rPageMar.top ); + pSectionContext->SetRightMargin( rPageMar.right ); + pSectionContext->SetBottomMargin( rPageMar.bottom ); + pSectionContext->SetLeftMargin( rPageMar.left ); + pSectionContext->SetHeaderTop( rPageMar.header ); + pSectionContext->SetHeaderBottom( rPageMar.footer ); + pSectionContext->SetGutterMargin(rPageMar.gutter); + } + break; + + case NS_ooxml::LN_EG_SectPrContents_cols: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + + tools::SvRef< SectionColumnHandler > pSectHdl( new SectionColumnHandler ); + pProperties->resolve(*pSectHdl); + if(pSectionContext && !m_pImpl->isInIndexContext()) + { + sal_Int16 nColumnCount = pSectHdl->GetNum() == 1 ? 0 : pSectHdl->GetNum(); + if( pSectHdl->IsEqualWidth() ) + { + pSectionContext->SetEvenlySpaced( true ); + pSectionContext->SetColumnCount( nColumnCount ); + pSectionContext->SetColumnDistance( pSectHdl->GetSpace() ); + pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() ); + } + else if( !pSectHdl->GetColumns().empty() ) + { + pSectionContext->SetEvenlySpaced( false ); + pSectionContext->SetColumnDistance( pSectHdl->GetSpace() ); + nColumnCount = pSectHdl->GetColumns().size(); + pSectionContext->SetColumnCount( nColumnCount == 1 ? 0 : nColumnCount ); + std::vector<Column_>::const_iterator tmpIter = pSectHdl->GetColumns().begin(); + for (; tmpIter != pSectHdl->GetColumns().end(); ++tmpIter) + { + pSectionContext->AppendColumnWidth( tmpIter->nWidth ); + if ((tmpIter != pSectHdl->GetColumns().end() - 1) || (tmpIter->nSpace > 0)) + pSectionContext->AppendColumnSpacing( tmpIter->nSpace ); + } + pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() ); + } + else if( nColumnCount ) + { + pSectionContext->SetColumnCount( nColumnCount ); + pSectionContext->SetColumnDistance( pSectHdl->GetSpace() ); + pSectionContext->SetSeparatorLine( pSectHdl->IsSeparator() ); + } + } + + else if ( pSectionContext ) + { + FieldContextPtr pContext = m_pImpl->GetTopFieldContext(); + uno::Reference< beans::XPropertySet > xTOC = pContext->GetTOC(); + if( xTOC.is() ) + { + uno::Reference<text::XTextColumns> xTextColumns; + xTOC->getPropertyValue(getPropertyName( PROP_TEXT_COLUMNS )) >>= xTextColumns; + if (xTextColumns.is()) + { + uno::Reference< beans::XPropertySet > xColumnPropSet( xTextColumns, uno::UNO_QUERY_THROW ); + xColumnPropSet->setPropertyValue( getPropertyName( PROP_AUTOMATIC_DISTANCE ), uno::Any( pSectHdl->GetSpace() )); + xTOC->setPropertyValue( getPropertyName( PROP_TEXT_COLUMNS ), uno::Any( xTextColumns ) ); + } + } + } + } + } + break; + case NS_ooxml::LN_EG_SectPrContents_docGrid: + resolveSprmProps(*this, rSprm); + break; + case NS_ooxml::LN_EG_SectPrContents_pgBorders: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties && pSectionContext ) + { + tools::SvRef< PageBordersHandler > pHandler( new PageBordersHandler ); + pProperties->resolve( *pHandler ); + + // Set the borders to the context and apply them to the styles + pHandler->SetBorders( pSectionContext ); + } + } + break; + + case NS_ooxml::LN_CT_PPrBase_snapToGrid: + if (!IsStyleSheetImport()||!m_pImpl->isInteropGrabBagEnabled()) + { + rContext->Insert( PROP_SNAP_TO_GRID, uno::Any(bool(nIntValue))); + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "snapToGrid", OUString::number(nIntValue)); + } + break; + case NS_ooxml::LN_CT_PPrBase_pStyle: + { + StyleSheetTablePtr pStyleTable = m_pImpl->GetStyleSheetTable(); + const OUString sConvertedStyleName = pStyleTable->ConvertStyleName( sStringValue, true ); + m_pImpl->SetCurrentParaStyleName( sConvertedStyleName ); + if (m_pImpl->GetTopContext() && m_pImpl->GetTopContextType() != CONTEXT_SECTION) + m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::Any( sConvertedStyleName )); + } + break; + case NS_ooxml::LN_EG_RPrBase_rStyle: + { + OUString sConvertedName( m_pImpl->GetStyleSheetTable()->ConvertStyleName( sStringValue, true ) ); + if (m_pImpl->CheckFootnoteStyle() && m_pImpl->GetFootnoteContext()) + m_pImpl->SetHasFootnoteStyle(m_pImpl->GetFootnoteContext()->GetFootnoteStyle() == sConvertedName); + + // First check if the style exists in the document. + StyleSheetEntryPtr pEntry = m_pImpl->GetStyleSheetTable( )->FindStyleSheetByConvertedStyleName( sConvertedName ); + bool bExists = pEntry && ( pEntry->nStyleTypeCode == STYLE_TYPE_CHAR ); + // Add the property if the style exists, but do not add it elements in TOC: + // they will receive later another style references from TOC + if ( bExists && m_pImpl->GetTopContext() && !m_pImpl->IsInTOC()) + m_pImpl->GetTopContext()->Insert( PROP_CHAR_STYLE_NAME, uno::Any( sConvertedName ) ); + } + break; + case NS_ooxml::LN_CT_TblPrBase_tblCellMar: //cell margins + { + resolveSprmProps(*this, rSprm);//contains LN_CT_TblCellMar_top, LN_CT_TblCellMar_left, LN_CT_TblCellMar_bottom, LN_CT_TblCellMar_right + } + break; + case NS_ooxml::LN_CT_TblCellMar_top: + case NS_ooxml::LN_CT_TblCellMar_start: + case NS_ooxml::LN_CT_TblCellMar_left: + case NS_ooxml::LN_CT_TblCellMar_bottom: + case NS_ooxml::LN_CT_TblCellMar_end: + case NS_ooxml::LN_CT_TblCellMar_right: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + MeasureHandlerPtr pMeasureHandler( new MeasureHandler ); + pProperties->resolve(*pMeasureHandler); + sal_Int32 nMeasureValue = pMeasureHandler->getMeasureValue(); + PropertyIds eId = META_PROP_CELL_MAR_TOP; + bool rtl = false; // TODO + switch(nSprmId) + { + case NS_ooxml::LN_CT_TblCellMar_top: + break; + case NS_ooxml::LN_CT_TblCellMar_start: + eId = rtl ? META_PROP_CELL_MAR_RIGHT : META_PROP_CELL_MAR_LEFT; + break; + case NS_ooxml::LN_CT_TblCellMar_left: + eId = META_PROP_CELL_MAR_LEFT; + break; + case NS_ooxml::LN_CT_TblCellMar_bottom: + eId = META_PROP_CELL_MAR_BOTTOM; + break; + case NS_ooxml::LN_CT_TblCellMar_end: + eId = rtl ? META_PROP_CELL_MAR_LEFT : META_PROP_CELL_MAR_RIGHT; + break; + case NS_ooxml::LN_CT_TblCellMar_right: + eId = META_PROP_CELL_MAR_RIGHT; + break; + default:; + } + rContext->Insert( eId, uno::Any(nMeasureValue), false); + } + } + break; + case NS_ooxml::LN_EG_RPrBase_noProof: // no grammar and spell checking, unsupported + break; + case NS_ooxml::LN_anchor_anchor: // at_character drawing + case NS_ooxml::LN_inline_inline: // as_character drawing + { + if ( m_pImpl->IsDiscardHeaderFooter() ) + break; + //tdf112342: Break before images as well, if there are page break + if (m_pImpl->isBreakDeferred(BreakType::PAGE_BREAK)) + { + m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) + ->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + m_pImpl->clearDeferredBreak(PAGE_BREAK); + } + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + GraphicImportType eGraphicType = + (NS_ooxml::LN_anchor_anchor == + sal::static_int_cast<Id>(nSprmId)) ? + IMPORT_AS_DETECTED_ANCHOR : + IMPORT_AS_DETECTED_INLINE; + GraphicImportPtr pGraphicImport = + m_pImpl->GetGraphicImport(eGraphicType); + pProperties->resolve(*pGraphicImport); + m_pImpl->ImportGraphic(pProperties, eGraphicType); + if( !pGraphicImport->IsGraphic() ) + { + m_pImpl->ResetGraphicImport(); + // todo: It's a shape, now start shape import + } + } + } + break; + case NS_ooxml::LN_EG_RPrBase_vertAlign: + { + sal_Int16 nEscapement = 0; + sal_Int8 nProp = DFLT_ESC_PROP; + if ( sStringValue == "superscript" ) + nEscapement = DFLT_ESC_AUTO_SUPER; + else if ( sStringValue == "subscript" ) + nEscapement = DFLT_ESC_AUTO_SUB; + else + nProp = 100; + + rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::Any( nEscapement ) ); + rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::Any( nProp ) ); + } + break; + case NS_ooxml::LN_CT_FtnProps_pos: + //footnotes in word can be at page end or beneath text - writer supports only the first + //endnotes in word can be at section end or document end - writer supports only the latter + // -> so this property can be ignored + break; + case NS_ooxml::LN_CT_FtnProps_numFmt: + case NS_ooxml::LN_CT_EdnProps_numFmt: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + } + break; + case NS_ooxml::LN_EG_FtnEdnNumProps_numStart: + case NS_ooxml::LN_EG_FtnEdnNumProps_numRestart: + { + try + { + uno::Reference< beans::XPropertySet > xFtnEdnSettings; + if( m_pImpl->IsInFootnoteProperties() ) + { + uno::Reference< text::XFootnotesSupplier> xFootnotesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY ); + if (xFootnotesSupplier.is()) + xFtnEdnSettings = xFootnotesSupplier->getFootnoteSettings(); + } + else + { + uno::Reference< text::XEndnotesSupplier> xEndnotesSupplier( m_pImpl->GetTextDocument(), uno::UNO_QUERY ); + if (xEndnotesSupplier.is()) + xFtnEdnSettings = xEndnotesSupplier->getEndnoteSettings(); + } + if( NS_ooxml::LN_EG_FtnEdnNumProps_numStart == nSprmId && xFtnEdnSettings.is()) + { + xFtnEdnSettings->setPropertyValue( + getPropertyName( PROP_START_AT), + uno::Any( sal_Int16( nIntValue - 1 ))); + } + else if( NS_ooxml::LN_EG_FtnEdnNumProps_numRestart == nSprmId && xFtnEdnSettings.is()) + { + sal_Int16 nFootnoteCounting = 0; + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_RestartNumber_continuous: nFootnoteCounting = text::FootnoteNumbering::PER_DOCUMENT; break; + case NS_ooxml::LN_Value_ST_RestartNumber_eachPage: nFootnoteCounting = text::FootnoteNumbering::PER_PAGE; break; + case NS_ooxml::LN_Value_ST_RestartNumber_eachSect: nFootnoteCounting = text::FootnoteNumbering::PER_CHAPTER; break; + default: break; + } + xFtnEdnSettings->setPropertyValue( + getPropertyName( PROP_FOOTNOTE_COUNTING ), + uno::Any( nFootnoteCounting )); + } + else if (xFtnEdnSettings.is()) + { + sal_Int16 nNumType = ConversionHelper::ConvertNumberingType( nIntValue ); + xFtnEdnSettings->setPropertyValue( + getPropertyName( PROP_NUMBERING_TYPE), + uno::Any( nNumType )); + } + } + catch( const uno::Exception& ) + { + } + } + break; + case NS_ooxml::LN_EG_RangeMarkupElements_moveFromRangeStart: + m_pImpl->SetMoveBookmark(/*bIsFrom=*/true); + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().setMoved( getPropertyName(PROP_TABLE_ROW_DELETE) ); + break; + case NS_ooxml::LN_EG_RangeMarkupElements_moveToRangeStart: + m_pImpl->SetMoveBookmark(/*bIsFrom=*/false); + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().setMoved( getPropertyName(PROP_TABLE_ROW_INSERT) ); + break; + case NS_ooxml::LN_EG_RangeMarkupElements_moveFromRangeEnd: + case NS_ooxml::LN_EG_RangeMarkupElements_moveToRangeEnd: + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().setMoved( OUString() ); + break; + case NS_ooxml::LN_CT_ParaRPr_moveFrom: + case NS_ooxml::LN_CT_ParaRPr_moveTo: + m_pImpl->StartParaMarkerMove( ); + break; + case NS_ooxml::LN_paratrackchange: + m_pImpl->StartParaMarkerChange( ); + [[fallthrough]]; + case NS_ooxml::LN_CT_PPr_pPrChange: + case NS_ooxml::LN_CT_ParaRPr_rPrChange: + case NS_ooxml::LN_trackchange: + case NS_ooxml::LN_EG_RPrContent_rPrChange: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlDelRangeStart: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlDelRangeEnd: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveFromRangeStart: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveFromRangeEnd: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveToRangeStart: + case NS_ooxml::LN_EG_RangeMarkupElements_customXmlMoveToRangeEnd: + { + HandleRedline( rSprm ); + } + break; + case NS_ooxml::LN_endtrackchange: + m_pImpl->RemoveTopRedline(); + break; + case NS_ooxml::LN_CT_RPrChange_rPr: + { + // Push all the current 'Character' properties to the stack, so that we don't store them + // as 'tracked changes' by mistake + m_pImpl->PushProperties(CONTEXT_CHARACTER); + + // Resolve all the properties that are under the 'rPrChange'->'rPr' XML node + resolveSprmProps(*this, rSprm ); + + // Get all the properties that were processed in the 'rPrChange'->'rPr' XML node + uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues(); + + // Pop back out the character properties that were on the run + m_pImpl->PopProperties(CONTEXT_CHARACTER); + + // Store these properties in the current redline object (do it after the PopProperties() above, since + // otherwise it'd be stored in the content dropped there). + m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties ); + } + break; + case NS_ooxml::LN_CT_PPrChange_pPr: + { + // Push all the current 'Paragraph' properties to the stack, so that we don't store them + // as 'tracked changes' by mistake + m_pImpl->PushProperties(CONTEXT_PARAGRAPH); + + // Resolve all the properties that are under the 'pPrChange'->'pPr' XML node + resolveSprmProps(*this, rSprm ); + + // Get all the properties that were processed in the 'pPrChange'->'pPr' XML node + uno::Sequence< beans::PropertyValue > currentRedlineRevertProperties = m_pImpl->GetTopContext()->GetPropertyValues(); + + // Pop back out the character properties that were on the run + m_pImpl->PopProperties(CONTEXT_PARAGRAPH); + + // Store these properties in the current redline object (do it after the PopProperties() above, since + // otherwise it'd be stored in the content dropped there). + m_pImpl->SetCurrentRedlineRevertProperties( currentRedlineRevertProperties ); + } + break; + case NS_ooxml::LN_object: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + auto pOLEHandler = std::make_shared<OLEHandler>(*this); + pProperties->resolve(*pOLEHandler); + if ( pOLEHandler->isOLEObject( ) ) + { + OUString sStreamName = pOLEHandler->copyOLEOStream( m_pImpl->GetTextDocument() ); + if( !sStreamName.isEmpty() ) + { + m_pImpl->appendOLE( sStreamName, pOLEHandler ); + } + } + } + } + break; + case NS_ooxml::LN_EG_HdrFtrReferences_headerReference: // header reference - not needed + case NS_ooxml::LN_EG_HdrFtrReferences_footerReference: // footer reference - not needed + break; + case NS_ooxml::LN_EG_RPrBase_snapToGrid: // "Use document grid settings for inter-paragraph spacing" + break; + case NS_ooxml::LN_CT_PPrBase_contextualSpacing: + rContext->Insert(PROP_PARA_CONTEXT_MARGIN, uno::Any( nIntValue != 0 )); + break; + case NS_ooxml::LN_CT_PPrBase_mirrorIndents: // mirrorIndents + rContext->Insert(PROP_MIRROR_INDENTS, uno::Any( nIntValue != 0 ), true, PARA_GRAB_BAG); + break; + case NS_ooxml::LN_EG_SectPrContents_formProt: //section protection + { + if( pSectionContext ) + pSectionContext->Insert( PROP_IS_PROTECTED, uno::Any( bool(nIntValue) ) ); + } + break; + case NS_ooxml::LN_EG_SectPrContents_vAlign: + { + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if( pSectionContext ) + { + drawing::TextVerticalAdjust nVA = drawing::TextVerticalAdjust_TOP; + switch( nIntValue ) + { + case NS_ooxml::LN_Value_ST_VerticalJc_center: //92367 + nVA = drawing::TextVerticalAdjust_CENTER; + break; + case NS_ooxml::LN_Value_ST_VerticalJc_both: //92368 - justify + nVA = drawing::TextVerticalAdjust_BLOCK; + break; + case NS_ooxml::LN_Value_ST_VerticalJc_bottom: //92369 + nVA = drawing::TextVerticalAdjust_BOTTOM; + break; + default: + break; + } + pSectionContext->Insert( PROP_TEXT_VERTICAL_ADJUST, uno::Any( nVA ), true, PARA_GRAB_BAG ); + } + } + break; + case NS_ooxml::LN_EG_RPrBase_fitText: + break; + case NS_ooxml::LN_ffdata: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + FFDataHandler::Pointer_t pFFDataHandler(new FFDataHandler()); + + pProperties->resolve(*pFFDataHandler); + m_pImpl->SetFieldFFData(pFFDataHandler); + } + } + break; + case NS_ooxml::LN_CT_SdtPr_dropDownList: + case NS_ooxml::LN_CT_SdtPr_comboBox: + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::dropDown); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + } + break; + case NS_ooxml::LN_CT_SdtDropDownList_listItem: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + + size_t nDropDownDisplayTexts = m_pImpl->m_pSdtHelper->getDropDownDisplayTexts().size(); + size_t nDropDownItems = m_pImpl->m_pSdtHelper->getDropDownItems().size(); + + if (pProperties) + pProperties->resolve(*this); + + if (m_pImpl->m_pSdtHelper->getDropDownDisplayTexts().size() != nDropDownDisplayTexts + 1) + { + // w:displayText="..." is optional, add empty value if it was not provided. + m_pImpl->m_pSdtHelper->getDropDownDisplayTexts().push_back(OUString()); + } + if (m_pImpl->m_pSdtHelper->getDropDownItems().size() != nDropDownItems + 1) + { + // w:value="..." is optional, add empty value if it was not provided. + m_pImpl->m_pSdtHelper->getDropDownItems().push_back(OUString()); + } + } + break; + case NS_ooxml::LN_CT_SdtPr_placeholder: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + } + break; + break; + case NS_ooxml::LN_CT_SdtPr_date: + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::datePicker); + resolveSprmProps(*this, rSprm); + m_pImpl->m_pSdtHelper->setDateFieldStartRange(GetCurrentTextRange()->getEnd()); + } + break; + case NS_ooxml::LN_CT_SdtDate_dateFormat: + { + m_pImpl->m_pSdtHelper->getDateFormat().append(sStringValue); + } + break; + case NS_ooxml::LN_CT_SdtDate_storeMappedDataAs: + { + } + break; + case NS_ooxml::LN_CT_SdtDate_calendar: + { + } + break; + case NS_ooxml::LN_CT_SdtDate_lid: + { + m_pImpl->m_pSdtHelper->getLocale().append(sStringValue); + } + break; + case NS_ooxml::LN_CT_SdtPr_text: + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::plainText); + enableInteropGrabBag("ooxml:CT_SdtPr_text"); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag()); + m_pImpl->disableInteropGrabBag(); + } + break; + case NS_ooxml::LN_CT_SdtPr_showingPlcHdr: + { + m_pImpl->m_pSdtHelper->SetShowingPlcHdr(); + } + break; + case NS_ooxml::LN_CT_SdtPr_dataBinding: + case NS_ooxml::LN_CT_SdtPr_equation: + case NS_ooxml::LN_CT_SdtPr_checkbox: + case NS_ooxml::LN_CT_SdtPr_docPartObj: + case NS_ooxml::LN_CT_SdtPr_docPartList: + case NS_ooxml::LN_CT_SdtPr_picture: + case NS_ooxml::LN_CT_SdtPr_citation: + case NS_ooxml::LN_CT_SdtPr_group: + case NS_ooxml::LN_CT_SdtPr_id: + case NS_ooxml::LN_CT_SdtPr_alias: + case NS_ooxml::LN_CT_SdtPlaceholder_docPart: + case NS_ooxml::LN_CT_SdtPr_color: + { + if (!m_pImpl->GetSdtStarts().empty()) + { + if (nSprmId == NS_ooxml::LN_CT_SdtPr_color) + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + break; + } + + if (nSprmId == NS_ooxml::LN_CT_SdtPr_checkbox) + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::checkBox); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + break; + } + else if (nSprmId == NS_ooxml::LN_CT_SdtPr_picture) + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::picture); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + break; + } + else if (nSprmId == NS_ooxml::LN_CT_SdtPr_date) + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::datePicker); + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + } + break; + } + } + + // this is an unsupported SDT property, create a grab bag for it + OUString sName; + switch (nSprmId) + { + case NS_ooxml::LN_CT_SdtPr_dataBinding: sName = "ooxml:CT_SdtPr_dataBinding"; break; + case NS_ooxml::LN_CT_SdtPr_equation: sName = "ooxml:CT_SdtPr_equation"; break; + case NS_ooxml::LN_CT_SdtPr_checkbox: sName = "ooxml:CT_SdtPr_checkbox"; break; + case NS_ooxml::LN_CT_SdtPr_docPartObj: sName = "ooxml:CT_SdtPr_docPartObj"; break; + case NS_ooxml::LN_CT_SdtPr_docPartList: sName = "ooxml:CT_SdtPr_docPartList"; break; + case NS_ooxml::LN_CT_SdtPr_picture: sName = "ooxml:CT_SdtPr_picture"; break; + case NS_ooxml::LN_CT_SdtPr_citation: sName = "ooxml:CT_SdtPr_citation"; break; + case NS_ooxml::LN_CT_SdtPr_group: sName = "ooxml:CT_SdtPr_group"; break; + case NS_ooxml::LN_CT_SdtPr_id: sName = "ooxml:CT_SdtPr_id"; break; + case NS_ooxml::LN_CT_SdtPr_alias: sName = "ooxml:CT_SdtPr_alias"; break; + case NS_ooxml::LN_CT_SdtPlaceholder_docPart: sName = "ooxml:CT_SdtPlaceholder_docPart"; break; + case NS_ooxml::LN_CT_SdtPr_color: sName = "ooxml:CT_SdtPr_color"; break; + default: assert(false); + }; + if ( + nSprmId == NS_ooxml::LN_CT_SdtPr_checkbox || + nSprmId == NS_ooxml::LN_CT_SdtPr_docPartObj || + nSprmId == NS_ooxml::LN_CT_SdtPr_docPartList || + nSprmId == NS_ooxml::LN_CT_SdtPr_picture || + nSprmId == NS_ooxml::LN_CT_SdtPr_citation) + { + m_pImpl->m_pSdtHelper->setControlType(SdtControlType::unsupported); + } + enableInteropGrabBag(sName); + + // process subitems + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + + if (nSprmId == NS_ooxml::LN_CT_SdtPr_alias) + { + beans::PropertyValue aValue; + aValue.Name = sName; + aValue.Value <<= sStringValue; + m_pImpl->m_pSdtHelper->appendToInteropGrabBag(aValue); + } + else + m_pImpl->m_pSdtHelper->appendToInteropGrabBag(getInteropGrabBag()); + m_pImpl->m_pSdtHelper->setOutsideAParagraph(m_pImpl->IsOutsideAParagraph()); + m_pImpl->disableInteropGrabBag(); + } + break; + case NS_ooxml::LN_CT_SdtCheckbox_checked: + if (!m_pImpl->GetSdtStarts().empty()) + { + // nIntValue is not just 0 or 1, because we're in the w14 namespace's ST_OnOff. + if (nIntValue == NS_ooxml::LN_ST_OnOff_true || nIntValue == NS_ooxml::LN_ST_OnOff_1) + { + m_pImpl->m_pSdtHelper->SetChecked(); + } + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checked", + TextEffectsHandler::getOnOffString(nIntValue)); + } + break; + case NS_ooxml::LN_CT_SdtCheckbox_checkedState: + if (!m_pImpl->GetSdtStarts().empty()) + { + m_pImpl->m_pSdtHelper->SetCheckedState(OUString(sal_Unicode(sStringValue.toInt32(16)))); + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtCheckbox_checkedState", + sStringValue); + } + break; + case NS_ooxml::LN_CT_SdtCheckbox_uncheckedState: + if (!m_pImpl->GetSdtStarts().empty()) + { + m_pImpl->m_pSdtHelper->SetUncheckedState( + OUString(sal_Unicode(sStringValue.toInt32(16)))); + } + else + { + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, + "ooxml:CT_SdtCheckbox_uncheckedState", sStringValue); + } + break; + case NS_ooxml::LN_CT_SdtDocPart_docPartGallery: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartGallery", sStringValue); + break; + case NS_ooxml::LN_CT_SdtDocPart_docPartCategory: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartCategory", sStringValue); + break; + case NS_ooxml::LN_CT_SdtDocPart_docPartUnique: + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "ooxml:CT_SdtDocPart_docPartUnique", sStringValue); + break; + case NS_ooxml::LN_EG_SectPrContents_pgNumType: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + pProperties->resolve(*this); + } + } + break; + case NS_ooxml::LN_tblStart: + { + if (m_pImpl->hasTableManager()) + { + bool bTableStartsAtCellStart = m_pImpl->m_nTableDepth > 0 && m_pImpl->m_nTableCellDepth > m_pImpl->m_nLastTableCellParagraphDepth + 1; + m_pImpl->getTableManager().setTableStartsAtCellStart(bTableStartsAtCellStart); + } + /* + * Hack for Importing Section Properties + * LO is not able to import section properties if first element in the + * section is a table. So in case first element is a table add a dummy para + * and remove it again when lcl_endSectionGroup is called + */ + if(m_pImpl->m_nTableDepth == 0 && m_pImpl->GetIsFirstParagraphInSection() + && !m_pImpl->GetIsDummyParaAddedForTableInSection() && !m_pImpl->GetIsTextFrameInserted() + && !IsInHeaderFooter()) + { + m_pImpl->AddDummyParaForTableInSection(); + } + + // if first paragraph style in table has break-before-page, transfer that setting to the table itself. + if( m_pImpl->m_nTableDepth == 0 ) + { + const uno::Any aBreakType(style::BreakType_PAGE_BEFORE); + const PropertyMapPtr pParagraphProps = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if( pParagraphProps && pParagraphProps->isSet(PROP_PARA_STYLE_NAME) ) + { + StyleSheetEntryPtr pStyle; + OUString sStyleName; + pParagraphProps->getProperty(PROP_PARA_STYLE_NAME)->second >>= sStyleName; + if( !sStyleName.isEmpty() && GetStyleSheetTable() ) + pStyle = GetStyleSheetTable()->FindStyleSheetByConvertedStyleName( sStyleName ); + + if( pStyle && pStyle->pProperties + && pStyle->pProperties->isSet(PROP_BREAK_TYPE) + && pStyle->pProperties->getProperty(PROP_BREAK_TYPE)->second == aBreakType ) + { + pParagraphProps->Insert(PROP_BREAK_TYPE, aBreakType); + } + } + } + + m_pImpl->m_nTableDepth++; + } + break; + case NS_ooxml::LN_tblEnd: + m_pImpl->m_nTableDepth--; + break; + case NS_ooxml::LN_tcStart: + m_pImpl->m_nTableCellDepth++; + break; + case NS_ooxml::LN_tcEnd: + m_pImpl->m_nTableCellDepth--; + m_pImpl->m_nLastTableCellParagraphDepth = 0; + break; + case NS_ooxml::LN_glow_glow: + case NS_ooxml::LN_shadow_shadow: + case NS_ooxml::LN_reflection_reflection: + case NS_ooxml::LN_textOutline_textOutline: + case NS_ooxml::LN_textFill_textFill: + case NS_ooxml::LN_scene3d_scene3d: + case NS_ooxml::LN_props3d_props3d: + case NS_ooxml::LN_ligatures_ligatures: + case NS_ooxml::LN_numForm_numForm: + case NS_ooxml::LN_numSpacing_numSpacing: + case NS_ooxml::LN_stylisticSets_stylisticSets: + case NS_ooxml::LN_cntxtAlts_cntxtAlts: + { + tools::SvRef<TextEffectsHandler> pTextEffectsHandlerPtr( new TextEffectsHandler(nSprmId) ); + std::optional<PropertyIds> aPropertyId = pTextEffectsHandlerPtr->getGrabBagPropertyId(); + if(aPropertyId) + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if( pProperties ) + { + pProperties->resolve(*pTextEffectsHandlerPtr); + + beans::PropertyValue aGrabBag = pTextEffectsHandlerPtr->getInteropGrabBag(); + rContext->Insert(*aPropertyId, uno::Any(aGrabBag), true, CHAR_GRAB_BAG); + + sal_Int16 nTransparency = TextEffectsHandler::GetTextFillSolidFillAlpha(aGrabBag); + if (nTransparency != 0) + { + rContext->Insert(PROP_CHAR_TRANSPARENCE, uno::Any(nTransparency)); + } + } + else if (nSprmId == NS_ooxml::LN_cntxtAlts_cntxtAlts) + { + pTextEffectsHandlerPtr->lcl_sprm(rSprm); + beans::PropertyValue aGrabBag = pTextEffectsHandlerPtr->getInteropGrabBag(); + rContext->Insert(*aPropertyId, uno::Any(aGrabBag), true, CHAR_GRAB_BAG); + } + } + } + break; + case NS_ooxml::LN_CT_SdtPr_rPr: + { + // Make sure properties from a previous SDT are not merged with the current ones. + m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + } + break; + case NS_ooxml::LN_CT_TblPrBase_tblLook: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + { + pProperties->resolve(*this); + m_pImpl->getTableManager().finishTableLook(); + } + } + break; + case NS_ooxml::LN_CT_TrPrBase_cnfStyle: + { + m_pImpl->enableInteropGrabBag("cnfStyle"); + resolveSprmProps(*this, rSprm); + + TablePropertyMapPtr pPropMap(new TablePropertyMap()); + pPropMap->Insert(PROP_ROW_CNF_STYLE, uno::Any(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, ROW_GRAB_BAG); + m_pImpl->getTableManager().insertRowProps(pPropMap); + + m_pImpl->disableInteropGrabBag(); + } + break; + case NS_ooxml::LN_CT_TcPrBase_cnfStyle: + { + m_pImpl->enableInteropGrabBag("cnfStyle"); + resolveSprmProps(*this, rSprm); + + TablePropertyMapPtr pPropMap(new TablePropertyMap()); + pPropMap->Insert(PROP_CELL_CNF_STYLE, uno::Any(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, CELL_GRAB_BAG); + m_pImpl->getTableManager().cellProps(pPropMap); + + m_pImpl->disableInteropGrabBag(); + } + break; + case NS_ooxml::LN_CT_PPrBase_cnfStyle: + { + m_pImpl->enableInteropGrabBag("cnfStyle"); + resolveSprmProps(*this, rSprm); + rContext->Insert(PROP_PARA_CNF_STYLE, uno::Any(comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag)), true, PARA_GRAB_BAG); + m_pImpl->disableInteropGrabBag(); + } + break; + case NS_ooxml::LN_EG_RunInnerContent_sym: + { + resolveSprmProps(*this, rSprm); + SymbolData aSymbolData = m_pImpl->GetSymbolData(); + uno::Any aVal( aSymbolData.sFont ); + auto xFootnote = rContext->GetFootnote(); + if (!xFootnote.is() && m_pImpl->IsInCustomFootnote()) + xFootnote = m_pImpl->GetFootnoteContext()->GetFootnote(); + if (xFootnote.is()) + { + // DOCX can have different labels for the footnote reference and the footnote area. + // This skips the one from the footnote area and just uses the reference one. + if (!m_pImpl->IsInFootOrEndnote()) + { + auto xAnchorRange = xFootnote->getAnchor(); + auto xAnchorCursor(xAnchorRange->getText()->createTextCursorByRange(xAnchorRange)); + + // append a dummy character, so the following properties will be set as + // as SwpHints::SwTextAttr instead of the SwAttrSet of the paragraph, + // which would be removed by SwXText::Impl::finishOrAppendParagraph + xAnchorCursor->collapseToEnd(); + uno::Reference<text::XTextRange> xHackRange(xAnchorCursor, uno::UNO_QUERY); + xHackRange->setString("x"); + + uno::Reference<beans::XPropertySet> xAnchorProps(xAnchorRange, uno::UNO_QUERY); + xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME), aVal); + xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME_ASIAN), aVal); + xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_NAME_COMPLEX), aVal); + xAnchorProps->setPropertyValue(getPropertyName(PROP_CHAR_FONT_CHAR_SET), uno::Any(awt::CharSet::SYMBOL)); + + // remove the dummy char + xHackRange->setString(""); + + OUString sLabel = xFootnote->getLabel() + OUStringChar(aSymbolData.cSymbol); + xFootnote->setLabel(sLabel); + } + } + else //it's a _real_ symbol + { + rContext->Insert(PROP_CHAR_FONT_NAME, aVal); + rContext->Insert(PROP_CHAR_FONT_NAME_ASIAN, aVal); + rContext->Insert(PROP_CHAR_FONT_NAME_COMPLEX, aVal); + rContext->Insert(PROP_CHAR_FONT_CHAR_SET, uno::Any(awt::CharSet::SYMBOL)); + utext( reinterpret_cast < const sal_uInt8 * >( &(aSymbolData.cSymbol) ), 1 ); + } + } + break; + case NS_ooxml::LN_EG_RunInnerContent_ruby: + { + RubyInfo aInfo ; + m_pImpl->SetRubyInfo(aInfo); + } + break; + case NS_ooxml::LN_CT_RubyPr: + case NS_ooxml::LN_CT_Ruby_rt: + case NS_ooxml::LN_CT_Ruby_rubyBase: + { + m_pImpl->SetRubySprmId(nSprmId); + if (nSprmId == NS_ooxml::LN_CT_RubyPr) + { + resolveSprmProps(*this, rSprm); + } + } + break; + case NS_ooxml::LN_EG_RubyContent_r: + { + const RubyInfo & aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rubyBase) + { + rContext->Insert(PROP_RUBY_TEXT, uno::Any(aInfo.sRubyText)); + rContext->Insert(PROP_RUBY_STYLE, uno::Any(aInfo.sRubyStyle)); + rContext->Insert(PROP_RUBY_ADJUST, uno::Any(static_cast<sal_Int16>(ConversionHelper::convertRubyAlign(aInfo.nRubyAlign)))); + if ( aInfo.nRubyAlign == NS_ooxml::LN_Value_ST_RubyAlign_rightVertical ) + rContext->Insert(PROP_RUBY_POSITION, uno::Any(css::text::RubyPosition::INTER_CHARACTER)); + + m_pImpl->SetRubySprmId(0); + } + } + break; + case NS_ooxml::LN_CT_RubyPr_rubyAlign: + case NS_ooxml::LN_CT_RubyPr_hps: + case NS_ooxml::LN_CT_RubyPr_hpsBaseText: + { + RubyInfo aInfo = m_pImpl->GetRubyInfo(); + switch(nSprmId) + { + case NS_ooxml::LN_CT_RubyPr_rubyAlign: + aInfo.nRubyAlign = nIntValue; + break; + case NS_ooxml::LN_CT_RubyPr_hps: + aInfo.nHps= nIntValue; + break; + case NS_ooxml::LN_CT_RubyPr_hpsBaseText: + aInfo.nHpsBaseText = nIntValue; + break; + } + m_pImpl->SetRubyInfo(aInfo); + } + break; + case NS_ooxml::LN_CT_SmartTagRun_smartTagPr: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties && m_pImpl->GetTopContextType() == CONTEXT_PARAGRAPH) + pProperties->resolve(m_pImpl->getSmartTagHandler()); + } + break; + case NS_ooxml::LN_CT_DocPartPr_name: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + } + break; + case NS_ooxml::LN_CT_DocPartPr_category: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + } + break; + case NS_ooxml::LN_CT_DocPartCategory_gallery: + { + writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps(); + if (pProperties) + pProperties->resolve(*this); + } + break; + default: + { +#ifdef DBG_UTIL + TagLogger::getInstance().startElement("unhandled"); + TagLogger::getInstance().attribute("id", nSprmId); + TagLogger::getInstance().attribute("name", rSprm.getName()); + TagLogger::getInstance().endElement(); +#endif + } + } +} + +void DomainMapper::processDeferredCharacterProperties( const std::map< sal_Int32, uno::Any >& deferredCharacterProperties ) +{ + assert( m_pImpl->GetTopContextType() == CONTEXT_CHARACTER ); + PropertyMapPtr rContext = m_pImpl->GetTopContext(); + for( const auto& rProp : deferredCharacterProperties ) + { + sal_Int32 Id = rProp.first; + sal_Int32 nIntValue = 0; + OUString sStringValue; + rProp.second >>= nIntValue; + rProp.second >>= sStringValue; + switch( Id ) + { + case NS_ooxml::LN_EG_RPrBase_position: + { + double nEscapement = 0; + sal_Int8 nProp = 0; + if ( nIntValue ) + { + nProp = 100; + double fFontSize = 0; + m_pImpl->GetAnyProperty(PROP_CHAR_HEIGHT, rContext) >>= fFontSize; + if ( fFontSize ) + // nIntValue is in half-points, fontsize is in points, escapement is a percentage. + nEscapement = round( nIntValue/2.0 / fFontSize * 100 ); + else + nEscapement = nIntValue > 0 ? DFLT_ESC_SUPER : DFLT_ESC_SUB; + } + if ( nEscapement > MAX_ESC_POS ) + nEscapement = MAX_ESC_POS; + else if ( nEscapement < -MAX_ESC_POS ) + nEscapement = -MAX_ESC_POS; + + rContext->Insert(PROP_CHAR_ESCAPEMENT, uno::Any( sal_Int16(nEscapement) ) ); + rContext->Insert(PROP_CHAR_ESCAPEMENT_HEIGHT, uno::Any( nProp ) ); + } + break; + default: + SAL_WARN( "writerfilter", "Unhandled property in processDeferredCharacterProperty()" ); + break; + } + } +} + +void DomainMapper::lcl_entry(writerfilter::Reference<Properties>::Pointer_t ref) +{ + ref->resolve(*this); +} + +void DomainMapper::data(const sal_uInt8* /*buf*/, size_t /*len*/) +{ +} + +void DomainMapper::lcl_startSectionGroup() +{ + if (!m_pImpl->isInIndexContext() && !m_pImpl->isInBibliographyContext()) + { + m_pImpl->PushProperties(CONTEXT_SECTION); + } + m_pImpl->SetIsFirstParagraphInSection(true); + m_pImpl->SetIsFirstParagraphInSectionAfterRedline(true); +} + +void DomainMapper::lcl_endSectionGroup() +{ + if (m_pImpl->isInIndexContext() || m_pImpl->isInBibliographyContext()) + return; + + m_pImpl->CheckUnregisteredFrameConversion(); + m_pImpl->ExecuteFrameConversion(); + // When pasting, it's fine to not have any paragraph inside the document at all. + if (m_pImpl->GetIsFirstParagraphInSection() && m_pImpl->IsNewDoc()) + { + // This section has no paragraph at all (e.g. they are all actually in a frame). + // If this section has a page break, there would be nothing to apply to the page + // style, so force a dummy paragraph. + lcl_startParagraphGroup(); + lcl_startCharacterGroup(); + sal_uInt8 const sBreak[] = { 0xd }; + lcl_text(sBreak, 1); + lcl_endCharacterGroup(); + lcl_endParagraphGroup(); + } + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_SECTION); + SectionPropertyMap* pSectionContext = dynamic_cast< SectionPropertyMap* >( pContext.get() ); + OSL_ENSURE(pSectionContext, "SectionContext unavailable!"); + if(pSectionContext) + { + pSectionContext->CloseSectionGroup( *m_pImpl ); + // Remove the dummy paragraph if added for + // handling the section properties if section starts with a table + if (m_pImpl->GetIsDummyParaAddedForTableInSection()) + m_pImpl->RemoveDummyParaForTableInSection(); + } + m_pImpl->SetIsTextFrameInserted( false ); + m_pImpl->PopProperties(CONTEXT_SECTION); +} + +void DomainMapper::lcl_startParagraphGroup() +{ + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().startParagraphGroup(); + /* + * Add new para properties only if paragraph is not split + * or the top context is not of paragraph properties + * Set mbIsSplitPara to false as it has been handled + */ + if (!mbIsSplitPara) + m_pImpl->PushProperties(CONTEXT_PARAGRAPH); + mbIsSplitPara = false; + if (m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) != m_pImpl->GetTopContext()) + m_pImpl->PushProperties(CONTEXT_PARAGRAPH); + + if (m_pImpl->GetTopContext()) + { + if (!m_pImpl->IsInShape()) + { + const OUString& sDefaultParaStyle = m_pImpl->GetDefaultParaStyleName(); + m_pImpl->GetTopContext()->Insert( PROP_PARA_STYLE_NAME, uno::Any( sDefaultParaStyle ) ); + m_pImpl->SetCurrentParaStyleName( sDefaultParaStyle ); + + if (m_pImpl->isBreakDeferred(PAGE_BREAK)) + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + else if (m_pImpl->isBreakDeferred(COLUMN_BREAK)) + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_COLUMN_BEFORE)); + mbWasShapeInPara = false; + } + + if (m_pImpl->isParaSdtEndDeferred()) + m_pImpl->GetTopContext()->Insert(PROP_PARA_SDT_END_BEFORE, uno::Any(true), true, PARA_GRAB_BAG); + } + m_pImpl->SetIsFirstRun(true); + m_pImpl->SetIsOutsideAParagraph(false); + if (!m_pImpl->IsInShape()) + m_pImpl->clearDeferredBreaks(); + m_pImpl->setParaSdtEndDeferred(false); +} + +void DomainMapper::lcl_endParagraphGroup() +{ + if (m_pImpl->isBreakDeferred(LINE_BREAK)) + { + if (m_pImpl->GetIsLastParagraphInSection()) + m_pImpl->clearDeferredBreak(LINE_BREAK); + + while (m_pImpl->isBreakDeferred(LINE_BREAK)) + { + m_pImpl->clearDeferredBreak(LINE_BREAK); + m_pImpl->appendTextPortion("\n", m_pImpl->GetTopContext()); + } + } + + m_pImpl->PopProperties(CONTEXT_PARAGRAPH); + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().endParagraphGroup(); + //frame conversion has to be executed after table conversion + m_pImpl->ExecuteFrameConversion(); + m_pImpl->SetIsOutsideAParagraph(true); +} + +void DomainMapper::markLastParagraphInSection( ) +{ + m_pImpl->SetIsLastParagraphInSection( true ); +} + +void DomainMapper::markLastSectionGroup( ) +{ + m_pImpl->SetIsLastSectionGroup( true ); +} + +void DomainMapper::lcl_startShape(uno::Reference<drawing::XShape> const& xShape) +{ + assert(xShape.is()); + + m_pImpl->AttachTextBoxContentToShape(xShape); + if (m_pImpl->GetTopContext()) + { + // If there is a deferred page break, handle it now, so that the + // started shape will be on the correct page. + if (m_pImpl->isBreakDeferred(PAGE_BREAK)) + { + m_pImpl->clearDeferredBreak(PAGE_BREAK); + lcl_startCharacterGroup(); + sal_uInt8 const sBreak[] = { 0xd }; + lcl_text(sBreak, 1); + lcl_endCharacterGroup(); + lcl_endParagraphGroup(); + lcl_startParagraphGroup(); + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + } + m_pImpl->PushShapeContext( xShape ); + lcl_startParagraphGroup(); + } + else + { + // No context? Then this image should not appear directly inside the + // document, just save it for later usage. + m_pImpl->PushPendingShape(xShape); + } + + m_pImpl->SetIsFirstParagraphInShape(true); + mbWasShapeInPara = true; +} + +void DomainMapper::lcl_endShape( ) +{ + if (!m_pImpl->GetTopContext()) + return; + + // End the current table, if there are any. Otherwise the unavoidable + // empty paragraph at the end of the shape text will cause problems: if + // the shape text ends with a table, the extra paragraph will be + // handled as an additional row of the ending table. + if (m_pImpl->hasTableManager()) + m_pImpl->getTableManager().endTable(); + + lcl_endParagraphGroup(); + m_pImpl->PopShapeContext( ); + // A shape is always inside a paragraph (anchored or inline). + m_pImpl->SetIsOutsideAParagraph(false); +} + +void DomainMapper::lcl_startTextBoxContent() +{ + m_pImpl->PushTextBoxContent(); +} + +void DomainMapper::lcl_endTextBoxContent() +{ + m_pImpl->PopTextBoxContent(); +} + +void DomainMapper::PushStyleSheetProperties( const PropertyMapPtr& pStyleProperties, bool bAffectTableMngr ) +{ + m_pImpl->PushStyleProperties( pStyleProperties ); + if ( bAffectTableMngr ) + m_pImpl->getTableManager( ).SetStyleProperties( pStyleProperties ); +} + +void DomainMapper::PopStyleSheetProperties( bool bAffectTableMngr ) +{ + m_pImpl->PopProperties( CONTEXT_STYLESHEET ); + if ( bAffectTableMngr ) + { + PropertyMapPtr emptyPtr; + m_pImpl->getTableManager( ).SetStyleProperties( emptyPtr ); + } +} + +void DomainMapper::PushListProperties( const ::tools::SvRef<PropertyMap>& pListProperties ) +{ + m_pImpl->PushListProperties( pListProperties ); +} + +void DomainMapper::PopListProperties() +{ + m_pImpl->PopProperties( CONTEXT_LIST ); +} + +void DomainMapper::lcl_startCharacterGroup() +{ + m_pImpl->PushProperties(CONTEXT_CHARACTER); + if (m_pImpl->isSdtEndDeferred()) + { + // Fields have an empty character group before the real one, so don't + // call setSdtEndDeferred(false) here, that will happen only in lcl_utext(). + m_pImpl->GetTopContext()->Insert(PROP_SDT_END_BEFORE, uno::Any(true), true, CHAR_GRAB_BAG); + } +} + +void DomainMapper::lcl_endCharacterGroup() +{ + if (m_pImpl->CheckFootnoteStyle()) + { + m_pImpl->SetCheckFootnoteStyle(m_pImpl->IsInCustomFootnote()); + m_pImpl->SetHasFootnoteStyle(false); + } + m_pImpl->PopProperties(CONTEXT_CHARACTER); +} + +void DomainMapper::lcl_text(const sal_uInt8 * data_, size_t len) +{ + //TODO: Determine the right text encoding (FIB?) + OUString sText( reinterpret_cast<const char*>(data_), len, RTL_TEXTENCODING_MS_1252 ); +#ifdef DBG_UTIL + TagLogger::getInstance().startElement("text"); + TagLogger::getInstance().chars(sText); + TagLogger::getInstance().endElement(); +#endif + + try + { + if(len == 1) + { + switch(*data_) + { + case 0x02: return; //footnote character + case 0x08: // Lock field if in field context + if (m_pImpl->IsOpenField()) + m_pImpl->SetFieldLocked(); + return; + case 0x0c: //page break + // page breaks aren't supported in footnotes and endnotes + if (!m_pImpl->IsInFootOrEndnote()) + { + m_pImpl->deferBreak(PAGE_BREAK); + m_pImpl->SetIsDummyParaAddedForTableInSectionPage(false); + } + return; + case 0x0e: //column break + m_pImpl->deferBreak(COLUMN_BREAK); + return; + case 0x0a: //line break + if (m_pImpl->GetIsLastParagraphInSection()) + { + m_pImpl->deferBreak(LINE_BREAK); + return; + } + break; + case 0x07: + m_pImpl->getTableManager().text(data_, len); + return; + case 0x0d: + { + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if (pContext && m_pImpl->isBreakDeferred(COLUMN_BREAK)) + { + pContext->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_COLUMN_BEFORE)); + m_pImpl->clearDeferredBreak(COLUMN_BREAK); + } + finishParagraph(); + return; + } + case cFieldStart: + m_pImpl->PushFieldContext(); + return; + case cFieldSep: + // delimiter not necessarily available + // appears only if field contains further content + m_pImpl->CloseFieldCommand(); + return; + case cFieldEnd: + m_pImpl->PopFieldContext(); + return; + default: + break; + } + } + + // GetTopContext() is changed by inserted breaks, but we want to keep the current context + PropertyMapPtr pContext = m_pImpl->GetTopContext(); + + while (m_pImpl->isBreakDeferred(LINE_BREAK)) + { + m_pImpl->clearDeferredBreak(LINE_BREAK); + m_pImpl->appendTextPortion("\n", pContext); + } + + if (!m_pImpl->GetFootnoteContext()) + { + if (m_pImpl->isBreakDeferred(PAGE_BREAK)) + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + else if (m_pImpl->isBreakDeferred(COLUMN_BREAK)) + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_COLUMN_BEFORE)); + m_pImpl->clearDeferredBreaks(); + } + + if (pContext && pContext->GetFootnote().is() && m_pImpl->IsInCustomFootnote()) + { + pContext->GetFootnote()->setLabel(sText); + m_pImpl->EndCustomFootnote(); + //otherwise ignore sText + } + else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields()) + { + m_pImpl->AppendFieldCommand(sText); + } + else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString()) + /*depending on the success of the field insert operation this result will be + set at the field or directly inserted into the text*/ + m_pImpl->AppendFieldResult(sText); + else + { + if (pContext == nullptr) + pContext = new PropertyMap(); + + if (sText == "\n") + { + m_pImpl->HandleLineBreak(pContext); + } + else + { + m_pImpl->appendTextPortion(sText, pContext); + } + } + } + catch( const uno::RuntimeException& ) + { + TOOLS_WARN_EXCEPTION("writerfilter", ""); + } +} + +void DomainMapper::lcl_positionOffset(const OUString& rText, bool bVertical) +{ + if (bVertical) + m_pImpl->m_aPositionOffsets.second = rText; + else + m_pImpl->m_aPositionOffsets.first = rText; +} + +awt::Point DomainMapper::getPositionOffset() +{ + awt::Point aRet; + aRet.X = oox::drawingml::convertEmuToHmm(m_pImpl->m_aPositionOffsets.first.toInt32()); + aRet.Y = oox::drawingml::convertEmuToHmm(m_pImpl->m_aPositionOffsets.second.toInt32()); + return aRet; +} + +void DomainMapper::lcl_align(const OUString& rText, bool bVertical) +{ + if (bVertical) + m_pImpl->m_aAligns.second = rText; + else + m_pImpl->m_aAligns.first = rText; +} + +void DomainMapper::lcl_positivePercentage(const OUString& rText) +{ + m_pImpl->m_aPositivePercentages.push(rText); +} + +void DomainMapper::lcl_checkId(const sal_Int32 nId) +{ + if (m_pImpl->IsInFootnote()) + { + m_pImpl->m_aFootnoteIds.push_back(nId); + // keep only the first real footnote + if (m_pImpl->GetFootnoteCount() == -1 && m_pImpl->m_aFootnoteIds.size() == 2) + m_pImpl->m_aFootnoteIds.pop_front(); + } + else + { + m_pImpl->m_aEndnoteIds.push_back(nId); + // keep only the first real endnote + if (m_pImpl->GetEndnoteCount() == -1 && m_pImpl->m_aEndnoteIds.size() == 2) + m_pImpl->m_aEndnoteIds.pop_front(); + } +} + +void DomainMapper::lcl_utext(const sal_uInt8 * data_, size_t len) +{ + // All these fixed values are defined as static const sal_Unicode codepoints in the fast parser, + // like uFtnEdnRef = 0x2, uFtnEdnSep = 0x3, ... and have a len of 1, if they aren't valid unicode. + + OUString sText(reinterpret_cast<const sal_Unicode *>(data_), len); + const RubyInfo & aInfo = m_pImpl->GetRubyInfo(); + if (aInfo.nSprmId == NS_ooxml::LN_CT_Ruby_rt) + { + PropertyMapPtr pContext = m_pImpl->GetTopContext(); + PropertyValueVector_t aProps = comphelper::sequenceToContainer< PropertyValueVector_t >(pContext->GetPropertyValues()); + OUString sStyle = getOrCreateCharStyle(aProps, /*bAlwaysCreate=*/false); + m_pImpl->SetRubyText(sText,sStyle); + return; + } + + if (len == 1) + { + // preload all footnotes in separated footnotes + if (sText[0] == 0x5) + { + if (m_pImpl->IsInFootnote()) + { + if (m_pImpl->GetFootnoteCount() > -1) + { + m_pImpl->PopFootOrEndnote(); + m_pImpl->PushFootOrEndnote(/*bIsFootnote=*/true); + } + m_pImpl->IncrementFootnoteCount(); + } + else + { + if (m_pImpl->GetEndnoteCount() > -1) + { + m_pImpl->PopFootOrEndnote(); + m_pImpl->PushFootOrEndnote(/*bIsFootnote=*/false); + } + m_pImpl->IncrementEndnoteCount(); + } + } + + // If the footnote contains a Footnote Reference Mark, it can't be a custom footnote + // ****** + // This code block is wrong, as it should also be in m_pImpl->IsInFootOrEndnote(). + // The main problem is that + // + // assert(len != 1 || sText[0] != 0x2) + // + // is triggered by the unit test SwLayoutWriter::testForcepoint75, so all these pseudo + // value handling is broken. + // But this is just a symptom, as I guess it's possible to generate broken DOCX documents, + // which might be problematic, triggering *funny* code paths left and right. + // ****** + if (sText[0] == 0x2) + { + m_pImpl->EndCustomFootnote(); + return; + } + + if (m_pImpl->IsInCustomFootnote()) + { + if (sText[0] != 0xd && sText[0] != 0x3) + { + // DOCX can have different labels for the footnote reference and the footnote area. + // This skips the one from the footnote area and just uses the reference one. + if (!m_pImpl->IsInFootOrEndnote()) + { + if (PropertyMapPtr pFootnoteContext = m_pImpl->GetFootnoteContext()) + { + auto xFootnote = pFootnoteContext->GetFootnote(); + xFootnote->setLabel(xFootnote->getLabel() + sText); + } + } + return; + } + else + m_pImpl->SetHasFootnoteStyle(true); + } + } + + if (m_pImpl->isSdtEndDeferred()) + { + // In case we have a field context, then save the property there, so + // SDT's ending right before a field start are handled as well. + PropertyMapPtr pContext = m_pImpl->GetTopContext(); + if (m_pImpl->IsOpenField()) + pContext = m_pImpl->GetTopFieldContext()->getProperties(); + pContext->Insert(PROP_SDT_END_BEFORE, uno::Any(true), true, CHAR_GRAB_BAG); + m_pImpl->setSdtEndDeferred(false); + } + + bool bNewLine = len == 1 && (sText[0] == 0x0d || sText[0] == 0x07); + if (m_pImpl->GetSdtStarts().empty() && m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::dropDown) + { + // Block, cell or row SDT. + if (bNewLine) + // Dropdown control has single-line texts, so in case of newline, create the control. + m_pImpl->m_pSdtHelper->createDropDownControl(); + else + { + m_pImpl->m_pSdtHelper->getSdtTexts().append(sText); + return; + } + } + else if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::datePicker) + { + if (IsInHeaderFooter() && m_pImpl->IsDiscardHeaderFooter()) + { + m_pImpl->m_pSdtHelper->getDateFormat().truncate(); + m_pImpl->m_pSdtHelper->getLocale().truncate(); + return; + } + } + else if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::plainText) + { + m_pImpl->m_pSdtHelper->getSdtTexts().append(sText); + if (bNewLine) + { + m_pImpl->m_pSdtHelper->createPlainTextControl(); + finishParagraph(); + } + return; + } + else if (!m_pImpl->m_pSdtHelper->isInteropGrabBagEmpty()) + { + // there are unsupported SDT properties in the document + // save them in the paragraph interop grab bag + if (m_pImpl->IsDiscardHeaderFooter()) + { + // Unless we're supposed to ignore this header/footer. + m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + return; + } + if((m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_checkbox") || + m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_text") || + m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_dataBinding") || + m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_citation") || + (m_pImpl->m_pSdtHelper->containedInInteropGrabBag("ooxml:CT_SdtPr_id") && + m_pImpl->m_pSdtHelper->getInteropGrabBagSize() == 1)) && !m_pImpl->m_pSdtHelper->isOutsideAParagraph()) + { + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_CHARACTER); + + if (m_pImpl->IsOpenField()) + // We have a field, insert the SDT properties to the field's grab-bag, so they won't be lost. + pContext = m_pImpl->GetTopFieldContext()->getProperties(); + + uno::Sequence<beans::PropertyValue> aGrabBag = m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + if (m_pImpl->GetSdtStarts().empty() || m_pImpl->m_pSdtHelper->getControlType() != SdtControlType::dropDown) + { + pContext->Insert(PROP_SDTPR, uno::Any(aGrabBag), true, CHAR_GRAB_BAG); + } + } + else + { + uno::Sequence<beans::PropertyValue> aGrabBag = m_pImpl->m_pSdtHelper->getInteropGrabBagAndClear(); + if (m_pImpl->GetSdtStarts().empty() + || (m_pImpl->m_pSdtHelper->getControlType() != SdtControlType::dropDown && m_pImpl->m_pSdtHelper->getControlType() != SdtControlType::richText)) + { + m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)->Insert(PROP_SDTPR, + uno::Any(aGrabBag), true, PARA_GRAB_BAG); + } + } + } + else if (len == 1 && sText[0] == 0x03) + { + // This is the uFtnEdnSep, remember that the document has a separator. + m_pImpl->m_bHasFtnSep = true; + return; + } + else if (len == 1 && sText[0] == '\r') + { + // Clear "last" one linebreak at end of section + if (m_pImpl->GetIsLastParagraphInSection() && m_pImpl->isBreakDeferred(LINE_BREAK)) + m_pImpl->clearDeferredBreak(LINE_BREAK); + // And emit all other linebreaks + while (m_pImpl->isBreakDeferred(LINE_BREAK)) + { + m_pImpl->clearDeferredBreak(LINE_BREAK); + m_pImpl->appendTextPortion("\n", m_pImpl->GetTopContext()); + } + } + else if (len == 1 && sText[0] == '\t' ) + { + if ( m_pImpl->m_bCheckFirstFootnoteTab && m_pImpl->IsInFootOrEndnote() ) + { + // Allow MSO to emulate LO footnote text starting at left margin - only meaningful with hanging indent + m_pImpl->m_bCheckFirstFootnoteTab = false; + sal_Int32 nFirstLineIndent = 0; + m_pImpl->GetAnyProperty(PROP_PARA_FIRST_LINE_INDENT, m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH)) >>= nFirstLineIndent; + if ( nFirstLineIndent < 0 ) + m_pImpl->m_bIgnoreNextTab = true; + } + + if ( m_pImpl->m_bIgnoreNextTab ) + { + m_pImpl->m_bIgnoreNextTab = false; + return; + } + } + if (!m_pImpl->hasTableManager()) + return; + + SkipFootnoteSeparator eSkip = m_pImpl->GetSkipFootnoteState(); + if ( eSkip == SkipFootnoteSeparator::ON || eSkip == SkipFootnoteSeparator::SKIPPING ) + { + m_pImpl->SetSkipFootnoteState( SkipFootnoteSeparator::SKIPPING ); + return; + } + + try + { + while (m_pImpl->isBreakDeferred(LINE_BREAK)) + { + m_pImpl->clearDeferredBreak(LINE_BREAK); + m_pImpl->appendTextPortion("\n", m_pImpl->GetTopContext()); + } + + m_pImpl->getTableManager().utext(data_, len); + + if (bNewLine) + { + const bool bSingleParagraph = m_pImpl->GetIsFirstParagraphInSection() && m_pImpl->GetIsLastParagraphInSection(); + const bool bSingleParagraphAfterRedline = m_pImpl->GetIsFirstParagraphInSection(/*bAfterRedline=*/true) && + m_pImpl->GetIsLastParagraphInSection(); + PropertyMapPtr pContext = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH); + if (!m_pImpl->GetFootnoteContext()) + { + if (m_pImpl->isBreakDeferred(PAGE_BREAK)) + { + if (m_pImpl->GetSettingsTable()->GetSplitPgBreakAndParaMark()) + { + if ( m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun() ) + { + m_pImpl->m_bIsSplitPara = true; + finishParagraph(); + lcl_startParagraphGroup(); + } + + + pContext->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + m_pImpl->clearDeferredBreaks(); + } + } + else if (m_pImpl->isBreakDeferred(COLUMN_BREAK)) + { + if ( m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun() ) + { + mbIsSplitPara = true; + finishParagraph(); + lcl_startParagraphGroup(); + } + + pContext->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_COLUMN_BEFORE)); + m_pImpl->clearDeferredBreaks(); + } + } + + // If the paragraph contains only the section properties and it has + // no runs, we should not create a paragraph for it in Writer, unless that would remove the whole section. + // Also do not remove here column breaks: they are treated in a different way and place. + bool bIsColumnBreak = false; + if (pContext->isSet(PROP_BREAK_TYPE)) + { + const uno::Any aBreakType = pContext->getProperty(PROP_BREAK_TYPE)->second; + bIsColumnBreak = + aBreakType == style::BreakType_COLUMN_BEFORE || + aBreakType == style::BreakType_COLUMN_AFTER || + aBreakType == style::BreakType_COLUMN_BOTH; + } + + bool bRemove = (!m_pImpl->GetParaChanged() && m_pImpl->GetRemoveThisPara()) || + (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr() + && !bSingleParagraphAfterRedline + && !bIsColumnBreak + && !m_pImpl->GetParaHadField() + && (!m_pImpl->GetIsDummyParaAddedForTableInSectionPage()) + && !m_pImpl->GetIsPreviousParagraphFramed() + && !m_pImpl->HasTopAnchoredObjects() + && !m_pImpl->IsParaWithInlineObject()); + + const bool bNoNumbering = bRemove || (!m_pImpl->GetParaChanged() && m_pImpl->GetParaSectpr() && bSingleParagraph); + PropertyMapPtr xContext = bNoNumbering ? m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH) : PropertyMapPtr(); + if (xContext) + { + // tdf#97417 delete numbering of the paragraph + // it will be deleted anyway, and the numbering would be copied + // to the next paragraph in sw SplitNode and then be applied to + // every following paragraph + xContext->Erase(PROP_NUMBERING_RULES); + static_cast<ParagraphPropertyMap*>(xContext.get())->SetListId(-1);; + xContext->Erase(PROP_NUMBERING_LEVEL); + } + finishParagraph(bRemove, bNoNumbering); + if (bRemove) + m_pImpl->RemoveLastParagraph(); + m_pImpl->SetParaSectpr(false); + } + else + { + // GetTopContext() is changed by inserted breaks, but we want to keep the current context + PropertyMapPtr pContext = m_pImpl->GetTopContext(); + if (!m_pImpl->GetFootnoteContext()) + { + if (m_pImpl->isBreakDeferred(PAGE_BREAK)) + { + /* If PAGEBREAK appears in first paragraph of the section or + * after first run of any paragraph then need to split paragraph + * to handle it properly. + */ + if (m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun()) + { + m_pImpl->m_bIsSplitPara = true; + finishParagraph(); + lcl_startParagraphGroup(); + } + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_PAGE_BEFORE)); + } + else if (m_pImpl->isBreakDeferred(COLUMN_BREAK)) + { + if (m_pImpl->GetIsFirstParagraphInSection() || !m_pImpl->IsFirstRun() || mbWasShapeInPara) + { + mbWasShapeInPara = false; + mbIsSplitPara = true; + finishParagraph(); + lcl_startParagraphGroup(); + } + m_pImpl->GetTopContext()->Insert(PROP_BREAK_TYPE, uno::Any(style::BreakType_COLUMN_BEFORE)); + } + m_pImpl->clearDeferredBreaks(); + } + + if (pContext && pContext->GetFootnote().is()) + { + pContext->GetFootnote()->setLabel( sText ); + // tdf#141548 don't lose footnote/endnote text of the run with uFtnEdnRef + // (i.e. when footnoteRef/endnoteRef is followed by some text in the same run) + m_pImpl->appendTextPortion( sText, pContext ); + } + else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields()) + { + m_pImpl->AppendFieldCommand(sText); + } + else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString()) + /*depending on the success of the field insert operation this result will be + set at the field or directly inserted into the text*/ + m_pImpl->AppendFieldResult(sText); + else + { + if (pContext == nullptr) + pContext = new PropertyMap(); + + m_pImpl->appendTextPortion( sText, pContext ); + } + + } + m_pImpl->SetIsFirstRun(false); + } + catch( const uno::RuntimeException& ) + { + } +} + +void DomainMapper::lcl_props(writerfilter::Reference<Properties>::Pointer_t ref) +{ + ref->resolve(*this); +} + +void DomainMapper::lcl_table(Id name, writerfilter::Reference<Table>::Pointer_t ref) +{ + m_pImpl->SetAnyTableImport(true); + switch(name) + { + case NS_ooxml::LN_FONTTABLE: + + // create a font table object that listens to the attributes + // each entry call inserts a new font entry + ref->resolve( *m_pImpl->GetFontTable() ); + break; + case NS_ooxml::LN_STYLESHEET: + //same as above to import style sheets + m_pImpl->SetStyleSheetImport( true ); + ref->resolve( *m_pImpl->GetStyleSheetTable() ); + m_pImpl->GetStyleSheetTable()->ApplyStyleSheets(m_pImpl->GetFontTable()); + m_pImpl->SetStyleSheetImport( false ); + break; + case NS_ooxml::LN_NUMBERING: + { + m_pImpl->SetNumberingImport(true); + //the same for list tables + ref->resolve( *m_pImpl->GetListTable() ); + m_pImpl->GetListTable( )->CreateNumberingRules( ); + m_pImpl->SetNumberingImport(false); + } + break; + case NS_ooxml::LN_THEMETABLE: + m_pImpl->GetThemeTable()->setThemeFontLangProperties( + m_pImpl->GetSettingsTable()->GetThemeFontLangProperties() ); + ref->resolve ( *m_pImpl->GetThemeTable() ); + break; + case NS_ooxml::LN_settings_settings: + ref->resolve ( *m_pImpl->GetSettingsTable() ); + m_pImpl->ApplySettingsTable(); + break; + default: + OSL_FAIL( "which table is to be filled here?"); + } + m_pImpl->SetAnyTableImport(false); +} + +void DomainMapper::lcl_substream(Id rName, ::writerfilter::Reference<Stream>::Pointer_t ref) +{ + m_pImpl->substream(rName, ref); +} + +void DomainMapper::lcl_startGlossaryEntry() +{ + uno::Reference< text::XTextRange > xTextRange = GetCurrentTextRange(); + m_pImpl->setGlossaryEntryStart(xTextRange); +} + +void DomainMapper::lcl_endGlossaryEntry() +{ + m_pImpl->appendGlossaryEntry(); +} + +void DomainMapper::handleUnderlineType(const Id nId, const ::tools::SvRef<PropertyMap>& rContext) +{ + sal_Int16 nUnderline = awt::FontUnderline::NONE; + + switch (nId) + { + case NS_ooxml::LN_Value_ST_Underline_none: + nUnderline = awt::FontUnderline::NONE; + break; + case NS_ooxml::LN_Value_ST_Underline_words: + rContext->Insert(PROP_CHAR_WORD_MODE, uno::Any(true)); + [[fallthrough]]; + case NS_ooxml::LN_Value_ST_Underline_single: + nUnderline = awt::FontUnderline::SINGLE; + break; + case NS_ooxml::LN_Value_ST_Underline_double: + nUnderline = awt::FontUnderline::DOUBLE; + break; + case NS_ooxml::LN_Value_ST_Underline_dotted: + nUnderline = awt::FontUnderline::DOTTED; + break; + case NS_ooxml::LN_Value_ST_Underline_dash: + nUnderline = awt::FontUnderline::DASH; + break; + case NS_ooxml::LN_Value_ST_Underline_dotDash: + nUnderline = awt::FontUnderline::DASHDOT; + break; + case NS_ooxml::LN_Value_ST_Underline_dotDotDash: + nUnderline = awt::FontUnderline::DASHDOTDOT; + break; + case NS_ooxml::LN_Value_ST_Underline_thick: + nUnderline = awt::FontUnderline::BOLD; + break; + case NS_ooxml::LN_Value_ST_Underline_wave: + nUnderline = awt::FontUnderline::WAVE; + break; + case NS_ooxml::LN_Value_ST_Underline_dottedHeavy: + nUnderline = awt::FontUnderline::BOLDDOTTED; + break; + case NS_ooxml::LN_Value_ST_Underline_dashedHeavy: + nUnderline = awt::FontUnderline::BOLDDASH; + break; + case NS_ooxml::LN_Value_ST_Underline_dashLong: + nUnderline = awt::FontUnderline::LONGDASH; + break; + case NS_ooxml::LN_Value_ST_Underline_dashLongHeavy: + nUnderline = awt::FontUnderline::BOLDLONGDASH; + break; + case NS_ooxml::LN_Value_ST_Underline_dashDotHeavy: + nUnderline = awt::FontUnderline::BOLDDASHDOT; + break; + case NS_ooxml::LN_Value_ST_Underline_dashDotDotHeavy: + nUnderline = awt::FontUnderline::BOLDDASHDOTDOT; + break; + case NS_ooxml::LN_Value_ST_Underline_wavyHeavy: + nUnderline = awt::FontUnderline::BOLDWAVE; + break; + case NS_ooxml::LN_Value_ST_Underline_wavyDouble: + nUnderline = awt::FontUnderline::DOUBLEWAVE; + break; + } + rContext->Insert(PROP_CHAR_UNDERLINE, uno::Any(nUnderline)); +} + +void DomainMapper::handleParaJustification(const sal_Int32 nIntValue, const ::tools::SvRef<PropertyMap>& rContext, const bool bExchangeLeftRight) +{ + style::ParagraphAdjust nAdjust = style::ParagraphAdjust_LEFT; + style::ParagraphAdjust nLastLineAdjust = style::ParagraphAdjust_LEFT; + OUString aStringValue = "left"; + switch(nIntValue) + { + case NS_ooxml::LN_Value_ST_Jc_center: + nAdjust = style::ParagraphAdjust_CENTER; + aStringValue = "center"; + break; + case NS_ooxml::LN_Value_ST_Jc_right: + case NS_ooxml::LN_Value_ST_Jc_end: + nAdjust = bExchangeLeftRight ? style::ParagraphAdjust_LEFT : style::ParagraphAdjust_RIGHT; + aStringValue = "right"; + break; + case NS_ooxml::LN_Value_ST_Jc_distribute: + nLastLineAdjust = style::ParagraphAdjust_BLOCK; + [[fallthrough]]; + case NS_ooxml::LN_Value_ST_Jc_both: + nAdjust = style::ParagraphAdjust_BLOCK; + aStringValue = "both"; + break; + case NS_ooxml::LN_Value_ST_Jc_left: + case NS_ooxml::LN_Value_ST_Jc_start: + default: + nAdjust = bExchangeLeftRight ? style::ParagraphAdjust_RIGHT : style::ParagraphAdjust_LEFT; + break; + } + rContext->Insert( PROP_PARA_ADJUST, uno::Any( nAdjust ) ); + rContext->Insert( PROP_PARA_LAST_LINE_ADJUST, uno::Any( nLastLineAdjust ) ); + m_pImpl->appendGrabBag(m_pImpl->m_aInteropGrabBag, "jc", aStringValue); +} + +bool DomainMapper::getColorFromId(const Id nId, sal_Int32 &nColor) +{ + nColor = 0; + if ((nId < NS_ooxml::LN_Value_ST_HighlightColor_black) || (nId > NS_ooxml::LN_Value_ST_HighlightColor_none)) + return false; + + switch (nId) + { + case NS_ooxml::LN_Value_ST_HighlightColor_black: nColor=0x000000; break; + case NS_ooxml::LN_Value_ST_HighlightColor_blue: nColor=0x0000ff; break; + case NS_ooxml::LN_Value_ST_HighlightColor_cyan: nColor=0x00ffff; break; + case NS_ooxml::LN_Value_ST_HighlightColor_green: nColor=0x00ff00; break; + case NS_ooxml::LN_Value_ST_HighlightColor_magenta: nColor=0xff00ff; break; + case NS_ooxml::LN_Value_ST_HighlightColor_red: nColor=0xff0000; break; + case NS_ooxml::LN_Value_ST_HighlightColor_yellow: nColor=0xffff00; break; + case NS_ooxml::LN_Value_ST_HighlightColor_white: nColor=0xffffff; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkBlue: nColor=0x000080; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkCyan: nColor=0x008080; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkGreen: nColor=0x008000; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkMagenta: nColor=0x800080; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkRed: nColor=0x800000; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkYellow: nColor=0x808000; break; + case NS_ooxml::LN_Value_ST_HighlightColor_darkGray: nColor=0x808080; break; + case NS_ooxml::LN_Value_ST_HighlightColor_lightGray: nColor=0xC0C0C0; break; + case NS_ooxml::LN_Value_ST_HighlightColor_none: nColor=0xFFFFFFFF; break; //COL_AUTO + default: + return false; + } + return true; +} + +sal_Int16 DomainMapper::getEmphasisValue(const sal_Int32 nIntValue) +{ + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_Em_dot: + return text::FontEmphasis::DOT_ABOVE; + case NS_ooxml::LN_Value_ST_Em_comma: + return text::FontEmphasis::ACCENT_ABOVE; + case NS_ooxml::LN_Value_ST_Em_circle: + return text::FontEmphasis::CIRCLE_ABOVE; + case NS_ooxml::LN_Value_ST_Em_underDot: + return text::FontEmphasis::DOT_BELOW; + default: + return text::FontEmphasis::NONE; + } +} + +OUString DomainMapper::getBracketStringFromEnum(const sal_Int32 nIntValue, const bool bIsPrefix) +{ + switch(nIntValue) + { + case NS_ooxml::LN_Value_ST_CombineBrackets_round: + if (bIsPrefix) + return "("; + return ")"; + + case NS_ooxml::LN_Value_ST_CombineBrackets_square: + if (bIsPrefix) + return "["; + return "]"; + + case NS_ooxml::LN_Value_ST_CombineBrackets_angle: + if (bIsPrefix) + return "<"; + return ">"; + + case NS_ooxml::LN_Value_ST_CombineBrackets_curly: + if (bIsPrefix) + return "{"; + return "}"; + + case NS_ooxml::LN_Value_ST_CombineBrackets_none: + default: + return OUString(); + } +} + +style::TabAlign DomainMapper::getTabAlignFromValue(const sal_Int32 nIntValue) +{ + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_TabJc_start: + case NS_ooxml::LN_Value_ST_TabJc_left: + case NS_ooxml::LN_Value_ST_TabJc_bar: // bar not supported + case NS_ooxml::LN_Value_ST_TabJc_num: // num not supported + return style::TabAlign_LEFT; + case NS_ooxml::LN_Value_ST_TabJc_center: + return style::TabAlign_CENTER; + case NS_ooxml::LN_Value_ST_TabJc_end: + case NS_ooxml::LN_Value_ST_TabJc_right: + return style::TabAlign_RIGHT; + case NS_ooxml::LN_Value_ST_TabJc_decimal: + return style::TabAlign_DECIMAL; + } + return style::TabAlign_LEFT; +} + +sal_Unicode DomainMapper::getFillCharFromValue(const sal_Int32 nIntValue) +{ + switch (nIntValue) + { + case NS_ooxml::LN_Value_ST_TabTlc_dot: + return u'.'; + case NS_ooxml::LN_Value_ST_TabTlc_hyphen: + return u'-'; + case NS_ooxml::LN_Value_ST_TabTlc_underscore: + case NS_ooxml::LN_Value_ST_TabTlc_heavy: // FIXME ??? + return u'_'; + case NS_ooxml::LN_Value_ST_TabTlc_middleDot: // middleDot + return u'\x00b7'; + case NS_ooxml::LN_Value_ST_TabTlc_none: + default: + return u' '; // blank space + } +} + +bool DomainMapper::IsOOXMLImport() const +{ + return m_pImpl->IsOOXMLImport(); +} + +bool DomainMapper::IsRTFImport() const +{ + return m_pImpl->IsRTFImport(); +} + +uno::Reference < lang::XMultiServiceFactory > const & DomainMapper::GetTextFactory() const +{ + return m_pImpl->GetTextFactory(); +} + +uno::Reference< text::XTextRange > DomainMapper::GetCurrentTextRange() +{ + if (m_pImpl->HasTopText()) + return m_pImpl->GetTopTextAppend()->getEnd(); + return m_pImpl->m_xInsertTextRange; +} + +OUString DomainMapper::getOrCreateCharStyle( PropertyValueVector_t& rCharProperties, bool bAlwaysCreate ) +{ + StyleSheetTablePtr pStyleSheets = m_pImpl->GetStyleSheetTable(); + return pStyleSheets->getOrCreateCharStyle( rCharProperties, bAlwaysCreate ); +} + +StyleSheetTablePtr const & DomainMapper::GetStyleSheetTable( ) +{ + return m_pImpl->GetStyleSheetTable( ); +} + +SettingsTablePtr const & DomainMapper::GetSettingsTable() +{ + return m_pImpl->GetSettingsTable(); +} + +GraphicZOrderHelper* DomainMapper::graphicZOrderHelper() +{ + if (zOrderHelper == nullptr) + zOrderHelper.reset( new GraphicZOrderHelper ); + return zOrderHelper.get(); +} + +GraphicNamingHelper& DomainMapper::GetGraphicNamingHelper() +{ + if (m_pGraphicNamingHelper == nullptr) + m_pGraphicNamingHelper.reset(new GraphicNamingHelper()); + return *m_pGraphicNamingHelper; +} + +uno::Reference<drawing::XShape> DomainMapper::PopPendingShape() +{ + return m_pImpl->PopPendingShape(); +} + +bool DomainMapper::IsInHeaderFooter() const +{ + return m_pImpl->IsInHeaderFooter(); +} + +bool DomainMapper::IsInShape() const { return m_pImpl->IsInShape(); } + +bool DomainMapper::IsInTable() const +{ + return m_pImpl->hasTableManager() && m_pImpl->getTableManager().isInCell(); +} + +OUString DomainMapper::GetListStyleName(sal_Int32 nListId) const +{ + return m_pImpl->GetListStyleName( nListId ); +} + +void DomainMapper::ValidateListLevel(const OUString& sStyleIdentifierD) +{ + m_pImpl->ValidateListLevel(sStyleIdentifierD); +} + +void DomainMapper::SetDocDefaultsImport(bool bSet) +{ + m_pImpl->SetDocDefaultsImport(bSet); +} + +bool DomainMapper::IsStyleSheetImport() const +{ + return m_pImpl->IsStyleSheetImport(); +} + +bool DomainMapper::IsNumberingImport() const +{ + return m_pImpl->IsNumberingImport(); +} + +void DomainMapper::enableInteropGrabBag(const OUString& aName) +{ + m_pImpl->m_aInteropGrabBagName = aName; +} + +beans::PropertyValue DomainMapper::getInteropGrabBag() +{ + beans::PropertyValue aRet; + aRet.Name = m_pImpl->m_aInteropGrabBagName; + aRet.Value <<= comphelper::containerToSequence(m_pImpl->m_aInteropGrabBag); + + m_pImpl->m_aInteropGrabBag.clear(); + m_pImpl->m_aInteropGrabBagName.clear(); + return aRet; +} + +void DomainMapper::HandleRedline( Sprm& rSprm ) +{ + sal_uInt32 nSprmId = rSprm.getId(); + + m_pImpl->AddNewRedline( nSprmId ); + + if (nSprmId == NS_ooxml::LN_CT_PPr_pPrChange) + { + m_pImpl->SetCurrentRedlineToken(XML_ParagraphFormat); + } + else if (nSprmId == NS_ooxml::LN_CT_TrPr_ins) + { + m_pImpl->SetCurrentRedlineToken(XML_tableRowInsert); + } + else if (nSprmId == NS_ooxml::LN_CT_TrPr_del) + { + m_pImpl->SetCurrentRedlineToken(XML_tableRowDelete); + } + else if (nSprmId == NS_ooxml::LN_CT_TcPrBase_cellIns) + { + m_pImpl->SetCurrentRedlineToken(XML_tableCellInsert); + } + else if (nSprmId == NS_ooxml::LN_CT_TcPrBase_cellDel) + { + m_pImpl->SetCurrentRedlineToken(XML_tableCellDelete); + } + + resolveSprmProps(*this, rSprm ); + // now the properties author, date and id should be available + sal_Int32 nToken = m_pImpl->GetCurrentRedlineToken(); + switch( nToken & 0xffff ) + { + case XML_mod: + case XML_ins: + case XML_del: + case XML_moveTo: + case XML_moveFrom: + case XML_ParagraphFormat: + case XML_tableRowInsert: + case XML_tableRowDelete: + case XML_tableCellInsert: + case XML_tableCellDelete: + break; + default: OSL_FAIL( "redline token other than mod, ins, del, moveTo, moveFrom or table row" ); break; + } + m_pImpl->EndParaMarkerChange( ); + m_pImpl->SetCurrentRedlineIsRead(); +} + +void DomainMapper::finishParagraph(const bool bRemove, const bool bNoNumbering) +{ + if (m_pImpl->m_pSdtHelper->getControlType() == SdtControlType::datePicker) + m_pImpl->m_pSdtHelper->createDateContentControl(); + m_pImpl->finishParagraph(m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH), bRemove, bNoNumbering); +} + +void DomainMapper::commentProps(const OUString& sId, const CommentProperties& rProps) +{ + m_pImpl->commentProps(sId, rProps); +} + +css::uno::Reference<css::container::XNameContainer> const & DomainMapper::GetCharacterStyles() +{ + return m_pImpl->GetCharacterStyles(); +} + +OUString DomainMapper::GetUnusedCharacterStyleName() +{ + return m_pImpl->GetUnusedCharacterStyleName(); +} + +} //namespace writerfilter + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |