LibreOffice Module sw (master)  1
ndtbl.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <memory>
21 #include <fesh.hxx>
22 #include <hintids.hxx>
23 #include <editeng/lrspitem.hxx>
24 #include <editeng/protitem.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <svl/stritem.hxx>
27 #include <editeng/shaditem.hxx>
28 #include <fmtfsize.hxx>
29 #include <fmtornt.hxx>
30 #include <fmtfordr.hxx>
31 #include <fmtpdsc.hxx>
32 #include <fmtanchr.hxx>
33 #include <fmtlsplt.hxx>
34 #include <frmatr.hxx>
35 #include <cellfrm.hxx>
36 #include <pagefrm.hxx>
37 #include <tabcol.hxx>
38 #include <doc.hxx>
39 #include <IDocumentUndoRedo.hxx>
40 #include <UndoManager.hxx>
47 #include <IDocumentState.hxx>
48 #include <cntfrm.hxx>
49 #include <pam.hxx>
50 #include <swcrsr.hxx>
51 #include <swtable.hxx>
52 #include <swundo.hxx>
53 #include <tblsel.hxx>
54 #include <poolfmt.hxx>
55 #include <tabfrm.hxx>
56 #include <UndoCore.hxx>
57 #include <UndoRedline.hxx>
58 #include <UndoDelete.hxx>
59 #include <UndoNumbering.hxx>
60 #include <UndoTable.hxx>
61 #include <hints.hxx>
62 #include <tblafmt.hxx>
63 #include <frminf.hxx>
64 #include <cellatr.hxx>
65 #include <swtblfmt.hxx>
66 #include <swddetbl.hxx>
67 #include <mvsave.hxx>
68 #include <docary.hxx>
69 #include <redline.hxx>
70 #include <rolbck.hxx>
71 #include <tblrwcl.hxx>
72 #include <editsh.hxx>
73 #include <txtfrm.hxx>
74 #include <section.hxx>
75 #include <frmtool.hxx>
76 #include <node2lay.hxx>
77 #include <strings.hrc>
78 #include <docsh.hxx>
79 #include <unochart.hxx>
80 #include <node.hxx>
81 #include <ndtxt.hxx>
82 #include <cstdlib>
83 #include <map>
84 #include <algorithm>
85 #include <rootfrm.hxx>
86 #include <fldupde.hxx>
87 #include <calbck.hxx>
88 #include <fntcache.hxx>
89 #include <frameformats.hxx>
90 #include <o3tl/numeric.hxx>
91 #include <tools/datetimeutils.hxx>
92 #include <sal/log.hxx>
93 
94 #ifdef DBG_UTIL
95 #define CHECK_TABLE(t) (t).CheckConsistency();
96 #else
97 #define CHECK_TABLE(t)
98 #endif
99 
100 using ::editeng::SvxBorderLine;
101 using namespace ::com::sun::star;
102 
103 const sal_Unicode T2T_PARA = 0x0a;
104 
105 static void lcl_SetDfltBoxAttr( SwFrameFormat& rFormat, sal_uInt8 nId )
106 {
107  bool bTop = false, bBottom = false, bLeft = false, bRight = false;
108  switch ( nId )
109  {
110  case 0: bTop = bBottom = bLeft = true; break;
111  case 1: bTop = bBottom = bLeft = bRight = true; break;
112  case 2: bBottom = bLeft = true; break;
113  case 3: bBottom = bLeft = bRight = true; break;
114  }
115 
116  const bool bHTML = rFormat.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE);
117  Color aCol( bHTML ? COL_GRAY : COL_BLACK );
118  SvxBorderLine aLine( &aCol, DEF_LINE_WIDTH_0 );
119  if ( bHTML )
120  {
121  aLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
122  aLine.SetWidth( DEF_LINE_WIDTH_0 );
123  }
124  SvxBoxItem aBox(RES_BOX);
125  aBox.SetAllDistances(55);
126  if ( bTop )
127  aBox.SetLine( &aLine, SvxBoxItemLine::TOP );
128  if ( bBottom )
129  aBox.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
130  if ( bLeft )
131  aBox.SetLine( &aLine, SvxBoxItemLine::LEFT );
132  if ( bRight )
133  aBox.SetLine( &aLine, SvxBoxItemLine::RIGHT );
134  rFormat.SetFormatAttr( aBox );
135 }
136 
137 typedef std::map<SwFrameFormat *, SwTableBoxFormat *> DfltBoxAttrMap_t;
138 typedef std::vector<DfltBoxAttrMap_t *> DfltBoxAttrList_t;
139 
140 static void
142  sal_uInt8 const nId, SwTableAutoFormat const*const pAutoFormat = nullptr)
143 {
144  DfltBoxAttrMap_t * pMap = rBoxFormatArr[ nId ];
145  if (!pMap)
146  {
147  pMap = new DfltBoxAttrMap_t;
148  rBoxFormatArr[ nId ] = pMap;
149  }
150 
151  SwTableBoxFormat* pNewTableBoxFormat = nullptr;
152  SwFrameFormat* pBoxFrameFormat = rBox.GetFrameFormat();
153  DfltBoxAttrMap_t::iterator const iter(pMap->find(pBoxFrameFormat));
154  if (pMap->end() != iter)
155  {
156  pNewTableBoxFormat = iter->second;
157  }
158  else
159  {
160  SwDoc* pDoc = pBoxFrameFormat->GetDoc();
161  // format does not exist, so create it
162  pNewTableBoxFormat = pDoc->MakeTableBoxFormat();
163  pNewTableBoxFormat->SetFormatAttr( pBoxFrameFormat->GetAttrSet().Get( RES_FRM_SIZE ) );
164 
165  if( pAutoFormat )
166  pAutoFormat->UpdateToSet( nId, false, false,
167  const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pNewTableBoxFormat->GetAttrSet())),
169  pDoc->GetNumberFormatter() );
170  else
171  ::lcl_SetDfltBoxAttr( *pNewTableBoxFormat, nId );
172 
173  (*pMap)[pBoxFrameFormat] = pNewTableBoxFormat;
174  }
175  rBox.ChgFrameFormat( pNewTableBoxFormat );
176 }
177 
178 static SwTableBoxFormat *lcl_CreateDfltBoxFormat( SwDoc &rDoc, std::vector<SwTableBoxFormat*> &rBoxFormatArr,
179  sal_uInt16 nCols, sal_uInt8 nId )
180 {
181  if ( !rBoxFormatArr[nId] )
182  {
183  SwTableBoxFormat* pBoxFormat = rDoc.MakeTableBoxFormat();
184  if( USHRT_MAX != nCols )
186  USHRT_MAX / nCols, 0 ));
187  ::lcl_SetDfltBoxAttr( *pBoxFormat, nId );
188  rBoxFormatArr[ nId ] = pBoxFormat;
189  }
190  return rBoxFormatArr[nId];
191 }
192 
193 static SwTableBoxFormat *lcl_CreateAFormatBoxFormat( SwDoc &rDoc, std::vector<SwTableBoxFormat*> &rBoxFormatArr,
194  const SwTableAutoFormat& rAutoFormat,
195  const sal_uInt16 nRows, const sal_uInt16 nCols, sal_uInt8 nId )
196 {
197  if( !rBoxFormatArr[nId] )
198  {
199  SwTableBoxFormat* pBoxFormat = rDoc.MakeTableBoxFormat();
200  rAutoFormat.UpdateToSet( nId, nRows==1, nCols==1,
201  const_cast<SfxItemSet&>(static_cast<SfxItemSet const &>(pBoxFormat->GetAttrSet())),
203  rDoc.GetNumberFormatter( ) );
204  if( USHRT_MAX != nCols )
206  USHRT_MAX / nCols, 0 ));
207  rBoxFormatArr[ nId ] = pBoxFormat;
208  }
209  return rBoxFormatArr[nId];
210 }
211 
213 {
214  SwTableNode* pTableNd = nullptr;
215  sal_uLong nIndex = rIdx.GetIndex();
216  do {
217  SwNode* pNd = GetNodes()[ nIndex ]->StartOfSectionNode();
218  pTableNd = pNd->GetTableNode();
219  if( nullptr != pTableNd )
220  break;
221 
222  nIndex = pNd->GetIndex();
223  } while ( nIndex );
224  return pTableNd;
225 }
226 
231  SwTableLine* pLine,
232  SwTableBoxFormat* pBoxFormat,
233  SwTextFormatColl* pTextColl,
234  const SfxItemSet* pAutoAttr,
235  sal_uInt16 nInsPos,
236  sal_uInt16 nCnt )
237 {
238  if( !nCnt )
239  return false;
240  OSL_ENSURE( pLine, "No valid Line" );
241 
242  // Move Index after the Line's last Box
243  sal_uLong nIdxPos = 0;
244  SwTableBox *pPrvBox = nullptr, *pNxtBox = nullptr;
245  if( !pLine->GetTabBoxes().empty() )
246  {
247  if( nInsPos < pLine->GetTabBoxes().size() )
248  {
249  pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable(),
250  pLine->GetTabBoxes()[ nInsPos ] );
251  if( nullptr == pPrvBox )
252  pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable() );
253  }
254  else
255  {
256  pNxtBox = pLine->FindNextBox( pTableNd->GetTable(),
257  pLine->GetTabBoxes().back() );
258  if( nullptr == pNxtBox )
259  pNxtBox = pLine->FindNextBox( pTableNd->GetTable() );
260  }
261  }
262  else
263  {
264  pNxtBox = pLine->FindNextBox( pTableNd->GetTable() );
265  if( nullptr == pNxtBox )
266  pPrvBox = pLine->FindPreviousBox( pTableNd->GetTable() );
267  }
268 
269  if( !pPrvBox && !pNxtBox )
270  {
271  bool bSetIdxPos = true;
272  if( !pTableNd->GetTable().GetTabLines().empty() && !nInsPos )
273  {
274  const SwTableLine* pTableLn = pLine;
275  while( pTableLn->GetUpper() )
276  pTableLn = pTableLn->GetUpper()->GetUpper();
277 
278  if( pTableNd->GetTable().GetTabLines()[ 0 ] == pTableLn )
279  {
280  // Before the Table's first Box
281  while( !( pNxtBox = pLine->GetTabBoxes()[0])->GetTabLines().empty() )
282  pLine = pNxtBox->GetTabLines()[0];
283  nIdxPos = pNxtBox->GetSttIdx();
284  bSetIdxPos = false;
285  }
286  }
287  if( bSetIdxPos )
288  // Tables without content or at the end; move before the End
289  nIdxPos = pTableNd->EndOfSectionIndex();
290  }
291  else if( pNxtBox ) // There is a successor
292  nIdxPos = pNxtBox->GetSttIdx();
293  else // There is a predecessor
294  nIdxPos = pPrvBox->GetSttNd()->EndOfSectionIndex() + 1;
295 
296  SwNodeIndex aEndIdx( *this, nIdxPos );
297  for( sal_uInt16 n = 0; n < nCnt; ++n )
298  {
299  SwStartNode* pSttNd = new SwStartNode( aEndIdx, SwNodeType::Start,
301  pSttNd->m_pStartOfSection = pTableNd;
302  new SwEndNode( aEndIdx, *pSttNd );
303 
304  pPrvBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
305 
306  SwTableBoxes & rTabBoxes = pLine->GetTabBoxes();
307  sal_uInt16 nRealInsPos = nInsPos + n;
308  if (nRealInsPos > rTabBoxes.size())
309  nRealInsPos = rTabBoxes.size();
310 
311  rTabBoxes.insert( rTabBoxes.begin() + nRealInsPos, pPrvBox );
312 
313  if( ! pTextColl->IsAssignedToListLevelOfOutlineStyle()
314 //FEATURE::CONDCOLL
315  && RES_CONDTXTFMTCOLL != pTextColl->Which()
316 //FEATURE::CONDCOLL
317  )
318  new SwTextNode( SwNodeIndex( *pSttNd->EndOfSectionNode() ),
319  pTextColl, pAutoAttr );
320  else
321  {
322  // Handle Outline numbering correctly!
323  SwTextNode* pTNd = new SwTextNode(
324  SwNodeIndex( *pSttNd->EndOfSectionNode() ),
326  pAutoAttr );
327  pTNd->ChgFormatColl( pTextColl );
328  }
329  }
330  return true;
331 }
332 
336 const SwTable* SwDoc::InsertTable( const SwInsertTableOptions& rInsTableOpts,
337  const SwPosition& rPos, sal_uInt16 nRows,
338  sal_uInt16 nCols, sal_Int16 eAdjust,
339  const SwTableAutoFormat* pTAFormat,
340  const std::vector<sal_uInt16> *pColArr,
341  bool bCalledFromShell,
342  bool bNewModel )
343 {
344  assert(nRows && "Table without line?");
345  assert(nCols && "Table without rows?");
346 
347  {
348  // Do not copy into Footnotes!
349  if( rPos.nNode < GetNodes().GetEndOfInserts().GetIndex() &&
350  rPos.nNode >= GetNodes().GetEndOfInserts().StartOfSectionIndex() )
351  return nullptr;
352 
353  // If the ColumnArray has a wrong count, ignore it!
354  if( pColArr &&
355  static_cast<size_t>(nCols + ( text::HoriOrientation::NONE == eAdjust ? 2 : 1 )) != pColArr->size() )
356  pColArr = nullptr;
357  }
358 
359  OUString aTableName = GetUniqueTableName();
360 
361  if( GetIDocumentUndoRedo().DoesUndo() )
362  {
364  std::make_unique<SwUndoInsTable>( rPos, nCols, nRows, static_cast<sal_uInt16>(eAdjust),
365  rInsTableOpts, pTAFormat, pColArr,
366  aTableName));
367  }
368 
369  // Start with inserting the Nodes and get the AutoFormat for the Table
371  *pHeadColl = pBodyColl;
372 
373  bool bDfltBorders( rInsTableOpts.mnInsMode & SwInsertTableFlags::DefaultBorder );
374 
375  if( (rInsTableOpts.mnInsMode & SwInsertTableFlags::Headline) && (1 != nRows || !bDfltBorders) )
377 
378  const sal_uInt16 nRowsToRepeat =
380  rInsTableOpts.mnRowsToRepeat :
381  0;
382 
383  /* Save content node to extract FRAMEDIR from. */
384  const SwContentNode * pContentNd = rPos.nNode.GetNode().GetContentNode();
385 
386  /* If we are called from a shell pass the attrset from
387  pContentNd (aka the node the table is inserted at) thus causing
388  SwNodes::InsertTable to propagate an adjust item if
389  necessary. */
390  SwTableNode *pTableNd = SwNodes::InsertTable(
391  rPos.nNode,
392  nCols,
393  pBodyColl,
394  nRows,
395  nRowsToRepeat,
396  pHeadColl,
397  bCalledFromShell ? &pContentNd->GetSwAttrSet() : nullptr );
398 
399  // Create the Box/Line/Table construct
400  SwTableLineFormat* pLineFormat = MakeTableLineFormat();
401  SwTableFormat* pTableFormat = MakeTableFrameFormat( aTableName, GetDfltFrameFormat() );
402 
403  /* If the node to insert the table at is a context node and has a
404  non-default FRAMEDIR propagate it to the table. */
405  if (pContentNd)
406  {
407  const SwAttrSet & aNdSet = pContentNd->GetSwAttrSet();
408  const SfxPoolItem *pItem = nullptr;
409 
410  if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
411  && pItem != nullptr)
412  {
413  pTableFormat->SetFormatAttr( *pItem );
414  }
415  }
416 
417  // Set Orientation at the Table's Format
418  pTableFormat->SetFormatAttr( SwFormatHoriOrient( 0, eAdjust ) );
419  // All lines use the left-to-right Fill-Order!
420  pLineFormat->SetFormatAttr( SwFormatFillOrder( ATT_LEFT_TO_RIGHT ));
421 
422  // Set USHRT_MAX as the Table's default SSize
423  SwTwips nWidth = USHRT_MAX;
424  if( pColArr )
425  {
426  sal_uInt16 nSttPos = pColArr->front();
427  sal_uInt16 nLastPos = pColArr->back();
428  if( text::HoriOrientation::NONE == eAdjust )
429  {
430  sal_uInt16 nFrameWidth = nLastPos;
431  nLastPos = (*pColArr)[ pColArr->size()-2 ];
432  pTableFormat->SetFormatAttr( SvxLRSpaceItem( nSttPos, nFrameWidth - nLastPos, 0, 0, RES_LR_SPACE ) );
433  }
434  nWidth = nLastPos - nSttPos;
435  }
436  else
437  {
438  nWidth /= nCols;
439  nWidth *= nCols; // to avoid rounding problems
440  }
441  pTableFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nWidth ));
442  if( !(rInsTableOpts.mnInsMode & SwInsertTableFlags::SplitLayout) )
443  pTableFormat->SetFormatAttr( SwFormatLayoutSplit( false ));
444 
445  // Move the hard PageDesc/PageBreak Attributes if needed
446  SwContentNode* pNextNd = GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]
447  ->GetContentNode();
448  if( pNextNd && pNextNd->HasSwAttrSet() )
449  {
450  const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet();
451  const SfxPoolItem *pItem;
452  if( SfxItemState::SET == pNdSet->GetItemState( RES_PAGEDESC, false,
453  &pItem ) )
454  {
455  pTableFormat->SetFormatAttr( *pItem );
456  pNextNd->ResetAttr( RES_PAGEDESC );
457  pNdSet = pNextNd->GetpSwAttrSet();
458  }
459  if( pNdSet && SfxItemState::SET == pNdSet->GetItemState( RES_BREAK, false,
460  &pItem ) )
461  {
462  pTableFormat->SetFormatAttr( *pItem );
463  pNextNd->ResetAttr( RES_BREAK );
464  }
465  }
466 
467  SwTable& rNdTable = pTableNd->GetTable();
468  rNdTable.RegisterToFormat( *pTableFormat );
469 
470  rNdTable.SetRowsToRepeat( nRowsToRepeat );
471  rNdTable.SetTableModel( bNewModel );
472 
473  std::vector<SwTableBoxFormat*> aBoxFormatArr;
474  SwTableBoxFormat* pBoxFormat = nullptr;
475  if( !bDfltBorders && !pTAFormat )
476  {
477  pBoxFormat = MakeTableBoxFormat();
478  pBoxFormat->SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, USHRT_MAX / nCols, 0 ));
479  }
480  else
481  {
482  const sal_uInt16 nBoxArrLen = pTAFormat ? 16 : 4;
483  aBoxFormatArr.resize( nBoxArrLen, nullptr );
484  }
486 
487  SwNodeIndex aNdIdx( *pTableNd, 1 ); // Set to StartNode of first Box
488  SwTableLines& rLines = rNdTable.GetTabLines();
489  for( sal_uInt16 n = 0; n < nRows; ++n )
490  {
491  SwTableLine* pLine = new SwTableLine( pLineFormat, nCols, nullptr );
492  rLines.insert( rLines.begin() + n, pLine );
493  SwTableBoxes& rBoxes = pLine->GetTabBoxes();
494  for( sal_uInt16 i = 0; i < nCols; ++i )
495  {
496  SwTableBoxFormat *pBoxF;
497  if( pTAFormat )
498  {
499  sal_uInt8 nId = SwTableAutoFormat::CountPos(i, nCols, n, nRows);
500  pBoxF = ::lcl_CreateAFormatBoxFormat( *this, aBoxFormatArr, *pTAFormat,
501  nRows, nCols, nId );
502 
503  // Set the Paragraph/Character Attributes if needed
504  if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
505  {
506  aCharSet.ClearItem();
507  pTAFormat->UpdateToSet( nId, nRows==1, nCols==1, aCharSet,
509  if( aCharSet.Count() )
510  GetNodes()[ aNdIdx.GetIndex()+1 ]->GetContentNode()->
511  SetAttr( aCharSet );
512  }
513  }
514  else if( bDfltBorders )
515  {
516  sal_uInt8 nBoxId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
517  pBoxF = ::lcl_CreateDfltBoxFormat( *this, aBoxFormatArr, nCols, nBoxId);
518  }
519  else
520  pBoxF = pBoxFormat;
521 
522  // For AutoFormat on input: the columns are set when inserting the Table
523  // The Array contains the columns positions and not their widths!
524  if( pColArr )
525  {
526  nWidth = (*pColArr)[ i + 1 ] - (*pColArr)[ i ];
527  if( pBoxF->GetFrameSize().GetWidth() != nWidth )
528  {
529  if( pBoxF->HasWriterListeners() ) // Create new Format
530  {
531  SwTableBoxFormat *pNewFormat = MakeTableBoxFormat();
532  *pNewFormat = *pBoxF;
533  pBoxF = pNewFormat;
534  }
536  }
537  }
538 
539  SwTableBox *pBox = new SwTableBox( pBoxF, aNdIdx, pLine);
540  rBoxes.insert( rBoxes.begin() + i, pBox );
541  aNdIdx += 3; // StartNode, TextNode, EndNode == 3 Nodes
542  }
543  }
544  // Insert Frames
545  GetNodes().GoNext( &aNdIdx ); // Go to the next ContentNode
546  pTableNd->MakeOwnFrames( &aNdIdx );
547 
548  // To-Do - add 'SwExtraRedlineTable' also ?
549  if( getIDocumentRedlineAccess().IsRedlineOn() || (!getIDocumentRedlineAccess().IsIgnoreRedline() && !getIDocumentRedlineAccess().GetRedlineTable().empty() ))
550  {
551  SwPaM aPam( *pTableNd->EndOfSectionNode(), *pTableNd, 1 );
553  getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert, aPam ), true);
554  else
556  }
557 
559  CHECK_TABLE(rNdTable);
560  return &rNdTable;
561 }
562 
564  sal_uInt16 nBoxes,
565  SwTextFormatColl* pContentTextColl,
566  sal_uInt16 nLines,
567  sal_uInt16 nRepeat,
568  SwTextFormatColl* pHeadlineTextColl,
569  const SwAttrSet * pAttrSet)
570 {
571  if( !nBoxes )
572  return nullptr;
573 
574  // If Lines is given, create the Matrix from Lines and Boxes
575  if( !pHeadlineTextColl || !nLines )
576  pHeadlineTextColl = pContentTextColl;
577 
578  SwTableNode * pTableNd = new SwTableNode( rNdIdx );
579  SwEndNode* pEndNd = new SwEndNode( rNdIdx, *pTableNd );
580 
581  if( !nLines ) // For the for loop
582  ++nLines;
583 
584  SwNodeIndex aIdx( *pEndNd );
585  SwTextFormatColl* pTextColl = pHeadlineTextColl;
586  for( sal_uInt16 nL = 0; nL < nLines; ++nL )
587  {
588  for( sal_uInt16 nB = 0; nB < nBoxes; ++nB )
589  {
590  SwStartNode* pSttNd = new SwStartNode( aIdx, SwNodeType::Start,
592  pSttNd->m_pStartOfSection = pTableNd;
593 
594  SwTextNode * pTmpNd = new SwTextNode( aIdx, pTextColl );
595 
596  // #i60422# Propagate some more attributes.
597  const SfxPoolItem* pItem = nullptr;
598  if ( nullptr != pAttrSet )
599  {
600  static const sal_uInt16 aPropagateItems[] = {
605 
606  const sal_uInt16* pIdx = aPropagateItems;
607  while ( *pIdx != 0 )
608  {
609  if ( SfxItemState::SET != pTmpNd->GetSwAttrSet().GetItemState( *pIdx ) &&
610  SfxItemState::SET == pAttrSet->GetItemState( *pIdx, true, &pItem ) )
611  static_cast<SwContentNode *>(pTmpNd)->SetAttr(*pItem);
612  ++pIdx;
613  }
614  }
615 
616  new SwEndNode( aIdx, *pSttNd );
617  }
618  if ( nL + 1 >= nRepeat )
619  pTextColl = pContentTextColl;
620  }
621  return pTableNd;
622 }
623 
627 const SwTable* SwDoc::TextToTable( const SwInsertTableOptions& rInsTableOpts,
628  const SwPaM& rRange, sal_Unicode cCh,
629  sal_Int16 eAdjust,
630  const SwTableAutoFormat* pTAFormat )
631 {
632  // See if the selection contains a Table
633  const SwPosition *pStt = rRange.Start(), *pEnd = rRange.End();
634  {
635  sal_uLong nCnt = pStt->nNode.GetIndex();
636  for( ; nCnt <= pEnd->nNode.GetIndex(); ++nCnt )
637  if( !GetNodes()[ nCnt ]->IsTextNode() )
638  return nullptr;
639  }
640 
641  // Save first node in the selection if it is a context node
642  SwContentNode * pSttContentNd = pStt->nNode.GetNode().GetContentNode();
643 
644  SwPaM aOriginal( *pStt, *pEnd );
645  pStt = aOriginal.GetMark();
646  pEnd = aOriginal.GetPoint();
647 
648  SwUndoTextToTable* pUndo = nullptr;
649  if( GetIDocumentUndoRedo().DoesUndo() )
650  {
652  pUndo = new SwUndoTextToTable( aOriginal, rInsTableOpts, cCh,
653  static_cast<sal_uInt16>(eAdjust), pTAFormat );
654  GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
655 
656  // Do not add splitting the TextNode to the Undo history
657  GetIDocumentUndoRedo().DoUndo( false );
658  }
659 
660  ::PaMCorrAbs( aOriginal, *pEnd );
661 
662  // Make sure that the range is on Node Edges
663  SwNodeRange aRg( pStt->nNode, pEnd->nNode );
664  if( pStt->nContent.GetIndex() )
665  getIDocumentContentOperations().SplitNode( *pStt, false );
666 
667  bool bEndContent = 0 != pEnd->nContent.GetIndex();
668 
669  // Do not split at the End of a Line (except at the End of the Doc)
670  if( bEndContent )
671  {
672  if( pEnd->nNode.GetNode().GetContentNode()->Len() != pEnd->nContent.GetIndex()
673  || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
674  {
675  getIDocumentContentOperations().SplitNode( *pEnd, false );
676  --const_cast<SwNodeIndex&>(pEnd->nNode);
677  const_cast<SwIndex&>(pEnd->nContent).Assign(
678  pEnd->nNode.GetNode().GetContentNode(), 0 );
679  // A Node and at the End?
680  if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
681  --aRg.aStart;
682  }
683  else
684  ++aRg.aEnd;
685  }
686 
687  if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
688  {
689  OSL_FAIL( "empty range" );
690  ++aRg.aEnd;
691  }
692 
693  // We always use Upper to insert the Table
694  SwNode2LayoutSaveUpperFrames aNode2Layout( aRg.aStart.GetNode() );
695 
696  GetIDocumentUndoRedo().DoUndo( nullptr != pUndo );
697 
698  // Create the Box/Line/Table construct
699  SwTableBoxFormat* pBoxFormat = MakeTableBoxFormat();
700  SwTableLineFormat* pLineFormat = MakeTableLineFormat();
702 
703  // All Lines have a left-to-right Fill Order
705  // The Table's SSize is USHRT_MAX
707  if( !(rInsTableOpts.mnInsMode & SwInsertTableFlags::SplitLayout) )
708  pTableFormat->SetFormatAttr( SwFormatLayoutSplit( false ));
709 
710  /* If the first node in the selection is a context node and if it
711  has an item FRAMEDIR set (no default) propagate the item to the
712  replacing table. */
713  if (pSttContentNd)
714  {
715  const SwAttrSet & aNdSet = pSttContentNd->GetSwAttrSet();
716  const SfxPoolItem *pItem = nullptr;
717 
718  if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
719  && pItem != nullptr)
720  {
721  pTableFormat->SetFormatAttr( *pItem );
722  }
723  }
724 
725  //Resolves: tdf#87977, tdf#78599, disable broadcasting modifications
726  //until after RegisterToFormat is completed
727  bool bEnableSetModified = getIDocumentState().IsEnableSetModified();
729 
730  SwTableNode* pTableNd = GetNodes().TextToTable(
731  aRg, cCh, pTableFormat, pLineFormat, pBoxFormat,
732  getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ), pUndo );
733 
734  SwTable& rNdTable = pTableNd->GetTable();
735 
736  const sal_uInt16 nRowsToRepeat =
738  rInsTableOpts.mnRowsToRepeat :
739  0;
740  rNdTable.SetRowsToRepeat(nRowsToRepeat);
741 
742  bool bUseBoxFormat = false;
743  if( !pBoxFormat->HasWriterListeners() )
744  {
745  // The Box's Formats already have the right size, we must only set
746  // the right Border/AutoFormat.
747  bUseBoxFormat = true;
748  pTableFormat->SetFormatAttr( pBoxFormat->GetFrameSize() );
749  delete pBoxFormat;
750  eAdjust = text::HoriOrientation::NONE;
751  }
752 
753  // Set Orientation in the Table's Format
754  pTableFormat->SetFormatAttr( SwFormatHoriOrient( 0, eAdjust ) );
755  rNdTable.RegisterToFormat(*pTableFormat);
756 
757  if( pTAFormat || ( rInsTableOpts.mnInsMode & SwInsertTableFlags::DefaultBorder) )
758  {
759  sal_uInt8 nBoxArrLen = pTAFormat ? 16 : 4;
760  std::unique_ptr< DfltBoxAttrList_t > aBoxFormatArr1;
761  std::unique_ptr< std::vector<SwTableBoxFormat*> > aBoxFormatArr2;
762  if( bUseBoxFormat )
763  {
764  aBoxFormatArr1.reset(new DfltBoxAttrList_t( nBoxArrLen, nullptr ));
765  }
766  else
767  {
768  aBoxFormatArr2.reset(new std::vector<SwTableBoxFormat*>( nBoxArrLen, nullptr ));
769  }
770 
772 
773  SwHistory* pHistory = pUndo ? &pUndo->GetHistory() : nullptr;
774 
775  SwTableBoxFormat *pBoxF = nullptr;
776  SwTableLines& rLines = rNdTable.GetTabLines();
777  const SwTableLines::size_type nRows = rLines.size();
778  for( SwTableLines::size_type n = 0; n < nRows; ++n )
779  {
780  SwTableBoxes& rBoxes = rLines[ n ]->GetTabBoxes();
781  const SwTableBoxes::size_type nCols = rBoxes.size();
782  for( SwTableBoxes::size_type i = 0; i < nCols; ++i )
783  {
784  SwTableBox* pBox = rBoxes[ i ];
785  bool bChgSz = false;
786 
787  if( pTAFormat )
788  {
789  sal_uInt8 nId = static_cast<sal_uInt8>(!n ? 0 : (( n+1 == nRows )
790  ? 12 : (4 * (1 + ((n-1) & 1 )))));
791  nId = nId + static_cast<sal_uInt8>(!i ? 0 :
792  ( i+1 == nCols ? 3 : (1 + ((i-1) & 1))));
793  if( bUseBoxFormat )
794  ::lcl_SetDfltBoxAttr( *pBox, *aBoxFormatArr1, nId, pTAFormat );
795  else
796  {
797  bChgSz = nullptr == (*aBoxFormatArr2)[ nId ];
798  pBoxF = ::lcl_CreateAFormatBoxFormat( *this, *aBoxFormatArr2,
799  *pTAFormat, USHRT_MAX, USHRT_MAX, nId );
800  }
801 
802  // Set Paragraph/Character Attributes if needed
803  if( pTAFormat->IsFont() || pTAFormat->IsJustify() )
804  {
805  aCharSet.ClearItem();
806  pTAFormat->UpdateToSet( nId, nRows==1, nCols==1, aCharSet,
808  if( aCharSet.Count() )
809  {
810  sal_uLong nSttNd = pBox->GetSttIdx()+1;
811  sal_uLong nEndNd = pBox->GetSttNd()->EndOfSectionIndex();
812  for( ; nSttNd < nEndNd; ++nSttNd )
813  {
814  SwContentNode* pNd = GetNodes()[ nSttNd ]->GetContentNode();
815  if( pNd )
816  {
817  if( pHistory )
818  {
819  SwRegHistory aReg( pNd, *pNd, pHistory );
820  pNd->SetAttr( aCharSet );
821  }
822  else
823  pNd->SetAttr( aCharSet );
824  }
825  }
826  }
827  }
828  }
829  else
830  {
831  sal_uInt8 nId = (i < nCols - 1 ? 0 : 1) + (n ? 2 : 0 );
832  if( bUseBoxFormat )
833  ::lcl_SetDfltBoxAttr( *pBox, *aBoxFormatArr1, nId );
834  else
835  {
836  bChgSz = nullptr == (*aBoxFormatArr2)[ nId ];
837  pBoxF = ::lcl_CreateDfltBoxFormat( *this, *aBoxFormatArr2,
838  USHRT_MAX, nId );
839  }
840  }
841 
842  if( !bUseBoxFormat )
843  {
844  if( bChgSz )
845  pBoxF->SetFormatAttr( pBox->GetFrameFormat()->GetFrameSize() );
846  pBox->ChgFrameFormat( pBoxF );
847  }
848  }
849  }
850 
851  if( bUseBoxFormat )
852  {
853  for( sal_uInt8 i = 0; i < nBoxArrLen; ++i )
854  {
855  delete (*aBoxFormatArr1)[ i ];
856  }
857  }
858  }
859 
860  // Check the boxes for numbers
861  if( IsInsTableFormatNum() )
862  {
863  for (size_t nBoxes = rNdTable.GetTabSortBoxes().size(); nBoxes; )
864  {
865  ChkBoxNumFormat(*rNdTable.GetTabSortBoxes()[ --nBoxes ], false);
866  }
867  }
868 
869  sal_uLong nIdx = pTableNd->GetIndex();
870  aNode2Layout.RestoreUpperFrames( GetNodes(), nIdx, nIdx + 1 );
871 
872  {
873  SwPaM& rTmp = const_cast<SwPaM&>(rRange); // Point always at the Start
874  rTmp.DeleteMark();
875  rTmp.GetPoint()->nNode = *pTableNd;
876  SwContentNode* pCNd = GetNodes().GoNext( &rTmp.GetPoint()->nNode );
877  rTmp.GetPoint()->nContent.Assign( pCNd, 0 );
878  }
879 
880  if( pUndo )
881  {
883  }
884 
885  getIDocumentState().SetEnableSetModified(bEnableSetModified);
887  getIDocumentFieldsAccess().SetFieldsDirty(true, nullptr, 0);
888  return &rNdTable;
889 }
890 
891 static void lcl_RemoveBreaks(SwContentNode & rNode, SwTableFormat *const pTableFormat)
892 {
893  // delete old layout frames, new ones need to be created...
894  rNode.DelFrames(nullptr);
895 
896  if (!rNode.IsTextNode())
897  {
898  return;
899  }
900 
901  SwTextNode & rTextNode = *rNode.GetTextNode();
902  // remove PageBreaks/PageDesc/ColBreak
903  SfxItemSet const* pSet = rTextNode.GetpSwAttrSet();
904  if (!pSet)
905  return;
906 
907  const SfxPoolItem* pItem;
908  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false, &pItem))
909  {
910  if (pTableFormat)
911  {
912  pTableFormat->SetFormatAttr(*pItem);
913  }
914  rTextNode.ResetAttr(RES_BREAK);
915  pSet = rTextNode.GetpSwAttrSet();
916  }
917 
918  if (pSet
919  && (SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false, &pItem))
920  && static_cast<SwFormatPageDesc const*>(pItem)->GetPageDesc())
921  {
922  if (pTableFormat)
923  {
924  pTableFormat->SetFormatAttr(*pItem);
925  }
926  rTextNode.ResetAttr(RES_PAGEDESC);
927  }
928 }
929 
933 static void
934 lcl_BalanceTable(SwTable & rTable, size_t const nMaxBoxes,
935  SwTableNode & rTableNd, SwTableBoxFormat & rBoxFormat, SwTextFormatColl & rTextColl,
936  SwUndoTextToTable *const pUndo, std::vector<sal_uInt16> *const pPositions)
937 {
938  for (size_t n = 0; n < rTable.GetTabLines().size(); ++n)
939  {
940  SwTableLine *const pCurrLine = rTable.GetTabLines()[ n ];
941  size_t const nBoxes = pCurrLine->GetTabBoxes().size();
942  if (nMaxBoxes != nBoxes)
943  {
944  rTableNd.GetNodes().InsBoxen(&rTableNd, pCurrLine, &rBoxFormat, &rTextColl,
945  nullptr, nBoxes, nMaxBoxes - nBoxes);
946 
947  if (pUndo)
948  {
949  for (size_t i = nBoxes; i < nMaxBoxes; ++i)
950  {
951  pUndo->AddFillBox( *pCurrLine->GetTabBoxes()[i] );
952  }
953  }
954 
955  // if the first line is missing boxes, the width array is useless!
956  if (!n && pPositions)
957  {
958  pPositions->clear();
959  }
960  }
961  }
962 }
963 
964 static void
965 lcl_SetTableBoxWidths(SwTable & rTable, size_t const nMaxBoxes,
966  SwTableBoxFormat & rBoxFormat, SwDoc & rDoc,
967  std::vector<sal_uInt16> *const pPositions)
968 {
969  if (pPositions && !pPositions->empty())
970  {
971  SwTableLines& rLns = rTable.GetTabLines();
972  sal_uInt16 nLastPos = 0;
973  for (size_t n = 0; n < pPositions->size(); ++n)
974  {
975  SwTableBoxFormat *pNewFormat = rDoc.MakeTableBoxFormat();
976  pNewFormat->SetFormatAttr(
977  SwFormatFrameSize(SwFrameSize::Variable, (*pPositions)[n] - nLastPos));
978  for (size_t nTmpLine = 0; nTmpLine < rLns.size(); ++nTmpLine)
979  {
980  // Have to do an Add here, because the BoxFormat
981  // is still needed by the caller
982  pNewFormat->Add( rLns[ nTmpLine ]->GetTabBoxes()[ n ] );
983  }
984 
985  nLastPos = (*pPositions)[ n ];
986  }
987 
988  // propagate size upwards from format, so the table gets the right size
989  SAL_WARN_IF(rBoxFormat.HasWriterListeners(), "sw.core",
990  "who is still registered in the format?");
991  rBoxFormat.SetFormatAttr( SwFormatFrameSize( SwFrameSize::Variable, nLastPos ));
992  }
993  else
994  {
995  size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
997  }
998 }
999 
1001  SwTableFormat* pTableFormat,
1002  SwTableLineFormat* pLineFormat,
1003  SwTableBoxFormat* pBoxFormat,
1004  SwTextFormatColl* pTextColl,
1005  SwUndoTextToTable* pUndo )
1006 {
1007  if( rRange.aStart >= rRange.aEnd )
1008  return nullptr;
1009 
1010  SwTableNode * pTableNd = new SwTableNode( rRange.aStart );
1011  new SwEndNode( rRange.aEnd, *pTableNd );
1012 
1013  SwDoc* pDoc = GetDoc();
1014  std::vector<sal_uInt16> aPosArr;
1015  SwTable& rTable = pTableNd->GetTable();
1016  SwTableBox* pBox;
1017  sal_uInt16 nBoxes, nLines, nMaxBoxes = 0;
1018 
1019  SwNodeIndex aSttIdx( *pTableNd, 1 );
1020  SwNodeIndex aEndIdx( rRange.aEnd, -1 );
1021  for( nLines = 0, nBoxes = 0;
1022  aSttIdx.GetIndex() < aEndIdx.GetIndex();
1023  aSttIdx += 2, nLines++, nBoxes = 0 )
1024  {
1025  SwTextNode* pTextNd = aSttIdx.GetNode().GetTextNode();
1026  OSL_ENSURE( pTextNd, "Only add TextNodes to the Table" );
1027 
1028  if( !nLines && 0x0b == cCh )
1029  {
1030  cCh = 0x09;
1031 
1032  // Get the separator's position from the first Node, in order for the Boxes to be set accordingly
1033  SwTextFrameInfo aFInfo( static_cast<SwTextFrame*>(pTextNd->getLayoutFrame( pTextNd->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout() )) );
1034  if( aFInfo.IsOneLine() ) // only makes sense in this case
1035  {
1036  OUString const& rText(pTextNd->GetText());
1037  for (sal_Int32 nChPos = 0; nChPos < rText.getLength(); ++nChPos)
1038  {
1039  if (rText[nChPos] == cCh)
1040  {
1041  // sw_redlinehide: no idea if this makes any sense...
1042  TextFrameIndex const nPos(aFInfo.GetFrame()->MapModelToView(pTextNd, nChPos));
1043  aPosArr.push_back( static_cast<sal_uInt16>(
1044  aFInfo.GetCharPos(nPos+TextFrameIndex(1), false)) );
1045  }
1046  }
1047 
1048  aPosArr.push_back(
1049  static_cast<sal_uInt16>(aFInfo.GetFrame()->IsVertical() ?
1050  aFInfo.GetFrame()->getFramePrintArea().Bottom() :
1051  aFInfo.GetFrame()->getFramePrintArea().Right()) );
1052 
1053  }
1054  }
1055 
1056  lcl_RemoveBreaks(*pTextNd, (0 == nLines) ? pTableFormat : nullptr);
1057 
1058  // Set the TableNode as StartNode for all TextNodes in the Table
1059  pTextNd->m_pStartOfSection = pTableNd;
1060 
1061  SwTableLine* pLine = new SwTableLine( pLineFormat, 1, nullptr );
1062  rTable.GetTabLines().insert(rTable.GetTabLines().begin() + nLines, pLine);
1063 
1064  SwStartNode* pSttNd;
1065  SwPosition aCntPos( aSttIdx, SwIndex( pTextNd ));
1066 
1067  const std::shared_ptr< sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1068  pContentStore->Save(pDoc, aSttIdx.GetIndex(), SAL_MAX_INT32);
1069 
1070  if( T2T_PARA != cCh )
1071  {
1072  for (sal_Int32 nChPos = 0; nChPos < pTextNd->GetText().getLength();)
1073  {
1074  if (pTextNd->GetText()[nChPos] == cCh)
1075  {
1076  aCntPos.nContent = nChPos;
1077  std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
1078  [&](SwTextNode *const pNewNode, sw::mark::RestoreMode const eMode)
1079  {
1080  if (!pContentStore->Empty())
1081  {
1082  pContentStore->Restore(*pNewNode, nChPos, nChPos + 1, eMode);
1083  }
1084  });
1085  SwContentNode *const pNewNd =
1086  pTextNd->SplitContentNode(aCntPos, &restoreFunc);
1087 
1088  // Delete separator and correct search string
1089  pTextNd->EraseText( aCntPos.nContent, 1 );
1090  nChPos = 0;
1091 
1092  // Set the TableNode as StartNode for all TextNodes in the Table
1093  const SwNodeIndex aTmpIdx( aCntPos.nNode, -1 );
1094  pSttNd = new SwStartNode( aTmpIdx, SwNodeType::Start,
1096  new SwEndNode( aCntPos.nNode, *pSttNd );
1097  pNewNd->m_pStartOfSection = pSttNd;
1098 
1099  // Assign Section to the Box
1100  pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1101  pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1102  }
1103  else
1104  {
1105  ++nChPos;
1106  }
1107  }
1108  }
1109 
1110  // Now for the last substring
1111  if( !pContentStore->Empty())
1112  pContentStore->Restore( *pTextNd, pTextNd->GetText().getLength(), pTextNd->GetText().getLength()+1 );
1113 
1114  pSttNd = new SwStartNode( aCntPos.nNode, SwNodeType::Start, SwTableBoxStartNode );
1115  const SwNodeIndex aTmpIdx( aCntPos.nNode, 1 );
1116  new SwEndNode( aTmpIdx, *pSttNd );
1117  pTextNd->m_pStartOfSection = pSttNd;
1118 
1119  pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1120  pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1121  if( nMaxBoxes < nBoxes )
1122  nMaxBoxes = nBoxes;
1123  }
1124 
1125  lcl_BalanceTable(rTable, nMaxBoxes, *pTableNd, *pBoxFormat, *pTextColl,
1126  pUndo, &aPosArr);
1127  lcl_SetTableBoxWidths(rTable, nMaxBoxes, *pBoxFormat, *pDoc, &aPosArr);
1128 
1129  return pTableNd;
1130 }
1131 
1132 const SwTable* SwDoc::TextToTable( const std::vector< std::vector<SwNodeRange> >& rTableNodes )
1133 {
1134  if (rTableNodes.empty())
1135  return nullptr;
1136 
1137  const std::vector<SwNodeRange>& rFirstRange = *rTableNodes.begin();
1138 
1139  if (rFirstRange.empty())
1140  return nullptr;
1141 
1142  const std::vector<SwNodeRange>& rLastRange = *rTableNodes.rbegin();
1143 
1144  if (rLastRange.empty())
1145  return nullptr;
1146 
1147  /* Save first node in the selection if it is a content node. */
1148  SwContentNode * pSttContentNd = rFirstRange.begin()->aStart.GetNode().GetContentNode();
1149 
1150  const SwNodeRange& rStartRange = *rFirstRange.begin();
1151  const SwNodeRange& rEndRange = *rLastRange.rbegin();
1152 
1154  SwPaM aOriginal( rStartRange.aStart, rEndRange.aEnd );
1155  const SwPosition *pStt = aOriginal.GetMark();
1156  const SwPosition *pEnd = aOriginal.GetPoint();
1157 
1158  bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
1159  if (bUndo)
1160  {
1161  // Do not add splitting the TextNode to the Undo history
1162  GetIDocumentUndoRedo().DoUndo(false);
1163  }
1164 
1165  ::PaMCorrAbs( aOriginal, *pEnd );
1166 
1167  // make sure that the range is on Node Edges
1168  SwNodeRange aRg( pStt->nNode, pEnd->nNode );
1169  if( pStt->nContent.GetIndex() )
1170  getIDocumentContentOperations().SplitNode( *pStt, false );
1171 
1172  bool bEndContent = 0 != pEnd->nContent.GetIndex();
1173 
1174  // Do not split at the End of a Line (except at the End of the Doc)
1175  if( bEndContent )
1176  {
1177  if( pEnd->nNode.GetNode().GetContentNode()->Len() != pEnd->nContent.GetIndex()
1178  || pEnd->nNode.GetIndex() >= GetNodes().GetEndOfContent().GetIndex()-1 )
1179  {
1180  getIDocumentContentOperations().SplitNode( *pEnd, false );
1181  --const_cast<SwNodeIndex&>(pEnd->nNode);
1182  const_cast<SwIndex&>(pEnd->nContent).Assign(
1183  pEnd->nNode.GetNode().GetContentNode(), 0 );
1184  // A Node and at the End?
1185  if( pStt->nNode.GetIndex() >= pEnd->nNode.GetIndex() )
1186  --aRg.aStart;
1187  }
1188  else
1189  ++aRg.aEnd;
1190  }
1191 
1192  assert(aRg.aEnd == pEnd->nNode);
1193  assert(aRg.aStart == pStt->nNode);
1194  if( aRg.aEnd.GetIndex() == aRg.aStart.GetIndex() )
1195  {
1196  OSL_FAIL( "empty range" );
1197  ++aRg.aEnd;
1198  }
1199 
1200 
1201  {
1202  // TODO: this is not Undo-able - only good enough for file import
1204  SwNodeIndex const prev(rTableNodes.begin()->begin()->aStart, -1);
1205  SwNodeIndex const* pPrev(&prev);
1206  // pPrev could point to non-textnode now
1207  for (const auto& rRow : rTableNodes)
1208  {
1209  for (const auto& rCell : rRow)
1210  {
1211  assert(SwNodeIndex(*pPrev, +1) == rCell.aStart);
1212  SwPaM pam(rCell.aStart, 0, *pPrev,
1213  (pPrev->GetNode().IsContentNode())
1214  ? pPrev->GetNode().GetContentNode()->Len() : 0);
1215  rIDRA.SplitRedline(pam);
1216  pPrev = &rCell.aEnd;
1217  }
1218  }
1219  // another one to break between last cell and node after table
1220  SwPaM pam(SwNodeIndex(*pPrev, +1), 0, *pPrev,
1221  (pPrev->GetNode().IsContentNode())
1222  ? pPrev->GetNode().GetContentNode()->Len() : 0);
1223  rIDRA.SplitRedline(pam);
1224  }
1225 
1226  // We always use Upper to insert the Table
1227  SwNode2LayoutSaveUpperFrames aNode2Layout( aRg.aStart.GetNode() );
1228 
1229  GetIDocumentUndoRedo().DoUndo(bUndo);
1230 
1231  // Create the Box/Line/Table construct
1232  SwTableBoxFormat* pBoxFormat = MakeTableBoxFormat();
1233  SwTableLineFormat* pLineFormat = MakeTableLineFormat();
1235 
1236  // All Lines have a left-to-right Fill Order
1238  // The Table's SSize is USHRT_MAX
1240 
1241  /* If the first node in the selection is a context node and if it
1242  has an item FRAMEDIR set (no default) propagate the item to the
1243  replacing table. */
1244  if (pSttContentNd)
1245  {
1246  const SwAttrSet & aNdSet = pSttContentNd->GetSwAttrSet();
1247  const SfxPoolItem *pItem = nullptr;
1248 
1249  if (SfxItemState::SET == aNdSet.GetItemState( RES_FRAMEDIR, true, &pItem )
1250  && pItem != nullptr)
1251  {
1252  pTableFormat->SetFormatAttr( *pItem );
1253  }
1254  }
1255 
1256  //Resolves: tdf#87977, tdf#78599, disable broadcasting modifications
1257  //until after RegisterToFormat is completed
1258  bool bEnableSetModified = getIDocumentState().IsEnableSetModified();
1260 
1261  SwTableNode* pTableNd = GetNodes().TextToTable(
1262  rTableNodes, pTableFormat, pLineFormat, pBoxFormat );
1263 
1264  SwTable& rNdTable = pTableNd->GetTable();
1265  rNdTable.RegisterToFormat(*pTableFormat);
1266 
1267  if( !pBoxFormat->HasWriterListeners() )
1268  {
1269  // The Box's Formats already have the right size, we must only set
1270  // the right Border/AutoFormat.
1271  pTableFormat->SetFormatAttr( pBoxFormat->GetFrameSize() );
1272  delete pBoxFormat;
1273  }
1274 
1275  sal_uLong nIdx = pTableNd->GetIndex();
1276  aNode2Layout.RestoreUpperFrames( GetNodes(), nIdx, nIdx + 1 );
1277 
1278  getIDocumentState().SetEnableSetModified(bEnableSetModified);
1280  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
1281  return &rNdTable;
1282 }
1283 
1284 std::unique_ptr<SwNodeRange> SwNodes::ExpandRangeForTableBox(const SwNodeRange & rRange)
1285 {
1286  bool bChanged = false;
1287 
1288  SwNodeIndex aNewStart = rRange.aStart;
1289  SwNodeIndex aNewEnd = rRange.aEnd;
1290 
1291  SwNodeIndex aEndIndex = rRange.aEnd;
1292  SwNodeIndex aIndex = rRange.aStart;
1293 
1294  while (aIndex < aEndIndex)
1295  {
1296  SwNode& rNode = aIndex.GetNode();
1297 
1298  if (rNode.IsStartNode())
1299  {
1300  // advance aIndex to the end node of this start node
1301  SwNode * pEndNode = rNode.EndOfSectionNode();
1302  aIndex = *pEndNode;
1303 
1304  if (aIndex > aNewEnd)
1305  {
1306  aNewEnd = aIndex;
1307  bChanged = true;
1308  }
1309  }
1310  else if (rNode.IsEndNode())
1311  {
1312  SwNode * pStartNode = rNode.StartOfSectionNode();
1313  SwNodeIndex aStartIndex = *pStartNode;
1314 
1315  if (aStartIndex < aNewStart)
1316  {
1317  aNewStart = aStartIndex;
1318  bChanged = true;
1319  }
1320  }
1321 
1322  if (aIndex < aEndIndex)
1323  ++aIndex;
1324  }
1325 
1326  SwNode * pNode = &aIndex.GetNode();
1327  while (pNode->IsEndNode() && aIndex < Count() - 1)
1328  {
1329  SwNode * pStartNode = pNode->StartOfSectionNode();
1330  SwNodeIndex aStartIndex(*pStartNode);
1331  aNewStart = aStartIndex;
1332  aNewEnd = aIndex;
1333  bChanged = true;
1334 
1335  ++aIndex;
1336  pNode = &aIndex.GetNode();
1337  }
1338 
1339  std::unique_ptr<SwNodeRange> pResult;
1340  if (bChanged)
1341  pResult.reset(new SwNodeRange(aNewStart, aNewEnd));
1342  return pResult;
1343 }
1344 
1345 static void
1346 lcl_SetTableBoxWidths2(SwTable & rTable, size_t const nMaxBoxes,
1347  SwTableBoxFormat & rBoxFormat, SwDoc & rDoc)
1348 {
1349  // rhbz#820283, fdo#55462: set default box widths so table width is covered
1350  SwTableLines & rLines = rTable.GetTabLines();
1351  for (size_t nTmpLine = 0; nTmpLine < rLines.size(); ++nTmpLine)
1352  {
1353  SwTableBoxes & rBoxes = rLines[nTmpLine]->GetTabBoxes();
1354  assert(!rBoxes.empty()); // ensured by convertToTable
1355  size_t const nMissing = nMaxBoxes - rBoxes.size();
1356  if (nMissing)
1357  {
1358  // default width for box at the end of an incomplete line
1359  SwTableBoxFormat *const pNewFormat = rDoc.MakeTableBoxFormat();
1360  size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
1362  nWidth * (nMissing + 1)) );
1363  pNewFormat->Add(rBoxes.back());
1364  }
1365  }
1366  size_t nWidth = nMaxBoxes ? USHRT_MAX / nMaxBoxes : USHRT_MAX;
1367  // default width for all boxes not at the end of an incomplete line
1369 }
1370 
1372  SwTableFormat* pTableFormat,
1373  SwTableLineFormat* pLineFormat,
1374  SwTableBoxFormat* pBoxFormat )
1375 {
1376  if( rTableNodes.empty() )
1377  return nullptr;
1378 
1379  SwTableNode * pTableNd = new SwTableNode( rTableNodes.begin()->begin()->aStart );
1380  //insert the end node after the last text node
1381  SwNodeIndex aInsertIndex( rTableNodes.rbegin()->rbegin()->aEnd );
1382  ++aInsertIndex;
1383 
1386  new SwEndNode( aInsertIndex, *pTableNd );
1387 
1388  SwDoc* pDoc = GetDoc();
1389  SwTable& rTable = pTableNd->GetTable();
1390  SwTableBox* pBox;
1391  sal_uInt16 nLines, nMaxBoxes = 0;
1392 
1393  SwNodeIndex aNodeIndex = rTableNodes.begin()->begin()->aStart;
1394  // delete frames of all contained content nodes
1395  for( nLines = 0; aNodeIndex <= rTableNodes.rbegin()->rbegin()->aEnd; ++aNodeIndex,++nLines )
1396  {
1397  SwNode& rNode = aNodeIndex.GetNode();
1398  if( rNode.IsContentNode() )
1399  {
1400  lcl_RemoveBreaks(static_cast<SwContentNode&>(rNode),
1401  (0 == nLines) ? pTableFormat : nullptr);
1402  }
1403  }
1404 
1405  nLines = 0;
1406  for( const auto& rRow : rTableNodes )
1407  {
1408  sal_uInt16 nBoxes = 0;
1409  SwTableLine* pLine = new SwTableLine( pLineFormat, 1, nullptr );
1410  rTable.GetTabLines().insert(rTable.GetTabLines().begin() + nLines, pLine);
1411 
1412  for( const auto& rCell : rRow )
1413  {
1414  const SwNodeIndex aTmpIdx( rCell.aStart, 0 );
1415 
1416  SwNodeIndex aCellEndIdx(rCell.aEnd);
1417  ++aCellEndIdx;
1418  SwStartNode* pSttNd = new SwStartNode( aTmpIdx, SwNodeType::Start,
1420 
1421  // Quotation of http://nabble.documentfoundation.org/Some-strange-lines-by-taking-a-look-at-the-bt-of-fdo-51916-tp3994561p3994639.html
1422  // SwNode's constructor adds itself to the same SwNodes array as the other node (pSttNd).
1423  // So this statement is only executed for the side-effect.
1424  new SwEndNode( aCellEndIdx, *pSttNd );
1425 
1426  //set the start node on all node of the current cell
1427  SwNodeIndex aCellNodeIdx = rCell.aStart;
1428  for(;aCellNodeIdx <= rCell.aEnd; ++aCellNodeIdx )
1429  {
1430  aCellNodeIdx.GetNode().m_pStartOfSection = pSttNd;
1431  //skip start/end node pairs
1432  if( aCellNodeIdx.GetNode().IsStartNode() )
1433  aCellNodeIdx.Assign(*aCellNodeIdx.GetNode().EndOfSectionNode());
1434  }
1435 
1436  // assign Section to the Box
1437  pBox = new SwTableBox( pBoxFormat, *pSttNd, pLine );
1438  pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin() + nBoxes++, pBox );
1439  }
1440  if( nMaxBoxes < nBoxes )
1441  nMaxBoxes = nBoxes;
1442 
1443  nLines++;
1444  }
1445 
1446  lcl_SetTableBoxWidths2(rTable, nMaxBoxes, *pBoxFormat, *pDoc);
1447 
1448  return pTableNd;
1449 }
1450 
1454 bool SwDoc::TableToText( const SwTableNode* pTableNd, sal_Unicode cCh )
1455 {
1456  if( !pTableNd )
1457  return false;
1458 
1459  // #i34471#
1460  // If this is triggered by SwUndoTableToText::Repeat() nobody ever deleted
1461  // the table cursor.
1462  SwEditShell* pESh = GetEditShell();
1463  if( pESh && pESh->IsTableMode() )
1464  pESh->ClearMark();
1465 
1466  SwNodeRange aRg( *pTableNd, 0, *pTableNd->EndOfSectionNode() );
1467  std::unique_ptr<SwUndoTableToText> pUndo;
1468  SwNodeRange* pUndoRg = nullptr;
1470  {
1472  pUndoRg = new SwNodeRange( aRg.aStart, -1, aRg.aEnd, +1 );
1473  pUndo.reset(new SwUndoTableToText( pTableNd->GetTable(), cCh ));
1474  }
1475 
1476  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
1477  aMsgHint.m_eFlags = TBL_BOXNAME;
1479 
1480  bool bRet = GetNodes().TableToText( aRg, cCh, pUndo.get() );
1481  if( pUndoRg )
1482  {
1483  ++pUndoRg->aStart;
1484  --pUndoRg->aEnd;
1485  pUndo->SetRange( *pUndoRg );
1486  GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
1487  delete pUndoRg;
1488  }
1489 
1490  if( bRet )
1492 
1493  return bRet;
1494 }
1495 
1496 namespace {
1497 
1502 struct DelTabPara
1503 {
1504  SwTextNode* pLastNd;
1505  SwNodes& rNds;
1506  SwUndoTableToText* pUndo;
1507  sal_Unicode cCh;
1508 
1509  DelTabPara( SwNodes& rNodes, sal_Unicode cChar, SwUndoTableToText* pU ) :
1510  pLastNd(nullptr), rNds( rNodes ), pUndo( pU ), cCh( cChar ) {}
1511 };
1512 
1513 }
1514 
1515 // Forward declare so that the Lines and Boxes can use recursion
1516 static void lcl_DelBox( SwTableBox* pBox, DelTabPara* pDelPara );
1517 
1518 static void lcl_DelLine( SwTableLine* pLine, DelTabPara* pPara )
1519 {
1520  assert(pPara && "The parameters are missing!");
1521  DelTabPara aPara( *pPara );
1522  for( auto& rpBox : pLine->GetTabBoxes() )
1523  lcl_DelBox(rpBox, &aPara );
1524  if( pLine->GetUpper() ) // Is there a parent Box?
1525  // Return the last TextNode
1526  pPara->pLastNd = aPara.pLastNd;
1527 }
1528 
1529 static void lcl_DelBox( SwTableBox* pBox, DelTabPara* pDelPara )
1530 {
1531  assert(pDelPara && "The parameters are missing");
1532 
1533  // Delete the Box's Lines
1534  if( !pBox->GetTabLines().empty() )
1535  {
1536  for( SwTableLine* pLine : pBox->GetTabLines() )
1537  lcl_DelLine( pLine, pDelPara );
1538  }
1539  else
1540  {
1541  SwDoc* pDoc = pDelPara->rNds.GetDoc();
1542  SwNodeRange aDelRg( *pBox->GetSttNd(), 0,
1543  *pBox->GetSttNd()->EndOfSectionNode() );
1544  // Delete the Section
1545  pDelPara->rNds.SectionUp( &aDelRg );
1546  const SwTextNode* pCurTextNd = nullptr;
1547  if (T2T_PARA != pDelPara->cCh && pDelPara->pLastNd)
1548  pCurTextNd = aDelRg.aStart.GetNode().GetTextNode();
1549  if (nullptr != pCurTextNd)
1550  {
1551  // Join the current text node with the last from the previous box if possible
1552  sal_uLong nNdIdx = aDelRg.aStart.GetIndex();
1553  --aDelRg.aStart;
1554  if( pDelPara->pLastNd == &aDelRg.aStart.GetNode() )
1555  {
1556  // Inserting the separator
1557  SwIndex aCntIdx( pDelPara->pLastNd,
1558  pDelPara->pLastNd->GetText().getLength());
1559  pDelPara->pLastNd->InsertText( OUString(pDelPara->cCh), aCntIdx,
1561  if( pDelPara->pUndo )
1562  pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex(),
1563  aCntIdx.GetIndex() );
1564 
1565  const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
1566  const sal_Int32 nOldTextLen = aCntIdx.GetIndex();
1567  pContentStore->Save(pDoc, nNdIdx, SAL_MAX_INT32);
1568 
1569  pDelPara->pLastNd->JoinNext();
1570 
1571  if( !pContentStore->Empty() )
1572  pContentStore->Restore( pDoc, pDelPara->pLastNd->GetIndex(), nOldTextLen );
1573  }
1574  else if( pDelPara->pUndo )
1575  {
1576  ++aDelRg.aStart;
1577  pDelPara->pUndo->AddBoxPos( *pDoc, nNdIdx, aDelRg.aEnd.GetIndex() );
1578  }
1579  }
1580  else if( pDelPara->pUndo )
1581  pDelPara->pUndo->AddBoxPos( *pDoc, aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1582  --aDelRg.aEnd;
1583  pDelPara->pLastNd = aDelRg.aEnd.GetNode().GetTextNode();
1584 
1585  // Do not take over the NumberFormatting's adjustment
1586  if( pDelPara->pLastNd && pDelPara->pLastNd->HasSwAttrSet() )
1587  pDelPara->pLastNd->ResetAttr( RES_PARATR_ADJUST );
1588  }
1589 }
1590 
1592  SwUndoTableToText* pUndo )
1593 {
1594  // Is a Table selected?
1595  if (rRange.aStart.GetIndex() >= rRange.aEnd.GetIndex())
1596  return false;
1597  SwTableNode *const pTableNd(rRange.aStart.GetNode().GetTableNode());
1598  if (nullptr == pTableNd ||
1599  &rRange.aEnd.GetNode() != pTableNd->EndOfSectionNode() )
1600  return false;
1601 
1602  // If the Table was alone in a Section, create the Frames via the Table's Upper
1603  SwNode2LayoutSaveUpperFrames * pNode2Layout = nullptr;
1604  SwNodeIndex aFrameIdx( rRange.aStart );
1605  SwNode* pFrameNd = FindPrvNxtFrameNode( aFrameIdx, &rRange.aEnd.GetNode() );
1606  if( !pFrameNd )
1607  // Collect all Uppers
1608  pNode2Layout = new SwNode2LayoutSaveUpperFrames(*pTableNd);
1609 
1610  // Delete the Frames
1611  pTableNd->DelFrames();
1612 
1613  // "Delete" the Table and merge all Lines/Boxes
1614  DelTabPara aDelPara( *this, cCh, pUndo );
1615  for( SwTableLine *pLine : pTableNd->m_pTable->GetTabLines() )
1616  lcl_DelLine( pLine, &aDelPara );
1617 
1618  // We just created a TextNode with fitting separator for every TableLine.
1619  // Now we only need to delete the TableSection and create the Frames for the
1620  // new TextNode.
1621  SwNodeRange aDelRg( rRange.aStart, rRange.aEnd );
1622 
1623  // If the Table has PageDesc/Break Attributes, carry them over to the
1624  // first Text Node
1625  {
1626  // What about UNDO?
1627  const SfxItemSet& rTableSet = pTableNd->m_pTable->GetFrameFormat()->GetAttrSet();
1628  const SfxPoolItem *pBreak, *pDesc;
1629  if( SfxItemState::SET != rTableSet.GetItemState( RES_PAGEDESC, false, &pDesc ))
1630  pDesc = nullptr;
1631  if( SfxItemState::SET != rTableSet.GetItemState( RES_BREAK, false, &pBreak ))
1632  pBreak = nullptr;
1633 
1634  if( pBreak || pDesc )
1635  {
1636  SwNodeIndex aIdx( *pTableNd );
1637  SwContentNode* pCNd = GoNext( &aIdx );
1638  if( pBreak )
1639  pCNd->SetAttr( *pBreak );
1640  if( pDesc )
1641  pCNd->SetAttr( *pDesc );
1642  }
1643  }
1644 
1645  SectionUp( &aDelRg ); // Delete this Section and by that the Table
1646  // #i28006#
1647  sal_uLong nStt = aDelRg.aStart.GetIndex(), nEnd = aDelRg.aEnd.GetIndex();
1648  if( !pFrameNd )
1649  {
1650  pNode2Layout->RestoreUpperFrames( *this,
1651  aDelRg.aStart.GetIndex(), aDelRg.aEnd.GetIndex() );
1652  delete pNode2Layout;
1653  }
1654  else
1655  {
1656  SwContentNode *pCNd;
1657  SwSectionNode *pSNd;
1658  while( aDelRg.aStart.GetIndex() < nEnd )
1659  {
1660  pCNd = aDelRg.aStart.GetNode().GetContentNode();
1661  if( nullptr != pCNd )
1662  {
1663  if( pFrameNd->IsContentNode() )
1664  static_cast<SwContentNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(*pCNd);
1665  else if( pFrameNd->IsTableNode() )
1666  static_cast<SwTableNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aDelRg.aStart);
1667  else if( pFrameNd->IsSectionNode() )
1668  static_cast<SwSectionNode*>(pFrameNd)->MakeFramesForAdjacentContentNode(aDelRg.aStart);
1669  pFrameNd = pCNd;
1670  }
1671  else
1672  {
1673  pSNd = aDelRg.aStart.GetNode().GetSectionNode();
1674  if( pSNd )
1675  {
1676  if( !pSNd->GetSection().IsHidden() && !pSNd->IsContentHidden() )
1677  {
1678  pSNd->MakeOwnFrames(&aFrameIdx, &aDelRg.aEnd);
1679  break;
1680  }
1681  aDelRg.aStart = *pSNd->EndOfSectionNode();
1682  }
1683  }
1684  ++aDelRg.aStart;
1685  }
1686  }
1687 
1688  // #i28006# Fly frames have to be restored even if the table was
1689  // #alone in the section
1690  const SwFrameFormats& rFlyArr = *GetDoc()->GetSpzFrameFormats();
1691  for( auto pFly : rFlyArr )
1692  {
1693  SwFrameFormat *const pFormat = pFly;
1694  const SwFormatAnchor& rAnchor = pFormat->GetAnchor();
1695  SwPosition const*const pAPos = rAnchor.GetContentAnchor();
1696  if (pAPos &&
1697  ((RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1698  (RndStdIds::FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
1699  nStt <= pAPos->nNode.GetIndex() &&
1700  pAPos->nNode.GetIndex() < nEnd )
1701  {
1702  pFormat->MakeFrames();
1703  }
1704  }
1705 
1706  return true;
1707 }
1708 
1712 void SwDoc::InsertCol( const SwCursor& rCursor, sal_uInt16 nCnt, bool bBehind )
1713 {
1714  if( !::CheckSplitCells( rCursor, nCnt + 1, SwTableSearchType::Col ) )
1715  return;
1716 
1717  // Find the Boxes via the Layout
1718  SwSelBoxes aBoxes;
1719  ::GetTableSel( rCursor, aBoxes, SwTableSearchType::Col );
1720 
1721  if( !aBoxes.empty() )
1722  InsertCol( aBoxes, nCnt, bBehind );
1723 }
1724 
1725 bool SwDoc::InsertCol( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
1726 {
1727  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1728  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1729  if( !pTableNd )
1730  return false;
1731 
1732  SwTable& rTable = pTableNd->GetTable();
1733  if( dynamic_cast<const SwDDETable*>( &rTable) != nullptr)
1734  return false;
1735 
1736  SwTableSortBoxes aTmpLst;
1737  std::unique_ptr<SwUndoTableNdsChg> pUndo;
1738  if (GetIDocumentUndoRedo().DoesUndo())
1739  {
1740  pUndo.reset(new SwUndoTableNdsChg( SwUndoId::TABLE_INSCOL, rBoxes, *pTableNd,
1741  0, 0, nCnt, bBehind, false ));
1742  aTmpLst.insert( rTable.GetTabSortBoxes() );
1743  }
1744 
1745  bool bRet(false);
1746  {
1747  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1748 
1749  SwTableFormulaUpdate aMsgHint( &rTable );
1750  aMsgHint.m_eFlags = TBL_BOXPTR;
1752 
1753  bRet = rTable.InsertCol( this, rBoxes, nCnt, bBehind );
1754  if (bRet)
1755  {
1757  ::ClearFEShellTabCols(*this, nullptr);
1758  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
1759  }
1760  }
1761 
1762  if( pUndo && bRet )
1763  {
1764  pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
1765  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
1766  }
1767  return bRet;
1768 }
1769 
1770 void SwDoc::InsertRow( const SwCursor& rCursor, sal_uInt16 nCnt, bool bBehind )
1771 {
1772  // Find the Boxes via the Layout
1773  SwSelBoxes aBoxes;
1774  GetTableSel( rCursor, aBoxes, SwTableSearchType::Row );
1775 
1776  if( !aBoxes.empty() )
1777  InsertRow( aBoxes, nCnt, bBehind );
1778 }
1779 
1780 bool SwDoc::InsertRow( const SwSelBoxes& rBoxes, sal_uInt16 nCnt, bool bBehind )
1781 {
1782  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1783  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1784  if( !pTableNd )
1785  return false;
1786 
1787  SwTable& rTable = pTableNd->GetTable();
1788  if( dynamic_cast<const SwDDETable*>( &rTable) != nullptr)
1789  return false;
1790 
1791  SwTableSortBoxes aTmpLst;
1792  std::unique_ptr<SwUndoTableNdsChg> pUndo;
1793  if (GetIDocumentUndoRedo().DoesUndo())
1794  {
1795  pUndo.reset(new SwUndoTableNdsChg( SwUndoId::TABLE_INSROW,rBoxes, *pTableNd,
1796  0, 0, nCnt, bBehind, false ));
1797  aTmpLst.insert( rTable.GetTabSortBoxes() );
1798  }
1799 
1800  bool bRet(false);
1801  {
1802  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
1803 
1804  SwTableFormulaUpdate aMsgHint( &rTable );
1805  aMsgHint.m_eFlags = TBL_BOXPTR;
1807 
1808  bRet = rTable.InsertRow( this, rBoxes, nCnt, bBehind );
1809  if (bRet)
1810  {
1812  ::ClearFEShellTabCols(*this, nullptr);
1813  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
1814  }
1815  }
1816 
1817  if( pUndo && bRet )
1818  {
1819  pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
1820  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
1821  }
1822  return bRet;
1823 
1824 }
1825 
1829 void SwDoc::DeleteRow( const SwCursor& rCursor )
1830 {
1831  // Find the Boxes via the Layout
1832  SwSelBoxes aBoxes;
1833  GetTableSel( rCursor, aBoxes, SwTableSearchType::Row );
1834  if( ::HasProtectedCells( aBoxes ))
1835  return;
1836 
1837  // Remove the Cursor from the to-be-deleted Section.
1838  // The Cursor is placed after the table, except for
1839  // - when there's another Line, we place it in that one
1840  // - when a Line precedes it, we place it in that one
1841  {
1842  SwTableNode* pTableNd = rCursor.GetNode().FindTableNode();
1843 
1844  if(dynamic_cast<const SwDDETable*>( & pTableNd->GetTable()) != nullptr)
1845  return;
1846 
1847  // Find all Boxes/Lines
1848  FndBox_ aFndBox( nullptr, nullptr );
1849  {
1850  FndPara aPara( aBoxes, &aFndBox );
1851  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
1852  }
1853 
1854  if( aFndBox.GetLines().empty() )
1855  return;
1856 
1857  SwEditShell* pESh = GetEditShell();
1858  if( pESh )
1859  {
1860  pESh->KillPams();
1861  // FIXME: actually we should be iterating over all Shells!
1862  }
1863 
1864  FndBox_* pFndBox = &aFndBox;
1865  while( 1 == pFndBox->GetLines().size() &&
1866  1 == pFndBox->GetLines().front()->GetBoxes().size() )
1867  {
1868  FndBox_ *const pTmp = pFndBox->GetLines().front()->GetBoxes()[0].get();
1869  if( pTmp->GetBox()->GetSttNd() )
1870  break; // Else it gets too far
1871  pFndBox = pTmp;
1872  }
1873 
1874  SwTableLine* pDelLine = pFndBox->GetLines().back()->GetLine();
1875  SwTableBox* pDelBox = pDelLine->GetTabBoxes().back();
1876  while( !pDelBox->GetSttNd() )
1877  {
1878  SwTableLine* pLn = pDelBox->GetTabLines()[
1879  pDelBox->GetTabLines().size()-1 ];
1880  pDelBox = pLn->GetTabBoxes().back();
1881  }
1882  SwTableBox* pNextBox = pDelLine->FindNextBox( pTableNd->GetTable(),
1883  pDelBox );
1884  while( pNextBox &&
1885  pNextBox->GetFrameFormat()->GetProtect().IsContentProtected() )
1886  pNextBox = pNextBox->FindNextBox( pTableNd->GetTable(), pNextBox );
1887 
1888  if( !pNextBox ) // No succeeding Boxes? Then take the preceding one
1889  {
1890  pDelLine = pFndBox->GetLines().front()->GetLine();
1891  pDelBox = pDelLine->GetTabBoxes()[ 0 ];
1892  while( !pDelBox->GetSttNd() )
1893  pDelBox = pDelBox->GetTabLines()[0]->GetTabBoxes()[0];
1894  pNextBox = pDelLine->FindPreviousBox( pTableNd->GetTable(),
1895  pDelBox );
1896  while( pNextBox &&
1897  pNextBox->GetFrameFormat()->GetProtect().IsContentProtected() )
1898  pNextBox = pNextBox->FindPreviousBox( pTableNd->GetTable(), pNextBox );
1899  }
1900 
1901  sal_uLong nIdx;
1902  if( pNextBox ) // Place the Cursor here
1903  nIdx = pNextBox->GetSttIdx() + 1;
1904  else // Else after the Table
1905  nIdx = pTableNd->EndOfSectionIndex() + 1;
1906 
1907  SwNodeIndex aIdx( GetNodes(), nIdx );
1908  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
1909  if( !pCNd )
1910  pCNd = GetNodes().GoNext( &aIdx );
1911 
1912  if( pCNd )
1913  {
1914  // Change the Shell's Cursor or the one passed?
1915  SwPaM* pPam = const_cast<SwPaM*>(static_cast<SwPaM const *>(&rCursor));
1916  pPam->GetPoint()->nNode = aIdx;
1917  pPam->GetPoint()->nContent.Assign( pCNd, 0 );
1918  pPam->SetMark(); // Both want a part of it
1919  pPam->DeleteMark();
1920  }
1921  }
1922 
1923  // Thus delete the Rows
1925  DeleteRowCol( aBoxes );
1927 }
1928 
1929 void SwDoc::DeleteCol( const SwCursor& rCursor )
1930 {
1931  // Find the Boxes via the Layout
1932  SwSelBoxes aBoxes;
1933  GetTableSel( rCursor, aBoxes, SwTableSearchType::Col );
1934  if( ::HasProtectedCells( aBoxes ))
1935  return;
1936 
1937  // The Cursors need to be removed from the to-be-deleted range.
1938  // Always place them after/on top of the Table; they are always set
1939  // to the old position via the document position.
1940  SwEditShell* pESh = GetEditShell();
1941  if( pESh )
1942  {
1943  const SwNode* pNd = rCursor.GetNode().FindTableBoxStartNode();
1944  pESh->ParkCursor( SwNodeIndex( *pNd ) );
1945  }
1946 
1947  // Thus delete the Columns
1949  DeleteRowCol( aBoxes, true );
1951 }
1952 
1953 bool SwDoc::DeleteRowCol( const SwSelBoxes& rBoxes, bool bColumn )
1954 {
1955  if( ::HasProtectedCells( rBoxes ))
1956  return false;
1957 
1958  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
1959  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
1960  if( !pTableNd )
1961  return false;
1962 
1963  if( dynamic_cast<const SwDDETable*>( &pTableNd->GetTable() ) != nullptr)
1964  return false;
1965 
1966  ::ClearFEShellTabCols(*this, nullptr);
1967  SwSelBoxes aSelBoxes( rBoxes );
1968  SwTable &rTable = pTableNd->GetTable();
1969  long nMin = 0;
1970  long nMax = 0;
1971  if( rTable.IsNewModel() )
1972  {
1973  if( bColumn )
1974  rTable.ExpandColumnSelection( aSelBoxes, nMin, nMax );
1975  else
1976  rTable.FindSuperfluousRows( aSelBoxes );
1977  }
1978 
1979  // Are we deleting the whole Table?
1980  const sal_uLong nTmpIdx1 = pTableNd->GetIndex();
1981  const sal_uLong nTmpIdx2 = aSelBoxes.back()->GetSttNd()->EndOfSectionIndex() + 1;
1982  if( pTableNd->GetTable().GetTabSortBoxes().size() == aSelBoxes.size() &&
1983  aSelBoxes[0]->GetSttIdx()-1 == nTmpIdx1 &&
1984  nTmpIdx2 == pTableNd->EndOfSectionIndex() )
1985  {
1986  bool bNewTextNd = false;
1987  // Is it alone in a FlyFrame?
1988  SwNodeIndex aIdx( *pTableNd, -1 );
1989  const SwStartNode* pSttNd = aIdx.GetNode().GetStartNode();
1990  if( pSttNd )
1991  {
1992  const sal_uLong nTableEnd = pTableNd->EndOfSectionIndex() + 1;
1993  const sal_uLong nSectEnd = pSttNd->EndOfSectionIndex();
1994  if( nTableEnd == nSectEnd )
1995  {
1996  if( SwFlyStartNode == pSttNd->GetStartNodeType() )
1997  {
1998  SwFrameFormat* pFormat = pSttNd->GetFlyFormat();
1999  if( pFormat )
2000  {
2001  // That's the FlyFormat we're looking for
2003  return true;
2004  }
2005  }
2006  // No Fly? Thus Header or Footer: always leave a TextNode
2007  // We can forget about Undo then!
2008  bNewTextNd = true;
2009  }
2010  }
2011 
2012  // No Fly? Then it is a Header or Footer, so keep always a TextNode
2013  ++aIdx;
2014  if (GetIDocumentUndoRedo().DoesUndo())
2015  {
2017  SwPaM aPaM( *pTableNd->EndOfSectionNode(), aIdx.GetNode() );
2018 
2019  if( bNewTextNd )
2020  {
2021  const SwNodeIndex aTmpIdx( *pTableNd->EndOfSectionNode(), 1 );
2022  GetNodes().MakeTextNode( aTmpIdx,
2023  getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
2024  }
2025 
2026  // Save the cursors (UNO and otherwise)
2027  SwPaM aSavePaM( SwNodeIndex( *pTableNd->EndOfSectionNode() ) );
2028  if( ! aSavePaM.Move( fnMoveForward, GoInNode ) )
2029  {
2030  *aSavePaM.GetMark() = SwPosition( *pTableNd );
2031  aSavePaM.Move( fnMoveBackward, GoInNode );
2032  }
2033  {
2034  SwPaM const tmpPaM(*pTableNd, *pTableNd->EndOfSectionNode());
2035  ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2036  }
2037 
2038  // Move hard PageBreaks to the succeeding Node
2039  bool bSavePageBreak = false, bSavePageDesc = false;
2040  sal_uLong nNextNd = pTableNd->EndOfSectionIndex()+1;
2041  SwContentNode* pNextNd = GetNodes()[ nNextNd ]->GetContentNode();
2042  if( pNextNd )
2043  {
2044  SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
2045  const SfxPoolItem *pItem;
2046  if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
2047  false, &pItem ) )
2048  {
2049  pNextNd->SetAttr( *pItem );
2050  bSavePageDesc = true;
2051  }
2052 
2053  if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
2054  false, &pItem ) )
2055  {
2056  pNextNd->SetAttr( *pItem );
2057  bSavePageBreak = true;
2058  }
2059  }
2060  std::unique_ptr<SwUndoDelete> pUndo(new SwUndoDelete( aPaM ));
2061  if( bNewTextNd )
2062  pUndo->SetTableDelLastNd();
2063  pUndo->SetPgBrkFlags( bSavePageBreak, bSavePageDesc );
2064  pUndo->SetTableName(pTableNd->GetTable().GetFrameFormat()->GetName());
2065  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
2066  }
2067  else
2068  {
2069  if( bNewTextNd )
2070  {
2071  const SwNodeIndex aTmpIdx( *pTableNd->EndOfSectionNode(), 1 );
2072  GetNodes().MakeTextNode( aTmpIdx,
2073  getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD ) );
2074  }
2075 
2076  // Save the cursors (UNO and otherwise)
2077  SwPaM aSavePaM( SwNodeIndex( *pTableNd->EndOfSectionNode() ) );
2078  if( ! aSavePaM.Move( fnMoveForward, GoInNode ) )
2079  {
2080  *aSavePaM.GetMark() = SwPosition( *pTableNd );
2081  aSavePaM.Move( fnMoveBackward, GoInNode );
2082  }
2083  {
2084  SwPaM const tmpPaM(*pTableNd, *pTableNd->EndOfSectionNode());
2085  ::PaMCorrAbs(tmpPaM, *aSavePaM.GetMark());
2086  }
2087 
2088  // Move hard PageBreaks to the succeeding Node
2089  SwContentNode* pNextNd = GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]->GetContentNode();
2090  if( pNextNd )
2091  {
2092  SwFrameFormat* pTableFormat = pTableNd->GetTable().GetFrameFormat();
2093  const SfxPoolItem *pItem;
2094  if( SfxItemState::SET == pTableFormat->GetItemState( RES_PAGEDESC,
2095  false, &pItem ) )
2096  pNextNd->SetAttr( *pItem );
2097 
2098  if( SfxItemState::SET == pTableFormat->GetItemState( RES_BREAK,
2099  false, &pItem ) )
2100  pNextNd->SetAttr( *pItem );
2101  }
2102 
2103  pTableNd->DelFrames();
2105  }
2106 
2108 
2110  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
2111 
2112  return true;
2113  }
2114 
2115  std::unique_ptr<SwUndoTableNdsChg> pUndo;
2116  if (GetIDocumentUndoRedo().DoesUndo())
2117  {
2118  pUndo.reset(new SwUndoTableNdsChg( SwUndoId::TABLE_DELBOX, aSelBoxes, *pTableNd,
2119  nMin, nMax, 0, false, false ));
2120  }
2121 
2122  bool bRet(false);
2123  {
2124  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2125 
2126  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
2127  aMsgHint.m_eFlags = TBL_BOXPTR;
2129 
2130  if (rTable.IsNewModel())
2131  {
2132  if (bColumn)
2133  rTable.PrepareDeleteCol( nMin, nMax );
2134  rTable.FindSuperfluousRows( aSelBoxes );
2135  if (pUndo)
2136  pUndo->ReNewBoxes( aSelBoxes );
2137  }
2138  bRet = rTable.DeleteSel( this, aSelBoxes, nullptr, pUndo.get(), true, true );
2139  if (bRet)
2140  {
2142 
2144  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
2145  }
2146  }
2147 
2148  if( pUndo && bRet )
2149  {
2150  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
2151  }
2152 
2153  return bRet;
2154 }
2155 
2159 bool SwDoc::SplitTable( const SwSelBoxes& rBoxes, bool bVert, sal_uInt16 nCnt,
2160  bool bSameHeight )
2161 {
2162  OSL_ENSURE( !rBoxes.empty() && nCnt, "No valid Box list" );
2163  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
2164  if( !pTableNd )
2165  return false;
2166 
2167  SwTable& rTable = pTableNd->GetTable();
2168  if( dynamic_cast<const SwDDETable*>( &rTable) != nullptr)
2169  return false;
2170 
2171  std::vector<sal_uLong> aNdsCnts;
2172  SwTableSortBoxes aTmpLst;
2173  std::unique_ptr<SwUndoTableNdsChg> pUndo;
2174  if (GetIDocumentUndoRedo().DoesUndo())
2175  {
2176  pUndo.reset(new SwUndoTableNdsChg( SwUndoId::TABLE_SPLIT, rBoxes, *pTableNd, 0, 0,
2177  nCnt, bVert, bSameHeight ));
2178 
2179  aTmpLst.insert( rTable.GetTabSortBoxes() );
2180  if( !bVert )
2181  {
2182  for (size_t n = 0; n < rBoxes.size(); ++n)
2183  {
2184  const SwStartNode* pSttNd = rBoxes[ n ]->GetSttNd();
2185  aNdsCnts.push_back( pSttNd->EndOfSectionIndex() -
2186  pSttNd->GetIndex() );
2187  }
2188  }
2189  }
2190 
2191  bool bRet(false);
2192  {
2193  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
2194 
2195  SwTableFormulaUpdate aMsgHint( &rTable );
2196  aMsgHint.m_eFlags = TBL_BOXPTR;
2198 
2199  if (bVert)
2200  bRet = rTable.SplitCol( this, rBoxes, nCnt );
2201  else
2202  bRet = rTable.SplitRow( this, rBoxes, nCnt, bSameHeight );
2203 
2204  if (bRet)
2205  {
2207 
2209  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
2210  }
2211  }
2212 
2213  if( pUndo && bRet )
2214  {
2215  if( bVert )
2216  pUndo->SaveNewBoxes( *pTableNd, aTmpLst );
2217  else
2218  pUndo->SaveNewBoxes( *pTableNd, aTmpLst, rBoxes, aNdsCnts );
2219  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
2220  }
2221 
2222  return bRet;
2223 }
2224 
2226 {
2227  // Check if the current cursor's Point/Mark are inside a Table
2228  SwTableNode* pTableNd = rPam.GetNode().FindTableNode();
2229  if( !pTableNd )
2231  SwTable& rTable = pTableNd->GetTable();
2232  if( dynamic_cast<const SwDDETable*>( &rTable) != nullptr )
2235  if( !rTable.IsNewModel() )
2236  {
2237  nRet =::CheckMergeSel( rPam );
2238  if( TableMergeErr::Ok != nRet )
2239  return nRet;
2241  }
2242 
2243  // #i33394#
2245 
2248 
2249  std::unique_ptr<SwUndoTableMerge> pUndo;
2250  if (GetIDocumentUndoRedo().DoesUndo())
2251  pUndo.reset(new SwUndoTableMerge( rPam ));
2252 
2253  // Find the Boxes via the Layout
2254  SwSelBoxes aBoxes;
2255  SwSelBoxes aMerged;
2256  SwTableBox* pMergeBox;
2257 
2258  if( !rTable.PrepareMerge( rPam, aBoxes, aMerged, &pMergeBox, pUndo.get() ) )
2259  { // No cells found to merge
2261  if( pUndo )
2262  {
2263  pUndo.reset();
2264  SwUndoId nLastUndoId(SwUndoId::EMPTY);
2265  if (GetIDocumentUndoRedo().GetLastUndoInfo(nullptr, & nLastUndoId)
2266  && (SwUndoId::REDLINE == nLastUndoId))
2267  {
2268  // FIXME: why is this horrible cleanup necessary?
2269  SwUndoRedline *const pU = dynamic_cast<SwUndoRedline*>(
2271  if (pU && pU->GetRedlSaveCount())
2272  {
2273  SwEditShell *const pEditShell(GetEditShell());
2274  assert(pEditShell);
2275  ::sw::UndoRedoContext context(*this, *pEditShell);
2276  static_cast<SfxUndoAction *>(pU)->UndoWithContext(context);
2277  }
2278  delete pU;
2279  }
2280  }
2281  }
2282  else
2283  {
2284  // The PaMs need to be removed from the to-be-deleted range. Thus always place
2285  // them at the end of/on top of the Table; it's always set to the old position via
2286  // the Document Position.
2287  // For a start remember an index for the temporary position, because we cannot
2288  // access it after GetMergeSel
2289  {
2290  rPam.DeleteMark();
2291  rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2292  rPam.GetPoint()->nContent.Assign( nullptr, 0 );
2293  rPam.SetMark();
2294  rPam.DeleteMark();
2295 
2296  SwPaM* pTmp = &rPam;
2297  while( &rPam != ( pTmp = pTmp->GetNext() ))
2298  for( int i = 0; i < 2; ++i )
2299  pTmp->GetBound( static_cast<bool>(i) ) = *rPam.GetPoint();
2300 
2301  if (SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(&rPam))
2302  {
2303  // tdf#135098 update selection so rPam's m_SelectedBoxes is updated
2304  // to not contain the soon to-be-deleted SwTableBox so if the rPam
2305  // is queried via a11y it doesn't claim the deleted cell still
2306  // exists
2307  pTableCursor->NewTableSelection();
2308  }
2309  }
2310 
2311  // Merge them
2312  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
2313  aMsgHint.m_eFlags = TBL_BOXPTR;
2315 
2316  if( pTableNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo.get() ))
2317  {
2318  nRet = TableMergeErr::Ok;
2319 
2321  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
2322  if( pUndo )
2323  {
2324  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
2325  }
2326  }
2327 
2328  rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2329  rPam.Move();
2330 
2331  ::ClearFEShellTabCols(*this, nullptr);
2333  }
2335  return nRet;
2336 }
2337 
2339  : SwStartNode( rIdx, SwNodeType::Table )
2340 {
2341  m_pTable.reset(new SwTable);
2342 }
2343 
2345 {
2346  // Notify UNO wrappers
2347  GetTable().GetFrameFormat()->GetNotifier().Broadcast(SfxHint(SfxHintId::Dying));
2348  DelFrames();
2349  m_pTable->SetTableNode(this); // set this so that ~SwDDETable can read it!
2350  m_pTable.reset();
2351 }
2352 
2354 {
2355  return new SwTabFrame( *m_pTable, pSib );
2356 }
2357 
2363 {
2364  if( !GetTable().GetFrameFormat()->HasWriterListeners()) // Do we actually have Frame?
2365  return;
2366 
2367  SwFrame *pFrame;
2368  SwContentNode * pNode = rIdx.GetNode().GetContentNode();
2369 
2370  OSL_ENSURE( pNode, "No ContentNode or CopyNode and new Node is identical");
2371 
2372  bool bBefore = rIdx < GetIndex();
2373 
2374  SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
2375 
2376  while( nullptr != (pFrame = aNode2Layout.NextFrame()) )
2377  {
2378  if (pFrame->getRootFrame()->IsHideRedlines()
2379  && !pNode->IsCreateFrameWhenHidingRedlines())
2380  {
2381  continue;
2382  }
2383  SwFrame *pNew = pNode->MakeFrame( pFrame );
2384  // Will the Node receive Frames before or after?
2385  if ( bBefore )
2386  // The new one precedes me
2387  pNew->Paste( pFrame->GetUpper(), pFrame );
2388  else
2389  // The new one succeeds me
2390  pNew->Paste( pFrame->GetUpper(), pFrame->GetNext() );
2391  }
2392 }
2393 
2398 {
2399  OSL_ENSURE( pIdxBehind, "No Index" );
2400  *pIdxBehind = *this;
2401  SwNode *pNd = GetNodes().FindPrvNxtFrameNode( *pIdxBehind, EndOfSectionNode() );
2402  if( !pNd )
2403  return ;
2404 
2405  SwFrame *pFrame( nullptr );
2406  SwLayoutFrame *pUpper( nullptr );
2407  SwNode2Layout aNode2Layout( *pNd, GetIndex() );
2408  while( nullptr != (pUpper = aNode2Layout.UpperFrame( pFrame, *this )) )
2409  {
2410  if (pUpper->getRootFrame()->IsHideRedlines()
2412  {
2413  continue;
2414  }
2415  SwTabFrame* pNew = MakeFrame( pUpper );
2416  pNew->Paste( pUpper, pFrame );
2417  // #i27138#
2418  // notify accessibility paragraphs objects about changed
2419  // CONTENT_FLOWS_FROM/_TO relation.
2420  // Relation CONTENT_FLOWS_FROM for next paragraph will change
2421  // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2422  {
2423  SwViewShell* pViewShell( pNew->getRootFrame()->GetCurrShell() );
2424  if ( pViewShell && pViewShell->GetLayout() &&
2425  pViewShell->GetLayout()->IsAnyShellAccessible() )
2426  {
2428  dynamic_cast<SwTextFrame*>(pNew->FindNextCnt( true )),
2429  dynamic_cast<SwTextFrame*>(pNew->FindPrevCnt()) );
2430  }
2431  }
2432  pNew->RegistFlys();
2433  }
2434 }
2435 
2436 void SwTableNode::DelFrames(SwRootFrame const*const pLayout)
2437 {
2438  /* For a start, cut out and delete the TabFrames (which will also delete the Columns and Rows)
2439  The TabFrames are attached to the FrameFormat of the SwTable.
2440  We need to delete them in a more cumbersome way, for the Master to also delete the Follows. */
2441 
2442  SwIterator<SwTabFrame,SwFormat> aIter( *(m_pTable->GetFrameFormat()) );
2443  SwTabFrame *pFrame = aIter.First();
2444  while ( pFrame )
2445  {
2446  bool bAgain = false;
2447  {
2448  if (!pFrame->IsFollow() && (!pLayout || pLayout == pFrame->getRootFrame()))
2449  {
2450  while ( pFrame->HasFollow() )
2451  pFrame->JoinAndDelFollows();
2452  // #i27138#
2453  // notify accessibility paragraphs objects about changed
2454  // CONTENT_FLOWS_FROM/_TO relation.
2455  // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2456  // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2457  {
2458  SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
2459  if ( pViewShell && pViewShell->GetLayout() &&
2460  pViewShell->GetLayout()->IsAnyShellAccessible() )
2461  {
2463  dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
2464  dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
2465  }
2466  }
2467  pFrame->Cut();
2468  SwFrame::DestroyFrame(pFrame);
2469  bAgain = true;
2470  }
2471  }
2472  pFrame = bAgain ? aIter.First() : aIter.Next();
2473  }
2474 }
2475 
2476 void SwTableNode::SetNewTable( std::unique_ptr<SwTable> pNewTable, bool bNewFrames )
2477 {
2478  DelFrames();
2479  m_pTable->SetTableNode(this);
2480  m_pTable = std::move(pNewTable);
2481  if( bNewFrames )
2482  {
2483  SwNodeIndex aIdx( *EndOfSectionNode());
2484  GetNodes().GoNext( &aIdx );
2485  MakeOwnFrames(&aIdx);
2486  }
2487 }
2488 
2490 {
2491  SwDoc* pDoc = GetDoc();
2492  if (pDoc)
2493  {
2494  SwTable& rTable = GetTable();
2496  pDoc->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteAllTableRedlines( pDoc, rTable, true, RedlineType::Any );
2497  }
2498 }
2499 
2500 void SwDoc::GetTabCols( SwTabCols &rFill, const SwCellFrame* pBoxFrame )
2501 {
2502  OSL_ENSURE( pBoxFrame, "pBoxFrame needs to be specified!" );
2503  if( !pBoxFrame )
2504  return;
2505 
2506  SwTabFrame *pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2507  const SwTableBox* pBox = pBoxFrame->GetTabBox();
2508 
2509  // Set fixed points, LeftMin in Document coordinates, all others relative
2510  SwRectFnSet aRectFnSet(pTab);
2511  const SwPageFrame* pPage = pTab->FindPageFrame();
2512  const sal_uLong nLeftMin = aRectFnSet.GetLeft(pTab->getFrameArea()) -
2513  aRectFnSet.GetLeft(pPage->getFrameArea());
2514  const sal_uLong nRightMax = aRectFnSet.GetRight(pTab->getFrameArea()) -
2515  aRectFnSet.GetLeft(pPage->getFrameArea());
2516 
2517  rFill.SetLeftMin ( nLeftMin );
2518  rFill.SetLeft ( aRectFnSet.GetLeft(pTab->getFramePrintArea()) );
2519  rFill.SetRight ( aRectFnSet.GetRight(pTab->getFramePrintArea()));
2520  rFill.SetRightMax( nRightMax - nLeftMin );
2521 
2522  pTab->GetTable()->GetTabCols( rFill, pBox );
2523 }
2524 
2525 // Here are some little helpers used in SwDoc::GetTabRows
2526 
2527 #define ROWFUZZY 25
2528 
2529 namespace {
2530 
2531 struct FuzzyCompare
2532 {
2533  bool operator() ( long s1, long s2 ) const;
2534 };
2535 
2536 }
2537 
2538 bool FuzzyCompare::operator() ( long s1, long s2 ) const
2539 {
2540  return ( s1 < s2 && std::abs( s1 - s2 ) > ROWFUZZY );
2541 }
2542 
2543 static bool lcl_IsFrameInColumn( const SwCellFrame& rFrame, SwSelBoxes const & rBoxes )
2544 {
2545  for (size_t i = 0; i < rBoxes.size(); ++i)
2546  {
2547  if ( rFrame.GetTabBox() == rBoxes[ i ] )
2548  return true;
2549  }
2550 
2551  return false;
2552 }
2553 
2554 void SwDoc::GetTabRows( SwTabCols &rFill, const SwCellFrame* pBoxFrame )
2555 {
2556  OSL_ENSURE( pBoxFrame, "GetTabRows called without pBoxFrame" );
2557 
2558  // Make code robust:
2559  if ( !pBoxFrame )
2560  return;
2561 
2562  // #i39552# Collection of the boxes of the current
2563  // column has to be done at the beginning of this function, because
2564  // the table may be formatted in ::GetTableSel.
2565  SwDeletionChecker aDelCheck( pBoxFrame );
2566 
2567  SwSelBoxes aBoxes;
2568  const SwContentFrame* pContent = ::GetCellContent( *pBoxFrame );
2569  if ( pContent && pContent->IsTextFrame() )
2570  {
2571  const SwPosition aPos(*static_cast<const SwTextFrame*>(pContent)->GetTextNodeFirst());
2572  const SwCursor aTmpCursor( aPos, nullptr );
2573  ::GetTableSel( aTmpCursor, aBoxes, SwTableSearchType::Col );
2574  }
2575 
2576  // Make code robust:
2577  if ( aDelCheck.HasBeenDeleted() )
2578  {
2579  OSL_FAIL( "Current box has been deleted during GetTabRows()" );
2580  return;
2581  }
2582 
2583  // Make code robust:
2584  const SwTabFrame* pTab = pBoxFrame->FindTabFrame();
2585  OSL_ENSURE( pTab, "GetTabRows called without a table" );
2586  if ( !pTab )
2587  return;
2588 
2589  const SwFrame* pFrame = pTab->GetNextLayoutLeaf();
2590 
2591  // Set fixed points, LeftMin in Document coordinates, all others relative
2592  SwRectFnSet aRectFnSet(pTab);
2593  const SwPageFrame* pPage = pTab->FindPageFrame();
2594  const long nLeftMin = ( aRectFnSet.IsVert() ?
2595  pTab->GetPrtLeft() - pPage->getFrameArea().Left() :
2596  pTab->GetPrtTop() - pPage->getFrameArea().Top() );
2597  const long nLeft = aRectFnSet.IsVert() ? LONG_MAX : 0;
2598  const long nRight = aRectFnSet.GetHeight(pTab->getFramePrintArea());
2599  const long nRightMax = aRectFnSet.IsVert() ? nRight : LONG_MAX;
2600 
2601  rFill.SetLeftMin( nLeftMin );
2602  rFill.SetLeft( nLeft );
2603  rFill.SetRight( nRight );
2604  rFill.SetRightMax( nRightMax );
2605 
2606  typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap;
2607  BoundaryMap aBoundaries;
2608  BoundaryMap::iterator aIter;
2609  std::pair< long, long > aPair;
2610 
2611  typedef std::map< long, bool > HiddenMap;
2612  HiddenMap aHidden;
2613  HiddenMap::iterator aHiddenIter;
2614 
2615  while ( pFrame && pTab->IsAnLower( pFrame ) )
2616  {
2617  if ( pFrame->IsCellFrame() && pFrame->FindTabFrame() == pTab )
2618  {
2619  // upper and lower borders of current cell frame:
2620  long nUpperBorder = aRectFnSet.GetTop(pFrame->getFrameArea());
2621  long nLowerBorder = aRectFnSet.GetBottom(pFrame->getFrameArea());
2622 
2623  // get boundaries for nUpperBorder:
2624  aIter = aBoundaries.find( nUpperBorder );
2625  if ( aIter == aBoundaries.end() )
2626  {
2627  aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2628  aBoundaries[ nUpperBorder ] = aPair;
2629  }
2630 
2631  // get boundaries for nLowerBorder:
2632  aIter = aBoundaries.find( nLowerBorder );
2633  if ( aIter == aBoundaries.end() )
2634  {
2635  aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2636  }
2637  else
2638  {
2639  nLowerBorder = (*aIter).first;
2640  long nNewLowerBorderUpperBoundary = std::max( (*aIter).second.first, nUpperBorder );
2641  aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX;
2642  }
2643  aBoundaries[ nLowerBorder ] = aPair;
2644 
2645  // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2646  long nTmpVal = nUpperBorder;
2647  for ( sal_uInt8 i = 0; i < 2; ++i )
2648  {
2649  aHiddenIter = aHidden.find( nTmpVal );
2650  if ( aHiddenIter == aHidden.end() )
2651  aHidden[ nTmpVal ] = !lcl_IsFrameInColumn( *static_cast<const SwCellFrame*>(pFrame), aBoxes );
2652  else
2653  {
2654  if ( aHidden[ nTmpVal ] &&
2655  lcl_IsFrameInColumn( *static_cast<const SwCellFrame*>(pFrame), aBoxes ) )
2656  aHidden[ nTmpVal ] = false;
2657  }
2658  nTmpVal = nLowerBorder;
2659  }
2660  }
2661 
2662  pFrame = pFrame->GetNextLayoutLeaf();
2663  }
2664 
2665  // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2666  size_t nIdx = 0;
2667  for ( const auto& rEntry : aBoundaries )
2668  {
2669  const long nTabTop = aRectFnSet.GetPrtTop(*pTab);
2670  const long nKey = aRectFnSet.YDiff( rEntry.first, nTabTop );
2671  const std::pair< long, long > aTmpPair = rEntry.second;
2672  const long nFirst = aRectFnSet.YDiff( aTmpPair.first, nTabTop );
2673  const long nSecond = aTmpPair.second;
2674 
2675  aHiddenIter = aHidden.find( rEntry.first );
2676  const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second;
2677  rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ );
2678  }
2679 
2680  // delete first and last entry
2681  OSL_ENSURE( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" );
2682  // #i60818# There may be only one entry in rFill. Make
2683  // code robust by checking count of rFill.
2684  if ( rFill.Count() ) rFill.Remove( 0 );
2685  if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 );
2686  rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() );
2687 }
2688 
2689 void SwDoc::SetTabCols( const SwTabCols &rNew, bool bCurRowOnly,
2690  const SwCellFrame* pBoxFrame )
2691 {
2692  const SwTableBox* pBox = nullptr;
2693  SwTabFrame *pTab = nullptr;
2694 
2695  if( pBoxFrame )
2696  {
2697  pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2698  pBox = pBoxFrame->GetTabBox();
2699  }
2700  else
2701  {
2702  OSL_ENSURE( false, "must specify pBoxFrame" );
2703  return ;
2704  }
2705 
2706  // If the Table is still using relative values (USHRT_MAX)
2707  // we need to switch to absolute ones.
2708  SwTable& rTab = *pTab->GetTable();
2709  const SwFormatFrameSize& rTableFrameSz = rTab.GetFrameFormat()->GetFrameSize();
2710  SwRectFnSet aRectFnSet(pTab);
2711  // #i17174# - With fix for #i9040# the shadow size is taken
2712  // from the table width. Thus, add its left and right size to current table
2713  // printing area width in order to get the correct table size attribute.
2714  SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
2715  {
2716  SvxShadowItem aShadow( rTab.GetFrameFormat()->GetShadow() );
2717  nPrtWidth += aShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ) +
2718  aShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT );
2719  }
2720  if( nPrtWidth != rTableFrameSz.GetWidth() )
2721  {
2722  SwFormatFrameSize aSz( rTableFrameSz );
2723  aSz.SetWidth( nPrtWidth );
2724  rTab.GetFrameFormat()->SetFormatAttr( aSz );
2725  }
2726 
2727  SwTabCols aOld( rNew.Count() );
2728 
2729  const SwPageFrame* pPage = pTab->FindPageFrame();
2730  const sal_uLong nLeftMin = aRectFnSet.GetLeft(pTab->getFrameArea()) -
2731  aRectFnSet.GetLeft(pPage->getFrameArea());
2732  const sal_uLong nRightMax = aRectFnSet.GetRight(pTab->getFrameArea()) -
2733  aRectFnSet.GetLeft(pPage->getFrameArea());
2734 
2735  // Set fixed points, LeftMin in Document coordinates, all others relative
2736  aOld.SetLeftMin ( nLeftMin );
2737  aOld.SetLeft ( aRectFnSet.GetLeft(pTab->getFramePrintArea()) );
2738  aOld.SetRight ( aRectFnSet.GetRight(pTab->getFramePrintArea()));
2739  aOld.SetRightMax( nRightMax - nLeftMin );
2740 
2741  rTab.GetTabCols( aOld, pBox );
2742  SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly );
2743 }
2744 
2745 void SwDoc::SetTabRows( const SwTabCols &rNew, bool bCurColOnly,
2746  const SwCellFrame* pBoxFrame )
2747 {
2748  SwTabFrame *pTab = nullptr;
2749 
2750  if( pBoxFrame )
2751  {
2752  pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2753  }
2754  else
2755  {
2756  OSL_ENSURE( false, "must specify pBoxFrame" );
2757  return ;
2758  }
2759 
2760  // If the Table is still using relative values (USHRT_MAX)
2761  // we need to switch to absolute ones.
2762  SwRectFnSet aRectFnSet(pTab);
2763  SwTabCols aOld( rNew.Count() );
2764 
2765  // Set fixed points, LeftMin in Document coordinates, all others relative
2766  const SwPageFrame* pPage = pTab->FindPageFrame();
2767 
2768  aOld.SetRight( aRectFnSet.GetHeight(pTab->getFramePrintArea()) );
2769  long nLeftMin;
2770  if ( aRectFnSet.IsVert() )
2771  {
2772  nLeftMin = pTab->GetPrtLeft() - pPage->getFrameArea().Left();
2773  aOld.SetLeft ( LONG_MAX );
2774  aOld.SetRightMax( aOld.GetRight() );
2775 
2776  }
2777  else
2778  {
2779  nLeftMin = pTab->GetPrtTop() - pPage->getFrameArea().Top();
2780  aOld.SetLeft ( 0 );
2781  aOld.SetRightMax( LONG_MAX );
2782  }
2783  aOld.SetLeftMin ( nLeftMin );
2784 
2785  GetTabRows( aOld, pBoxFrame );
2786 
2788 
2789  // check for differences between aOld and rNew:
2790  const size_t nCount = rNew.Count();
2791  const SwTable* pTable = pTab->GetTable();
2792  OSL_ENSURE( pTable, "My colleague told me, this couldn't happen" );
2793 
2794  for ( size_t i = 0; i <= nCount; ++i )
2795  {
2796  const size_t nIdxStt = aRectFnSet.IsVert() ? nCount - i : i - 1;
2797  const size_t nIdxEnd = aRectFnSet.IsVert() ? nCount - i - 1 : i;
2798 
2799  const long nOldRowStart = i == 0 ? 0 : aOld[ nIdxStt ];
2800  const long nOldRowEnd = i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ];
2801  const long nOldRowHeight = nOldRowEnd - nOldRowStart;
2802 
2803  const long nNewRowStart = i == 0 ? 0 : rNew[ nIdxStt ];
2804  const long nNewRowEnd = i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ];
2805  const long nNewRowHeight = nNewRowEnd - nNewRowStart;
2806 
2807  const long nDiff = nNewRowHeight - nOldRowHeight;
2808  if ( std::abs( nDiff ) >= ROWFUZZY )
2809  {
2810  // For the old table model pTextFrame and pLine will be set for every box.
2811  // For the new table model pTextFrame will be set if the box is not covered,
2812  // but the pLine will be set if the box is not an overlapping box
2813  // In the new table model the row height can be adjusted,
2814  // when both variables are set.
2815  const SwTextFrame* pTextFrame = nullptr;
2816  const SwTableLine* pLine = nullptr;
2817 
2818  // Iterate over all SwCellFrames with Bottom = nOldPos
2819  const SwFrame* pFrame = pTab->GetNextLayoutLeaf();
2820  while ( pFrame && pTab->IsAnLower( pFrame ) )
2821  {
2822  if ( pFrame->IsCellFrame() && pFrame->FindTabFrame() == pTab )
2823  {
2824  const long nLowerBorder = aRectFnSet.GetBottom(pFrame->getFrameArea());
2825  const sal_uLong nTabTop = aRectFnSet.GetPrtTop(*pTab);
2826  if ( std::abs( aRectFnSet.YInc( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY )
2827  {
2828  if ( !bCurColOnly || pFrame == pBoxFrame )
2829  {
2830  const SwFrame* pContent = ::GetCellContent( static_cast<const SwCellFrame&>(*pFrame) );
2831 
2832  if ( pContent && pContent->IsTextFrame() )
2833  {
2834  const SwTableBox* pBox = static_cast<const SwCellFrame*>(pFrame)->GetTabBox();
2835  const long nRowSpan = pBox->getRowSpan();
2836  if( nRowSpan > 0 ) // Not overlapped
2837  pTextFrame = static_cast<const SwTextFrame*>(pContent);
2838  if( nRowSpan < 2 ) // Not overlapping for row height
2839  pLine = pBox->GetUpper();
2840  if( pLine && pTextFrame ) // always for old table model
2841  {
2842  // The new row height must not to be calculated from an overlapping box
2843  SwFormatFrameSize aNew( pLine->GetFrameFormat()->GetFrameSize() );
2844  const long nNewSize = aRectFnSet.GetHeight(pFrame->getFrameArea()) + nDiff;
2845  if( nNewSize != aNew.GetHeight() )
2846  {
2847  aNew.SetHeight( nNewSize );
2848  if ( SwFrameSize::Variable == aNew.GetHeightSizeType() )
2849  aNew.SetHeightSizeType( SwFrameSize::Minimum );
2850  // This position must not be in an overlapped box
2851  const SwPosition aPos(*static_cast<const SwTextFrame*>(pContent)->GetTextNodeFirst());
2852  const SwCursor aTmpCursor( aPos, nullptr );
2853  SetRowHeight( aTmpCursor, aNew );
2854  // For the new table model we're done, for the old one
2855  // there might be another (sub)row to adjust...
2856  if( pTable->IsNewModel() )
2857  break;
2858  }
2859  pLine = nullptr;
2860  }
2861  }
2862  }
2863  }
2864  }
2865  pFrame = pFrame->GetNextLayoutLeaf();
2866  }
2867  }
2868  }
2869 
2871 
2872  ::ClearFEShellTabCols(*this, nullptr);
2873 }
2874 
2878 void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld,
2879  const SwTableBox *pStart, bool bCurRowOnly )
2880 {
2881  if (GetIDocumentUndoRedo().DoesUndo())
2882  {
2884  std::make_unique<SwUndoAttrTable>( *rTab.GetTableNode(), true ));
2885  }
2886  rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
2887  ::ClearFEShellTabCols(*this, nullptr);
2890 }
2891 
2892 void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet )
2893 {
2894  if( nSet == rTable.GetRowsToRepeat() )
2895  return;
2896 
2898  {
2900  std::make_unique<SwUndoTableHeadline>(rTable, rTable.GetRowsToRepeat(), nSet) );
2901  }
2902 
2904  rTable.SetRowsToRepeat( nSet );
2905  rTable.GetFrameFormat()->ModifyNotification( &aChg, &aChg );
2907 }
2908 
2910 {
2911  if( m_pHistory )
2913 }
2914 
2916 {
2917  m_aPositionArr.push_back(m_nWidth);
2918  SwTableBox* p = const_cast<SwTableBox*>(&rBox);
2919  m_Boxes.push_back(p);
2920  m_nWidth = m_nWidth + static_cast<sal_uInt16>(rBox.GetFrameFormat()->GetFrameSize().GetWidth());
2921 }
2922 
2924 {
2925  const SwTableBox* pRet = nullptr;
2926 
2927  if( !m_aPositionArr.empty() )
2928  {
2929  std::vector<sal_uInt16>::size_type n;
2930  for( n = 0; n < m_aPositionArr.size(); ++n )
2931  if( m_aPositionArr[ n ] == m_nWidth )
2932  break;
2933  else if( m_aPositionArr[ n ] > m_nWidth )
2934  {
2935  if( n )
2936  --n;
2937  break;
2938  }
2939 
2940  if( n >= m_aPositionArr.size() )
2941  --n;
2942 
2943  m_nWidth = m_nWidth + static_cast<sal_uInt16>(rBox.GetFrameFormat()->GetFrameSize().GetWidth());
2944  pRet = m_Boxes[ n ];
2945  }
2946  return pRet;
2947 }
2948 
2949 bool SwCollectTableLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth )
2950 {
2951  if( !m_aPositionArr.empty() )
2952  {
2953  std::vector<sal_uInt16>::size_type n;
2954  for( n = 0; n < m_aPositionArr.size(); ++n )
2955  {
2956  if( m_aPositionArr[ n ] == nOffset )
2957  break;
2958  else if( m_aPositionArr[ n ] > nOffset )
2959  {
2960  if( n )
2961  --n;
2962  break;
2963  }
2964  }
2965 
2966  m_aPositionArr.erase( m_aPositionArr.begin(), m_aPositionArr.begin() + n );
2967  m_Boxes.erase(m_Boxes.begin(), m_Boxes.begin() + n);
2968 
2969  size_t nArrSize = m_aPositionArr.size();
2970  if (nArrSize)
2971  {
2972  if (nOldWidth == 0)
2973  throw o3tl::divide_by_zero();
2974 
2975  // Adapt the positions to the new Size
2976  for( n = 0; n < nArrSize; ++n )
2977  {
2978  sal_uLong nSize = m_nWidth;
2979  nSize *= ( m_aPositionArr[ n ] - nOffset );
2980  nSize /= nOldWidth;
2981  m_aPositionArr[ n ] = sal_uInt16( nSize );
2982  }
2983  }
2984  }
2985  return !m_aPositionArr.empty();
2986 }
2987 
2988 bool sw_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
2989 {
2990  SwCollectTableLineBoxes* pSplPara = static_cast<SwCollectTableLineBoxes*>(pPara);
2991  if( pSplPara->IsGetValues() )
2992  for( const auto& rpBox : const_cast<SwTableLine*>(rpLine)->GetTabBoxes() )
2993  sw_Box_CollectBox(rpBox, pSplPara );
2994  else
2995  for( auto& rpBox : const_cast<SwTableLine*>(rpLine)->GetTabBoxes() )
2996  sw_BoxSetSplitBoxFormats(rpBox, pSplPara );
2997  return true;
2998 }
2999 
3001 {
3002  auto nLen = pBox->GetTabLines().size();
3003  if( nLen )
3004  {
3005  // Continue with the actual Line
3006  if( pSplPara->IsGetFromTop() )
3007  nLen = 0;
3008  else
3009  --nLen;
3010 
3011  const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3012  sw_Line_CollectBox( pLn, pSplPara );
3013  }
3014  else
3015  pSplPara->AddBox( *pBox );
3016 }
3017 
3019 {
3020  auto nLen = pBox->GetTabLines().size();
3021  if( nLen )
3022  {
3023  // Continue with the actual Line
3024  if( pSplPara->IsGetFromTop() )
3025  nLen = 0;
3026  else
3027  --nLen;
3028 
3029  const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3030  sw_Line_CollectBox( pLn, pSplPara );
3031  }
3032  else
3033  {
3034  const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *pBox );
3035  SwFrameFormat* pFormat = pSrcBox->GetFrameFormat();
3036 
3037  if( SplitTable_HeadlineOption::BorderCopy == pSplPara->GetMode() )
3038  {
3039  const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
3040  if( !rBoxItem.GetTop() )
3041  {
3042  SvxBoxItem aNew( rBoxItem );
3043  aNew.SetLine( pFormat->GetBox().GetBottom(), SvxBoxItemLine::TOP );
3044  if( aNew != rBoxItem )
3045  pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
3046  }
3047  }
3048  else
3049  {
3050  sal_uInt16 const aTableSplitBoxSetRange[] {
3055  0 };
3056 
3057  SfxItemSet aTmpSet( pFormat->GetDoc()->GetAttrPool(),
3058  aTableSplitBoxSetRange );
3059  aTmpSet.Put( pFormat->GetAttrSet() );
3060  if( aTmpSet.Count() )
3061  pBox->ClaimFrameFormat()->SetFormatAttr( aTmpSet );
3062 
3064  {
3065  SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
3066  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3067  if( !pCNd )
3068  pCNd = aIdx.GetNodes().GoNext( &aIdx );
3069  aIdx = *pBox->GetSttNd();
3070  SwContentNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );
3071 
3072  // If the Node is alone in the Section
3073  if( 2 == pDNd->EndOfSectionIndex() -
3074  pDNd->StartOfSectionIndex() )
3075  {
3076  pSplPara->AddToUndoHistory( *pDNd );
3077  pDNd->ChgFormatColl( pCNd->GetFormatColl() );
3078  }
3079  }
3080 
3081  // note conditional template
3082  pBox->GetSttNd()->CheckSectionCondColl();
3083  }
3084  }
3085 }
3086 
3097  bool bCalcNewSize )
3098 {
3099  SwNode* pNd = &rPos.nNode.GetNode();
3100  SwTableNode* pTNd = pNd->FindTableNode();
3101  if( !pTNd || pNd->IsTableNode() )
3102  return false;
3103 
3104  if( dynamic_cast<const SwDDETable*>( &pTNd->GetTable() ) != nullptr)
3105  return false;
3106 
3107  SwTable& rTable = pTNd->GetTable();
3108  rTable.SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
3109 
3110  SwTableFormulaUpdate aMsgHint( &rTable );
3111 
3112  SwHistory aHistory;
3113  if (GetIDocumentUndoRedo().DoesUndo())
3114  {
3115  aMsgHint.m_pHistory = &aHistory;
3116  }
3117 
3118  {
3119  sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3120 
3121  // Find top-level Line
3122  SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3123  if( pBox )
3124  {
3125  SwTableLine* pLine = pBox->GetUpper();
3126  while( pLine->GetUpper() )
3127  pLine = pLine->GetUpper()->GetUpper();
3128 
3129  // pLine contains the top-level Line now
3130  aMsgHint.m_nSplitLine = rTable.GetTabLines().GetPos( pLine );
3131  }
3132 
3133  OUString sNewTableNm( GetUniqueTableName() );
3134  aMsgHint.m_aData.pNewTableNm = &sNewTableNm;
3135  aMsgHint.m_eFlags = TBL_SPLITTBL;
3137  }
3138 
3139  // Find Lines for the Layout update
3140  FndBox_ aFndBox( nullptr, nullptr );
3141  aFndBox.SetTableLines( rTable );
3142  aFndBox.DelFrames( rTable );
3143 
3144  SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, false, bCalcNewSize );
3145 
3146  if( pNew )
3147  {
3148  std::unique_ptr<SwSaveRowSpan> pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTable.GetTabLines().size() );
3149  SwUndoSplitTable* pUndo = nullptr;
3151  {
3152  pUndo = new SwUndoSplitTable(
3153  *pNew, std::move(pSaveRowSp), eHdlnMode, bCalcNewSize);
3154  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3155  if( aHistory.Count() )
3156  pUndo->SaveFormula( aHistory );
3157  }
3158 
3159  switch( eHdlnMode )
3160  {
3161  // Set the lower Border of the preceding Line to
3162  // the upper Border of the current one
3164  {
3165  SwCollectTableLineBoxes aPara( false, eHdlnMode );
3166  SwTableLine* pLn = rTable.GetTabLines()[
3167  rTable.GetTabLines().size() - 1 ];
3168  for( const auto& rpBox : pLn->GetTabBoxes() )
3169  sw_Box_CollectBox(rpBox, &aPara );
3170 
3171  aPara.SetValues( true );
3172  pLn = pNew->GetTable().GetTabLines()[ 0 ];
3173  for( auto& rpBox : pLn->GetTabBoxes() )
3174  sw_BoxSetSplitBoxFormats(rpBox, &aPara );
3175 
3176  // Switch off repeating Header
3177  pNew->GetTable().SetRowsToRepeat( 0 );
3178  }
3179  break;
3180 
3181  // Take over the Attributes of the first Line to the new one
3184  {
3185  SwHistory* pHst = nullptr;
3186  if( SplitTable_HeadlineOption::BoxAttrAllCopy == eHdlnMode && pUndo )
3187  pHst = pUndo->GetHistory();
3188 
3189  SwCollectTableLineBoxes aPara( true, eHdlnMode, pHst );
3190  SwTableLine* pLn = rTable.GetTabLines()[ 0 ];
3191  for( const auto& rpBox : pLn->GetTabBoxes() )
3192  sw_Box_CollectBox(rpBox, &aPara );
3193 
3194  aPara.SetValues( true );
3195  pLn = pNew->GetTable().GetTabLines()[ 0 ];
3196  for( auto& rpBox : pLn->GetTabBoxes() )
3197  sw_BoxSetSplitBoxFormats(rpBox, &aPara );
3198  }
3199  break;
3200 
3202  rTable.CopyHeadlineIntoTable( *pNew );
3203  if( pUndo )
3204  pUndo->SetTableNodeOffset( pNew->GetIndex() );
3205  break;
3206 
3208  // Switch off repeating the Header
3209  pNew->GetTable().SetRowsToRepeat( 0 );
3210  break;
3211  }
3212 
3213  // And insert Frames
3214  SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() );
3215  GetNodes().GoNext( &aNdIdx ); // To the next ContentNode
3216  pNew->MakeOwnFrames( &aNdIdx );
3217 
3218  // Insert a paragraph between the Table
3219  GetNodes().MakeTextNode( SwNodeIndex( *pNew ),
3220  getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
3221  }
3222 
3223  // Update Layout
3224  aFndBox.MakeFrames( rTable );
3225 
3226  // TL_CHART2: need to inform chart of probably changed cell names
3227  UpdateCharts( rTable.GetFrameFormat()->GetName() );
3228 
3229  // update table style formatting of both the tables
3232 
3233  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3234 
3235  return nullptr != pNew;
3236 }
3237 
3238 static bool lcl_ChgTableSize( SwTable& rTable )
3239 {
3240  // The Attribute must not be set via the Modify or else all Boxes are
3241  // set back to 0.
3242  // So lock the Format.
3243  SwFrameFormat* pFormat = rTable.GetFrameFormat();
3244  SwFormatFrameSize aTableMaxSz( pFormat->GetFrameSize() );
3245 
3246  if( USHRT_MAX == aTableMaxSz.GetWidth() )
3247  return false;
3248 
3249  bool bLocked = pFormat->IsModifyLocked();
3250  pFormat->LockModify();
3251 
3252  aTableMaxSz.SetWidth( 0 );
3253 
3254  SwTableLines& rLns = rTable.GetTabLines();
3255  for( auto pLn : rLns )
3256  {
3257  SwTwips nMaxLnWidth = 0;
3258  SwTableBoxes& rBoxes = pLn->GetTabBoxes();
3259  for( auto pBox : rBoxes )
3260  nMaxLnWidth += pBox->GetFrameFormat()->GetFrameSize().GetWidth();
3261 
3262  if( nMaxLnWidth > aTableMaxSz.GetWidth() )
3263  aTableMaxSz.SetWidth( nMaxLnWidth );
3264  }
3265  pFormat->SetFormatAttr( aTableMaxSz );
3266  if( !bLocked ) // Release the Lock if appropriate
3267  pFormat->UnlockModify();
3268 
3269  return true;
3270 }
3271 
3272 namespace {
3273 
3274 class SplitTable_Para
3275 {
3276  std::map<SwFrameFormat const*, SwFrameFormat*> m_aSrcDestMap;
3277  SwTableNode* m_pNewTableNode;
3278  SwTable& m_rOldTable;
3279 
3280 public:
3281  SplitTable_Para(SwTableNode* pNew, SwTable& rOld)
3282  : m_aSrcDestMap()
3283  , m_pNewTableNode(pNew)
3284  , m_rOldTable(rOld)
3285  {}
3286  SwFrameFormat* GetDestFormat( SwFrameFormat* pSrcFormat ) const
3287  {
3288  auto it = m_aSrcDestMap.find(pSrcFormat);
3289  return it == m_aSrcDestMap.end() ? nullptr : it->second;
3290  }
3291 
3292  void InsertSrcDest( SwFrameFormat const * pSrcFormat, SwFrameFormat* pDestFormat )
3293  {
3294  m_aSrcDestMap[pSrcFormat] = pDestFormat;
3295  }
3296 
3297  void ChgBox( SwTableBox* pBox )
3298  {
3299  m_rOldTable.GetTabSortBoxes().erase(pBox);
3300  m_pNewTableNode->GetTable().GetTabSortBoxes().insert(pBox);
3301  }
3302 };
3303 
3304 }
3305 
3306 static void lcl_SplitTable_CpyBox( SwTableBox* pBox, SplitTable_Para* pPara );
3307 
3308 static void lcl_SplitTable_CpyLine( SwTableLine* pLn, SplitTable_Para* pPara )
3309 {
3310  SwFrameFormat *pSrcFormat = pLn->GetFrameFormat();
3311  SwTableLineFormat* pDestFormat = static_cast<SwTableLineFormat*>( pPara->GetDestFormat( pSrcFormat ) );
3312  if( pDestFormat == nullptr )
3313  {
3314  pPara->InsertSrcDest( pSrcFormat, pLn->ClaimFrameFormat() );
3315  }
3316  else
3317  pLn->ChgFrameFormat( pDestFormat );
3318 
3319  for( auto& rpBox : pLn->GetTabBoxes() )
3320  lcl_SplitTable_CpyBox(rpBox, pPara );
3321 }
3322 
3323 static void lcl_SplitTable_CpyBox( SwTableBox* pBox, SplitTable_Para* pPara )
3324 {
3325  SwFrameFormat *pSrcFormat = pBox->GetFrameFormat();
3326  SwTableBoxFormat* pDestFormat = static_cast<SwTableBoxFormat*>(pPara->GetDestFormat( pSrcFormat ));
3327  if( pDestFormat == nullptr )
3328  {
3329  pPara->InsertSrcDest( pSrcFormat, pBox->ClaimFrameFormat() );
3330  }
3331  else
3332  pBox->ChgFrameFormat( pDestFormat );
3333 
3334  if( pBox->GetSttNd() )
3335  pPara->ChgBox( pBox );
3336  else
3337  for( SwTableLine* pLine : pBox->GetTabLines() )
3338  lcl_SplitTable_CpyLine( pLine, pPara );
3339 }
3340 
3341 SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, bool bAfter,
3342  bool bCalcNewSize )
3343 {
3344  SwNode* pNd = &rPos.GetNode();
3345  SwTableNode* pTNd = pNd->FindTableNode();
3346  if( !pTNd || pNd->IsTableNode() )
3347  return nullptr;
3348 
3349  sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3350 
3351  // Find this Box/top-level line
3352  SwTable& rTable = pTNd->GetTable();
3353  SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3354  if( !pBox )
3355  return nullptr;
3356 
3357  SwTableLine* pLine = pBox->GetUpper();
3358  while( pLine->GetUpper() )
3359  pLine = pLine->GetUpper()->GetUpper();
3360 
3361  // pLine now contains the top-level line
3362  sal_uInt16 nLinePos = rTable.GetTabLines().GetPos( pLine );
3363  if( USHRT_MAX == nLinePos ||
3364  ( bAfter ? ++nLinePos >= rTable.GetTabLines().size() : !nLinePos ))
3365  return nullptr; // Not found or last Line!
3366 
3367  // Find the first Box of the succeeding Line
3368  SwTableLine* pNextLine = rTable.GetTabLines()[ nLinePos ];
3369  pBox = pNextLine->GetTabBoxes()[0];
3370  while( !pBox->GetSttNd() )
3371  pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
3372 
3373  // Insert an EndNode and TableNode into the Nodes Array
3374  SwTableNode * pNewTableNd;
3375  {
3376  SwEndNode* pOldTableEndNd = pTNd->EndOfSectionNode()->GetEndNode();
3377  assert(pOldTableEndNd && "Where is the EndNode?");
3378 
3379  SwNodeIndex aIdx( *pBox->GetSttNd() );
3380  new SwEndNode( aIdx, *pTNd );
3381  pNewTableNd = new SwTableNode( aIdx );
3382  pNewTableNd->GetTable().SetTableModel( rTable.IsNewModel() );
3383 
3384  pOldTableEndNd->m_pStartOfSection = pNewTableNd;
3385  pNewTableNd->m_pEndOfSection = pOldTableEndNd;
3386 
3387  SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3388  do {
3389  OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3390  pBoxNd->m_pStartOfSection = pNewTableNd;
3391  pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3392  } while( pBoxNd != pOldTableEndNd );
3393  }
3394 
3395  {
3396  // Move the Lines
3397  SwTable& rNewTable = pNewTableNd->GetTable();
3398  rNewTable.GetTabLines().insert( rNewTable.GetTabLines().begin(),
3399  rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3400 
3401  /* From the back (bottom right) to the front (top left) deregister all Boxes from the
3402  Chart Data Provider. The Modify event is triggered in the calling function.
3403  TL_CHART2: */
3405  if( pPCD )
3406  {
3407  for (SwTableLines::size_type k = nLinePos; k < rTable.GetTabLines().size(); ++k)
3408  {
3409  const SwTableLines::size_type nLineIdx = (rTable.GetTabLines().size() - 1) - k + nLinePos;
3410  const SwTableBoxes::size_type nBoxCnt = rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes().size();
3411  for (SwTableBoxes::size_type j = 0; j < nBoxCnt; ++j)
3412  {
3413  const SwTableBoxes::size_type nIdx = nBoxCnt - 1 - j;
3414  pPCD->DeleteBox( &rTable, *rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] );
3415  }
3416  }
3417  }
3418 
3419  // Delete
3420  sal_uInt16 nDeleted = rTable.GetTabLines().size() - nLinePos;
3421  rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3422 
3423  // Move the affected Boxes. Make the Formats unique and correct the StartNodes
3424  SplitTable_Para aPara( pNewTableNd, rTable );
3425  for( SwTableLine* pNewLine : rNewTable.GetTabLines() )
3426  lcl_SplitTable_CpyLine( pNewLine, &aPara );
3427  rTable.CleanUpBottomRowSpan( nDeleted );
3428  }
3429 
3430  {
3431  // Copy the Table FrameFormat
3432  SwFrameFormat* pOldTableFormat = rTable.GetFrameFormat();
3433  SwFrameFormat* pNewTableFormat = pOldTableFormat->GetDoc()->MakeTableFrameFormat(
3434  pOldTableFormat->GetDoc()->GetUniqueTableName(),
3435  pOldTableFormat->GetDoc()->GetDfltFrameFormat() );
3436 
3437  *pNewTableFormat = *pOldTableFormat;
3438  pNewTableNd->GetTable().RegisterToFormat( *pNewTableFormat );
3439 
3440  pNewTableNd->GetTable().SetTableStyleName(rTable.GetTableStyleName());
3441 
3442  // Calculate a new Size?
3443  // lcl_ChgTableSize: Only execute the second call if the first call was
3444  // successful, thus has an absolute Size
3445  if( bCalcNewSize && lcl_ChgTableSize( rTable ) )
3446  lcl_ChgTableSize( pNewTableNd->GetTable() );
3447  }
3448 
3449  // TL_CHART2: need to inform chart of probably changed cell names
3450  rTable.UpdateCharts();
3451 
3452  return pNewTableNd; // That's it!
3453 }
3454 
3461 bool SwDoc::MergeTable( const SwPosition& rPos, bool bWithPrev, sal_uInt16 nMode )
3462 {
3463  SwTableNode* pTableNd = rPos.nNode.GetNode().FindTableNode(), *pDelTableNd;
3464  if( !pTableNd )
3465  return false;
3466 
3467  SwNodes& rNds = GetNodes();
3468  if( bWithPrev )
3469  pDelTableNd = rNds[ pTableNd->GetIndex() - 1 ]->FindTableNode();
3470  else
3471  pDelTableNd = rNds[ pTableNd->EndOfSectionIndex() + 1 ]->GetTableNode();
3472  if( !pDelTableNd )
3473  return false;
3474 
3475  if( dynamic_cast<const SwDDETable*>( &pTableNd->GetTable() ) != nullptr ||
3476  dynamic_cast<const SwDDETable*>( &pDelTableNd->GetTable() ) != nullptr)
3477  return false;
3478 
3479  // Delete HTML Layout
3480  pTableNd->GetTable().SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3481  pDelTableNd->GetTable().SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3482 
3483  // Both Tables are present; we can start
3484  SwUndoMergeTable* pUndo = nullptr;
3485  std::unique_ptr<SwHistory> pHistory;
3486  if (GetIDocumentUndoRedo().DoesUndo())
3487  {
3488  pUndo = new SwUndoMergeTable( *pTableNd, *pDelTableNd, bWithPrev, nMode );
3489  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3490  pHistory.reset(new SwHistory);
3491  }
3492 
3493  // Adapt all "TableFormulas"
3494  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3495  aMsgHint.m_aData.pDelTable = &pDelTableNd->GetTable();
3496  aMsgHint.m_eFlags = TBL_MERGETBL;
3497  aMsgHint.m_pHistory = pHistory.get();
3499 
3500  // The actual merge
3501  SwNodeIndex aIdx( bWithPrev ? *pTableNd : *pDelTableNd );
3502  bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode );
3503 
3504  if( pHistory )
3505  {
3506  if( pHistory->Count() )
3507  pUndo->SaveFormula( *pHistory );
3508  pHistory.reset();
3509  }
3510  if( bRet )
3511  {
3513 
3515  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3516  }
3517  return bRet;
3518 }
3519 
3520 bool SwNodes::MergeTable( const SwNodeIndex& rPos, bool bWithPrev,
3521  sal_uInt16 nMode )
3522 {
3523  SwTableNode* pDelTableNd = rPos.GetNode().GetTableNode();
3524  OSL_ENSURE( pDelTableNd, "Where did the TableNode go?" );
3525 
3526  SwTableNode* pTableNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode();
3527  OSL_ENSURE( pTableNd, "Where did the TableNode go?" );
3528 
3529  if( !pDelTableNd || !pTableNd )
3530  return false;
3531 
3532  pDelTableNd->DelFrames();
3533 
3534  SwTable& rDelTable = pDelTableNd->GetTable();
3535  SwTable& rTable = pTableNd->GetTable();
3536 
3537  // Find Lines for the Layout update
3538  FndBox_ aFndBox( nullptr, nullptr );
3539  aFndBox.SetTableLines( rTable );
3540  aFndBox.DelFrames( rTable );
3541 
3542  // TL_CHART2:
3543  // tell the charts about the table to be deleted and have them use their own data
3545 
3546  // Sync the TableFormat's Width
3547  {
3548  const SwFormatFrameSize& rTableSz = rTable.GetFrameFormat()->GetFrameSize();
3549  const SwFormatFrameSize& rDelTableSz = rDelTable.GetFrameFormat()->GetFrameSize();
3550  if( rTableSz != rDelTableSz )
3551  {
3552  // The needs correction
3553  if( bWithPrev )
3554  rDelTable.GetFrameFormat()->SetFormatAttr( rTableSz );
3555  else
3556  rTable.GetFrameFormat()->SetFormatAttr( rDelTableSz );
3557  }
3558  }
3559 
3560  if( !bWithPrev )
3561  {
3562  // Transfer all Attributes of the succeeding Table to the preceding one
3563  // We do this, because the succeeding one is deleted when deleting the Node
3564  rTable.SetRowsToRepeat( rDelTable.GetRowsToRepeat() );
3565  rTable.SetTableChgMode( rDelTable.GetTableChgMode() );
3566 
3567  rTable.GetFrameFormat()->LockModify();
3568  *rTable.GetFrameFormat() = *rDelTable.GetFrameFormat();
3569  // Also switch the Name
3570  rTable.GetFrameFormat()->SetName( rDelTable.GetFrameFormat()->GetName() );
3571  rTable.GetFrameFormat()->UnlockModify();
3572  }
3573 
3574  // Move the Lines and Boxes
3575  SwTableLines::size_type nOldSize = rTable.GetTabLines().size();
3576  rTable.GetTabLines().insert( rTable.GetTabLines().begin() + nOldSize,
3577  rDelTable.GetTabLines().begin(), rDelTable.GetTabLines().end() );
3578  rDelTable.GetTabLines().clear();
3579 
3580  rTable.GetTabSortBoxes().insert( rDelTable.GetTabSortBoxes() );
3581  rDelTable.GetTabSortBoxes().clear();
3582 
3583  // The preceding Table always remains, while the succeeding one is deleted
3584  SwEndNode* pTableEndNd = pDelTableNd->EndOfSectionNode();
3585  pTableNd->m_pEndOfSection = pTableEndNd;
3586 
3587  SwNodeIndex aIdx( *pDelTableNd, 1 );
3588 
3589  SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3590  do {
3591  OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3592  pBoxNd->m_pStartOfSection = pTableNd;
3593  pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3594  } while( pBoxNd != pTableEndNd );
3595  pBoxNd->m_pStartOfSection = pTableNd;
3596 
3597  aIdx -= 2;
3598  DelNodes( aIdx, 2 );
3599 
3600  // tweak the conditional styles at the first inserted Line
3601  const SwTableLine* pFirstLn = rTable.GetTabLines()[ nOldSize ];
3602  if( 1 == nMode )
3603  {
3604  // Set Header Template in the Line and save in the History
3605  // if needed for Undo!
3606  }
3607  sw_LineSetHeadCondColl( pFirstLn );
3608 
3609  // Clean up the Borders
3610  if( nOldSize )
3611  {
3612  SwGCLineBorder aPara( rTable );
3613  aPara.nLinePos = --nOldSize;
3614  pFirstLn = rTable.GetTabLines()[ nOldSize ];
3615  sw_GC_Line_Border( pFirstLn, &aPara );
3616  }
3617 
3618  // Update Layout
3619  aFndBox.MakeFrames( rTable );
3620 
3621  return true;
3622 }
3623 
3624 namespace {
3625 
3626 // Use the PtrArray's ForEach method
3627 struct SetAFormatTabPara
3628 {
3629  SwTableAutoFormat& rTableFormat;
3630  SwUndoTableAutoFormat* pUndo;
3631  sal_uInt16 nEndBox, nCurBox;
3632  sal_uInt8 nAFormatLine, nAFormatBox;
3633  bool bSingleRowTable;
3634 
3635  explicit SetAFormatTabPara( const SwTableAutoFormat& rNew )
3636  : rTableFormat( const_cast<SwTableAutoFormat&>(rNew) ), pUndo( nullptr ),
3637  nEndBox( 0 ), nCurBox( 0 ), nAFormatLine( 0 ), nAFormatBox( 0 ), bSingleRowTable(false)
3638  {}
3639 };
3640 
3641 }
3642 
3643 // Forward declare so that the Lines and Boxes can use recursion
3644 static bool lcl_SetAFormatBox(FndBox_ &, SetAFormatTabPara *pSetPara, bool bResetDirect);
3645 static bool lcl_SetAFormatLine(FndLine_ &, SetAFormatTabPara *pPara, bool bResetDirect);
3646 
3647 static bool lcl_SetAFormatLine(FndLine_ & rLine, SetAFormatTabPara *pPara, bool bResetDirect)
3648 {
3649  for (auto const& it : rLine.GetBoxes())
3650  {
3651  lcl_SetAFormatBox(*it, pPara, bResetDirect);
3652  }
3653  return true;
3654 }
3655 
3656 static bool lcl_SetAFormatBox(FndBox_ & rBox, SetAFormatTabPara *pSetPara, bool bResetDirect)
3657 {
3658  if (!rBox.GetUpper()->GetUpper()) // Box on first level?
3659  {
3660  if( !pSetPara->nCurBox )
3661  pSetPara->nAFormatBox = 0;
3662  else if( pSetPara->nCurBox == pSetPara->nEndBox )
3663  pSetPara->nAFormatBox = 3;
3664  else //Even column(1) or Odd column(2)
3665  pSetPara->nAFormatBox = static_cast<sal_uInt8>(1 + ((pSetPara->nCurBox-1) & 1));
3666  }
3667 
3668  if (rBox.GetBox()->GetSttNd())
3669  {
3670  SwTableBox* pSetBox = rBox.GetBox();
3671  if (!pSetBox->HasDirectFormatting() || bResetDirect)
3672  {
3673  if (bResetDirect)
3674  pSetBox->SetDirectFormatting(false);
3675 
3676  SwDoc* pDoc = pSetBox->GetFrameFormat()->GetDoc();
3678  SfxItemSet aBoxSet(pDoc->GetAttrPool(), aTableBoxSetRange);
3679  sal_uInt8 nPos = pSetPara->nAFormatLine * 4 + pSetPara->nAFormatBox;
3680  const bool bSingleRowTable = pSetPara->bSingleRowTable;
3681  const bool bSingleColTable = pSetPara->nEndBox == 0;
3682  pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aCharSet, SwTableAutoFormatUpdateFlags::Char, nullptr);
3683  pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aBoxSet, SwTableAutoFormatUpdateFlags::Box, pDoc->GetNumberFormatter());
3684 
3685  if (aCharSet.Count())
3686  {
3687  sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
3688  sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
3689  for (; nSttNd < nEndNd; ++nSttNd)
3690  {
3691  SwContentNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetContentNode();
3692  if (pNd)
3693  pNd->SetAttr(aCharSet);
3694  }
3695  }
3696 
3697  if (aBoxSet.Count())
3698  {
3699  if (pSetPara->pUndo && SfxItemState::SET == aBoxSet.GetItemState(RES_BOXATR_FORMAT))
3700  pSetPara->pUndo->SaveBoxContent( *pSetBox );
3701 
3702  pSetBox->ClaimFrameFormat()->SetFormatAttr(aBoxSet);
3703  }
3704  }
3705  }
3706  else
3707  {
3708  // Not sure how this situation can occur, but apparently we have some kind of table in table.
3709  // I am guessing at how to best handle singlerow in this situation.
3710  const bool bOrigSingleRowTable = pSetPara->bSingleRowTable;
3711  pSetPara->bSingleRowTable = rBox.GetLines().size() == 1;
3712  for (auto const& rpFndLine : rBox.GetLines())
3713  {
3714  lcl_SetAFormatLine(*rpFndLine, pSetPara, bResetDirect);
3715  }
3716  pSetPara->bSingleRowTable = bOrigSingleRowTable;
3717  }
3718 
3719  if (!rBox.GetUpper()->GetUpper()) // a BaseLine
3720  ++pSetPara->nCurBox;
3721  return true;
3722 }
3723 
3724 bool SwDoc::SetTableAutoFormat(const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew, bool bResetDirect, bool const isSetStyleName)
3725 {
3726  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3727  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3728  if( !pTableNd )
3729  return false;
3730 
3731  // Find all Boxes/Lines
3732  FndBox_ aFndBox( nullptr, nullptr );
3733  {
3734  FndPara aPara( rBoxes, &aFndBox );
3735  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3736  }
3737  if( aFndBox.GetLines().empty() )
3738  return false;
3739 
3740  SwTable &table = pTableNd->GetTable();
3741  table.SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3742 
3743  FndBox_* pFndBox = &aFndBox;
3744  while( 1 == pFndBox->GetLines().size() &&
3745  1 == pFndBox->GetLines().front()->GetBoxes().size())
3746  {
3747  pFndBox = pFndBox->GetLines().front()->GetBoxes()[0].get();
3748  }
3749 
3750  if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3751  pFndBox = pFndBox->GetUpper()->GetUpper();
3752 
3753  // Disable Undo, but first store parameters
3754  SwUndoTableAutoFormat* pUndo = nullptr;
3755  bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3756  if (bUndo)
3757  {
3758  pUndo = new SwUndoTableAutoFormat( *pTableNd, rNew );
3759  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3760  GetIDocumentUndoRedo().DoUndo(false);
3761  }
3762 
3763  if (isSetStyleName)
3764  { // tdf#98226 do this here where undo can record it
3765  pTableNd->GetTable().SetTableStyleName(rNew.GetName());
3766  }
3767 
3768  rNew.RestoreTableProperties(table);
3769 
3770  SetAFormatTabPara aPara( rNew );
3771  FndLines_t& rFLns = pFndBox->GetLines();
3772  aPara.bSingleRowTable = rFLns.size() == 1;
3773 
3774  for (FndLines_t::size_type n = 0; n < rFLns.size(); ++n)
3775  {
3776  FndLine_* pLine = rFLns[n].get();
3777 
3778  // Set Upper to 0 (thus simulate BaseLine)
3779  FndBox_* pSaveBox = pLine->GetUpper();
3780  pLine->SetUpper( nullptr );
3781 
3782  if( !n )
3783  aPara.nAFormatLine = 0;
3784  else if (static_cast<size_t>(n+1) == rFLns.size())
3785  aPara.nAFormatLine = 3;
3786  else
3787  aPara.nAFormatLine = static_cast<sal_uInt8>(1 + ((n-1) & 1 ));
3788 
3789  aPara.nAFormatBox = 0;
3790  aPara.nCurBox = 0;
3791  aPara.nEndBox = pLine->GetBoxes().size()-1;
3792  aPara.pUndo = pUndo;
3793  for (auto const& it : pLine->GetBoxes())
3794  {
3795  lcl_SetAFormatBox(*it, &aPara, bResetDirect);
3796  }
3797 
3798  pLine->SetUpper( pSaveBox );
3799  }
3800 
3801  if( pUndo )
3802  {
3803  GetIDocumentUndoRedo().DoUndo(bUndo);
3804  }
3805 
3807  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3808 
3809  return true;
3810 }
3811 
3816 {
3817  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3818  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3819  if( !pTableNd )
3820  return false;
3821 
3822  // Find all Boxes/Lines
3823  FndBox_ aFndBox( nullptr, nullptr );
3824  {
3825  FndPara aPara( rBoxes, &aFndBox );
3826  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3827  }
3828  if( aFndBox.GetLines().empty() )
3829  return false;
3830 
3831  // Store table properties
3832  SwTable &table = pTableNd->GetTable();
3833  rGet.StoreTableProperties(table);
3834 
3835  FndBox_* pFndBox = &aFndBox;
3836  while( 1 == pFndBox->GetLines().size() &&
3837  1 == pFndBox->GetLines().front()->GetBoxes().size())
3838  {
3839  pFndBox = pFndBox->GetLines().front()->GetBoxes()[0].get();
3840  }
3841 
3842  if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3843  pFndBox = pFndBox->GetUpper()->GetUpper();
3844 
3845  FndLines_t& rFLns = pFndBox->GetLines();
3846 
3847  sal_uInt16 aLnArr[4];
3848  aLnArr[0] = 0;
3849  aLnArr[1] = 1 < rFLns.size() ? 1 : 0;
3850  aLnArr[2] = 2 < rFLns.size() ? 2 : aLnArr[1];
3851  aLnArr[3] = rFLns.size() - 1;
3852 
3853  for( sal_uInt8 nLine = 0; nLine < 4; ++nLine )
3854  {
3855  FndLine_& rLine = *rFLns[ aLnArr[ nLine ] ];
3856 
3857  sal_uInt16 aBoxArr[4];
3858  aBoxArr[0] = 0;
3859  aBoxArr[1] = 1 < rLine.GetBoxes().size() ? 1 : 0;
3860  aBoxArr[2] = 2 < rLine.GetBoxes().size() ? 2 : aBoxArr[1];
3861  aBoxArr[3] = rLine.GetBoxes().size() - 1;
3862 
3863  for( sal_uInt8 nBox = 0; nBox < 4; ++nBox )
3864  {
3865  SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ]->GetBox();
3866  // Always apply to the first ones
3867  while( !pFBox->GetSttNd() )
3868  pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0];
3869 
3870  sal_uInt8 nPos = nLine * 4 + nBox;
3871  SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 );
3872  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3873  if( !pCNd )
3874  pCNd = GetNodes().GoNext( &aIdx );
3875 
3876  if( pCNd )
3877  rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(),
3879  rGet.UpdateFromSet( nPos, pFBox->GetFrameFormat()->GetAttrSet(),
3881  GetNumberFormatter() );
3882  }
3883  }
3884 
3885  return true;
3886 }
3887 
3889 {
3890  if (!m_pTableStyles)
3891  {
3893  m_pTableStyles->Load();
3894  }
3895  return *m_pTableStyles;
3896 }
3897 
3899 {
3900  if( IsInMailMerge())
3901  {
3902  OUString newName = "MailMergeTable"
3903  + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
3904  + OUString::number( mpTableFrameFormatTable->size() + 1 );
3905  return newName;
3906  }
3907 
3908  const OUString aName(SwResId(STR_TABLE_DEFNAME));
3909 
3910  const size_t nFlagSize = ( mpTableFrameFormatTable->size() / 8 ) + 2;
3911 
3912  std::unique_ptr<sal_uInt8[]> pSetFlags( new sal_uInt8[ nFlagSize ] );
3913  memset( pSetFlags.get(), 0, nFlagSize );
3914 
3915  for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3916  {
3917  const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3918  if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3919  pFormat->GetName().startsWith( aName ) )
3920  {
3921  // Get number and set the Flag
3922  const sal_Int32 nNmLen = aName.getLength();
3923  size_t nNum = pFormat->GetName().copy( nNmLen ).toInt32();
3924  if( nNum-- && nNum < mpTableFrameFormatTable->size() )
3925  pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
3926  }
3927  }
3928 
3929  // All numbers are flagged properly, thus calculate the right number
3930  size_t nNum = mpTableFrameFormatTable->size();
3931  for( size_t n = 0; n < nFlagSize; ++n )
3932  {
3933  auto nTmp = pSetFlags[ n ];
3934  if( nTmp != 0xFF )
3935  {
3936  // Calculate the number
3937  nNum = n * 8;
3938  while( nTmp & 1 )
3939  {
3940  ++nNum;
3941  nTmp >>= 1;
3942  }
3943  break;
3944  }
3945  }
3946 
3947  return aName + OUString::number( ++nNum );
3948 }
3949 
3950 SwTableFormat* SwDoc::FindTableFormatByName( const OUString& rName, bool bAll ) const
3951 {
3952  const SwFormat* pRet = nullptr;
3953  if( bAll )
3954  pRet = FindFormatByName( *mpTableFrameFormatTable, rName );
3955  else
3956  {
3957  // Only the ones set in the Doc
3958  for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3959  {
3960  const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3961  if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3962  pFormat->GetName() == rName )
3963  {
3964  pRet = pFormat;
3965  break;
3966  }
3967  }
3968  }
3969  return const_cast<SwTableFormat*>(static_cast<const SwTableFormat*>(pRet));
3970 }
3971 
3973  SwTwips nAbsDiff, SwTwips nRelDiff )
3974 {
3975  SwTableNode* pTableNd = const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode());
3976  std::unique_ptr<SwUndo> pUndo;
3977 
3978  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3979  aMsgHint.m_eFlags = TBL_BOXPTR;
3981 
3982  bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3983  bool bRet = false;
3984  switch( extractPosition(eType) )
3985  {
3990  {
3991  bRet = pTableNd->GetTable().SetColWidth( rCurrentBox,
3992  eType, nAbsDiff, nRelDiff,
3993  bUndo ? &pUndo : nullptr );
3994  }
3995  break;
3999  bRet = pTableNd->GetTable().SetRowHeight( rCurrentBox,
4000  eType, nAbsDiff, nRelDiff,
4001  bUndo ? &pUndo : nullptr );
4002  break;
4003  default: break;
4004  }
4005 
4006  GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off
4007  if( pUndo )
4008  {
4009  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4010  }
4011 
4012  if( bRet )
4013  {
4015  }
4016  return bRet;
4017 }
4018 
4019 bool SwDoc::IsNumberFormat( const OUString& rString, sal_uInt32& F_Index, double& fOutNumber )
4020 {
4021  if( rString.getLength() > 308 ) // optimization matches svl:IsNumberFormat arbitrary value
4022  return false;
4023 
4024  // remove any comment anchor marks
4025  OUStringBuffer sStringBuffer(rString);
4026  sal_Int32 nCommentPosition = sStringBuffer.indexOf( CH_TXTATR_INWORD );
4027  while( nCommentPosition != -1 )
4028  {
4029  sStringBuffer.remove( nCommentPosition, 1 );
4030  nCommentPosition = sStringBuffer.indexOf( CH_TXTATR_INWORD, nCommentPosition );
4031  }
4032 
4033  return GetNumberFormatter()->IsNumberFormat( sStringBuffer.makeStringAndClear(), F_Index, fOutNumber );
4034 }
4035 
4036 void SwDoc::ChkBoxNumFormat( SwTableBox& rBox, bool bCallUpdate )
4037 {
4038  // Optimization: If the Box says it's Text, it remains Text
4039  const SfxPoolItem* pNumFormatItem = nullptr;
4040  if( SfxItemState::SET == rBox.GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT,
4041  false, &pNumFormatItem ) && GetNumberFormatter()->IsTextFormat(
4042  static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue() ))
4043  return ;
4044 
4045  std::unique_ptr<SwUndoTableNumFormat> pUndo;
4046 
4047  bool bIsEmptyTextNd;
4048  bool bChgd = true;
4049  sal_uInt32 nFormatIdx;
4050  double fNumber;
4051  if( rBox.HasNumContent( fNumber, nFormatIdx, bIsEmptyTextNd ) )
4052  {
4053  if( !rBox.IsNumberChanged() )
4054  bChgd = false;
4055  else
4056  {
4058  {
4060  pUndo.reset(new SwUndoTableNumFormat( rBox ));
4061  pUndo->SetNumFormat( nFormatIdx, fNumber );
4062  }
4063 
4064  SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4066 
4067  bool bLockModify = true;
4068  bool bSetNumberFormat = IsInsTableFormatNum();
4069  const bool bForceNumberFormat = IsInsTableFormatNum() && IsInsTableChangeNumFormat();
4070 
4071  // if the user forced a number format in this cell previously,
4072  // keep it, unless the user set that she wants the full number
4073  // format recognition
4074  if( pNumFormatItem && !bForceNumberFormat )
4075  {
4076  sal_uLong nOldNumFormat = static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue();
4077  SvNumberFormatter* pNumFormatr = GetNumberFormatter();
4078 
4079  SvNumFormatType nFormatType = pNumFormatr->GetType( nFormatIdx );
4080  if( nFormatType == pNumFormatr->GetType( nOldNumFormat ) || SvNumFormatType::NUMBER == nFormatType )
4081  {
4082  // Current and specified NumFormat match
4083  // -> keep old Format
4084  nFormatIdx = nOldNumFormat;
4085  bSetNumberFormat = true;
4086  }
4087  else
4088  {
4089  // Current and specified NumFormat do not match
4090  // -> insert as Text
4091  bLockModify = bSetNumberFormat = false;
4092  }
4093  }
4094 
4095  if( bSetNumberFormat || bForceNumberFormat )
4096  {
4097  pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4098 
4099  aBoxSet.Put( SwTableBoxValue( fNumber ));
4100  aBoxSet.Put( SwTableBoxNumFormat( nFormatIdx ));
4101  }
4102 
4103  // It's not enough to only reset the Formula.
4104  // Make sure that the Text is formatted accordingly
4105  if( !bSetNumberFormat && !bIsEmptyTextNd && pNumFormatItem )
4106  {
4107  // Just resetting Attributes is not enough
4108  // Make sure that the Text is formatted accordingly
4109  pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4110  }
4111 
4112  if( bLockModify ) pBoxFormat->LockModify();
4114  if( bLockModify ) pBoxFormat->UnlockModify();
4115 
4116  if( bSetNumberFormat )
4117  pBoxFormat->SetFormatAttr( aBoxSet );
4118  }
4119  }
4120  else
4121  {
4122  // It's not a number
4123  const SfxPoolItem* pValueItem = nullptr, *pFormatItem = nullptr;
4124  SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4125  if( SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_FORMAT,
4126  false, &pFormatItem ) ||
4127  SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_VALUE,
4128  false, &pValueItem ))
4129  {
4131  {
4133  pUndo.reset(new SwUndoTableNumFormat( rBox ));
4134  }
4135 
4136  pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4137 
4138  // Remove all number formats
4139  sal_uInt16 nWhich1 = RES_BOXATR_FORMULA;
4140  if( !bIsEmptyTextNd )
4141  {
4142  nWhich1 = RES_BOXATR_FORMAT;
4143 
4144  // Just resetting Attributes is not enough
4145  // Make sure that the Text is formatted accordingly
4146  pBoxFormat->SetFormatAttr( *GetDfltAttr( nWhich1 ));
4147  }
4148  pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4149  }
4150  else
4151  bChgd = false;
4152  }
4153 
4154  if( !bChgd )
4155  return;
4156 
4157  if( pUndo )
4158  {
4159  pUndo->SetBox( rBox );
4160  GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
4162  }
4163 
4164  const SwTableNode* pTableNd = rBox.GetSttNd()->FindTableNode();
4165  if( bCallUpdate )
4166  {
4167  SwTableFormulaUpdate aTableUpdate( &pTableNd->GetTable() );
4168  getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate );
4169 
4170  // TL_CHART2: update charts (when cursor leaves cell and
4171  // automatic update is enabled)
4172  if (AUTOUPD_FIELD_AND_CHARTS == GetDocumentSettingManager().getFieldUpdateFlags(true))
4173  pTableNd->GetTable().UpdateCharts();
4174  }
4176 }
4177 
4179 {
4180  if (GetIDocumentUndoRedo().DoesUndo())
4181  {
4182  GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoTableNumFormat>(rBox, &rSet) );
4183  }
4184 
4185  SwFrameFormat* pBoxFormat = rBox.ClaimFrameFormat();
4186  if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
4187  {
4188  pBoxFormat->LockModify();
4189  pBoxFormat->ResetFormatAttr( RES_BOXATR_VALUE );
4190  pBoxFormat->UnlockModify();
4191  }
4192  else if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE ))
4193  {
4194  pBoxFormat->LockModify();
4195  pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMULA );
4196  pBoxFormat->UnlockModify();
4197  }
4198  pBoxFormat->SetFormatAttr( rSet );
4200 }
4201 
4203 {
4204  SwPaM aPam(rPos);
4205  aPam.Move(fnMoveBackward);
4206  SwContentNode *pNode = aPam.GetContentNode();
4207  if ( nullptr == pNode )
4208  return ;
4209  if( !pNode->IsTextNode() )
4210  return;
4211 
4212  SwTextNode * pTextNode = pNode->GetTextNode();
4213  if (!(pTextNode && pTextNode->IsNumbered()
4214  && pTextNode->GetText().isEmpty()))
4215  return;
4216 
4217  const SfxPoolItem* pFormatItem = nullptr;
4218  SfxItemSet rSet( pTextNode->GetDoc()->GetAttrPool(),
4220  pTextNode->SwContentNode::GetAttr( rSet );
4221  if ( SfxItemState::SET != rSet.GetItemState( RES_PARATR_NUMRULE , false , &pFormatItem ) )
4222  return;
4223 
4224  SwUndoDelNum * pUndo;
4225  if( GetIDocumentUndoRedo().DoesUndo() )
4226  {
4228  pUndo = new SwUndoDelNum( aPam );
4229  GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
4230  }
4231  else
4232  pUndo = nullptr;
4233  SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
4234  aRegH.RegisterInModify( pTextNode , *pTextNode );
4235  if ( pUndo )
4236  pUndo->AddNode( *pTextNode );
4237  std::unique_ptr<SfxStringItem> pNewItem(static_cast<SfxStringItem*>(pFormatItem->Clone()));
4238  pNewItem->SetValue(OUString());
4239  rSet.Put( std::move(pNewItem) );
4240  pTextNode->SetAttr( rSet );
4241 }
4242 
4244 {
4246  if( nullptr == pSttNd ||
4247  2 != pSttNd->EndOfSectionIndex() - pSttNd->GetIndex())
4248  return;
4249 
4250  SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
4251  GetTableBox( pSttNd->GetIndex() );
4252 
4253  const SfxPoolItem* pFormatItem = nullptr;
4254  const SfxItemSet& rSet = pBox->GetFrameFormat()->GetAttrSet();
4255  if( !(SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT, false, &pFormatItem ) ||
4256  SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA, false ) ||
4257  SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE, false )))
4258  return;
4259 
4261  {
4262  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoTableNumFormat>(*pBox));
4263  }
4264 
4265  SwFrameFormat* pBoxFormat = pBox->ClaimFrameFormat();
4266 
4267  // Keep TextFormats!
4268  sal_uInt16 nWhich1 = RES_BOXATR_FORMAT;
4269  if( pFormatItem && GetNumberFormatter()->IsTextFormat(
4270  static_cast<const SwTableBoxNumFormat*>(pFormatItem)->GetValue() ))
4271  nWhich1 = RES_BOXATR_FORMULA;
4272  else
4273  // Just resetting Attributes is not enough
4274  // Make sure that the Text is formatted accordingly
4275  pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4276 
4277  pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4279 }
4280 
4288 bool SwDoc::InsCopyOfTable( SwPosition& rInsPos, const SwSelBoxes& rBoxes,
4289  const SwTable* pCpyTable, bool bCpyName, bool bCorrPos )
4290 {
4291  bool bRet;
4292 
4293  const SwTableNode* pSrcTableNd = pCpyTable
4294  ? pCpyTable->GetTableNode()
4295  : rBoxes[ 0 ]->GetSttNd()->FindTableNode();
4296 
4297  SwTableNode * pInsTableNd = rInsPos.nNode.GetNode().FindTableNode();
4298 
4299  bool const bUndo( GetIDocumentUndoRedo().DoesUndo() );
4300  if( !pCpyTable && !pInsTableNd )
4301  {
4302  std::unique_ptr<SwUndoCpyTable> pUndo;
4303  if (bUndo)
4304  {
4306  pUndo.reset(new SwUndoCpyTable(this));
4307  }
4308 
4309  {
4310  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
4311  bRet = pSrcTableNd->GetTable().MakeCopy( this, rInsPos, rBoxes,
4312  bCpyName );
4313  }
4314 
4315  if( pUndo && bRet )
4316  {
4317  pInsTableNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode();
4318 
4319  pUndo->SetTableSttIdx( pInsTableNd->GetIndex() );
4320  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4321  }
4322  }
4323  else
4324  {
4326  if( getIDocumentRedlineAccess().IsRedlineOn() )
4330 
4331  std::unique_ptr<SwUndoTableCpyTable> pUndo;
4332  if (bUndo)
4333  {
4335  pUndo.reset(new SwUndoTableCpyTable(this));
4336  GetIDocumentUndoRedo().DoUndo(false);
4337  }
4338 
4339  rtl::Reference<SwDoc> xCpyDoc( const_cast<SwDoc*>(pSrcTableNd->GetDoc()) );
4340  bool bDelCpyDoc = xCpyDoc == this;
4341 
4342  if( bDelCpyDoc )
4343  {
4344  // Copy the Table into a temporary Doc
4345  xCpyDoc = new SwDoc;
4346 
4347  SwPosition aPos( SwNodeIndex( xCpyDoc->GetNodes().GetEndOfContent() ));
4348  if( !pSrcTableNd->GetTable().MakeCopy( xCpyDoc.get(), aPos, rBoxes, true ))
4349  {
4350  xCpyDoc.clear();
4351 
4352  if( pUndo )
4353  {
4354  GetIDocumentUndoRedo().DoUndo(bUndo);
4355  }
4356  return false;
4357  }
4358  aPos.nNode -= 1; // Set to the Table's EndNode
4359  pSrcTableNd = aPos.nNode.GetNode().FindTableNode();
4360  }
4361 
4362  const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
4363 
4364  rInsPos.nContent.Assign( nullptr, 0 );
4365 
4366  // no complex into complex, but copy into or from new model is welcome
4367  if( ( !pSrcTableNd->GetTable().IsTableComplex() || pInsTableNd->GetTable().IsNewModel() )
4368  && ( bDelCpyDoc || !rBoxes.empty() ) )
4369  {
4370  // Copy the Table "relatively"
4371  const SwSelBoxes* pBoxes;
4372  SwSelBoxes aBoxes;
4373 
4374  if( bDelCpyDoc )
4375  {
4376  SwTableBox* pBox = pInsTableNd->GetTable().GetTableBox(
4377  pSttNd->GetIndex() );
4378  OSL_ENSURE( pBox, "Box is not in this Table" );
4379  aBoxes.insert( pBox );
4380  pBoxes = &aBoxes;
4381  }
4382  else
4383  pBoxes = &rBoxes;
4384 
4385  // Copy Table to the selected Lines
4386  bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4387  *pBoxes, pUndo.get() );
4388  }
4389  else
4390  {
4391  SwNodeIndex aNdIdx( *pSttNd, 1 );
4392  bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4393  aNdIdx, pUndo.get() );
4394  }
4395 
4396  xCpyDoc.clear();
4397 
4398  if( pUndo )
4399  {
4400  // If the Table could not be copied, delete the Undo object
4401  GetIDocumentUndoRedo().DoUndo(bUndo);
4402  if( bRet || !pUndo->IsEmpty() )
4403  {
4404  GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
4405  }
4406  }
4407 
4408  if( bCorrPos )
4409  {
4410  rInsPos.nNode = *pSttNd;
4411  rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 );
4412  }
4414  }
4415 
4416  if( bRet )
4417  {
4419  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
4420  }
4421  return bRet;
4422 }
4423 
4425 {
4426  bool bChgd = false;
4427  std::unique_ptr<SwUndoAttrTable> pUndo;
4428  if (GetIDocumentUndoRedo().DoesUndo())
4429  pUndo.reset(new SwUndoAttrTable( *rTable.GetTableNode() ));
4430 
4431  SwTableSortBoxes& rSrtBox = rTable.GetTabSortBoxes();
4432  for (size_t i = rSrtBox.size(); i; )
4433  {
4434  SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4435  if( pBoxFormat->GetProtect().IsContentProtected() )
4436  {
4437  pBoxFormat->ResetFormatAttr( RES_PROTECT );
4438  bChgd = true;
4439  }
4440  }
4441 
4442  if( pUndo && bChgd )
4443  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4444  return bChgd;
4445 }
4446 
4447 void SwDoc::UnProtectCells( const OUString& rName )
4448 {
4449  bool bChgd = false;
4450  SwTableFormat* pFormat = FindTableFormatByName( rName );
4451  if( pFormat )
4452  {
4453  bChgd = UnProtectTableCells( *SwTable::FindTable( pFormat ) );
4454  if( bChgd )
4456  }
4457 }
4458 
4459 bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes )
4460 {
4461  bool bChgd = false;
4462  if( !rBoxes.empty() )
4463  {
4464  std::unique_ptr<SwUndoAttrTable> pUndo;
4466  pUndo.reset(new SwUndoAttrTable( *rBoxes[0]->GetSttNd()->FindTableNode() ));
4467 
4468  std::map<SwFrameFormat*, SwTableBoxFormat*> aFormatsMap;
4469  for (size_t i = rBoxes.size(); i; )
4470  {
4471  SwTableBox* pBox = rBoxes[ --i ];
4472  SwFrameFormat* pBoxFormat = pBox->GetFrameFormat();
4473  if( pBoxFormat->GetProtect().IsContentProtected() )
4474  {
4475  std::map<SwFrameFormat*, SwTableBoxFormat*>::const_iterator const it =
4476  aFormatsMap.find(pBoxFormat);
4477  if (aFormatsMap.end() != it)
4478  pBox->ChgFrameFormat(it->second);
4479  else
4480  {
4481  SwTableBoxFormat *const pNewBoxFormat(
4482  static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat()));
4483  pNewBoxFormat->ResetFormatAttr( RES_PROTECT );
4484  aFormatsMap.insert(std::make_pair(pBoxFormat, pNewBoxFormat));
4485  }
4486  bChgd = true;
4487  }
4488  }
4489 
4490  if( pUndo && bChgd )
4491  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4492  }
4493  return bChgd;
4494 }
4495 
4496 void SwDoc::UnProtectTables( const SwPaM& rPam )
4497 {
4499 
4500  bool bChgd = false, bHasSel = rPam.HasMark() ||
4501  rPam.GetNext() != &rPam;
4502  SwFrameFormats& rFormats = *GetTableFrameFormats();
4503  SwTable* pTable;
4504  const SwTableNode* pTableNd;
4505  for( auto n = rFormats.size(); n ; )
4506  if( nullptr != (pTable = SwTable::FindTable( rFormats[ --n ] )) &&
4507  nullptr != (pTableNd = pTable->GetTableNode() ) &&
4508  pTableNd->GetNodes().IsDocNodes() )
4509  {
4510  sal_uLong nTableIdx = pTableNd->GetIndex();
4511 
4512  // Check whether the Table is within the Selection
4513  if( bHasSel )
4514  {
4515  bool bFound = false;
4516  SwPaM* pTmp = const_cast<SwPaM*>(&rPam);
4517  do {
4518  const SwPosition *pStt = pTmp->Start(),
4519  *pEnd = pTmp->End();
4520  bFound = pStt->nNode.GetIndex() < nTableIdx &&
4521  nTableIdx < pEnd->nNode.GetIndex();
4522 
4523  } while( !bFound && &rPam != ( pTmp = pTmp->GetNext() ) );
4524  if( !bFound )
4525  continue; // Continue searching
4526  }
4527 
4528  // Lift the protection
4529  bChgd |= UnProtectTableCells( *pTable );
4530  }
4531 
4533  if( bChgd )
4535 }
4536 
4538  const OUString* pTableName,
4539  bool* pFullTableProtection )
4540 {
4541  bool bHasProtection = false;
4542  SwTable* pTable = nullptr;
4543  if( pTableName )
4544  pTable = SwTable::FindTable( FindTableFormatByName( *pTableName ) );
4545  else if( pPos )
4546  {
4547  SwTableNode* pTableNd = pPos->nNode.GetNode().FindTableNode();
4548  if( pTableNd )
4549  pTable = &pTableNd->GetTable();
4550  }
4551 
4552  if( pTable )
4553  {
4554  SwTableSortBoxes& rSrtBox = pTable->GetTabSortBoxes();
4555  for (size_t i = rSrtBox.size(); i; )
4556  {
4557  SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4558  if( pBoxFormat->GetProtect().IsContentProtected() )
4559  {
4560  if( !bHasProtection )
4561  {
4562  bHasProtection = true;
4563  if( !pFullTableProtection )
4564  break;
4565  *pFullTableProtection = true;
4566  }
4567  }
4568  else if( bHasProtection && pFullTableProtection )
4569  {
4570  *pFullTableProtection = false;
4571  break;
4572  }
4573  }
4574  }
4575  return bHasProtection;
4576 }
4577 
4578 SwTableAutoFormat* SwDoc::MakeTableStyle(const OUString& rName, bool bBroadcast)
4579 {
4580  SwTableAutoFormat aTableFormat(rName);
4581  GetTableStyles().AddAutoFormat(aTableFormat);
4582  SwTableAutoFormat* pTableFormat = GetTableStyles().FindAutoFormat(rName);
4583 
4585 
4586  if (GetIDocumentUndoRedo().DoesUndo())
4587  {
4589  std::make_unique<SwUndoTableStyleMake>(rName, this));
4590  }
4591 
4592  if (bBroadcast)
4593  BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxHintId::StyleSheetCreated);
4594 
4595  return pTableFormat;
4596 }
4597 
4598 std::unique_ptr<SwTableAutoFormat> SwDoc::DelTableStyle(const OUString& rName, bool bBroadcast)
4599 {
4600  if (bBroadcast)
4601  BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxHintId::StyleSheetErased);
4602 
4603  std::unique_ptr<SwTableAutoFormat> pReleasedFormat = GetTableStyles().ReleaseAutoFormat(rName);
4604 
4605  std::vector<SwTable*> vAffectedTables;
4606  if (pReleasedFormat)
4607  {
4608  size_t nTableCount = GetTableFrameFormatCount(true);
4609  for (size_t i=0; i < nTableCount; ++i)
4610  {
4611  SwFrameFormat* pFrameFormat = &GetTableFrameFormat(i, true);
4612  SwTable* pTable = SwTable::FindTable(pFrameFormat);
4613  if (pTable->GetTableStyleName() == pReleasedFormat->GetName())
4614  {
4615  pTable->SetTableStyleName("");
4616  vAffectedTables.push_back(pTable);
4617  }
4618  }
4619 
4621 
4622  if (GetIDocumentUndoRedo().DoesUndo())
4623  {
4625  std::make_unique<SwUndoTableStyleDelete>(std::move(pReleasedFormat), vAffectedTables, this));
4626  }
4627  }
4628 
4629  return pReleasedFormat;
4630 }
4631 
4632 void SwDoc::ChgTableStyle(const OUString& rName, const SwTableAutoFormat& rNewFormat)
4633 {
4634  SwTableAutoFormat* pFormat = GetTableStyles().FindAutoFormat(rName);
4635  if (!pFormat)
4636  return;
4637 
4638  SwTableAutoFormat aOldFormat = *pFormat;
4639  *pFormat = rNewFormat;
4640  pFormat->SetName(rName);
4641 
4642  size_t nTableCount = GetTableFrameFormatCount(true);
4643  for (size_t i=0; i < nTableCount; ++i)
4644  {
4645  SwFrameFormat* pFrameFormat = &GetTableFrameFormat(i, true);
4646  SwTable* pTable = SwTable::FindTable(pFrameFormat);
4647  if (pTable->GetTableStyleName() == rName)
4649  }
4650 
4652 
4653  if (GetIDocumentUndoRedo().DoesUndo())
4654  {
4656  std::make_unique<SwUndoTableStyleUpdate>(*pFormat, aOldFormat, this));
4657  }
4658 }
4659 
4660 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwStartNode * FindSttNodeByType(SwStartNodeType eTyp)
Definition: node.cxx:759
bool IsInsTableChangeNumFormat() const
Definition: doc.cxx:1684
sal_uInt16 GetRedlSaveCount() const
Definition: unredln.cxx:83
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
SwTableFormat * MakeTableFrameFormat(const OUString &rFormatName, SwFrameFormat *pDerivedFrom)
Definition: docfmt.cxx:799
void SetTableBoxFormulaAttrs(SwTableBox &rBox, const SfxItemSet &rSet)
Definition: ndtbl.cxx:4178
bool IsTableComplex() const
Definition: swtable.cxx:1445
static SwTableBoxFormat * lcl_CreateAFormatBoxFormat(SwDoc &rDoc, std::vector< SwTableBoxFormat * > &rBoxFormatArr, const SwTableAutoFormat &rAutoFormat, const sal_uInt16 nRows, const sal_uInt16 nCols, sal_uInt8 nId)
Definition: ndtbl.cxx:193
const SwEndNode * EndOfSectionNode() const
Definition: node.hxx:682
Starts a section of nodes in the document model.
Definition: node.hxx:303
constexpr TypedWhichId< SvxProtectItem > RES_PROTECT(100)
std::vector< SwTableLine * >::size_type size_type
Definition: swtable.hxx:66
Base class of the Writer layout elements.
Definition: frame.hxx:297
void SetName(const OUString &rNew)
Definition: tblafmt.hxx:207
void ExpandColumnSelection(SwSelBoxes &rBoxes, long &rMin, long &rMax) const
void SwTable::ExpandColumnSelection(..) adds cell to the give selection to assure that at least one c...
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:151
const FndLines_t & GetLines() const
Definition: tblsel.hxx:173
constexpr TypedWhichId< SvxFrameDirectionItem > RES_FRAMEDIR(120)
virtual sal_Int32 Len() const
Definition: node.cxx:1223
SwHistory * GetHistory()
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
long GetPrtLeft() const
Definition: ssfrm.cxx:47
void SwClearFntCacheTextGlyphs()
Clears the pre-calculated text glyphs in all SwFntObj instances.
Definition: fntcache.cxx:2706
void DeleteMark()
Definition: pam.hxx:177
virtual void Cut() override
Definition: tabfrm.cxx:3599
void KillPams()
Definition: crsrsh.cxx:1020
bool IsInMailMerge() const
Definition: doc.hxx:957
static SwTableBoxFormat * lcl_CreateDfltBoxFormat(SwDoc &rDoc, std::vector< SwTableBoxFormat * > &rBoxFormatArr, sal_uInt16 nCols, sal_uInt8 nId)
Definition: ndtbl.cxx:178
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
const Value & back() const
SwTableLineFormat * MakeTableLineFormat()
Definition: docfmt.cxx:1713
SwStartNode * m_pStartOfSection
Definition: node.hxx:112
sal_Int32 nIndex
void Add(SwClient *pDepend)
Definition: calbck.cxx:217
bool IsFollow() const
Definition: flowfrm.hxx:166
sal_uLong Count() const
Definition: ndarr.hxx:142
void SetRowsToRepeat(sal_uInt16 nNumOfRows)
Definition: swtable.hxx:194
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
void RegisterToFormat(SwFormat &rFormat)
Definition: swtable.cxx:2745
Marks a position in the document model.
Definition: pam.hxx:35
bool IsSectionNode() const
Definition: node.hxx:644
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_CTL_FONT(27)
static SwFormat * FindFormatByName(const SwFormatsBase &rFormatArr, const OUString &rName)
Definition: docfmt.cxx:1610
const SwTableBox * GetTableBox(const OUString &rName, const bool bPerformValidCheck=false) const
Definition: swtable.cxx:1344
long YInc(long n1, long n2) const
Definition: frame.hxx:1403
static bool lcl_ChgTableSize(SwTable &rTable)
Definition: ndtbl.cxx:3238
std::vector< SwTableBox * > m_Boxes
Definition: tblrwcl.hxx:64
bool IsDefault() const
Definition: format.hxx:109
union SwTableFormulaUpdate::@26 m_aData
sal_uLong StartOfSectionIndex() const
Definition: node.hxx:673
void DelFrames(SwRootFrame const *pLayout=nullptr)
Method deletes all views of document for the node.
Definition: ndtbl.cxx:2436
constexpr TypedWhichId< SwTableBoxNumFormat > RES_BOXATR_FORMAT(RES_BOXATR_BEGIN)
void FindSuperfluousRows(SwSelBoxes &rBoxes)
Definition: swtable.hxx:255
SwTableAutoFormat * FindAutoFormat(const OUString &rName) const
Find table style with the provided name, return nullptr when not found.
Definition: tblafmt.cxx:995
bool IsInsTableFormatNum() const
Definition: doc.cxx:1679
bool TableToText(const SwTableNode *pTableNd, sal_Unicode cCh)
Table to Text.
Definition: ndtbl.cxx:1454
const OUString & GetText() const
Definition: ndtxt.hxx:211
void UpdateCharts() const
Definition: docchart.cxx:34
static void lcl_SetTableBoxWidths2(SwTable &rTable, size_t const nMaxBoxes, SwTableBoxFormat &rBoxFormat, SwDoc &rDoc)
Definition: ndtbl.cxx:1346
virtual const SwRootFrame * GetCurrentLayout() const =0
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr) override
Definition: tabfrm.cxx:3704
sal_uLong GetSttIdx() const
Definition: swtable.cxx:1882
SwUndoId
Definition: swundo.hxx:29
SwDocShell * GetDocShell()
Definition: doc.hxx:1348
virtual bool SetAttr(const SfxPoolItem &) override
overriding to handle change of certain paragraph attributes
Definition: ndtxt.cxx:4906
std::string GetValue
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1407
constexpr TypedWhichId< SwTableBoxValue > RES_BOXATR_VALUE(150)
void UpdateToSet(const sal_uInt8 nPos, const bool bSingleRowTable, const bool bSingleColTable, SfxItemSet &rSet, SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter *) const
Definition: tblafmt.cxx:560
SwHistory * m_pHistory
Definition: hints.hxx:206
virtual AppendResult AppendRedline(SwRangeRedline *pNewRedl, bool bCallDelete)=0
Append a new redline.
const SwFrameFormats * GetTableFrameFormats() const
Definition: doc.hxx:808
virtual void SetRedlineFlags_intern(RedlineFlags eMode)=0
Set a new redline mode.
void RegistFlys()
Definition: tabfrm.cxx:158
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const =0
void DeleteRow(const SwCursor &rCursor)
Deleting Columns/Rows.
Definition: ndtbl.cxx:1829
const SwTable * GetTable() const
Definition: tabfrm.hxx:144
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:643
constexpr TypedWhichId< SwFormatFrameSize > RES_FRM_SIZE(89)
sal_uInt16 char char * pDesc
long GetWidth() const
void RegisterInModify(SwModify *pRegIn, const SwNode &rNd)
Definition: rolbck.cxx:1489
static void GetTabCols(SwTabCols &rFill, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2500
static bool lcl_SetAFormatBox(FndBox_ &, SetAFormatTabPara *pSetPara, bool bResetDirect)
Definition: ndtbl.cxx:3656
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
void StoreTableProperties(const SwTable &table)
Definition: tblafmt.cxx:703
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
OUString GetUniqueTableName() const
Definition: ndtbl.cxx:3898
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
const SwPosition * GetMark() const
Definition: pam.hxx:209
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
SwInsertTableFlags mnInsMode
Definition: itabenum.hxx:40
virtual void CreateChartInternalDataProviders(const SwTable *pTable)=0
calls createInternalDataProvider for all charts using the specified table
bool IsContentHidden() const
Check for not hidden areas whether there is content that is not in a hidden sub-area.
Definition: ndsect.cxx:1275
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1190
virtual SwContentFrame * MakeFrame(SwFrame *pSib)=0
MakeFrame will be called for a certain layout pSib is another SwFrame of the same layout (e...
sal_Int64 n
virtual SwUndoId EndUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Closes undo block.
SwTableFormat * FindTableFormatByName(const OUString &rName, bool bAll=false) const
Definition: ndtbl.cxx:3950
Definition: doc.hxx:184
SwFrameFormat * ClaimFrameFormat()
Definition: swtable.cxx:1482
TElementType * Next()
Definition: calbck.hxx:351
bool HasFollow() const
Definition: flowfrm.hxx:165
SvNumFormatType GetType(sal_uInt32 nFIndex) const
void DelFrames(SwTable &rTable)
Definition: tblsel.cxx:2172
sal_Int16 nId
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1356
exports com.sun.star. table
TableChgWidthHeightType
Definition: tblenum.hxx:25
bool IsGetFromTop() const
Definition: tblrwcl.hxx:93
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
virtual bool HasExtraRedlineTable() const =0
SwTableLine is one table row in the document model.
Definition: swtable.hxx:344
sal_uInt16 nLinePos
Definition: tblrwcl.hxx:122
void SetTabRows(const SwTabCols &rNew, bool bCurColOnly, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2745
SwNode & GetNode() const
Definition: ndindex.hxx:119
long SwTwips
Definition: swtypes.hxx:49
bool HasProtectedCells(const SwSelBoxes &rBoxes)
Definition: tblsel.cxx:856
void RemoveRedlines()
Definition: ndtbl.cxx:2489
bool IsVert() const
Definition: frame.hxx:1345
sal_uInt16 GetRowsToRepeat() const
Definition: swtable.hxx:193
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:382
SwTextNode * SplitContentNode(const SwPosition &, std::function< void(SwTextNode *, sw::mark::RestoreMode)> const *pContentIndexRestore)
Definition: ndtxt.cxx:412
SwPosition & GetBound(bool bOne=true)
Definition: pam.hxx:245
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:144
bool IsCellFrame() const
Definition: frame.hxx:1204
iterator begin()
Definition: swtable.hxx:75
void CheckSectionCondColl() const
Call ChkCondcoll to all ContentNodes of section.
Definition: node.cxx:970
IDocumentChartDataProviderAccess & getIDocumentChartDataProviderAccess()
Gives access to the chart data-provider.
Definition: format.cxx:764
long GetPrtTop(const SwFrame &rFrame) const
Definition: frame.hxx:1387
bool InsertRow(SwDoc *, const SwSelBoxes &rBoxes, sal_uInt16 nCnt, bool bBehind)
SwTable::InsertRow(..) inserts one or more rows before or behind the selected boxes.
void AddAutoFormat(const SwTableAutoFormat &rFormat)
Append table style to the existing styles.
Definition: tblafmt.cxx:943
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
bool HasWriterListeners() const
Definition: calbck.hxx:208
The root element of a Writer document layout.
Definition: rootfrm.hxx:80
static void GetTabRows(SwTabCols &rFill, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2554
sal_uInt16 mnRowsToRepeat
Definition: itabenum.hxx:41
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
SwTableFormat * GetFrameFormat()
Definition: swtable.hxx:201
void SetValues(bool bFlag)
Definition: tblrwcl.hxx:97
const SwFrameFormats * GetSpzFrameFormats() const
Definition: doc.hxx:739
void ClearBoxNumAttrs(const SwNodeIndex &rNode)
Definition: ndtbl.cxx:4243
Value in Var-direction gives minimum (can be exceeded but not be less).
bool PrepareMerge(const SwPaM &rPam, SwSelBoxes &rBoxes, SwSelBoxes &rMerged, SwTableBox **ppMergeBox, SwUndoTableMerge *pUndo)
SwTable::PrepareMerge(..) some preparation for the coming Merge(..)
Definition: swnewtable.cxx:806
void UnProtectTables(const SwPaM &rPam)
Definition: ndtbl.cxx:4496
void Insert(long nValue, bool bValue, size_t nPos)
Definition: tabcol.cxx:69
size_type size() const
Definition: swtable.hxx:74
static void lcl_SplitTable_CpyBox(SwTableBox *pBox, SplitTable_Para *pPara)
Definition: ndtbl.cxx:3323
SwTableNode * TextToTable(const SwNodeRange &rRange, sal_Unicode cCh, SwTableFormat *pTableFormat, SwTableLineFormat *pLineFormat, SwTableBoxFormat *pBoxFormat, SwTextFormatColl *pTextColl, SwUndoTextToTable *pUndo)
Create balanced table from selected range.
Definition: ndtbl.cxx:1000
void ForEach_FndLineCopyCol(SwTableLines &rLines, FndPara *pFndPara)
Definition: tblsel.cxx:2104
bool TableToText(const SwNodeRange &rRange, sal_Unicode cCh, SwUndoTableToText *)
Create regular text from what was table.
Definition: ndtbl.cxx:1591
long GetRight() const
Definition: tabcol.hxx:78
std::unique_ptr< SwTable > m_pTable
Definition: node.hxx:490
show all inserts
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
static void lcl_SetTableBoxWidths(SwTable &rTable, size_t const nMaxBoxes, SwTableBoxFormat &rBoxFormat, SwDoc &rDoc, std::vector< sal_uInt16 > *const pPositions)
Definition: ndtbl.cxx:965
bool DeleteRowCol(const SwSelBoxes &rBoxes, bool bColumn=false)
Definition: ndtbl.cxx:1953
const SwSection & GetSection() const
Definition: node.hxx:541
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
SwTableBox * FindNextBox(const SwTable &, const SwTableBox *=nullptr, bool bOvrTableLns=true) const
Definition: tblrwcl.cxx:2194
long YDiff(long n1, long n2) const
Definition: frame.hxx:1401
void MakeFramesForAdjacentContentNode(SwContentNode &rNode)
Method creates all views of document for given node.
Definition: node.cxx:1341
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
constexpr TypedWhichId< SwFormatVertOrient > RES_VERT_ORIENT(102)
bool IsFont() const
Definition: tblafmt.hxx:219
TableMergeErr
Definition: tblenum.hxx:62
void ChgFrameFormat(SwTableLineFormat *pNewFormat)
Definition: swtable.cxx:1515
sal_uInt16 sal_Unicode
bool IsAssignedToListLevelOfOutlineStyle() const
Definition: fmtcol.hxx:109
void MakeFramesForAdjacentContentNode(const SwNodeIndex &rIdx)
Method creates all views of the document for the previous node.
Definition: ndtbl.cxx:2362
void SetUpper(FndBox_ *pUp)
Definition: tblsel.hxx:210
void GetTabCols(SwTabCols &rToFill, const SwTableBox *pStart, bool bHidden=false, bool bCurRowOnly=false) const
Definition: swtable.cxx:526
#define CH_TXTATR_INWORD
Definition: hintids.hxx:171
SwTableNode * GetTableNode()
Definition: node.hxx:599
void JoinAndDelFollows()
Definition: tabfrm.cxx:148
void Top(const long nTop)
Definition: swrect.hxx:204
constexpr sal_uInt16 RES_PARATR_BEGIN(RES_TXTATR_END)
static void lcl_SplitTable_CpyLine(SwTableLine *pLn, SplitTable_Para *pPara)
Definition: ndtbl.cxx:3308
std::unique_ptr< SwFrameFormats > mpTableFrameFormatTable
Definition: doc.hxx:240
bool UpdateTableStyleFormatting(SwTableNode *pTableNode=nullptr, bool bResetDirect=false, OUString const *pStyleName=nullptr)
Update the direct formatting according to the current table style.
Definition: fetab.cxx:1201
const SwTableBox * GetTabBox() const
Definition: cellfrm.hxx:52
SW_DLLPUBLIC bool DeleteAllTableRedlines(SwDoc *pDoc, const SwTable &rTable, bool bSaveInUndo, RedlineType nRedlineTypeToDelete)
Definition: docredln.cxx:130
SwIndex nContent
Definition: pam.hxx:38
bool IsJustify() const
Definition: tblafmt.hxx:220
const SwRect & getFrameArea() const
Definition: frame.hxx:177
SwTableNode * SplitTable(const SwNodeIndex &rPos, bool bAfter=true, bool bCalcNewSize=false)
Splits a table at the base-line which contains the index.
Definition: ndtbl.cxx:3341
friend class SwStartNode
Definition: ndarr.hxx:93
SwNodeIndex aStart
Definition: ndindex.hxx:132
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void sw_LineSetHeadCondColl(const SwTableLine *pLine)
Definition: tblrwcl.cxx:2331
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:426
const SwTextFormatColl * GetDfltTextFormatColl() const
Definition: doc.hxx:773
void SetAttr(const SfxPoolItem &, SwFormat &)
Set attribute in given format.1y If Undo is enabled, the old values is added to the Undo history...
Definition: docfmt.cxx:450
void MakeOwnFrames(SwNodeIndex *pIdxBehind, SwNodeIndex *pEnd=nullptr)
Creates the frms for the SectionNode (i.e.
Definition: ndsect.cxx:1142
static bool IsRedlineOn(const RedlineFlags eM)
std::vector< NodeRanges_t > TableRanges_t
Definition: ndarr.hxx:138
bool InsBoxen(SwTableNode *, SwTableLine *, SwTableBoxFormat *, SwTextFormatColl *, const SfxItemSet *pAutoAttr, sal_uInt16 nInsPos, sal_uInt16 nCnt=1)
Insert a new box in the line before InsPos.
Definition: ndtbl.cxx:230
void UnProtectCells(const OUString &rTableName)
Definition: ndtbl.cxx:4447
const OUString & GetName() const
Definition: format.hxx:111
bool MakeCopy(SwDoc *, const SwPosition &, const SwSelBoxes &, bool bCpyName=false) const
Definition: tblrwcl.cxx:2045
void SetTableModel(bool bNew)
Definition: swtable.hxx:184
int nCount
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
virtual void UpdateTableFields(SfxPoolItem *pHt)=0
virtual void DelLayoutFormat(SwFrameFormat *pFormat)=0
virtual void SetName(const OUString &rNewName, bool bBroadcast=false) override
Definition: atrfrm.cxx:2493
bool IsTextFrame() const
Definition: frame.hxx:1212
virtual void DoUndo(bool const bDoUndo)=0
Enable/Disable Undo.
bool IsStartNode() const
Definition: node.hxx:624
virtual ~SwTableNode() override
Definition: ndtbl.cxx:2344
void SetTabCols(const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:831
const FndBoxes_t & GetBoxes() const
Definition: tblsel.hxx:203
virtual bool SetFieldsDirty(bool b, const SwNode *pChk, sal_uLong nLen)=0
static void lcl_RemoveBreaks(SwContentNode &rNode, SwTableFormat *const pTableFormat)
Definition: ndtbl.cxx:891
Mode eMode
iterator insert(iterator aIt, SwTableLine *pLine)
Definition: swtable.hxx:84
void SetHTMLTableLayout(std::shared_ptr< SwHTMLTableLayout > const &r)
Definition: swtable.cxx:1944
void CopyHeadlineIntoTable(SwTableNode &rTableNd)
Definition: tblrwcl.cxx:2000
const SwTable & GetTable() const
Definition: node.hxx:497
virtual void DeleteSection(SwNode *pNode)=0
Delete section containing the node.
void DelNodes(const SwNodeIndex &rStart, sal_uLong nCnt=1)
Delete a number of nodes.
Definition: nodes.cxx:1327
const SfxPoolItem * GetDfltAttr(sal_uInt16 nWhich)
Get the default attribute from corresponding default attribute table.
Definition: hints.cxx:153
const OUString & GetTableStyleName() const
Return the table style name of this table.
Definition: swtable.hxx:188
static sal_uInt8 CountPos(sal_uInt32 nCol, sal_uInt32 nCols, sal_uInt32 nRow, sal_uInt32 nRows)
Calculates the relevant position in the table autoformat for a given cell in a given table...
Definition: tblafmt.cxx:914
void SetAllDistances(sal_uInt16 nNew)
long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1357
long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1358
SwTableBox * FindPreviousBox(const SwTable &, const SwTableBox *) const
Definition: tblrwcl.cxx:2312
void UpdateCharts(const OUString &rName) const
Definition: docchart.cxx:120
RedlineFlags on.
bool InsTable(const SwTable &rCpyTable, const SwNodeIndex &, SwUndoTableCpyTable *pUndo)
Copy Table into this Box.
Definition: tblcpy.cxx:705
virtual bool IsEnableSetModified() const =0
size_type size() const
virtual bool DoesUndo() const =0
Is Undo enabled?
void SetRowHeight(const SwCursor &rCursor, const SwFormatFrameSize &rNew)
Definition: ndtbl1.cxx:385
void sw_BoxSetSplitBoxFormats(SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3018
const FndBox_ * GetUpper() const
Definition: tblsel.hxx:207
bool IsGetValues() const
Definition: tblrwcl.hxx:94
SwPaM * GetNext()
Definition: pam.hxx:264
helper class to check if a frame has been deleted during an operation WARNING! This should only be us...
Definition: frmtool.hxx:594
void ClearLineNumAttrs(SwPosition const &rPos)
Definition: ndtbl.cxx:4202
void InsertRow(const SwCursor &rCursor, sal_uInt16 nCnt=1, bool bBehind=true)
Definition: ndtbl.cxx:1770
void DeleteCol(const SwCursor &rCursor)
Definition: ndtbl.cxx:1929
virtual void ModifyNotification(const SfxPoolItem *pOldValue, const SfxPoolItem *pNewValue)
Definition: calbck.hxx:154
Specific frame formats (frames, DrawObjects).
void MakeFrames(SwTable &rTable)
Definition: tblsel.cxx:2333
void SetWidth(long n)
Base class for various Writer styles.
Definition: format.hxx:43
void SetTableNodeOffset(sal_uLong nIdx)
Definition: UndoTable.hxx:329
virtual void Paste(SwFrame *pParent, SwFrame *pSibling=nullptr)=0
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:163
Class for SplitTable Collects the uppermost or lowermost Lines of a Box from a Line in an array...
Definition: tblrwcl.hxx:61
virtual bool ResetAttr(sal_uInt16 nWhich1, sal_uInt16 nWhich2=0)
Definition: node.cxx:1652
SwTableSortBoxes & GetTabSortBoxes()
Definition: swtable.hxx:259
Table of Contents - heading.
Definition: poolfmt.hxx:341
bool IsContentNode() const
Definition: node.hxx:628
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
std::unique_ptr< SwTableAutoFormatTable > m_pTableStyles
Table styles (autoformats that are applied with table changes).
Definition: doc.hxx:282
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:443
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:501
const editeng::SvxBorderLine * GetTop() const
static SwTable * FindTable(SwFrameFormat const *const pFormat)
Definition: swtable.cxx:1922
virtual void AppendUndo(std::unique_ptr< SwUndo > pUndo)=0
Add new Undo action.
SwTabFrame * ImplFindTabFrame()
Definition: findfrm.cxx:468
virtual void ClearRedo()=0
Delete all Redo actions.
bool SetColWidth(SwTableBox &rCurrentBox, TableChgWidthHeightType eType, SwTwips nAbsDiff, SwTwips nRelDiff, std::unique_ptr< SwUndo > *ppUndo)
Definition: tblrwcl.cxx:2592
Style of a layout element.
Definition: frmfmt.hxx:57
::sw::UndoManager & GetUndoManager()
Definition: doc.cxx:133
bool GoNext(SwNode *pNd, SwIndex *pIdx, sal_uInt16 nMode)
Definition: pam.cxx:288
virtual SwUndoId StartUndo(SwUndoId const eUndoId, SwRewriter const *const pRewriter)=0
Opens undo block.
SwNodeType
Definition: ndtyp.hxx:28
#define SAL_MAX_INT32
virtual const SwExtraRedlineTable & GetExtraRedlineTable() const =0
void Broadcast(const SfxHint &rHint)
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
void SetTableLines(const SwSelBoxes &rBoxes, const SwTable &rTable)
Definition: tblsel.cxx:2110
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:81
int i
static void lcl_DelLine(SwTableLine *pLine, DelTabPara *pPara)
Definition: ndtbl.cxx:1518
bool GoInNode(SwPaM &rPam, SwMoveFnCollection const &fnMove)
Definition: pam.cxx:954
void GetTableSel(const SwCursorShell &rShell, SwSelBoxes &rBoxes, const SwTableSearchType eSearchType)
Definition: tblsel.cxx:149
SwEndNode * GetEndNode()
Definition: node.hxx:583
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:131
const SwPosition * GetPoint() const
Definition: pam.hxx:207
bool empty() const
Definition: swtable.hxx:73
bool DeleteSel(SwDoc *, const SwSelBoxes &rBoxes, const SwSelBoxes *pMerged, SwUndo *pUndo, const bool bDelMakeFrames, const bool bCorrBorder)
Definition: tblrwcl.cxx:933
constexpr sal_uInt16 RES_PARATR_LIST_END(88)
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:65
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:327
bool HasDirectFormatting() const
Do we contain any direct formatting (ie. something not affected by the table style)?
Definition: swtable.hxx:432