summaryrefslogtreecommitdiffstats
path: root/writerfilter/source
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--writerfilter/source/dmapper/DomainMapper.cxx53
-rw-r--r--writerfilter/source/dmapper/DomainMapper.hxx2
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx7
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx249
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx141
-rw-r--r--writerfilter/source/dmapper/GraphicImport.cxx7
-rw-r--r--writerfilter/source/dmapper/PropertyIds.cxx1
-rw-r--r--writerfilter/source/dmapper/PropertyIds.hxx1
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx30
-rw-r--r--writerfilter/source/dmapper/PropertyMap.hxx10
-rw-r--r--writerfilter/source/dmapper/SdtHelper.cxx4
-rw-r--r--writerfilter/source/dmapper/SdtHelper.hxx1
-rw-r--r--writerfilter/source/dmapper/SettingsTable.cxx2
-rw-r--r--writerfilter/source/dmapper/SettingsTable.hxx2
-rw-r--r--writerfilter/source/filter/WriterFilter.cxx1
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx14
-rw-r--r--writerfilter/source/ooxml/model.xml4
-rw-r--r--writerfilter/source/rtftok/rtfdispatchsymbol.cxx9
-rw-r--r--writerfilter/source/rtftok/rtfdispatchvalue.cxx12
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx41
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx2
-rw-r--r--writerfilter/source/rtftok/rtfsprm.cxx20
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx2
-rw-r--r--writerfilter/source/rtftok/rtfvalue.cxx4
24 files changed, 399 insertions, 220 deletions
diff --git a/writerfilter/source/dmapper/DomainMapper.cxx b/writerfilter/source/dmapper/DomainMapper.cxx
index 7e81cfd430..7e4eeda7d3 100644
--- a/writerfilter/source/dmapper/DomainMapper.cxx
+++ b/writerfilter/source/dmapper/DomainMapper.cxx
@@ -138,6 +138,8 @@ DomainMapper::DomainMapper( const uno::Reference< uno::XComponentContext >& xCon
m_pImpl->SetDocumentSettingsProperty("FrameAutowidthWithMorePara", uno::Any(true));
m_pImpl->SetDocumentSettingsProperty("FootnoteInColumnToPageEnd", uno::Any(true));
m_pImpl->SetDocumentSettingsProperty("TabAtLeftIndentForParagraphsInList", uno::Any(true));
+ m_pImpl->SetDocumentSettingsProperty(u"NoGapAfterNoteNumber"_ustr,
+ uno::Any(true));
// Enable only for new documents, since pasting from clipboard can influence existing doc
m_pImpl->SetDocumentSettingsProperty("NoNumberingShowFollowBy", uno::Any(true));
@@ -703,6 +705,12 @@ void DomainMapper::lcl_attribute(Id nName, Value & val)
case NS_ooxml::LN_CT_PageMar_gutter:
m_pImpl->SetPageMarginTwip( PAGE_MAR_GUTTER, nIntValue );
break;
+ case NS_ooxml::LN_CT_PaperSource_first:
+ m_pImpl->SetPaperSource(PAPER_SOURCE_FIRST, nIntValue);
+ break;
+ case NS_ooxml::LN_CT_PaperSource_other:
+ m_pImpl->SetPaperSource(PAPER_SOURCE_OTHER, 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
@@ -2419,8 +2427,6 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
}
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 )
@@ -2495,7 +2501,16 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
pSectionContext->SetGutterMargin(rPageMar.gutter);
}
break;
-
+ case NS_ooxml::LN_EG_SectPrContents_paperSrc:
+ m_pImpl->InitPaperSource();
+ resolveSprmProps(*this, rSprm);
+ OSL_ENSURE(pSectionContext, "SectionContext unavailable!");
+ if(pSectionContext)
+ {
+ const PaperSource& rPaperSource = m_pImpl->GetPaperSource();
+ pSectionContext->SetPaperSource( rPaperSource.first, rPaperSource.other );
+ }
+ break;
case NS_ooxml::LN_EG_SectPrContents_cols:
{
writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
@@ -3258,7 +3273,8 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
* 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()
+ if (m_pImpl->m_StreamStateStack.top().nTableDepth == 0
+ && m_pImpl->GetIsFirstParagraphInSection()
&& !m_pImpl->GetIsDummyParaAddedForTableInSection() && !m_pImpl->GetIsTextFrameInserted()
&& !m_pImpl->GetIsPreviousParagraphFramed() && !IsInHeaderFooter())
{
@@ -3266,7 +3282,7 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
}
// if first paragraph style in table has break-before-page, transfer that setting to the table itself.
- if( m_pImpl->m_nTableDepth == 0 )
+ if (m_pImpl->m_StreamStateStack.top().nTableDepth == 0)
{
const uno::Any aBreakType(style::BreakType_PAGE_BEFORE);
const PropertyMapPtr pParagraphProps = m_pImpl->GetTopContextOfType(CONTEXT_PARAGRAPH);
@@ -3287,11 +3303,11 @@ void DomainMapper::sprmWithProps( Sprm& rSprm, const PropertyMapPtr& rContext )
}
}
- m_pImpl->m_nTableDepth++;
+ m_pImpl->m_StreamStateStack.top().nTableDepth++;
}
break;
case NS_ooxml::LN_tblEnd:
- m_pImpl->m_nTableDepth--;
+ m_pImpl->m_StreamStateStack.top().nTableDepth--;
break;
case NS_ooxml::LN_tcStart:
m_pImpl->m_nTableCellDepth++;
@@ -4417,8 +4433,6 @@ void DomainMapper::lcl_utext(const sal_Unicode *const data_, size_t len)
xContext->Erase(PROP_NUMBERING_LEVEL);
}
finishParagraph(bRemove, bNoNumbering);
- if (bRemove)
- m_pImpl->RemoveLastParagraph();
m_pImpl->SetParaSectpr(false);
}
@@ -4483,14 +4497,24 @@ void DomainMapper::lcl_utext(const sal_Unicode *const data_, size_t len)
}
else if (m_pImpl->IsOpenFieldCommand() && !m_pImpl->IsForceGenericFields())
{
- if (bInSdtBlockText && m_pImpl->m_pSdtHelper->hasUnusedText())
- m_pImpl->m_pSdtHelper->createPlainTextControl();
+ if (bInSdtBlockText)
+ {
+ if (m_pImpl->m_pSdtHelper->hasUnusedText())
+ m_pImpl->m_pSdtHelper->createPlainTextControl();
+ else if (!m_pImpl->m_pSdtHelper->isFieldStartRangeSet())
+ m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
+ }
m_pImpl->AppendFieldCommand(sText);
}
else if( m_pImpl->IsOpenField() && m_pImpl->IsFieldResultAsString())
{
- if (bInSdtBlockText && m_pImpl->m_pSdtHelper->hasUnusedText())
- m_pImpl->m_pSdtHelper->createPlainTextControl();
+ if (bInSdtBlockText)
+ {
+ if (m_pImpl->m_pSdtHelper->hasUnusedText())
+ m_pImpl->m_pSdtHelper->createPlainTextControl();
+ else if (!m_pImpl->m_pSdtHelper->isFieldStartRangeSet())
+ m_pImpl->m_pSdtHelper->setFieldStartRange(GetCurrentTextRange()->getEnd());
+ }
/*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);
@@ -4947,6 +4971,9 @@ 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);
+ if (bRemove || mbIsLastPara)
+ m_pImpl->RemoveLastParagraph();
+ mbIsLastPara = false; // handle other subdocuments
}
void DomainMapper::commentProps(const OUString& sId, const CommentProperties& rProps)
diff --git a/writerfilter/source/dmapper/DomainMapper.hxx b/writerfilter/source/dmapper/DomainMapper.hxx
index f9c163ab1f..e19dcd44bb 100644
--- a/writerfilter/source/dmapper/DomainMapper.hxx
+++ b/writerfilter/source/dmapper/DomainMapper.hxx
@@ -83,6 +83,7 @@ public:
// Stream
virtual void markLastParagraphInSection() override;
+ virtual void markLastParagraph() override { mbIsLastPara = true; }
virtual void markLastSectionGroup() override;
// BinaryObj
@@ -188,6 +189,7 @@ private:
bool mbIsSplitPara;
bool mbHasControls;
bool mbWasShapeInPara;
+ bool mbIsLastPara = false;
std::unique_ptr< GraphicZOrderHelper > m_zOrderHelper;
OUString m_sGlossaryEntryName;
};
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 2092ba4096..e63d1cf961 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -1599,7 +1599,12 @@ void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
// m_xText points to the body text, get the current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xFrameAnchor;
- if (xTextAppendAndConvert.is())
+
+ // Writer layout has problems with redlines on floating table rows in footnotes, avoid
+ // them.
+ bool bInFootnote = m_rDMapper_Impl.IsInFootOrEndnote();
+ bool bRecordChanges = m_rDMapper_Impl.GetSettingsTable()->GetRecordChanges();
+ if (xTextAppendAndConvert.is() && !(bInFootnote && bRecordChanges))
{
std::deque<css::uno::Any> aFramedRedlines = m_rDMapper_Impl.m_aStoredRedlines[StoredRedlines::FRAME];
std::vector<sal_Int32> redPos, redLen;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index db2a712703..58568a9105 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -341,9 +341,6 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bSetCitation( false ),
m_bSetDateValue( false ),
m_bIsFirstSection( true ),
- m_bIsColumnBreakDeferred( false ),
- m_bIsPageBreakDeferred( false ),
- m_nLineBreaksDeferred( 0 ),
m_bSdtEndDeferred(false),
m_bParaSdtEndDeferred(false),
m_bStartTOC(false),
@@ -352,7 +349,6 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bStartIndex(false),
m_bStartBibliography(false),
m_nStartGenericField(0),
- m_bTextInserted(false),
m_bTextDeleted(false),
m_nLastRedlineMovedID(1),
m_sCurrentPermId(0),
@@ -361,10 +357,7 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bInStyleSheetImport( false ),
m_bInNumberingImport(false),
m_bInAnyTableImport( false ),
- m_eInHeaderFooterImport( HeaderFooterImportState::none ),
m_bDiscardHeaderFooter( false ),
- m_bInFootOrEndnote(false),
- m_bInFootnote(false),
m_bHasFootnoteStyle(false),
m_bCheckFootnoteStyle(false),
m_eSkipFootnoteState(SkipFootnoteSeparator::OFF),
@@ -377,16 +370,9 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bIsParaMarkerChange( false ),
m_bIsParaMarkerMove( false ),
m_bRedlineImageInPreviousRun( false ),
- m_bParaChanged( false ),
- m_bIsFirstParaInSection( true ),
- m_bIsFirstParaInSectionAfterRedline( true ),
m_bDummyParaAddedForTableInSection( false ),
m_bTextFrameInserted(false),
- m_bIsPreviousParagraphFramed( false ),
- m_bIsLastParaInSection( false ),
m_bIsLastSectionGroup( false ),
- m_bIsInComments( false ),
- m_bParaSectpr( false ),
m_bUsingEnhancedFields( false ),
m_bSdt(false),
m_bIsFirstRun(false),
@@ -399,7 +385,6 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bIsNewDoc(!rMediaDesc.getUnpackedValueOrDefault("InsertMode", false)),
m_bIsAltChunk(rMediaDesc.getUnpackedValueOrDefault("AltChunkMode", false)),
m_bIsReadGlossaries(rMediaDesc.getUnpackedValueOrDefault("ReadGlossaries", false)),
- m_nTableDepth(0),
m_nTableCellDepth(0),
m_bHasFtn(false),
m_bHasFtnSep(false),
@@ -407,14 +392,10 @@ DomainMapper_Impl::DomainMapper_Impl(
m_bIgnoreNextTab(false),
m_bIsSplitPara(false),
m_bIsActualParagraphFramed( false ),
- m_bParaHadField(false),
- m_bSaveParaHadField(false),
m_bParaAutoBefore(false),
- m_bFirstParagraphInCell(true),
- m_bSaveFirstParagraphInCell(false),
- m_bParaWithInlineObject(false),
m_bSaxError(false)
{
+ m_StreamStateStack.emplace(); // add state for document body
m_aBaseUrl = rMediaDesc.getUnpackedValueOrDefault(
utl::MediaDescriptor::PROP_DOCUMENTBASEURL, OUString());
if (m_aBaseUrl.isEmpty()) {
@@ -454,6 +435,7 @@ DomainMapper_Impl::DomainMapper_Impl(
DomainMapper_Impl::~DomainMapper_Impl()
{
+ assert(!m_StreamStateStack.empty());
ChainTextFrames();
// Don't remove last paragraph when pasting, sw expects that empty paragraph.
if (m_bIsNewDoc)
@@ -947,27 +929,29 @@ void DomainMapper_Impl::SetIsLastSectionGroup( bool bIsLast )
void DomainMapper_Impl::SetIsLastParagraphInSection( bool bIsLast )
{
- m_bIsLastParaInSection = bIsLast;
+ m_StreamStateStack.top().bIsLastParaInSection = bIsLast;
}
void DomainMapper_Impl::SetIsFirstParagraphInSection( bool bIsFirst )
{
- m_bIsFirstParaInSection = bIsFirst;
+ m_StreamStateStack.top().bIsFirstParaInSection = bIsFirst;
}
void DomainMapper_Impl::SetIsFirstParagraphInSectionAfterRedline( bool bIsFirstAfterRedline )
{
- m_bIsFirstParaInSectionAfterRedline = bIsFirstAfterRedline;
+ m_StreamStateStack.top().bIsFirstParaInSectionAfterRedline = bIsFirstAfterRedline;
}
bool DomainMapper_Impl::GetIsFirstParagraphInSection( bool bAfterRedline ) const
{
// Anchored objects may include multiple paragraphs,
// and none of them should be considered the first para in section.
- return ( bAfterRedline ? m_bIsFirstParaInSectionAfterRedline : m_bIsFirstParaInSection )
+ return (bAfterRedline
+ ? m_StreamStateStack.top().bIsFirstParaInSectionAfterRedline
+ : m_StreamStateStack.top().bIsFirstParaInSection)
&& !IsInShape()
- && !m_bIsInComments
+ && !IsInComments()
&& !IsInFootOrEndnote();
}
@@ -987,13 +971,11 @@ void DomainMapper_Impl::SetIsTextFrameInserted( bool bIsInserted )
m_bTextFrameInserted = bIsInserted;
}
-
void DomainMapper_Impl::SetParaSectpr(bool bParaSectpr)
{
- m_bParaSectpr = bParaSectpr;
+ m_StreamStateStack.top().bParaSectpr = bParaSectpr;
}
-
void DomainMapper_Impl::SetSdt(bool bSdt)
{
m_bSdt = bSdt;
@@ -1599,21 +1581,22 @@ ListsManager::Pointer const & DomainMapper_Impl::GetListTable()
void DomainMapper_Impl::deferBreak( BreakType deferredBreakType)
{
+ assert(!m_StreamStateStack.empty());
switch (deferredBreakType)
{
case LINE_BREAK:
- m_nLineBreaksDeferred++;
+ m_StreamStateStack.top().nLineBreaksDeferred++;
break;
case COLUMN_BREAK:
- m_bIsColumnBreakDeferred = true;
+ m_StreamStateStack.top().bIsColumnBreakDeferred = true;
break;
case PAGE_BREAK:
// See SwWW8ImplReader::HandlePageBreakChar(), page break should be
// ignored inside tables.
- if (m_nTableDepth > 0)
+ if (0 < m_StreamStateStack.top().nTableDepth)
return;
- m_bIsPageBreakDeferred = true;
+ m_StreamStateStack.top().bIsPageBreakDeferred = true;
break;
default:
return;
@@ -1622,14 +1605,15 @@ void DomainMapper_Impl::deferBreak( BreakType deferredBreakType)
bool DomainMapper_Impl::isBreakDeferred( BreakType deferredBreakType )
{
+ assert(!m_StreamStateStack.empty());
switch (deferredBreakType)
{
case LINE_BREAK:
- return m_nLineBreaksDeferred > 0;
+ return 0 < m_StreamStateStack.top().nLineBreaksDeferred;
case COLUMN_BREAK:
- return m_bIsColumnBreakDeferred;
+ return m_StreamStateStack.top().bIsColumnBreakDeferred;
case PAGE_BREAK:
- return m_bIsPageBreakDeferred;
+ return m_StreamStateStack.top().bIsPageBreakDeferred;
default:
return false;
}
@@ -1637,17 +1621,18 @@ bool DomainMapper_Impl::isBreakDeferred( BreakType deferredBreakType )
void DomainMapper_Impl::clearDeferredBreak(BreakType deferredBreakType)
{
+ assert(!m_StreamStateStack.empty());
switch (deferredBreakType)
{
case LINE_BREAK:
- assert(m_nLineBreaksDeferred > 0);
- m_nLineBreaksDeferred--;
+ assert(0 < m_StreamStateStack.top().nLineBreaksDeferred);
+ m_StreamStateStack.top().nLineBreaksDeferred--;
break;
case COLUMN_BREAK:
- m_bIsColumnBreakDeferred = false;
+ m_StreamStateStack.top().bIsColumnBreakDeferred = false;
break;
case PAGE_BREAK:
- m_bIsPageBreakDeferred = false;
+ m_StreamStateStack.top().bIsPageBreakDeferred = false;
break;
default:
break;
@@ -1656,9 +1641,10 @@ void DomainMapper_Impl::clearDeferredBreak(BreakType deferredBreakType)
void DomainMapper_Impl::clearDeferredBreaks()
{
- m_nLineBreaksDeferred = 0;
- m_bIsColumnBreakDeferred = false;
- m_bIsPageBreakDeferred = false;
+ assert(!m_StreamStateStack.empty());
+ m_StreamStateStack.top().nLineBreaksDeferred = 0;
+ m_StreamStateStack.top().bIsColumnBreakDeferred = false;
+ m_StreamStateStack.top().bIsPageBreakDeferred = false;
}
void DomainMapper_Impl::setSdtEndDeferred(bool bSdtEndDeferred)
@@ -1731,7 +1717,11 @@ static void lcl_MoveBorderPropertiesToFrame(std::vector<beans::PropertyValue>& r
aValue.Name = sPropertyName;
aValue.Value = xTextRangeProperties->getPropertyValue(sPropertyName);
if( nProperty < 4 )
+ {
xTextRangeProperties->setPropertyValue( sPropertyName, uno::Any(table::BorderLine2()));
+ if (!aValue.Value.hasValue())
+ aValue.Value <<= table::BorderLine2();
+ }
else // border spacing
{
sal_Int32 nDistance = 0;
@@ -2356,7 +2346,9 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
{
if ( GetIsFirstParagraphInShape() ||
(GetIsFirstParagraphInSection() && GetSectionContext() && GetSectionContext()->IsFirstSection()) ||
- (m_bFirstParagraphInCell && m_nTableDepth > 0 && m_nTableDepth == m_nTableCellDepth) )
+ (m_StreamStateStack.top().bFirstParagraphInCell
+ && 0 < m_StreamStateStack.top().nTableDepth
+ && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth))
{
// export requires grabbag to match top_margin, so keep them in sync
if (nBeforeAutospacing && bIsAutoSet)
@@ -2609,7 +2601,8 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
else
{
uno::Reference<text::XTextCursor> xCursor;
- if (m_bParaHadField && !m_bIsInComments && !m_xTOCMarkerCursor.is())
+ if (m_StreamStateStack.top().bParaHadField
+ && !IsInComments() && !m_xTOCMarkerCursor.is())
{
// Workaround to make sure char props of the field are not lost.
// Not relevant for editeng-based comments.
@@ -2651,9 +2644,10 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
TOOLS_WARN_EXCEPTION("writerfilter", "DomainMapper_Impl::finishParagraph NumberingRules");
}
}
- else if ( m_xPreviousParagraph->getPropertySetInfo()->hasPropertyByName("NumberingStyleName") &&
+ else if (m_xPreviousParagraph->getPropertySetInfo()->hasPropertyByName("NumberingStyleName")
// don't update before tables
- (m_nTableDepth == 0 || !m_bFirstParagraphInCell))
+ && (m_StreamStateStack.top().nTableDepth == 0
+ || !m_StreamStateStack.top().bFirstParagraphInCell))
{
aCurrentNumberingName = GetListStyleName(nListId);
m_xPreviousParagraph->getPropertyValue("NumberingStyleName") >>= aPreviousNumberingName;
@@ -2808,7 +2802,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
// tdf#77417 trim right white spaces in table cells in 2010 compatibility mode
sal_Int32 nMode = GetSettingsTable()->GetWordCompatibilityMode();
- if ( m_nTableDepth > 0 && nMode > 0 && nMode <= 14 )
+ if (0 < m_StreamStateStack.top().nTableDepth && 0 < nMode && nMode <= 14)
{
// skip new line
xCur->goLeft(1, false);
@@ -2829,7 +2823,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
xCur->goLeft( 1 , true );
// Extend the redline ranges for empty paragraphs
- if ( !m_bParaChanged && m_previousRedline )
+ if (!m_StreamStateStack.top().bParaChanged && m_previousRedline)
CreateRedline( xCur, m_previousRedline );
CheckParaMarkerRedline( xCur );
}
@@ -2837,8 +2831,9 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
css::uno::Reference<css::beans::XPropertySet> xParaProps(xTextRange, uno::UNO_QUERY);
// table style precedence and not hidden shapes anchored to hidden empty table paragraphs
- if (xParaProps && !m_bIsInComments
- && (m_nTableDepth > 0 || !m_aAnchoredObjectAnchors.empty()))
+ if (xParaProps && !IsInComments()
+ && (0 < m_StreamStateStack.top().nTableDepth
+ || !m_aAnchoredObjectAnchors.empty()))
{
// table style has got bigger precedence than docDefault style
// collect these pending paragraph properties to process in endTable()
@@ -2848,7 +2843,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
uno::Reference<text::XTextCursor> xCur2 = xTextRange->getText()->createTextCursorByRange(xCur);
uno::Reference<text::XParagraphCursor> xParaCursor(xCur2, uno::UNO_QUERY_THROW);
xParaCursor->gotoStartOfParagraph(false);
- if (m_nTableDepth > 0)
+ if (0 < m_StreamStateStack.top().nTableDepth)
{
TableParagraph aPending{xParaCursor, xCur, pParaContext, xParaProps};
getTableManager().getCurrentParagraphs()->push_back(aPending);
@@ -2972,23 +2967,23 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
else
SetIsPreviousParagraphFramed(false);
- m_bRemoveThisParagraph = false;
+ m_StreamStateStack.top().bRemoveThisParagraph = false;
if( !IsInHeaderFooter() && !IsInShape()
&& (!pParaContext || !pParaContext->props().IsFrameMode()) )
{ // If the paragraph is in a frame, shape or header/footer, it's not a paragraph of the section itself.
SetIsFirstParagraphInSection(false);
// don't count an empty deleted paragraph as first paragraph in section to avoid of
// the deletion of the next empty paragraph later, resulting loss of the associated page break
- if (!m_previousRedline || m_bParaChanged)
+ if (!m_previousRedline || m_StreamStateStack.top().bParaChanged)
{
SetIsFirstParagraphInSectionAfterRedline(false);
SetIsLastParagraphInSection(false);
}
}
m_previousRedline.clear();
- m_bParaChanged = false;
+ m_StreamStateStack.top().bParaChanged = false;
- if (m_bIsInComments && pParaContext)
+ if (IsInComments() && pParaContext)
{
if (const OUString sParaId = pParaContext->props().GetParaId(); !sParaId.isEmpty())
{
@@ -3011,15 +3006,19 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
}
SetIsOutsideAParagraph(true);
- m_bParaHadField = false;
+ m_StreamStateStack.top().bParaHadField = false;
// don't overwrite m_bFirstParagraphInCell in table separator nodes
// and in text boxes anchored to the first paragraph of table cells
- if (m_nTableDepth > 0 && m_nTableDepth == m_nTableCellDepth && !IsInShape() && !m_bIsInComments)
- m_bFirstParagraphInCell = false;
+ if (0 < m_StreamStateStack.top().nTableDepth
+ && m_StreamStateStack.top().nTableDepth == m_nTableCellDepth
+ && !IsInShape() && !IsInComments())
+ {
+ m_StreamStateStack.top().bFirstParagraphInCell = false;
+ }
m_bParaAutoBefore = false;
- m_bParaWithInlineObject = false;
+ m_StreamStateStack.top().bParaWithInlineObject = false;
#ifdef DBG_UTIL
TagLogger::getInstance().endElement();
@@ -3187,7 +3186,7 @@ void DomainMapper_Impl::applyToggleAttributes(const PropertyMapPtr& pPropertyMap
{
applyToggleAttributes(pPropertyMap);
// If we are in comments, then disable CharGrabBag, comment text doesn't support that.
- uno::Sequence< beans::PropertyValue > aValues = pPropertyMap->GetPropertyValues(/*bCharGrabBag=*/!m_bIsInComments);
+ uno::Sequence<beans::PropertyValue> aValues = pPropertyMap->GetPropertyValues(/*bCharGrabBag=*/!IsInComments());
if (IsInTOC() || m_bStartIndex || m_bStartBibliography)
for( auto& rValue : asNonConstRange(aValues) )
@@ -3254,11 +3253,14 @@ void DomainMapper_Impl::applyToggleAttributes(const PropertyMapPtr& pPropertyMap
{
xTOCTextCursor->goLeft(1, false);
}
- xTextRange = xTextAppend->insertTextPortion(rString, aValues, xTOCTextCursor);
+ if (IsInComments())
+ xTextRange = xTextAppend->finishParagraphInsert(aValues, xTOCTextCursor);
+ else
+ xTextRange = xTextAppend->insertTextPortion(rString, aValues, xTOCTextCursor);
SAL_WARN_IF(!xTextRange.is(), "writerfilter.dmapper", "insertTextPortion failed");
if (!xTextRange.is())
throw uno::Exception("insertTextPortion failed", nullptr);
- m_bTextInserted = true;
+ m_StreamStateStack.top().bTextInserted = true;
xTOCTextCursor->gotoRange(xTextRange->getEnd(), true);
if (m_nStartGenericField == 0)
{
@@ -3299,7 +3301,7 @@ void DomainMapper_Impl::applyToggleAttributes(const PropertyMapPtr& pPropertyMap
m_pParaMarkerRedlineMove.clear();
}
CheckRedline( xTextRange );
- m_bParaChanged = true;
+ m_StreamStateStack.top().bParaChanged = true;
//getTableManager( ).handle(xTextRange);
}
@@ -3779,11 +3781,6 @@ bool isContentEmpty(uno::Reference<text::XText> const& xText, uno::Reference<tex
void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, PageType eType)
{
- m_bSaveParaHadField = m_bParaHadField;
- m_aHeaderFooterStack.push(HeaderFooterContext(m_bTextInserted, m_nTableDepth));
- m_bTextInserted = false;
- m_nTableDepth = 0;
-
bool bHeader = ePagePartType == PagePartType::Header;
const PropertyIds ePropIsOn = bHeader ? PROP_HEADER_IS_ON: PROP_FOOTER_IS_ON;
@@ -3793,7 +3790,7 @@ void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, PageTyp
const PropertyIds ePropTextRight = bHeader ? PROP_HEADER_TEXT: PROP_FOOTER_TEXT;
m_bDiscardHeaderFooter = true;
- m_eInHeaderFooterImport = bHeader ? HeaderFooterImportState::header : HeaderFooterImportState::footer;
+ m_StreamStateStack.top().eSubstreamType = bHeader ? SubstreamType::Header : SubstreamType::Footer;
//get the section context
SectionPropertyMap* pSectionContext = GetSectionContext();;
@@ -3822,7 +3819,10 @@ void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, PageTyp
if (eType == PageType::LEFT)
{
if (bHeader)
+ {
pSectionContext->m_bLeftHeader = true;
+ pSectionContext->m_bHadLeftHeader = true;
+ }
else
pSectionContext->m_bLeftFooter = true;
@@ -3831,7 +3831,10 @@ void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, PageTyp
else if (eType == PageType::FIRST)
{
if (bHeader)
+ {
pSectionContext->m_bFirstHeader = true;
+ pSectionContext->m_bHadFirstHeader = true;
+ }
else
pSectionContext->m_bFirstFooter = true;
@@ -3840,7 +3843,10 @@ void DomainMapper_Impl::PushPageHeaderFooter(PagePartType ePagePartType, PageTyp
else
{
if (bHeader)
+ {
pSectionContext->m_bRightHeader = true;
+ pSectionContext->m_bHadRightHeader = true;
+ }
else
pSectionContext->m_bRightFooter = true;
@@ -3942,25 +3948,13 @@ void DomainMapper_Impl::PopPageHeaderFooter(PagePartType ePagePartType, PageType
}
m_bDiscardHeaderFooter = false;
}
- m_eInHeaderFooterImport = HeaderFooterImportState::none;
-
- if (!m_aHeaderFooterStack.empty())
- {
- m_bTextInserted = m_aHeaderFooterStack.top().getTextInserted();
- m_nTableDepth = m_aHeaderFooterStack.top().getTableDepth();
- m_aHeaderFooterStack.pop();
- }
-
- m_bParaHadField = m_bSaveParaHadField;
}
void DomainMapper_Impl::PushFootOrEndnote( bool bIsFootnote )
{
- SAL_WARN_IF(m_bInFootOrEndnote, "writerfilter.dmapper", "PushFootOrEndnote() is called from another foot or endnote");
- m_bInFootOrEndnote = true;
- m_bInFootnote = bIsFootnote;
+ SAL_WARN_IF(m_StreamStateStack.top().eSubstreamType != SubstreamType::Body, "writerfilter.dmapper", "PushFootOrEndnote() is called from another foot or endnote");
+ m_StreamStateStack.top().eSubstreamType = bIsFootnote ? SubstreamType::Footnote : SubstreamType::Endnote;
m_bCheckFirstFootnoteTab = true;
- m_bSaveFirstParagraphInCell = m_bFirstParagraphInCell;
try
{
// Redlines outside the footnote should not affect footnote content
@@ -4108,7 +4102,7 @@ void DomainMapper_Impl::CreateRedline(uno::Reference<text::XTextRange> const& xR
}
// store frame and (possible floating) table redline data for restoring them after frame conversion
enum StoredRedlines eType;
- if (m_bIsActualParagraphFramed || m_nTableDepth > 0)
+ if (m_bIsActualParagraphFramed || 0 < m_StreamStateStack.top().nTableDepth)
eType = StoredRedlines::FRAME;
else if (IsInFootOrEndnote())
eType = IsInFootnote() ? StoredRedlines::FOOTNOTE : StoredRedlines::ENDNOTE;
@@ -4166,7 +4160,8 @@ void DomainMapper_Impl::CheckRedline( uno::Reference< text::XTextRange > const&
// only export ParagraphFormat, when there is no other redline in the same text portion to avoid missing redline compression,
// but always export the first ParagraphFormat redline in a paragraph to keep the paragraph style change data for rejection
- if( (!bUsedRange || !m_bParaChanged) && GetTopContextOfType(CONTEXT_PARAGRAPH) )
+ if ((!bUsedRange || !m_StreamStateStack.top().bParaChanged)
+ && GetTopContextOfType(CONTEXT_PARAGRAPH))
{
std::vector<RedlineParamsPtr>& avRedLines = GetTopContextOfType(CONTEXT_PARAGRAPH)->Redlines();
for( const auto& rRedline : avRedLines )
@@ -4225,7 +4220,7 @@ void DomainMapper_Impl::PushAnnotation()
{
try
{
- m_bIsInComments = true;
+ m_StreamStateStack.top().eSubstreamType = SubstreamType::Annotation;
if (!GetTextFactory().is())
return;
m_xAnnotationField.set( GetTextFactory()->createInstance( "com.sun.star.text.TextField.Annotation" ),
@@ -4487,16 +4482,13 @@ void DomainMapper_Impl::PopFootOrEndnote()
}
m_aRedlines.pop();
m_eSkipFootnoteState = SkipFootnoteSeparator::OFF;
- m_bInFootOrEndnote = m_bInFootnote = false;
m_pFootnoteContext = nullptr;
- m_bFirstParagraphInCell = m_bSaveFirstParagraphInCell;
}
void DomainMapper_Impl::PopAnnotation()
{
RemoveLastParagraph();
- m_bIsInComments = false;
m_aTextAppendStack.pop();
try
@@ -4814,7 +4806,7 @@ void DomainMapper_Impl::PushShapeContext( const uno::Reference< drawing::XShape
getPropertyName( PROP_OPAQUE ),
uno::Any( true ) );
}
- m_bParaChanged = true;
+ m_StreamStateStack.top().bParaChanged = true;
getTableManager().setIsInShape(true);
}
catch ( const uno::Exception& )
@@ -4964,7 +4956,7 @@ bool DomainMapper_Impl::IsDiscardHeaderFooter() const
void DomainMapper_Impl::ClearPreviousParagraph()
{
// in table cells, set bottom auto margin of last paragraph to 0, except in paragraphs with numbering
- if ((m_nTableDepth == (m_nTableCellDepth + 1))
+ if ((m_StreamStateStack.top().nTableDepth == (m_nTableCellDepth + 1))
&& m_xPreviousParagraph.is()
&& hasTableManager() && getTableManager().isCellLastParaAfterAutospacing())
{
@@ -4976,7 +4968,7 @@ void DomainMapper_Impl::ClearPreviousParagraph()
m_xPreviousParagraph.clear();
// next table paragraph will be first paragraph in a cell
- m_bFirstParagraphInCell = true;
+ m_StreamStateStack.top().bFirstParagraphInCell = true;
}
void DomainMapper_Impl::HandleAltChunk(const OUString& rStreamName)
@@ -5926,7 +5918,7 @@ uno::Reference<beans::XPropertySet> DomainMapper_Impl::FindOrCreateFieldMaster(c
void DomainMapper_Impl::PushFieldContext()
{
- m_bParaHadField = true;
+ m_StreamStateStack.top().bParaHadField = true;
if(m_bDiscardHeaderFooter)
return;
#ifdef DBG_UTIL
@@ -5971,18 +5963,6 @@ void DomainMapper_Impl::SetFieldLocked()
m_aFieldStack.back()->SetFieldLocked();
}
-HeaderFooterContext::HeaderFooterContext(bool bTextInserted, sal_Int32 nTableDepth)
- : m_bTextInserted(bTextInserted)
- , m_nTableDepth(nTableDepth)
-{
-}
-
-bool HeaderFooterContext::getTextInserted() const
-{
- return m_bTextInserted;
-}
-
-sal_Int32 HeaderFooterContext::getTableDepth() const { return m_nTableDepth; }
FieldContext::FieldContext(uno::Reference< text::XTextRange > xStart)
: m_bFieldCommandCompleted(false)
@@ -6809,15 +6789,15 @@ OUString DomainMapper_Impl::extractTocTitle()
css::uno::Reference<css::beans::XPropertySet>
DomainMapper_Impl::StartIndexSectionChecked(const OUString& sServiceName)
{
- if (m_bParaChanged)
+ if (m_StreamStateStack.top().bParaChanged)
{
- finishParagraph(GetTopContextOfType(CONTEXT_PARAGRAPH), false); // resets m_bParaChanged
+ finishParagraph(GetTopContextOfType(CONTEXT_PARAGRAPH), false); // resets bParaChanged
PopProperties(CONTEXT_PARAGRAPH);
PushProperties(CONTEXT_PARAGRAPH);
SetIsFirstRun(true);
// The first paragraph of the index that is continuation of just finished one needs to be
- // removed when finished (unless more content will arrive, which will set m_bParaChanged)
- m_bRemoveThisParagraph = true;
+ // removed when finished (unless more content will arrive, which will set bParaChanged)
+ m_StreamStateStack.top().bRemoveThisParagraph = true;
}
const auto& xTextAppend = GetTopTextAppend();
const auto xTextRange = xTextAppend->getEnd();
@@ -7051,7 +7031,7 @@ void DomainMapper_Impl::handleToc
m_bStartTOC = true;
pContext->SetTOC(xTOC);
- m_bParaHadField = false;
+ m_StreamStateStack.top().bParaHadField = false;
if (!xTOC)
return;
@@ -7284,7 +7264,7 @@ void DomainMapper_Impl::handleBibliography
xTOC->setPropertyValue(getPropertyName( PROP_TITLE ), uno::Any(OUString()));
pContext->SetTOC( xTOC );
- m_bParaHadField = false;
+ m_StreamStateStack.top().bParaHadField = false;
uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
appendTextContent(xToInsert, uno::Sequence< beans::PropertyValue >() );
@@ -7327,7 +7307,7 @@ void DomainMapper_Impl::handleIndex
}
}
pContext->SetTOC( xTOC );
- m_bParaHadField = false;
+ m_StreamStateStack.top().bParaHadField = false;
uno::Reference< text::XTextContent > xToInsert( xTOC, uno::UNO_QUERY );
appendTextContent(xToInsert, uno::Sequence< beans::PropertyValue >() );
@@ -8345,7 +8325,7 @@ void DomainMapper_Impl::CloseFieldCommand()
}
}
else
- m_bParaHadField = false;
+ m_StreamStateStack.top().bParaHadField = false;
}
}
catch( const uno::Exception& )
@@ -8642,7 +8622,7 @@ void DomainMapper_Impl::PopFieldContext()
if (m_bStartedTOC || m_bStartIndex || m_bStartBibliography)
{
// inside SDT, last empty paragraph is also part of index
- if (!m_bParaChanged && !m_xSdtEntryStart)
+ if (!m_StreamStateStack.top().bParaChanged && !m_xSdtEntryStart)
{
// End of index is the first item on a new paragraph - this paragraph
// should not be part of index
@@ -8667,8 +8647,8 @@ void DomainMapper_Impl::PopFieldContext()
}
m_bStartedTOC = false;
m_aTextAppendStack.pop();
- m_bTextInserted = false;
- m_bParaChanged = true; // the paragraph must stay anyway
+ m_StreamStateStack.top().bTextInserted = false;
+ m_StreamStateStack.top().bParaChanged = true; // the paragraph must stay anyway
}
m_bStartTOC = false;
m_bStartIndex = false;
@@ -8789,9 +8769,9 @@ void DomainMapper_Impl::PopFieldContext()
{
--m_nStartGenericField;
PopFieldmark(m_aTextAppendStack, xCrsr, pContext->GetFieldId());
- if(m_bTextInserted)
+ if (m_StreamStateStack.top().bTextInserted)
{
- m_bTextInserted = false;
+ m_StreamStateStack.top().bTextInserted = false;
}
}
}
@@ -8871,8 +8851,10 @@ void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
* iff the first element in the section is a table. If the dummy para is not added yet, then add it;
* So bookmark is not attached to the wrong paragraph.
*/
- if(hasTableManager() && getTableManager().isInCell() && m_nTableDepth == 0 && GetIsFirstParagraphInSection()
- && !GetIsDummyParaAddedForTableInSection() &&!GetIsTextFrameInserted())
+ if (hasTableManager() && getTableManager().isInCell()
+ && m_StreamStateStack.top().nTableDepth == 0
+ && GetIsFirstParagraphInSection()
+ && !GetIsDummyParaAddedForTableInSection() && !GetIsTextFrameInserted())
{
AddDummyParaForTableInSection();
}
@@ -8913,8 +8895,11 @@ void DomainMapper_Impl::StartOrEndBookmark( const OUString& rId )
// keep bookmark range, if it doesn't exceed cell boundary
uno::Reference< text::XTextRange > xStart = xCursor->getStart();
xCursor->goLeft( 1, false );
- if (m_nTableDepth == 0 || !m_bFirstParagraphInCell)
+ if (m_StreamStateStack.top().nTableDepth == 0
+ || !m_StreamStateStack.top().bFirstParagraphInCell)
+ {
xCursor->gotoRange(xStart, true );
+ }
}
uno::Reference< container::XNamed > xBkmNamed( xBookmark, uno::UNO_QUERY_THROW );
SAL_WARN_IF(aBookmarkIter->second.m_sBookmarkName.isEmpty(), "writerfilter.dmapper", "anonymous bookmark");
@@ -8992,7 +8977,8 @@ void DomainMapper_Impl::startOrEndPermissionRange(sal_Int32 permissinId)
* if the first element in the section is a table. If the dummy para is not added yet, then add it;
* So permission is not attached to the wrong paragraph.
*/
- if (getTableManager().isInCell() && m_nTableDepth == 0 && GetIsFirstParagraphInSection()
+ if (getTableManager().isInCell()
+ && m_StreamStateStack.top().nTableDepth == 0 && GetIsFirstParagraphInSection()
&& !GetIsDummyParaAddedForTableInSection() && !GetIsTextFrameInserted())
{
AddDummyParaForTableInSection();
@@ -9259,7 +9245,7 @@ void DomainMapper_Impl::ImportGraphic(const writerfilter::Reference<Properties>
}
else if (m_eGraphicImportType == IMPORT_AS_DETECTED_INLINE)
{
- m_bParaWithInlineObject = true;
+ m_StreamStateStack.top().bParaWithInlineObject = true;
// store inline images with track changes, because the anchor point
// to set redlining is not available yet
@@ -9331,6 +9317,14 @@ void DomainMapper_Impl::SetPageMarginTwip( PageMarElement eElement, sal_Int32 nV
}
}
+void DomainMapper_Impl::SetPaperSource(PaperSourceElement eElement, sal_Int32 nValue)
+{
+ if(eElement == PAPER_SOURCE_FIRST)
+ m_aPaperSource.first = nValue;
+ else
+ m_aPaperSource.other = nValue;
+}
+
PageMar::PageMar()
: top(ConversionHelper::convertTwipToMM100( sal_Int32(1440)))
@@ -9751,6 +9745,8 @@ void DomainMapper_Impl::substream(Id rName,
appendTableHandler();
getTableManager().startLevel();
+ m_StreamStateStack.emplace();
+
//import of page header/footer
//Ensure that only one header/footer per section is pushed
@@ -9781,8 +9777,12 @@ void DomainMapper_Impl::substream(Id rName,
case NS_ooxml::LN_annotation :
PushAnnotation();
break;
+ default:
+ assert(false); // unexpected?
}
+ assert(m_StreamStateStack.top().eSubstreamType != SubstreamType::Body);
+
try
{
ref->resolve(m_rDMapper);
@@ -9822,6 +9822,9 @@ void DomainMapper_Impl::substream(Id rName,
break;
}
+ assert(!m_StreamStateStack.empty());
+ m_StreamStateStack.pop();
+
getTableManager().endLevel();
popTableManager();
m_bHasFtn = bHasFtn;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index fbca4aa1f3..082eda8fc5 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -103,6 +103,23 @@ enum PageMarElement
PAGE_MAR_GUTTER
};
+struct PaperSource
+{
+ sal_Int32 first;
+ sal_Int32 other;
+ public:
+ PaperSource() :
+ first(0),
+ other(0)
+ {}
+};
+
+enum PaperSourceElement
+{
+ PAPER_SOURCE_FIRST,
+ PAPER_SOURCE_OTHER,
+};
+
/// property stack element
enum ContextType
{
@@ -146,22 +163,57 @@ enum StoredRedlines
NONE
};
+enum class SubstreamType
+{
+ Body,
+ Header,
+ Footer,
+ Footnote,
+ Endnote,
+ Annotation,
+};
+
/**
* Storage for state that is relevant outside a header/footer, but not inside it.
*
* In case some state of DomainMapper_Impl should be reset before handling the
* header/footer and should be restored once handling of header/footer is done,
* then you can use this class to do so.
+ *
+ * note: presumably more state should be moved here.
*/
-class HeaderFooterContext
+struct SubstreamContext
{
- bool m_bTextInserted;
- sal_Int32 m_nTableDepth;
-
-public:
- explicit HeaderFooterContext(bool bTextInserted, sal_Int32 nTableDepth);
- bool getTextInserted() const;
- sal_Int32 getTableDepth() const;
+ SubstreamType eSubstreamType = SubstreamType::Body;
+ bool bTextInserted = false;
+ /**
+ * This contains the raw table depth. nTableDepth > 0 is the same as
+ * getTableManager().isInTable(), unless we're in the first paragraph of a
+ * table, or first paragraph after a table, as the table manager is only
+ * updated once we ended the paragraph (and know if the para has the
+ * inTbl SPRM or not).
+ */
+ sal_Int32 nTableDepth = 0;
+ // deferred breaks need to be saved for RTF, also for DOCX annotations
+ bool bIsColumnBreakDeferred = false;
+ bool bIsPageBreakDeferred = false;
+ sal_Int32 nLineBreaksDeferred = 0;
+ /// Current paragraph had at least one field in it.
+ bool bParaHadField = false;
+ /// Current paragraph in a table is first paragraph of a cell
+ bool bFirstParagraphInCell = true;
+ /// If the current paragraph has any runs.
+ bool bParaChanged = false;
+ bool bIsFirstParaInSectionAfterRedline = true;
+ bool bIsFirstParaInSection = true;
+ bool bIsLastParaInSection = false;
+ /// If the current paragraph contains section property definitions.
+ bool bParaSectpr = false;
+ bool bIsPreviousParagraphFramed = false;
+ /// Current paragraph had at least one inline object in it.
+ bool bParaWithInlineObject = false;
+ /// This is a continuation of already finished paragraph - e.g., first in an index section
+ bool bRemoveThisParagraph = false;
};
/// Information about a paragraph to be finished after a field end.
@@ -460,7 +512,9 @@ private:
std::stack<TextAppendContext> m_aTextAppendStack;
std::stack<AnchoredContext> m_aAnchoredStack;
- std::stack<HeaderFooterContext> m_aHeaderFooterStack;
+public: // DomainMapper needs it
+ std::stack<SubstreamContext> m_StreamStateStack;
+private:
std::stack<std::pair<TextAppendContext, PagePartType>> m_aHeaderFooterTextAppendStack;
std::deque<FieldContextPtr> m_aFieldStack;
@@ -471,9 +525,6 @@ private:
bool m_bSetCitation;
bool m_bSetDateValue;
bool m_bIsFirstSection;
- bool m_bIsColumnBreakDeferred;
- bool m_bIsPageBreakDeferred;
- sal_Int32 m_nLineBreaksDeferred;
/// If we want to set "sdt end" on the next character context.
bool m_bSdtEndDeferred;
/// If we want to set "paragraph sdt end" on the next paragraph context.
@@ -485,7 +536,6 @@ private:
bool m_bStartIndex;
bool m_bStartBibliography;
unsigned int m_nStartGenericField;
- bool m_bTextInserted;
bool m_bTextDeleted;
LineNumberSettings m_aLineNumberSettings;
@@ -504,6 +554,7 @@ private:
OUString m_sCurrentPermEdGrp;
PageMar m_aPageMargins;
+ PaperSource m_aPaperSource;
SymbolData m_aSymbolData;
// TableManagers are stacked: one for each stream to avoid any confusion
@@ -537,15 +588,7 @@ private:
bool m_bInStyleSheetImport; //in import of fonts, styles, lists or lfos
bool m_bInNumberingImport; //in import of numbering (i.e. numbering.xml)
bool m_bInAnyTableImport; //in import of fonts, styles, lists or lfos
- enum class HeaderFooterImportState
- {
- none,
- header,
- footer,
- } m_eInHeaderFooterImport;
bool m_bDiscardHeaderFooter;
- bool m_bInFootOrEndnote;
- bool m_bInFootnote;
PropertyMapPtr m_pFootnoteContext;
bool m_bHasFootnoteStyle;
bool m_bCheckFootnoteStyle;
@@ -583,26 +626,15 @@ private:
// text ZWSPs to keep the change tracking of the image in Writer.)
bool m_bRedlineImageInPreviousRun;
- /// If the current paragraph has any runs.
- bool m_bParaChanged;
- bool m_bIsFirstParaInSection;
- bool m_bIsFirstParaInSectionAfterRedline;
bool m_bIsFirstParaInShape = false;
bool m_bDummyParaAddedForTableInSection;
bool m_bTextFrameInserted;
- bool m_bIsPreviousParagraphFramed;
- bool m_bIsLastParaInSection;
bool m_bIsLastSectionGroup;
- bool m_bIsInComments;
- /// If the current paragraph contains section property definitions.
- bool m_bParaSectpr;
bool m_bUsingEnhancedFields;
/// If the current paragraph is inside a structured document element.
bool m_bSdt;
bool m_bIsFirstRun;
bool m_bIsOutsideAParagraph;
- /// This is a continuation of already finished paragraph - e.g., first in an index section
- bool m_bRemoveThisParagraph = false;
css::uno::Reference< css::text::XTextCursor > m_xTOCMarkerCursor;
@@ -701,7 +733,7 @@ public:
void SetIsDecimalComma() { m_bIsDecimalComma = true; };
void SetIsLastParagraphInSection( bool bIsLast );
- bool GetIsLastParagraphInSection() const { return m_bIsLastParaInSection;}
+ bool GetIsLastParagraphInSection() const { return m_StreamStateStack.top().bIsLastParaInSection; }
void SetRubySprmId( sal_uInt32 nSprmId) { m_aRubyInfo.nSprmId = nSprmId ; }
void SetRubyText( OUString const &sText, OUString const &sStyle) {
m_aRubyInfo.sRubyText = sText;
@@ -725,10 +757,11 @@ public:
bool GetIsTextFrameInserted() const { return m_bTextFrameInserted;}
void SetIsTextDeleted(bool bIsTextDeleted) { m_bTextDeleted = bIsTextDeleted; }
- void SetIsPreviousParagraphFramed( bool bIsFramed ) { m_bIsPreviousParagraphFramed = bIsFramed; }
- bool GetIsPreviousParagraphFramed() const { return m_bIsPreviousParagraphFramed; }
+ void SetIsPreviousParagraphFramed(bool const bIsFramed)
+ { m_StreamStateStack.top().bIsPreviousParagraphFramed = bIsFramed; }
+ bool GetIsPreviousParagraphFramed() const { return m_StreamStateStack.top().bIsPreviousParagraphFramed; }
void SetParaSectpr(bool bParaSectpr);
- bool GetParaSectpr() const { return m_bParaSectpr;}
+ bool GetParaSectpr() const { return m_StreamStateStack.top().bParaSectpr; }
void SetSymbolChar( sal_Int32 nSymbol) { m_aSymbolData.cSymbol = sal_Unicode(nSymbol); }
void SetSymbolFont( OUString const &rName ) { m_aSymbolData.sFont = rName; }
@@ -744,9 +777,9 @@ public:
/// Getter method for m_bSdt.
bool GetSdt() const { return m_bSdt;}
- bool GetParaChanged() const { return m_bParaChanged;}
- bool GetParaHadField() const { return m_bParaHadField; }
- bool GetRemoveThisPara() const { return m_bRemoveThisParagraph; }
+ bool GetParaChanged() const { return m_StreamStateStack.top().bParaChanged; }
+ bool GetParaHadField() const { return m_StreamStateStack.top().bParaHadField; }
+ bool GetRemoveThisPara() const { return m_StreamStateStack.top().bRemoveThisParagraph; }
void deferBreak( BreakType deferredBreakType );
bool isBreakDeferred( BreakType deferredBreakType );
@@ -865,7 +898,7 @@ public:
css::uno::Reference<css::drawing::XShape> PopPendingShape();
void PopPageHeaderFooter(PagePartType ePagePartType, PageType eType);
- bool IsInHeaderFooter() const { return m_eInHeaderFooterImport != HeaderFooterImportState::none; }
+ bool IsInHeaderFooter() const { auto const type(m_StreamStateStack.top().eSubstreamType); return type == SubstreamType::Header || type == SubstreamType::Footer; }
void ConvertHeaderFooterToTextFrame(bool, bool);
static void fillEmptyFrameProperties(std::vector<css::beans::PropertyValue>& rFrameProperties, bool bSetAnchorToChar);
@@ -873,8 +906,8 @@ public:
void PushFootOrEndnote( bool bIsFootnote );
void PopFootOrEndnote();
- bool IsInFootOrEndnote() const { return m_bInFootOrEndnote; }
- bool IsInFootnote() const { return IsInFootOrEndnote() && m_bInFootnote; }
+ bool IsInFootOrEndnote() const { auto const type(m_StreamStateStack.top().eSubstreamType); return type == SubstreamType::Footnote || type == SubstreamType::Endnote; }
+ bool IsInFootnote() const { return m_StreamStateStack.top().eSubstreamType == SubstreamType::Footnote; }
void StartCustomFootnote(const PropertyMapPtr pContext);
void EndCustomFootnote();
@@ -1014,13 +1047,17 @@ public:
void SetPageMarginTwip( PageMarElement eElement, sal_Int32 nValue );
const PageMar& GetPageMargins() const {return m_aPageMargins;}
+ void InitPaperSource() { m_aPaperSource = PaperSource(); }
+ void SetPaperSource( PaperSourceElement eElement, sal_Int32 nValue );
+ const PaperSource& GetPaperSource() {return m_aPaperSource;}
+
const LineNumberSettings& GetLineNumberSettings() const { return m_aLineNumberSettings;}
void SetLineNumberSettings(const LineNumberSettings& rSet) { m_aLineNumberSettings = rSet;}
void SetInFootnoteProperties(bool bSet) { m_bIsInFootnoteProperties = bSet;}
bool IsInFootnoteProperties() const { return m_bIsInFootnoteProperties;}
- bool IsInComments() const { return m_bIsInComments; };
+ bool IsInComments() const { return m_StreamStateStack.top().eSubstreamType == SubstreamType::Annotation; };
std::vector<css::beans::PropertyValue> MakeFrameProperties(const ParagraphProperties& rProps);
void CheckUnregisteredFrameConversion(bool bPreventOverlap = false);
@@ -1104,14 +1141,6 @@ public:
/// Document background color, applied to every page style.
std::optional<sal_Int32> m_oBackgroundColor;
- /**
- * This contains the raw table depth. m_nTableDepth > 0 is the same as
- * getTableManager().isInTable(), unless we're in the first paragraph of a
- * table, or first paragraph after a table, as the table manager is only
- * updated once we ended the paragraph (and know if the para has the
- * inTbl SPRM or not).
- */
- sal_Int32 m_nTableDepth;
/// Raw table cell depth.
sal_Int32 m_nTableCellDepth;
@@ -1182,7 +1211,7 @@ public:
bool m_bIsActualParagraphFramed;
std::deque<css::uno::Any> m_aStoredRedlines[StoredRedlines::NONE];
- bool IsParaWithInlineObject() const { return m_bParaWithInlineObject; }
+ bool IsParaWithInlineObject() const { return m_StreamStateStack.top().bParaWithInlineObject; }
css::uno::Reference< css::embed::XStorage > m_xDocumentStorage;
@@ -1209,17 +1238,9 @@ private:
// Start a new index section; if needed, finish current paragraph
css::uno::Reference<css::beans::XPropertySet> StartIndexSectionChecked(const OUString& sServiceName);
std::vector<css::uno::Reference< css::drawing::XShape > > m_vTextFramesForChaining ;
- /// Current paragraph had at least one field in it.
- bool m_bParaHadField;
- bool m_bSaveParaHadField;
css::uno::Reference<css::beans::XPropertySet> m_xPreviousParagraph;
/// Current paragraph has automatic before spacing.
bool m_bParaAutoBefore;
- /// Current paragraph in a table is first paragraph of a cell
- bool m_bFirstParagraphInCell;
- bool m_bSaveFirstParagraphInCell;
- /// Current paragraph had at least one inline object in it.
- bool m_bParaWithInlineObject;
/// SAXException was seen so document will be abandoned
bool m_bSaxError;
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index 63330c477c..eebd1b8228 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -1850,6 +1850,13 @@ uno::Reference<text::XTextContent> GraphicImport::createGraphicObject(uno::Refer
m_pImpl->m_nLeftPosition = 0;
}
+ if (m_pImpl->m_nVertRelation == text::RelOrientation::TEXT_LINE)
+ {
+ // Word's "line" is "below the bottom of the line", our TEXT_LINE is
+ // "towards top, from the bottom of the line", so invert the vertical position.
+ m_pImpl->m_nTopPosition *= -1;
+ }
+
m_pImpl->applyPosition(xGraphicObjectProperties);
m_pImpl->applyRelativePosition(xGraphicObjectProperties);
if( !m_pImpl->m_bOpaque )
diff --git a/writerfilter/source/dmapper/PropertyIds.cxx b/writerfilter/source/dmapper/PropertyIds.cxx
index 01cf1203d3..b8b4efc062 100644
--- a/writerfilter/source/dmapper/PropertyIds.cxx
+++ b/writerfilter/source/dmapper/PropertyIds.cxx
@@ -383,6 +383,7 @@ namespace
{ PROP_CURSOR_NOT_IGNORE_TABLES_IN_HF, u"CursorNotIgnoreTables"},
{ PROP_PARA_CONNECT_BORDERS, u"ParaIsConnectBorder"},
{ PROP_DECORATIVE, u"Decorative"},
+ { PROP_PAPER_TRAY, u"PrinterPaperTray"},
});
} // end anonymous ns
diff --git a/writerfilter/source/dmapper/PropertyIds.hxx b/writerfilter/source/dmapper/PropertyIds.hxx
index 83d05d81c8..b39fcd24fa 100644
--- a/writerfilter/source/dmapper/PropertyIds.hxx
+++ b/writerfilter/source/dmapper/PropertyIds.hxx
@@ -262,6 +262,7 @@ enum PropertyIds
,PROP_PARA_TOP_MARGIN
,PROP_PARA_VERT_ALIGNMENT
,PROP_PARA_WIDOWS
+ ,PROP_PAPER_TRAY
,PROP_PARENT_NUMBERING
,PROP_POSITION_AND_SPACE_MODE
,PROP_POSITION_PROTECTED
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index 9f9269b734..9c3e031e40 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -429,6 +429,8 @@ SectionPropertyMap::SectionPropertyMap( bool bIsFirstSection )
, m_nLnc(NS_ooxml::LN_Value_ST_LineNumberRestart_newPage)
, m_ndxaLnn( 0 )
, m_nLnnMin( 0 )
+ , m_nPaperSourceFirst( 0 )
+ , m_nPaperSourceOther( 0 )
, m_bDynamicHeightTop( true )
, m_bDynamicHeightBottom( true )
{
@@ -566,6 +568,12 @@ void SectionPropertyMap::setHeaderFooterProperties(DomainMapper_Impl& rDM_Impl)
m_aPageStyle->setPropertyValue(getPropertyName(PROP_HEADER_IS_SHARED), uno::Any(!bEvenAndOdd));
m_aPageStyle->setPropertyValue(getPropertyName(PROP_FOOTER_IS_SHARED), uno::Any(!bEvenAndOdd));
m_aPageStyle->setPropertyValue(getPropertyName(PROP_FIRST_IS_SHARED), uno::Any(!m_bTitlePage));
+
+ bool bHadFirstHeader = m_bHadFirstHeader && m_bTitlePage;
+ if (bHasHeader && !bHadFirstHeader && !m_bHadLeftHeader && !m_bHadRightHeader)
+ {
+ m_aPageStyle->setPropertyValue(sHeaderIsOn, uno::Any(false));
+ }
}
void SectionPropertyMap::SetBorder( BorderPosition ePos, sal_Int32 nLineDistance, const table::BorderLine2& rBorderLine, bool bShadow )
@@ -575,6 +583,27 @@ void SectionPropertyMap::SetBorder( BorderPosition ePos, sal_Int32 nLineDistance
m_bBorderShadows[ePos] = bShadow;
}
+void SectionPropertyMap::ApplyPaperSource(DomainMapper_Impl& rDM_Impl)
+{
+ uno::Reference<beans::XPropertySet> xFirst;
+ // todo: negative spacing (from ww8par6.cxx)
+ if (!m_sPageStyleName.isEmpty())
+ {
+ xFirst = GetPageStyle(rDM_Impl);
+ if ( xFirst.is() )
+ try
+ {
+ //TODO: which of the two tray values needs to be set? first/other - the interfaces requires the name of the tray!
+ xFirst->setPropertyValue(getPropertyName(PROP_PAPER_TRAY),
+ uno::Any(m_nPaperSourceFirst));
+ }
+ catch (const uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("writerfilter", "Paper source not found");
+ }
+ }
+}
+
void SectionPropertyMap::ApplyBorderToPageStyles( DomainMapper_Impl& rDM_Impl,
BorderApply /*eBorderApply*/, BorderOffsetFrom eOffsetFrom )
{
@@ -1751,6 +1780,7 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
ApplyProperties_(xPageStyle);
ApplyBorderToPageStyles( rDM_Impl, m_eBorderApply, m_eBorderOffsetFrom );
+ ApplyPaperSource(rDM_Impl);
try
{
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index d6ecfb2e71..711ef47195 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -295,6 +295,9 @@ private:
sal_Int32 m_ndxaLnn;
sal_Int32 m_nLnnMin;
+ sal_Int32 m_nPaperSourceFirst;
+ sal_Int32 m_nPaperSourceOther;
+
bool m_bDynamicHeightTop;
bool m_bDynamicHeightBottom;
@@ -409,12 +412,14 @@ public:
void SetdxaLnn( sal_Int32 nValue ) { m_ndxaLnn = nValue; }
void SetLnnMin( sal_Int32 nValue ) { m_nLnnMin = nValue; }
+ void SetPaperSource(sal_Int32 first, sal_Int32 other) { m_nPaperSourceFirst = first; m_nPaperSourceOther = other;}
+
void addRelativeWidthShape( css::uno::Reference<css::drawing::XShape> xShape ) { m_xRelativeWidthShapes.push_back( xShape ); }
// determine which style gets the borders
void ApplyBorderToPageStyles( DomainMapper_Impl &rDM_Impl,
BorderApply eBorderApply, BorderOffsetFrom eOffsetFrom );
-
+ void ApplyPaperSource(DomainMapper_Impl& rDM_Impl);
void CloseSectionGroup( DomainMapper_Impl& rDM_Impl );
// Handling of margins, header and footer for any kind of sections breaks.
void HandleMarginsHeaderFooter(DomainMapper_Impl& rDM_Impl);
@@ -428,6 +433,9 @@ public:
bool m_bLeftFooter = false;
bool m_bRightHeader = false;
bool m_bRightFooter = false;
+ bool m_bHadFirstHeader = false;
+ bool m_bHadLeftHeader = false;
+ bool m_bHadRightHeader = false;
static void removeXTextContent(css::uno::Reference<css::text::XText> const& rxText);
};
diff --git a/writerfilter/source/dmapper/SdtHelper.cxx b/writerfilter/source/dmapper/SdtHelper.cxx
index 922ac5bea1..09e7903b5f 100644
--- a/writerfilter/source/dmapper/SdtHelper.cxx
+++ b/writerfilter/source/dmapper/SdtHelper.cxx
@@ -355,7 +355,7 @@ void SdtHelper::createPlainTextControl()
try
{
bool bIsInTable = (m_rDM_Impl.hasTableManager() && m_rDM_Impl.getTableManager().isInTable())
- != (m_rDM_Impl.m_nTableDepth > 0)
+ != (0 < m_rDM_Impl.m_StreamStateStack.top().nTableDepth)
&& m_rDM_Impl.GetIsDummyParaAddedForTableInSection();
if (bIsInTable)
xCrsr->goRight(1, false);
@@ -459,7 +459,7 @@ void SdtHelper::createDateContentControl()
// tdf#138093: Date selector reset, if placed inside table
// Modified to XOR relationship and adding dummy paragraph conditions
bool bIsInTable = (m_rDM_Impl.hasTableManager() && m_rDM_Impl.getTableManager().isInTable())
- != (m_rDM_Impl.m_nTableDepth > 0)
+ != (0 < m_rDM_Impl.m_StreamStateStack.top().nTableDepth)
&& m_rDM_Impl.GetIsDummyParaAddedForTableInSection();
if (bIsInTable)
xCrsr->goRight(1, false);
diff --git a/writerfilter/source/dmapper/SdtHelper.hxx b/writerfilter/source/dmapper/SdtHelper.hxx
index 5db799bd1f..85b95a4881 100644
--- a/writerfilter/source/dmapper/SdtHelper.hxx
+++ b/writerfilter/source/dmapper/SdtHelper.hxx
@@ -171,6 +171,7 @@ public:
void setDataBindingStoreItemID(const OUString& sValue) { m_sDataBindingStoreItemID = sValue; }
const OUString& GetDataBindingStoreItemID() const { return m_sDataBindingStoreItemID; }
+ bool isFieldStartRangeSet() const { return m_xFieldStartRange.is(); }
void setFieldStartRange(const css::uno::Reference<css::text::XTextRange>& xStartRange)
{
m_xFieldStartRange = xStartRange;
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index 43ef02f681..b168464206 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -778,6 +778,8 @@ bool SettingsTable::GetNoLeading() const
bool SettingsTable::GetGutterAtTop() const { return m_pImpl->m_bGutterAtTop; }
+bool SettingsTable::GetRecordChanges() const { return m_pImpl->m_bRecordChanges; }
+
}//namespace dmapper
} //namespace writerfilter
diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx
index a0af31bed6..471d15b7a9 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -97,6 +97,8 @@ public:
const OUString& GetCurrentDatabaseDataSource() const;
bool GetGutterAtTop() const;
+ bool GetRecordChanges() const;
+
private:
// Properties
virtual void lcl_attribute(Id Name, Value& val) override;
diff --git a/writerfilter/source/filter/WriterFilter.cxx b/writerfilter/source/filter/WriterFilter.cxx
index 1f97e8e70a..e7d32c4843 100644
--- a/writerfilter/source/filter/WriterFilter.cxx
+++ b/writerfilter/source/filter/WriterFilter.cxx
@@ -304,6 +304,7 @@ void WriterFilter::setTargetDocument(const uno::Reference<lang::XComponent>& xDo
xSettings->setPropertyValue("UseOldNumbering", uno::Any(false));
xSettings->setPropertyValue("IgnoreFirstLineIndentInNumbering", uno::Any(false));
+ xSettings->setPropertyValue(u"NoGapAfterNoteNumber"_ustr, uno::Any(true));
xSettings->setPropertyValue("DoNotResetParaAttrsForNumFont", uno::Any(false));
xSettings->setPropertyValue("UseFormerLineSpacing", uno::Any(false));
xSettings->setPropertyValue("AddParaSpacingToTableCells", uno::Any(true));
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index cbc75c1407..ae69281a0c 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -1827,8 +1827,20 @@ void OOXMLFastContextHandlerShape::sendShape( Token_t Element )
uno::Reference<beans::XPropertySet> xShapePropSet(xShape, uno::UNO_QUERY);
if (mnTableDepth > 0 && xShapePropSet.is() && mbIsVMLfound) //if we had a table
{
+ bool bForceShapeIntoCell = mbAllowInCell;
+ // According to tdf#153909 and GraphicImport's LN_shape handling,
+ // through-anchored shapes should not force the shape into the cell
+ if (bForceShapeIntoCell)
+ {
+ text::WrapTextMode nSurround = text::WrapTextMode_NONE;
+ xShapePropSet->getPropertyValue("Surround") >>= nSurround;
+ sal_Int32 nHoriRelation = -1;
+ xShapePropSet->getPropertyValue("HoriOrientRelation") >>= nHoriRelation;
+ bForceShapeIntoCell = (nSurround != text::WrapTextMode_THROUGH)
+ || (nHoriRelation != text::RelOrientation::FRAME);
+ }
xShapePropSet->setPropertyValue(dmapper::getPropertyName(dmapper::PROP_FOLLOW_TEXT_FLOW),
- uno::Any(mbAllowInCell));
+ uno::Any(bForceShapeIntoCell));
}
// Notify the dmapper that the shape is ready to use
if ( !bIsPicture )
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index fd99a745e6..2c174743f9 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -17964,6 +17964,10 @@
<attribute name="footer" tokenid="ooxml:CT_PageMar_footer"/>
<attribute name="gutter" tokenid="ooxml:CT_PageMar_gutter"/>
</resource>
+ <resource name="CT_PaperSource" resource="Properties">
+ <attribute name="first" tokenid="ooxml:CT_PaperSource_first"/>
+ <attribute name="other" tokenid="ooxml:CT_PaperSource_other"/>
+ </resource>
<resource name="ST_PageBorderZOrder" resource="List">
<value tokenid="ooxml:Value_doc_ST_PageBorderZOrder_front">front</value>
<value tokenid="ooxml:Value_doc_ST_PageBorderZOrder_back">back</value>
diff --git a/writerfilter/source/rtftok/rtfdispatchsymbol.cxx b/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
index aa1360f6dc..0f01d79f5c 100644
--- a/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
@@ -131,11 +131,8 @@ RTFError RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
break;
case RTFKeyword::SECT:
{
- if (m_bNeedCr)
- dispatchSymbol(RTFKeyword::PAR);
-
m_bHadSect = true;
- if (m_bIgnoreNextContSectBreak)
+ if (m_bIgnoreNextContSectBreak || m_aStates.top().getFrame().hasProperties())
{
// testContSectionPageBreak: need \par now
dispatchSymbol(RTFKeyword::PAR);
@@ -143,6 +140,10 @@ RTFError RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
}
else
{
+ if (m_bNeedCr)
+ { // tdf#158586 don't dispatch \par here, it eats deferred page breaks
+ setNeedPar(true);
+ }
sectBreak();
if (m_nResetBreakOnSectBreak != RTFKeyword::invalid)
{
diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
index 69157a9782..f699b0ed39 100644
--- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -1342,6 +1342,18 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
NS_ooxml::LN_EG_SectPrContents_pgSz, NS_ooxml::LN_CT_PageSz_w,
pIntValue);
break;
+ case RTFKeyword::BINFSXN:
+ putNestedAttribute(m_aStates.top().getSectionSprms(),
+ NS_ooxml::LN_EG_SectPrContents_paperSrc,
+ NS_ooxml::LN_CT_PaperSource_first, pIntValue);
+ break;
+ case RTFKeyword::BINSXN:
+ {
+ putNestedAttribute(m_aStates.top().getSectionSprms(),
+ NS_ooxml::LN_EG_SectPrContents_paperSrc,
+ NS_ooxml::LN_CT_PaperSource_other, pIntValue);
+ }
+ break;
case RTFKeyword::MARGL:
putNestedAttribute(m_aDefaultState.getSectionSprms(),
NS_ooxml::LN_EG_SectPrContents_pgMar, NS_ooxml::LN_CT_PageMar_left,
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 1d0c2d7dde..e82674930b 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -653,6 +653,7 @@ void RTFDocumentImpl::runBreak()
void RTFDocumentImpl::tableBreak()
{
+ checkFirstRun(); // ooo113308-1.rtf has a header at offset 151084 that doesn't startParagraphGroup() without this
runBreak();
Mapper().endParagraphGroup();
Mapper().startParagraphGroup();
@@ -671,7 +672,10 @@ void RTFDocumentImpl::parBreak()
m_bHadPicture = false;
// start new one
- Mapper().startParagraphGroup();
+ if (!m_bParAtEndOfSection)
+ {
+ Mapper().startParagraphGroup();
+ }
}
void RTFDocumentImpl::sectBreak(bool bFinal)
@@ -685,14 +689,26 @@ void RTFDocumentImpl::sectBreak(bool bFinal)
// unless this is the end of the doc, we had nothing since the last section break and this is not a continuous one.
// Also, when pasting, it's fine to not have any paragraph inside the document at all.
if (m_bNeedPar && (!bFinal || m_bNeedSect || bContinuous) && !isSubstream() && m_bIsNewDoc)
+ {
+ m_bParAtEndOfSection = true;
dispatchSymbol(RTFKeyword::PAR);
+ }
// It's allowed to not have a non-table paragraph at the end of an RTF doc, add it now if required.
if (m_bNeedFinalPar && bFinal)
{
dispatchFlag(RTFKeyword::PARD);
+ m_bParAtEndOfSection = true;
dispatchSymbol(RTFKeyword::PAR);
m_bNeedSect = bNeedSect;
}
+ // testTdf148515, if RTF ends with \row, endParagraphGroup() must be called!
+ if (!m_bParAtEndOfSection || m_aStates.top().getCurrentBuffer())
+ {
+ Mapper().endParagraphGroup(); // < top para context dies with page break
+ }
+ m_bParAtEndOfSection = false;
+ // paragraph properties are *done* now - only section properties following
+
while (!m_nHeaderFooterPositions.empty())
{
std::pair<Id, std::size_t> aPair = m_nHeaderFooterPositions.front();
@@ -725,7 +741,6 @@ void RTFDocumentImpl::sectBreak(bool bFinal)
// The trick is that we send properties of the previous section right now, which will be exactly what dmapper expects.
Mapper().props(pProperties);
- Mapper().endParagraphGroup();
// End Section
if (!m_pSuperstream)
@@ -2119,6 +2134,8 @@ RTFError RTFDocumentImpl::pushState()
case Destination::FIELDRESULT:
case Destination::SHAPETEXT:
case Destination::FORMFIELD:
+ //TODO: if this is pushed then the font encoding is used which results in a broken command string
+ // if it is not pushed to NORMAL then it is not restored in time.
case Destination::FIELDINSTRUCTION:
case Destination::PICT:
m_aStates.top().setDestination(Destination::NORMAL);
@@ -2342,7 +2359,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
if (m_aStates.top().isFieldLocked())
singleChar(cFieldLock);
- singleChar(cFieldSep);
+ singleChar(cFieldSep, true);
}
break;
case Destination::FIELDRESULT:
@@ -2569,7 +2586,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
str = OUString::Concat(field) + " \"" + str.replaceAll("\"", "\\\"") + "\"";
singleChar(cFieldStart);
Mapper().utext(str.getStr(), str.getLength());
- singleChar(cFieldSep);
+ singleChar(cFieldSep, true);
// no result
singleChar(cFieldEnd);
}
@@ -3654,8 +3671,15 @@ RTFError RTFDocumentImpl::popState()
// \par means an empty paragraph at the end of footnotes/endnotes, but
// not in case of other substreams, like headers.
if (m_bNeedCr && m_nStreamType != NS_ooxml::LN_footnote
- && m_nStreamType != NS_ooxml::LN_endnote && m_bIsNewDoc)
+ && m_nStreamType != NS_ooxml::LN_endnote)
+ {
+ if (!m_bIsNewDoc)
+ {
+ // Make sure all the paragraph settings are set, but do not add next paragraph
+ Mapper().markLastParagraph();
+ }
dispatchSymbol(RTFKeyword::PAR);
+ }
if (m_bNeedSect) // may be set by dispatchSymbol above!
sectBreak(true);
else if (!m_pSuperstream)
@@ -3782,8 +3806,11 @@ void RTFDocumentImpl::checkUnicode(bool bUnicode, bool bHex)
if (bHex && !m_aHexBuffer.isEmpty())
{
rtl_TextEncoding nEncoding = m_aStates.top().getCurrentEncoding();
- if (m_aStates.top().getDestination() == Destination::FONTENTRY
- && m_aStates.top().getCurrentEncoding() == RTL_TEXTENCODING_SYMBOL)
+ if (nEncoding == RTL_TEXTENCODING_SYMBOL
+ && (m_aStates.top().getDestination() == Destination::FONTENTRY
+ || (m_aStates.size() > 1
+ && m_aStates[m_aStates.size() - 2].getDestination()
+ == Destination::FIELDINSTRUCTION)))
nEncoding = RTL_TEXTENCODING_MS_1252;
OUString aString = OStringToOUString(m_aHexBuffer, nEncoding);
m_aHexBuffer.setLength(0);
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index eb50e3c7e0..f05f7d321c 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -852,6 +852,8 @@ private:
bool m_bNeedPar;
/// If set, an empty paragraph will be added at the end of the document.
bool m_bNeedFinalPar;
+ /// a synthetic \par was dispatched at the end of the current section
+ bool m_bParAtEndOfSection = false;
/// The list table and list override table combined.
RTFSprms m_aListTableSprms;
/// Maps between listoverridetable and listtable indexes.
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx
index 5d57348f20..148d39c2e4 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -437,12 +437,22 @@ RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference, Id const nStyleType
return ret;
}
-bool RTFSprms::equals(const RTFValue& rOther) const
+bool RTFSprms::equals(const RTFSprms& rOther) const
{
- return std::all_of(m_pSprms->cbegin(), m_pSprms->cend(),
- [&](const std::pair<Id, RTFValue::Pointer_t>& raPair) -> bool {
- return raPair.second->equals(rOther);
- });
+ auto it1 = m_pSprms->cbegin();
+ auto it1End = m_pSprms->cend();
+ auto it2 = rOther.m_pSprms->cbegin();
+ auto it2End = rOther.m_pSprms->cend();
+ while (it1 != it1End && it2 != it2End)
+ {
+ if (it1->first != it2->first)
+ return false;
+ if (!it1->second->equals(*it2->second))
+ return false;
+ ++it1;
+ ++it2;
+ }
+ return it1 == it1End && it2 == it2End;
}
void RTFSprms::ensureCopyBeforeWrite()
diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx
index 9f3bbd78b3..132a2bbcbe 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -73,7 +73,7 @@ public:
Iterator_t begin() { return m_pSprms->begin(); }
Iterator_t end() { return m_pSprms->end(); }
void clear();
- bool equals(const RTFValue& rOther) const;
+ bool equals(const RTFSprms& rOther) const;
private:
void ensureCopyBeforeWrite();
diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx
index 373fb7521b..7a9137f5db 100644
--- a/writerfilter/source/rtftok/rtfvalue.cxx
+++ b/writerfilter/source/rtftok/rtfvalue.cxx
@@ -172,7 +172,7 @@ bool RTFValue::equals(const RTFValue& rOther) const
{
if (m_pAttributes->size() != rOther.m_pAttributes->size())
return false;
- if (!m_pAttributes->equals(rOther))
+ if (!m_pAttributes->equals(*rOther.m_pAttributes))
return false;
}
else if (m_pAttributes && m_pAttributes->size())
@@ -188,7 +188,7 @@ bool RTFValue::equals(const RTFValue& rOther) const
{
if (m_pSprms->size() != rOther.m_pSprms->size())
return false;
- if (!m_pSprms->equals(rOther))
+ if (!m_pSprms->equals(*rOther.m_pSprms))
return false;
}
else if (m_pSprms && m_pSprms->size())