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