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