summaryrefslogtreecommitdiff
path: root/sw/source/core/table/swnewtable.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/table/swnewtable.cxx')
-rw-r--r--sw/source/core/table/swnewtable.cxx142
1 files changed, 100 insertions, 42 deletions
diff --git a/sw/source/core/table/swnewtable.cxx b/sw/source/core/table/swnewtable.cxx
index 85592b9a7458..a8b7e0e0d233 100644
--- a/sw/source/core/table/swnewtable.cxx
+++ b/sw/source/core/table/swnewtable.cxx
@@ -18,6 +18,7 @@
*/
#include <swtable.hxx>
+#include <swcrsr.hxx>
#include <tblsel.hxx>
#include <tblrwcl.hxx>
#include <ndtxt.hxx>
@@ -34,6 +35,7 @@
#include <IDocumentContentOperations.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
#include <cstdlib>
#include <vector>
#include <set>
@@ -326,15 +328,15 @@ static void lcl_ChangeRowSpan( const SwTable& rTable, const tools::Long nDiff,
and prepares the selected cells for merging
*/
-std::unique_ptr<SwBoxSelection> SwTable::CollectBoxSelection( const SwPaM& rPam ) const
+std::optional<SwBoxSelection> SwTable::CollectBoxSelection( const SwPaM& rPam ) const
{
OSL_ENSURE( m_bNewModel, "Don't call me for old tables" );
if( m_aLines.empty() )
- return nullptr;
- const SwNode* pStartNd = rPam.Start()->nNode.GetNode().FindTableBoxStartNode();
- const SwNode* pEndNd = rPam.End()->nNode.GetNode().FindTableBoxStartNode();
+ return std::nullopt;
+ const SwNode* pStartNd = rPam.Start()->GetNode().FindTableBoxStartNode();
+ const SwNode* pEndNd = rPam.End()->GetNode().FindTableBoxStartNode();
if( !pStartNd || !pEndNd || pStartNd == pEndNd )
- return nullptr;
+ return std::nullopt;
const size_t nLines = m_aLines.size();
size_t nTop = 0;
@@ -369,12 +371,12 @@ std::unique_ptr<SwBoxSelection> SwTable::CollectBoxSelection( const SwPaM& rPam
}
}
if( nFound < 2 )
- return nullptr;
+ return std::nullopt;
bool bOkay = true;
tools::Long nMid = ( nMin + nMax ) / 2;
- auto pRet(std::make_unique<SwBoxSelection>());
+ std::optional<SwBoxSelection> pRet(std::in_place);
std::vector< std::pair< SwTableBox*, tools::Long > > aNewWidthVector;
size_t nCheckBottom = nBottom;
tools::Long nLeftSpan = 0;
@@ -651,7 +653,7 @@ insertion behind (true) or before (false) the selected boxes
*/
bool SwTable::NewInsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes,
- sal_uInt16 nCnt, bool bBehind )
+ sal_uInt16 nCnt, bool bBehind, bool bInsertDummy )
{
if( m_aLines.empty() || !nCnt )
return false;
@@ -745,6 +747,24 @@ bool SwTable::NewInsertCol( SwDoc& rDoc, const SwSelBoxes& rBoxes,
for( sal_uInt16 j = 0; j < nCnt; ++j )
{
SwTableBox *pCurrBox = pLine->GetTabBoxes()[nInsPos+j];
+
+ // set tracked insertion by inserting a dummy redline
+ // drag & drop: no need to insert dummy character
+ if ( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
+ {
+ SwPosition aPos(*pCurrBox->GetSttNd());
+ SwCursor aCursor( aPos, nullptr );
+ if ( bInsertDummy )
+ {
+ SwNodeIndex aInsDummyPos(*pCurrBox->GetSttNd(), 1 );
+ SwPaM aPaM(aInsDummyPos);
+ rDoc.getIDocumentContentOperations().InsertString( aPaM,
+ OUStringChar(CH_TXT_TRACKED_DUMMY_CHAR) );
+ }
+ SvxPrintItem aHasTextChangesOnly(RES_PRINT, false);
+ rDoc.SetBoxAttr( aCursor, aHasTextChangesOnly );
+ }
+
if( bNewSpan )
{
pCurrBox->setRowSpan( nLastRowSpan );
@@ -816,7 +836,7 @@ bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
}
CHECK_TABLE( *this )
// We have to assert a "rectangular" box selection before we start to merge
- std::unique_ptr< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
+ std::optional< SwBoxSelection > pSel( CollectBoxSelection( rPam ) );
if (!pSel || pSel->isEmpty())
return false;
// Now we should have a rectangle of boxes,
@@ -884,11 +904,12 @@ bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
// we do not transfer this paragraph.
if( !IsEmptyBox( *pBox, aChkPam ) )
{
- SwNodeIndex& rInsPosNd = aInsPos.nNode;
+ SwNode& rInsPosNd = aInsPos.GetNode();
SwPaM aPam( aInsPos );
- aPam.GetPoint()->nNode.Assign( *pBox->GetSttNd()->EndOfSectionNode(), -1 );
- SwContentNode* pCNd = aPam.GetContentNode();
- aPam.GetPoint()->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
+ aPam.GetPoint()->Assign( *pBox->GetSttNd()->EndOfSectionNode(), SwNodeOffset(-1) );
+ SwContentNode* pCNd = aPam.GetPointContentNode();
+ if( pCNd )
+ aPam.GetPoint()->SetContent( pCNd->Len() );
SwNodeIndex aSttNdIdx( *pBox->GetSttNd(), 1 );
bool const bUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
if( pUndo )
@@ -900,7 +921,7 @@ bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
{
pDoc->GetIDocumentUndoRedo().DoUndo(bUndo);
}
- SwNodeRange aRg( aSttNdIdx, aPam.GetPoint()->nNode );
+ SwNodeRange aRg( aSttNdIdx.GetNode(), aPam.GetPoint()->GetNode() );
if( pUndo )
pUndo->MoveBoxContent( *pDoc, aRg, rInsPosNd );
else
@@ -948,14 +969,14 @@ bool SwTable::PrepareMerge( const SwPaM& rPam, SwSelBoxes& rBoxes,
if( nCurrLine )
{
SwPaM aPam( *pBox->GetSttNd(), 0 );
- aPam.GetPoint()->nNode++;
- SwTextNode* pNd = aPam.GetNode().GetTextNode();
+ aPam.GetPoint()->Adjust(SwNodeOffset(+1));
+ SwTextNode* pNd = aPam.GetPointNode().GetTextNode();
while( pNd )
{
pNd->SetCountedInList( false );
- aPam.GetPoint()->nNode++;
- pNd = aPam.GetNode().GetTextNode();
+ aPam.GetPoint()->Adjust(SwNodeOffset(+1));
+ pNd = aPam.GetPointNode().GetTextNode();
}
}
}
@@ -1062,7 +1083,7 @@ SwTableBox& SwTableBox::FindEndOfRowSpan( const SwTable& rTable, sal_uInt16 nMax
return *this;
if( nMaxStep > --nAbsSpan )
- nMaxStep = static_cast<sal_uInt16>(nAbsSpan);
+ nMaxStep = o3tl::narrowing<sal_uInt16>(nAbsSpan);
const SwTableLine* pMyUpper = GetUpper();
sal_uInt16 nLine = rTable.GetTabLines().GetPos( pMyUpper );
nMaxStep = nLine + nMaxStep;
@@ -1184,7 +1205,7 @@ void SwTable::InsertSpannedRow( SwDoc& rDoc, sal_uInt16 nRowIdx, sal_uInt16 nCnt
aFSz.SetHeight( nNewHeight );
pFrameFormat->SetFormatAttr( aFSz );
}
- InsertRow_( &rDoc, aBoxes, nCnt, true );
+ InsertRow_( &rDoc, aBoxes, nCnt, true, true );
const size_t nBoxCount = rLine.GetTabBoxes().size();
for( sal_uInt16 n = 0; n < nCnt; ++n )
{
@@ -1388,7 +1409,7 @@ static sal_uInt16 lcl_LineIndex( const SwTable& rTable, const SwSelBoxes& rBoxes
nSpan = 0;
else if( nSpan )
{
- sal_uInt16 nEndOfRowSpan = static_cast<sal_uInt16>(nPos + nRowSpan - 1);
+ sal_uInt16 nEndOfRowSpan = o3tl::narrowing<sal_uInt16>(nPos + nRowSpan - 1);
if( nEndOfRowSpan > nSpan || nSpan == USHRT_MAX )
nSpan = nEndOfRowSpan;
}
@@ -1489,7 +1510,7 @@ bool SwTable::NewSplitRow( SwDoc& rDoc, const SwSelBoxes& rBoxes, sal_uInt16 nCn
*/
bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
- sal_uInt16 nCnt, bool bBehind )
+ sal_uInt16 nCnt, bool bBehind, bool bInsertDummy )
{
bool bRet = false;
if( IsNewModel() )
@@ -1506,7 +1527,7 @@ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
SwTableLine *pLine = GetTabLines()[ nRowIdx ];
SwSelBoxes aLineBoxes;
lcl_FillSelBoxes( aLineBoxes, *pLine );
- InsertRow_( pDoc, aLineBoxes, nCnt, bBehind );
+ InsertRow_( pDoc, aLineBoxes, nCnt, bBehind, bInsertDummy );
const size_t nBoxCount = pLine->GetTabBoxes().size();
sal_uInt16 nOfs = bBehind ? 0 : 1;
for( sal_uInt16 n = 0; n < nCnt; ++n )
@@ -1531,8 +1552,7 @@ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
if( pCNd && pCNd->IsTextNode() && pCNd->GetTextNode()->GetNumRule() )
{
- SwPosition aPos( *pCNd->GetTextNode() );
- SwPaM aPam( aPos, aPos );
+ SwPaM aPam( *pCNd->GetTextNode(), *pCNd->GetTextNode() );
pDoc->DelNumRules( aPam );
}
}
@@ -1557,7 +1577,7 @@ bool SwTable::InsertRow( SwDoc* pDoc, const SwSelBoxes& rBoxes,
CHECK_TABLE( *this )
}
else
- bRet = InsertRow_( pDoc, rBoxes, nCnt, bBehind );
+ bRet = InsertRow_( pDoc, rBoxes, nCnt, bBehind, bInsertDummy );
return bRet;
}
@@ -1675,8 +1695,8 @@ void SwTable::CreateSelection( const SwPaM& rPam, SwSelBoxes& rBoxes,
OSL_ENSURE( m_bNewModel, "Don't call me for old tables" );
if( m_aLines.empty() )
return;
- const SwNode* pStartNd = rPam.GetPoint()->nNode.GetNode().FindTableBoxStartNode();
- const SwNode* pEndNd = rPam.GetMark()->nNode.GetNode().FindTableBoxStartNode();
+ const SwNode* pStartNd = rPam.GetPoint()->GetNode().FindTableBoxStartNode();
+ const SwNode* pEndNd = rPam.GetMark()->GetNode().FindTableBoxStartNode();
if( !pStartNd || !pEndNd )
return;
CreateSelection( pStartNd, pEndNd, rBoxes, eSearch, bChkProtected );
@@ -1719,7 +1739,11 @@ void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
rBoxes.insert( pBox );
if( nFound )
{
- nBottom = nRow;
+ //if box is hiding cells bottom needs to be moved
+ if (pBox->getRowSpan() > 1)
+ nBottom = std::max(nBottom, size_t(nRow + pBox->getRowSpan() - 1));
+ else
+ nBottom = std::max(nRow, nBottom);
lcl_CheckMinMax( nLowerMin, nLowerMax, *pLine, nCol, true );
++nFound;
break;
@@ -1727,6 +1751,9 @@ void SwTable::CreateSelection( const SwNode* pStartNd, const SwNode* pEndNd,
else
{
nTop = nRow;
+ //if box is hiding cells bottom needs to be moved
+ if (pBox->getRowSpan() > 1)
+ nBottom = nRow + pBox->getRowSpan() - 1;
lcl_CheckMinMax( nUpperMin, nUpperMax, *pLine, nCol, true );
++nFound;
// If start and end node are identical, we're nearly done...
@@ -2101,7 +2128,7 @@ void SwTable::CleanUpBottomRowSpan( sal_uInt16 nDelLines )
if( nRowSp > 1 )
{
lcl_ChangeRowSpan( *this, -static_cast<tools::Long>(nDelLines),
- static_cast<sal_uInt16>(nLastLine), false );
+ o3tl::narrowing<sal_uInt16>(nLastLine), false );
break;
}
}
@@ -2133,12 +2160,16 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
assert(!pSubTableBox->GetTabLines().empty());
// are relative (%) heights possible? apparently not
SwFormatFrameSize const outerSize(pSourceLine->GetFrameFormat()->GetFrameSize());
+ if (outerSize.GetHeightSizeType() != SwFrameSize::Variable)
+ { // tdf#145871 clear fixed size in first row
+ pSourceLine->ClaimFrameFormat();
+ pSourceLine->GetFrameFormat()->ResetFormatAttr(RES_FRM_SIZE);
+ }
tools::Long minHeights(0);
{
- SwFormatFrameSize const* pSize(nullptr);
SwFrameFormat const& rSubLineFormat(*pSubTableBox->GetTabLines()[0]->GetFrameFormat());
- if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
- reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+ SwFormatFrameSize const* pSize = rSubLineFormat.GetItemIfSet(RES_FRM_SIZE);
+ if (pSize)
{ // for first row, apply height from inner row to outer row.
// in case the existing outer row height was larger than the entire
// subtable, the last inserted row needs to be tweaked (below)
@@ -2157,9 +2188,8 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
pSourceLine->GetTabBoxes().size() - 1 + pSubLine->GetTabBoxes().size(),
nullptr);
SwFrameFormat const& rSubLineFormat(*pSubLine->GetFrameFormat());
- SwFormatFrameSize const* pSize(nullptr);
- if (rSubLineFormat.GetItemState(RES_FRM_SIZE, true,
- reinterpret_cast<SfxPoolItem const**>(&pSize)) == SfxItemState::SET)
+ SwFormatFrameSize const* pSize = rSubLineFormat.GetItemIfSet(RES_FRM_SIZE);
+ if (pSize)
{ // for rows 2..N, copy inner row height to outer row
pNewLine->ClaimFrameFormat();
pNewLine->GetFrameFormat()->SetFormatAttr(*pSize);
@@ -2179,6 +2209,7 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
{
lastSize.SetHeightSizeType(SwFrameSize::Minimum);
}
+ pNewLine->ClaimFrameFormat();
pNewLine->GetFrameFormat()->SetFormatAttr(lastSize);
}
SfxPoolItem const* pRowBrush(nullptr);
@@ -2200,9 +2231,9 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
pSourceBox, j+k, 1);
// insert dummy text node...
pDoc->GetNodes().MakeTextNode(
- SwNodeIndex(*pSourceBox->GetSttNd(), +1),
+ SwNodeIndex(*pSourceBox->GetSttNd(), +1).GetNode(),
pDoc->GetDfltTextFormatColl());
- SwNodeRange content(*pSourceBox->GetSttNd(), +2,
+ SwNodeRange content(*pSourceBox->GetSttNd(), SwNodeOffset(+2),
*pSourceBox->GetSttNd()->EndOfSectionNode());
SwTableBox *const pNewBox(pNewLine->GetTabBoxes()[j+k]);
SwNodeIndex insPos(*pNewBox->GetSttNd(), 1);
@@ -2211,14 +2242,13 @@ void SwTable::ConvertSubtableBox(sal_uInt16 const nRow, sal_uInt16 const nBox)
#if 0
pDoc->GetNodes().MoveNodes(content, pDoc->GetNodes(), insPos, false);
#else
- pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos, SwMoveFlags::NO_DELFRMS|SwMoveFlags::REDLINES);
+ pDoc->getIDocumentContentOperations().MoveNodeRange(content, insPos.GetNode(), SwMoveFlags::NO_DELFRMS|SwMoveFlags::REDLINES);
#endif
// delete the empty node that was bundled in the new box
pDoc->GetNodes().Delete(insPos);
if (pRowBrush)
{
- SfxPoolItem const* pCellBrush(nullptr);
- if (pNewBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true, &pCellBrush) != SfxItemState::SET)
+ if (pNewBox->GetFrameFormat()->GetItemState(RES_BACKGROUND, true) != SfxItemState::SET)
{ // set inner row background on inner cell
pNewBox->ClaimFrameFormat();
pNewBox->GetFrameFormat()->SetFormatAttr(*pRowBrush);
@@ -2298,6 +2328,7 @@ bool SwTable::CanConvertSubtables() const
return false;
}
haveSubtable = true;
+ bool haveNonFixedInnerLine(false);
for (SwTableLine const*const pInnerLine : pBox->GetTabLines())
{
// bitmap row background will look different
@@ -2314,6 +2345,17 @@ bool SwTable::CanConvertSubtables() const
return false;
}
}
+ if (SwFormatFrameSize const* pSize = rRowFormat.GetItemIfSet(RES_FRM_SIZE))
+ {
+ if (pSize->GetHeightSizeType() != SwFrameSize::Fixed)
+ {
+ haveNonFixedInnerLine = true;
+ }
+ }
+ else
+ {
+ haveNonFixedInnerLine = true; // default
+ }
for (SwTableBox const*const pInnerBox : pInnerLine->GetTabBoxes())
{
if (!pInnerBox->GetTabLines().empty())
@@ -2322,6 +2364,17 @@ bool SwTable::CanConvertSubtables() const
}
}
}
+ if (haveNonFixedInnerLine)
+ {
+ if (SwFormatFrameSize const* pSize = pLine->GetFrameFormat()->GetItemIfSet(RES_FRM_SIZE))
+ {
+ if (pSize->GetHeightSizeType() != SwFrameSize::Variable)
+ {
+ // not possible to distribute fixed outer row height on rows without layout
+ return false;
+ }
+ }
+ }
}
}
}
@@ -2337,7 +2390,9 @@ bool SwTable::CanConvertSubtables() const
{
return false; // no formulas in fields yet
}
- if (pDoc->GetAttrPool().GetItemCount2(RES_BOXATR_FORMULA) != 0)
+ ItemSurrogates aSurrogates;
+ pDoc->GetAttrPool().GetItemSurrogates(aSurrogates, RES_BOXATR_FORMULA);
+ if (!aSurrogates.empty())
{
return false; // no table box formulas yet
}
@@ -2359,6 +2414,8 @@ bool SwTable::CanConvertSubtables() const
void SwTable::ConvertSubtables()
{
+ FndBox_ all(nullptr, nullptr);
+ all.DelFrames(*this); // tdf#151375 avoid UAF by frames on deleted cells
for (size_t i = 0; i < GetTabLines().size(); ++i)
{
SwTableLine *const pLine(GetTabLines()[i]);
@@ -2374,6 +2431,7 @@ void SwTable::ConvertSubtables()
}
GCLines();
m_bNewModel = true;
+ all.MakeFrames(*this);
#if 0
// note: outline nodes (and ordinary lists) are sorted by MoveNodes() itself
// (this could change order inside table of contents, but that's a