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