summaryrefslogtreecommitdiff
path: root/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/rtftok/rtfdispatchsymbol.cxx')
-rw-r--r--writerfilter/source/rtftok/rtfdispatchsymbol.cxx455
1 files changed, 0 insertions, 455 deletions
diff --git a/writerfilter/source/rtftok/rtfdispatchsymbol.cxx b/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
deleted file mode 100644
index b40fd55dde9b..000000000000
--- a/writerfilter/source/rtftok/rtfdispatchsymbol.cxx
+++ /dev/null
@@ -1,455 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#include "rtfdocumentimpl.hxx"
-
-#include <com/sun/star/io/WrongFormatException.hpp>
-#include <svl/lngmisc.hxx>
-
-#include <ooxml/resourceids.hxx>
-
-#include <sal/log.hxx>
-
-#include "rtfreferenceproperties.hxx"
-#include "rtfskipdestination.hxx"
-
-using namespace com::sun::star;
-
-namespace writerfilter::rtftok
-{
-RTFError RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
-{
- setNeedSect(true);
- if (nKeyword != RTFKeyword::HEXCHAR)
- checkUnicode(/*bUnicode =*/true, /*bHex =*/true);
- else
- checkUnicode(/*bUnicode =*/true, /*bHex =*/false);
- RTFSkipDestination aSkip(*this);
-
- if (RTFKeyword::LINE == nKeyword)
- {
- // very special handling since text() will eat lone '\n'
- singleChar('\n', /*bRunProps=*/true);
- return RTFError::OK;
- }
- // Trivial symbols
- sal_uInt8 cCh = 0;
- switch (nKeyword)
- {
- case RTFKeyword::TAB:
- cCh = '\t';
- break;
- case RTFKeyword::BACKSLASH:
- cCh = '\\';
- break;
- case RTFKeyword::LBRACE:
- cCh = '{';
- break;
- case RTFKeyword::RBRACE:
- cCh = '}';
- break;
- case RTFKeyword::EMDASH:
- cCh = 151;
- break;
- case RTFKeyword::ENDASH:
- cCh = 150;
- break;
- case RTFKeyword::BULLET:
- cCh = 149;
- break;
- case RTFKeyword::LQUOTE:
- cCh = 145;
- break;
- case RTFKeyword::RQUOTE:
- cCh = 146;
- break;
- case RTFKeyword::LDBLQUOTE:
- cCh = 147;
- break;
- case RTFKeyword::RDBLQUOTE:
- cCh = 148;
- break;
- default:
- break;
- }
- if (cCh > 0)
- {
- OUString aStr(OStringToOUString(OStringChar(char(cCh)), RTL_TEXTENCODING_MS_1252));
- text(aStr);
- return RTFError::OK;
- }
-
- switch (nKeyword)
- {
- case RTFKeyword::IGNORE:
- {
- m_bSkipUnknown = true;
- aSkip.setReset(false);
- return RTFError::OK;
- }
- break;
- case RTFKeyword::PAR:
- {
- if (m_aStates.top().getDestination() == Destination::FOOTNOTESEPARATOR)
- break; // just ignore it - only thing we read in here is CHFTNSEP
- checkFirstRun();
- checkNeedPap();
- runProps(); // tdf#152872 paragraph marker formatting
- if (!m_aStates.top().getCurrentBuffer())
- {
- parBreak();
- // Not in table? Reset max width.
- if (m_nCellxMax)
- {
- // Was in table, but not anymore -> tblEnd.
- RTFSprms aAttributes;
- RTFSprms aSprms;
- aSprms.set(NS_ooxml::LN_tblEnd, new RTFValue(1));
- writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(std::move(aAttributes), std::move(aSprms));
- Mapper().props(pProperties);
- }
- m_nCellxMax = 0;
- }
- else if (m_aStates.top().getDestination() != Destination::SHAPETEXT)
- {
- RTFValue::Pointer_t pValue;
- m_aStates.top().getCurrentBuffer()->push_back(Buf_t(BUFFER_PAR, pValue, nullptr));
- }
- // but don't emit properties yet, since they may change till the first text token arrives
- m_bNeedPap = true;
- if (!m_aStates.top().getFrame().hasProperties())
- m_bNeedPar = false;
- m_bNeedFinalPar = false;
- }
- break;
- case RTFKeyword::SECT:
- {
- m_bHadSect = true;
- if (m_bIgnoreNextContSectBreak || m_aStates.top().getFrame().hasProperties())
- {
- // testContSectionPageBreak: need \par now
- dispatchSymbol(RTFKeyword::PAR);
- m_bIgnoreNextContSectBreak = false;
- }
- else
- {
- bool bPendingFloatingTable = false;
- RTFValue::Pointer_t pTblpPr
- = m_aStates.top().getTableRowSprms().find(NS_ooxml::LN_CT_TblPrBase_tblpPr);
- if (pTblpPr)
- {
- // We have a pending floating table, provide an anchor for it still in this
- // section.
- bPendingFloatingTable = true;
- }
-
- if (m_bNeedCr || bPendingFloatingTable)
- { // tdf#158586 don't dispatch \par here, it eats deferred page breaks
- setNeedPar(true);
- }
-
- sectBreak();
- if (m_nResetBreakOnSectBreak != RTFKeyword::invalid)
- {
- // this should run on _second_ \sect after \page
- dispatchFlag(m_nResetBreakOnSectBreak); // lazy reset
- m_nResetBreakOnSectBreak = RTFKeyword::invalid;
- m_bNeedSect = false; // dispatchSymbol set it
- }
- setNeedPar(true); // testFdo52052: need \par at end of document
- // testNestedTable: but not m_bNeedCr, that creates a page break
- }
- }
- break;
- case RTFKeyword::NOBREAK:
- {
- OUString aStr(SVT_HARD_SPACE);
- text(aStr);
- }
- break;
- case RTFKeyword::NOBRKHYPH:
- {
- OUString aStr(SVT_HARD_HYPHEN);
- text(aStr);
- }
- break;
- case RTFKeyword::OPTHYPH:
- {
- OUString aStr(SVT_SOFT_HYPHEN);
- text(aStr);
- }
- break;
- case RTFKeyword::HEXCHAR:
- m_aStates.top().setInternalState(RTFInternalState::HEX);
- break;
- case RTFKeyword::CELL:
- case RTFKeyword::NESTCELL:
- {
- checkFirstRun();
- if (m_bNeedPap)
- {
- // There were no runs in the cell, so we need to send paragraph and character properties here.
- auto pPValue = new RTFValue(m_aStates.top().getParagraphAttributes(),
- m_aStates.top().getParagraphSprms());
- bufferProperties(m_aTableBufferStack.back(), pPValue, nullptr);
- auto pCValue = new RTFValue(m_aStates.top().getCharacterAttributes(),
- m_aStates.top().getCharacterSprms());
- bufferProperties(m_aTableBufferStack.back(), pCValue, nullptr);
- }
-
- RTFValue::Pointer_t pValue;
- m_aTableBufferStack.back().emplace_back(Buf_t(BUFFER_CELLEND, pValue, nullptr));
- m_bNeedPap = true;
- }
- break;
- case RTFKeyword::NESTROW:
- {
- tools::SvRef<TableRowBuffer> const pBuffer(
- new TableRowBuffer(m_aTableBufferStack.back(), m_aNestedTableCellsSprms,
- m_aNestedTableCellsAttributes, m_nNestedCells));
- prepareProperties(m_aStates.top(), pBuffer->GetParaProperties(),
- pBuffer->GetFrameProperties(), pBuffer->GetRowProperties(),
- m_nNestedCells, m_nNestedCurrentCellX - m_nNestedTRLeft);
-
- if (m_aTableBufferStack.size() == 1 || !m_aStates.top().getCurrentBuffer())
- {
- throw io::WrongFormatException("mismatch between \\itap and number of \\nestrow",
- nullptr);
- }
- assert(m_aStates.top().getCurrentBuffer() == &m_aTableBufferStack.back());
- // note: there may be several states pointing to table buffer!
- for (std::size_t i = 0; i < m_aStates.size(); ++i)
- {
- if (m_aStates[i].getCurrentBuffer() == &m_aTableBufferStack.back())
- {
- m_aStates[i].setCurrentBuffer(
- &m_aTableBufferStack[m_aTableBufferStack.size() - 2]);
- }
- }
- m_aTableBufferStack.pop_back();
- m_aTableBufferStack.back().emplace_back(
- Buf_t(BUFFER_NESTROW, RTFValue::Pointer_t(), pBuffer));
-
- m_aNestedTableCellsSprms.clear();
- m_aNestedTableCellsAttributes.clear();
- m_nNestedCells = 0;
- m_bNeedPap = true;
- }
- break;
- case RTFKeyword::ROW:
- {
- if (m_aStates.top().getTableRowWidthAfter() > 0)
- {
- // Add fake cellx / cell, RTF equivalent of
- // OOXMLFastContextHandlerTextTableRow::handleGridAfter().
- auto pXValue = new RTFValue(m_aStates.top().getTableRowWidthAfter());
- m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue,
- RTFOverwrite::NO_APPEND);
- dispatchSymbol(RTFKeyword::CELL);
-
- // Adjust total width, which is done in the \cellx handler for normal cells.
- m_nTopLevelCurrentCellX += m_aStates.top().getTableRowWidthAfter();
-
- m_aStates.top().setTableRowWidthAfter(0);
- }
-
- bool bRestored = false;
- // Ending a row, but no cells defined?
- // See if there was an invalid table row reset, so we can restore cell infos to help invalid documents.
- if (!m_nTopLevelCurrentCellX && m_nBackupTopLevelCurrentCellX)
- {
- restoreTableRowProperties();
- bRestored = true;
- }
-
- // If the right edge of the last cell (row width) is smaller than the width of some other row, mimic WW8TabDesc::CalcDefaults(): resize the last cell
- const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
- if ((m_nCellxMax - m_nTopLevelCurrentCellX) >= MINLAY)
- {
- auto pXValueLast = m_aStates.top().getTableRowSprms().find(
- NS_ooxml::LN_CT_TblGridBase_gridCol, false);
- const int nXValueLast = pXValueLast ? pXValueLast->getInt() : 0;
- auto pXValue = new RTFValue(nXValueLast + m_nCellxMax - m_nTopLevelCurrentCellX);
- m_aStates.top().getTableRowSprms().eraseLast(NS_ooxml::LN_CT_TblGridBase_gridCol);
- m_aStates.top().getTableRowSprms().set(NS_ooxml::LN_CT_TblGridBase_gridCol, pXValue,
- RTFOverwrite::NO_APPEND);
- m_nTopLevelCurrentCellX = m_nCellxMax;
- }
-
- if (m_nTopLevelCells)
- {
- // Make a backup before we start popping elements
- m_aTableInheritingCellsSprms = m_aTopLevelTableCellsSprms;
- m_aTableInheritingCellsAttributes = m_aTopLevelTableCellsAttributes;
- m_nInheritingCells = m_nTopLevelCells;
- }
- else
- {
- // No table definition? Then inherit from the previous row
- m_aTopLevelTableCellsSprms = m_aTableInheritingCellsSprms;
- m_aTopLevelTableCellsAttributes = m_aTableInheritingCellsAttributes;
- m_nTopLevelCells = m_nInheritingCells;
- }
-
- while (m_aTableBufferStack.size() > 1)
- {
- SAL_WARN("writerfilter.rtf", "dropping extra table buffer");
- // note: there may be several states pointing to table buffer!
- for (std::size_t i = 0; i < m_aStates.size(); ++i)
- {
- if (m_aStates[i].getCurrentBuffer() == &m_aTableBufferStack.back())
- {
- m_aStates[i].setCurrentBuffer(&m_aTableBufferStack.front());
- }
- }
- m_aTableBufferStack.pop_back();
- }
-
- replayRowBuffer(m_aTableBufferStack.back(), m_aTopLevelTableCellsSprms,
- m_aTopLevelTableCellsAttributes, m_nTopLevelCells);
-
- // The scope of the table cell defaults is one row.
- m_aDefaultState.getTableCellSprms().clear();
- m_aStates.top().getTableCellSprms() = m_aDefaultState.getTableCellSprms();
- m_aStates.top().getTableCellAttributes() = m_aDefaultState.getTableCellAttributes();
-
- writerfilter::Reference<Properties>::Pointer_t paraProperties;
- writerfilter::Reference<Properties>::Pointer_t frameProperties;
- writerfilter::Reference<Properties>::Pointer_t rowProperties;
- prepareProperties(m_aStates.top(), paraProperties, frameProperties, rowProperties,
- m_nTopLevelCells, m_nTopLevelCurrentCellX - m_nTopLevelTRLeft);
- sendProperties(paraProperties, frameProperties, rowProperties);
-
- m_bNeedPap = true;
- m_bNeedFinalPar = true;
- m_aTableBufferStack.back().clear();
- m_nTopLevelCells = 0;
-
- if (bRestored)
- // We restored cell definitions, clear these now.
- // This is necessary, as later cell definitions want to overwrite the restored ones.
- resetTableRowProperties();
- }
- break;
- case RTFKeyword::COLUMN:
- {
- bool bColumns = false; // If we have multiple columns
- RTFValue::Pointer_t pCols
- = m_aStates.top().getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_cols);
- if (pCols)
- {
- RTFValue::Pointer_t pNum = pCols->getAttributes().find(NS_ooxml::LN_CT_Columns_num);
- if (pNum && pNum->getInt() > 1)
- bColumns = true;
- }
- checkFirstRun();
- if (bColumns)
- {
- sal_uInt8 const sBreak[] = { 0xe };
- Mapper().startCharacterGroup();
- Mapper().text(sBreak, 1);
- Mapper().endCharacterGroup();
- }
- else
- dispatchSymbol(RTFKeyword::PAGE);
- }
- break;
- case RTFKeyword::CHFTN:
- {
- if (m_aStates.top().getCurrentBuffer() == &m_aSuperBuffer)
- // Stop buffering, there will be no custom mark for this footnote or endnote.
- m_aStates.top().setCurrentBuffer(nullptr);
- break;
- }
- case RTFKeyword::PAGE:
- {
- // Ignore page breaks inside tables.
- if (m_aStates.top().getCurrentBuffer() == &m_aTableBufferStack.back())
- break;
-
- // If we're inside a continuous section, we should send a section break, not a page one.
- RTFValue::Pointer_t pBreak
- = m_aStates.top().getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_type);
- // Unless we're on a title page.
- RTFValue::Pointer_t pTitlePg
- = m_aStates.top().getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_titlePg);
- if (((pBreak
- && pBreak->getInt()
- == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous)
- && m_bHadSect) // tdf#158983 before first \sect, ignore \sbknone!
- || m_nResetBreakOnSectBreak == RTFKeyword::SBKNONE)
- && !(pTitlePg && pTitlePg->getInt()))
- {
- if (m_bWasInFrame)
- {
- dispatchSymbol(RTFKeyword::PAR);
- m_bWasInFrame = false;
- }
- sectBreak();
- // note: this will not affect the following section break
- // but the one just pushed
- dispatchFlag(RTFKeyword::SBKPAGE);
- if (m_bNeedPar)
- dispatchSymbol(RTFKeyword::PAR);
- m_bIgnoreNextContSectBreak = true;
- // arrange to clean up the synthetic RTFKeyword::SBKPAGE
- m_nResetBreakOnSectBreak = RTFKeyword::SBKNONE;
- }
- else
- {
- bool bFirstRun = m_bFirstRun;
- checkFirstRun();
- if (bFirstRun || m_bNeedCr)
- {
- // Only send the paragraph properties early if we'll create a new paragraph in a
- // bit anyway.
- checkNeedPap();
- // flush previously deferred break - needed for testFdo49893_2
- // which has consecutive \page with no text between
- sal_Unicode const nothing[] = { 0 /*MSVC doesn't allow it to be empty*/ };
- Mapper().utext(nothing, 0);
- }
- sal_uInt8 const sBreak[] = { 0xc };
- Mapper().text(sBreak, 1);
- // testFdo81892 don't do another \par break directly; because of
- // GetSplitPgBreakAndParaMark() it does finishParagraph *twice*
- m_bNeedCr = true;
- }
- }
- break;
- case RTFKeyword::CHPGN:
- {
- OUString aStr("PAGE");
- singleChar(cFieldStart);
- text(aStr);
- singleChar(cFieldSep, true);
- singleChar(cFieldEnd);
- }
- break;
- case RTFKeyword::CHFTNSEP:
- {
- static const sal_Unicode uFtnEdnSep = 0x3;
- Mapper().utext(&uFtnEdnSep, 1);
- }
- break;
- default:
- {
- SAL_INFO("writerfilter.rtf",
- "TODO handle symbol '" << keywordToString(nKeyword) << "'");
- aSkip.setParsed(false);
- }
- break;
- }
- return RTFError::OK;
-}
-
-} // namespace writerfilter::rtftok
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */