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  {
906  const SfxPoolItem* pItem;
907  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false, &pItem))
908  {
909  if (pTableFormat)
910  {
911  pTableFormat->SetFormatAttr(*pItem);
912  }
913  rTextNode.ResetAttr(RES_BREAK);
914  pSet = rTextNode.GetpSwAttrSet();
915  }
916 
917  if (pSet
918  && (SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false, &pItem))
919  && static_cast<SwFormatPageDesc const*>(pItem)->GetPageDesc())
920  {
921  if (pTableFormat)
922  {
923  pTableFormat->SetFormatAttr(*pItem);
924  }
925  rTextNode.ResetAttr(RES_PAGEDESC);
926  }
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 
2302  // Merge them
2303  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
2304  aMsgHint.m_eFlags = TBL_BOXPTR;
2306 
2307  if( pTableNd->GetTable().Merge( this, aBoxes, aMerged, pMergeBox, pUndo.get() ))
2308  {
2309  nRet = TableMergeErr::Ok;
2310 
2312  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
2313  if( pUndo )
2314  {
2315  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
2316  }
2317  }
2318 
2319  rPam.GetPoint()->nNode = *pMergeBox->GetSttNd();
2320  rPam.Move();
2321 
2322  ::ClearFEShellTabCols(*this, nullptr);
2324  }
2326  return nRet;
2327 }
2328 
2330  : SwStartNode( rIdx, SwNodeType::Table )
2331 {
2332  m_pTable.reset(new SwTable);
2333 }
2334 
2336 {
2337  // Notify UNO wrappers
2338  GetTable().GetFrameFormat()->GetNotifier().Broadcast(SfxHint(SfxHintId::Dying));
2339  DelFrames();
2340  m_pTable->SetTableNode(this); // set this so that ~SwDDETable can read it!
2341  m_pTable.reset();
2342 }
2343 
2345 {
2346  return new SwTabFrame( *m_pTable, pSib );
2347 }
2348 
2354 {
2355  if( !GetTable().GetFrameFormat()->HasWriterListeners()) // Do we actually have Frame?
2356  return;
2357 
2358  SwFrame *pFrame;
2359  SwContentNode * pNode = rIdx.GetNode().GetContentNode();
2360 
2361  OSL_ENSURE( pNode, "No ContentNode or CopyNode and new Node is identical");
2362 
2363  bool bBefore = rIdx < GetIndex();
2364 
2365  SwNode2Layout aNode2Layout( *this, rIdx.GetIndex() );
2366 
2367  while( nullptr != (pFrame = aNode2Layout.NextFrame()) )
2368  {
2369  if (pFrame->getRootFrame()->IsHideRedlines()
2370  && !pNode->IsCreateFrameWhenHidingRedlines())
2371  {
2372  continue;
2373  }
2374  SwFrame *pNew = pNode->MakeFrame( pFrame );
2375  // Will the Node receive Frames before or after?
2376  if ( bBefore )
2377  // The new one precedes me
2378  pNew->Paste( pFrame->GetUpper(), pFrame );
2379  else
2380  // The new one succeeds me
2381  pNew->Paste( pFrame->GetUpper(), pFrame->GetNext() );
2382  }
2383 }
2384 
2389 {
2390  OSL_ENSURE( pIdxBehind, "No Index" );
2391  *pIdxBehind = *this;
2392  SwNode *pNd = GetNodes().FindPrvNxtFrameNode( *pIdxBehind, EndOfSectionNode() );
2393  if( !pNd )
2394  return ;
2395 
2396  SwFrame *pFrame( nullptr );
2397  SwLayoutFrame *pUpper( nullptr );
2398  SwNode2Layout aNode2Layout( *pNd, GetIndex() );
2399  while( nullptr != (pUpper = aNode2Layout.UpperFrame( pFrame, *this )) )
2400  {
2401  if (pUpper->getRootFrame()->IsHideRedlines()
2403  {
2404  continue;
2405  }
2406  SwTabFrame* pNew = MakeFrame( pUpper );
2407  pNew->Paste( pUpper, pFrame );
2408  // #i27138#
2409  // notify accessibility paragraphs objects about changed
2410  // CONTENT_FLOWS_FROM/_TO relation.
2411  // Relation CONTENT_FLOWS_FROM for next paragraph will change
2412  // and relation CONTENT_FLOWS_TO for previous paragraph will change.
2413  {
2414  SwViewShell* pViewShell( pNew->getRootFrame()->GetCurrShell() );
2415  if ( pViewShell && pViewShell->GetLayout() &&
2416  pViewShell->GetLayout()->IsAnyShellAccessible() )
2417  {
2419  dynamic_cast<SwTextFrame*>(pNew->FindNextCnt( true )),
2420  dynamic_cast<SwTextFrame*>(pNew->FindPrevCnt()) );
2421  }
2422  }
2423  pNew->RegistFlys();
2424  }
2425 }
2426 
2427 void SwTableNode::DelFrames(SwRootFrame const*const pLayout)
2428 {
2429  /* For a start, cut out and delete the TabFrames (which will also delete the Columns and Rows)
2430  The TabFrames are attached to the FrameFormat of the SwTable.
2431  We need to delete them in a more cumbersome way, for the Master to also delete the Follows. */
2432 
2433  SwIterator<SwTabFrame,SwFormat> aIter( *(m_pTable->GetFrameFormat()) );
2434  SwTabFrame *pFrame = aIter.First();
2435  while ( pFrame )
2436  {
2437  bool bAgain = false;
2438  {
2439  if (!pFrame->IsFollow() && (!pLayout || pLayout == pFrame->getRootFrame()))
2440  {
2441  while ( pFrame->HasFollow() )
2442  pFrame->JoinAndDelFollows();
2443  // #i27138#
2444  // notify accessibility paragraphs objects about changed
2445  // CONTENT_FLOWS_FROM/_TO relation.
2446  // Relation CONTENT_FLOWS_FROM for current next paragraph will change
2447  // and relation CONTENT_FLOWS_TO for current previous paragraph will change.
2448  {
2449  SwViewShell* pViewShell( pFrame->getRootFrame()->GetCurrShell() );
2450  if ( pViewShell && pViewShell->GetLayout() &&
2451  pViewShell->GetLayout()->IsAnyShellAccessible() )
2452  {
2454  dynamic_cast<SwTextFrame*>(pFrame->FindNextCnt( true )),
2455  dynamic_cast<SwTextFrame*>(pFrame->FindPrevCnt()) );
2456  }
2457  }
2458  pFrame->Cut();
2459  SwFrame::DestroyFrame(pFrame);
2460  bAgain = true;
2461  }
2462  }
2463  pFrame = bAgain ? aIter.First() : aIter.Next();
2464  }
2465 }
2466 
2467 void SwTableNode::SetNewTable( std::unique_ptr<SwTable> pNewTable, bool bNewFrames )
2468 {
2469  DelFrames();
2470  m_pTable->SetTableNode(this);
2471  m_pTable = std::move(pNewTable);
2472  if( bNewFrames )
2473  {
2474  SwNodeIndex aIdx( *EndOfSectionNode());
2475  GetNodes().GoNext( &aIdx );
2476  MakeOwnFrames(&aIdx);
2477  }
2478 }
2479 
2481 {
2482  SwDoc* pDoc = GetDoc();
2483  if (pDoc)
2484  {
2485  SwTable& rTable = GetTable();
2487  pDoc->getIDocumentRedlineAccess().GetExtraRedlineTable().DeleteAllTableRedlines( pDoc, rTable, true, RedlineType::Any );
2488  }
2489 }
2490 
2491 void SwDoc::GetTabCols( SwTabCols &rFill, const SwCellFrame* pBoxFrame )
2492 {
2493  OSL_ENSURE( pBoxFrame, "pBoxFrame needs to be specified!" );
2494  if( !pBoxFrame )
2495  return;
2496 
2497  SwTabFrame *pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2498  const SwTableBox* pBox = pBoxFrame->GetTabBox();
2499 
2500  // Set fixed points, LeftMin in Document coordinates, all others relative
2501  SwRectFnSet aRectFnSet(pTab);
2502  const SwPageFrame* pPage = pTab->FindPageFrame();
2503  const sal_uLong nLeftMin = aRectFnSet.GetLeft(pTab->getFrameArea()) -
2504  aRectFnSet.GetLeft(pPage->getFrameArea());
2505  const sal_uLong nRightMax = aRectFnSet.GetRight(pTab->getFrameArea()) -
2506  aRectFnSet.GetLeft(pPage->getFrameArea());
2507 
2508  rFill.SetLeftMin ( nLeftMin );
2509  rFill.SetLeft ( aRectFnSet.GetLeft(pTab->getFramePrintArea()) );
2510  rFill.SetRight ( aRectFnSet.GetRight(pTab->getFramePrintArea()));
2511  rFill.SetRightMax( nRightMax - nLeftMin );
2512 
2513  pTab->GetTable()->GetTabCols( rFill, pBox );
2514 }
2515 
2516 // Here are some little helpers used in SwDoc::GetTabRows
2517 
2518 #define ROWFUZZY 25
2519 
2520 namespace {
2521 
2522 struct FuzzyCompare
2523 {
2524  bool operator() ( long s1, long s2 ) const;
2525 };
2526 
2527 }
2528 
2529 bool FuzzyCompare::operator() ( long s1, long s2 ) const
2530 {
2531  return ( s1 < s2 && std::abs( s1 - s2 ) > ROWFUZZY );
2532 }
2533 
2534 static bool lcl_IsFrameInColumn( const SwCellFrame& rFrame, SwSelBoxes const & rBoxes )
2535 {
2536  for (size_t i = 0; i < rBoxes.size(); ++i)
2537  {
2538  if ( rFrame.GetTabBox() == rBoxes[ i ] )
2539  return true;
2540  }
2541 
2542  return false;
2543 }
2544 
2545 void SwDoc::GetTabRows( SwTabCols &rFill, const SwCellFrame* pBoxFrame )
2546 {
2547  OSL_ENSURE( pBoxFrame, "GetTabRows called without pBoxFrame" );
2548 
2549  // Make code robust:
2550  if ( !pBoxFrame )
2551  return;
2552 
2553  // #i39552# Collection of the boxes of the current
2554  // column has to be done at the beginning of this function, because
2555  // the table may be formatted in ::GetTableSel.
2556  SwDeletionChecker aDelCheck( pBoxFrame );
2557 
2558  SwSelBoxes aBoxes;
2559  const SwContentFrame* pContent = ::GetCellContent( *pBoxFrame );
2560  if ( pContent && pContent->IsTextFrame() )
2561  {
2562  const SwPosition aPos(*static_cast<const SwTextFrame*>(pContent)->GetTextNodeFirst());
2563  const SwCursor aTmpCursor( aPos, nullptr );
2564  ::GetTableSel( aTmpCursor, aBoxes, SwTableSearchType::Col );
2565  }
2566 
2567  // Make code robust:
2568  if ( aDelCheck.HasBeenDeleted() )
2569  {
2570  OSL_FAIL( "Current box has been deleted during GetTabRows()" );
2571  return;
2572  }
2573 
2574  // Make code robust:
2575  const SwTabFrame* pTab = pBoxFrame->FindTabFrame();
2576  OSL_ENSURE( pTab, "GetTabRows called without a table" );
2577  if ( !pTab )
2578  return;
2579 
2580  const SwFrame* pFrame = pTab->GetNextLayoutLeaf();
2581 
2582  // Set fixed points, LeftMin in Document coordinates, all others relative
2583  SwRectFnSet aRectFnSet(pTab);
2584  const SwPageFrame* pPage = pTab->FindPageFrame();
2585  const long nLeftMin = ( aRectFnSet.IsVert() ?
2586  pTab->GetPrtLeft() - pPage->getFrameArea().Left() :
2587  pTab->GetPrtTop() - pPage->getFrameArea().Top() );
2588  const long nLeft = aRectFnSet.IsVert() ? LONG_MAX : 0;
2589  const long nRight = aRectFnSet.GetHeight(pTab->getFramePrintArea());
2590  const long nRightMax = aRectFnSet.IsVert() ? nRight : LONG_MAX;
2591 
2592  rFill.SetLeftMin( nLeftMin );
2593  rFill.SetLeft( nLeft );
2594  rFill.SetRight( nRight );
2595  rFill.SetRightMax( nRightMax );
2596 
2597  typedef std::map< long, std::pair< long, long >, FuzzyCompare > BoundaryMap;
2598  BoundaryMap aBoundaries;
2599  BoundaryMap::iterator aIter;
2600  std::pair< long, long > aPair;
2601 
2602  typedef std::map< long, bool > HiddenMap;
2603  HiddenMap aHidden;
2604  HiddenMap::iterator aHiddenIter;
2605 
2606  while ( pFrame && pTab->IsAnLower( pFrame ) )
2607  {
2608  if ( pFrame->IsCellFrame() && pFrame->FindTabFrame() == pTab )
2609  {
2610  // upper and lower borders of current cell frame:
2611  long nUpperBorder = aRectFnSet.GetTop(pFrame->getFrameArea());
2612  long nLowerBorder = aRectFnSet.GetBottom(pFrame->getFrameArea());
2613 
2614  // get boundaries for nUpperBorder:
2615  aIter = aBoundaries.find( nUpperBorder );
2616  if ( aIter == aBoundaries.end() )
2617  {
2618  aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2619  aBoundaries[ nUpperBorder ] = aPair;
2620  }
2621 
2622  // get boundaries for nLowerBorder:
2623  aIter = aBoundaries.find( nLowerBorder );
2624  if ( aIter == aBoundaries.end() )
2625  {
2626  aPair.first = nUpperBorder; aPair.second = LONG_MAX;
2627  }
2628  else
2629  {
2630  nLowerBorder = (*aIter).first;
2631  long nNewLowerBorderUpperBoundary = std::max( (*aIter).second.first, nUpperBorder );
2632  aPair.first = nNewLowerBorderUpperBoundary; aPair.second = LONG_MAX;
2633  }
2634  aBoundaries[ nLowerBorder ] = aPair;
2635 
2636  // calculate hidden flags for entry nUpperBorder/nLowerBorder:
2637  long nTmpVal = nUpperBorder;
2638  for ( sal_uInt8 i = 0; i < 2; ++i )
2639  {
2640  aHiddenIter = aHidden.find( nTmpVal );
2641  if ( aHiddenIter == aHidden.end() )
2642  aHidden[ nTmpVal ] = !lcl_IsFrameInColumn( *static_cast<const SwCellFrame*>(pFrame), aBoxes );
2643  else
2644  {
2645  if ( aHidden[ nTmpVal ] &&
2646  lcl_IsFrameInColumn( *static_cast<const SwCellFrame*>(pFrame), aBoxes ) )
2647  aHidden[ nTmpVal ] = false;
2648  }
2649  nTmpVal = nLowerBorder;
2650  }
2651  }
2652 
2653  pFrame = pFrame->GetNextLayoutLeaf();
2654  }
2655 
2656  // transfer calculated values from BoundaryMap and HiddenMap into rFill:
2657  size_t nIdx = 0;
2658  for ( const auto& rEntry : aBoundaries )
2659  {
2660  const long nTabTop = aRectFnSet.GetPrtTop(*pTab);
2661  const long nKey = aRectFnSet.YDiff( rEntry.first, nTabTop );
2662  const std::pair< long, long > aTmpPair = rEntry.second;
2663  const long nFirst = aRectFnSet.YDiff( aTmpPair.first, nTabTop );
2664  const long nSecond = aTmpPair.second;
2665 
2666  aHiddenIter = aHidden.find( rEntry.first );
2667  const bool bHidden = aHiddenIter != aHidden.end() && (*aHiddenIter).second;
2668  rFill.Insert( nKey, nFirst, nSecond, bHidden, nIdx++ );
2669  }
2670 
2671  // delete first and last entry
2672  OSL_ENSURE( rFill.Count(), "Deleting from empty vector. Fasten your seatbelts!" );
2673  // #i60818# There may be only one entry in rFill. Make
2674  // code robust by checking count of rFill.
2675  if ( rFill.Count() ) rFill.Remove( 0 );
2676  if ( rFill.Count() ) rFill.Remove( rFill.Count() - 1 );
2677  rFill.SetLastRowAllowedToChange( !pTab->HasFollowFlowLine() );
2678 }
2679 
2680 void SwDoc::SetTabCols( const SwTabCols &rNew, bool bCurRowOnly,
2681  const SwCellFrame* pBoxFrame )
2682 {
2683  const SwTableBox* pBox = nullptr;
2684  SwTabFrame *pTab = nullptr;
2685 
2686  if( pBoxFrame )
2687  {
2688  pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2689  pBox = pBoxFrame->GetTabBox();
2690  }
2691  else
2692  {
2693  OSL_ENSURE( false, "must specify pBoxFrame" );
2694  return ;
2695  }
2696 
2697  // If the Table is still using relative values (USHRT_MAX)
2698  // we need to switch to absolute ones.
2699  SwTable& rTab = *pTab->GetTable();
2700  const SwFormatFrameSize& rTableFrameSz = rTab.GetFrameFormat()->GetFrameSize();
2701  SwRectFnSet aRectFnSet(pTab);
2702  // #i17174# - With fix for #i9040# the shadow size is taken
2703  // from the table width. Thus, add its left and right size to current table
2704  // printing area width in order to get the correct table size attribute.
2705  SwTwips nPrtWidth = aRectFnSet.GetWidth(pTab->getFramePrintArea());
2706  {
2707  SvxShadowItem aShadow( rTab.GetFrameFormat()->GetShadow() );
2708  nPrtWidth += aShadow.CalcShadowSpace( SvxShadowItemSide::LEFT ) +
2709  aShadow.CalcShadowSpace( SvxShadowItemSide::RIGHT );
2710  }
2711  if( nPrtWidth != rTableFrameSz.GetWidth() )
2712  {
2713  SwFormatFrameSize aSz( rTableFrameSz );
2714  aSz.SetWidth( nPrtWidth );
2715  rTab.GetFrameFormat()->SetFormatAttr( aSz );
2716  }
2717 
2718  SwTabCols aOld( rNew.Count() );
2719 
2720  const SwPageFrame* pPage = pTab->FindPageFrame();
2721  const sal_uLong nLeftMin = aRectFnSet.GetLeft(pTab->getFrameArea()) -
2722  aRectFnSet.GetLeft(pPage->getFrameArea());
2723  const sal_uLong nRightMax = aRectFnSet.GetRight(pTab->getFrameArea()) -
2724  aRectFnSet.GetLeft(pPage->getFrameArea());
2725 
2726  // Set fixed points, LeftMin in Document coordinates, all others relative
2727  aOld.SetLeftMin ( nLeftMin );
2728  aOld.SetLeft ( aRectFnSet.GetLeft(pTab->getFramePrintArea()) );
2729  aOld.SetRight ( aRectFnSet.GetRight(pTab->getFramePrintArea()));
2730  aOld.SetRightMax( nRightMax - nLeftMin );
2731 
2732  rTab.GetTabCols( aOld, pBox );
2733  SetTabCols(rTab, rNew, aOld, pBox, bCurRowOnly );
2734 }
2735 
2736 void SwDoc::SetTabRows( const SwTabCols &rNew, bool bCurColOnly,
2737  const SwCellFrame* pBoxFrame )
2738 {
2739  SwTabFrame *pTab = nullptr;
2740 
2741  if( pBoxFrame )
2742  {
2743  pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pBoxFrame))->ImplFindTabFrame();
2744  }
2745  else
2746  {
2747  OSL_ENSURE( false, "must specify pBoxFrame" );
2748  return ;
2749  }
2750 
2751  // If the Table is still using relative values (USHRT_MAX)
2752  // we need to switch to absolute ones.
2753  SwRectFnSet aRectFnSet(pTab);
2754  SwTabCols aOld( rNew.Count() );
2755 
2756  // Set fixed points, LeftMin in Document coordinates, all others relative
2757  const SwPageFrame* pPage = pTab->FindPageFrame();
2758 
2759  aOld.SetRight( aRectFnSet.GetHeight(pTab->getFramePrintArea()) );
2760  long nLeftMin;
2761  if ( aRectFnSet.IsVert() )
2762  {
2763  nLeftMin = pTab->GetPrtLeft() - pPage->getFrameArea().Left();
2764  aOld.SetLeft ( LONG_MAX );
2765  aOld.SetRightMax( aOld.GetRight() );
2766 
2767  }
2768  else
2769  {
2770  nLeftMin = pTab->GetPrtTop() - pPage->getFrameArea().Top();
2771  aOld.SetLeft ( 0 );
2772  aOld.SetRightMax( LONG_MAX );
2773  }
2774  aOld.SetLeftMin ( nLeftMin );
2775 
2776  GetTabRows( aOld, pBoxFrame );
2777 
2779 
2780  // check for differences between aOld and rNew:
2781  const size_t nCount = rNew.Count();
2782  const SwTable* pTable = pTab->GetTable();
2783  OSL_ENSURE( pTable, "My colleague told me, this couldn't happen" );
2784 
2785  for ( size_t i = 0; i <= nCount; ++i )
2786  {
2787  const size_t nIdxStt = aRectFnSet.IsVert() ? nCount - i : i - 1;
2788  const size_t nIdxEnd = aRectFnSet.IsVert() ? nCount - i - 1 : i;
2789 
2790  const long nOldRowStart = i == 0 ? 0 : aOld[ nIdxStt ];
2791  const long nOldRowEnd = i == nCount ? aOld.GetRight() : aOld[ nIdxEnd ];
2792  const long nOldRowHeight = nOldRowEnd - nOldRowStart;
2793 
2794  const long nNewRowStart = i == 0 ? 0 : rNew[ nIdxStt ];
2795  const long nNewRowEnd = i == nCount ? rNew.GetRight() : rNew[ nIdxEnd ];
2796  const long nNewRowHeight = nNewRowEnd - nNewRowStart;
2797 
2798  const long nDiff = nNewRowHeight - nOldRowHeight;
2799  if ( std::abs( nDiff ) >= ROWFUZZY )
2800  {
2801  // For the old table model pTextFrame and pLine will be set for every box.
2802  // For the new table model pTextFrame will be set if the box is not covered,
2803  // but the pLine will be set if the box is not an overlapping box
2804  // In the new table model the row height can be adjusted,
2805  // when both variables are set.
2806  const SwTextFrame* pTextFrame = nullptr;
2807  const SwTableLine* pLine = nullptr;
2808 
2809  // Iterate over all SwCellFrames with Bottom = nOldPos
2810  const SwFrame* pFrame = pTab->GetNextLayoutLeaf();
2811  while ( pFrame && pTab->IsAnLower( pFrame ) )
2812  {
2813  if ( pFrame->IsCellFrame() && pFrame->FindTabFrame() == pTab )
2814  {
2815  const long nLowerBorder = aRectFnSet.GetBottom(pFrame->getFrameArea());
2816  const sal_uLong nTabTop = aRectFnSet.GetPrtTop(*pTab);
2817  if ( std::abs( aRectFnSet.YInc( nTabTop, nOldRowEnd ) - nLowerBorder ) <= ROWFUZZY )
2818  {
2819  if ( !bCurColOnly || pFrame == pBoxFrame )
2820  {
2821  const SwFrame* pContent = ::GetCellContent( static_cast<const SwCellFrame&>(*pFrame) );
2822 
2823  if ( pContent && pContent->IsTextFrame() )
2824  {
2825  const SwTableBox* pBox = static_cast<const SwCellFrame*>(pFrame)->GetTabBox();
2826  const long nRowSpan = pBox->getRowSpan();
2827  if( nRowSpan > 0 ) // Not overlapped
2828  pTextFrame = static_cast<const SwTextFrame*>(pContent);
2829  if( nRowSpan < 2 ) // Not overlapping for row height
2830  pLine = pBox->GetUpper();
2831  if( pLine && pTextFrame ) // always for old table model
2832  {
2833  // The new row height must not to be calculated from an overlapping box
2834  SwFormatFrameSize aNew( pLine->GetFrameFormat()->GetFrameSize() );
2835  const long nNewSize = aRectFnSet.GetHeight(pFrame->getFrameArea()) + nDiff;
2836  if( nNewSize != aNew.GetHeight() )
2837  {
2838  aNew.SetHeight( nNewSize );
2839  if ( SwFrameSize::Variable == aNew.GetHeightSizeType() )
2840  aNew.SetHeightSizeType( SwFrameSize::Minimum );
2841  // This position must not be in an overlapped box
2842  const SwPosition aPos(*static_cast<const SwTextFrame*>(pContent)->GetTextNodeFirst());
2843  const SwCursor aTmpCursor( aPos, nullptr );
2844  SetRowHeight( aTmpCursor, aNew );
2845  // For the new table model we're done, for the old one
2846  // there might be another (sub)row to adjust...
2847  if( pTable->IsNewModel() )
2848  break;
2849  }
2850  pLine = nullptr;
2851  }
2852  }
2853  }
2854  }
2855  }
2856  pFrame = pFrame->GetNextLayoutLeaf();
2857  }
2858  }
2859  }
2860 
2862 
2863  ::ClearFEShellTabCols(*this, nullptr);
2864 }
2865 
2869 void SwDoc::SetTabCols(SwTable& rTab, const SwTabCols &rNew, const SwTabCols &rOld,
2870  const SwTableBox *pStart, bool bCurRowOnly )
2871 {
2872  if (GetIDocumentUndoRedo().DoesUndo())
2873  {
2875  std::make_unique<SwUndoAttrTable>( *rTab.GetTableNode(), true ));
2876  }
2877  rTab.SetTabCols( rNew, rOld, pStart, bCurRowOnly );
2878  ::ClearFEShellTabCols(*this, nullptr);
2881 }
2882 
2883 void SwDoc::SetRowsToRepeat( SwTable &rTable, sal_uInt16 nSet )
2884 {
2885  if( nSet == rTable.GetRowsToRepeat() )
2886  return;
2887 
2889  {
2891  std::make_unique<SwUndoTableHeadline>(rTable, rTable.GetRowsToRepeat(), nSet) );
2892  }
2893 
2895  rTable.SetRowsToRepeat( nSet );
2896  rTable.GetFrameFormat()->ModifyNotification( &aChg, &aChg );
2898 }
2899 
2901 {
2902  if( pHst )
2903  pHst->Add( rNd.GetFormatColl(), rNd.GetIndex(), SwNodeType::Text );
2904 }
2905 
2907 {
2908  aPosArr.push_back(nWidth);
2909  SwTableBox* p = const_cast<SwTableBox*>(&rBox);
2910  m_Boxes.push_back(p);
2911  nWidth = nWidth + static_cast<sal_uInt16>(rBox.GetFrameFormat()->GetFrameSize().GetWidth());
2912 }
2913 
2915 {
2916  const SwTableBox* pRet = nullptr;
2917 
2918  if( !aPosArr.empty() )
2919  {
2920  std::vector<sal_uInt16>::size_type n;
2921  for( n = 0; n < aPosArr.size(); ++n )
2922  if( aPosArr[ n ] == nWidth )
2923  break;
2924  else if( aPosArr[ n ] > nWidth )
2925  {
2926  if( n )
2927  --n;
2928  break;
2929  }
2930 
2931  if( n >= aPosArr.size() )
2932  --n;
2933 
2934  nWidth = nWidth + static_cast<sal_uInt16>(rBox.GetFrameFormat()->GetFrameSize().GetWidth());
2935  pRet = m_Boxes[ n ];
2936  }
2937  return pRet;
2938 }
2939 
2940 bool SwCollectTableLineBoxes::Resize( sal_uInt16 nOffset, sal_uInt16 nOldWidth )
2941 {
2942  if( !aPosArr.empty() )
2943  {
2944  std::vector<sal_uInt16>::size_type n;
2945  for( n = 0; n < aPosArr.size(); ++n )
2946  {
2947  if( aPosArr[ n ] == nOffset )
2948  break;
2949  else if( aPosArr[ n ] > nOffset )
2950  {
2951  if( n )
2952  --n;
2953  break;
2954  }
2955  }
2956 
2957  aPosArr.erase( aPosArr.begin(), aPosArr.begin() + n );
2958  m_Boxes.erase(m_Boxes.begin(), m_Boxes.begin() + n);
2959 
2960  size_t nArrSize = aPosArr.size();
2961  if (nArrSize)
2962  {
2963  if (nOldWidth == 0)
2964  throw o3tl::divide_by_zero();
2965 
2966  // Adapt the positions to the new Size
2967  for( n = 0; n < nArrSize; ++n )
2968  {
2969  sal_uLong nSize = nWidth;
2970  nSize *= ( aPosArr[ n ] - nOffset );
2971  nSize /= nOldWidth;
2972  aPosArr[ n ] = sal_uInt16( nSize );
2973  }
2974  }
2975  }
2976  return !aPosArr.empty();
2977 }
2978 
2979 bool sw_Line_CollectBox( const SwTableLine*& rpLine, void* pPara )
2980 {
2981  SwCollectTableLineBoxes* pSplPara = static_cast<SwCollectTableLineBoxes*>(pPara);
2982  if( pSplPara->IsGetValues() )
2983  for( const auto& rpBox : const_cast<SwTableLine*>(rpLine)->GetTabBoxes() )
2984  sw_Box_CollectBox(rpBox, pSplPara );
2985  else
2986  for( auto& rpBox : const_cast<SwTableLine*>(rpLine)->GetTabBoxes() )
2987  sw_BoxSetSplitBoxFormats(rpBox, pSplPara );
2988  return true;
2989 }
2990 
2992 {
2993  auto nLen = pBox->GetTabLines().size();
2994  if( nLen )
2995  {
2996  // Continue with the actual Line
2997  if( pSplPara->IsGetFromTop() )
2998  nLen = 0;
2999  else
3000  --nLen;
3001 
3002  const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3003  sw_Line_CollectBox( pLn, pSplPara );
3004  }
3005  else
3006  pSplPara->AddBox( *pBox );
3007 }
3008 
3010 {
3011  auto nLen = pBox->GetTabLines().size();
3012  if( nLen )
3013  {
3014  // Continue with the actual Line
3015  if( pSplPara->IsGetFromTop() )
3016  nLen = 0;
3017  else
3018  --nLen;
3019 
3020  const SwTableLine* pLn = pBox->GetTabLines()[ nLen ];
3021  sw_Line_CollectBox( pLn, pSplPara );
3022  }
3023  else
3024  {
3025  const SwTableBox* pSrcBox = pSplPara->GetBoxOfPos( *pBox );
3026  SwFrameFormat* pFormat = pSrcBox->GetFrameFormat();
3027 
3028  if( SplitTable_HeadlineOption::BorderCopy == pSplPara->GetMode() )
3029  {
3030  const SvxBoxItem& rBoxItem = pBox->GetFrameFormat()->GetBox();
3031  if( !rBoxItem.GetTop() )
3032  {
3033  SvxBoxItem aNew( rBoxItem );
3034  aNew.SetLine( pFormat->GetBox().GetBottom(), SvxBoxItemLine::TOP );
3035  if( aNew != rBoxItem )
3036  pBox->ClaimFrameFormat()->SetFormatAttr( aNew );
3037  }
3038  }
3039  else
3040  {
3041  sal_uInt16 const aTableSplitBoxSetRange[] {
3046  0 };
3047 
3048  SfxItemSet aTmpSet( pFormat->GetDoc()->GetAttrPool(),
3049  aTableSplitBoxSetRange );
3050  aTmpSet.Put( pFormat->GetAttrSet() );
3051  if( aTmpSet.Count() )
3052  pBox->ClaimFrameFormat()->SetFormatAttr( aTmpSet );
3053 
3055  {
3056  SwNodeIndex aIdx( *pSrcBox->GetSttNd(), 1 );
3057  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3058  if( !pCNd )
3059  pCNd = aIdx.GetNodes().GoNext( &aIdx );
3060  aIdx = *pBox->GetSttNd();
3061  SwContentNode* pDNd = aIdx.GetNodes().GoNext( &aIdx );
3062 
3063  // If the Node is alone in the Section
3064  if( 2 == pDNd->EndOfSectionIndex() -
3065  pDNd->StartOfSectionIndex() )
3066  {
3067  pSplPara->AddToUndoHistory( *pDNd );
3068  pDNd->ChgFormatColl( pCNd->GetFormatColl() );
3069  }
3070  }
3071 
3072  // note conditional template
3073  pBox->GetSttNd()->CheckSectionCondColl();
3074  }
3075  }
3076 }
3077 
3088  bool bCalcNewSize )
3089 {
3090  SwNode* pNd = &rPos.nNode.GetNode();
3091  SwTableNode* pTNd = pNd->FindTableNode();
3092  if( !pTNd || pNd->IsTableNode() )
3093  return false;
3094 
3095  if( dynamic_cast<const SwDDETable*>( &pTNd->GetTable() ) != nullptr)
3096  return false;
3097 
3098  SwTable& rTable = pTNd->GetTable();
3099  rTable.SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>()); // Delete HTML Layout
3100 
3101  SwTableFormulaUpdate aMsgHint( &rTable );
3102 
3103  SwHistory aHistory;
3104  if (GetIDocumentUndoRedo().DoesUndo())
3105  {
3106  aMsgHint.m_pHistory = &aHistory;
3107  }
3108 
3109  {
3110  sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3111 
3112  // Find top-level Line
3113  SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3114  if( pBox )
3115  {
3116  SwTableLine* pLine = pBox->GetUpper();
3117  while( pLine->GetUpper() )
3118  pLine = pLine->GetUpper()->GetUpper();
3119 
3120  // pLine contains the top-level Line now
3121  aMsgHint.m_nSplitLine = rTable.GetTabLines().GetPos( pLine );
3122  }
3123 
3124  OUString sNewTableNm( GetUniqueTableName() );
3125  aMsgHint.m_aData.pNewTableNm = &sNewTableNm;
3126  aMsgHint.m_eFlags = TBL_SPLITTBL;
3128  }
3129 
3130  // Find Lines for the Layout update
3131  FndBox_ aFndBox( nullptr, nullptr );
3132  aFndBox.SetTableLines( rTable );
3133  aFndBox.DelFrames( rTable );
3134 
3135  SwTableNode* pNew = GetNodes().SplitTable( rPos.nNode, false, bCalcNewSize );
3136 
3137  if( pNew )
3138  {
3139  std::unique_ptr<SwSaveRowSpan> pSaveRowSp = pNew->GetTable().CleanUpTopRowSpan( rTable.GetTabLines().size() );
3140  SwUndoSplitTable* pUndo = nullptr;
3142  {
3143  pUndo = new SwUndoSplitTable(
3144  *pNew, std::move(pSaveRowSp), eHdlnMode, bCalcNewSize);
3145  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3146  if( aHistory.Count() )
3147  pUndo->SaveFormula( aHistory );
3148  }
3149 
3150  switch( eHdlnMode )
3151  {
3152  // Set the lower Border of the preceding Line to
3153  // the upper Border of the current one
3155  {
3156  SwCollectTableLineBoxes aPara( false, eHdlnMode );
3157  SwTableLine* pLn = rTable.GetTabLines()[
3158  rTable.GetTabLines().size() - 1 ];
3159  for( const auto& rpBox : pLn->GetTabBoxes() )
3160  sw_Box_CollectBox(rpBox, &aPara );
3161 
3162  aPara.SetValues( true );
3163  pLn = pNew->GetTable().GetTabLines()[ 0 ];
3164  for( auto& rpBox : pLn->GetTabBoxes() )
3165  sw_BoxSetSplitBoxFormats(rpBox, &aPara );
3166 
3167  // Switch off repeating Header
3168  pNew->GetTable().SetRowsToRepeat( 0 );
3169  }
3170  break;
3171 
3172  // Take over the Attributes of the first Line to the new one
3175  {
3176  SwHistory* pHst = nullptr;
3177  if( SplitTable_HeadlineOption::BoxAttrAllCopy == eHdlnMode && pUndo )
3178  pHst = pUndo->GetHistory();
3179 
3180  SwCollectTableLineBoxes aPara( true, eHdlnMode, pHst );
3181  SwTableLine* pLn = rTable.GetTabLines()[ 0 ];
3182  for( const auto& rpBox : pLn->GetTabBoxes() )
3183  sw_Box_CollectBox(rpBox, &aPara );
3184 
3185  aPara.SetValues( true );
3186  pLn = pNew->GetTable().GetTabLines()[ 0 ];
3187  for( auto& rpBox : pLn->GetTabBoxes() )
3188  sw_BoxSetSplitBoxFormats(rpBox, &aPara );
3189  }
3190  break;
3191 
3193  rTable.CopyHeadlineIntoTable( *pNew );
3194  if( pUndo )
3195  pUndo->SetTableNodeOffset( pNew->GetIndex() );
3196  break;
3197 
3199  // Switch off repeating the Header
3200  pNew->GetTable().SetRowsToRepeat( 0 );
3201  break;
3202  }
3203 
3204  // And insert Frames
3205  SwNodeIndex aNdIdx( *pNew->EndOfSectionNode() );
3206  GetNodes().GoNext( &aNdIdx ); // To the next ContentNode
3207  pNew->MakeOwnFrames( &aNdIdx );
3208 
3209  // Insert a paragraph between the Table
3210  GetNodes().MakeTextNode( SwNodeIndex( *pNew ),
3211  getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
3212  }
3213 
3214  // Update Layout
3215  aFndBox.MakeFrames( rTable );
3216 
3217  // TL_CHART2: need to inform chart of probably changed cell names
3218  UpdateCharts( rTable.GetFrameFormat()->GetName() );
3219 
3220  // update table style formatting of both the tables
3223 
3224  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3225 
3226  return nullptr != pNew;
3227 }
3228 
3229 static bool lcl_ChgTableSize( SwTable& rTable )
3230 {
3231  // The Attribute must not be set via the Modify or else all Boxes are
3232  // set back to 0.
3233  // So lock the Format.
3234  SwFrameFormat* pFormat = rTable.GetFrameFormat();
3235  SwFormatFrameSize aTableMaxSz( pFormat->GetFrameSize() );
3236 
3237  if( USHRT_MAX == aTableMaxSz.GetWidth() )
3238  return false;
3239 
3240  bool bLocked = pFormat->IsModifyLocked();
3241  pFormat->LockModify();
3242 
3243  aTableMaxSz.SetWidth( 0 );
3244 
3245  SwTableLines& rLns = rTable.GetTabLines();
3246  for( auto pLn : rLns )
3247  {
3248  SwTwips nMaxLnWidth = 0;
3249  SwTableBoxes& rBoxes = pLn->GetTabBoxes();
3250  for( auto pBox : rBoxes )
3251  nMaxLnWidth += pBox->GetFrameFormat()->GetFrameSize().GetWidth();
3252 
3253  if( nMaxLnWidth > aTableMaxSz.GetWidth() )
3254  aTableMaxSz.SetWidth( nMaxLnWidth );
3255  }
3256  pFormat->SetFormatAttr( aTableMaxSz );
3257  if( !bLocked ) // Release the Lock if appropriate
3258  pFormat->UnlockModify();
3259 
3260  return true;
3261 }
3262 
3263 namespace {
3264 
3265 class SplitTable_Para
3266 {
3267  std::map<SwFrameFormat const *, SwFrameFormat*> aSrcDestMap;
3268  SwTableNode* pNewTableNd;
3269  SwTable& rOldTable;
3270 
3271 public:
3272  SplitTable_Para( SwTableNode* pNew, SwTable& rOld )
3273  : aSrcDestMap(), pNewTableNd( pNew ), rOldTable( rOld )
3274  {}
3275  SwFrameFormat* GetDestFormat( SwFrameFormat* pSrcFormat ) const
3276  {
3277  auto it = aSrcDestMap.find( pSrcFormat );
3278  return it == aSrcDestMap.end() ? nullptr : it->second;
3279  }
3280 
3281  void InsertSrcDest( SwFrameFormat const * pSrcFormat, SwFrameFormat* pDestFormat )
3282  { aSrcDestMap[ pSrcFormat ] = pDestFormat; }
3283 
3284  void ChgBox( SwTableBox* pBox )
3285  {
3286  rOldTable.GetTabSortBoxes().erase( pBox );
3287  pNewTableNd->GetTable().GetTabSortBoxes().insert( pBox );
3288  }
3289 };
3290 
3291 }
3292 
3293 static void lcl_SplitTable_CpyBox( SwTableBox* pBox, SplitTable_Para* pPara );
3294 
3295 static void lcl_SplitTable_CpyLine( SwTableLine* pLn, SplitTable_Para* pPara )
3296 {
3297  SwFrameFormat *pSrcFormat = pLn->GetFrameFormat();
3298  SwTableLineFormat* pDestFormat = static_cast<SwTableLineFormat*>( pPara->GetDestFormat( pSrcFormat ) );
3299  if( pDestFormat == nullptr )
3300  {
3301  pPara->InsertSrcDest( pSrcFormat, pLn->ClaimFrameFormat() );
3302  }
3303  else
3304  pLn->ChgFrameFormat( pDestFormat );
3305 
3306  for( auto& rpBox : pLn->GetTabBoxes() )
3307  lcl_SplitTable_CpyBox(rpBox, pPara );
3308 }
3309 
3310 static void lcl_SplitTable_CpyBox( SwTableBox* pBox, SplitTable_Para* pPara )
3311 {
3312  SwFrameFormat *pSrcFormat = pBox->GetFrameFormat();
3313  SwTableBoxFormat* pDestFormat = static_cast<SwTableBoxFormat*>(pPara->GetDestFormat( pSrcFormat ));
3314  if( pDestFormat == nullptr )
3315  {
3316  pPara->InsertSrcDest( pSrcFormat, pBox->ClaimFrameFormat() );
3317  }
3318  else
3319  pBox->ChgFrameFormat( pDestFormat );
3320 
3321  if( pBox->GetSttNd() )
3322  pPara->ChgBox( pBox );
3323  else
3324  for( SwTableLine* pLine : pBox->GetTabLines() )
3325  lcl_SplitTable_CpyLine( pLine, pPara );
3326 }
3327 
3328 SwTableNode* SwNodes::SplitTable( const SwNodeIndex& rPos, bool bAfter,
3329  bool bCalcNewSize )
3330 {
3331  SwNode* pNd = &rPos.GetNode();
3332  SwTableNode* pTNd = pNd->FindTableNode();
3333  if( !pTNd || pNd->IsTableNode() )
3334  return nullptr;
3335 
3336  sal_uLong nSttIdx = pNd->FindTableBoxStartNode()->GetIndex();
3337 
3338  // Find this Box/top-level line
3339  SwTable& rTable = pTNd->GetTable();
3340  SwTableBox* pBox = rTable.GetTableBox( nSttIdx );
3341  if( !pBox )
3342  return nullptr;
3343 
3344  SwTableLine* pLine = pBox->GetUpper();
3345  while( pLine->GetUpper() )
3346  pLine = pLine->GetUpper()->GetUpper();
3347 
3348  // pLine now contains the top-level line
3349  sal_uInt16 nLinePos = rTable.GetTabLines().GetPos( pLine );
3350  if( USHRT_MAX == nLinePos ||
3351  ( bAfter ? ++nLinePos >= rTable.GetTabLines().size() : !nLinePos ))
3352  return nullptr; // Not found or last Line!
3353 
3354  // Find the first Box of the succeeding Line
3355  SwTableLine* pNextLine = rTable.GetTabLines()[ nLinePos ];
3356  pBox = pNextLine->GetTabBoxes()[0];
3357  while( !pBox->GetSttNd() )
3358  pBox = pBox->GetTabLines()[0]->GetTabBoxes()[0];
3359 
3360  // Insert an EndNode and TableNode into the Nodes Array
3361  SwTableNode * pNewTableNd;
3362  {
3363  SwEndNode* pOldTableEndNd = pTNd->EndOfSectionNode()->GetEndNode();
3364  assert(pOldTableEndNd && "Where is the EndNode?");
3365 
3366  SwNodeIndex aIdx( *pBox->GetSttNd() );
3367  new SwEndNode( aIdx, *pTNd );
3368  pNewTableNd = new SwTableNode( aIdx );
3369  pNewTableNd->GetTable().SetTableModel( rTable.IsNewModel() );
3370 
3371  pOldTableEndNd->m_pStartOfSection = pNewTableNd;
3372  pNewTableNd->m_pEndOfSection = pOldTableEndNd;
3373 
3374  SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3375  do {
3376  OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3377  pBoxNd->m_pStartOfSection = pNewTableNd;
3378  pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3379  } while( pBoxNd != pOldTableEndNd );
3380  }
3381 
3382  {
3383  // Move the Lines
3384  SwTable& rNewTable = pNewTableNd->GetTable();
3385  rNewTable.GetTabLines().insert( rNewTable.GetTabLines().begin(),
3386  rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3387 
3388  /* From the back (bottom right) to the front (top left) deregister all Boxes from the
3389  Chart Data Provider. The Modify event is triggered in the calling function.
3390  TL_CHART2: */
3392  if( pPCD )
3393  {
3394  for (SwTableLines::size_type k = nLinePos; k < rTable.GetTabLines().size(); ++k)
3395  {
3396  const SwTableLines::size_type nLineIdx = (rTable.GetTabLines().size() - 1) - k + nLinePos;
3397  const SwTableBoxes::size_type nBoxCnt = rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes().size();
3398  for (SwTableBoxes::size_type j = 0; j < nBoxCnt; ++j)
3399  {
3400  const SwTableBoxes::size_type nIdx = nBoxCnt - 1 - j;
3401  pPCD->DeleteBox( &rTable, *rTable.GetTabLines()[ nLineIdx ]->GetTabBoxes()[nIdx] );
3402  }
3403  }
3404  }
3405 
3406  // Delete
3407  sal_uInt16 nDeleted = rTable.GetTabLines().size() - nLinePos;
3408  rTable.GetTabLines().erase( rTable.GetTabLines().begin() + nLinePos, rTable.GetTabLines().end() );
3409 
3410  // Move the affected Boxes. Make the Formats unique and correct the StartNodes
3411  SplitTable_Para aPara( pNewTableNd, rTable );
3412  for( SwTableLine* pNewLine : rNewTable.GetTabLines() )
3413  lcl_SplitTable_CpyLine( pNewLine, &aPara );
3414  rTable.CleanUpBottomRowSpan( nDeleted );
3415  }
3416 
3417  {
3418  // Copy the Table FrameFormat
3419  SwFrameFormat* pOldTableFormat = rTable.GetFrameFormat();
3420  SwFrameFormat* pNewTableFormat = pOldTableFormat->GetDoc()->MakeTableFrameFormat(
3421  pOldTableFormat->GetDoc()->GetUniqueTableName(),
3422  pOldTableFormat->GetDoc()->GetDfltFrameFormat() );
3423 
3424  *pNewTableFormat = *pOldTableFormat;
3425  pNewTableNd->GetTable().RegisterToFormat( *pNewTableFormat );
3426 
3427  pNewTableNd->GetTable().SetTableStyleName(rTable.GetTableStyleName());
3428 
3429  // Calculate a new Size?
3430  // lcl_ChgTableSize: Only execute the second call if the first call was
3431  // successful, thus has an absolute Size
3432  if( bCalcNewSize && lcl_ChgTableSize( rTable ) )
3433  lcl_ChgTableSize( pNewTableNd->GetTable() );
3434  }
3435 
3436  // TL_CHART2: need to inform chart of probably changed cell names
3437  rTable.UpdateCharts();
3438 
3439  return pNewTableNd; // That's it!
3440 }
3441 
3448 bool SwDoc::MergeTable( const SwPosition& rPos, bool bWithPrev, sal_uInt16 nMode )
3449 {
3450  SwTableNode* pTableNd = rPos.nNode.GetNode().FindTableNode(), *pDelTableNd;
3451  if( !pTableNd )
3452  return false;
3453 
3454  SwNodes& rNds = GetNodes();
3455  if( bWithPrev )
3456  pDelTableNd = rNds[ pTableNd->GetIndex() - 1 ]->FindTableNode();
3457  else
3458  pDelTableNd = rNds[ pTableNd->EndOfSectionIndex() + 1 ]->GetTableNode();
3459  if( !pDelTableNd )
3460  return false;
3461 
3462  if( dynamic_cast<const SwDDETable*>( &pTableNd->GetTable() ) != nullptr ||
3463  dynamic_cast<const SwDDETable*>( &pDelTableNd->GetTable() ) != nullptr)
3464  return false;
3465 
3466  // Delete HTML Layout
3467  pTableNd->GetTable().SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3468  pDelTableNd->GetTable().SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3469 
3470  // Both Tables are present; we can start
3471  SwUndoMergeTable* pUndo = nullptr;
3472  std::unique_ptr<SwHistory> pHistory;
3473  if (GetIDocumentUndoRedo().DoesUndo())
3474  {
3475  pUndo = new SwUndoMergeTable( *pTableNd, *pDelTableNd, bWithPrev, nMode );
3476  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3477  pHistory.reset(new SwHistory);
3478  }
3479 
3480  // Adapt all "TableFormulas"
3481  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3482  aMsgHint.m_aData.pDelTable = &pDelTableNd->GetTable();
3483  aMsgHint.m_eFlags = TBL_MERGETBL;
3484  aMsgHint.m_pHistory = pHistory.get();
3486 
3487  // The actual merge
3488  SwNodeIndex aIdx( bWithPrev ? *pTableNd : *pDelTableNd );
3489  bool bRet = rNds.MergeTable( aIdx, !bWithPrev, nMode );
3490 
3491  if( pHistory )
3492  {
3493  if( pHistory->Count() )
3494  pUndo->SaveFormula( *pHistory );
3495  pHistory.reset();
3496  }
3497  if( bRet )
3498  {
3500 
3502  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3503  }
3504  return bRet;
3505 }
3506 
3507 bool SwNodes::MergeTable( const SwNodeIndex& rPos, bool bWithPrev,
3508  sal_uInt16 nMode )
3509 {
3510  SwTableNode* pDelTableNd = rPos.GetNode().GetTableNode();
3511  OSL_ENSURE( pDelTableNd, "Where did the TableNode go?" );
3512 
3513  SwTableNode* pTableNd = (*this)[ rPos.GetIndex() - 1]->FindTableNode();
3514  OSL_ENSURE( pTableNd, "Where did the TableNode go?" );
3515 
3516  if( !pDelTableNd || !pTableNd )
3517  return false;
3518 
3519  pDelTableNd->DelFrames();
3520 
3521  SwTable& rDelTable = pDelTableNd->GetTable();
3522  SwTable& rTable = pTableNd->GetTable();
3523 
3524  // Find Lines for the Layout update
3525  FndBox_ aFndBox( nullptr, nullptr );
3526  aFndBox.SetTableLines( rTable );
3527  aFndBox.DelFrames( rTable );
3528 
3529  // TL_CHART2:
3530  // tell the charts about the table to be deleted and have them use their own data
3532 
3533  // Sync the TableFormat's Width
3534  {
3535  const SwFormatFrameSize& rTableSz = rTable.GetFrameFormat()->GetFrameSize();
3536  const SwFormatFrameSize& rDelTableSz = rDelTable.GetFrameFormat()->GetFrameSize();
3537  if( rTableSz != rDelTableSz )
3538  {
3539  // The needs correction
3540  if( bWithPrev )
3541  rDelTable.GetFrameFormat()->SetFormatAttr( rTableSz );
3542  else
3543  rTable.GetFrameFormat()->SetFormatAttr( rDelTableSz );
3544  }
3545  }
3546 
3547  if( !bWithPrev )
3548  {
3549  // Transfer all Attributes of the succeeding Table to the preceding one
3550  // We do this, because the succeeding one is deleted when deleting the Node
3551  rTable.SetRowsToRepeat( rDelTable.GetRowsToRepeat() );
3552  rTable.SetTableChgMode( rDelTable.GetTableChgMode() );
3553 
3554  rTable.GetFrameFormat()->LockModify();
3555  *rTable.GetFrameFormat() = *rDelTable.GetFrameFormat();
3556  // Also switch the Name
3557  rTable.GetFrameFormat()->SetName( rDelTable.GetFrameFormat()->GetName() );
3558  rTable.GetFrameFormat()->UnlockModify();
3559  }
3560 
3561  // Move the Lines and Boxes
3562  SwTableLines::size_type nOldSize = rTable.GetTabLines().size();
3563  rTable.GetTabLines().insert( rTable.GetTabLines().begin() + nOldSize,
3564  rDelTable.GetTabLines().begin(), rDelTable.GetTabLines().end() );
3565  rDelTable.GetTabLines().clear();
3566 
3567  rTable.GetTabSortBoxes().insert( rDelTable.GetTabSortBoxes() );
3568  rDelTable.GetTabSortBoxes().clear();
3569 
3570  // The preceding Table always remains, while the succeeding one is deleted
3571  SwEndNode* pTableEndNd = pDelTableNd->EndOfSectionNode();
3572  pTableNd->m_pEndOfSection = pTableEndNd;
3573 
3574  SwNodeIndex aIdx( *pDelTableNd, 1 );
3575 
3576  SwNode* pBoxNd = aIdx.GetNode().GetStartNode();
3577  do {
3578  OSL_ENSURE( pBoxNd->IsStartNode(), "This needs to be a StartNode!" );
3579  pBoxNd->m_pStartOfSection = pTableNd;
3580  pBoxNd = (*this)[ pBoxNd->EndOfSectionIndex() + 1 ];
3581  } while( pBoxNd != pTableEndNd );
3582  pBoxNd->m_pStartOfSection = pTableNd;
3583 
3584  aIdx -= 2;
3585  DelNodes( aIdx, 2 );
3586 
3587  // tweak the conditional styles at the first inserted Line
3588  const SwTableLine* pFirstLn = rTable.GetTabLines()[ nOldSize ];
3589  if( 1 == nMode )
3590  {
3591  // Set Header Template in the Line and save in the History
3592  // if needed for Undo!
3593  }
3594  sw_LineSetHeadCondColl( pFirstLn );
3595 
3596  // Clean up the Borders
3597  if( nOldSize )
3598  {
3599  SwGCLineBorder aPara( rTable );
3600  aPara.nLinePos = --nOldSize;
3601  pFirstLn = rTable.GetTabLines()[ nOldSize ];
3602  sw_GC_Line_Border( pFirstLn, &aPara );
3603  }
3604 
3605  // Update Layout
3606  aFndBox.MakeFrames( rTable );
3607 
3608  return true;
3609 }
3610 
3611 namespace {
3612 
3613 // Use the PtrArray's ForEach method
3614 struct SetAFormatTabPara
3615 {
3616  SwTableAutoFormat& rTableFormat;
3617  SwUndoTableAutoFormat* pUndo;
3618  sal_uInt16 nEndBox, nCurBox;
3619  sal_uInt8 nAFormatLine, nAFormatBox;
3620  bool bSingleRowTable;
3621 
3622  explicit SetAFormatTabPara( const SwTableAutoFormat& rNew )
3623  : rTableFormat( const_cast<SwTableAutoFormat&>(rNew) ), pUndo( nullptr ),
3624  nEndBox( 0 ), nCurBox( 0 ), nAFormatLine( 0 ), nAFormatBox( 0 ), bSingleRowTable(false)
3625  {}
3626 };
3627 
3628 }
3629 
3630 // Forward declare so that the Lines and Boxes can use recursion
3631 static bool lcl_SetAFormatBox(FndBox_ &, SetAFormatTabPara *pSetPara, bool bResetDirect);
3632 static bool lcl_SetAFormatLine(FndLine_ &, SetAFormatTabPara *pPara, bool bResetDirect);
3633 
3634 static bool lcl_SetAFormatLine(FndLine_ & rLine, SetAFormatTabPara *pPara, bool bResetDirect)
3635 {
3636  for (auto const& it : rLine.GetBoxes())
3637  {
3638  lcl_SetAFormatBox(*it, pPara, bResetDirect);
3639  }
3640  return true;
3641 }
3642 
3643 static bool lcl_SetAFormatBox(FndBox_ & rBox, SetAFormatTabPara *pSetPara, bool bResetDirect)
3644 {
3645  if (!rBox.GetUpper()->GetUpper()) // Box on first level?
3646  {
3647  if( !pSetPara->nCurBox )
3648  pSetPara->nAFormatBox = 0;
3649  else if( pSetPara->nCurBox == pSetPara->nEndBox )
3650  pSetPara->nAFormatBox = 3;
3651  else //Even column(1) or Odd column(2)
3652  pSetPara->nAFormatBox = static_cast<sal_uInt8>(1 + ((pSetPara->nCurBox-1) & 1));
3653  }
3654 
3655  if (rBox.GetBox()->GetSttNd())
3656  {
3657  SwTableBox* pSetBox = rBox.GetBox();
3658  if (!pSetBox->HasDirectFormatting() || bResetDirect)
3659  {
3660  if (bResetDirect)
3661  pSetBox->SetDirectFormatting(false);
3662 
3663  SwDoc* pDoc = pSetBox->GetFrameFormat()->GetDoc();
3665  SfxItemSet aBoxSet(pDoc->GetAttrPool(), aTableBoxSetRange);
3666  sal_uInt8 nPos = pSetPara->nAFormatLine * 4 + pSetPara->nAFormatBox;
3667  const bool bSingleRowTable = pSetPara->bSingleRowTable;
3668  const bool bSingleColTable = pSetPara->nEndBox == 0;
3669  pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aCharSet, SwTableAutoFormatUpdateFlags::Char, nullptr);
3670  pSetPara->rTableFormat.UpdateToSet(nPos, bSingleRowTable, bSingleColTable, aBoxSet, SwTableAutoFormatUpdateFlags::Box, pDoc->GetNumberFormatter());
3671 
3672  if (aCharSet.Count())
3673  {
3674  sal_uLong nSttNd = pSetBox->GetSttIdx()+1;
3675  sal_uLong nEndNd = pSetBox->GetSttNd()->EndOfSectionIndex();
3676  for (; nSttNd < nEndNd; ++nSttNd)
3677  {
3678  SwContentNode* pNd = pDoc->GetNodes()[ nSttNd ]->GetContentNode();
3679  if (pNd)
3680  pNd->SetAttr(aCharSet);
3681  }
3682  }
3683 
3684  if (aBoxSet.Count())
3685  {
3686  if (pSetPara->pUndo && SfxItemState::SET == aBoxSet.GetItemState(RES_BOXATR_FORMAT))
3687  pSetPara->pUndo->SaveBoxContent( *pSetBox );
3688 
3689  pSetBox->ClaimFrameFormat()->SetFormatAttr(aBoxSet);
3690  }
3691  }
3692  }
3693  else
3694  {
3695  // Not sure how this situation can occur, but apparently we have some kind of table in table.
3696  // I am guessing at how to best handle singlerow in this situation.
3697  const bool bOrigSingleRowTable = pSetPara->bSingleRowTable;
3698  pSetPara->bSingleRowTable = rBox.GetLines().size() == 1;
3699  for (auto const& rpFndLine : rBox.GetLines())
3700  {
3701  lcl_SetAFormatLine(*rpFndLine, pSetPara, bResetDirect);
3702  }
3703  pSetPara->bSingleRowTable = bOrigSingleRowTable;
3704  }
3705 
3706  if (!rBox.GetUpper()->GetUpper()) // a BaseLine
3707  ++pSetPara->nCurBox;
3708  return true;
3709 }
3710 
3711 bool SwDoc::SetTableAutoFormat(const SwSelBoxes& rBoxes, const SwTableAutoFormat& rNew, bool bResetDirect, bool const isSetStyleName)
3712 {
3713  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3714  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3715  if( !pTableNd )
3716  return false;
3717 
3718  // Find all Boxes/Lines
3719  FndBox_ aFndBox( nullptr, nullptr );
3720  {
3721  FndPara aPara( rBoxes, &aFndBox );
3722  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3723  }
3724  if( aFndBox.GetLines().empty() )
3725  return false;
3726 
3727  SwTable &table = pTableNd->GetTable();
3728  table.SetHTMLTableLayout(std::shared_ptr<SwHTMLTableLayout>());
3729 
3730  FndBox_* pFndBox = &aFndBox;
3731  while( 1 == pFndBox->GetLines().size() &&
3732  1 == pFndBox->GetLines().front()->GetBoxes().size())
3733  {
3734  pFndBox = pFndBox->GetLines().front()->GetBoxes()[0].get();
3735  }
3736 
3737  if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3738  pFndBox = pFndBox->GetUpper()->GetUpper();
3739 
3740  // Disable Undo, but first store parameters
3741  SwUndoTableAutoFormat* pUndo = nullptr;
3742  bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3743  if (bUndo)
3744  {
3745  pUndo = new SwUndoTableAutoFormat( *pTableNd, rNew );
3746  GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndo>(pUndo));
3747  GetIDocumentUndoRedo().DoUndo(false);
3748  }
3749 
3750  if (isSetStyleName)
3751  { // tdf#98226 do this here where undo can record it
3752  pTableNd->GetTable().SetTableStyleName(rNew.GetName());
3753  }
3754 
3755  rNew.RestoreTableProperties(table);
3756 
3757  SetAFormatTabPara aPara( rNew );
3758  FndLines_t& rFLns = pFndBox->GetLines();
3759  aPara.bSingleRowTable = rFLns.size() == 1;
3760 
3761  for (FndLines_t::size_type n = 0; n < rFLns.size(); ++n)
3762  {
3763  FndLine_* pLine = rFLns[n].get();
3764 
3765  // Set Upper to 0 (thus simulate BaseLine)
3766  FndBox_* pSaveBox = pLine->GetUpper();
3767  pLine->SetUpper( nullptr );
3768 
3769  if( !n )
3770  aPara.nAFormatLine = 0;
3771  else if (static_cast<size_t>(n+1) == rFLns.size())
3772  aPara.nAFormatLine = 3;
3773  else
3774  aPara.nAFormatLine = static_cast<sal_uInt8>(1 + ((n-1) & 1 ));
3775 
3776  aPara.nAFormatBox = 0;
3777  aPara.nCurBox = 0;
3778  aPara.nEndBox = pLine->GetBoxes().size()-1;
3779  aPara.pUndo = pUndo;
3780  for (auto const& it : pLine->GetBoxes())
3781  {
3782  lcl_SetAFormatBox(*it, &aPara, bResetDirect);
3783  }
3784 
3785  pLine->SetUpper( pSaveBox );
3786  }
3787 
3788  if( pUndo )
3789  {
3790  GetIDocumentUndoRedo().DoUndo(bUndo);
3791  }
3792 
3794  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
3795 
3796  return true;
3797 }
3798 
3803 {
3804  OSL_ENSURE( !rBoxes.empty(), "No valid Box list" );
3805  SwTableNode* pTableNd = const_cast<SwTableNode*>(rBoxes[0]->GetSttNd()->FindTableNode());
3806  if( !pTableNd )
3807  return false;
3808 
3809  // Find all Boxes/Lines
3810  FndBox_ aFndBox( nullptr, nullptr );
3811  {
3812  FndPara aPara( rBoxes, &aFndBox );
3813  ForEach_FndLineCopyCol( pTableNd->GetTable().GetTabLines(), &aPara );
3814  }
3815  if( aFndBox.GetLines().empty() )
3816  return false;
3817 
3818  // Store table properties
3819  SwTable &table = pTableNd->GetTable();
3820  rGet.StoreTableProperties(table);
3821 
3822  FndBox_* pFndBox = &aFndBox;
3823  while( 1 == pFndBox->GetLines().size() &&
3824  1 == pFndBox->GetLines().front()->GetBoxes().size())
3825  {
3826  pFndBox = pFndBox->GetLines().front()->GetBoxes()[0].get();
3827  }
3828 
3829  if( pFndBox->GetLines().empty() ) // One too far? (only one sel. Box)
3830  pFndBox = pFndBox->GetUpper()->GetUpper();
3831 
3832  FndLines_t& rFLns = pFndBox->GetLines();
3833 
3834  sal_uInt16 aLnArr[4];
3835  aLnArr[0] = 0;
3836  aLnArr[1] = 1 < rFLns.size() ? 1 : 0;
3837  aLnArr[2] = 2 < rFLns.size() ? 2 : aLnArr[1];
3838  aLnArr[3] = rFLns.size() - 1;
3839 
3840  for( sal_uInt8 nLine = 0; nLine < 4; ++nLine )
3841  {
3842  FndLine_& rLine = *rFLns[ aLnArr[ nLine ] ];
3843 
3844  sal_uInt16 aBoxArr[4];
3845  aBoxArr[0] = 0;
3846  aBoxArr[1] = 1 < rLine.GetBoxes().size() ? 1 : 0;
3847  aBoxArr[2] = 2 < rLine.GetBoxes().size() ? 2 : aBoxArr[1];
3848  aBoxArr[3] = rLine.GetBoxes().size() - 1;
3849 
3850  for( sal_uInt8 nBox = 0; nBox < 4; ++nBox )
3851  {
3852  SwTableBox* pFBox = rLine.GetBoxes()[ aBoxArr[ nBox ] ]->GetBox();
3853  // Always apply to the first ones
3854  while( !pFBox->GetSttNd() )
3855  pFBox = pFBox->GetTabLines()[0]->GetTabBoxes()[0];
3856 
3857  sal_uInt8 nPos = nLine * 4 + nBox;
3858  SwNodeIndex aIdx( *pFBox->GetSttNd(), 1 );
3859  SwContentNode* pCNd = aIdx.GetNode().GetContentNode();
3860  if( !pCNd )
3861  pCNd = GetNodes().GoNext( &aIdx );
3862 
3863  if( pCNd )
3864  rGet.UpdateFromSet( nPos, pCNd->GetSwAttrSet(),
3866  rGet.UpdateFromSet( nPos, pFBox->GetFrameFormat()->GetAttrSet(),
3868  GetNumberFormatter() );
3869  }
3870  }
3871 
3872  return true;
3873 }
3874 
3876 {
3877  if (!m_pTableStyles)
3878  {
3880  m_pTableStyles->Load();
3881  }
3882  return *m_pTableStyles;
3883 }
3884 
3886 {
3887  if( IsInMailMerge())
3888  {
3889  OUString newName = "MailMergeTable"
3890  + OStringToOUString( DateTimeToOString( DateTime( DateTime::SYSTEM )), RTL_TEXTENCODING_ASCII_US )
3891  + OUString::number( mpTableFrameFormatTable->size() + 1 );
3892  return newName;
3893  }
3894 
3895  const OUString aName(SwResId(STR_TABLE_DEFNAME));
3896 
3897  const size_t nFlagSize = ( mpTableFrameFormatTable->size() / 8 ) + 2;
3898 
3899  std::unique_ptr<sal_uInt8[]> pSetFlags( new sal_uInt8[ nFlagSize ] );
3900  memset( pSetFlags.get(), 0, nFlagSize );
3901 
3902  for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3903  {
3904  const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3905  if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3906  pFormat->GetName().startsWith( aName ) )
3907  {
3908  // Get number and set the Flag
3909  const sal_Int32 nNmLen = aName.getLength();
3910  size_t nNum = pFormat->GetName().copy( nNmLen ).toInt32();
3911  if( nNum-- && nNum < mpTableFrameFormatTable->size() )
3912  pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
3913  }
3914  }
3915 
3916  // All numbers are flagged properly, thus calculate the right number
3917  size_t nNum = mpTableFrameFormatTable->size();
3918  for( size_t n = 0; n < nFlagSize; ++n )
3919  {
3920  auto nTmp = pSetFlags[ n ];
3921  if( nTmp != 0xFF )
3922  {
3923  // Calculate the number
3924  nNum = n * 8;
3925  while( nTmp & 1 )
3926  {
3927  ++nNum;
3928  nTmp >>= 1;
3929  }
3930  break;
3931  }
3932  }
3933 
3934  return aName + OUString::number( ++nNum );
3935 }
3936 
3937 SwTableFormat* SwDoc::FindTableFormatByName( const OUString& rName, bool bAll ) const
3938 {
3939  const SwFormat* pRet = nullptr;
3940  if( bAll )
3941  pRet = FindFormatByName( *mpTableFrameFormatTable, rName );
3942  else
3943  {
3944  // Only the ones set in the Doc
3945  for( size_t n = 0; n < mpTableFrameFormatTable->size(); ++n )
3946  {
3947  const SwFrameFormat* pFormat = (*mpTableFrameFormatTable)[ n ];
3948  if( !pFormat->IsDefault() && IsUsed( *pFormat ) &&
3949  pFormat->GetName() == rName )
3950  {
3951  pRet = pFormat;
3952  break;
3953  }
3954  }
3955  }
3956  return const_cast<SwTableFormat*>(static_cast<const SwTableFormat*>(pRet));
3957 }
3958 
3960  SwTwips nAbsDiff, SwTwips nRelDiff )
3961 {
3962  SwTableNode* pTableNd = const_cast<SwTableNode*>(rCurrentBox.GetSttNd()->FindTableNode());
3963  std::unique_ptr<SwUndo> pUndo;
3964 
3965  SwTableFormulaUpdate aMsgHint( &pTableNd->GetTable() );
3966  aMsgHint.m_eFlags = TBL_BOXPTR;
3968 
3969  bool const bUndo(GetIDocumentUndoRedo().DoesUndo());
3970  bool bRet = false;
3971  switch( extractPosition(eType) )
3972  {
3977  {
3978  bRet = pTableNd->GetTable().SetColWidth( rCurrentBox,
3979  eType, nAbsDiff, nRelDiff,
3980  bUndo ? &pUndo : nullptr );
3981  }
3982  break;
3986  bRet = pTableNd->GetTable().SetRowHeight( rCurrentBox,
3987  eType, nAbsDiff, nRelDiff,
3988  bUndo ? &pUndo : nullptr );
3989  break;
3990  default: break;
3991  }
3992 
3993  GetIDocumentUndoRedo().DoUndo(bUndo); // SetColWidth can turn it off
3994  if( pUndo )
3995  {
3996  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
3997  }
3998 
3999  if( bRet )
4000  {
4002  }
4003  return bRet;
4004 }
4005 
4006 bool SwDoc::IsNumberFormat( const OUString& rString, sal_uInt32& F_Index, double& fOutNumber )
4007 {
4008  if( rString.getLength() > 308 ) // optimization matches svl:IsNumberFormat arbitrary value
4009  return false;
4010 
4011  // remove any comment anchor marks
4012  OUStringBuffer sStringBuffer(rString);
4013  sal_Int32 nCommentPosition = sStringBuffer.indexOf( CH_TXTATR_INWORD );
4014  while( nCommentPosition != -1 )
4015  {
4016  sStringBuffer.remove( nCommentPosition, 1 );
4017  nCommentPosition = sStringBuffer.indexOf( CH_TXTATR_INWORD, nCommentPosition );
4018  }
4019 
4020  return GetNumberFormatter()->IsNumberFormat( sStringBuffer.makeStringAndClear(), F_Index, fOutNumber );
4021 }
4022 
4023 void SwDoc::ChkBoxNumFormat( SwTableBox& rBox, bool bCallUpdate )
4024 {
4025  // Optimization: If the Box says it's Text, it remains Text
4026  const SfxPoolItem* pNumFormatItem = nullptr;
4027  if( SfxItemState::SET == rBox.GetFrameFormat()->GetItemState( RES_BOXATR_FORMAT,
4028  false, &pNumFormatItem ) && GetNumberFormatter()->IsTextFormat(
4029  static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue() ))
4030  return ;
4031 
4032  std::unique_ptr<SwUndoTableNumFormat> pUndo;
4033 
4034  bool bIsEmptyTextNd;
4035  bool bChgd = true;
4036  sal_uInt32 nFormatIdx;
4037  double fNumber;
4038  if( rBox.HasNumContent( fNumber, nFormatIdx, bIsEmptyTextNd ) )
4039  {
4040  if( !rBox.IsNumberChanged() )
4041  bChgd = false;
4042  else
4043  {
4045  {
4047  pUndo.reset(new SwUndoTableNumFormat( rBox ));
4048  pUndo->SetNumFormat( nFormatIdx, fNumber );
4049  }
4050 
4051  SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4053 
4054  bool bLockModify = true;
4055  bool bSetNumberFormat = IsInsTableFormatNum();
4056  const bool bForceNumberFormat = IsInsTableFormatNum() && IsInsTableChangeNumFormat();
4057 
4058  // if the user forced a number format in this cell previously,
4059  // keep it, unless the user set that she wants the full number
4060  // format recognition
4061  if( pNumFormatItem && !bForceNumberFormat )
4062  {
4063  sal_uLong nOldNumFormat = static_cast<const SwTableBoxNumFormat*>(pNumFormatItem)->GetValue();
4064  SvNumberFormatter* pNumFormatr = GetNumberFormatter();
4065 
4066  SvNumFormatType nFormatType = pNumFormatr->GetType( nFormatIdx );
4067  if( nFormatType == pNumFormatr->GetType( nOldNumFormat ) || SvNumFormatType::NUMBER == nFormatType )
4068  {
4069  // Current and specified NumFormat match
4070  // -> keep old Format
4071  nFormatIdx = nOldNumFormat;
4072  bSetNumberFormat = true;
4073  }
4074  else
4075  {
4076  // Current and specified NumFormat do not match
4077  // -> insert as Text
4078  bLockModify = bSetNumberFormat = false;
4079  }
4080  }
4081 
4082  if( bSetNumberFormat || bForceNumberFormat )
4083  {
4084  pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4085 
4086  aBoxSet.Put( SwTableBoxValue( fNumber ));
4087  aBoxSet.Put( SwTableBoxNumFormat( nFormatIdx ));
4088  }
4089 
4090  // It's not enough to only reset the Formula.
4091  // Make sure that the Text is formatted accordingly
4092  if( !bSetNumberFormat && !bIsEmptyTextNd && pNumFormatItem )
4093  {
4094  // Just resetting Attributes is not enough
4095  // Make sure that the Text is formatted accordingly
4096  pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4097  }
4098 
4099  if( bLockModify ) pBoxFormat->LockModify();
4101  if( bLockModify ) pBoxFormat->UnlockModify();
4102 
4103  if( bSetNumberFormat )
4104  pBoxFormat->SetFormatAttr( aBoxSet );
4105  }
4106  }
4107  else
4108  {
4109  // It's not a number
4110  const SfxPoolItem* pValueItem = nullptr, *pFormatItem = nullptr;
4111  SwTableBoxFormat* pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.GetFrameFormat());
4112  if( SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_FORMAT,
4113  false, &pFormatItem ) ||
4114  SfxItemState::SET == pBoxFormat->GetItemState( RES_BOXATR_VALUE,
4115  false, &pValueItem ))
4116  {
4118  {
4120  pUndo.reset(new SwUndoTableNumFormat( rBox ));
4121  }
4122 
4123  pBoxFormat = static_cast<SwTableBoxFormat*>(rBox.ClaimFrameFormat());
4124 
4125  // Remove all number formats
4126  sal_uInt16 nWhich1 = RES_BOXATR_FORMULA;
4127  if( !bIsEmptyTextNd )
4128  {
4129  nWhich1 = RES_BOXATR_FORMAT;
4130 
4131  // Just resetting Attributes is not enough
4132  // Make sure that the Text is formatted accordingly
4133  pBoxFormat->SetFormatAttr( *GetDfltAttr( nWhich1 ));
4134  }
4135  pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4136  }
4137  else
4138  bChgd = false;
4139  }
4140 
4141  if( bChgd )
4142  {
4143  if( pUndo )
4144  {
4145  pUndo->SetBox( rBox );
4146  GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
4148  }
4149 
4150  const SwTableNode* pTableNd = rBox.GetSttNd()->FindTableNode();
4151  if( bCallUpdate )
4152  {
4153  SwTableFormulaUpdate aTableUpdate( &pTableNd->GetTable() );
4154  getIDocumentFieldsAccess().UpdateTableFields( &aTableUpdate );
4155 
4156  // TL_CHART2: update charts (when cursor leaves cell and
4157  // automatic update is enabled)
4158  if (AUTOUPD_FIELD_AND_CHARTS == GetDocumentSettingManager().getFieldUpdateFlags(true))
4159  pTableNd->GetTable().UpdateCharts();
4160  }
4162  }
4163 }
4164 
4166 {
4167  if (GetIDocumentUndoRedo().DoesUndo())
4168  {
4169  GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoTableNumFormat>(rBox, &rSet) );
4170  }
4171 
4172  SwFrameFormat* pBoxFormat = rBox.ClaimFrameFormat();
4173  if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA ))
4174  {
4175  pBoxFormat->LockModify();
4176  pBoxFormat->ResetFormatAttr( RES_BOXATR_VALUE );
4177  pBoxFormat->UnlockModify();
4178  }
4179  else if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE ))
4180  {
4181  pBoxFormat->LockModify();
4182  pBoxFormat->ResetFormatAttr( RES_BOXATR_FORMULA );
4183  pBoxFormat->UnlockModify();
4184  }
4185  pBoxFormat->SetFormatAttr( rSet );
4187 }
4188 
4190 {
4191  SwPaM aPam(rPos);
4192  aPam.Move(fnMoveBackward);
4193  SwContentNode *pNode = aPam.GetContentNode();
4194  if ( nullptr == pNode )
4195  return ;
4196  if( pNode->IsTextNode() )
4197  {
4198  SwTextNode * pTextNode = pNode->GetTextNode();
4199  if (pTextNode && pTextNode->IsNumbered()
4200  && pTextNode->GetText().isEmpty())
4201  {
4202  const SfxPoolItem* pFormatItem = nullptr;
4203  SfxItemSet rSet( pTextNode->GetDoc()->GetAttrPool(),
4205  pTextNode->SwContentNode::GetAttr( rSet );
4206  if ( SfxItemState::SET == rSet.GetItemState( RES_PARATR_NUMRULE , false , &pFormatItem ) )
4207  {
4208  SwUndoDelNum * pUndo;
4209  if( GetIDocumentUndoRedo().DoesUndo() )
4210  {
4212  pUndo = new SwUndoDelNum( aPam );
4213  GetIDocumentUndoRedo().AppendUndo( std::unique_ptr<SwUndo>(pUndo) );
4214  }
4215  else
4216  pUndo = nullptr;
4217  SwRegHistory aRegH( pUndo ? pUndo->GetHistory() : nullptr );
4218  aRegH.RegisterInModify( pTextNode , *pTextNode );
4219  if ( pUndo )
4220  pUndo->AddNode( *pTextNode );
4221  std::unique_ptr<SfxStringItem> pNewItem(static_cast<SfxStringItem*>(pFormatItem->Clone()));
4222  pNewItem->SetValue(OUString());
4223  rSet.Put( std::move(pNewItem) );
4224  pTextNode->SetAttr( rSet );
4225  }
4226  }
4227  }
4228 }
4229 
4231 {
4232  SwStartNode* pSttNd;
4233  if( nullptr != ( pSttNd = rNode.GetNode().
4234  FindSttNodeByType( SwTableBoxStartNode )) &&
4235  2 == pSttNd->EndOfSectionIndex() - pSttNd->GetIndex() )
4236  {
4237  SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().
4238  GetTableBox( pSttNd->GetIndex() );
4239 
4240  const SfxPoolItem* pFormatItem = nullptr;
4241  const SfxItemSet& rSet = pBox->GetFrameFormat()->GetAttrSet();
4242  if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT, false, &pFormatItem ) ||
4243  SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMULA, false ) ||
4244  SfxItemState::SET == rSet.GetItemState( RES_BOXATR_VALUE, false ))
4245  {
4247  {
4248  GetIDocumentUndoRedo().AppendUndo(std::make_unique<SwUndoTableNumFormat>(*pBox));
4249  }
4250 
4251  SwFrameFormat* pBoxFormat = pBox->ClaimFrameFormat();
4252 
4253  // Keep TextFormats!
4254  sal_uInt16 nWhich1 = RES_BOXATR_FORMAT;
4255  if( pFormatItem && GetNumberFormatter()->IsTextFormat(
4256  static_cast<const SwTableBoxNumFormat*>(pFormatItem)->GetValue() ))
4257  nWhich1 = RES_BOXATR_FORMULA;
4258  else
4259  // Just resetting Attributes is not enough
4260  // Make sure that the Text is formatted accordingly
4261  pBoxFormat->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
4262 
4263  pBoxFormat->ResetFormatAttr( nWhich1, RES_BOXATR_VALUE );
4265  }
4266  }
4267 }
4268 
4276 bool SwDoc::InsCopyOfTable( SwPosition& rInsPos, const SwSelBoxes& rBoxes,
4277  const SwTable* pCpyTable, bool bCpyName, bool bCorrPos )
4278 {
4279  bool bRet;
4280 
4281  const SwTableNode* pSrcTableNd = pCpyTable
4282  ? pCpyTable->GetTableNode()
4283  : rBoxes[ 0 ]->GetSttNd()->FindTableNode();
4284 
4285  SwTableNode * pInsTableNd = rInsPos.nNode.GetNode().FindTableNode();
4286 
4287  bool const bUndo( GetIDocumentUndoRedo().DoesUndo() );
4288  if( !pCpyTable && !pInsTableNd )
4289  {
4290  std::unique_ptr<SwUndoCpyTable> pUndo;
4291  if (bUndo)
4292  {
4294  pUndo.reset(new SwUndoCpyTable(this));
4295  }
4296 
4297  {
4298  ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo());
4299  bRet = pSrcTableNd->GetTable().MakeCopy( this, rInsPos, rBoxes,
4300  bCpyName );
4301  }
4302 
4303  if( pUndo && bRet )
4304  {
4305  pInsTableNd = GetNodes()[ rInsPos.nNode.GetIndex() - 1 ]->FindTableNode();
4306 
4307  pUndo->SetTableSttIdx( pInsTableNd->GetIndex() );
4308  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4309  }
4310  }
4311  else
4312  {
4314  if( getIDocumentRedlineAccess().IsRedlineOn() )
4318 
4319  std::unique_ptr<SwUndoTableCpyTable> pUndo;
4320  if (bUndo)
4321  {
4323  pUndo.reset(new SwUndoTableCpyTable(this));
4324  GetIDocumentUndoRedo().DoUndo(false);
4325  }
4326 
4327  rtl::Reference<SwDoc> xCpyDoc( const_cast<SwDoc*>(pSrcTableNd->GetDoc()) );
4328  bool bDelCpyDoc = xCpyDoc == this;
4329 
4330  if( bDelCpyDoc )
4331  {
4332  // Copy the Table into a temporary Doc
4333  xCpyDoc = new SwDoc;
4334 
4335  SwPosition aPos( SwNodeIndex( xCpyDoc->GetNodes().GetEndOfContent() ));
4336  if( !pSrcTableNd->GetTable().MakeCopy( xCpyDoc.get(), aPos, rBoxes, true ))
4337  {
4338  xCpyDoc.clear();
4339 
4340  if( pUndo )
4341  {
4342  GetIDocumentUndoRedo().DoUndo(bUndo);
4343  }
4344  return false;
4345  }
4346  aPos.nNode -= 1; // Set to the Table's EndNode
4347  pSrcTableNd = aPos.nNode.GetNode().FindTableNode();
4348  }
4349 
4350  const SwStartNode* pSttNd = rInsPos.nNode.GetNode().FindTableBoxStartNode();
4351 
4352  rInsPos.nContent.Assign( nullptr, 0 );
4353 
4354  // no complex into complex, but copy into or from new model is welcome
4355  if( ( !pSrcTableNd->GetTable().IsTableComplex() || pInsTableNd->GetTable().IsNewModel() )
4356  && ( bDelCpyDoc || !rBoxes.empty() ) )
4357  {
4358  // Copy the Table "relatively"
4359  const SwSelBoxes* pBoxes;
4360  SwSelBoxes aBoxes;
4361 
4362  if( bDelCpyDoc )
4363  {
4364  SwTableBox* pBox = pInsTableNd->GetTable().GetTableBox(
4365  pSttNd->GetIndex() );
4366  OSL_ENSURE( pBox, "Box is not in this Table" );
4367  aBoxes.insert( pBox );
4368  pBoxes = &aBoxes;
4369  }
4370  else
4371  pBoxes = &rBoxes;
4372 
4373  // Copy Table to the selected Lines
4374  bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4375  *pBoxes, pUndo.get() );
4376  }
4377  else
4378  {
4379  SwNodeIndex aNdIdx( *pSttNd, 1 );
4380  bRet = pInsTableNd->GetTable().InsTable( pSrcTableNd->GetTable(),
4381  aNdIdx, pUndo.get() );
4382  }
4383 
4384  xCpyDoc.clear();
4385 
4386  if( pUndo )
4387  {
4388  // If the Table could not be copied, delete the Undo object
4389  GetIDocumentUndoRedo().DoUndo(bUndo);
4390  if( bRet || !pUndo->IsEmpty() )
4391  {
4392  GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
4393  }
4394  }
4395 
4396  if( bCorrPos )
4397  {
4398  rInsPos.nNode = *pSttNd;
4399  rInsPos.nContent.Assign( GetNodes().GoNext( &rInsPos.nNode ), 0 );
4400  }
4402  }
4403 
4404  if( bRet )
4405  {
4407  getIDocumentFieldsAccess().SetFieldsDirty( true, nullptr, 0 );
4408  }
4409  return bRet;
4410 }
4411 
4413 {
4414  bool bChgd = false;
4415  std::unique_ptr<SwUndoAttrTable> pUndo;
4416  if (GetIDocumentUndoRedo().DoesUndo())
4417  pUndo.reset(new SwUndoAttrTable( *rTable.GetTableNode() ));
4418 
4419  SwTableSortBoxes& rSrtBox = rTable.GetTabSortBoxes();
4420  for (size_t i = rSrtBox.size(); i; )
4421  {
4422  SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4423  if( pBoxFormat->GetProtect().IsContentProtected() )
4424  {
4425  pBoxFormat->ResetFormatAttr( RES_PROTECT );
4426  bChgd = true;
4427  }
4428  }
4429 
4430  if( pUndo && bChgd )
4431  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4432  return bChgd;
4433 }
4434 
4435 void SwDoc::UnProtectCells( const OUString& rName )
4436 {
4437  bool bChgd = false;
4438  SwTableFormat* pFormat = FindTableFormatByName( rName );
4439  if( pFormat )
4440  {
4441  bChgd = UnProtectTableCells( *SwTable::FindTable( pFormat ) );
4442  if( bChgd )
4444  }
4445 }
4446 
4447 bool SwDoc::UnProtectCells( const SwSelBoxes& rBoxes )
4448 {
4449  bool bChgd = false;
4450  if( !rBoxes.empty() )
4451  {
4452  std::unique_ptr<SwUndoAttrTable> pUndo;
4454  pUndo.reset(new SwUndoAttrTable( *rBoxes[0]->GetSttNd()->FindTableNode() ));
4455 
4456  std::map<SwFrameFormat*, SwTableBoxFormat*> aFormatsMap;
4457  for (size_t i = rBoxes.size(); i; )
4458  {
4459  SwTableBox* pBox = rBoxes[ --i ];
4460  SwFrameFormat* pBoxFormat = pBox->GetFrameFormat();
4461  if( pBoxFormat->GetProtect().IsContentProtected() )
4462  {
4463  std::map<SwFrameFormat*, SwTableBoxFormat*>::const_iterator const it =
4464  aFormatsMap.find(pBoxFormat);
4465  if (aFormatsMap.end() != it)
4466  pBox->ChgFrameFormat(it->second);
4467  else
4468  {
4469  SwTableBoxFormat *const pNewBoxFormat(
4470  static_cast<SwTableBoxFormat*>(pBox->ClaimFrameFormat()));
4471  pNewBoxFormat->ResetFormatAttr( RES_PROTECT );
4472  aFormatsMap.insert(std::make_pair(pBoxFormat, pNewBoxFormat));
4473  }
4474  bChgd = true;
4475  }
4476  }
4477 
4478  if( pUndo && bChgd )
4479  GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
4480  }
4481  return bChgd;
4482 }
4483 
4484 void SwDoc::UnProtectTables( const SwPaM& rPam )
4485 {
4487 
4488  bool bChgd = false, bHasSel = rPam.HasMark() ||
4489  rPam.GetNext() != &rPam;
4490  SwFrameFormats& rFormats = *GetTableFrameFormats();
4491  SwTable* pTable;
4492  const SwTableNode* pTableNd;
4493  for( auto n = rFormats.size(); n ; )
4494  if( nullptr != (pTable = SwTable::FindTable( rFormats[ --n ] )) &&
4495  nullptr != (pTableNd = pTable->GetTableNode() ) &&
4496  pTableNd->GetNodes().IsDocNodes() )
4497  {
4498  sal_uLong nTableIdx = pTableNd->GetIndex();
4499 
4500  // Check whether the Table is within the Selection
4501  if( bHasSel )
4502  {
4503  bool bFound = false;
4504  SwPaM* pTmp = const_cast<SwPaM*>(&rPam);
4505  do {
4506  const SwPosition *pStt = pTmp->Start(),
4507  *pEnd = pTmp->End();
4508  bFound = pStt->nNode.GetIndex() < nTableIdx &&
4509  nTableIdx < pEnd->nNode.GetIndex();
4510 
4511  } while( !bFound && &rPam != ( pTmp = pTmp->GetNext() ) );
4512  if( !bFound )
4513  continue; // Continue searching
4514  }
4515 
4516  // Lift the protection
4517  bChgd |= UnProtectTableCells( *pTable );
4518  }
4519 
4521  if( bChgd )
4523 }
4524 
4526  const OUString* pTableName,
4527  bool* pFullTableProtection )
4528 {
4529  bool bHasProtection = false;
4530  SwTable* pTable = nullptr;
4531  if( pTableName )
4532  pTable = SwTable::FindTable( FindTableFormatByName( *pTableName ) );
4533  else if( pPos )
4534  {
4535  SwTableNode* pTableNd = pPos->nNode.GetNode().FindTableNode();
4536  if( pTableNd )
4537  pTable = &pTableNd->GetTable();
4538  }
4539 
4540  if( pTable )
4541  {
4542  SwTableSortBoxes& rSrtBox = pTable->GetTabSortBoxes();
4543  for (size_t i = rSrtBox.size(); i; )
4544  {
4545  SwFrameFormat *pBoxFormat = rSrtBox[ --i ]->GetFrameFormat();
4546  if( pBoxFormat->GetProtect().IsContentProtected() )
4547  {
4548  if( !bHasProtection )
4549  {
4550  bHasProtection = true;
4551  if( !pFullTableProtection )
4552  break;
4553  *pFullTableProtection = true;
4554  }
4555  }
4556  else if( bHasProtection && pFullTableProtection )
4557  {
4558  *pFullTableProtection = false;
4559  break;
4560  }
4561  }
4562  }
4563  return bHasProtection;
4564 }
4565 
4566 SwTableAutoFormat* SwDoc::MakeTableStyle(const OUString& rName, bool bBroadcast)
4567 {
4568  SwTableAutoFormat aTableFormat(rName);
4569  GetTableStyles().AddAutoFormat(aTableFormat);
4570  SwTableAutoFormat* pTableFormat = GetTableStyles().FindAutoFormat(rName);
4571 
4573 
4574  if (GetIDocumentUndoRedo().DoesUndo())
4575  {
4577  std::make_unique<SwUndoTableStyleMake>(rName, this));
4578  }
4579 
4580  if (bBroadcast)
4581  BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxHintId::StyleSheetCreated);
4582 
4583  return pTableFormat;
4584 }
4585 
4586 std::unique_ptr<SwTableAutoFormat> SwDoc::DelTableStyle(const OUString& rName, bool bBroadcast)
4587 {
4588  if (bBroadcast)
4589  BroadcastStyleOperation(rName, SfxStyleFamily::Table, SfxHintId::StyleSheetErased);
4590 
4591  std::unique_ptr<SwTableAutoFormat> pReleasedFormat = GetTableStyles().ReleaseAutoFormat(rName);
4592 
4593  std::vector<SwTable*> vAffectedTables;
4594  if (pReleasedFormat)
4595  {
4596  size_t nTableCount = GetTableFrameFormatCount(true);
4597  for (size_t i=0; i < nTableCount; ++i)
4598  {
4599  SwFrameFormat* pFrameFormat = &GetTableFrameFormat(i, true);
4600  SwTable* pTable = SwTable::FindTable(pFrameFormat);
4601  if (pTable->GetTableStyleName() == pReleasedFormat->GetName())
4602  {
4603  pTable->SetTableStyleName("");
4604  vAffectedTables.push_back(pTable);
4605  }
4606  }
4607 
4609 
4610  if (GetIDocumentUndoRedo().DoesUndo())
4611  {
4613  std::make_unique<SwUndoTableStyleDelete>(std::move(pReleasedFormat), vAffectedTables, this));
4614  }
4615  }
4616 
4617  return pReleasedFormat;
4618 }
4619 
4620 void SwDoc::ChgTableStyle(const OUString& rName, const SwTableAutoFormat& rNewFormat)
4621 {
4622  SwTableAutoFormat* pFormat = GetTableStyles().FindAutoFormat(rName);
4623  if (pFormat)
4624  {
4625  SwTableAutoFormat aOldFormat = *pFormat;
4626  *pFormat = rNewFormat;
4627  pFormat->SetName(rName);
4628 
4629  size_t nTableCount = GetTableFrameFormatCount(true);
4630  for (size_t i=0; i < nTableCount; ++i)
4631  {
4632  SwFrameFormat* pFrameFormat = &GetTableFrameFormat(i, true);
4633  SwTable* pTable = SwTable::FindTable(pFrameFormat);
4634  if (pTable->GetTableStyleName() == rName)
4636  }
4637 
4639 
4640  if (GetIDocumentUndoRedo().DoesUndo())
4641  {
4643  std::make_unique<SwUndoTableStyleUpdate>(*pFormat, aOldFormat, this));
4644  }
4645  }
4646 }
4647 
4648 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool IsInsTableChangeNumFormat() const
Definition: doc.cxx:1685
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:4165
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:3572
void KillPams()
Definition: crsrsh.cxx:1021
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:1712
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
constexpr::Color COL_BLACK(0x00, 0x00, 0x00)
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:3229
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:2427
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:996
bool IsInsTableFormatNum() const
Definition: doc.cxx:1680
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:3677
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:4884
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:561
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:1494
static void GetTabCols(SwTabCols &rFill, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2491
static bool lcl_SetAFormatBox(FndBox_ &, SetAFormatTabPara *pSetPara, bool bResetDirect)
Definition: ndtbl.cxx:3643
virtual void SetModified()=0
Must be called manually at changes of format.
sal_uIntPtr sal_uLong
void StoreTableProperties(const SwTable &table)
Definition: tblafmt.cxx:704
constexpr TypedWhichId< SwNumRuleItem > RES_PARATR_NUMRULE(72)
OUString GetUniqueTableName() const
Definition: ndtbl.cxx:3885
const SwRect & getFramePrintArea() const
Definition: frame.hxx:178
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
std::vector< sal_uInt16 > aPosArr
Definition: tblrwcl.hxx:63
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:1273
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:3937
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::Color COL_GRAY(0x80, 0x80, 0x80)
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:2736
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:2480
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:411
SwPosition & GetBound(bool bOne=true)
Definition: pam.hxx:245
IDocumentUndoRedo & GetIDocumentUndoRedo()
Definition: doc.cxx:143
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:944
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
bool HasWriterListeners() const
Definition: calbck.hxx:208
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
static void GetTabRows(SwTabCols &rFill, const SwCellFrame *pBoxFrame)
Definition: ndtbl.cxx:2545
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:4230
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:4484
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:3310
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:356
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:2353
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:527
#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:3295
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:3328
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:425
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:1141
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:4435
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:2460
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:2335
void SetTabCols(const SwTabCols &rNew, const SwTabCols &rOld, const SwTableBox *pStart, bool bCurRowOnly)
Definition: swtable.cxx:832
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:1320
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:915
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:383
void sw_BoxSetSplitBoxFormats(SwTableBox *pBox, SwCollectTableLineBoxes *pSplPara)
Definition: ndtbl.cxx:3009
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:591
void ClearLineNumAttrs(SwPosition const &rPos)
Definition: ndtbl.cxx:4189
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:342
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:132
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
const SwPosition * GetContentAnchor() const
Definition: fmtanchr.hxx:67
void clear()
Definition: swtable.hxx:81
SwPageFrame * FindPageFrame()
Definition: frame.hxx:660
bool IsHidden() const
Definition: section.hxx:178