sw/source/core/docnode/ndtbl.cxx | 247 ++++++++++++++++-------------------- sw/source/core/table/swnewtable.cxx | 34 +++- 2 files changed, 137 insertions(+), 144 deletions(-)
New commits: commit 5e21ad82ef769b944927b498a196ec82476e17e8 Author: Michael Stahl <mst...@redhat.com> Date: Mon Sep 24 13:44:50 2012 +0200 de-duplicate SwNodes::TextToTable() Change-Id: I8a61b67cb5bd1333c05f9a98c7af6e3ed05c8fd0 diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx index 22e44f5..cc7e88f 100644 --- a/sw/source/core/docnode/ndtbl.cxx +++ b/sw/source/core/docnode/ndtbl.cxx @@ -889,6 +889,112 @@ const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTblOpts, return pNdTbl; } +static void lcl_RemoveBreaks(SwCntntNode & rNode, SwTableFmt *const pTableFmt) +{ + // delete old layout frames, new ones need to be created... + rNode.DelFrms(); + + if (!rNode.IsTxtNode()) + { + return; + } + + SwTxtNode & rTxtNode = static_cast<SwTxtNode&>(rNode); + // remove PageBreaks/PageDesc/ColBreak + SfxItemSet const* pSet = rTxtNode.GetpSwAttrSet(); + if (pSet) + { + const SfxPoolItem* pItem; + if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false, &pItem)) + { + if (pTableFmt) + { + pTableFmt->SetFmtAttr(*pItem); + } + rTxtNode.ResetAttr(RES_BREAK); + pSet = rTxtNode.GetpSwAttrSet(); + } + + if (pSet + && (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false, &pItem)) + && static_cast<SwFmtPageDesc const*>(pItem)->GetPageDesc()) + { + if (pTableFmt) + { + pTableFmt->SetFmtAttr(*pItem); + } + rTxtNode.ResetAttr(RES_PAGEDESC); + } + } +} + +static void +lcl_BalanceTable(SwTable & rTable, size_t const nMaxBoxes, + SwTableNode & rTblNd, SwTableBoxFmt & rBoxFmt, SwTxtFmtColl & rTxtColl, + SwUndoTxtToTbl *const pUndo, std::vector<sal_uInt16> *const pPositions) +{ + // balance lines in table, insert empty boxes so all lines have the size + for (size_t n = 0; n < rTable.GetTabLines().size(); ++n) + { + SwTableLine *const pCurrLine = rTable.GetTabLines()[ n ]; + size_t const nBoxes = pCurrLine->GetTabBoxes().size(); + if (nMaxBoxes != nBoxes) + { + rTblNd.GetNodes().InsBoxen(&rTblNd, pCurrLine, &rBoxFmt, &rTxtColl, + 0, nBoxes, nMaxBoxes - nBoxes); + + if (pUndo) + { + for (size_t i = nBoxes; i < nMaxBoxes; ++i) + { + pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[i] ); + } + } + + // if the first line is missing boxes, the width array is useless! + if (!n && pPositions) + { + pPositions->clear(); + } + } + } +} + +static void +lcl_SetTableBoxWidths(SwTable & rTable, size_t const nMaxBoxes, + SwTableBoxFmt & rBoxFmt, SwDoc & rDoc, + std::vector<sal_uInt16> *const pPositions) +{ + if (pPositions && !pPositions->empty()) + { + SwTableLines& rLns = rTable.GetTabLines(); + sal_uInt16 nLastPos = 0; + for (size_t n = 0; n < pPositions->size(); ++n) + { + SwTableBoxFmt *pNewFmt = rDoc.MakeTableBoxFmt(); + pNewFmt->SetFmtAttr( + SwFmtFrmSize(ATT_VAR_SIZE, (*pPositions)[n] - nLastPos)); + for (size_t nTmpLine = 0; nTmpLine < rLns.size(); ++nTmpLine) + { + //JP 24.06.98: have to do an Add here, because the BoxFormat is + // still needed by the caller + pNewFmt->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] ); + } + + nLastPos = (*pPositions)[ n ]; + } + + // propagate size upwards from format, so the table gets the right size + SAL_WARN_IF(rBoxFmt.GetDepends(), "sw.core", + "who is still registered in the format?"); + rBoxFmt.SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos )); + } + else + { + rBoxFmt.SetFmtAttr(SwFmtFrmSize(ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes)); + } +} + SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh, SwTableFmt* pTblFmt, SwTableLineFmt* pLineFmt, @@ -945,31 +1051,7 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh, } } - // die alten Frames loeschen, es werden neue erzeugt - pTxtNd->DelFrms(); - - // PageBreaks/PageDesc/ColBreak rausschmeissen. - const SfxItemSet* pSet = pTxtNd->GetpSwAttrSet(); - if( pSet ) - { - const SfxPoolItem* pItem; - if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) ) - { - if( !nLines ) - pTblFmt->SetFmtAttr( *pItem ); - pTxtNd->ResetAttr( RES_BREAK ); - pSet = pTxtNd->GetpSwAttrSet(); - } - - if( pSet && SFX_ITEM_SET == pSet->GetItemState( - RES_PAGEDESC, sal_False, &pItem ) && - ((SwFmtPageDesc*)pItem)->GetPageDesc() ) - { - if( !nLines ) - pTblFmt->SetFmtAttr( *pItem ); - pTxtNd->ResetAttr( RES_PAGEDESC ); - } - } + lcl_RemoveBreaks(*pTxtNd, (0 == nLines) ? pTblFmt : 0); // setze den bei allen TextNode in der Tabelle den TableNode // als StartNode @@ -1032,54 +1114,10 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh, nMaxBoxes = nBoxes; } - // die Tabelle ausgleichen, leere Sections einfuegen - sal_uInt16 n; - - for( n = 0; n < pTable->GetTabLines().size(); ++n ) - { - SwTableLine* pCurrLine = pTable->GetTabLines()[ n ]; - if( nMaxBoxes != ( nBoxes = pCurrLine->GetTabBoxes().size() )) - { - InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0, - nBoxes, nMaxBoxes - nBoxes ); - - if( pUndo ) - for( sal_uInt16 i = nBoxes; i < nMaxBoxes; ++i ) - pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[ i ] ); - - // fehlen der 1. Line Boxen, dann kann man das Breiten Array - // vergessen! - if( !n ) - aPosArr.clear(); - } - } - - if( !aPosArr.empty() ) - { - SwTableLines& rLns = pTable->GetTabLines(); - sal_uInt16 nLastPos = 0; - for( n = 0; n < aPosArr.size(); ++n ) - { - SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt(); - pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, - aPosArr[ n ] - nLastPos )); - for( sal_uInt16 nTmpLine = 0; nTmpLine < rLns.size(); ++nTmpLine ) - //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat - // von der rufenden Methode noch gebraucht wird! - pNewFmt->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] ); - - nLastPos = aPosArr[ n ]; - } + lcl_BalanceTable(*pTable, nMaxBoxes, *pTblNd, *pBoxFmt, *pTxtColl, + pUndo, &aPosArr); + lcl_SetTableBoxWidths(*pTable, nMaxBoxes, *pBoxFmt, *pDoc, &aPosArr); - // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die - // Groesse nach "oben" transportieren. - OSL_ENSURE( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" ); - pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos )); - } - else - pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes )); - - // das wars doch wohl ?? return pTblNd; } @@ -1295,7 +1333,6 @@ SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes, #endif SwDoc* pDoc = GetDoc(); - std::vector<sal_uInt16> aPosArr; SwTable * pTable = &pTblNd->GetTable(); SwTableLine* pLine; SwTableBox* pBox; @@ -1308,36 +1345,8 @@ SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes, SwNode& rNode = aNodeIndex.GetNode(); if( rNode.IsCntntNode() ) { - static_cast<SwCntntNode&>(rNode).DelFrms(); - if(rNode.IsTxtNode()) - { - SwTxtNode& rTxtNode = static_cast<SwTxtNode&>(rNode); - // setze den bei allen TextNode in der Tabelle den TableNode - // als StartNode - - // remove PageBreaks/PageDesc/ColBreak - const SwAttrSet* pSet = rTxtNode.GetpSwAttrSet(); - if( pSet ) - { - const SfxPoolItem* pItem; - if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, sal_False, &pItem ) ) - { - if( !nLines ) - pTblFmt->SetFmtAttr( *pItem ); - rTxtNode.ResetAttr( RES_BREAK ); - pSet = rTxtNode.GetpSwAttrSet(); - } - - if( pSet && SFX_ITEM_SET == pSet->GetItemState( - RES_PAGEDESC, sal_False, &pItem ) && - ((SwFmtPageDesc*)pItem)->GetPageDesc() ) - { - if( !nLines ) - pTblFmt->SetFmtAttr( *pItem ); - rTxtNode.ResetAttr( RES_PAGEDESC ); - } - } - } + lcl_RemoveBreaks(static_cast<SwCntntNode&>(rNode), + (0 == nLines) ? pTblFmt : 0); } } @@ -1383,49 +1392,11 @@ SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes, nMaxBoxes = nBoxes; } - // die Tabelle ausgleichen, leere Sections einfuegen - sal_uInt16 n; - - for (n = 0; n < pTable->GetTabLines().size(); ++n ) - { - // rhbz#820283: balance the cells in table rows - SwTableLine *const pCurrLine = pTable->GetTabLines()[ n ]; - nBoxes = pCurrLine->GetTabBoxes().size(); - SwTxtFmtColl *const pTxtColl(const_cast<SwTxtFmtColl*>( - GetDoc()->GetDfltTxtFmtColl())); - if (nMaxBoxes != nBoxes) - { - InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0, - nBoxes, nMaxBoxes - nBoxes ); - } - } - - if( !aPosArr.empty() ) - { - SwTableLines& rLns = pTable->GetTabLines(); - sal_uInt16 nLastPos = 0; - for( n = 0; n < aPosArr.size(); ++n ) - { - SwTableBoxFmt *pNewFmt = pDoc->MakeTableBoxFmt(); - pNewFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, - aPosArr[ n ] - nLastPos )); - for( sal_uInt16 nLines2 = 0; nLines2 < rLns.size(); ++nLines2 ) - //JP 24.06.98: hier muss ein Add erfolgen, da das BoxFormat - // von der rufenden Methode noch gebraucht wird! - pNewFmt->Add( rLns[ nLines2 ]->GetTabBoxes()[ n ] ); - - nLastPos = aPosArr[ n ]; - } - - // damit die Tabelle die richtige Groesse bekommt, im BoxFormat die - // Groesse nach "oben" transportieren. - OSL_ENSURE( !pBoxFmt->GetDepends(), "wer ist in dem Format noch angemeldet" ); - pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, nLastPos )); - } - else - pBoxFmt->SetFmtAttr( SwFmtFrmSize( ATT_VAR_SIZE, USHRT_MAX / nMaxBoxes )); + SwTxtFmtColl *const pTxtColl(const_cast<SwTxtFmtColl*>( + GetDoc()->GetDfltTxtFmtColl())); + lcl_BalanceTable(*pTable, nMaxBoxes, *pTblNd, *pBoxFmt, *pTxtColl, 0, 0); + lcl_SetTableBoxWidths(*pTable, nMaxBoxes, *pBoxFmt, *pDoc, 0); - // das wars doch wohl ?? return pTblNd; } commit 6d2e09db4a677068095b0bebd08fbbb96620d60c Author: Michael Stahl <mst...@redhat.com> Date: Mon Sep 24 11:21:11 2012 +0200 rhbz#820283: fix crashes in DOCX table import: It is apparently possible that writerfilter creates a table with irregular structure, where the lines have varying numbers of boxes in them. This may cause crashes on later editing operations, e.g. when SwTable::NewInsertCol() is unable to find boxes covering a particular column. To prevent this, add missing boxes in SwNodes::TextToTable(). Change-Id: I423821645baeaf55595e4933e1ab8fb89b2099f3 diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx index a39e015..22e44f5 100644 --- a/sw/source/core/docnode/ndtbl.cxx +++ b/sw/source/core/docnode/ndtbl.cxx @@ -1386,6 +1386,20 @@ SwTableNode* SwNodes::TextToTable( const SwNodes::TableRanges_t & rTableNodes, // die Tabelle ausgleichen, leere Sections einfuegen sal_uInt16 n; + for (n = 0; n < pTable->GetTabLines().size(); ++n ) + { + // rhbz#820283: balance the cells in table rows + SwTableLine *const pCurrLine = pTable->GetTabLines()[ n ]; + nBoxes = pCurrLine->GetTabBoxes().size(); + SwTxtFmtColl *const pTxtColl(const_cast<SwTxtFmtColl*>( + GetDoc()->GetDfltTxtFmtColl())); + if (nMaxBoxes != nBoxes) + { + InsBoxen( pTblNd, pCurrLine, pBoxFmt, pTxtColl, 0, + nBoxes, nMaxBoxes - nBoxes ); + } + } + if( !aPosArr.empty() ) { SwTableLines& rLns = pTable->GetTabLines(); commit 53c91152ea52d053fa85df9868b29524739ab0b7 Author: Michael Stahl <mst...@redhat.com> Date: Mon Sep 24 11:19:45 2012 +0200 tweak assertions in SwTable::CheckConsistency() Change-Id: Ib06543b7e59694f240b2b5fadcd6b464ce9e5792 diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx index 6ba86f5..12f60e3 100644 --- a/sw/source/core/table/swnewtable.cxx +++ b/sw/source/core/table/swnewtable.cxx @@ -700,7 +700,7 @@ sal_Bool SwTable::NewInsertCol( SwDoc* pDoc, const SwSelBoxes& rBoxes, { SwTableLine* pLine = aLines[ i ]; sal_uInt16 nInsPos = aInsPos[i]; - OSL_ENSURE( nInsPos != USHRT_MAX, "Didn't found insert position" ); + assert(nInsPos != USHRT_MAX); // didn't find insert position SwTableBox* pBox = pLine->GetTabBoxes()[ nInsPos ]; if( bBehind ) ++nInsPos; @@ -2114,22 +2114,24 @@ void SwTable::CheckConsistency() const { SwTwips nWidth = 0; SwTableLine* pLine = GetTabLines()[nCurrLine]; - SAL_WARN_IF( !pLine, "sw", "Missing Table Line" ); + SAL_WARN_IF( !pLine, "sw.core", "Missing Table Line" ); sal_uInt16 nColCount = pLine->GetTabBoxes().size(); - SAL_WARN_IF( !nColCount, "sw", "Empty Table Line" ); + SAL_WARN_IF( !nColCount, "sw.core", "Empty Table Line" ); for( sal_uInt16 nCurrCol = 0; nCurrCol < nColCount; ++nCurrCol ) { SwTableBox* pBox = pLine->GetTabBoxes()[nCurrCol]; - SAL_WARN_IF( !pBox, "sw", "Missing Table Box" ); + SAL_WARN_IF( !pBox, "sw.core", "Missing Table Box" ); SwTwips nNewWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth() + nWidth; long nRowSp = pBox->getRowSpan(); if( nRowSp < 0 ) { - SAL_WARN_IF( aIter == aRowSpanCells.end(), "sw", "Missing master box" ); + SAL_WARN_IF( aIter == aRowSpanCells.end(), + "sw.core", "Missing master box"); SAL_WARN_IF( aIter->nLeft != nWidth || aIter->nRight != nNewWidth, - "sw", "Wrong position/size of overlapped table box" ); + "sw.core", "Wrong position/size of overlapped table box"); --(aIter->nRowSpan); - SAL_WARN_IF( aIter->nRowSpan != -nRowSp, "sw", "Wrong row span value" ); + SAL_WARN_IF( aIter->nRowSpan != -nRowSp, "sw.core", + "Wrong row span value" ); if( nRowSp == -1 ) { std::list< RowSpanCheck >::iterator aEraseIter = aIter; @@ -2141,7 +2143,7 @@ void SwTable::CheckConsistency() const } else if( nRowSp != 1 ) { - SAL_WARN_IF( !nRowSp, "sw", "Zero row span?!" ); + SAL_WARN_IF( !nRowSp, "sw.core", "Zero row span?!" ); RowSpanCheck aEntry; aEntry.nLeft = nWidth; aEntry.nRight = nNewWidth; @@ -2152,14 +2154,20 @@ void SwTable::CheckConsistency() const } if( !nCurrLine ) nLineWidth = nWidth; - SAL_WARN_IF( nWidth != nLineWidth, "sw", "Different Line Widths" ); - SAL_WARN_IF( nWidth != nTabSize, "sw", "Line's Boxes are too small or too large" ); - SAL_WARN_IF( nWidth < 0 || nWidth > USHRT_MAX, "sw", "Width out of range" ); - SAL_WARN_IF( aIter != aRowSpanCells.end(), "sw", "Missing overlapped box" ); + SAL_WARN_IF( nWidth != nLineWidth, "sw.core", + "Different Line Widths: first: " << nLineWidth + << " current [" << nCurrLine << "]: " << nWidth); + SAL_WARN_IF( abs(nWidth - nTabSize) > 1 /* how tolerant? */, "sw.core", + "Line width differs from table width: " << nTabSize + << " current [" << nCurrLine << "]: " << nWidth); + SAL_WARN_IF( nWidth < 0 || nWidth > USHRT_MAX, "sw.core", + "Width out of range [" << nCurrLine << "]: " << nWidth); + SAL_WARN_IF( aIter != aRowSpanCells.end(), "sw.core", + "Missing overlapped box" ); aIter = aRowSpanCells.begin(); } bool bEmpty = aRowSpanCells.empty(); - SAL_WARN_IF( !bEmpty, "sw", "Open row span detected" ); + SAL_WARN_IF( !bEmpty, "sw.core", "Open row span detected" ); } #endif _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits