summaryrefslogtreecommitdiff
path: root/writerfilter/source/rtftok/rtfdocumentimpl.cxx
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2014-02-27 23:48:59 +0100
committerLuboš Luňák <l.lunak@centrum.cz>2014-05-28 11:56:34 +0200
commit4c8858b4a63906a5f5af009be139a8c5247c54b0 (patch)
tree96ac2f681edc59d9ca633e824d9b96451bb6989c /writerfilter/source/rtftok/rtfdocumentimpl.cxx
parentf58522d989b17552f739c1fe63fe5ba483c662e3 (diff)
RTF import: fix spurious page breaks at doc end (related: rhbz#1065629)
When a document ends with \sect it's possible that a spurious page break is created. In fact the spurious page break is always created by the RTF importer, sometimes it is deleted again by DomainMapper_Impl::RemoveLastParagraph() and sometimes not. It is created because on the final \sect RTFDocumentImpl::sectBreak() still calls startSectionGroup(), and the popState() for the \rtf1 group then calls sectBreak() another time. To prevent this, do not call startSectionGroup() from sectBreak() but instead from setNeedSect(), and ensure that it is called as soon as anything after \sect is read. One unit test fails because the \page is not handled properly: the conversion to \skbpage \sect \skbnone is not correct, because the \skb* keywords are an exception and affect the \sect that precedes them, not the following one; sending the \skbpage later unfortunately requires additional cleanup later. (cherry picked from commit e3f254ab8211fbab7541cde2100a35c875b0c240) Signed-off-by: Luboš Luňák <l.lunak@centrum.cz> Conflicts: sw/qa/extras/rtfimport/rtfimport.cxx writerfilter/source/rtftok/rtfdocumentimpl.cxx Change-Id: I3c1a3bceb2c8b75bbecdc748170562451ce5f5c3
Diffstat (limited to 'writerfilter/source/rtftok/rtfdocumentimpl.cxx')
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx70
1 files changed, 49 insertions, 21 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index f7a6aae1adaf..c672aa65b1e2 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -263,7 +263,8 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
m_aHexBuffer(),
m_bMathNor(false),
m_bIgnoreNextContSectBreak(false),
- m_bNeedSect(true),
+ m_nResetBreakOnSectBreak(static_cast<RTFKeyword>(-1)),
+ m_bNeedSect(false), // done by checkFirstRun
m_bWasInFrame(false),
m_bHadPicture(false),
m_bHadSect(false),
@@ -370,16 +371,15 @@ void RTFDocumentImpl::checkFirstRun()
writerfilter::Reference<Table>::Pointer_t const pTable(new RTFReferenceTable(aSettingsTableEntries));
Mapper().table(NS_ooxml::LN_settings_settings, pTable);
// start initial paragraph
- if (!m_pSuperstream)
- Mapper().startSectionGroup();
- Mapper().startParagraphGroup();
+ m_bFirstRun = false;
+ assert(!m_bNeedSect);
+ setNeedSect(); // first call that succeeds
// set the requested default font, if there are none
RTFValue::Pointer_t pFont = m_aDefaultState.aCharacterSprms.find(NS_sprm::LN_CRgFtc0);
RTFValue::Pointer_t pCurrentFont = m_aStates.top().aCharacterSprms.find(NS_sprm::LN_CRgFtc0);
if (pFont && !pCurrentFont)
dispatchValue(RTF_F, pFont->getInt());
- m_bFirstRun = false;
}
}
@@ -395,7 +395,21 @@ void RTFDocumentImpl::setNeedPar(bool bNeedPar)
void RTFDocumentImpl::setNeedSect(bool bNeedSect)
{
- m_bNeedSect = bNeedSect;
+ // ignore setting before checkFirstRun - every keyword calls setNeedSect!
+ if (!m_bNeedSect && bNeedSect && !m_bFirstRun)
+ {
+ if (!m_pSuperstream) // no sections in header/footer!
+ {
+ Mapper().startSectionGroup();
+ m_bNeedSect = bNeedSect;
+ }
+ Mapper().startParagraphGroup();
+ setNeedPar(true);
+ }
+ else if (m_bNeedSect && !bNeedSect)
+ {
+ m_bNeedSect = bNeedSect;
+ }
}
writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms)
@@ -519,6 +533,7 @@ void RTFDocumentImpl::sectBreak(bool bFinal = false)
{
dispatchFlag(RTF_PARD);
dispatchSymbol(RTF_PAR);
+ m_bNeedSect = bNeedSect;
}
while (m_nHeaderFooterPositions.size())
{
@@ -549,12 +564,7 @@ void RTFDocumentImpl::sectBreak(bool bFinal = false)
Mapper().endParagraphGroup();
if (!m_pSuperstream)
Mapper().endSectionGroup();
- if (!bFinal)
- {
- Mapper().startSectionGroup();
- Mapper().startParagraphGroup();
- }
- m_bNeedPar = true;
+ m_bNeedPar = false;
m_bNeedSect = false;
}
@@ -1225,8 +1235,8 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer)
int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
{
- checkUnicode();
setNeedSect();
+ checkUnicode();
RTFSkipDestination aSkip(*this);
switch (nKeyword)
{
@@ -1697,11 +1707,11 @@ int RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword)
int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
{
+ setNeedSect();
if (nKeyword != RTF_HEXCHAR)
checkUnicode(/*bUnicode =*/ true, /*bHex =*/ true);
else
checkUnicode(/*bUnicode =*/ true, /*bHex =*/ false);
- setNeedSect();
RTFSkipDestination aSkip(*this);
if (RTF_LINE == nKeyword)
@@ -1773,7 +1783,15 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
if (m_bIgnoreNextContSectBreak)
m_bIgnoreNextContSectBreak = false;
else
+ {
sectBreak();
+ if (m_nResetBreakOnSectBreak != -1)
+ { // this should run on _second_ \sect after \page
+ dispatchSymbol(m_nResetBreakOnSectBreak); // lazy reset
+ m_nResetBreakOnSectBreak = static_cast<RTFKeyword>(-1);
+ m_bNeedSect = false; // dispatchSymbol set it
+ }
+ }
}
break;
case RTF_NOBREAK:
@@ -1944,19 +1962,24 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
RTFValue::Pointer_t pBreak = m_aStates.top().aSectionSprms.find(NS_sprm::LN_SBkc);
// Unless we're on a title page.
RTFValue::Pointer_t pTitlePg = m_aStates.top().aSectionSprms.find(NS_ooxml::LN_EG_SectPrContents_titlePg);
- if ((pBreak.get() && !pBreak->getInt()) && !(pTitlePg.get() && pTitlePg->getInt()))
+ if (((pBreak.get() && !pBreak->getInt())
+ || m_nResetBreakOnSectBreak == RTF_SBKNONE)
+ && !(pTitlePg.get() && pTitlePg->getInt()))
{
if (m_bWasInFrame)
{
dispatchSymbol(RTF_PAR);
m_bWasInFrame = false;
}
- dispatchFlag(RTF_SBKPAGE);
sectBreak();
- dispatchFlag(RTF_SBKNONE);
+ // note: this will not affect the following section break
+ // but the one just pushed
+ dispatchFlag(RTF_SBKPAGE);
if (m_bNeedPar)
dispatchSymbol(RTF_PAR);
m_bIgnoreNextContSectBreak = true;
+ // arrange to clean up the syntetic RTF_SBKPAGE
+ m_nResetBreakOnSectBreak = RTF_SBKNONE;
}
else
{
@@ -2001,8 +2024,8 @@ bool lcl_findPropertyName(const std::vector<beans::PropertyValue>& rProperties,
int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
{
- checkUnicode();
setNeedSect();
+ checkUnicode();
RTFSkipDestination aSkip(*this);
int nParam = -1;
int nSprm = -1;
@@ -2134,6 +2157,10 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
}
if (nParam >= 0)
{
+ if (m_nResetBreakOnSectBreak != -1)
+ {
+ m_nResetBreakOnSectBreak = nKeyword;
+ }
RTFValue::Pointer_t pValue(new RTFValue(nParam));
m_aStates.top().aSectionSprms.set(NS_sprm::LN_SBkc, pValue);
return 0;
@@ -2730,8 +2757,8 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
{
- checkUnicode(nKeyword != RTF_U, true);
setNeedSect();
+ checkUnicode(nKeyword != RTF_U, true);
RTFSkipDestination aSkip(*this);
int nSprm = 0;
RTFValue::Pointer_t pIntValue(new RTFValue(nParam));
@@ -3644,8 +3671,8 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
int RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int nParam)
{
- checkUnicode();
setNeedSect();
+ checkUnicode();
RTFSkipDestination aSkip(*this);
int nSprm = -1;
RTFValue::Pointer_t pBoolValue(new RTFValue(!bParam || nParam != 0));
@@ -4473,7 +4500,8 @@ int RTFDocumentImpl::popState()
{
if (m_bNeedCr && !isSubstream())
dispatchSymbol(RTF_PAR);
- sectBreak(true);
+ if (m_bNeedSect) // may be set by dispatchSymbol above!
+ sectBreak(true);
}
m_aStates.pop();