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