writerfilter/source/rtftok/rtfdocumentimpl.cxx | 304 +++++++++++++------------ writerfilter/source/rtftok/rtfdocumentimpl.hxx | 2 2 files changed, 161 insertions(+), 145 deletions(-)
New commits: commit 845c7a3bd93f25e6138cff61fa91e346746174d2 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Mar 11 21:43:14 2020 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu Mar 12 09:07:36 2020 +0100 writerfilter: extract before/afterPopState() from popState() This function was a 1365 lines monster. Ideally it would be a one-liner, just popping the parser stack. In reality the RTF format has lots of exceptions where the state leaks outside the current push/pop boundaries. Move this large list of special cases to separate functions. Change-Id: Ib6c729c5eccbcd361852f5bbc0539fd51315f86d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/90349 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 7981ee6126ba..3de574e75c12 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -2160,32 +2160,9 @@ static bool lcl_containsProperty(const uno::Sequence<beans::Property>& rProperti [&](const beans::Property& rProperty) { return rProperty.Name == rName; }); } -RTFError RTFDocumentImpl::popState() +RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState) { - //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() << - // ", dest state: " << m_aStates.top().eDestination); - - checkUnicode(/*bUnicode =*/true, /*bHex =*/true); - RTFParserState aState(m_aStates.top()); - m_bWasInFrame = aState.getFrame().inFrame(); - - // dmapper expects some content in header/footer, so if there would be nothing, add an empty paragraph. - if (m_pTokenizer->getGroup() == 1 && m_bFirstRun) - { - switch (m_nStreamType) - { - case NS_ooxml::LN_headerl: - case NS_ooxml::LN_headerr: - case NS_ooxml::LN_headerf: - case NS_ooxml::LN_footerl: - case NS_ooxml::LN_footerr: - case NS_ooxml::LN_footerf: - dispatchSymbol(RTF_PAR); - break; - } - } - - switch (aState.getDestination()) + switch (rState.getDestination()) { case Destination::FONTTABLE: { @@ -2222,8 +2199,8 @@ RTFError RTFDocumentImpl::popState() } break; case Destination::LISTENTRY: - for (const auto& rListLevelEntry : aState.getListLevelEntries()) - aState.getTableSprms().set(rListLevelEntry.first, rListLevelEntry.second, + for (const auto& rListLevelEntry : rState.getListLevelEntries()) + rState.getTableSprms().set(rListLevelEntry.first, rListLevelEntry.second, RTFOverwrite::NO_APPEND); break; case Destination::FIELDINSTRUCTION: @@ -2308,7 +2285,7 @@ RTFError RTFDocumentImpl::popState() else aValue = aStr; auto pValue = new RTFValue(aValue, true); - aState.getTableAttributes().set(NS_ooxml::LN_CT_LevelText_val, pValue); + rState.getTableAttributes().set(NS_ooxml::LN_CT_LevelText_val, pValue); } break; case Destination::LEVELNUMBERS: @@ -2318,12 +2295,12 @@ RTFError RTFDocumentImpl::popState() // Current destination is levelnumbers and parent destination is levelnumbers as well. bNestedLevelNumbers = m_aStates[m_aStates.size() - 2].getDestination() == Destination::LEVELNUMBERS; - if (!bNestedLevelNumbers && aState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)) + if (!bNestedLevelNumbers && rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)) { RTFSprms& rAttributes - = aState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes(); + = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_lvlText)->getAttributes(); RTFValue::Pointer_t pValue = rAttributes.find(NS_ooxml::LN_CT_LevelText_val); - if (pValue && aState.getLevelNumbersValid()) + if (pValue && rState.getLevelNumbersValid()) { OUString aOrig = pValue->getString(); @@ -2331,14 +2308,14 @@ RTFError RTFDocumentImpl::popState() sal_Int32 nReplaces = 1; for (int i = 0; i < aOrig.getLength(); i++) { - if (std::find(aState.getLevelNumbers().begin(), - aState.getLevelNumbers().end(), i + 1) - != aState.getLevelNumbers().end()) + if (std::find(rState.getLevelNumbers().begin(), + rState.getLevelNumbers().end(), i + 1) + != rState.getLevelNumbers().end()) { aBuf.append('%'); // '1.1.1' -> '%1.%2.%3', but '1.' (with '2.' prefix omitted) is %2. - aBuf.append(sal_Int32(nReplaces++ + aState.getListLevelNum() + 1 - - aState.getLevelNumbers().size())); + aBuf.append(sal_Int32(nReplaces++ + rState.getListLevelNum() + 1 + - rState.getLevelNumbers().size())); } else aBuf.append(aOrig[i]); @@ -2356,24 +2333,24 @@ RTFError RTFDocumentImpl::popState() if (&m_aStates.top().getDestinationText() != m_aStates.top().getCurrentDestinationText()) break; // not for nested group - aState.getShape().getProperties().emplace_back( + rState.getShape().getProperties().emplace_back( m_aStates.top().getCurrentDestinationText()->makeStringAndClear(), OUString()); break; case Destination::SHAPEPROPERTYVALUE: - if (!aState.getShape().getProperties().empty()) + if (!rState.getShape().getProperties().empty()) { - aState.getShape().getProperties().back().second + rState.getShape().getProperties().back().second = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); if (m_aStates.top().getHadShapeText()) - m_pSdrImport->append(aState.getShape().getProperties().back().first, - aState.getShape().getProperties().back().second); - else if (aState.getInShapeGroup() && !aState.getInShape() - && aState.getShape().getProperties().back().first == "rotation") + m_pSdrImport->append(rState.getShape().getProperties().back().first, + rState.getShape().getProperties().back().second); + else if (rState.getInShapeGroup() && !rState.getInShape() + && rState.getShape().getProperties().back().first == "rotation") { // Rotation should be applied on the groupshape itself, not on each shape. - aState.getShape().getGroupProperties().push_back( - aState.getShape().getProperties().back()); - aState.getShape().getProperties().pop_back(); + rState.getShape().getGroupProperties().push_back( + rState.getShape().getProperties().back()); + rState.getShape().getProperties().pop_back(); } } break; @@ -2385,12 +2362,12 @@ RTFError RTFDocumentImpl::popState() { // Do not resolve shape if shape instruction destination is inside other shape instruction } - else if (!m_bObject && !aState.getInListpicture() && !aState.getHadShapeText() - && !(aState.getInShapeGroup() && !aState.getInShape())) + else if (!m_bObject && !rState.getInListpicture() && !rState.getHadShapeText() + && !(rState.getInShapeGroup() && !rState.getInShape())) { // Don't trigger a shape import in case we're only leaving the \shpinst of the groupshape itself. RTFSdrImport::ShapeOrPict eType - = (aState.getDestination() == Destination::SHAPEINSTRUCTION) + = (rState.getDestination() == Destination::SHAPEINSTRUCTION) ? RTFSdrImport::SHAPE : RTFSdrImport::PICT; if (!m_aStates.top().getCurrentBuffer() || eType != RTFSdrImport::SHAPE) @@ -2420,12 +2397,12 @@ RTFError RTFDocumentImpl::popState() Buf_t(BUFFER_RESOLVESHAPE, pValue, nullptr)); } } - else if (aState.getInShapeGroup() && !aState.getInShape()) + else if (rState.getInShapeGroup() && !rState.getInShape()) { // End of a groupshape, as we're in shapegroup, but not in a real shape. - for (const auto& rGroupProperty : aState.getShape().getGroupProperties()) + for (const auto& rGroupProperty : rState.getShape().getGroupProperties()) m_pSdrImport->appendGroupProperty(rGroupProperty.first, rGroupProperty.second); - aState.getShape().getGroupProperties().clear(); + rState.getShape().getGroupProperties().clear(); } break; case Destination::BOOKMARKSTART: @@ -2466,7 +2443,7 @@ RTFError RTFDocumentImpl::popState() break; // not for nested group OUString str(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); // dmapper expects this as a field, so let's fake something... - OUString const field((Destination::INDEXENTRY == aState.getDestination()) + OUString const field((Destination::INDEXENTRY == rState.getDestination()) ? OUStringLiteral("XE") : OUStringLiteral("TC")); str = field + " \"" + str.replaceAll("\"", "\\\"") + "\""; @@ -2506,7 +2483,7 @@ RTFError RTFDocumentImpl::popState() break; // not for nested group OString aStr = OUStringToOString( m_aStates.top().getCurrentDestinationText()->makeStringAndClear(), - aState.getCurrentEncoding()); + rState.getCurrentEncoding()); // decode hex dump OStringBuffer aBuf; int b = 0; @@ -2549,13 +2526,13 @@ RTFError RTFDocumentImpl::popState() nLength = aStr.toChar(); if (!aStr.isEmpty()) aStr = aStr.copy(1); - auto pNValue = new RTFValue(OStringToOUString(aName, aState.getCurrentEncoding())); + auto pNValue = new RTFValue(OStringToOUString(aName, rState.getCurrentEncoding())); m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFData_name, pNValue); if (nLength > 0) { OString aDefaultText = aStr.copy(0, std::min(nLength, aStr.getLength())); auto pDValue = new RTFValue( - OStringToOUString(aDefaultText, aState.getCurrentEncoding())); + OStringToOUString(aDefaultText, rState.getCurrentEncoding())); m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFTextInput_default, pDValue); } @@ -2565,15 +2542,15 @@ RTFError RTFDocumentImpl::popState() break; case Destination::CREATIONTIME: if (m_xDocumentProperties.is()) - m_xDocumentProperties->setCreationDate(lcl_getDateTime(aState)); + m_xDocumentProperties->setCreationDate(lcl_getDateTime(rState)); break; case Destination::REVISIONTIME: if (m_xDocumentProperties.is()) - m_xDocumentProperties->setModificationDate(lcl_getDateTime(aState)); + m_xDocumentProperties->setModificationDate(lcl_getDateTime(rState)); break; case Destination::PRINTTIME: if (m_xDocumentProperties.is()) - m_xDocumentProperties->setPrintDate(lcl_getDateTime(aState)); + m_xDocumentProperties->setPrintDate(lcl_getDateTime(rState)); break; case Destination::AUTHOR: if (&m_aStates.top().getDestinationText() @@ -2614,7 +2591,7 @@ RTFError RTFDocumentImpl::popState() break; // not for nested group if (m_xDocumentProperties.is()) m_xDocumentProperties->setTitle( - aState.getCurrentDestinationText()->makeStringAndClear()); + rState.getCurrentDestinationText()->makeStringAndClear()); } break; @@ -2632,7 +2609,7 @@ RTFError RTFDocumentImpl::popState() if (&m_aStates.top().getDestinationText() != m_aStates.top().getCurrentDestinationText()) break; // not for nested group - OUString aName = aState.getDestination() == Destination::OPERATOR ? OUString("Operator") + OUString aName = rState.getDestination() == Destination::OPERATOR ? OUString("Operator") : OUString("Company"); uno::Any aValue = uno::makeAny(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); @@ -2714,7 +2691,7 @@ RTFError RTFDocumentImpl::popState() OUString aStr(OStringToOUString( DTTM22OString( m_aStates.top().getCurrentDestinationText()->makeStringAndClear().toInt32()), - aState.getCurrentEncoding())); + rState.getCurrentEncoding())); auto pValue = new RTFValue(aStr); RTFSprms aAnnAttributes; aAnnAttributes.set(NS_ooxml::LN_CT_TrackChange_date, pValue); @@ -2744,7 +2721,7 @@ RTFError RTFDocumentImpl::popState() OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); auto pValue = new RTFValue(aStr.toInt32()); RTFSprms aAttributes; - if (aState.getDestination() == Destination::ANNOTATIONREFERENCESTART) + if (rState.getDestination() == Destination::ANNOTATIONREFERENCESTART) aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart, pValue); else aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd, pValue); @@ -2771,7 +2748,7 @@ RTFError RTFDocumentImpl::popState() break; // not for nested group OUString aStr(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); auto pValue = new RTFValue(aStr); - aState.getTableSprms().set(NS_ooxml::LN_CT_Font_altName, pValue); + rState.getTableSprms().set(NS_ooxml::LN_CT_Font_altName, pValue); } break; case Destination::DRAWINGOBJECT: @@ -2840,13 +2817,13 @@ RTFError RTFDocumentImpl::popState() case Destination::SHAPE: m_bNeedFinalPar = true; m_bNeedCr = m_bNeedCrOrig; - if (aState.getFrame().inFrame()) + if (rState.getFrame().inFrame()) { // parBreak() modifies m_aStates.top() so we can't apply resetFrame() directly on aState resetFrame(); parBreak(); // Save this state for later use, so we only reset frame status only for the first shape inside a frame. - aState = m_aStates.top(); + rState = m_aStates.top(); m_bNeedPap = true; } break; @@ -2920,7 +2897,7 @@ RTFError RTFDocumentImpl::popState() case Destination::MGROW: { sal_Int32 nMathToken = 0; - switch (aState.getDestination()) + switch (rState.getDestination()) { case Destination::MCHR: nMathToken = M_TOKEN(chr); @@ -3081,14 +3058,14 @@ RTFError RTFDocumentImpl::popState() m_aMathBuffer.appendClosingTag(M_TOKEN(eqArr)); break; case Destination::SHAPEGROUP: - if (aState.getCreatedShapeGroup()) + if (rState.getCreatedShapeGroup()) m_pSdrImport->popParent(); break; case Destination::PROPNAME: if (&m_aStates.top().getDestinationText() != m_aStates.top().getCurrentDestinationText()) break; // not for nested group - aState.setPropName(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); + rState.setPropName(m_aStates.top().getCurrentDestinationText()->makeStringAndClear()); break; case Destination::STATICVAL: if (&m_aStates.top().getDestinationText() @@ -3181,47 +3158,22 @@ RTFError RTFDocumentImpl::popState() break; } - // See if we need to end a track change - if (aState.getStartedTrackchange()) - { - RTFSprms aTCSprms; - auto pValue = new RTFValue(0); - aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue); - if (!m_aStates.top().getCurrentBuffer()) - Mapper().props(new RTFReferenceProperties(RTFSprms(), aTCSprms)); - else - bufferProperties(*m_aStates.top().getCurrentBuffer(), - new RTFValue(RTFSprms(), aTCSprms), nullptr); - } - - // This is the end of the doc, see if we need to close the last section. - if (m_pTokenizer->getGroup() == 1 && !m_bFirstRun) - { - // \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) - dispatchSymbol(RTF_PAR); - if (m_bNeedSect) // may be set by dispatchSymbol above! - sectBreak(true); - } - - m_aStates.pop(); - - m_pTokenizer->popGroup(); + return RTFError::OK; +} +void RTFDocumentImpl::afterPopState(RTFParserState& rState) +{ // list table - switch (aState.getDestination()) + switch (rState.getDestination()) { case Destination::LISTENTRY: { - auto pValue = new RTFValue(aState.getTableAttributes(), aState.getTableSprms()); + auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue, RTFOverwrite::NO_APPEND); - m_aListTable[aState.getCurrentListIndex()] = pValue; + m_aListTable[rState.getCurrentListIndex()] = pValue; m_nListLevel = -1; - m_aInvalidListTableFirstIndents[aState.getCurrentListIndex()] + m_aInvalidListTableFirstIndents[rState.getCurrentListIndex()] = m_aInvalidListLevelFirstIndents; m_aInvalidListLevelFirstIndents.clear(); } @@ -3229,19 +3181,19 @@ RTFError RTFDocumentImpl::popState() case Destination::PARAGRAPHNUMBERING: { RTFValue::Pointer_t pIdValue - = aState.getTableAttributes().find(NS_ooxml::LN_CT_AbstractNum_nsid); + = rState.getTableAttributes().find(NS_ooxml::LN_CT_AbstractNum_nsid); if (pIdValue.get() && !m_aStates.empty()) { // Abstract numbering RTFSprms aLeveltextAttributes; OUString aTextValue; RTFValue::Pointer_t pTextBefore - = aState.getTableAttributes().find(NS_ooxml::LN_CT_LevelText_val); + = rState.getTableAttributes().find(NS_ooxml::LN_CT_LevelText_val); if (pTextBefore) aTextValue += pTextBefore->getString(); aTextValue += "%1"; RTFValue::Pointer_t pTextAfter - = aState.getTableAttributes().find(NS_ooxml::LN_CT_LevelSuffix_val); + = rState.getTableAttributes().find(NS_ooxml::LN_CT_LevelSuffix_val); if (pTextAfter) aTextValue += pTextAfter->getString(); auto pTextValue = new RTFValue(aTextValue); @@ -3253,19 +3205,19 @@ RTFError RTFDocumentImpl::popState() aLevelAttributes.set(NS_ooxml::LN_CT_Lvl_ilvl, pIlvlValue); RTFValue::Pointer_t pFmtValue - = aState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_numFmt); + = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_numFmt); if (pFmtValue) aLevelSprms.set(NS_ooxml::LN_CT_Lvl_numFmt, pFmtValue); RTFValue::Pointer_t pStartatValue - = aState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_start); + = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_start); if (pStartatValue) aLevelSprms.set(NS_ooxml::LN_CT_Lvl_start, pStartatValue); auto pLeveltextValue = new RTFValue(aLeveltextAttributes); aLevelSprms.set(NS_ooxml::LN_CT_Lvl_lvlText, pLeveltextValue); RTFValue::Pointer_t pRunProps - = aState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_rPr); + = rState.getTableSprms().find(NS_ooxml::LN_CT_Lvl_rPr); if (pRunProps) aLevelSprms.set(NS_ooxml::LN_CT_Lvl_rPr, pRunProps); @@ -3314,7 +3266,7 @@ RTFError RTFDocumentImpl::popState() if (!m_aStates.empty()) { // FIXME: don't use pDestinationText, points to popped state - auto pValue = new RTFValue(aState.getDestinationText().makeStringAndClear(), true); + auto pValue = new RTFValue(rState.getDestinationText().makeStringAndClear(), true); m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_LevelSuffix_val, pValue); } break; @@ -3322,7 +3274,7 @@ RTFError RTFDocumentImpl::popState() if (!m_aStates.empty()) { // FIXME: don't use pDestinationText, points to popped state - auto pValue = new RTFValue(aState.getDestinationText().makeStringAndClear(), true); + auto pValue = new RTFValue(rState.getDestinationText().makeStringAndClear(), true); m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_LevelText_val, pValue); } break; @@ -3332,9 +3284,9 @@ RTFError RTFDocumentImpl::popState() if (!m_aStates.empty()) { auto pInnerValue = new RTFValue(m_aStates.top().getListLevelNum()++); - aState.getTableAttributes().set(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue); + rState.getTableAttributes().set(NS_ooxml::LN_CT_Lvl_ilvl, pInnerValue); - auto pValue = new RTFValue(aState.getTableAttributes(), aState.getTableSprms()); + auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); if (m_aStates.top().getDestination() != Destination::LFOLEVEL) m_aStates.top().getListLevelEntries().set(NS_ooxml::LN_CT_AbstractNum_lvl, pValue, RTFOverwrite::NO_APPEND); @@ -3346,9 +3298,9 @@ RTFError RTFDocumentImpl::popState() if (!m_aStates.empty()) { auto pInnerValue = new RTFValue(m_aStates.top().getListLevelNum()++); - aState.getTableAttributes().set(NS_ooxml::LN_CT_NumLvl_ilvl, pInnerValue); + rState.getTableAttributes().set(NS_ooxml::LN_CT_NumLvl_ilvl, pInnerValue); - auto pValue = new RTFValue(aState.getTableAttributes(), aState.getTableSprms()); + auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Num_lvlOverride, pValue, RTFOverwrite::NO_APPEND); } @@ -3360,35 +3312,35 @@ RTFError RTFDocumentImpl::popState() if (m_aStates.top().getDestination() == Destination::LISTOVERRIDEENTRY) { // copy properties upwards so upper popState() inserts it - m_aStates.top().getTableAttributes() = aState.getTableAttributes(); - m_aStates.top().getTableSprms() = aState.getTableSprms(); + m_aStates.top().getTableAttributes() = rState.getTableAttributes(); + m_aStates.top().getTableSprms() = rState.getTableSprms(); } else { - auto pValue = new RTFValue(aState.getTableAttributes(), aState.getTableSprms()); + auto pValue = new RTFValue(rState.getTableAttributes(), rState.getTableSprms()); m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pValue, RTFOverwrite::NO_APPEND); - m_aListOverrideTable[aState.getCurrentListOverrideIndex()] - = aState.getCurrentListIndex(); + m_aListOverrideTable[rState.getCurrentListOverrideIndex()] + = rState.getCurrentListIndex(); } } break; case Destination::LEVELTEXT: if (!m_aStates.empty()) { - auto pValue = new RTFValue(aState.getTableAttributes()); + auto pValue = new RTFValue(rState.getTableAttributes()); m_aStates.top().getTableSprms().set(NS_ooxml::LN_CT_Lvl_lvlText, pValue); } break; case Destination::LEVELNUMBERS: if (!m_aStates.empty()) { - m_aStates.top().getTableSprms() = aState.getTableSprms(); + m_aStates.top().getTableSprms() = rState.getTableSprms(); if (m_aStates.top().getDestination() == Destination::LEVELNUMBERS || m_aStates.top().getDestination() == Destination::LISTLEVEL) // Parent state is level number or list level, current state is // level numbers: mark parent as invalid as well if necessary. - m_aStates.top().setLevelNumbersValid(aState.getLevelNumbersValid()); + m_aStates.top().setLevelNumbersValid(rState.getLevelNumbersValid()); } break; case Destination::FIELDINSTRUCTION: @@ -3400,29 +3352,29 @@ RTFError RTFDocumentImpl::popState() m_aStates.top().setFieldStatus(RTFFieldStatus::RESULT); break; case Destination::FIELD: - if (aState.getFieldStatus() == RTFFieldStatus::INSTRUCTION) + if (rState.getFieldStatus() == RTFFieldStatus::INSTRUCTION) singleChar(cFieldEnd); break; case Destination::SHAPEPROPERTYVALUEPICT: if (!m_aStates.empty()) { - m_aStates.top().getPicture() = aState.getPicture(); + m_aStates.top().getPicture() = rState.getPicture(); // both \sp and \sv are destinations, copy the text up-ward for later - m_aStates.top().getDestinationText() = aState.getDestinationText(); + m_aStates.top().getDestinationText() = rState.getDestinationText(); } break; case Destination::FALT: if (!m_aStates.empty()) - m_aStates.top().getTableSprms() = aState.getTableSprms(); + m_aStates.top().getTableSprms() = rState.getTableSprms(); break; case Destination::SHAPEPROPERTYNAME: case Destination::SHAPEPROPERTYVALUE: case Destination::SHAPEPROPERTY: if (!m_aStates.empty()) { - m_aStates.top().getShape() = aState.getShape(); - m_aStates.top().getPicture() = aState.getPicture(); - m_aStates.top().getCharacterAttributes() = aState.getCharacterAttributes(); + m_aStates.top().getShape() = rState.getShape(); + m_aStates.top().getPicture() = rState.getPicture(); + m_aStates.top().getCharacterAttributes() = rState.getCharacterAttributes(); } break; case Destination::SHAPEINSTRUCTION: @@ -3431,10 +3383,10 @@ RTFError RTFDocumentImpl::popState() { // Shape instruction inside other shape instruction: just copy new shape settings: // it will be resolved on end of topmost shape instruction destination - m_aStates.top().getShape() = aState.getShape(); - m_aStates.top().getPicture() = aState.getPicture(); - m_aStates.top().getCharacterSprms() = aState.getCharacterSprms(); - m_aStates.top().getCharacterAttributes() = aState.getCharacterAttributes(); + m_aStates.top().getShape() = rState.getShape(); + m_aStates.top().getPicture() = rState.getPicture(); + m_aStates.top().getCharacterSprms() = rState.getCharacterSprms(); + m_aStates.top().getCharacterAttributes() = rState.getCharacterAttributes(); } break; case Destination::FLYMAINCONTENT: @@ -3442,8 +3394,8 @@ RTFError RTFDocumentImpl::popState() case Destination::SHAPE: if (!m_aStates.empty()) { - m_aStates.top().getFrame() = aState.getFrame(); - if (aState.getDestination() == Destination::SHPPICT + m_aStates.top().getFrame() = rState.getFrame(); + if (rState.getDestination() == Destination::SHPPICT && m_aStates.top().getDestination() == Destination::LISTPICTURE) { RTFSprms aAttributes; @@ -3475,29 +3427,91 @@ RTFError RTFDocumentImpl::popState() // It's allowed to declare these inside the shape text, and they // are expected to have an effect for the whole shape. - if (aState.getDrawingObject().getLeft()) - m_aStates.top().getDrawingObject().setLeft(aState.getDrawingObject().getLeft()); - if (aState.getDrawingObject().getTop()) - m_aStates.top().getDrawingObject().setTop(aState.getDrawingObject().getTop()); - if (aState.getDrawingObject().getRight()) + if (rState.getDrawingObject().getLeft()) + m_aStates.top().getDrawingObject().setLeft(rState.getDrawingObject().getLeft()); + if (rState.getDrawingObject().getTop()) + m_aStates.top().getDrawingObject().setTop(rState.getDrawingObject().getTop()); + if (rState.getDrawingObject().getRight()) m_aStates.top().getDrawingObject().setRight( - aState.getDrawingObject().getRight()); - if (aState.getDrawingObject().getBottom()) + rState.getDrawingObject().getRight()); + if (rState.getDrawingObject().getBottom()) m_aStates.top().getDrawingObject().setBottom( - aState.getDrawingObject().getBottom()); + rState.getDrawingObject().getBottom()); } break; case Destination::PROPNAME: if (m_aStates.top().getDestination() == Destination::USERPROPS) - m_aStates.top().setPropName(aState.getPropName()); + m_aStates.top().setPropName(rState.getPropName()); break; default: { if (!m_aStates.empty() && m_aStates.top().getDestination() == Destination::PICT) - m_aStates.top().getPicture() = aState.getPicture(); + m_aStates.top().getPicture() = rState.getPicture(); } break; } +} + +RTFError RTFDocumentImpl::popState() +{ + //SAL_INFO("writerfilter", OSL_THIS_FUNC << " before pop: m_pTokenizer->getGroup() " << m_pTokenizer->getGroup() << + // ", dest state: " << m_aStates.top().eDestination); + + checkUnicode(/*bUnicode =*/true, /*bHex =*/true); + RTFParserState aState(m_aStates.top()); + m_bWasInFrame = aState.getFrame().inFrame(); + + // dmapper expects some content in header/footer, so if there would be nothing, add an empty paragraph. + if (m_pTokenizer->getGroup() == 1 && m_bFirstRun) + { + switch (m_nStreamType) + { + case NS_ooxml::LN_headerl: + case NS_ooxml::LN_headerr: + case NS_ooxml::LN_headerf: + case NS_ooxml::LN_footerl: + case NS_ooxml::LN_footerr: + case NS_ooxml::LN_footerf: + dispatchSymbol(RTF_PAR); + break; + } + } + + RTFError eError = beforePopState(aState); + if (eError != RTFError::OK) + return eError; + + // See if we need to end a track change + if (aState.getStartedTrackchange()) + { + RTFSprms aTCSprms; + auto pValue = new RTFValue(0); + aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue); + if (!m_aStates.top().getCurrentBuffer()) + Mapper().props(new RTFReferenceProperties(RTFSprms(), aTCSprms)); + else + bufferProperties(*m_aStates.top().getCurrentBuffer(), + new RTFValue(RTFSprms(), aTCSprms), nullptr); + } + + // This is the end of the doc, see if we need to close the last section. + if (m_pTokenizer->getGroup() == 1 && !m_bFirstRun) + { + // \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) + dispatchSymbol(RTF_PAR); + if (m_bNeedSect) // may be set by dispatchSymbol above! + sectBreak(true); + } + + m_aStates.pop(); + + m_pTokenizer->popGroup(); + + afterPopState(aState); if (aState.getCurrentBuffer() == &m_aSuperBuffer) { diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index 31b83a855dea..7901d6ee31c5 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -698,7 +698,9 @@ public: RTFError dispatchValue(RTFKeyword nKeyword, int nParam) override; RTFError resolveChars(char ch) override; RTFError pushState() override; + RTFError beforePopState(RTFParserState& rState); RTFError popState() override; + void afterPopState(RTFParserState& rState); Destination getDestination() override; void setDestination(Destination eDestination) override; RTFInternalState getInternalState() override; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits