1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <libxml/xmlwriter.h>
22 #include <UndoTable.hxx>
23 #include <UndoRedline.hxx>
24 #include <UndoDelete.hxx>
25 #include <UndoSplitMove.hxx>
26 #include <UndoCore.hxx>
28 #include <fmtpdsc.hxx>
29 #include <hintids.hxx>
32 #include <docredln.hxx>
33 #include <IDocumentUndoRedo.hxx>
34 #include <IDocumentChartDataProviderAccess.hxx>
35 #include <IDocumentRedlineAccess.hxx>
36 #include <IDocumentFieldsAccess.hxx>
37 #include <IDocumentStylePoolAccess.hxx>
38 #include <IDocumentLayoutAccess.hxx>
39 #include <rootfrm.hxx>
43 #include <swtable.hxx>
50 #include <tblafmt.hxx>
51 #include <poolfmt.hxx>
53 #include <cellatr.hxx>
54 #include <swtblfmt.hxx>
55 #include <swddetbl.hxx>
56 #include <redline.hxx>
57 #include <node2lay.hxx>
58 #include <tblrwcl.hxx>
59 #include <fmtanchr.hxx>
60 #include <strings.hrc>
61 #include <unochart.hxx>
63 #include <frameformats.hxx>
64 #include <editeng/formatbreakitem.hxx>
65 #include <osl/diagnose.h>
73 #define CHECK_TABLE(t) (t).CheckConsistency();
75 #define CHECK_TABLE(t)
79 #define DEBUG_REDLINE( pDoc ) sw_DebugRedline( pDoc );
81 #define DEBUG_REDLINE( pDoc )
84 typedef std::vector
<std::shared_ptr
<SfxItemSet
> > SfxItemSets
;
86 struct UndoTableCpyTable_Entry
88 SwNodeOffset nBoxIdx
, nOffset
;
89 std::unique_ptr
<SfxItemSet
> pBoxNumAttr
;
90 std::unique_ptr
<SwUndo
> pUndo
;
92 // Was the last paragraph of the new and the first paragraph of the old content joined?
93 bool bJoin
; // For redlining only
95 explicit UndoTableCpyTable_Entry( const SwTableBox
& rBox
);
97 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
105 void KillEmptyFrameFormat(SwFrameFormat
& rFormat
)
107 if(!rFormat
.HasWriterListeners())
117 SfxItemSet m_aTableSet
;
118 std::unique_ptr
<SaveLine
> m_pLine
;
119 const SwTable
* m_pSwTable
;
121 SwFrameFormatsV m_aFrameFormats
;
122 sal_uInt16 m_nLineCount
;
123 bool m_bModifyBox
: 1;
124 bool m_bSaveFormula
: 1;
125 bool m_bNewModel
: 1;
127 SaveTable(const SaveTable
&) = delete;
128 SaveTable
& operator=(const SaveTable
&) = delete;
129 SwFrameFormat
& CreateNewFormat(SwFrameFormat
& rFormat
, sal_uInt16 nFormatPos
);
132 SaveTable( const SwTable
& rTable
, sal_uInt16 nLnCnt
= USHRT_MAX
,
133 bool bSaveFormula
= true );
135 sal_uInt16
AddFormat( SwFrameFormat
* pFormat
, bool bIsLine
);
136 void NewFrameFormatForLine(const SwTableLine
&, sal_uInt16 nFormatPos
, SwFrameFormat
* pOldFormat
);
137 void NewFrameFormatForBox(const SwTableBox
&, sal_uInt16 nFormatPos
, SwFrameFormat
* pOldFormat
);
139 void RestoreAttr( SwTable
& rTable
, bool bModifyBox
= false );
140 void SaveContentAttrs( SwDoc
* pDoc
);
141 void CreateNew( SwTable
& rTable
, bool bCreateFrames
= true,
142 bool bRestoreChart
= true );
143 bool IsNewModel() const { return m_bNewModel
; }
151 friend class SaveBox
;
155 sal_uInt16 m_nItemSet
;
157 SaveLine(const SaveLine
&) = delete;
158 SaveLine
& operator=(const SaveLine
&) = delete;
161 SaveLine( SaveLine
* pPrev
, const SwTableLine
& rLine
, SaveTable
& rSTable
);
164 void RestoreAttr( SwTableLine
& rLine
, SaveTable
& rSTable
);
165 void SaveContentAttrs( SwDoc
* pDoc
);
167 void CreateNew( SwTable
& rTable
, SwTableBox
& rParent
, SaveTable
& rSTable
);
172 friend class SaveLine
;
175 SwNodeOffset m_nStartNode
;
176 sal_Int32 m_nRowSpan
;
177 sal_uInt16 m_nItemSet
;
180 SfxItemSets
* pContentAttrs
;
185 SaveBox( SaveBox
* pPrev
, const SwTableBox
& rBox
, SaveTable
& rSTable
);
188 void RestoreAttr( SwTableBox
& rBox
, SaveTable
& rSTable
);
189 void SaveContentAttrs( SwDoc
* pDoc
);
191 void CreateNew( SwTable
& rTable
, SwTableLine
& rParent
, SaveTable
& rSTable
);
196 #if OSL_DEBUG_LEVEL > 0
197 static void CheckTable( const SwTable
& );
198 #define CHECKTABLE(t) CheckTable( t );
200 #define CHECKTABLE(t)
203 /* #130880: Crash in undo of table to text when the table has (freshly) merged cells
204 The order of cell content nodes in the nodes array is not given by the recursive table structure.
205 The algorithm must not rely on this even it holds for a fresh loaded table in odt file format.
206 So we need to remember not only the start node position but the end node position as well.
209 struct SwTableToTextSave
211 SwNodeOffset m_nSttNd
;
212 SwNodeOffset m_nEndNd
;
213 sal_Int32 m_nContent
;
214 std::unique_ptr
<SwHistory
> m_pHstry
;
215 // metadata references for first and last paragraph in cell
216 std::shared_ptr
< ::sfx2::MetadatableUndo
> m_pMetadataUndoStart
;
217 std::shared_ptr
< ::sfx2::MetadatableUndo
> m_pMetadataUndoEnd
;
219 SwTableToTextSave( SwDoc
& rDoc
, SwNodeOffset nNd
, SwNodeOffset nEndIdx
, sal_Int32 nContent
);
222 SwTableToTextSave(const SwTableToTextSave
&) = delete;
223 SwTableToTextSave
& operator=(const SwTableToTextSave
&) = delete;
227 WhichRangesContainer
const aSave_BoxContentSet(svl::Items
<
228 RES_CHRATR_COLOR
, RES_CHRATR_CROSSEDOUT
,
229 RES_CHRATR_FONT
, RES_CHRATR_FONTSIZE
,
230 RES_CHRATR_POSTURE
, RES_CHRATR_POSTURE
,
231 RES_CHRATR_SHADOWED
, RES_CHRATR_WEIGHT
,
232 RES_PARATR_ADJUST
, RES_PARATR_ADJUST
>);
234 SwUndoInsTable::SwUndoInsTable( const SwPosition
& rPos
, sal_uInt16 nCl
, sal_uInt16 nRw
,
235 sal_uInt16 nAdj
, const SwInsertTableOptions
& rInsTableOpts
,
236 const SwTableAutoFormat
* pTAFormat
,
237 const std::vector
<sal_uInt16
> *pColArr
,
238 const OUString
& rName
)
239 : SwUndo( SwUndoId::INSTABLE
, &rPos
.GetDoc() ),
240 m_aInsTableOptions( rInsTableOpts
),
241 m_nStartNode( rPos
.GetNodeIndex() ), m_nRows( nRw
), m_nColumns( nCl
), m_nAdjust( nAdj
)
245 m_oColumnWidth
.emplace( *pColArr
);
248 m_pAutoFormat
.reset( new SwTableAutoFormat( *pTAFormat
) );
251 SwDoc
& rDoc
= rPos
.GetNode().GetDoc();
252 if( rDoc
.getIDocumentRedlineAccess().IsRedlineOn() )
254 m_pRedlineData
.reset( new SwRedlineData( RedlineType::Insert
, rDoc
.getIDocumentRedlineAccess().GetRedlineAuthor() ) );
255 SetRedlineFlags( rDoc
.getIDocumentRedlineAccess().GetRedlineFlags() );
258 m_sTableName
= rName
;
261 SwUndoInsTable::~SwUndoInsTable()
263 m_pDDEFieldType
.reset();
264 m_oColumnWidth
.reset();
265 m_pRedlineData
.reset();
266 m_pAutoFormat
.reset();
269 void SwUndoInsTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
271 SwDoc
& rDoc
= rContext
.GetDoc();
272 SwNodeIndex
aIdx( rDoc
.GetNodes(), m_nStartNode
);
274 SwTableNode
* pTableNd
= aIdx
.GetNode().GetTableNode();
275 OSL_ENSURE( pTableNd
, "no TableNode" );
276 pTableNd
->DelFrames();
278 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ))
279 rDoc
.getIDocumentRedlineAccess().DeleteRedline( *pTableNd
, true, RedlineType::Any
);
280 RemoveIdxFromSection( rDoc
, m_nStartNode
);
282 // move hard page breaks into next node
283 SwContentNode
* pNextNd
= rDoc
.GetNodes()[ pTableNd
->EndOfSectionIndex()+1 ]->GetContentNode();
286 SwFrameFormat
* pTableFormat
= pTableNd
->GetTable().GetFrameFormat();
288 if( const SwFormatPageDesc
* pItem
= pTableFormat
->GetItemIfSet( RES_PAGEDESC
,
290 pNextNd
->SetAttr( *pItem
);
292 if( const SvxFormatBreakItem
* pItem
= pTableFormat
->GetItemIfSet( RES_BREAK
,
294 pNextNd
->SetAttr( *pItem
);
296 ::sw::NotifyTableCollapsedParagraph(pNextNd
, nullptr);
299 m_sTableName
= pTableNd
->GetTable().GetFrameFormat()->GetName();
300 if( auto pDDETable
= dynamic_cast<const SwDDETable
*>(&pTableNd
->GetTable()) )
301 m_pDDEFieldType
.reset(static_cast<SwDDEFieldType
*>(pDDETable
->GetDDEFieldType()->Copy().release()));
303 rDoc
.GetNodes().Delete( aIdx
, pTableNd
->EndOfSectionIndex() -
304 aIdx
.GetIndex() + 1 );
306 SwPaM
& rPam( rContext
.GetCursorSupplier().CreateNewShellCursor() );
308 rPam
.GetPoint()->Assign(aIdx
);
311 void SwUndoInsTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
313 SwDoc
& rDoc
= rContext
.GetDoc();
315 SwEditShell
*const pEditShell(rDoc
.GetEditShell());
316 OSL_ENSURE(pEditShell
, "SwUndoInsTable::RedoImpl needs a SwEditShell!");
319 throw uno::RuntimeException();
322 SwPosition
const aPos(rDoc
.GetNodes(), m_nStartNode
);
323 const SwTable
* pTable
= rDoc
.InsertTable( m_aInsTableOptions
, aPos
, m_nRows
, m_nColumns
,
326 m_oColumnWidth
? &*m_oColumnWidth
: nullptr );
327 pEditShell
->MoveTable( GotoPrevTable
, fnTableStart
);
328 static_cast<SwFrameFormat
*>(pTable
->GetFrameFormat())->SetFormatName( m_sTableName
);
329 SwTableNode
* pTableNode
= rDoc
.GetNodes()[m_nStartNode
]->GetTableNode();
331 if( m_pDDEFieldType
)
333 SwDDEFieldType
* pNewType
= static_cast<SwDDEFieldType
*>(rDoc
.getIDocumentFieldsAccess().InsertFieldType(
335 std::unique_ptr
<SwDDETable
> pDDETable(new SwDDETable( pTableNode
->GetTable(), pNewType
));
336 pTableNode
->SetNewTable( std::move(pDDETable
) );
337 m_pDDEFieldType
.reset();
340 if( !((m_pRedlineData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() )) ||
341 ( !( RedlineFlags::Ignore
& GetRedlineFlags() ) &&
342 !rDoc
.getIDocumentRedlineAccess().GetRedlineTable().empty() )))
345 SwPaM
aPam( *pTableNode
->EndOfSectionNode(), *pTableNode
, SwNodeOffset(1) );
347 if( m_pRedlineData
&& IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
349 RedlineFlags eOld
= rDoc
.getIDocumentRedlineAccess().GetRedlineFlags();
350 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern(eOld
& ~RedlineFlags::Ignore
);
352 rDoc
.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlineData
, aPam
), true);
353 rDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
356 rDoc
.getIDocumentRedlineAccess().SplitRedline( aPam
);
359 void SwUndoInsTable::RepeatImpl(::sw::RepeatContext
& rContext
)
361 rContext
.GetDoc().InsertTable(
362 m_aInsTableOptions
, *rContext
.GetRepeatPaM().GetPoint(),
363 m_nRows
, m_nColumns
, m_nAdjust
, m_pAutoFormat
.get(),
364 m_oColumnWidth
? &*m_oColumnWidth
: nullptr );
367 SwRewriter
SwUndoInsTable::GetRewriter() const
369 SwRewriter aRewriter
;
371 aRewriter
.AddRule(UndoArg1
, SwResId(STR_START_QUOTE
));
372 aRewriter
.AddRule(UndoArg2
, m_sTableName
);
373 aRewriter
.AddRule(UndoArg3
, SwResId(STR_END_QUOTE
));
378 SwTableToTextSave::SwTableToTextSave( SwDoc
& rDoc
, SwNodeOffset nNd
, SwNodeOffset nEndIdx
, sal_Int32 nCnt
)
379 : m_nSttNd( nNd
), m_nEndNd( nEndIdx
), m_nContent( nCnt
)
381 // keep attributes of the joined node
382 SwTextNode
* pNd
= rDoc
.GetNodes()[ nNd
]->GetTextNode();
385 m_pHstry
.reset( new SwHistory
);
387 m_pHstry
->Add( pNd
->GetTextColl(), nNd
, SwNodeType::Text
);
388 if ( pNd
->GetpSwpHints() )
390 m_pHstry
->CopyAttr( pNd
->GetpSwpHints(), nNd
, 0,
391 pNd
->GetText().getLength(), false );
393 if( pNd
->HasSwAttrSet() )
394 m_pHstry
->CopyFormatAttr( *pNd
->GetpSwAttrSet(), nNd
);
396 if( !m_pHstry
->Count() )
402 m_pMetadataUndoStart
= pNd
->CreateUndo();
405 // we also need to store the metadata reference of the _last_ paragraph
406 // we subtract 1 to account for the removed cell start/end node pair
407 // (after SectionUp, the end of the range points to the node after the cell)
408 if ( nEndIdx
- 1 > nNd
)
410 SwTextNode
* pLastNode( rDoc
.GetNodes()[ nEndIdx
- 1 ]->GetTextNode() );
414 m_pMetadataUndoEnd
= pLastNode
->CreateUndo();
419 SwUndoTableToText::SwUndoTableToText( const SwTable
& rTable
, sal_Unicode cCh
)
420 : SwUndo( SwUndoId::TABLETOTEXT
, rTable
.GetFrameFormat()->GetDoc() ),
421 m_sTableName( rTable
.GetFrameFormat()->GetName() ),
422 m_nStartNode( 0 ), m_nEndNode( 0 ),
423 m_cSeparator( cCh
), m_nHeadlineRepeat( rTable
.GetRowsToRepeat() )
425 m_pTableSave
.reset( new SaveTable( rTable
) );
426 m_vBoxSaves
.reserve(rTable
.GetTabSortBoxes().size());
428 if( auto pDDETable
= dynamic_cast<const SwDDETable
*>(&rTable
) )
429 m_pDDEFieldType
.reset(static_cast<SwDDEFieldType
*>(pDDETable
->GetDDEFieldType()->Copy().release()));
431 m_bCheckNumFormat
= rTable
.GetFrameFormat()->GetDoc()->IsInsTableFormatNum();
433 m_pHistory
.reset(new SwHistory
);
434 const SwTableNode
* pTableNd
= rTable
.GetTableNode();
435 SwNodeOffset nTableStt
= pTableNd
->GetIndex(), nTableEnd
= pTableNd
->EndOfSectionIndex();
437 for(sw::SpzFrameFormat
* pFormat
: *pTableNd
->GetDoc().GetSpzFrameFormats())
439 SwFormatAnchor
const*const pAnchor
= &pFormat
->GetAnchor();
440 SwNode
const*const pAnchorNode
= pAnchor
->GetAnchorNode();
442 ((RndStdIds::FLY_AT_CHAR
== pAnchor
->GetAnchorId()) ||
443 (RndStdIds::FLY_AT_PARA
== pAnchor
->GetAnchorId())) &&
444 nTableStt
<= pAnchorNode
->GetIndex() &&
445 pAnchorNode
->GetIndex() < nTableEnd
)
447 m_pHistory
->AddChangeFlyAnchor(*pFormat
);
451 if( !m_pHistory
->Count() )
457 SwUndoTableToText::~SwUndoTableToText()
459 m_pDDEFieldType
.reset();
460 m_pTableSave
.reset();
465 void SwUndoTableToText::UndoImpl(::sw::UndoRedoContext
& rContext
)
467 SwDoc
& rDoc
= rContext
.GetDoc();
468 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
470 SwNodeIndex
aFrameIdx( rDoc
.GetNodes(), m_nStartNode
);
471 SwNodeIndex
aEndIdx( rDoc
.GetNodes(), m_nEndNode
);
473 pPam
->GetPoint()->Assign( aFrameIdx
);
475 pPam
->GetPoint()->Assign( aEndIdx
);
476 rDoc
.DelNumRules( *pPam
);
479 // now collect all Uppers
480 SwNode2LayoutSaveUpperFrames
aNode2Layout(aFrameIdx
.GetNode());
482 // create TableNode structure
483 SwTableNode
* pTableNd
= rDoc
.GetNodes().UndoTableToText( m_nStartNode
, m_nEndNode
, m_vBoxSaves
);
484 pTableNd
->GetTable().SetTableModel( m_pTableSave
->IsNewModel() );
485 SwTableFormat
* pTableFormat
= rDoc
.MakeTableFrameFormat( m_sTableName
, rDoc
.GetDfltFrameFormat() );
486 pTableNd
->GetTable().RegisterToFormat( *pTableFormat
);
487 pTableNd
->GetTable().SetRowsToRepeat( m_nHeadlineRepeat
);
489 // create old table structure
490 m_pTableSave
->CreateNew( pTableNd
->GetTable() );
492 if( m_pDDEFieldType
)
494 SwDDEFieldType
* pNewType
= static_cast<SwDDEFieldType
*>(rDoc
.getIDocumentFieldsAccess().InsertFieldType(
496 std::unique_ptr
<SwDDETable
> pDDETable( new SwDDETable( pTableNd
->GetTable(), pNewType
) );
497 pTableNd
->SetNewTable( std::move(pDDETable
), false );
498 m_pDDEFieldType
.reset();
501 if( m_bCheckNumFormat
)
503 SwTableSortBoxes
& rBxs
= pTableNd
->GetTable().GetTabSortBoxes();
504 for (size_t nBoxes
= rBxs
.size(); nBoxes
; )
506 rDoc
.ChkBoxNumFormat( *rBxs
[ --nBoxes
], false );
512 sal_uInt16 nTmpEnd
= m_pHistory
->GetTmpEnd();
513 m_pHistory
->TmpRollback( &rDoc
, 0 );
514 m_pHistory
->SetTmpEnd( nTmpEnd
);
517 aNode2Layout
.RestoreUpperFrames( rDoc
.GetNodes(),
518 pTableNd
->GetIndex(), pTableNd
->GetIndex()+1 );
520 // Is a table selection requested?
522 pPam
->GetPoint()->Assign( *pTableNd
->EndOfSectionNode() );
524 pPam
->GetPoint()->Assign( *pPam
->GetPointNode().StartOfSectionNode() );
525 pPam
->Move( fnMoveForward
, GoInContent
);
527 pPam
->Move( fnMoveBackward
, GoInContent
);
529 ClearFEShellTabCols(rDoc
, nullptr);
532 // located in untbl.cxx and only an Undo object is allowed to call it
533 SwTableNode
* SwNodes::UndoTableToText( SwNodeOffset nSttNd
, SwNodeOffset nEndNd
,
534 const SwTableToTextSaves
& rSavedData
)
536 SwNodeIndex
aSttIdx( *this, nSttNd
);
537 SwNodeIndex
aEndIdx( *this, nEndNd
+1 );
539 SwTableNode
* pTableNd
= new SwTableNode( aSttIdx
.GetNode() );
540 SwEndNode
* pEndNd
= new SwEndNode( aEndIdx
.GetNode(), *pTableNd
);
544 /* Set pTableNd as start of section for all nodes in [nSttNd, nEndNd].
545 Delete all Frames attached to the nodes in that range. */
548 SwNodeOffset n
, nTmpEnd
= aEndIdx
.GetIndex();
549 for( n
= pTableNd
->GetIndex() + 1; n
< nTmpEnd
; ++n
)
552 if (pNd
->IsContentNode())
554 static_cast<SwContentNode
*>(pNd
)->DelFrames(nullptr);
556 // tdf#147938 reset merge flag in nodes
557 pNd
->SetRedlineMergeFlag(SwNode::Merge::None
);
558 pNd
->m_pStartOfSection
= pTableNd
;
562 // than create table structure partially. First a single line that contains
563 // all boxes. The correct structure is then taken from SaveStruct.
564 SwTableBoxFormat
* pBoxFormat
= GetDoc().MakeTableBoxFormat();
565 SwTableLineFormat
* pLineFormat
= GetDoc().MakeTableLineFormat();
566 SwTableLine
* pLine
= new SwTableLine( pLineFormat
, rSavedData
.size(), nullptr );
567 pTableNd
->GetTable().GetTabLines().insert( pTableNd
->GetTable().GetTabLines().begin(), pLine
);
569 for( size_t n
= rSavedData
.size(); n
; )
571 const SwTableToTextSave
*const pSave
= rSavedData
[ --n
].get();
572 // if the start node was merged with last from prev. cell,
573 // subtract 1 from index to get the merged paragraph, and split that
574 aSttIdx
= pSave
->m_nSttNd
- ( ( SAL_MAX_INT32
!= pSave
->m_nContent
) ? 1 : 0);
575 SwTextNode
* pTextNd
= aSttIdx
.GetNode().GetTextNode();
577 if( SAL_MAX_INT32
!= pSave
->m_nContent
)
579 // split at ContentPosition, delete previous char (= separator)
580 OSL_ENSURE( pTextNd
, "Where is my TextNode?" );
581 SwContentIndex
aCntPos( pTextNd
, pSave
->m_nContent
- 1 );
583 const std::shared_ptr
<sw::mark::ContentIdxStore
> pContentStore(sw::mark::ContentIdxStore::Create());
584 pContentStore
->Save(GetDoc(), aSttIdx
.GetIndex(), aCntPos
.GetIndex());
586 pTextNd
->EraseText( aCntPos
, 1 );
588 std::function
<void (SwTextNode
*, sw::mark::RestoreMode
, bool)> restoreFunc(
589 [&](SwTextNode
*const pNewNode
, sw::mark::RestoreMode
const eMode
, bool)
591 if (!pContentStore
->Empty())
593 pContentStore
->Restore(*pNewNode
, pSave
->m_nContent
, pSave
->m_nContent
+ 1, eMode
);
596 pTextNd
->SplitContentNode(
597 SwPosition(aSttIdx
, aCntPos
), &restoreFunc
);
603 pTextNd
->GetTextNode()->RestoreMetadata(pSave
->m_pMetadataUndoStart
);
604 if( pTextNd
->HasSwAttrSet() )
605 pTextNd
->ResetAllAttr();
607 if( pTextNd
->GetpSwpHints() )
608 pTextNd
->ClearSwpHintsArr( false );
611 if( pSave
->m_pHstry
)
613 sal_uInt16 nTmpEnd
= pSave
->m_pHstry
->GetTmpEnd();
614 pSave
->m_pHstry
->TmpRollback( &GetDoc(), 0 );
615 pSave
->m_pHstry
->SetTmpEnd( nTmpEnd
);
619 // end points to node after cell
620 if ( pSave
->m_nEndNd
- 1 > pSave
->m_nSttNd
)
622 SwTextNode
* pLastNode
= (*this)[ pSave
->m_nEndNd
- 1 ]->GetTextNode();
625 pLastNode
->RestoreMetadata(pSave
->m_pMetadataUndoEnd
);
629 aEndIdx
= pSave
->m_nEndNd
;
630 SwStartNode
* pSttNd
= new SwStartNode( aSttIdx
.GetNode(), SwNodeType::Start
,
631 SwTableBoxStartNode
);
632 pSttNd
->m_pStartOfSection
= pTableNd
;
633 new SwEndNode( aEndIdx
.GetNode(), *pSttNd
);
635 for( SwNodeOffset i
= aSttIdx
.GetIndex(); i
< aEndIdx
.GetIndex()-1; ++i
)
638 pNd
->m_pStartOfSection
= pSttNd
;
639 if( pNd
->IsStartNode() )
640 i
= pNd
->EndOfSectionIndex();
643 SwTableBox
* pBox
= new SwTableBox( pBoxFormat
, *pSttNd
, pLine
);
644 pLine
->GetTabBoxes().insert( pLine
->GetTabBoxes().begin(), pBox
);
649 void SwUndoTableToText::RedoImpl(::sw::UndoRedoContext
& rContext
)
651 SwDoc
& rDoc
= rContext
.GetDoc();
652 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
654 pPam
->GetPoint()->Assign( m_nStartNode
);
655 SwNodeIndex
aSaveIdx( pPam
->GetPoint()->GetNode(), -1 );
657 pPam
->SetMark(); // log off all indices
660 SwTableNode
* pTableNd
= pPam
->GetPointNode().GetTableNode();
661 OSL_ENSURE( pTableNd
, "Could not find any TableNode" );
663 if( auto pDDETable
= dynamic_cast<const SwDDETable
*>(&pTableNd
->GetTable()) )
664 m_pDDEFieldType
.reset(static_cast<SwDDEFieldType
*>(pDDETable
->GetDDEFieldType()->Copy().release()));
666 rDoc
.TableToText( pTableNd
, m_cSeparator
);
669 SwContentNode
* pCNd
= aSaveIdx
.GetNode().GetContentNode();
670 if( !pCNd
&& nullptr == ( pCNd
= rDoc
.GetNodes().GoNext( &aSaveIdx
) ) &&
671 nullptr == ( pCNd
= SwNodes::GoPrevious( &aSaveIdx
)) )
673 OSL_FAIL( "Where is the TextNode now?" );
676 pPam
->GetPoint()->Assign( aSaveIdx
);
678 pPam
->SetMark(); // log off all indices
682 void SwUndoTableToText::RepeatImpl(::sw::RepeatContext
& rContext
)
684 SwPaM
*const pPam
= & rContext
.GetRepeatPaM();
685 SwTableNode
*const pTableNd
= pPam
->GetPointNode().FindTableNode();
688 // move cursor out of table
689 pPam
->GetPoint()->Assign( *pTableNd
->EndOfSectionNode() );
690 pPam
->Move( fnMoveForward
, GoInContent
);
694 rContext
.GetDoc().TableToText( pTableNd
, m_cSeparator
);
698 void SwUndoTableToText::SetRange( const SwNodeRange
& rRg
)
700 m_nStartNode
= rRg
.aStart
.GetIndex();
701 m_nEndNode
= rRg
.aEnd
.GetIndex();
704 void SwUndoTableToText::AddBoxPos( SwDoc
& rDoc
, SwNodeOffset nNdIdx
, SwNodeOffset nEndIdx
, sal_Int32 nContentIdx
)
706 m_vBoxSaves
.push_back(std::make_unique
<SwTableToTextSave
>(rDoc
, nNdIdx
, nEndIdx
, nContentIdx
));
709 SwUndoTextToTable::SwUndoTextToTable( const SwPaM
& rRg
,
710 const SwInsertTableOptions
& rInsTableOpts
,
711 sal_Unicode cCh
, sal_uInt16 nAdj
,
712 const SwTableAutoFormat
* pAFormat
)
713 : SwUndo( SwUndoId::TEXTTOTABLE
, &rRg
.GetDoc() ), SwUndRng( rRg
), m_aInsertTableOpts( rInsTableOpts
),
714 m_pHistory( nullptr ), m_cSeparator( cCh
), m_nAdjust( nAdj
)
717 m_pAutoFormat
.reset( new SwTableAutoFormat( *pAFormat
) );
719 const SwPosition
* pEnd
= rRg
.End();
720 SwNodes
& rNds
= rRg
.GetDoc().GetNodes();
721 m_bSplitEnd
= pEnd
->GetContentIndex() && ( pEnd
->GetContentIndex()
722 != pEnd
->GetNode().GetContentNode()->Len() ||
723 pEnd
->GetNodeIndex() >= rNds
.GetEndOfContent().GetIndex()-1 );
726 SwUndoTextToTable::~SwUndoTextToTable()
728 m_pAutoFormat
.reset();
731 void SwUndoTextToTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
733 SwDoc
& rDoc
= rContext
.GetDoc();
735 SwNodeOffset nTableNd
= m_nSttNode
;
737 ++nTableNd
; // Node was split previously
738 SwNodeIndex
aIdx( rDoc
.GetNodes(), nTableNd
);
739 SwTableNode
*const pTNd
= aIdx
.GetNode().GetTableNode();
740 OSL_ENSURE( pTNd
, "Could not find a TableNode" );
742 RemoveIdxFromSection( rDoc
, nTableNd
);
744 m_sTableName
= pTNd
->GetTable().GetFrameFormat()->GetName();
748 m_pHistory
->TmpRollback( &rDoc
, 0 );
749 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
752 if( !mvDelBoxes
.empty() )
755 SwTable
& rTable
= pTNd
->GetTable();
756 for( size_t n
= mvDelBoxes
.size(); n
; )
758 SwTableBox
* pBox
= rTable
.GetTableBox( mvDelBoxes
[ --n
] );
760 ::DeleteBox_( rTable
, pBox
, nullptr, false, false );
762 OSL_ENSURE( false, "Where is my box?" );
767 rDoc
.TableToText( pTNd
, 0x0b == m_cSeparator
? 0x09 : m_cSeparator
);
769 // join again at start?
772 SwPaM
aPam(rDoc
.GetNodes(), nTableNd
);
773 if (aPam
.Move(fnMoveBackward
, GoInContent
))
775 SwNode
& rIdx
= aPam
.GetPoint()->GetNode();
777 // than move, relatively, the Cursor/etc. again
778 RemoveIdxRel( rIdx
.GetIndex()+1, *aPam
.GetPoint() );
780 rIdx
.GetContentNode()->JoinNext();
784 // join again at end?
787 SwPosition
aEndPos( rDoc
.GetNodes(), m_nEndNode
);
788 SwTextNode
* pTextNd
= aEndPos
.GetNode().GetTextNode();
789 if( pTextNd
&& pTextNd
->CanJoinNext() )
791 aEndPos
.nContent
.Assign( nullptr, 0 );
793 // than move, relatively, the Cursor/etc. again
794 aEndPos
.SetContent(pTextNd
->GetText().getLength());
795 RemoveIdxRel( m_nEndNode
+ 1, aEndPos
);
801 AddUndoRedoPaM(rContext
);
804 void SwUndoTextToTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
806 SwPaM
& rPam( AddUndoRedoPaM(rContext
) );
807 RemoveIdxFromRange(rPam
, false);
810 SwTable
const*const pTable
= rContext
.GetDoc().TextToTable(
811 m_aInsertTableOpts
, rPam
, m_cSeparator
, m_nAdjust
, m_pAutoFormat
.get() );
812 static_cast<SwFrameFormat
*>(pTable
->GetFrameFormat())->SetFormatName( m_sTableName
);
815 void SwUndoTextToTable::RepeatImpl(::sw::RepeatContext
& rContext
)
818 if (!rContext
.GetRepeatPaM().GetPointNode().FindTableNode())
820 rContext
.GetDoc().TextToTable( m_aInsertTableOpts
, rContext
.GetRepeatPaM(),
821 m_cSeparator
, m_nAdjust
,
822 m_pAutoFormat
.get() );
826 void SwUndoTextToTable::AddFillBox( const SwTableBox
& rBox
)
828 mvDelBoxes
.push_back( rBox
.GetSttIdx() );
831 SwHistory
& SwUndoTextToTable::GetHistory()
834 m_pHistory
= new SwHistory
;
838 SwUndoTableHeadline::SwUndoTableHeadline( const SwTable
& rTable
, sal_uInt16 nOldHdl
,
840 : SwUndo( SwUndoId::TABLEHEADLINE
, rTable
.GetFrameFormat()->GetDoc() ),
841 m_nOldHeadline( nOldHdl
),
842 m_nNewHeadline( nNewHdl
)
844 OSL_ENSURE( !rTable
.GetTabSortBoxes().empty(), "Table without content" );
845 const SwStartNode
*pSttNd
= rTable
.GetTabSortBoxes()[ 0 ]->GetSttNd();
846 OSL_ENSURE( pSttNd
, "Box without content" );
848 m_nTableNode
= pSttNd
->StartOfSectionIndex();
851 void SwUndoTableHeadline::UndoImpl(::sw::UndoRedoContext
& rContext
)
853 SwDoc
& rDoc
= rContext
.GetDoc();
854 SwTableNode
* pTNd
= rDoc
.GetNodes()[ m_nTableNode
]->GetTableNode();
855 OSL_ENSURE( pTNd
, "could not find any TableNode" );
857 rDoc
.SetRowsToRepeat( pTNd
->GetTable(), m_nOldHeadline
);
860 void SwUndoTableHeadline::RedoImpl(::sw::UndoRedoContext
& rContext
)
862 SwDoc
& rDoc
= rContext
.GetDoc();
864 SwTableNode
* pTNd
= rDoc
.GetNodes()[ m_nTableNode
]->GetTableNode();
865 OSL_ENSURE( pTNd
, "could not find any TableNode" );
867 rDoc
.SetRowsToRepeat( pTNd
->GetTable(), m_nNewHeadline
);
870 void SwUndoTableHeadline::RepeatImpl(::sw::RepeatContext
& rContext
)
872 SwTableNode
*const pTableNd
=
873 rContext
.GetRepeatPaM().GetPointNode().FindTableNode();
876 rContext
.GetDoc().SetRowsToRepeat( pTableNd
->GetTable(), m_nNewHeadline
);
880 SaveTable::SaveTable( const SwTable
& rTable
, sal_uInt16 nLnCnt
, bool bSaveFormula
)
881 : m_aTableSet(*rTable
.GetFrameFormat()->GetAttrSet().GetPool(), aTableSetRange
),
882 m_pSwTable(&rTable
), m_nLineCount(nLnCnt
), m_bSaveFormula(bSaveFormula
)
884 m_bModifyBox
= false;
885 m_bNewModel
= rTable
.IsNewModel();
886 m_aTableSet
.Put(rTable
.GetFrameFormat()->GetAttrSet());
887 m_pLine
.reset( new SaveLine( nullptr, *rTable
.GetTabLines()[ 0 ], *this ) );
889 SaveLine
* pLn
= m_pLine
.get();
890 if( USHRT_MAX
== nLnCnt
)
891 nLnCnt
= rTable
.GetTabLines().size();
892 for( sal_uInt16 n
= 1; n
< nLnCnt
; ++n
)
893 pLn
= new SaveLine( pLn
, *rTable
.GetTabLines()[ n
], *this );
895 m_aFrameFormats
.clear();
896 m_pSwTable
= nullptr;
899 sal_uInt16
SaveTable::AddFormat( SwFrameFormat
* pFormat
, bool bIsLine
)
901 size_t nRet
= m_aFrameFormats
.GetPos(pFormat
);
902 if( SIZE_MAX
== nRet
)
904 // Create copy of ItemSet
905 auto pSet
= std::make_shared
<SfxItemSet
>( *pFormat
->GetAttrSet().GetPool(),
906 bIsLine
? aTableLineSetRange
: aTableBoxSetRange
);
907 pSet
->Put( pFormat
->GetAttrSet() );
908 // When a formula is set, never save the value. It possibly must be
910 // Save formulas always in plain text.
911 if( const SwTableBoxFormula
* pItem
= pSet
->GetItemIfSet( RES_BOXATR_FORMULA
))
913 pSet
->ClearItem( RES_BOXATR_VALUE
);
914 if (m_pSwTable
&& m_bSaveFormula
)
916 const_cast<SwTable
*>(m_pSwTable
)->SwitchFormulasToExternalRepresentation();
917 SwTableBoxFormula
* pFormulaItem
= const_cast<SwTableBoxFormula
*>(pItem
);
918 pFormulaItem
->ChgDefinedIn(pFormat
);
919 pFormulaItem
->ToRelBoxNm(m_pSwTable
);
920 pFormulaItem
->ChgDefinedIn(nullptr);
923 nRet
= m_aSets
.size();
924 m_aSets
.push_back(pSet
);
925 m_aFrameFormats
.insert(m_aFrameFormats
.begin() + nRet
, pFormat
);
927 return o3tl::narrowing
<sal_uInt16
>(nRet
);
930 void SaveTable::RestoreAttr( SwTable
& rTable
, bool bMdfyBox
)
932 m_bModifyBox
= bMdfyBox
;
934 FndBox_
aTmpBox( nullptr, nullptr );
935 bool bHideChanges
= rTable
.GetFrameFormat()->GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines();
936 // TODO delete/make frames only at changing line attribute TextChangesOnly (RES_PRINT) to true again
938 aTmpBox
.DelFrames( rTable
);
940 // first, get back attributes of TableFrameFormat
941 SwFrameFormat
* pFormat
= rTable
.GetFrameFormat();
942 SfxItemSet
& rFormatSet
= const_cast<SfxItemSet
&>(static_cast<SfxItemSet
const &>(pFormat
->GetAttrSet()));
943 rFormatSet
.ClearItem();
944 rFormatSet
.Put(m_aTableSet
);
946 pFormat
->InvalidateInSwCache(RES_ATTRSET_CHG
);
948 // table without table frame
949 bool bHiddenTable
= true;
951 // for safety, invalidate all TableFrames
952 SwIterator
<SwTabFrame
,SwFormat
> aIter( *pFormat
);
953 for( SwTabFrame
* pLast
= aIter
.First(); pLast
; pLast
= aIter
.Next() )
955 if( pLast
->GetTable() == &rTable
)
957 pLast
->InvalidateAll();
958 pLast
->SetCompletePaint();
959 bHiddenTable
= false;
963 // fill FrameFormats with defaults (0)
965 for (size_t n
= m_aSets
.size(); n
; --n
)
966 m_aFrameFormats
.push_back(pFormat
);
968 const size_t nLnCnt
= (USHRT_MAX
== m_nLineCount
)
969 ? rTable
.GetTabLines().size()
972 SaveLine
* pLn
= m_pLine
.get();
973 for (size_t n
= 0; n
< nLnCnt
; ++n
, pLn
= pLn
->m_pNext
)
977 OSL_ENSURE( false, "Number of lines changed" );
981 pLn
->RestoreAttr( *rTable
.GetTabLines()[ n
], *this );
984 m_aFrameFormats
.clear();
985 m_bModifyBox
= false;
991 SwTableNode
* pTableNode
= rTable
.GetTableNode();
992 pTableNode
->DelFrames();
993 pTableNode
->MakeOwnFrames();
997 aTmpBox
.MakeFrames( rTable
);
1002 void SaveTable::SaveContentAttrs( SwDoc
* pDoc
)
1004 m_pLine
->SaveContentAttrs(pDoc
);
1007 void SaveTable::CreateNew( SwTable
& rTable
, bool bCreateFrames
,
1008 bool bRestoreChart
)
1010 FndBox_
aTmpBox( nullptr, nullptr );
1011 aTmpBox
.DelFrames( rTable
);
1013 // first, get back attributes of TableFrameFormat
1014 SwFrameFormat
* pFormat
= rTable
.GetFrameFormat();
1015 SfxItemSet
& rFormatSet
= const_cast<SfxItemSet
&>(static_cast<SfxItemSet
const &>(pFormat
->GetAttrSet()));
1016 rFormatSet
.ClearItem();
1017 rFormatSet
.Put(m_aTableSet
);
1019 pFormat
->InvalidateInSwCache(RES_ATTRSET_CHG
);
1021 // SwTableBox must have a format - the SwTableBox takes ownership of it
1022 SwTableBoxFormat
*const pNewFormat(pFormat
->GetDoc()->MakeTableBoxFormat());
1023 SwTableBox
aParent(pNewFormat
, rTable
.GetTabLines().size(), nullptr);
1025 // fill FrameFormats with defaults (0)
1027 for( size_t n
= m_aSets
.size(); n
; --n
)
1028 m_aFrameFormats
.push_back(pFormat
);
1030 m_pLine
->CreateNew(rTable
, aParent
, *this);
1031 m_aFrameFormats
.clear();
1033 // add new lines, delete old ones
1034 const size_t nOldLines
= (USHRT_MAX
== m_nLineCount
)
1035 ? rTable
.GetTabLines().size()
1038 SwDoc
*pDoc
= rTable
.GetFrameFormat()->GetDoc();
1039 SwChartDataProvider
*pPCD
= pDoc
->getIDocumentChartDataProviderAccess().GetChartDataProvider();
1041 for( ; n
< aParent
.GetTabLines().size(); ++n
)
1043 SwTableLine
* pLn
= aParent
.GetTabLines()[ n
];
1044 pLn
->SetUpper( nullptr );
1047 SwTableLine
* pOld
= rTable
.GetTabLines()[ n
];
1049 // TL_CHART2: notify chart about boxes to be removed
1050 const SwTableBoxes
&rBoxes
= pOld
->GetTabBoxes();
1051 const size_t nBoxes
= rBoxes
.size();
1052 for (size_t k
= 0; k
< nBoxes
; ++k
)
1054 SwTableBox
*pBox
= rBoxes
[k
];
1056 pPCD
->DeleteBox( &rTable
, *pBox
);
1059 rTable
.GetTabLines()[n
] = pLn
;
1063 rTable
.GetTabLines().insert( rTable
.GetTabLines().begin() + n
, pLn
);
1068 // remove remaining lines...
1069 for (size_t k1
= 0; k1
< nOldLines
- n
; ++k1
)
1071 const SwTableBoxes
&rBoxes
= rTable
.GetTabLines()[n
+ k1
]->GetTabBoxes();
1072 const size_t nBoxes
= rBoxes
.size();
1073 for (size_t k2
= 0; k2
< nBoxes
; ++k2
)
1075 SwTableBox
*pBox
= rBoxes
[k2
];
1076 // TL_CHART2: notify chart about boxes to be removed
1078 pPCD
->DeleteBox( &rTable
, *pBox
);
1082 for( SwTableLines::const_iterator it
= rTable
.GetTabLines().begin() + n
;
1083 it
!= rTable
.GetTabLines().begin() + nOldLines
; ++it
)
1085 rTable
.GetTabLines().erase( rTable
.GetTabLines().begin() + n
, rTable
.GetTabLines().begin() + nOldLines
);
1088 aParent
.GetTabLines().erase( aParent
.GetTabLines().begin(), aParent
.GetTabLines().begin() + n
);
1089 assert(aParent
.GetTabLines().empty());
1092 aTmpBox
.MakeFrames( rTable
);
1095 // TL_CHART2: need to inform chart of probably changed cell names
1096 pDoc
->UpdateCharts( rTable
.GetFrameFormat()->GetName() );
1100 SwFrameFormat
& SaveTable::CreateNewFormat(SwFrameFormat
& rFormat
, sal_uInt16 nFormatPos
)
1102 rFormat
.SetFormatAttr(*m_aSets
[nFormatPos
]);
1103 m_aFrameFormats
[nFormatPos
] = &rFormat
;
1107 void SaveTable::NewFrameFormatForLine(const SwTableLine
& rTableLn
, sal_uInt16 nFormatPos
, SwFrameFormat
* pOldFormat
)
1109 SwFrameFormat
* pFormat
= m_aFrameFormats
[nFormatPos
];
1111 pFormat
= &CreateNewFormat(*pOldFormat
->GetDoc()->MakeTableLineFormat(), nFormatPos
);
1112 pOldFormat
->CallSwClientNotify(sw::MoveTableLineHint(*pFormat
, rTableLn
));
1113 pFormat
->Add(const_cast<SwTableLine
*>(&rTableLn
));
1114 KillEmptyFrameFormat(*pOldFormat
);
1117 void SaveTable::NewFrameFormatForBox(const SwTableBox
& rTableBx
, sal_uInt16 nFormatPos
, SwFrameFormat
* pOldFormat
)
1119 SwFrameFormat
* pFormat
= m_aFrameFormats
[nFormatPos
];
1121 pFormat
= &CreateNewFormat(*pOldFormat
->GetDoc()->MakeTableBoxFormat(), nFormatPos
);
1122 pOldFormat
->CallSwClientNotify(sw::MoveTableBoxHint(*pFormat
, rTableBx
));
1123 pFormat
->MoveTableBox(*const_cast<SwTableBox
*>(&rTableBx
), m_bModifyBox
? pOldFormat
: nullptr);
1124 KillEmptyFrameFormat(*pOldFormat
);
1127 SaveLine::SaveLine(SaveLine
* pPrev
, const SwTableLine
& rLine
, SaveTable
& rSTable
)
1131 pPrev
->m_pNext
= this;
1133 m_nItemSet
= rSTable
.AddFormat(rLine
.GetFrameFormat(), true);
1135 m_pBox
= new SaveBox(nullptr, *rLine
.GetTabBoxes()[0], rSTable
);
1136 SaveBox
* pBx
= m_pBox
;
1137 for( size_t n
= 1; n
< rLine
.GetTabBoxes().size(); ++n
)
1138 pBx
= new SaveBox( pBx
, *rLine
.GetTabBoxes()[ n
], rSTable
);
1141 SaveLine::~SaveLine()
1147 void SaveLine::RestoreAttr( SwTableLine
& rLine
, SaveTable
& rSTable
)
1149 rSTable
.NewFrameFormatForLine(rLine
, m_nItemSet
, rLine
.GetFrameFormat());
1151 SaveBox
* pBx
= m_pBox
;
1152 for (size_t n
= 0; n
< rLine
.GetTabBoxes().size(); ++n
, pBx
= pBx
->m_pNext
)
1156 OSL_ENSURE( false, "Number of boxes changed" );
1159 pBx
->RestoreAttr( *rLine
.GetTabBoxes()[ n
], rSTable
);
1163 void SaveLine::SaveContentAttrs( SwDoc
* pDoc
)
1165 m_pBox
->SaveContentAttrs(pDoc
);
1167 m_pNext
->SaveContentAttrs(pDoc
);
1170 void SaveLine::CreateNew( SwTable
& rTable
, SwTableBox
& rParent
, SaveTable
& rSTable
)
1172 SwTableLineFormat
* pFormat
1173 = static_cast<SwTableLineFormat
*>(rSTable
.m_aFrameFormats
[m_nItemSet
]);
1176 SwDoc
* pDoc
= rTable
.GetFrameFormat()->GetDoc();
1177 pFormat
= pDoc
->MakeTableLineFormat();
1178 pFormat
->SetFormatAttr(*rSTable
.m_aSets
[m_nItemSet
]);
1179 rSTable
.m_aFrameFormats
[m_nItemSet
] = pFormat
;
1181 SwTableLine
* pNew
= new SwTableLine( pFormat
, 1, &rParent
);
1183 rParent
.GetTabLines().push_back( pNew
);
1185 m_pBox
->CreateNew(rTable
, *pNew
, rSTable
);
1188 m_pNext
->CreateNew(rTable
, rParent
, rSTable
);
1191 SaveBox::SaveBox(SaveBox
* pPrev
, const SwTableBox
& rBox
, SaveTable
& rSTable
)
1193 , m_nStartNode(NODE_OFFSET_MAX
)
1196 m_Ptrs
.pLine
= nullptr;
1199 pPrev
->m_pNext
= this;
1201 m_nItemSet
= rSTable
.AddFormat(rBox
.GetFrameFormat(), false);
1203 if( rBox
.GetSttNd() )
1205 m_nStartNode
= rBox
.GetSttIdx();
1206 m_nRowSpan
= rBox
.getRowSpan();
1210 m_Ptrs
.pLine
= new SaveLine(nullptr, *rBox
.GetTabLines()[0], rSTable
);
1212 SaveLine
* pLn
= m_Ptrs
.pLine
;
1213 for( size_t n
= 1; n
< rBox
.GetTabLines().size(); ++n
)
1214 pLn
= new SaveLine( pLn
, *rBox
.GetTabLines()[ n
], rSTable
);
1220 if (NODE_OFFSET_MAX
== m_nStartNode
) // no EndBox
1221 delete m_Ptrs
.pLine
;
1223 delete m_Ptrs
.pContentAttrs
;
1227 void SaveBox::RestoreAttr( SwTableBox
& rBox
, SaveTable
& rSTable
)
1229 rSTable
.NewFrameFormatForBox(rBox
, m_nItemSet
, rBox
.GetFrameFormat());
1231 if (NODE_OFFSET_MAX
== m_nStartNode
) // no EndBox
1233 if( rBox
.GetTabLines().empty() )
1235 OSL_ENSURE( false, "Number of lines changed" );
1239 SaveLine
* pLn
= m_Ptrs
.pLine
;
1240 for (size_t n
= 0; n
< rBox
.GetTabLines().size(); ++n
, pLn
= pLn
->m_pNext
)
1244 OSL_ENSURE( false, "Number of lines changed" );
1248 pLn
->RestoreAttr( *rBox
.GetTabLines()[ n
], rSTable
);
1252 else if (rBox
.GetSttNd() && rBox
.GetSttIdx() == m_nStartNode
)
1254 if (m_Ptrs
.pContentAttrs
)
1256 SwNodes
& rNds
= rBox
.GetFrameFormat()->GetDoc()->GetNodes();
1257 sal_uInt16 nSet
= 0;
1258 SwNodeOffset nEnd
= rBox
.GetSttNd()->EndOfSectionIndex();
1259 for (SwNodeOffset n
= m_nStartNode
+ 1; n
< nEnd
; ++n
)
1261 SwContentNode
* pCNd
= rNds
[ n
]->GetContentNode();
1264 std::shared_ptr
<SfxItemSet
> pSet((*m_Ptrs
.pContentAttrs
)[nSet
++]);
1267 for( const WhichPair
& rPair
: aSave_BoxContentSet
)
1268 pCNd
->ResetAttr( rPair
.first
, rPair
.second
);
1269 pCNd
->SetAttr( *pSet
);
1272 pCNd
->ResetAllAttr();
1279 OSL_ENSURE( false, "Box not anymore at the same node" );
1283 void SaveBox::SaveContentAttrs( SwDoc
* pDoc
)
1285 if (NODE_OFFSET_MAX
== m_nStartNode
) // no EndBox
1287 // continue in current line
1288 m_Ptrs
.pLine
->SaveContentAttrs(pDoc
);
1292 SwNodeOffset nEnd
= pDoc
->GetNodes()[m_nStartNode
]->EndOfSectionIndex();
1293 m_Ptrs
.pContentAttrs
= new SfxItemSets
;
1294 for (SwNodeOffset n
= m_nStartNode
+ 1; n
< nEnd
; ++n
)
1296 SwContentNode
* pCNd
= pDoc
->GetNodes()[ n
]->GetContentNode();
1299 std::shared_ptr
<SfxItemSet
> pSet
;
1300 if( pCNd
->HasSwAttrSet() )
1302 pSet
= std::make_shared
<SfxItemSet
>( pDoc
->GetAttrPool(),
1303 aSave_BoxContentSet
);
1304 pSet
->Put( *pCNd
->GetpSwAttrSet() );
1307 m_Ptrs
.pContentAttrs
->push_back(pSet
);
1312 m_pNext
->SaveContentAttrs(pDoc
);
1315 void SaveBox::CreateNew( SwTable
& rTable
, SwTableLine
& rParent
, SaveTable
& rSTable
)
1317 SwTableBoxFormat
* pFormat
= static_cast<SwTableBoxFormat
*>(rSTable
.m_aFrameFormats
[m_nItemSet
]);
1320 SwDoc
* pDoc
= rTable
.GetFrameFormat()->GetDoc();
1321 pFormat
= pDoc
->MakeTableBoxFormat();
1322 pFormat
->SetFormatAttr(*rSTable
.m_aSets
[m_nItemSet
]);
1323 rSTable
.m_aFrameFormats
[m_nItemSet
] = pFormat
;
1326 if (NODE_OFFSET_MAX
== m_nStartNode
) // no EndBox
1328 SwTableBox
* pNew
= new SwTableBox( pFormat
, 1, &rParent
);
1329 rParent
.GetTabBoxes().push_back( pNew
);
1331 m_Ptrs
.pLine
->CreateNew(rTable
, *pNew
, rSTable
);
1335 // search box for StartNode in old table
1336 SwTableBox
* pBox
= rTable
.GetTableBox(m_nStartNode
);
1339 SwFrameFormat
* pOld
= pBox
->GetFrameFormat();
1340 pBox
->RegisterToFormat( *pFormat
);
1341 if( !pOld
->HasWriterListeners() )
1344 pBox
->setRowSpan(m_nRowSpan
);
1346 SwTableBoxes
* pTBoxes
= &pBox
->GetUpper()->GetTabBoxes();
1347 pTBoxes
->erase( std::find( pTBoxes
->begin(), pTBoxes
->end(), pBox
) );
1349 pBox
->SetUpper( &rParent
);
1350 pTBoxes
= &rParent
.GetTabBoxes();
1351 pTBoxes
->push_back( pBox
);
1356 m_pNext
->CreateNew(rTable
, rParent
, rSTable
);
1359 // UndoObject for attribute changes on table
1360 SwUndoAttrTable::SwUndoAttrTable( const SwTableNode
& rTableNd
, bool bClearTabCols
)
1361 : SwUndo( SwUndoId::TABLE_ATTR
, &rTableNd
.GetDoc() ),
1362 m_nStartNode( rTableNd
.GetIndex() )
1364 m_bClearTableCol
= bClearTabCols
;
1365 m_pSaveTable
.reset( new SaveTable( rTableNd
.GetTable() ) );
1368 SwUndoAttrTable::~SwUndoAttrTable()
1372 void SwUndoAttrTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
1374 SwDoc
& rDoc
= rContext
.GetDoc();
1375 SwTableNode
* pTableNd
= rDoc
.GetNodes()[ m_nStartNode
]->GetTableNode();
1376 OSL_ENSURE( pTableNd
, "no TableNode" );
1380 SaveTable
* pOrig
= new SaveTable( pTableNd
->GetTable() );
1381 m_pSaveTable
->RestoreAttr( pTableNd
->GetTable() );
1382 m_pSaveTable
.reset( pOrig
);
1385 if( m_bClearTableCol
)
1387 ClearFEShellTabCols(rDoc
, nullptr);
1391 void SwUndoAttrTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
1396 // UndoObject for AutoFormat on Table
1397 SwUndoTableAutoFormat::SwUndoTableAutoFormat( const SwTableNode
& rTableNd
,
1398 const SwTableAutoFormat
& rAFormat
)
1399 : SwUndo( SwUndoId::TABLE_AUTOFMT
, &rTableNd
.GetDoc() )
1400 , m_TableStyleName(rTableNd
.GetTable().GetTableStyleName())
1401 , m_nStartNode( rTableNd
.GetIndex() )
1402 , m_bSaveContentAttr( false )
1403 , m_nRepeatHeading(rTableNd
.GetTable().GetRowsToRepeat())
1405 m_pSaveTable
.reset( new SaveTable( rTableNd
.GetTable() ) );
1407 if( rAFormat
.IsFont() || rAFormat
.IsJustify() )
1409 // then also go over the ContentNodes of the EndBoxes and collect
1410 // all paragraph attributes
1411 m_pSaveTable
->SaveContentAttrs( &const_cast<SwDoc
&>(rTableNd
.GetDoc()) );
1412 m_bSaveContentAttr
= true;
1416 SwUndoTableAutoFormat::~SwUndoTableAutoFormat()
1420 void SwUndoTableAutoFormat::SaveBoxContent( const SwTableBox
& rBox
)
1422 m_Undos
.push_back(std::make_shared
<SwUndoTableNumFormat
>(rBox
));
1426 SwUndoTableAutoFormat::UndoRedo(bool const bUndo
, ::sw::UndoRedoContext
& rContext
)
1428 SwDoc
& rDoc
= rContext
.GetDoc();
1429 SwTableNode
* pTableNd
= rDoc
.GetNodes()[ m_nStartNode
]->GetTableNode();
1430 OSL_ENSURE( pTableNd
, "no TableNode" );
1432 SwTable
& table
= pTableNd
->GetTable();
1433 if (table
.GetTableStyleName() != m_TableStyleName
)
1435 OUString
const temp(table
.GetTableStyleName());
1436 table
.SetTableStyleName(m_TableStyleName
);
1437 m_TableStyleName
= temp
;
1439 SaveTable
* pOrig
= new SaveTable( table
);
1440 // then go also over the ContentNodes of the EndBoxes and collect
1441 // all paragraph attributes
1442 if( m_bSaveContentAttr
)
1443 pOrig
->SaveContentAttrs( &rDoc
);
1447 for (size_t n
= m_Undos
.size(); 0 < n
; --n
)
1449 m_Undos
.at(n
-1)->UndoImpl(rContext
);
1452 table
.SetRowsToRepeat(m_nRepeatHeading
);
1455 m_pSaveTable
->RestoreAttr( pTableNd
->GetTable(), !bUndo
);
1456 m_pSaveTable
.reset( pOrig
);
1459 void SwUndoTableAutoFormat::UndoImpl(::sw::UndoRedoContext
& rContext
)
1461 UndoRedo(true, rContext
);
1464 void SwUndoTableAutoFormat::RedoImpl(::sw::UndoRedoContext
& rContext
)
1466 UndoRedo(false, rContext
);
1469 SwUndoTableNdsChg::SwUndoTableNdsChg( SwUndoId nAction
,
1470 const SwSelBoxes
& rBoxes
,
1471 const SwTableNode
& rTableNd
,
1472 tools::Long nMn
, tools::Long nMx
,
1473 sal_uInt16 nCnt
, bool bFlg
, bool bSmHght
)
1474 : SwUndo( nAction
, &rTableNd
.GetDoc() ),
1475 m_nMin( nMn
), m_nMax( nMx
),
1476 m_nSttNode( rTableNd
.GetIndex() ),
1479 m_bSameHeight( bSmHght
)
1481 const SwTable
& rTable
= rTableNd
.GetTable();
1482 m_pSaveTable
.reset( new SaveTable( rTable
) );
1484 // and remember selection
1485 ReNewBoxes( rBoxes
);
1488 void SwUndoTableNdsChg::ReNewBoxes( const SwSelBoxes
& rBoxes
)
1490 if (rBoxes
.size() != m_Boxes
.size())
1493 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
1495 m_Boxes
.insert( rBoxes
[n
]->GetSttIdx() );
1500 SwUndoTableNdsChg::~SwUndoTableNdsChg()
1504 void SwUndoTableNdsChg::SaveNewBoxes( const SwTableNode
& rTableNd
,
1505 const SwTableSortBoxes
& rOld
)
1507 const SwTable
& rTable
= rTableNd
.GetTable();
1508 const SwTableSortBoxes
& rTableBoxes
= rTable
.GetTabSortBoxes();
1510 OSL_ENSURE( ! IsDelBox(), "wrong Action" );
1511 m_xNewSttNds
.emplace();
1514 for (size_t n
= 0; n
< rOld
.size(); ++i
)
1516 if( rOld
[ n
] == rTableBoxes
[ i
] )
1519 // new box: insert sorted
1520 m_xNewSttNds
->insert( BoxMove(rTableBoxes
[ i
]->GetSttIdx()) );
1523 for( ; i
< rTableBoxes
.size(); ++i
)
1524 // new box: insert sorted
1525 m_xNewSttNds
->insert( BoxMove(rTableBoxes
[ i
]->GetSttIdx()) );
1528 static SwTableLine
* lcl_FindTableLine( const SwTable
& rTable
,
1529 const SwTableBox
& rBox
)
1531 SwTableLine
* pRet
= nullptr;
1532 // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
1533 const SwTableLines
&rTableLines
= ( rBox
.GetUpper()->GetUpper() != nullptr ) ?
1534 rBox
.GetUpper()->GetUpper()->GetTabLines()
1535 : rTable
.GetTabLines();
1536 const SwTableLine
* pLine
= rBox
.GetUpper();
1537 sal_uInt16 nLineNo
= rTableLines
.GetPos( pLine
);
1538 pRet
= rTableLines
[nLineNo
- 1];
1543 static const SwTableLines
& lcl_FindParentLines( const SwTable
& rTable
,
1544 const SwTableBox
& rBox
)
1546 const SwTableLines
& rRet
=
1547 ( rBox
.GetUpper()->GetUpper() != nullptr ) ?
1548 rBox
.GetUpper()->GetUpper()->GetTabLines() :
1549 rTable
.GetTabLines();
1554 void SwUndoTableNdsChg::SaveNewBoxes( const SwTableNode
& rTableNd
,
1555 const SwTableSortBoxes
& rOld
,
1556 const SwSelBoxes
& rBoxes
,
1557 const std::vector
<SwNodeOffset
> &rNodeCnts
)
1559 const SwTable
& rTable
= rTableNd
.GetTable();
1560 const SwTableSortBoxes
& rTableBoxes
= rTable
.GetTabSortBoxes();
1562 OSL_ENSURE( ! IsDelBox(), "wrong Action" );
1563 m_xNewSttNds
.emplace();
1565 OSL_ENSURE( rTable
.IsNewModel() || rOld
.size() + m_nCount
* rBoxes
.size() == rTableBoxes
.size(),
1566 "unexpected boxes" );
1567 OSL_ENSURE( rOld
.size() <= rTableBoxes
.size(), "more unexpected boxes" );
1568 for (size_t n
= 0, i
= 0; i
< rTableBoxes
.size(); ++i
)
1570 if( ( n
< rOld
.size() ) &&
1571 ( rOld
[ n
] == rTableBoxes
[ i
] ) )
1573 // box already known? Then nothing to be done.
1578 // new box found: insert (obey sort order)
1579 const SwTableBox
* pBox
= rTableBoxes
[ i
];
1581 // find the source box. It must be one in rBoxes.
1582 // We found the right one if it's in the same column as pBox.
1583 // No, if more than one selected cell in the same column has been split,
1584 // we have to look for the nearest one (i65201)!
1585 const SwTableBox
* pSourceBox
= nullptr;
1586 const SwTableBox
* pCheckBox
= nullptr;
1587 const SwTableLine
* pBoxLine
= pBox
->GetUpper();
1588 sal_uInt16 nLineDiff
= lcl_FindParentLines(rTable
,*pBox
).GetPos(pBoxLine
);
1589 sal_uInt16 nLineNo
= 0;
1590 for (size_t j
= 0; j
< rBoxes
.size(); ++j
)
1592 pCheckBox
= rBoxes
[j
];
1593 if( pCheckBox
->GetUpper()->GetUpper() == pBox
->GetUpper()->GetUpper() )
1595 const SwTableLine
* pCheckLine
= pCheckBox
->GetUpper();
1596 sal_uInt16 nCheckLine
= lcl_FindParentLines( rTable
, *pCheckBox
).
1597 GetPos( pCheckLine
);
1598 if( ( !pSourceBox
|| nCheckLine
> nLineNo
) && nCheckLine
< nLineDiff
)
1600 nLineNo
= nCheckLine
;
1601 pSourceBox
= pCheckBox
;
1606 // find the line number difference
1607 // (to help determine bNodesMoved flag below)
1608 nLineDiff
= nLineDiff
- nLineNo
;
1609 OSL_ENSURE( pSourceBox
, "Split source box not found!" );
1610 // find out how many nodes the source box used to have
1611 // (to help determine bNodesMoved flag below)
1613 while( rBoxes
[ nNdsPos
] != pSourceBox
)
1615 SwNodeOffset nNodes
= rNodeCnts
[ nNdsPos
];
1617 // When a new table cell is created, it either gets a new
1618 // node, or it gets node(s) from elsewhere. The undo must
1619 // know, of course, and thus we must determine here just
1620 // where pBox's nodes are from:
1621 // If 1) the source box has lost nodes, and
1622 // 2) we're in the node range that got nodes
1623 // then pBox received nodes from elsewhere.
1624 // If bNodesMoved is set for pBox the undo must move the
1625 // boxes back, otherwise it must delete them.
1626 bool bNodesMoved
= pSourceBox
&&
1627 ( nNodes
!= ( pSourceBox
->GetSttNd()->EndOfSectionIndex() -
1628 pSourceBox
->GetSttIdx() ) )
1629 && ( nNodes
- 1 > SwNodeOffset(nLineDiff
) );
1630 m_xNewSttNds
->insert( BoxMove(pBox
->GetSttIdx(), bNodesMoved
) );
1635 void SwUndoTableNdsChg::SaveSection( SwStartNode
* pSttNd
)
1637 OSL_ENSURE( IsDelBox(), "wrong Action" );
1638 if (m_pDelSects
== nullptr)
1639 m_pDelSects
.reset(new SwUndoSaveSections
);
1641 SwTableNode
* pTableNd
= pSttNd
->FindTableNode();
1642 std::unique_ptr
<SwUndoSaveSection
, o3tl::default_delete
<SwUndoSaveSection
>> pSave(new SwUndoSaveSection
);
1643 pSave
->SaveSection( SwNodeIndex( *pSttNd
));
1645 m_pDelSects
->push_back(std::move(pSave
));
1646 m_nSttNode
= pTableNd
->GetIndex();
1649 void SwUndoTableNdsChg::UndoImpl(::sw::UndoRedoContext
& rContext
)
1651 SwDoc
& rDoc
= rContext
.GetDoc();
1652 SwNodeIndex
aIdx( rDoc
.GetNodes(), m_nSttNode
);
1654 SwTableNode
*const pTableNd
= aIdx
.GetNode().GetTableNode();
1655 OSL_ENSURE( pTableNd
, "no TableNode" );
1656 pTableNd
->GetTable().SwitchFormulasToInternalRepresentation();
1658 CHECK_TABLE( pTableNd
->GetTable() )
1660 FndBox_
aTmpBox( nullptr, nullptr );
1661 // ? TL_CHART2: notification or locking of controller required ?
1663 SwChartDataProvider
*pPCD
= rDoc
.getIDocumentChartDataProviderAccess().GetChartDataProvider();
1664 SwSelBoxes aDelBoxes
;
1665 std::vector
< std::pair
<SwTableBox
*, SwNodeOffset
> > aDelNodes
;
1668 // Trick: add missing boxes in any line, they will be connected
1669 // correctly when calling CreateNew
1670 SwTableBox
* pCpyBox
= pTableNd
->GetTable().GetTabSortBoxes()[0];
1671 SwTableBoxes
& rLnBoxes
= pCpyBox
->GetUpper()->GetTabBoxes();
1674 for (size_t n
= m_pDelSects
->size(); n
; )
1676 SwUndoSaveSection
*const pSave
= (*m_pDelSects
)[ --n
].get();
1677 pSave
->RestoreSection( &rDoc
, &aIdx
, SwTableBoxStartNode
);
1678 if( pSave
->GetHistory() )
1679 pSave
->GetHistory()->Rollback( &rDoc
);
1680 SwTableBox
* pBox
= new SwTableBox( static_cast<SwTableBoxFormat
*>(pCpyBox
->GetFrameFormat()), aIdx
,
1681 pCpyBox
->GetUpper() );
1682 rLnBoxes
.push_back( pBox
);
1684 m_pDelSects
->clear();
1686 else if( !m_xNewSttNds
->empty() )
1688 // Then the nodes have be moved and not deleted!
1689 // But for that we need a temp array.
1690 std::vector
<BoxMove
> aTmp( m_xNewSttNds
->begin(), m_xNewSttNds
->end() );
1693 for (size_t n
= aTmp
.size(); n
> 0 ; )
1696 // delete box from table structure
1697 SwNodeOffset nIdx
= aTmp
[n
].index
;
1698 SwTableBox
* pBox
= pTableNd
->GetTable().GetTableBox( nIdx
);
1699 OSL_ENSURE( pBox
, "Where is my TableBox?" );
1701 // TL_CHART2: notify chart about box to be removed
1703 pPCD
->DeleteBox( &pTableNd
->GetTable(), *pBox
);
1705 // insert _before_ deleting the section - otherwise the box
1706 // has no start node so all boxes sort equal in SwSelBoxes
1707 aDelBoxes
.insert(pBox
);
1709 if( aTmp
[n
].hasMoved
)
1711 SwNodeRange
aRg( *pBox
->GetSttNd(), SwNodeOffset(1),
1712 *pBox
->GetSttNd()->EndOfSectionNode() );
1714 SwTableLine
* pLine
= lcl_FindTableLine( pTableNd
->GetTable(), *pBox
);
1715 SwNodeIndex
aInsPos( *(pLine
->GetTabBoxes()[0]->GetSttNd()), 2 );
1717 // adjust all StartNode indices
1719 SwNodeOffset nSttIdx
= aInsPos
.GetIndex() - 2,
1720 nNdCnt
= aRg
.aEnd
.GetIndex() - aRg
.aStart
.GetIndex();
1721 while( i
&& aTmp
[ --i
].index
> nSttIdx
)
1722 aTmp
[ i
].index
+= nNdCnt
;
1727 rDoc
.GetNodes().MoveNodes( aRg
, rDoc
.GetNodes(), aInsPos
.GetNode(), false );
1731 aDelNodes
.emplace_back(pBox
, nIdx
);
1737 // Remove nodes from nodes array (backwards!)
1738 std::set
<BoxMove
>::reverse_iterator it
;
1739 for( it
= m_xNewSttNds
->rbegin(); it
!= m_xNewSttNds
->rend(); ++it
)
1741 SwNodeOffset nIdx
= (*it
).index
;
1742 SwTableBox
* pBox
= pTableNd
->GetTable().GetTableBox( nIdx
);
1743 OSL_ENSURE( pBox
, "Where's my table box?" );
1744 // TL_CHART2: notify chart about box to be removed
1746 pPCD
->DeleteBox( &pTableNd
->GetTable(), *pBox
);
1747 aDelBoxes
.insert(pBox
);
1748 aDelNodes
.emplace_back(pBox
, nIdx
);
1752 // fdo#57197: before deleting the SwTableBoxes, delete the SwTabFrames
1753 aTmpBox
.SetTableLines(aDelBoxes
, pTableNd
->GetTable());
1754 aTmpBox
.DelFrames(pTableNd
->GetTable());
1756 // do this _after_ deleting Frames because disposing SwAccessible requires
1757 // connection to the nodes, see SwAccessibleChild::IsAccessible()
1758 for (const std::pair
<SwTableBox
*, SwNodeOffset
> & rDelNode
: aDelNodes
)
1760 // first disconnect box from node, otherwise ~SwTableBox would
1761 // access pBox->pSttNd, deleted by DeleteSection
1762 rDelNode
.first
->RemoveFromTable();
1763 rDoc
.getIDocumentContentOperations().DeleteSection(rDoc
.GetNodes()[ rDelNode
.second
]);
1766 // Remove boxes from table structure
1767 for( size_t n
= 0; n
< aDelBoxes
.size(); ++n
)
1769 SwTableBox
* pCurrBox
= aDelBoxes
[n
];
1770 SwTableBoxes
* pTBoxes
= &pCurrBox
->GetUpper()->GetTabBoxes();
1771 pTBoxes
->erase( std::find( pTBoxes
->begin(), pTBoxes
->end(), pCurrBox
) );
1775 m_pSaveTable
->CreateNew( pTableNd
->GetTable(), true, false );
1777 // TL_CHART2: need to inform chart of probably changed cell names
1778 rDoc
.UpdateCharts( pTableNd
->GetTable().GetFrameFormat()->GetName() );
1779 if (SwFEShell
* pFEShell
= rDoc
.GetDocShell()->GetFEShell())
1780 pFEShell
->UpdateTableStyleFormatting(pTableNd
);
1782 m_nSttNode
= pTableNd
->GetIndex();
1783 ClearFEShellTabCols(rDoc
, nullptr);
1784 CHECK_TABLE( pTableNd
->GetTable() )
1787 void SwUndoTableNdsChg::RedoImpl(::sw::UndoRedoContext
& rContext
)
1789 SwDoc
& rDoc
= rContext
.GetDoc();
1791 SwTableNode
* pTableNd
= rDoc
.GetNodes()[ m_nSttNode
]->GetTableNode();
1792 OSL_ENSURE( pTableNd
, "no TableNode" );
1793 CHECK_TABLE( pTableNd
->GetTable() )
1795 SwSelBoxes aSelBoxes
;
1796 for (const auto& rBox
: m_Boxes
)
1798 SwTableBox
* pBox
= pTableNd
->GetTable().GetTableBox( rBox
);
1799 aSelBoxes
.insert( pBox
);
1802 // create SelBoxes and call InsertCell/-Row/SplitTable
1805 case SwUndoId::TABLE_INSCOL
:
1806 rDoc
.InsertCol( aSelBoxes
, m_nCount
, m_bFlag
);
1809 case SwUndoId::TABLE_INSROW
:
1810 rDoc
.InsertRow( aSelBoxes
, m_nCount
, m_bFlag
);
1813 case SwUndoId::TABLE_SPLIT
:
1814 rDoc
.SplitTable( aSelBoxes
, m_bFlag
, m_nCount
, m_bSameHeight
);
1816 case SwUndoId::TABLE_DELBOX
:
1817 case SwUndoId::ROW_DELETE
:
1818 case SwUndoId::COL_DELETE
:
1820 SwTable
&rTable
= pTableNd
->GetTable();
1821 rTable
.SwitchFormulasToInternalRepresentation();
1822 if( m_nMax
> m_nMin
&& rTable
.IsNewModel() )
1823 rTable
.PrepareDeleteCol( m_nMin
, m_nMax
);
1824 rTable
.DeleteSel( &rDoc
, aSelBoxes
, nullptr, this, true, true );
1825 m_nSttNode
= pTableNd
->GetIndex();
1831 ClearFEShellTabCols(rDoc
, nullptr);
1832 CHECK_TABLE( pTableNd
->GetTable() )
1835 SwUndoTableMerge::SwUndoTableMerge( const SwPaM
& rTableSel
)
1836 : SwUndo( SwUndoId::TABLE_MERGE
, &rTableSel
.GetDoc() ), SwUndRng( rTableSel
)
1838 const SwTableNode
* pTableNd
= rTableSel
.GetPointNode().FindTableNode();
1839 OSL_ENSURE( pTableNd
, "Where is the TableNode?" );
1840 m_pSaveTable
.reset( new SaveTable( pTableNd
->GetTable() ) );
1841 m_nTableNode
= pTableNd
->GetIndex();
1844 SwUndoTableMerge::~SwUndoTableMerge()
1846 m_pSaveTable
.reset();
1851 void SwUndoTableMerge::UndoImpl(::sw::UndoRedoContext
& rContext
)
1853 SwDoc
& rDoc
= rContext
.GetDoc();
1854 SwNodeIndex
aIdx( rDoc
.GetNodes(), m_nTableNode
);
1856 SwTableNode
*const pTableNd
= aIdx
.GetNode().GetTableNode();
1857 OSL_ENSURE( pTableNd
, "no TableNode" );
1859 pTableNd
->GetTable().SwitchFormulasToInternalRepresentation();
1861 // ? TL_CHART2: notification or locking of controller required ?
1863 // 1. restore deleted boxes:
1864 // Trick: add missing boxes in any line, they will be connected
1865 // correctly when calling CreateNew
1866 SwTableBox
*pBox
, *pCpyBox
= pTableNd
->GetTable().GetTabSortBoxes()[0];
1867 SwTableBoxes
& rLnBoxes
= pCpyBox
->GetUpper()->GetTabBoxes();
1869 CHECKTABLE(pTableNd
->GetTable())
1871 SwSelBoxes aSelBoxes
;
1872 SwTextFormatColl
* pColl
= rDoc
.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD
);
1874 for (const auto& rBox
: m_Boxes
)
1877 SwStartNode
* pSttNd
= rDoc
.GetNodes().MakeTextSection( aIdx
.GetNode(),
1878 SwTableBoxStartNode
, pColl
);
1879 pBox
= new SwTableBox( static_cast<SwTableBoxFormat
*>(pCpyBox
->GetFrameFormat()), *pSttNd
,
1880 pCpyBox
->GetUpper() );
1881 rLnBoxes
.push_back( pBox
);
1883 aSelBoxes
.insert( pBox
);
1886 CHECKTABLE(pTableNd
->GetTable())
1888 SwChartDataProvider
*pPCD
= rDoc
.getIDocumentChartDataProviderAccess().GetChartDataProvider();
1889 // 2. deleted the inserted boxes
1890 // delete nodes (from last to first)
1891 for( size_t n
= m_aNewStartNodes
.size(); n
; )
1893 // remove box from table structure
1894 SwNodeOffset nIdx
= m_aNewStartNodes
[ --n
];
1898 nIdx
= m_aNewStartNodes
[ --n
];
1899 pBox
= pTableNd
->GetTable().GetTableBox( nIdx
);
1900 OSL_ENSURE( pBox
, "Where is my TableBox?" );
1902 if( !m_pSaveTable
->IsNewModel() )
1903 rDoc
.GetNodes().MakeTextNode(
1904 const_cast<SwEndNode
&>(*pBox
->GetSttNd()->EndOfSectionNode()), pColl
);
1906 // this was the separator -> restore moved ones
1907 for (size_t i
= m_vMoves
.size(); i
; )
1909 SwTextNode
* pTextNd
= nullptr;
1910 sal_Int32 nDelPos
= 0;
1911 SwUndoMove
*const pUndo
= m_vMoves
[ --i
].get();
1912 if( !pUndo
->IsMoveRange() )
1914 pTextNd
= rDoc
.GetNodes()[ pUndo
->GetDestSttNode() ]->GetTextNode();
1915 nDelPos
= pUndo
->GetDestSttContent() - 1;
1917 pUndo
->UndoImpl(rContext
);
1918 if( pUndo
->IsMoveRange() )
1920 // delete the unnecessary node
1921 aIdx
= pUndo
->GetEndNode();
1922 SwContentNode
*pCNd
= aIdx
.GetNode().GetContentNode();
1925 SwNodeIndex
aTmp( aIdx
, -1 );
1926 SwContentNode
*pMove
= aTmp
.GetNode().GetContentNode();
1928 pCNd
->MoveTo( *pMove
);
1930 rDoc
.GetNodes().Delete( aIdx
);
1934 // also delete not needed attributes
1935 SwContentIndex
aTmpIdx( pTextNd
, nDelPos
);
1936 if( pTextNd
->GetpSwpHints() && pTextNd
->GetpSwpHints()->Count() )
1937 pTextNd
->RstTextAttr( nDelPos
, pTextNd
->GetText().getLength() - nDelPos
+ 1 );
1939 pTextNd
->EraseText( aTmpIdx
, 1 );
1942 nIdx
= pBox
->GetSttIdx();
1945 pBox
= pTableNd
->GetTable().GetTableBox( nIdx
);
1947 if( !m_pSaveTable
->IsNewModel() )
1949 // TL_CHART2: notify chart about box to be removed
1951 pPCD
->DeleteBox( &pTableNd
->GetTable(), *pBox
);
1953 SwTableBoxes
* pTBoxes
= &pBox
->GetUpper()->GetTabBoxes();
1954 pTBoxes
->erase( std::find(pTBoxes
->begin(), pTBoxes
->end(), pBox
) );
1956 // delete indices from section
1958 SwNodeIndex
aTmpIdx( *pBox
->GetSttNd() );
1959 SwDoc::CorrAbs( SwNodeIndex( aTmpIdx
, 1 ),
1960 SwNodeIndex( *aTmpIdx
.GetNode().EndOfSectionNode() ),
1961 SwPosition( aTmpIdx
, nullptr, 0 ), true );
1965 rDoc
.getIDocumentContentOperations().DeleteSection( rDoc
.GetNodes()[ nIdx
] );
1968 CHECKTABLE(pTableNd
->GetTable())
1970 m_pSaveTable
->CreateNew( pTableNd
->GetTable(), true, false );
1972 // TL_CHART2: need to inform chart of probably changed cell names
1973 rDoc
.UpdateCharts( pTableNd
->GetTable().GetFrameFormat()->GetName() );
1977 m_pHistory
->TmpRollback( &rDoc
, 0 );
1978 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
1980 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
1982 pPam
->GetPoint()->Assign(m_nSttNode
, m_nSttContent
);
1986 CHECKTABLE(pTableNd
->GetTable())
1987 ClearFEShellTabCols(rDoc
, nullptr);
1990 void SwUndoTableMerge::RedoImpl(::sw::UndoRedoContext
& rContext
)
1992 SwDoc
& rDoc
= rContext
.GetDoc();
1993 SwPaM
& rPam( AddUndoRedoPaM(rContext
) );
1994 rDoc
.MergeTable(rPam
);
1997 void SwUndoTableMerge::MoveBoxContent( SwDoc
& rDoc
, SwNodeRange
& rRg
, SwNode
& rPos
)
1999 SwNodeIndex
aTmp( rRg
.aStart
, -1 ), aTmp2( rPos
, -1 );
2000 std::unique_ptr
<SwUndoMove
> pUndo(new SwUndoMove( rDoc
, rRg
, rPos
));
2001 ::sw::UndoGuard
const undoGuard(rDoc
.GetIDocumentUndoRedo());
2002 rDoc
.getIDocumentContentOperations().MoveNodeRange( rRg
, rPos
, m_pSaveTable
->IsNewModel() ?
2003 SwMoveFlags::NO_DELFRMS
:
2004 SwMoveFlags::DEFAULT
);
2007 pUndo
->SetDestRange( aTmp2
.GetNode(), rPos
, aTmp
);
2009 m_vMoves
.push_back(std::move(pUndo
));
2012 void SwUndoTableMerge::SetSelBoxes( const SwSelBoxes
& rBoxes
)
2014 // memorize selection
2015 for (size_t n
= 0; n
< rBoxes
.size(); ++n
)
2017 m_Boxes
.insert(rBoxes
[n
]->GetSttIdx());
2020 // as separator for inserts of new boxes after shifting
2021 m_aNewStartNodes
.push_back( SwNodeOffset(0) );
2023 // The new table model does not delete overlapped cells (by row span),
2024 // so the rBoxes array might be empty even some cells have been merged.
2025 if( !rBoxes
.empty() )
2026 m_nTableNode
= rBoxes
[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
2029 void SwUndoTableMerge::SaveCollection( const SwTableBox
& rBox
)
2032 m_pHistory
.reset(new SwHistory
);
2034 SwNodeIndex
aIdx( *rBox
.GetSttNd(), 1 );
2035 SwContentNode
* pCNd
= aIdx
.GetNode().GetContentNode();
2037 pCNd
= aIdx
.GetNodes().GoNext( &aIdx
);
2039 m_pHistory
->Add( pCNd
->GetFormatColl(), aIdx
.GetIndex(), pCNd
->GetNodeType());
2040 if( pCNd
->HasSwAttrSet() )
2041 m_pHistory
->CopyFormatAttr( *pCNd
->GetpSwAttrSet(), aIdx
.GetIndex() );
2044 SwUndoTableNumFormat::SwUndoTableNumFormat( const SwTableBox
& rBox
,
2045 const SfxItemSet
* pNewSet
)
2046 : SwUndo(SwUndoId::TBLNUMFMT
, rBox
.GetFrameFormat()->GetDoc())
2047 , m_nFormatIdx(getSwDefaultTextFormat())
2048 , m_nNewFormatIdx(0)
2051 , m_bNewFormat(false)
2052 , m_bNewFormula(false)
2053 , m_bNewValue(false)
2055 m_nNode
= rBox
.GetSttIdx();
2057 m_nNodePos
= rBox
.IsValidNumTextNd( nullptr == pNewSet
);
2058 SwDoc
* pDoc
= rBox
.GetFrameFormat()->GetDoc();
2060 if( NODE_OFFSET_MAX
!= m_nNodePos
)
2062 SwTextNode
* pTNd
= pDoc
->GetNodes()[ m_nNodePos
]->GetTextNode();
2064 m_pHistory
.reset(new SwHistory
);
2065 SwRegHistory
aRHst( *rBox
.GetSttNd(), m_pHistory
.get() );
2066 // always save all text attributes because of possibly overlapping
2068 m_pHistory
->CopyAttr( pTNd
->GetpSwpHints(), m_nNodePos
, 0,
2069 pTNd
->GetText().getLength(), true );
2071 if( pTNd
->HasSwAttrSet() )
2072 m_pHistory
->CopyFormatAttr( *pTNd
->GetpSwAttrSet(), m_nNodePos
);
2074 m_aStr
= pTNd
->GetText();
2075 if( pTNd
->GetpSwpHints() )
2076 pTNd
->GetpSwpHints()->DeRegister();
2079 m_pBoxSet
.reset( new SfxItemSet( pDoc
->GetAttrPool(), aTableBoxSetRange
) );
2080 m_pBoxSet
->Put( rBox
.GetFrameFormat()->GetAttrSet() );
2084 if( const SwTableBoxNumFormat
* pItem
= pNewSet
->GetItemIfSet( RES_BOXATR_FORMAT
,
2087 m_bNewFormat
= true;
2088 m_nNewFormatIdx
= pItem
->GetValue();
2090 if( const SwTableBoxFormula
* pItem
= pNewSet
->GetItemIfSet( RES_BOXATR_FORMULA
,
2093 m_bNewFormula
= true;
2094 m_aNewFormula
= pItem
->GetFormula();
2096 if( const SwTableBoxValue
* pItem
= pNewSet
->GetItemIfSet( RES_BOXATR_VALUE
,
2100 m_fNewNum
= pItem
->GetValue();
2104 // is a history needed at all?
2105 if (m_pHistory
&& !m_pHistory
->Count())
2111 SwUndoTableNumFormat::~SwUndoTableNumFormat()
2117 void SwUndoTableNumFormat::UndoImpl(::sw::UndoRedoContext
& rContext
)
2119 OSL_ENSURE( m_pBoxSet
, "Where's the stored item set?" );
2121 SwDoc
& rDoc
= rContext
.GetDoc();
2122 SwStartNode
* pSttNd
= rDoc
.GetNodes()[ m_nNode
]->
2123 FindSttNodeByType( SwTableBoxStartNode
);
2124 OSL_ENSURE( pSttNd
, "without StartNode no TableBox" );
2125 SwTableBox
* pBox
= pSttNd
->FindTableNode()->GetTable().GetTableBox(
2126 pSttNd
->GetIndex() );
2127 OSL_ENSURE( pBox
, "found no TableBox" );
2129 SwTableBoxFormat
* pFormat
= rDoc
.MakeTableBoxFormat();
2130 pFormat
->SetFormatAttr( *m_pBoxSet
);
2131 pBox
->ChgFrameFormat( pFormat
);
2133 if( NODE_OFFSET_MAX
== m_nNodePos
)
2136 SwTextNode
* pTextNd
= rDoc
.GetNodes()[ m_nNodePos
]->GetTextNode();
2137 // If more than one node was deleted then all "node" attributes were also
2139 if( pTextNd
->HasSwAttrSet() )
2140 pTextNd
->ResetAllAttr();
2142 if( pTextNd
->GetpSwpHints() && !m_aStr
.isEmpty() )
2143 pTextNd
->ClearSwpHintsArr( true );
2145 // ChgTextToNum(..) only acts when the strings are different. We need to do
2147 if( pTextNd
->GetText() != m_aStr
)
2149 rDoc
.getIDocumentRedlineAccess().DeleteRedline( *( pBox
->GetSttNd() ), false, RedlineType::Any
);
2151 SwContentIndex
aIdx( pTextNd
, 0 );
2152 if( !m_aStr
.isEmpty() )
2154 pTextNd
->EraseText( aIdx
);
2155 pTextNd
->InsertText( m_aStr
, aIdx
,
2156 SwInsertFlags::NOHINTEXPAND
);
2162 sal_uInt16 nTmpEnd
= m_pHistory
->GetTmpEnd();
2163 m_pHistory
->TmpRollback( &rDoc
, 0 );
2164 m_pHistory
->SetTmpEnd( nTmpEnd
);
2167 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
2169 pPam
->GetPoint()->Assign( m_nNode
+ 1 );
2174 /** switch the RedlineFlags on the given document, using
2175 * SetRedlineFlags_intern. This class set the mode in the constructor,
2176 * and changes it back in the destructor, i.e. it uses the
2177 * initialization-is-resource-acquisition idiom.
2179 class RedlineFlagsInternGuard
2182 RedlineFlags meOldRedlineFlags
;
2185 RedlineFlagsInternGuard(
2186 SwDoc
& rDoc
, // change mode of this document
2187 RedlineFlags eNewRedlineFlags
, // new redline mode
2188 RedlineFlags eRedlineFlagsMask
/*change only bits set in this mask*/);
2190 ~RedlineFlagsInternGuard();
2195 RedlineFlagsInternGuard::RedlineFlagsInternGuard(
2197 RedlineFlags eNewRedlineFlags
,
2198 RedlineFlags eRedlineFlagsMask
)
2200 meOldRedlineFlags( rDoc
.getIDocumentRedlineAccess().GetRedlineFlags() )
2202 mrDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( ( meOldRedlineFlags
& ~eRedlineFlagsMask
) |
2203 ( eNewRedlineFlags
& eRedlineFlagsMask
) );
2206 RedlineFlagsInternGuard::~RedlineFlagsInternGuard()
2208 mrDoc
.getIDocumentRedlineAccess().SetRedlineFlags_intern( meOldRedlineFlags
);
2211 void SwUndoTableNumFormat::RedoImpl(::sw::UndoRedoContext
& rContext
)
2213 // Could the box be changed?
2217 SwDoc
& rDoc
= rContext
.GetDoc();
2218 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
2221 pPam
->GetPoint()->Assign( m_nNode
);
2223 SwNode
* pNd
= & pPam
->GetPoint()->GetNode();
2224 SwStartNode
* pSttNd
= pNd
->FindSttNodeByType( SwTableBoxStartNode
);
2225 assert(pSttNd
&& "without StartNode no TableBox");
2226 SwTableBox
* pBox
= pSttNd
->FindTableNode()->GetTable().GetTableBox(
2227 pSttNd
->GetIndex() );
2228 OSL_ENSURE( pBox
, "found no TableBox" );
2230 SwFrameFormat
* pBoxFormat
= pBox
->ClaimFrameFormat();
2231 if( m_bNewFormat
|| m_bNewFormula
|| m_bNewValue
)
2233 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aBoxSet( rDoc
.GetAttrPool() );
2235 // Resetting attributes is not enough. In addition, take care that the
2236 // text will be also formatted correctly.
2237 pBoxFormat
->LockModify();
2240 aBoxSet
.Put( SwTableBoxFormula( m_aNewFormula
));
2242 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMULA
);
2244 aBoxSet
.Put( SwTableBoxNumFormat( m_nNewFormatIdx
));
2246 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMAT
);
2248 aBoxSet
.Put( SwTableBoxValue( m_fNewNum
));
2250 pBoxFormat
->ResetFormatAttr( RES_BOXATR_VALUE
);
2251 pBoxFormat
->UnlockModify();
2253 // dvo: When redlining is (was) enabled, setting the attribute
2254 // will also change the cell content. To allow this, the
2255 // RedlineFlags::Ignore flag must be removed during Redo. #108450#
2256 RedlineFlagsInternGuard
aGuard( rDoc
, RedlineFlags::NONE
, RedlineFlags::Ignore
);
2257 pBoxFormat
->SetFormatAttr( aBoxSet
);
2259 else if( getSwDefaultTextFormat() != m_nFormatIdx
)
2261 SfxItemSetFixed
<RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aBoxSet( rDoc
.GetAttrPool() );
2263 aBoxSet
.Put( SwTableBoxNumFormat( m_nFormatIdx
));
2264 aBoxSet
.Put( SwTableBoxValue( m_fNum
));
2266 // Resetting attributes is not enough. In addition, take care that the
2267 // text will be also formatted correctly.
2268 pBoxFormat
->LockModify();
2269 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMULA
);
2270 pBoxFormat
->UnlockModify();
2272 // dvo: When redlining is (was) enabled, setting the attribute
2273 // will also change the cell content. To allow this, the
2274 // RedlineFlags::Ignore flag must be removed during Redo. #108450#
2275 RedlineFlagsInternGuard
aGuard( rDoc
, RedlineFlags::NONE
, RedlineFlags::Ignore
);
2276 pBoxFormat
->SetFormatAttr( aBoxSet
);
2282 // Resetting attributes is not enough. In addition, take care that the
2283 // text will be also formatted correctly.
2284 pBoxFormat
->SetFormatAttr( *GetDfltAttr( RES_BOXATR_FORMAT
));
2286 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
2291 // No matter what was set, an update of the table is always a good idea
2292 rDoc
.getIDocumentFieldsAccess().UpdateTableFields(&pSttNd
->FindTableNode()->GetTable());
2295 if( !pNd
->IsContentNode() )
2296 pNd
= rDoc
.GetNodes().GoNext( pPam
->GetPoint() );
2299 void SwUndoTableNumFormat::SetBox( const SwTableBox
& rBox
)
2301 m_nNode
= rBox
.GetSttIdx();
2304 UndoTableCpyTable_Entry::UndoTableCpyTable_Entry( const SwTableBox
& rBox
)
2305 : nBoxIdx( rBox
.GetSttIdx() ), nOffset( 0 ),
2310 void UndoTableCpyTable_Entry::dumpAsXml(xmlTextWriterPtr pWriter
) const
2312 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("UndoTableCpyTable_Entry"));
2314 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("nBoxIdx"));
2315 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("value"),
2316 BAD_CAST(OString::number(sal_Int32(nBoxIdx
)).getStr()));
2317 (void)xmlTextWriterEndElement(pWriter
);
2319 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("nOffset"));
2320 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("value"),
2321 BAD_CAST(OString::number(sal_Int32(nOffset
)).getStr()));
2322 (void)xmlTextWriterEndElement(pWriter
);
2326 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("pBoxNumAttr"));
2327 pBoxNumAttr
->dumpAsXml(pWriter
);
2328 (void)xmlTextWriterEndElement(pWriter
);
2333 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("pUndo"));
2334 pUndo
->dumpAsXml(pWriter
);
2335 (void)xmlTextWriterEndElement(pWriter
);
2338 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("bJoin"));
2339 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("value"),
2340 BAD_CAST(OString::boolean(bJoin
).getStr()));
2341 (void)xmlTextWriterEndElement(pWriter
);
2343 (void)xmlTextWriterEndElement(pWriter
);
2346 SwUndoTableCpyTable::SwUndoTableCpyTable(const SwDoc
& rDoc
)
2347 : SwUndo( SwUndoId::TBLCPYTBL
, &rDoc
)
2351 SwUndoTableCpyTable::~SwUndoTableCpyTable()
2354 m_pInsRowUndo
.reset();
2357 void SwUndoTableCpyTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
2359 SwDoc
& rDoc
= rContext
.GetDoc();
2360 DEBUG_REDLINE( &rDoc
)
2362 SwTableNode
* pTableNd
= nullptr;
2363 for (size_t n
= m_vArr
.size(); n
; )
2365 UndoTableCpyTable_Entry
*const pEntry
= m_vArr
[ --n
].get();
2366 SwNodeOffset nSttPos
= pEntry
->nBoxIdx
+ pEntry
->nOffset
;
2367 SwStartNode
* pSNd
= rDoc
.GetNodes()[ nSttPos
]->StartOfSectionNode();
2369 pTableNd
= pSNd
->FindTableNode();
2371 SwTableBox
* pBox
= pTableNd
->GetTable().GetTableBox( nSttPos
);
2375 "SwUndoTableCpyTable::UndoImpl: invalid start node index for table box");
2379 SwTableBox
& rBox
= *pBox
;
2381 SwNodeIndex
aInsIdx( *rBox
.GetSttNd(), 1 );
2382 rDoc
.GetNodes().MakeTextNode( aInsIdx
.GetNode(), rDoc
.GetDfltTextFormatColl() );
2384 // b62341295: Redline for copying tables
2385 const SwNode
*pEndNode
= rBox
.GetSttNd()->EndOfSectionNode();
2386 SwPaM
aPam( aInsIdx
.GetNode(), *pEndNode
);
2387 std::unique_ptr
<SwUndoDelete
> pUndo
;
2389 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
2391 bool bDeleteCompleteParagraph
= false;
2392 bool bShiftPam
= false;
2393 // There are a couple of different situations to consider during redlining
2396 SwUndoDelete
*const pUndoDelete
=
2397 dynamic_cast<SwUndoDelete
*>(pEntry
->pUndo
.get());
2398 SwUndoRedlineDelete
*const pUndoRedlineDelete
=
2399 dynamic_cast<SwUndoRedlineDelete
*>(pEntry
->pUndo
.get());
2400 assert(pUndoDelete
|| pUndoRedlineDelete
);
2401 if (pUndoRedlineDelete
)
2403 // The old content was not empty or he has been merged with the new content
2404 bDeleteCompleteParagraph
= !pEntry
->bJoin
; // bJoin is set when merged
2405 // Set aTmpIdx to the beginning of the old content
2406 SwNodeIndex
aTmpIdx( *pEndNode
,
2407 pUndoRedlineDelete
->NodeDiff()-1 );
2408 SwTextNode
*pText
= aTmpIdx
.GetNode().GetTextNode();
2411 aPam
.GetPoint()->Assign(*pText
,
2412 pUndoRedlineDelete
->ContentStart() );
2415 aPam
.GetPoint()->Assign( aTmpIdx
);
2417 else if (pUndoDelete
&& pUndoDelete
->IsDelFullPara())
2419 // When the old content was an empty paragraph, but could not be joined
2420 // with the new content (e.g. because of a section or table)
2421 // We "save" the aPam.Point, we go one step backwards (because later on the
2422 // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
2423 // for step forward later on.
2424 bDeleteCompleteParagraph
= true;
2426 aPam
.GetPoint()->Assign(*pEndNode
, SwNodeOffset(-1));
2429 rDoc
.getIDocumentRedlineAccess().DeleteRedline( aPam
, true, RedlineType::Any
);
2433 pEntry
->pUndo
->UndoImpl(rContext
);
2434 pEntry
->pUndo
.reset();
2438 // The aPam.Point is at the moment at the last position of the new content and has to be
2439 // moved to the first position of the old content for the SwUndoDelete operation
2440 aPam
.GetPoint()->Assign(aPam
.GetPoint()->GetNode(), SwNodeOffset(1));
2442 pUndo
= std::make_unique
<SwUndoDelete
>(aPam
, SwDeleteFlags::Default
, bDeleteCompleteParagraph
, true);
2446 pUndo
= std::make_unique
<SwUndoDelete
>(aPam
, SwDeleteFlags::Default
, true);
2449 pEntry
->pUndo
->UndoImpl(rContext
);
2450 pEntry
->pUndo
.reset();
2453 pEntry
->pUndo
= std::move(pUndo
);
2455 aInsIdx
= rBox
.GetSttIdx() + 1;
2456 rDoc
.GetNodes().Delete( aInsIdx
);
2459 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
2460 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
>
2461 aTmpSet(rDoc
.GetAttrPool());
2462 aTmpSet
.Put( rBox
.GetFrameFormat()->GetAttrSet() );
2463 if( aTmpSet
.Count() )
2465 SwFrameFormat
* pBoxFormat
= rBox
.ClaimFrameFormat();
2466 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
2467 pBoxFormat
->ResetFormatAttr( RES_VERT_ORIENT
);
2470 if( pEntry
->pBoxNumAttr
)
2472 rBox
.ClaimFrameFormat()->SetFormatAttr( *pEntry
->pBoxNumAttr
);
2473 pEntry
->pBoxNumAttr
.reset();
2476 if( aTmpSet
.Count() )
2478 pEntry
->pBoxNumAttr
= std::make_unique
<SfxItemSetFixed
<
2479 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
2480 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
>>(rDoc
.GetAttrPool());
2481 pEntry
->pBoxNumAttr
->Put( aTmpSet
);
2484 pEntry
->nOffset
= rBox
.GetSttIdx() - pEntry
->nBoxIdx
;
2489 m_pInsRowUndo
->UndoImpl(rContext
);
2491 DEBUG_REDLINE( &rDoc
)
2494 void SwUndoTableCpyTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
2496 SwDoc
& rDoc
= rContext
.GetDoc();
2497 DEBUG_REDLINE( &rDoc
)
2501 m_pInsRowUndo
->RedoImpl(rContext
);
2504 SwTableNode
* pTableNd
= nullptr;
2505 for (size_t n
= 0; n
< m_vArr
.size(); ++n
)
2507 UndoTableCpyTable_Entry
*const pEntry
= m_vArr
[ n
].get();
2508 SwNodeOffset nSttPos
= pEntry
->nBoxIdx
+ pEntry
->nOffset
;
2509 SwStartNode
* pSNd
= rDoc
.GetNodes()[ nSttPos
]->StartOfSectionNode();
2511 pTableNd
= pSNd
->FindTableNode();
2513 SwTableBox
& rBox
= *pTableNd
->GetTable().GetTableBox( nSttPos
);
2515 SwNodeIndex
aInsIdx( *rBox
.GetSttNd(), 1 );
2517 // b62341295: Redline for copying tables - Start.
2518 rDoc
.GetNodes().MakeTextNode( aInsIdx
.GetNode(), rDoc
.GetDfltTextFormatColl() );
2519 SwPaM
aPam( aInsIdx
.GetNode(), *rBox
.GetSttNd()->EndOfSectionNode());
2520 std::unique_ptr
<SwUndo
> pUndo(IDocumentRedlineAccess::IsRedlineOn(GetRedlineFlags())
2522 : std::make_unique
<SwUndoDelete
>(aPam
, SwDeleteFlags::Default
, true));
2525 pEntry
->pUndo
->UndoImpl(rContext
);
2526 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineFlags() ) )
2528 // PrepareRedline has to be called with the beginning of the old content
2529 // When new and old content has been joined, the rIter.pAktPam has been set
2530 // by the Undo operation to this point.
2531 // Otherwise aInsIdx has been moved during the Undo operation
2535 rContext
.GetCursorSupplier().GetCurrentShellCursor();
2536 pUndo
= PrepareRedline( &rDoc
, rBox
, *rLastPam
.GetPoint(),
2537 pEntry
->bJoin
, true );
2541 SwPosition
aTmpPos( aInsIdx
);
2542 pUndo
= PrepareRedline( &rDoc
, rBox
, aTmpPos
, pEntry
->bJoin
, true );
2545 pEntry
->pUndo
.reset();
2547 pEntry
->pUndo
= std::move(pUndo
);
2548 // b62341295: Redline for copying tables - End.
2550 aInsIdx
= rBox
.GetSttIdx() + 1;
2551 rDoc
.GetNodes().Delete( aInsIdx
);
2554 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
2555 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
> aTmpSet(rDoc
.GetAttrPool());
2556 aTmpSet
.Put( rBox
.GetFrameFormat()->GetAttrSet() );
2557 if( aTmpSet
.Count() )
2559 SwFrameFormat
* pBoxFormat
= rBox
.ClaimFrameFormat();
2560 pBoxFormat
->ResetFormatAttr( RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
);
2561 pBoxFormat
->ResetFormatAttr( RES_VERT_ORIENT
);
2563 if( pEntry
->pBoxNumAttr
)
2565 rBox
.ClaimFrameFormat()->SetFormatAttr( *pEntry
->pBoxNumAttr
);
2566 pEntry
->pBoxNumAttr
.reset();
2569 if( aTmpSet
.Count() )
2571 pEntry
->pBoxNumAttr
= std::make_unique
<SfxItemSetFixed
<
2572 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
2573 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
>>(rDoc
.GetAttrPool());
2574 pEntry
->pBoxNumAttr
->Put( aTmpSet
);
2577 pEntry
->nOffset
= rBox
.GetSttIdx() - pEntry
->nBoxIdx
;
2579 DEBUG_REDLINE( &rDoc
)
2582 void SwUndoTableCpyTable::AddBoxBefore( const SwTableBox
& rBox
, bool bDelContent
)
2584 if (!m_vArr
.empty() && !bDelContent
)
2587 UndoTableCpyTable_Entry
* pEntry
= new UndoTableCpyTable_Entry( rBox
);
2588 m_vArr
.push_back(std::unique_ptr
<UndoTableCpyTable_Entry
>(pEntry
));
2590 SwDoc
* pDoc
= rBox
.GetFrameFormat()->GetDoc();
2591 DEBUG_REDLINE( pDoc
)
2594 SwNodeIndex
aInsIdx( *rBox
.GetSttNd(), 1 );
2595 pDoc
->GetNodes().MakeTextNode( aInsIdx
.GetNode(), pDoc
->GetDfltTextFormatColl() );
2596 SwPaM
aPam( aInsIdx
.GetNode(), *rBox
.GetSttNd()->EndOfSectionNode() );
2598 if( !pDoc
->getIDocumentRedlineAccess().IsRedlineOn() )
2599 pEntry
->pUndo
= std::make_unique
<SwUndoDelete
>(aPam
, SwDeleteFlags::Default
, true);
2602 pEntry
->pBoxNumAttr
= std::make_unique
<SfxItemSetFixed
<
2603 RES_VERT_ORIENT
, RES_VERT_ORIENT
,
2604 RES_BOXATR_FORMAT
, RES_BOXATR_VALUE
>>(pDoc
->GetAttrPool());
2605 pEntry
->pBoxNumAttr
->Put( rBox
.GetFrameFormat()->GetAttrSet() );
2606 if( !pEntry
->pBoxNumAttr
->Count() )
2608 pEntry
->pBoxNumAttr
.reset();
2610 DEBUG_REDLINE( pDoc
)
2613 void SwUndoTableCpyTable::AddBoxAfter( const SwTableBox
& rBox
, const SwNodeIndex
& rIdx
, bool bDelContent
)
2615 UndoTableCpyTable_Entry
*const pEntry
= m_vArr
.back().get();
2617 // If the content was deleted then remove also the temporarily created node
2620 SwDoc
* pDoc
= rBox
.GetFrameFormat()->GetDoc();
2621 DEBUG_REDLINE( pDoc
)
2623 if( pDoc
->getIDocumentRedlineAccess().IsRedlineOn() )
2625 SwPosition
aTmpPos( rIdx
);
2626 pEntry
->pUndo
= PrepareRedline( pDoc
, rBox
, aTmpPos
, pEntry
->bJoin
, false );
2628 SwNodeIndex
aDelIdx( *rBox
.GetSttNd(), 1 );
2629 rBox
.GetFrameFormat()->GetDoc()->GetNodes().Delete( aDelIdx
);
2630 DEBUG_REDLINE( pDoc
)
2633 pEntry
->nOffset
= rBox
.GetSttIdx() - pEntry
->nBoxIdx
;
2636 // PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
2637 // bRedo is set by calling from Redo()
2638 // rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
2640 // rJoin is true if Redo() is calling and the content has already been merged
2642 std::unique_ptr
<SwUndo
> SwUndoTableCpyTable::PrepareRedline( SwDoc
* pDoc
, const SwTableBox
& rBox
,
2643 SwPosition
& rPos
, bool& rJoin
, bool bRedo
)
2645 std::unique_ptr
<SwUndo
> pUndo
;
2646 // b62341295: Redline for copying tables
2648 // Mark the cell content before rIdx as insertion,
2649 // mark the cell content behind rIdx as deletion
2650 // merge text nodes at rIdx if possible
2651 RedlineFlags eOld
= pDoc
->getIDocumentRedlineAccess().GetRedlineFlags();
2652 pDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern( ( eOld
| RedlineFlags::DontCombineRedlines
) & ~RedlineFlags::Ignore
);
2653 SwPosition
aInsertEnd( rPos
);
2657 // If the content is not merged, the end of the insertion is at the end of the node
2658 // _before_ the given position rPos
2659 aInsertEnd
.Adjust(SwNodeOffset(-1));
2660 pText
= aInsertEnd
.GetNode().GetTextNode();
2663 aInsertEnd
.SetContent(pText
->GetText().getLength());
2664 if( !bRedo
&& rPos
.GetNode().GetTextNode() )
2665 { // Try to merge, if not called by Redo()
2668 // Park this somewhere else so nothing points to the to-be-deleted node.
2669 rPos
.nContent
.Assign(pText
, 0);
2675 aInsertEnd
.nContent
.Assign(nullptr, 0);
2677 // For joined (merged) contents the start of deletion and end of insertion are identical
2678 // otherwise adjacent nodes.
2679 SwPosition
aDeleteStart( rJoin
? aInsertEnd
: rPos
);
2682 pText
= aDeleteStart
.GetNode().GetTextNode();
2684 aDeleteStart
.SetContent( 0 );
2686 SwPosition
aCellEnd( *rBox
.GetSttNd()->EndOfSectionNode(), SwNodeOffset(-1) );
2687 pText
= aCellEnd
.GetNode().GetTextNode();
2689 aCellEnd
.SetContent(pText
->GetText().getLength());
2690 if( aDeleteStart
!= aCellEnd
)
2691 { // If the old (deleted) part is not empty, here we are...
2692 SwPaM
aDeletePam( aDeleteStart
, aCellEnd
);
2693 pUndo
= std::make_unique
<SwUndoRedlineDelete
>( aDeletePam
, SwUndoId::DELETE
);
2694 pDoc
->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Delete
, aDeletePam
), true );
2696 else if( !rJoin
) // If the old part is empty and joined, we are finished
2697 { // if it is not joined, we have to delete this empty paragraph
2698 aCellEnd
.Assign(*rBox
.GetSttNd()->EndOfSectionNode());
2699 SwPaM
aTmpPam( aDeleteStart
, aCellEnd
);
2700 pUndo
= std::make_unique
<SwUndoDelete
>(aTmpPam
, SwDeleteFlags::Default
, true);
2702 SwPosition
aCellStart( *rBox
.GetSttNd(), SwNodeOffset(2) );
2703 pText
= aCellStart
.GetNode().GetTextNode();
2705 aCellStart
.SetContent( 0 );
2706 if( aCellStart
!= aInsertEnd
) // An empty insertion will not been marked
2708 SwPaM
aTmpPam( aCellStart
, aInsertEnd
);
2709 pDoc
->getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( RedlineType::Insert
, aTmpPam
), true );
2712 pDoc
->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld
);
2716 bool SwUndoTableCpyTable::InsertRow( SwTable
& rTable
, const SwSelBoxes
& rBoxes
,
2719 SwTableNode
* pTableNd
= const_cast<SwTableNode
*>(rTable
.GetTabSortBoxes()[0]->
2720 GetSttNd()->FindTableNode());
2722 m_pInsRowUndo
.reset( new SwUndoTableNdsChg( SwUndoId::TABLE_INSROW
, rBoxes
, *pTableNd
,
2723 0, 0, nCnt
, true, false ) );
2724 SwTableSortBoxes
aTmpLst( rTable
.GetTabSortBoxes() );
2726 bool bRet
= rTable
.InsertRow( rTable
.GetFrameFormat()->GetDoc(), rBoxes
, nCnt
, /*bBehind*/true );
2728 m_pInsRowUndo
->SaveNewBoxes( *pTableNd
, aTmpLst
);
2731 m_pInsRowUndo
.reset();
2736 void SwUndoTableCpyTable::dumpAsXml(xmlTextWriterPtr pWriter
) const
2738 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwUndoTableCpyTable"));
2740 for (const auto& pEntry
: m_vArr
)
2742 pEntry
->dumpAsXml(pWriter
);
2747 m_pInsRowUndo
->dumpAsXml(pWriter
);
2750 (void)xmlTextWriterEndElement(pWriter
);
2753 bool SwUndoTableCpyTable::IsEmpty() const
2755 return !m_pInsRowUndo
&& m_vArr
.empty();
2758 SwUndoCpyTable::SwUndoCpyTable(const SwDoc
& rDoc
)
2759 : SwUndo( SwUndoId::CPYTBL
, &rDoc
), m_nTableNode( 0 )
2763 SwUndoCpyTable::~SwUndoCpyTable()
2767 void SwUndoCpyTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
2769 SwDoc
& rDoc
= rContext
.GetDoc();
2770 SwTableNode
* pTNd
= rDoc
.GetNodes()[ m_nTableNode
]->GetTableNode();
2772 // move hard page breaks into next node
2773 SwContentNode
* pNextNd
= rDoc
.GetNodes()[ pTNd
->EndOfSectionIndex()+1 ]->GetContentNode();
2776 SwFrameFormat
* pTableFormat
= pTNd
->GetTable().GetFrameFormat();
2778 if( const SwFormatPageDesc
* pItem
= pTableFormat
->GetItemIfSet( RES_PAGEDESC
,
2780 pNextNd
->SetAttr( *pItem
);
2782 if( const SvxFormatBreakItem
* pItem
= pTableFormat
->GetItemIfSet( RES_BREAK
,
2784 pNextNd
->SetAttr( *pItem
);
2787 SwPaM
aPam( *pTNd
, *pTNd
->EndOfSectionNode(), SwNodeOffset(0) , SwNodeOffset(1) );
2788 m_pDelete
.reset(new SwUndoDelete(aPam
, SwDeleteFlags::Default
, true));
2791 void SwUndoCpyTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
2793 m_pDelete
->UndoImpl(rContext
);
2797 SwUndoSplitTable::SwUndoSplitTable( const SwTableNode
& rTableNd
,
2798 std::unique_ptr
<SwSaveRowSpan
> pRowSp
, SplitTable_HeadlineOption eMode
, bool bNewSize
)
2799 : SwUndo( SwUndoId::SPLIT_TABLE
, &rTableNd
.GetDoc() ),
2800 m_nTableNode( rTableNd
.GetIndex() ), m_nOffset( 0 ), mpSaveRowSpan( std::move(pRowSp
) ),
2801 m_nMode( eMode
), m_nFormulaEnd( 0 ), m_bCalcNewSize( bNewSize
)
2805 case SplitTable_HeadlineOption::BoxAttrAllCopy
:
2806 m_pHistory
.reset(new SwHistory
);
2808 case SplitTable_HeadlineOption::BorderCopy
:
2809 case SplitTable_HeadlineOption::BoxAttrCopy
:
2810 m_pSavedTable
.reset(new SaveTable( rTableNd
.GetTable(), 1, false ));
2816 SwUndoSplitTable::~SwUndoSplitTable()
2818 m_pSavedTable
.reset();
2820 mpSaveRowSpan
.reset();
2823 void SwUndoSplitTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
2825 SwDoc
*const pDoc
= & rContext
.GetDoc();
2826 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
2828 SwPosition
& rPtPos
= *pPam
->GetPoint();
2829 rPtPos
.Assign( m_nTableNode
+ m_nOffset
);
2830 assert(rPtPos
.GetNode().GetContentNode()->Len() == 0); // empty para inserted
2833 // avoid asserts from ~SwContentIndexReg
2834 SwNodeIndex
const idx(pDoc
->GetNodes(), m_nTableNode
+ m_nOffset
);
2837 pam
.Move(fnMoveBackward
, GoInContent
);
2838 ::PaMCorrAbs(*pPam
, *pam
.GetPoint());
2841 // remove implicitly created paragraph again
2842 pDoc
->GetNodes().Delete( idx
);
2845 rPtPos
.Assign( m_nTableNode
+ m_nOffset
);
2846 SwTableNode
* pTableNd
= rPtPos
.GetNode().GetTableNode();
2847 SwTable
& rTable
= pTableNd
->GetTable();
2848 rTable
.SwitchFormulasToInternalRepresentation();
2852 case SplitTable_HeadlineOption::BoxAttrAllCopy
:
2854 m_pHistory
->TmpRollback( pDoc
, m_nFormulaEnd
);
2856 case SplitTable_HeadlineOption::BoxAttrCopy
:
2857 case SplitTable_HeadlineOption::BorderCopy
:
2859 m_pSavedTable
->CreateNew( rTable
, false );
2860 m_pSavedTable
->RestoreAttr( rTable
);
2864 case SplitTable_HeadlineOption::ContentCopy
:
2865 // the created first line has to be removed again
2867 SwSelBoxes aSelBoxes
;
2868 SwTableBox
* pBox
= rTable
.GetTableBox( m_nTableNode
+ m_nOffset
+ 1 );
2869 SwTable::SelLineFromBox( pBox
, aSelBoxes
);
2870 FndBox_
aTmpBox( nullptr, nullptr );
2871 aTmpBox
.SetTableLines( aSelBoxes
, rTable
);
2872 aTmpBox
.DelFrames( rTable
);
2873 rTable
.DeleteSel( pDoc
, aSelBoxes
, nullptr, nullptr, false, false );
2879 pDoc
->GetNodes().MergeTable( rPtPos
.GetNode() );
2883 m_pHistory
->TmpRollback( pDoc
, 0 );
2884 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
2888 pTableNd
= rPtPos
.GetNode().FindTableNode();
2890 pTableNd
->GetTable().RestoreRowSpan( *mpSaveRowSpan
);
2892 ClearFEShellTabCols(*pDoc
, nullptr);
2895 void SwUndoSplitTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
2897 SwDoc
*const pDoc
= & rContext
.GetDoc();
2898 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
2901 pPam
->GetPoint()->Assign( m_nTableNode
);
2902 pDoc
->SplitTable( *pPam
->GetPoint(), m_nMode
, m_bCalcNewSize
);
2904 ClearFEShellTabCols(*pDoc
, nullptr);
2907 void SwUndoSplitTable::RepeatImpl(::sw::RepeatContext
& rContext
)
2909 SwPaM
*const pPam
= & rContext
.GetRepeatPaM();
2910 SwDoc
*const pDoc
= & rContext
.GetDoc();
2912 pDoc
->SplitTable( *pPam
->GetPoint(), m_nMode
, m_bCalcNewSize
);
2913 ClearFEShellTabCols(*pDoc
, nullptr);
2916 void SwUndoSplitTable::SaveFormula( SwHistory
& rHistory
)
2919 m_pHistory
.reset(new SwHistory
);
2921 m_nFormulaEnd
= rHistory
.Count();
2922 m_pHistory
->Move( 0, &rHistory
);
2925 SwUndoMergeTable::SwUndoMergeTable( const SwTableNode
& rTableNd
,
2926 const SwTableNode
& rDelTableNd
,
2928 : SwUndo( SwUndoId::MERGE_TABLE
, &rTableNd
.GetDoc() ),
2929 m_bWithPrev( bWithPrv
)
2931 // memorize end node of the last table cell that'll stay in position
2933 m_nTableNode
= rDelTableNd
.EndOfSectionIndex() - 1;
2935 m_nTableNode
= rTableNd
.EndOfSectionIndex() - 1;
2937 m_aName
= rDelTableNd
.GetTable().GetFrameFormat()->GetName();
2938 m_pSaveTable
.reset(new SaveTable( rDelTableNd
.GetTable() ));
2941 m_pSaveHdl
.reset( new SaveTable( rTableNd
.GetTable(), 1 ) );
2944 SwUndoMergeTable::~SwUndoMergeTable()
2946 m_pSaveTable
.reset();
2951 void SwUndoMergeTable::UndoImpl(::sw::UndoRedoContext
& rContext
)
2953 SwDoc
*const pDoc
= & rContext
.GetDoc();
2954 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
2957 SwPosition
& rPtPos
= *pPam
->GetPoint();
2958 rPtPos
.Assign( m_nTableNode
);
2960 SwTableNode
* pTableNd
= rPtPos
.GetNode().FindTableNode();
2961 SwTable
* pTable
= &pTableNd
->GetTable();
2962 pTable
->SwitchFormulasToInternalRepresentation();
2964 // get lines for layout update
2965 FndBox_
aFndBox( nullptr, nullptr );
2966 aFndBox
.SetTableLines( *pTable
);
2967 aFndBox
.DelFrames( *pTable
);
2968 // ? TL_CHART2: notification or locking of controller required ?
2970 SwTableNode
* pNew
= pDoc
->GetNodes().SplitTable( rPtPos
.GetNode() );
2973 aFndBox
.MakeFrames( *pTable
);
2974 // ? TL_CHART2: notification or locking of controller required ?
2979 pNew
->GetTable().GetFrameFormat()->SetFormatName( pTable
->GetFrameFormat()->GetName() );
2980 m_pSaveHdl
->RestoreAttr( pNew
->GetTable() );
2983 pTable
= &pNew
->GetTable();
2985 pTable
->GetFrameFormat()->SetFormatName( m_aName
);
2986 m_pSaveTable
->RestoreAttr( *pTable
);
2990 m_pHistory
->TmpRollback( pDoc
, 0 );
2991 m_pHistory
->SetTmpEnd( m_pHistory
->Count() );
2994 // create frames for the new table
2995 pNew
->MakeOwnFrames();
2997 // position cursor somewhere in content
2998 pDoc
->GetNodes().GoNext( &rPtPos
);
3000 ClearFEShellTabCols(*pDoc
, nullptr);
3002 // TL_CHART2: need to inform chart of probably changed cell names
3003 SwChartDataProvider
*pPCD
= pDoc
->getIDocumentChartDataProviderAccess().GetChartDataProvider();
3006 pDoc
->UpdateCharts( pTable
->GetFrameFormat()->GetName() );
3007 pDoc
->UpdateCharts( pNew
->GetTable().GetFrameFormat()->GetName() );
3011 void SwUndoMergeTable::RedoImpl(::sw::UndoRedoContext
& rContext
)
3013 SwDoc
*const pDoc
= & rContext
.GetDoc();
3014 SwPaM
*const pPam(& rContext
.GetCursorSupplier().CreateNewShellCursor());
3018 pPam
->GetPoint()->Assign( m_nTableNode
+ 3 );
3020 pPam
->GetPoint()->Assign( m_nTableNode
);
3022 pDoc
->MergeTable( *pPam
->GetPoint(), m_bWithPrev
);
3024 ClearFEShellTabCols(*pDoc
, nullptr);
3027 void SwUndoMergeTable::RepeatImpl(::sw::RepeatContext
& rContext
)
3029 SwDoc
*const pDoc
= & rContext
.GetDoc();
3030 SwPaM
*const pPam
= & rContext
.GetRepeatPaM();
3032 pDoc
->MergeTable( *pPam
->GetPoint(), m_bWithPrev
);
3033 ClearFEShellTabCols(*pDoc
, nullptr);
3036 void SwUndoMergeTable::SaveFormula( SwHistory
& rHistory
)
3039 m_pHistory
.reset( new SwHistory
);
3040 m_pHistory
->Move( 0, &rHistory
);
3043 void InsertSort( std::vector
<sal_uInt16
>& rArr
, sal_uInt16 nIdx
)
3045 size_t nO
= rArr
.size();
3052 const size_t nM
= nU
+ ( nO
- nU
) / 2;
3053 if ( rArr
[nM
] == nIdx
)
3055 OSL_FAIL( "Index already exists. This should never happen." );
3058 if( rArr
[nM
] < nIdx
)
3066 rArr
.insert( rArr
.begin() + nU
, nIdx
);
3069 #if OSL_DEBUG_LEVEL > 0
3070 void CheckTable( const SwTable
& rTable
)
3072 const SwNodes
& rNds
= rTable
.GetFrameFormat()->GetDoc()->GetNodes();
3073 const SwTableSortBoxes
& rSrtArr
= rTable
.GetTabSortBoxes();
3074 for (size_t n
= 0; n
< rSrtArr
.size(); ++n
)
3076 const SwTableBox
* pBox
= rSrtArr
[ n
];
3077 const SwNode
* pNd
= pBox
->GetSttNd();
3078 OSL_ENSURE( rNds
[ pBox
->GetSttIdx() ] == pNd
, "Box with wrong StartNode" );
3083 SwUndoTableStyleMake::SwUndoTableStyleMake(OUString aName
, const SwDoc
& rDoc
)
3084 : SwUndo(SwUndoId::TBLSTYLE_CREATE
, &rDoc
),
3085 m_sName(std::move(aName
))
3088 SwUndoTableStyleMake::~SwUndoTableStyleMake()
3091 void SwUndoTableStyleMake::UndoImpl(::sw::UndoRedoContext
& rContext
)
3093 m_pAutoFormat
= rContext
.GetDoc().DelTableStyle(m_sName
, true);
3096 void SwUndoTableStyleMake::RedoImpl(::sw::UndoRedoContext
& rContext
)
3100 SwTableAutoFormat
* pFormat
= rContext
.GetDoc().MakeTableStyle(m_sName
, true);
3103 *pFormat
= *m_pAutoFormat
;
3104 m_pAutoFormat
.reset();
3109 SwRewriter
SwUndoTableStyleMake::GetRewriter() const
3112 aResult
.AddRule(UndoArg1
, m_sName
);
3116 SwUndoTableStyleDelete::SwUndoTableStyleDelete(std::unique_ptr
<SwTableAutoFormat
> pAutoFormat
, std::vector
<SwTable
*>&& rAffectedTables
, const SwDoc
& rDoc
)
3117 : SwUndo(SwUndoId::TBLSTYLE_DELETE
, &rDoc
),
3118 m_pAutoFormat(std::move(pAutoFormat
)),
3119 m_rAffectedTables(std::move(rAffectedTables
))
3122 SwUndoTableStyleDelete::~SwUndoTableStyleDelete()
3125 void SwUndoTableStyleDelete::UndoImpl(::sw::UndoRedoContext
& rContext
)
3127 SwTableAutoFormat
* pNewFormat
= rContext
.GetDoc().MakeTableStyle(m_pAutoFormat
->GetName(), true);
3128 *pNewFormat
= *m_pAutoFormat
;
3129 for (size_t i
=0; i
< m_rAffectedTables
.size(); i
++)
3130 m_rAffectedTables
[i
]->SetTableStyleName(m_pAutoFormat
->GetName());
3133 void SwUndoTableStyleDelete::RedoImpl(::sw::UndoRedoContext
& rContext
)
3135 // Don't need to remember deleted table style nor affected tables, because they must be the same as these already known.
3136 rContext
.GetDoc().DelTableStyle(m_pAutoFormat
->GetName());
3139 SwRewriter
SwUndoTableStyleDelete::GetRewriter() const
3142 aResult
.AddRule(UndoArg1
, m_pAutoFormat
->GetName());
3146 SwUndoTableStyleUpdate::SwUndoTableStyleUpdate(const SwTableAutoFormat
& rNewFormat
, const SwTableAutoFormat
& rOldFormat
, const SwDoc
& rDoc
)
3147 : SwUndo(SwUndoId::TBLSTYLE_UPDATE
, &rDoc
)
3148 , m_pOldFormat(new SwTableAutoFormat(rOldFormat
))
3149 , m_pNewFormat(new SwTableAutoFormat(rNewFormat
))
3152 SwUndoTableStyleUpdate::~SwUndoTableStyleUpdate()
3155 void SwUndoTableStyleUpdate::UndoImpl(::sw::UndoRedoContext
& rContext
)
3157 rContext
.GetDoc().ChgTableStyle(m_pNewFormat
->GetName(), *m_pOldFormat
);
3160 void SwUndoTableStyleUpdate::RedoImpl(::sw::UndoRedoContext
& rContext
)
3162 rContext
.GetDoc().ChgTableStyle(m_pNewFormat
->GetName(), *m_pNewFormat
);
3165 SwRewriter
SwUndoTableStyleUpdate::GetRewriter() const
3168 aResult
.AddRule(UndoArg1
, m_pNewFormat
->GetName());
3172 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */