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