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