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