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