cid#1607171 Data race condition
[LibreOffice.git] / sc / source / ui / undo / undoblk3.cxx
blob9c4bc4409ebd7e0bb4c902b1938da028cde4eea2
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <sal/config.h>
22 #include <memory>
24 #include <scitems.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/justifyitem.hxx>
27 #include <svl/srchitem.hxx>
28 #include <sfx2/linkmgr.hxx>
29 #include <utility>
30 #include <vcl/virdev.hxx>
31 #include <sfx2/app.hxx>
32 #include <svx/svdundo.hxx>
33 #include <osl/diagnose.h>
35 #include <undoblk.hxx>
36 #include <globstr.hrc>
37 #include <scresid.hxx>
38 #include <global.hxx>
39 #include <arealink.hxx>
40 #include <patattr.hxx>
41 #include <target.hxx>
42 #include <document.hxx>
43 #include <docpool.hxx>
44 #include <docsh.hxx>
45 #include <tabvwsh.hxx>
46 #include <undoolk.hxx>
47 #include <undoutil.hxx>
48 #include <chgtrack.hxx>
49 #include <paramisc.hxx>
50 #include <postit.hxx>
51 #include <progress.hxx>
52 #include <editutil.hxx>
53 #include <editdataarray.hxx>
54 #include <rowheightcontext.hxx>
56 // TODO:
57 /*A*/ // SetOptimalHeight on Document, when no View
59 ScUndoDeleteContents::ScUndoDeleteContents(
60 ScDocShell* pNewDocShell,
61 const ScMarkData& rMark, const ScRange& rRange,
62 ScDocumentUniquePtr&& pNewUndoDoc, bool bNewMulti,
63 InsertDeleteFlags nNewFlags, bool bObjects )
64 : ScSimpleUndo( pNewDocShell ),
65 aRange ( rRange ),
66 aMarkData ( rMark ),
67 pUndoDoc ( std::move(pNewUndoDoc) ),
68 nFlags ( nNewFlags ),
69 bMulti ( bNewMulti ) // unnecessary
71 if (bObjects)
72 pDrawUndo = GetSdrUndoAction( &pDocShell->GetDocument() );
74 if ( !(aMarkData.IsMarked() || aMarkData.IsMultiMarked()) ) // if no cell is selected:
75 aMarkData.SetMarkArea( aRange ); // select cell under cursor
77 SetChangeTrack();
80 ScUndoDeleteContents::~ScUndoDeleteContents()
82 pUndoDoc.reset();
83 pDrawUndo.reset();
86 OUString ScUndoDeleteContents::GetComment() const
88 return ScResId( STR_UNDO_DELETECONTENTS ); // "Delete"
91 void ScUndoDeleteContents::SetDataSpans( const std::shared_ptr<DataSpansType>& pSpans )
93 mpDataSpans = pSpans;
96 void ScUndoDeleteContents::SetChangeTrack()
98 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
99 if ( pChangeTrack && (nFlags & InsertDeleteFlags::CONTENTS) )
100 pChangeTrack->AppendContentRange( aRange, pUndoDoc.get(),
101 nStartChangeAction, nEndChangeAction );
102 else
103 nStartChangeAction = nEndChangeAction = 0;
106 void ScUndoDeleteContents::DoChange( const bool bUndo )
108 ScDocument& rDoc = pDocShell->GetDocument();
110 SetViewMarkData( aMarkData );
112 sal_uInt16 nExtFlags = 0;
114 if (bUndo) // only Undo
116 InsertDeleteFlags nUndoFlags = InsertDeleteFlags::NONE; // copy either all or none of the content
117 if (nFlags & InsertDeleteFlags::CONTENTS) // (Only the correct ones have been copied into UndoDoc)
118 nUndoFlags |= InsertDeleteFlags::CONTENTS;
119 if (nFlags & InsertDeleteFlags::ATTRIB)
120 nUndoFlags |= InsertDeleteFlags::ATTRIB;
121 if (nFlags & InsertDeleteFlags::EDITATTR) // Edit-Engine attribute
122 nUndoFlags |= InsertDeleteFlags::STRING; // -> Cells will be changed
123 if (nFlags & InsertDeleteFlags::SPARKLINES)
124 nUndoFlags |= InsertDeleteFlags::SPARKLINES;
125 // do not create clones of note captions, they will be restored via drawing undo
126 nUndoFlags |= InsertDeleteFlags::NOCAPTIONS;
128 ScRange aCopyRange = aRange;
129 SCTAB nTabCount = rDoc.GetTableCount();
130 aCopyRange.aStart.SetTab(0);
131 aCopyRange.aEnd.SetTab(nTabCount-1);
133 pUndoDoc->CopyToDocument(aCopyRange, nUndoFlags, bMulti, rDoc, &aMarkData);
135 DoSdrUndoAction( pDrawUndo.get(), &rDoc );
137 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
138 if ( pChangeTrack )
139 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
141 pDocShell->UpdatePaintExt( nExtFlags, aRange ); // content after the change
143 else // only Redo
145 pDocShell->UpdatePaintExt( nExtFlags, aRange ); // content before the change
147 aMarkData.MarkToMulti();
148 RedoSdrUndoAction( pDrawUndo.get() );
149 // do not delete objects and note captions, they have been removed via drawing undo
150 InsertDeleteFlags nRedoFlags = (nFlags & ~InsertDeleteFlags::OBJECTS) | InsertDeleteFlags::NOCAPTIONS;
151 rDoc.DeleteSelection( nRedoFlags, aMarkData );
152 aMarkData.MarkToSimple();
154 SetChangeTrack();
157 if (nFlags & InsertDeleteFlags::CONTENTS)
159 // Broadcast only when the content changes. fdo#74687
160 if (mpDataSpans)
161 BroadcastChanges(*mpDataSpans);
162 else
163 BroadcastChanges(aRange);
166 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
167 if ( !( pViewShell && pViewShell->AdjustRowHeight(
168 aRange.aStart.Row(), aRange.aEnd.Row(), true ) ) )
169 /*A*/ pDocShell->PostPaint( aRange, PaintPartFlags::Grid | PaintPartFlags::Extras, nExtFlags );
171 if (pViewShell)
172 pViewShell->CellContentChanged();
174 ShowTable( aRange );
177 void ScUndoDeleteContents::Undo()
179 BeginUndo();
180 DoChange( true );
181 EndUndo();
183 HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange, u"undo"_ustr);
186 void ScUndoDeleteContents::Redo()
188 BeginRedo();
189 DoChange( false );
190 EndRedo();
192 HelperNotifyChanges::NotifyIfChangesListeners(*pDocShell, aRange, u"redo"_ustr);
195 void ScUndoDeleteContents::Repeat(SfxRepeatTarget& rTarget)
197 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
198 pViewTarget->GetViewShell()->DeleteContents( nFlags );
201 bool ScUndoDeleteContents::CanRepeat(SfxRepeatTarget& rTarget) const
203 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
206 ScUndoFillTable::ScUndoFillTable( ScDocShell* pNewDocShell,
207 const ScMarkData& rMark,
208 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
209 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
210 ScDocumentUniquePtr pNewUndoDoc, bool bNewMulti, SCTAB nSrc,
211 InsertDeleteFlags nFlg, ScPasteFunc nFunc, bool bSkip, bool bLink )
212 : ScSimpleUndo( pNewDocShell ),
213 aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
214 aMarkData ( rMark ),
215 pUndoDoc ( std::move(pNewUndoDoc) ),
216 nFlags ( nFlg ),
217 nFunction ( nFunc ),
218 nSrcTab ( nSrc ),
219 bMulti ( bNewMulti ),
220 bSkipEmpty ( bSkip ),
221 bAsLink ( bLink )
223 SetChangeTrack();
226 ScUndoFillTable::~ScUndoFillTable()
230 OUString ScUndoFillTable::GetComment() const
232 return ScResId( STR_FILL_TAB );
235 void ScUndoFillTable::SetChangeTrack()
237 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
238 if ( pChangeTrack )
240 SCTAB nTabCount = pDocShell->GetDocument().GetTableCount();
241 ScRange aWorkRange(aRange);
242 nStartChangeAction = 0;
243 sal_uLong nTmpAction;
244 for (const auto& rTab : aMarkData)
246 if (rTab >= nTabCount)
247 break;
248 if (rTab != nSrcTab)
250 aWorkRange.aStart.SetTab(rTab);
251 aWorkRange.aEnd.SetTab(rTab);
252 pChangeTrack->AppendContentRange( aWorkRange, pUndoDoc.get(),
253 nTmpAction, nEndChangeAction );
254 if ( !nStartChangeAction )
255 nStartChangeAction = nTmpAction;
259 else
260 nStartChangeAction = nEndChangeAction = 0;
263 void ScUndoFillTable::DoChange( const bool bUndo )
265 ScDocument& rDoc = pDocShell->GetDocument();
267 SetViewMarkData( aMarkData );
269 if (bUndo) // only Undo
271 SCTAB nTabCount = rDoc.GetTableCount();
272 ScRange aWorkRange(aRange);
273 for (const auto& rTab : aMarkData)
275 if (rTab >= nTabCount)
276 break;
277 if (rTab != nSrcTab)
279 aWorkRange.aStart.SetTab(rTab);
280 aWorkRange.aEnd.SetTab(rTab);
281 if (bMulti)
282 rDoc.DeleteSelectionTab( rTab, InsertDeleteFlags::ALL, aMarkData );
283 else
284 rDoc.DeleteAreaTab( aWorkRange, InsertDeleteFlags::ALL );
285 pUndoDoc->CopyToDocument(aWorkRange, InsertDeleteFlags::ALL, bMulti, rDoc, &aMarkData);
289 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
290 if ( pChangeTrack )
291 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
293 else // only Redo
295 aMarkData.MarkToMulti();
296 rDoc.FillTabMarked( nSrcTab, aMarkData, nFlags, nFunction, bSkipEmpty, bAsLink );
297 aMarkData.MarkToSimple();
298 SetChangeTrack();
301 pDocShell->PostPaint(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid|PaintPartFlags::Extras);
302 pDocShell->PostDataChanged();
304 // CellContentChanged comes with the selection
306 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
307 if (pViewShell)
309 SCTAB nTab = pViewShell->GetViewData().GetTabNo();
310 if ( !aMarkData.GetTableSelect(nTab) )
311 pViewShell->SetTabNo( nSrcTab );
313 pViewShell->DoneBlockMode(); // causes problems otherwise since selection is on the wrong sheet.
317 void ScUndoFillTable::Undo()
319 BeginUndo();
320 DoChange( true );
321 EndUndo();
324 void ScUndoFillTable::Redo()
326 BeginRedo();
327 DoChange( false );
328 EndRedo();
331 void ScUndoFillTable::Repeat(SfxRepeatTarget& rTarget)
333 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
334 pViewTarget->GetViewShell()->FillTab( nFlags, nFunction, bSkipEmpty, bAsLink );
337 bool ScUndoFillTable::CanRepeat(SfxRepeatTarget& rTarget) const
339 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
342 ScUndoSelectionAttr::ScUndoSelectionAttr( ScDocShell* pNewDocShell,
343 const ScMarkData& rMark,
344 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
345 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
346 ScDocumentUniquePtr pNewUndoDoc, bool bNewMulti,
347 const ScPatternAttr* pNewApply,
348 const SvxBoxItem* pNewOuter, const SvxBoxInfoItem* pNewInner,
349 const ScRange* pRangeCover )
350 : ScSimpleUndo( pNewDocShell ),
351 aMarkData ( rMark ),
352 aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
353 mpDataArray(new ScEditDataArray),
354 pUndoDoc ( std::move(pNewUndoDoc) ),
355 bMulti ( bNewMulti ),
356 aApplyPattern( pNewApply ),
357 maLineOuter(*pDocShell->GetDocument().GetPool(), pNewOuter),
358 maLineInner(*pDocShell->GetDocument().GetPool(), pNewInner)
360 aRangeCover = pRangeCover ? *pRangeCover : aRange;
363 ScUndoSelectionAttr::~ScUndoSelectionAttr()
365 pUndoDoc.reset();
368 OUString ScUndoSelectionAttr::GetComment() const
370 //"Attribute" "/Lines"
371 return ScResId( maLineOuter.getItem() ? STR_UNDO_SELATTRLINES : STR_UNDO_SELATTR );
374 ScEditDataArray* ScUndoSelectionAttr::GetDataArray()
376 return mpDataArray.get();
379 void ScUndoSelectionAttr::DoChange( const bool bUndo )
381 ScDocument& rDoc = pDocShell->GetDocument();
383 SetViewMarkData( aMarkData );
385 ScRange aEffRange( aRangeCover );
386 if ( rDoc.HasAttrib( aEffRange, HasAttrFlags::Merged ) ) // merged cells?
387 rDoc.ExtendMerge( aEffRange );
389 sal_uInt16 nExtFlags = 0;
390 pDocShell->UpdatePaintExt( nExtFlags, aEffRange );
392 ChangeEditData(bUndo);
394 if (bUndo) // only for Undo
396 ScRange aCopyRange = aRangeCover;
397 SCTAB nTabCount = rDoc.GetTableCount();
398 aCopyRange.aStart.SetTab(0);
399 aCopyRange.aEnd.SetTab(nTabCount-1);
400 pUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, bMulti, rDoc, &aMarkData);
402 else // only for Redo
404 aMarkData.MarkToMulti();
405 rDoc.ApplySelectionPattern( *aApplyPattern.getScPatternAttr(), aMarkData );
406 aMarkData.MarkToSimple();
408 if (maLineOuter.getItem())
409 rDoc.ApplySelectionFrame(aMarkData,
410 *static_cast<const SvxBoxItem*>(maLineOuter.getItem()),
411 static_cast<const SvxBoxInfoItem*>(maLineInner.getItem()));
414 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
415 if ( !( pViewShell && pViewShell->AdjustBlockHeight() ) )
416 /*A*/ pDocShell->PostPaint( aEffRange, PaintPartFlags::Grid | PaintPartFlags::Extras, nExtFlags );
418 ShowTable( aRange );
421 void ScUndoSelectionAttr::ChangeEditData( const bool bUndo )
423 ScDocument& rDoc = pDocShell->GetDocument();
424 for (const ScEditDataArray::Item* pItem = mpDataArray->First(); pItem; pItem = mpDataArray->Next())
426 ScAddress aPos(pItem->GetCol(), pItem->GetRow(), pItem->GetTab());
427 if (rDoc.GetCellType(aPos) != CELLTYPE_EDIT)
428 continue;
430 if (bUndo)
432 if (pItem->GetOldData())
433 rDoc.SetEditText(aPos, *pItem->GetOldData(), nullptr);
434 else
435 rDoc.SetEmptyCell(aPos);
437 else
439 if (pItem->GetNewData())
440 rDoc.SetEditText(aPos, *pItem->GetNewData(), nullptr);
441 else
442 rDoc.SetEmptyCell(aPos);
447 void ScUndoSelectionAttr::Undo()
449 BeginUndo();
450 DoChange( true );
451 EndUndo();
454 void ScUndoSelectionAttr::Redo()
456 BeginRedo();
457 DoChange( false );
458 EndRedo();
461 void ScUndoSelectionAttr::Repeat(SfxRepeatTarget& rTarget)
463 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
465 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
466 if (maLineOuter.getItem())
467 rViewShell.ApplyPatternLines(*aApplyPattern.getScPatternAttr(),
468 *static_cast<const SvxBoxItem*>(maLineOuter.getItem()),
469 static_cast<const SvxBoxInfoItem*>(maLineInner.getItem()));
470 else
471 rViewShell.ApplySelectionPattern( *aApplyPattern.getScPatternAttr() );
475 bool ScUndoSelectionAttr::CanRepeat(SfxRepeatTarget& rTarget) const
477 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
480 ScUndoAutoFill::ScUndoAutoFill( ScDocShell* pNewDocShell,
481 const ScRange& rRange, const ScRange& rSourceArea,
482 ScDocumentUniquePtr pNewUndoDoc, const ScMarkData& rMark,
483 FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
484 double fNewStartValue, double fNewStepValue, double fNewMaxValue )
485 : ScBlockUndo( pNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
486 aSource ( rSourceArea ),
487 aMarkData ( rMark ),
488 pUndoDoc ( std::move(pNewUndoDoc) ),
489 eFillDir ( eNewFillDir ),
490 eFillCmd ( eNewFillCmd ),
491 eFillDateCmd ( eNewFillDateCmd ),
492 fStartValue ( fNewStartValue ),
493 fStepValue ( fNewStepValue ),
494 fMaxValue ( fNewMaxValue )
496 SetChangeTrack();
499 ScUndoAutoFill::~ScUndoAutoFill()
503 OUString ScUndoAutoFill::GetComment() const
505 return ScResId( STR_UNDO_AUTOFILL ); //"Fill"
508 void ScUndoAutoFill::SetChangeTrack()
510 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
511 if ( pChangeTrack )
512 pChangeTrack->AppendContentRange( aBlockRange, pUndoDoc.get(),
513 nStartChangeAction, nEndChangeAction );
514 else
515 nStartChangeAction = nEndChangeAction = 0;
518 void ScUndoAutoFill::Undo()
520 BeginUndo();
522 ScDocument& rDoc = pDocShell->GetDocument();
524 SCTAB nTabCount = rDoc.GetTableCount();
525 for (const auto& rTab : aMarkData)
527 if (rTab >= nTabCount)
528 break;
529 ScRange aWorkRange = aBlockRange;
530 aWorkRange.aStart.SetTab(rTab);
531 aWorkRange.aEnd.SetTab(rTab);
533 sal_uInt16 nExtFlags = 0;
534 pDocShell->UpdatePaintExt( nExtFlags, aWorkRange );
535 rDoc.DeleteAreaTab( aWorkRange, InsertDeleteFlags::AUTOFILL );
536 pUndoDoc->CopyToDocument(aWorkRange, InsertDeleteFlags::AUTOFILL, false, rDoc);
538 // Actually we'd only need to broadcast the cells inserted during
539 // CopyToDocument(), as DeleteAreaTab() broadcasts deleted cells. For
540 // this we'd need to either record the span sets or let
541 // CopyToDocument() broadcast.
542 BroadcastChanges( aWorkRange);
544 rDoc.ExtendMerge( aWorkRange, true );
545 pDocShell->PostPaint( aWorkRange, PaintPartFlags::Grid, nExtFlags );
547 pDocShell->PostDataChanged();
548 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
549 if (pViewShell)
550 pViewShell->CellContentChanged();
552 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
553 if ( pChangeTrack )
554 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
556 EndUndo();
559 void ScUndoAutoFill::Redo()
561 BeginRedo();
563 //! Select sheet
565 SCCOLROW nCount = 0;
566 switch (eFillDir)
568 case FILL_TO_BOTTOM:
569 nCount = aBlockRange.aEnd.Row() - aSource.aEnd.Row();
570 break;
571 case FILL_TO_RIGHT:
572 nCount = aBlockRange.aEnd.Col() - aSource.aEnd.Col();
573 break;
574 case FILL_TO_TOP:
575 nCount = aSource.aStart.Row() - aBlockRange.aStart.Row();
576 break;
577 case FILL_TO_LEFT:
578 nCount = aSource.aStart.Col() - aBlockRange.aStart.Col();
579 break;
582 ScDocument& rDoc = pDocShell->GetDocument();
583 if ( fStartValue != MAXDOUBLE )
585 SCCOL nValX = (eFillDir == FILL_TO_LEFT) ? aSource.aEnd.Col() : aSource.aStart.Col();
586 SCROW nValY = (eFillDir == FILL_TO_TOP ) ? aSource.aEnd.Row() : aSource.aStart.Row();
587 SCTAB nTab = aSource.aStart.Tab();
588 rDoc.SetValue( nValX, nValY, nTab, fStartValue );
590 sal_uLong nProgCount;
591 if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
592 nProgCount = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
593 else
594 nProgCount = aSource.aEnd.Row() - aSource.aStart.Row() + 1;
595 nProgCount *= nCount;
596 ScProgress aProgress( rDoc.GetDocumentShell(),
597 ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
599 rDoc.Fill( aSource.aStart.Col(), aSource.aStart.Row(),
600 aSource.aEnd.Col(), aSource.aEnd.Row(), &aProgress,
601 aMarkData, nCount,
602 eFillDir, eFillCmd, eFillDateCmd,
603 fStepValue, fMaxValue );
605 SetChangeTrack();
607 pDocShell->PostPaint( aBlockRange, PaintPartFlags::Grid );
608 pDocShell->PostDataChanged();
609 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
610 if (pViewShell)
611 pViewShell->CellContentChanged();
613 EndRedo();
616 void ScUndoAutoFill::Repeat(SfxRepeatTarget& rTarget)
618 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
620 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
621 if (eFillCmd==FILL_SIMPLE)
622 rViewShell.FillSimple( eFillDir );
623 else
624 rViewShell.FillSeries( eFillDir, eFillCmd, eFillDateCmd,
625 fStartValue, fStepValue, fMaxValue );
629 bool ScUndoAutoFill::CanRepeat(SfxRepeatTarget& rTarget) const
631 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
634 ScUndoMerge::ScUndoMerge(ScDocShell* pNewDocShell, ScCellMergeOption aOption,
635 bool bMergeContents, ScDocumentUniquePtr pUndoDoc, std::unique_ptr<SdrUndoAction> pDrawUndo)
636 : ScSimpleUndo(pNewDocShell)
637 , maOption(std::move(aOption))
638 , mbMergeContents(bMergeContents)
639 , mxUndoDoc(std::move(pUndoDoc))
640 , mpDrawUndo(std::move(pDrawUndo))
644 ScUndoMerge::~ScUndoMerge()
646 mpDrawUndo.reset();
649 OUString ScUndoMerge::GetComment() const
651 return ScResId( STR_UNDO_MERGE );
654 void ScUndoMerge::DoChange( bool bUndo ) const
656 using ::std::set;
658 if (maOption.maTabs.empty())
659 // Nothing to do.
660 return;
662 ScDocument& rDoc = pDocShell->GetDocument();
663 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
665 ScRange aCurRange = maOption.getSingleRange(ScDocShell::GetCurTab());
666 ScUndoUtil::MarkSimpleBlock(pDocShell, aCurRange);
668 for (const SCTAB nTab : maOption.maTabs)
670 ScRange aRange = maOption.getSingleRange(nTab);
672 if (bUndo)
673 // remove merge (contents are copied back below from undo document)
674 rDoc.RemoveMerge( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() );
675 else
677 // repeat merge, but do not remove note captions (will be done by drawing redo below)
678 rDoc.DoMerge( aRange.aStart.Col(), aRange.aStart.Row(),
679 aRange.aEnd.Col(), aRange.aEnd.Row(),
680 aRange.aStart.Tab(), false );
682 if (maOption.mbCenter)
684 rDoc.ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
685 aRange.aStart.Tab(),
686 SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY ) );
687 rDoc.ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
688 aRange.aStart.Tab(),
689 SvxVerJustifyItem( SvxCellVerJustify::Center, ATTR_VER_JUSTIFY ) );
693 // undo -> copy back deleted contents
694 if (bUndo && mxUndoDoc)
696 // If there are note captions to be deleted during Undo they were
697 // kept or moved during the merge and copied to the Undo document
698 // without cloning the caption. Forget the target area's caption
699 // pointer that is identical to the one in the Undo document
700 // instead of deleting it.
701 rDoc.DeleteAreaTab( aRange,
702 InsertDeleteFlags::CONTENTS | InsertDeleteFlags::NOCAPTIONS | InsertDeleteFlags::FORGETCAPTIONS );
703 mxUndoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, rDoc);
706 // redo -> merge contents again
707 else if (!bUndo && mbMergeContents)
709 rDoc.DoMergeContents( aRange.aStart.Col(), aRange.aStart.Row(),
710 aRange.aEnd.Col(), aRange.aEnd.Row(),
711 aRange.aStart.Tab() );
714 if (bUndo)
715 DoSdrUndoAction( mpDrawUndo.get(), &rDoc );
716 else
717 RedoSdrUndoAction( mpDrawUndo.get() );
719 bool bDidPaint = false;
720 if ( pViewShell )
722 pViewShell->SetTabNo(nTab);
723 bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow, true);
726 if (!bDidPaint)
727 ScUndoUtil::PaintMore(pDocShell, aRange);
729 rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged);
732 ShowTable(aCurRange);
735 void ScUndoMerge::Undo()
737 BeginUndo();
738 DoChange( true );
739 EndUndo();
742 void ScUndoMerge::Redo()
744 BeginRedo();
745 DoChange( false );
746 EndRedo();
749 void ScUndoMerge::Repeat(SfxRepeatTarget& rTarget)
751 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
753 ScTabViewShell& rViewShell = *pViewTarget->GetViewShell();
754 rViewShell.MergeCells( false, false, false, 0 );
758 bool ScUndoMerge::CanRepeat(SfxRepeatTarget& rTarget) const
760 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
763 ScUndoAutoFormat::ScUndoAutoFormat( ScDocShell* pNewDocShell,
764 const ScRange& rRange, ScDocumentUniquePtr pNewUndoDoc,
765 const ScMarkData& rMark, bool bNewSize, sal_uInt16 nNewFormatNo )
766 : ScBlockUndo( pNewDocShell, rRange, bNewSize ? SC_UNDO_MANUALHEIGHT : SC_UNDO_AUTOHEIGHT ),
767 pUndoDoc ( std::move(pNewUndoDoc) ),
768 aMarkData ( rMark ),
769 bSize ( bNewSize ),
770 nFormatNo ( nNewFormatNo )
774 ScUndoAutoFormat::~ScUndoAutoFormat()
778 OUString ScUndoAutoFormat::GetComment() const
780 return ScResId( STR_UNDO_AUTOFORMAT ); //"Auto-Format"
783 void ScUndoAutoFormat::Undo()
785 BeginUndo();
787 ScDocument& rDoc = pDocShell->GetDocument();
789 SCTAB nTabCount = rDoc.GetTableCount();
790 rDoc.DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
791 aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(),
792 aMarkData, InsertDeleteFlags::ATTRIB );
793 ScRange aCopyRange = aBlockRange;
794 aCopyRange.aStart.SetTab(0);
795 aCopyRange.aEnd.SetTab(nTabCount-1);
796 pUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, false, rDoc, &aMarkData);
798 // cell heights and widths (InsertDeleteFlags::NONE)
799 if (bSize)
801 SCCOL nStartX = aBlockRange.aStart.Col();
802 SCROW nStartY = aBlockRange.aStart.Row();
803 SCTAB nStartZ = aBlockRange.aStart.Tab();
804 SCCOL nEndX = aBlockRange.aEnd.Col();
805 SCROW nEndY = aBlockRange.aEnd.Row();
806 SCTAB nEndZ = aBlockRange.aEnd.Tab();
808 pUndoDoc->CopyToDocument( nStartX, 0, 0, nEndX, rDoc.MaxRow(), nTabCount-1,
809 InsertDeleteFlags::NONE, false, rDoc, &aMarkData );
810 pUndoDoc->CopyToDocument( 0, nStartY, 0, rDoc.MaxCol(), nEndY, nTabCount-1,
811 InsertDeleteFlags::NONE, false, rDoc, &aMarkData );
812 pDocShell->PostPaint( 0, 0, nStartZ, rDoc.MaxCol(), rDoc.MaxRow(), nEndZ,
813 PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top, SC_PF_LINES );
815 else
816 pDocShell->PostPaint( aBlockRange, PaintPartFlags::Grid, SC_PF_LINES );
818 EndUndo();
821 void ScUndoAutoFormat::Redo()
823 BeginRedo();
825 ScDocument& rDoc = pDocShell->GetDocument();
827 SCCOL nStartX = aBlockRange.aStart.Col();
828 SCROW nStartY = aBlockRange.aStart.Row();
829 SCTAB nStartZ = aBlockRange.aStart.Tab();
830 SCCOL nEndX = aBlockRange.aEnd.Col();
831 SCROW nEndY = aBlockRange.aEnd.Row();
832 SCTAB nEndZ = aBlockRange.aEnd.Tab();
834 rDoc.AutoFormat( nStartX, nStartY, nEndX, nEndY, nFormatNo, aMarkData );
836 if (bSize)
838 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
839 Fraction aZoomX(1,1);
840 Fraction aZoomY = aZoomX;
841 double nPPTX,nPPTY;
842 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
843 if (pViewShell)
845 ScViewData& rData = pViewShell->GetViewData();
846 nPPTX = rData.GetPPTX();
847 nPPTY = rData.GetPPTY();
848 aZoomX = rData.GetZoomX();
849 aZoomY = rData.GetZoomY();
851 else
853 // Keep zoom at 100
854 nPPTX = ScGlobal::nScreenPPTX;
855 nPPTY = ScGlobal::nScreenPPTY;
858 sc::RowHeightContext aCxt(rDoc.MaxRow(), nPPTX, nPPTY, aZoomX, aZoomY, pVirtDev);
859 for (SCTAB nTab=nStartZ; nTab<=nEndZ; nTab++)
861 ScMarkData aDestMark(rDoc.GetSheetLimits());
862 aDestMark.SelectOneTable( nTab );
863 aDestMark.SetMarkArea( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) );
864 aDestMark.MarkToMulti();
866 // as SC_SIZE_VISOPT
867 for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
869 CRFlags nOld = rDoc.GetRowFlags(nRow,nTab);
870 bool bHidden = rDoc.RowHidden(nRow, nTab);
871 if ( !bHidden && ( nOld & CRFlags::ManualSize ) )
872 rDoc.SetRowFlags( nRow, nTab, nOld & ~CRFlags::ManualSize );
875 bool bChanged = rDoc.SetOptimalHeight(aCxt, nStartY, nEndY, nTab, true);
877 for (SCCOL nCol=nStartX; nCol<=nEndX; nCol++)
878 if (!rDoc.ColHidden(nCol, nTab))
880 sal_uInt16 nThisSize = STD_EXTRA_WIDTH + rDoc.GetOptimalColWidth( nCol, nTab,
881 pVirtDev, nPPTX, nPPTY, aZoomX, aZoomY, false/*bFormula*/,
882 &aDestMark );
883 rDoc.SetColWidth( nCol, nTab, nThisSize );
884 rDoc.ShowCol( nCol, nTab, true );
887 // tdf#76183: recalculate objects' positions
888 if (bChanged)
889 rDoc.SetDrawPageSize(nTab);
892 pDocShell->PostPaint( 0, 0, nStartZ,
893 rDoc.MaxCol(), rDoc.MaxRow(), nEndZ,
894 PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top, SC_PF_LINES);
896 else
897 pDocShell->PostPaint( aBlockRange, PaintPartFlags::Grid, SC_PF_LINES );
899 EndRedo();
902 void ScUndoAutoFormat::Repeat(SfxRepeatTarget& rTarget)
904 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
905 pViewTarget->GetViewShell()->AutoFormat( nFormatNo );
908 bool ScUndoAutoFormat::CanRepeat(SfxRepeatTarget& rTarget) const
910 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
913 ScUndoReplace::ScUndoReplace( ScDocShell* pNewDocShell, const ScMarkData& rMark,
914 SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
915 OUString aNewUndoStr, ScDocumentUniquePtr pNewUndoDoc,
916 const SvxSearchItem* pItem )
917 : ScSimpleUndo( pNewDocShell ),
918 aCursorPos ( nCurX, nCurY, nCurZ ),
919 aMarkData ( rMark ),
920 aUndoStr (std::move( aNewUndoStr )),
921 pUndoDoc ( std::move(pNewUndoDoc) )
923 pSearchItem.reset( new SvxSearchItem( *pItem ) );
924 SetChangeTrack();
927 ScUndoReplace::~ScUndoReplace()
929 pUndoDoc.reset();
930 pSearchItem.reset();
933 void ScUndoReplace::SetChangeTrack()
935 ScDocument& rDoc = pDocShell->GetDocument();
936 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
937 if ( pChangeTrack )
939 if ( pUndoDoc )
940 { //! UndoDoc includes only the changed cells,
941 // that is why an Iterator can be used
942 pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
943 nStartChangeAction, nEndChangeAction );
945 else
947 nStartChangeAction = pChangeTrack->GetActionMax() + 1;
948 ScChangeActionContent* pContent = new ScChangeActionContent(
949 ScRange( aCursorPos) );
950 ScCellValue aCell;
951 aCell.assign(rDoc, aCursorPos);
952 pContent->SetOldValue( aUndoStr, &rDoc );
953 pContent->SetNewValue(aCell, &rDoc);
954 pChangeTrack->Append( pContent );
955 nEndChangeAction = pChangeTrack->GetActionMax();
958 else
959 nStartChangeAction = nEndChangeAction = 0;
962 OUString ScUndoReplace::GetComment() const
964 return ScResId( STR_UNDO_REPLACE ); // "Replace"
967 void ScUndoReplace::Undo()
969 BeginUndo();
971 ScDocument& rDoc = pDocShell->GetDocument();
972 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
974 ShowTable( aCursorPos.Tab() );
976 if (pUndoDoc) // only for ReplaceAll !!
978 OSL_ENSURE(pSearchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL,
979 "ScUndoReplace:: Wrong Mode");
981 SetViewMarkData( aMarkData );
983 //! selected sheet
984 //! select range ?
986 // Undo document has no row/column information, thus copy with
987 // bColRowFlags = FALSE to not destroy Outline groups
989 InsertDeleteFlags nUndoFlags = (pSearchItem->GetPattern()) ? InsertDeleteFlags::ATTRIB : InsertDeleteFlags::CONTENTS;
990 pUndoDoc->CopyToDocument( 0, 0, 0,
991 rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB,
992 nUndoFlags, false, rDoc, nullptr, false ); // without row flags
993 pDocShell->PostPaintGridAll();
995 else if (pSearchItem->GetPattern() &&
996 pSearchItem->GetCommand() == SvxSearchCmd::REPLACE)
998 OUString aTempStr = pSearchItem->GetSearchString(); // toggle
999 pSearchItem->SetSearchString(pSearchItem->GetReplaceString());
1000 pSearchItem->SetReplaceString(aTempStr);
1001 rDoc.ReplaceStyle( *pSearchItem,
1002 aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
1003 aMarkData);
1004 pSearchItem->SetReplaceString(pSearchItem->GetSearchString());
1005 pSearchItem->SetSearchString(aTempStr);
1006 if (pViewShell)
1007 pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1008 SC_FOLLOW_JUMP, false, false );
1009 pDocShell->PostPaintGridAll();
1011 else if (pSearchItem->GetCellType() == SvxSearchCellType::NOTE)
1013 ScPostIt* pNote = rDoc.GetNote(aCursorPos);
1014 OSL_ENSURE( pNote, "ScUndoReplace::Undo - cell does not contain a note" );
1015 if (pNote)
1016 pNote->SetText( aCursorPos, aUndoStr );
1017 if (pViewShell)
1018 pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1019 SC_FOLLOW_JUMP, false, false );
1021 else
1023 // aUndoStr may contain line breaks
1024 if ( aUndoStr.indexOf('\n') != -1 )
1026 ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
1027 rEngine.SetTextCurrentDefaults(aUndoStr);
1028 rDoc.SetEditText(aCursorPos, rEngine.CreateTextObject());
1030 else
1031 rDoc.SetString( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aUndoStr );
1032 if (pViewShell)
1033 pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1034 SC_FOLLOW_JUMP, false, false );
1035 pDocShell->PostPaintGridAll();
1038 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
1039 if ( pChangeTrack )
1040 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1042 EndUndo();
1045 void ScUndoReplace::Redo()
1047 BeginRedo();
1049 ScDocument& rDoc = pDocShell->GetDocument();
1050 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1052 if (pViewShell)
1053 pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1054 SC_FOLLOW_JUMP, false, false );
1055 if (pUndoDoc)
1057 if (pViewShell)
1059 SetViewMarkData( aMarkData );
1061 pViewShell->SearchAndReplace( pSearchItem.get(), false, true );
1064 else if (pSearchItem->GetPattern() &&
1065 pSearchItem->GetCommand() == SvxSearchCmd::REPLACE)
1067 rDoc.ReplaceStyle( *pSearchItem,
1068 aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
1069 aMarkData);
1070 pDocShell->PostPaintGridAll();
1072 else
1073 if (pViewShell)
1074 pViewShell->SearchAndReplace( pSearchItem.get(), false, true );
1076 SetChangeTrack();
1078 EndRedo();
1081 void ScUndoReplace::Repeat(SfxRepeatTarget& rTarget)
1083 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1084 pViewTarget->GetViewShell()->SearchAndReplace( pSearchItem.get(), true, false );
1087 bool ScUndoReplace::CanRepeat(SfxRepeatTarget& rTarget) const
1089 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
1092 // multi-operation (only simple blocks)
1093 ScUndoTabOp::ScUndoTabOp( ScDocShell* pNewDocShell,
1094 SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
1095 SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, ScDocumentUniquePtr pNewUndoDoc,
1096 const ScRefAddress& rFormulaCell,
1097 const ScRefAddress& rFormulaEnd,
1098 const ScRefAddress& rRowCell,
1099 const ScRefAddress& rColCell,
1100 ScTabOpParam::Mode eMode )
1101 : ScSimpleUndo( pNewDocShell ),
1102 aRange ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
1103 pUndoDoc ( std::move(pNewUndoDoc) ),
1104 theFormulaCell ( rFormulaCell ),
1105 theFormulaEnd ( rFormulaEnd ),
1106 theRowCell ( rRowCell ),
1107 theColCell ( rColCell ),
1108 meMode(eMode)
1112 ScUndoTabOp::~ScUndoTabOp()
1116 OUString ScUndoTabOp::GetComment() const
1118 return ScResId( STR_UNDO_TABOP ); // "Multiple operation"
1121 void ScUndoTabOp::Undo()
1123 BeginUndo();
1125 ScUndoUtil::MarkSimpleBlock( pDocShell, aRange );
1127 sal_uInt16 nExtFlags = 0;
1128 pDocShell->UpdatePaintExt( nExtFlags, aRange );
1130 ScDocument& rDoc = pDocShell->GetDocument();
1131 rDoc.DeleteAreaTab( aRange,InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1132 pUndoDoc->CopyToDocument( aRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc );
1133 pDocShell->PostPaint( aRange, PaintPartFlags::Grid, nExtFlags );
1134 pDocShell->PostDataChanged();
1135 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1136 if (pViewShell)
1137 pViewShell->CellContentChanged();
1139 EndUndo();
1142 void ScUndoTabOp::Redo()
1144 BeginRedo();
1146 ScUndoUtil::MarkSimpleBlock( pDocShell, aRange );
1148 ScTabOpParam aParam(theFormulaCell, theFormulaEnd, theRowCell, theColCell, meMode);
1150 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1151 if (pViewShell)
1152 pViewShell->TabOp( aParam, false);
1154 EndRedo();
1157 void ScUndoTabOp::Repeat(SfxRepeatTarget& /* rTarget */)
1161 bool ScUndoTabOp::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1163 return false;
1166 ScUndoConversion::ScUndoConversion(
1167 ScDocShell* pNewDocShell, const ScMarkData& rMark,
1168 SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScDocumentUniquePtr pNewUndoDoc,
1169 SCCOL nNewX, SCROW nNewY, SCTAB nNewZ, ScDocumentUniquePtr pNewRedoDoc,
1170 ScConversionParam aConvParam ) :
1171 ScSimpleUndo( pNewDocShell ),
1172 aMarkData( rMark ),
1173 aCursorPos( nCurX, nCurY, nCurZ ),
1174 pUndoDoc( std::move(pNewUndoDoc) ),
1175 aNewCursorPos( nNewX, nNewY, nNewZ ),
1176 pRedoDoc( std::move(pNewRedoDoc) ),
1177 maConvParam(std::move( aConvParam ))
1179 SetChangeTrack();
1182 ScUndoConversion::~ScUndoConversion()
1184 pUndoDoc.reset();
1185 pRedoDoc.reset();
1188 void ScUndoConversion::SetChangeTrack()
1190 ScDocument& rDoc = pDocShell->GetDocument();
1191 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
1192 if ( pChangeTrack )
1194 if ( pUndoDoc )
1195 pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
1196 nStartChangeAction, nEndChangeAction );
1197 else
1199 OSL_FAIL( "ScUndoConversion::SetChangeTrack: no UndoDoc" );
1200 nStartChangeAction = nEndChangeAction = 0;
1203 else
1204 nStartChangeAction = nEndChangeAction = 0;
1207 OUString ScUndoConversion::GetComment() const
1209 OUString aText;
1210 switch( maConvParam.GetType() )
1212 case SC_CONVERSION_SPELLCHECK: aText = ScResId( STR_UNDO_SPELLING ); break;
1213 case SC_CONVERSION_HANGULHANJA: aText = ScResId( STR_UNDO_HANGULHANJA ); break;
1214 case SC_CONVERSION_CHINESE_TRANSL: aText = ScResId( STR_UNDO_CHINESE_TRANSLATION ); break;
1216 return aText;
1219 void ScUndoConversion::DoChange( ScDocument* pRefDoc, const ScAddress& rCursorPos )
1221 if (pRefDoc)
1223 ScDocument& rDoc = pDocShell->GetDocument();
1224 ShowTable( rCursorPos.Tab() );
1226 SetViewMarkData( aMarkData );
1228 SCTAB nTabCount = rDoc.GetTableCount();
1229 // Undo/Redo-doc has only selected tables
1231 bool bMulti = aMarkData.IsMultiMarked();
1232 pRefDoc->CopyToDocument( 0, 0, 0,
1233 rDoc.MaxCol(), rDoc.MaxRow(), nTabCount-1,
1234 InsertDeleteFlags::CONTENTS, bMulti, rDoc, &aMarkData );
1236 // Reset the spell checking results to re-check on paint, otherwise
1237 // we show the previous spelling markers (or lack thereof on misspellings).
1238 if (ScViewData* pViewData = ScDocShell::GetViewData())
1239 pViewData->GetActiveWin()->ResetAutoSpell();
1240 pDocShell->PostPaintGridAll();
1242 else
1244 OSL_FAIL("no Un-/RedoDoc for Un-/RedoSpelling");
1248 void ScUndoConversion::Undo()
1250 BeginUndo();
1251 DoChange( pUndoDoc.get(), aCursorPos );
1252 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
1253 if ( pChangeTrack )
1254 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1255 EndUndo();
1258 void ScUndoConversion::Redo()
1260 BeginRedo();
1261 DoChange( pRedoDoc.get(), aNewCursorPos );
1262 SetChangeTrack();
1263 EndRedo();
1266 void ScUndoConversion::Repeat( SfxRepeatTarget& rTarget )
1268 if( auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget) )
1269 pViewTarget->GetViewShell()->DoSheetConversion( maConvParam );
1272 bool ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const
1274 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
1277 ScUndoRefConversion::ScUndoRefConversion( ScDocShell* pNewDocShell,
1278 const ScRange& aMarkRange, const ScMarkData& rMark,
1279 ScDocumentUniquePtr pNewUndoDoc, ScDocumentUniquePtr pNewRedoDoc, bool bNewMulti) :
1280 ScSimpleUndo( pNewDocShell ),
1281 aMarkData ( rMark ),
1282 pUndoDoc ( std::move(pNewUndoDoc) ),
1283 pRedoDoc ( std::move(pNewRedoDoc) ),
1284 aRange ( aMarkRange ),
1285 bMulti ( bNewMulti )
1287 assert(pUndoDoc && pRedoDoc);
1288 SetChangeTrack();
1291 ScUndoRefConversion::~ScUndoRefConversion()
1293 pUndoDoc.reset();
1294 pRedoDoc.reset();
1297 OUString ScUndoRefConversion::GetComment() const
1299 return ScResId( STR_UNDO_ENTERDATA ); // "Input"
1302 void ScUndoRefConversion::SetChangeTrack()
1304 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
1305 if ( pChangeTrack )
1306 pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
1307 nStartChangeAction, nEndChangeAction );
1308 else
1309 nStartChangeAction = nEndChangeAction = 0;
1312 void ScUndoRefConversion::DoChange( ScDocument* pRefDoc)
1314 ScDocument& rDoc = pDocShell->GetDocument();
1316 ShowTable(aRange);
1318 SetViewMarkData( aMarkData );
1320 ScRange aCopyRange = aRange;
1321 SCTAB nTabCount = rDoc.GetTableCount();
1322 aCopyRange.aStart.SetTab(0);
1323 aCopyRange.aEnd.SetTab(nTabCount-1);
1324 pRefDoc->CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, rDoc, &aMarkData );
1325 pDocShell->PostPaint( aRange, PaintPartFlags::Grid);
1326 pDocShell->PostDataChanged();
1327 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1328 if (pViewShell)
1329 pViewShell->CellContentChanged();
1332 void ScUndoRefConversion::Undo()
1334 BeginUndo();
1335 if (pUndoDoc)
1336 DoChange(pUndoDoc.get());
1337 ScChangeTrack* pChangeTrack = pDocShell->GetDocument().GetChangeTrack();
1338 if ( pChangeTrack )
1339 pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1340 EndUndo();
1343 void ScUndoRefConversion::Redo()
1345 BeginRedo();
1346 if (pRedoDoc)
1347 DoChange(pRedoDoc.get());
1348 SetChangeTrack();
1349 EndRedo();
1352 void ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget)
1354 if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1355 pViewTarget->GetViewShell()->DoRefConversion();
1358 bool ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const
1360 return dynamic_cast<const ScTabViewTarget*>( &rTarget) != nullptr;
1363 ScUndoRefreshLink::ScUndoRefreshLink(ScDocShell* pNewDocShell,
1364 ScDocumentUniquePtr pNewUndoDoc)
1365 : ScSimpleUndo(pNewDocShell)
1366 , xUndoDoc(std::move(pNewUndoDoc))
1370 OUString ScUndoRefreshLink::GetComment() const
1372 return ScResId( STR_UNDO_UPDATELINK );
1375 void ScUndoRefreshLink::Undo()
1377 BeginUndo();
1379 bool bMakeRedo = !xRedoDoc;
1380 if (bMakeRedo)
1381 xRedoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1383 bool bFirst = true;
1384 ScDocument& rDoc = pDocShell->GetDocument();
1385 SCTAB nCount = rDoc.GetTableCount();
1386 for (SCTAB nTab=0; nTab<nCount; nTab++)
1387 if (xUndoDoc->HasTable(nTab))
1389 ScRange aRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab);
1390 if (bMakeRedo)
1392 if (bFirst)
1393 xRedoDoc->InitUndo(rDoc, nTab, nTab, true, true);
1394 else
1395 xRedoDoc->AddUndoTab(nTab, nTab, true, true);
1396 bFirst = false;
1397 rDoc.CopyToDocument(aRange, InsertDeleteFlags::ALL, false, *xRedoDoc);
1398 xRedoDoc->SetLink(nTab,
1399 rDoc.GetLinkMode(nTab),
1400 rDoc.GetLinkDoc(nTab),
1401 rDoc.GetLinkFlt(nTab),
1402 rDoc.GetLinkOpt(nTab),
1403 rDoc.GetLinkTab(nTab),
1404 rDoc.GetLinkRefreshDelay(nTab));
1405 xRedoDoc->SetTabBgColor( nTab, rDoc.GetTabBgColor(nTab) );
1408 rDoc.DeleteAreaTab( aRange,InsertDeleteFlags::ALL );
1409 xUndoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL, false, rDoc);
1410 rDoc.SetLink(nTab, xUndoDoc->GetLinkMode(nTab), xUndoDoc->GetLinkDoc(nTab),
1411 xUndoDoc->GetLinkFlt(nTab), xUndoDoc->GetLinkOpt(nTab),
1412 xUndoDoc->GetLinkTab(nTab),
1413 xUndoDoc->GetLinkRefreshDelay(nTab) );
1414 rDoc.SetTabBgColor(nTab, xUndoDoc->GetTabBgColor(nTab));
1417 pDocShell->PostPaintGridAll();
1418 pDocShell->PostPaintExtras();
1420 EndUndo();
1423 void ScUndoRefreshLink::Redo()
1425 OSL_ENSURE(xRedoDoc, "No RedoDoc for ScUndoRefreshLink::Redo");
1427 BeginUndo();
1429 ScDocument& rDoc = pDocShell->GetDocument();
1430 SCTAB nCount = rDoc.GetTableCount();
1431 for (SCTAB nTab=0; nTab<nCount; nTab++)
1432 if (xRedoDoc->HasTable(nTab))
1434 ScRange aRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab);
1436 rDoc.DeleteAreaTab( aRange, InsertDeleteFlags::ALL );
1437 xRedoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL, false, rDoc);
1438 rDoc.SetLink(nTab,
1439 xRedoDoc->GetLinkMode(nTab),
1440 xRedoDoc->GetLinkDoc(nTab),
1441 xRedoDoc->GetLinkFlt(nTab),
1442 xRedoDoc->GetLinkOpt(nTab),
1443 xRedoDoc->GetLinkTab(nTab),
1444 xRedoDoc->GetLinkRefreshDelay(nTab) );
1445 rDoc.SetTabBgColor(nTab, xRedoDoc->GetTabBgColor(nTab));
1448 pDocShell->PostPaintGridAll();
1449 pDocShell->PostPaintExtras();
1451 EndUndo();
1454 void ScUndoRefreshLink::Repeat(SfxRepeatTarget& /* rTarget */)
1456 // makes no sense
1459 bool ScUndoRefreshLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1461 return false;
1464 static ScAreaLink* lcl_FindAreaLink( const sfx2::LinkManager* pLinkManager, std::u16string_view rDoc,
1465 std::u16string_view rFlt, std::u16string_view rOpt,
1466 std::u16string_view rSrc, const ScRange& rDest )
1468 const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1469 sal_uInt16 nCount = pLinkManager->GetLinks().size();
1470 for (sal_uInt16 i=0; i<nCount; i++)
1472 ::sfx2::SvBaseLink* pBase = rLinks[i].get();
1473 if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
1474 if ( pAreaLink->IsEqual( rDoc, rFlt, rOpt, rSrc, rDest ) )
1475 return pAreaLink;
1478 OSL_FAIL("ScAreaLink not found");
1479 return nullptr;
1482 ScUndoInsertAreaLink::ScUndoInsertAreaLink( ScDocShell* pShell,
1483 OUString aDoc,
1484 OUString aFlt, OUString aOpt,
1485 OUString aArea, const ScRange& rDestRange,
1486 sal_uLong nRefresh )
1487 : ScSimpleUndo ( pShell ),
1488 aDocName (std::move( aDoc )),
1489 aFltName (std::move( aFlt )),
1490 aOptions (std::move( aOpt )),
1491 aAreaName (std::move( aArea )),
1492 aRange ( rDestRange ),
1493 nRefreshDelay ( nRefresh )
1497 ScUndoInsertAreaLink::~ScUndoInsertAreaLink()
1501 OUString ScUndoInsertAreaLink::GetComment() const
1503 return ScResId( STR_UNDO_INSERTAREALINK );
1506 void ScUndoInsertAreaLink::Undo()
1508 ScDocument& rDoc = pDocShell->GetDocument();
1509 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1511 ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions,
1512 aAreaName, aRange );
1513 if (pLink)
1514 pLinkManager->Remove( pLink );
1516 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); // Navigator
1519 void ScUndoInsertAreaLink::Redo()
1521 ScDocument& rDoc = pDocShell->GetDocument();
1522 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1524 ScAreaLink* pLink = new ScAreaLink( pDocShell, aDocName, aFltName, aOptions,
1525 aAreaName, ScRange(aRange.aStart), nRefreshDelay );
1526 pLink->SetInCreate( true );
1527 pLink->SetDestArea( aRange );
1528 pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, aDocName, &aFltName, &aAreaName );
1529 pLink->Update();
1530 pLink->SetInCreate( false );
1532 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); // Navigator
1535 void ScUndoInsertAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1537 // makes no sense
1540 bool ScUndoInsertAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1542 return false;
1545 ScUndoRemoveAreaLink::ScUndoRemoveAreaLink( ScDocShell* pShell,
1546 OUString aDoc, OUString aFlt, OUString aOpt,
1547 OUString aArea, const ScRange& rDestRange,
1548 sal_uLong nRefresh )
1549 : ScSimpleUndo ( pShell ),
1550 aDocName (std::move( aDoc )),
1551 aFltName (std::move( aFlt )),
1552 aOptions (std::move( aOpt )),
1553 aAreaName (std::move( aArea )),
1554 aRange ( rDestRange ),
1555 nRefreshDelay ( nRefresh )
1559 ScUndoRemoveAreaLink::~ScUndoRemoveAreaLink()
1563 OUString ScUndoRemoveAreaLink::GetComment() const
1565 return ScResId( STR_UNDO_REMOVELINK ); //! own text ??
1568 void ScUndoRemoveAreaLink::Undo()
1570 ScDocument& rDoc = pDocShell->GetDocument();
1571 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1573 ScAreaLink* pLink = new ScAreaLink( pDocShell, aDocName, aFltName, aOptions,
1574 aAreaName, ScRange(aRange.aStart), nRefreshDelay );
1575 pLink->SetInCreate( true );
1576 pLink->SetDestArea( aRange );
1577 pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, aDocName, &aFltName, &aAreaName );
1578 pLink->Update();
1579 pLink->SetInCreate( false );
1581 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); // Navigator
1584 void ScUndoRemoveAreaLink::Redo()
1586 ScDocument& rDoc = pDocShell->GetDocument();
1587 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1589 ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions,
1590 aAreaName, aRange );
1591 if (pLink)
1592 pLinkManager->Remove( pLink );
1594 SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) ); // Navigator
1597 void ScUndoRemoveAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1599 // makes no sense
1602 bool ScUndoRemoveAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1604 return false;
1607 ScUndoUpdateAreaLink::ScUndoUpdateAreaLink( ScDocShell* pShell,
1608 OUString aOldD, OUString aOldF, OUString aOldO,
1609 OUString aOldA, const ScRange& rOldR, sal_uLong nOldRD,
1610 OUString aNewD, OUString aNewF, OUString aNewO,
1611 OUString aNewA, const ScRange& rNewR, sal_uLong nNewRD,
1612 ScDocumentUniquePtr pUndo, ScDocumentUniquePtr pRedo, bool bDoInsert )
1613 : ScSimpleUndo( pShell ),
1614 aOldDoc (std::move( aOldD )),
1615 aOldFlt (std::move( aOldF )),
1616 aOldOpt (std::move( aOldO )),
1617 aOldArea (std::move( aOldA )),
1618 aOldRange ( rOldR ),
1619 aNewDoc (std::move( aNewD )),
1620 aNewFlt (std::move( aNewF )),
1621 aNewOpt (std::move( aNewO )),
1622 aNewArea (std::move( aNewA )),
1623 aNewRange ( rNewR ),
1624 xUndoDoc ( std::move(pUndo) ),
1625 xRedoDoc ( std::move(pRedo) ),
1626 nOldRefresh ( nOldRD ),
1627 nNewRefresh ( nNewRD ),
1628 bWithInsert ( bDoInsert )
1630 OSL_ENSURE( aOldRange.aStart == aNewRange.aStart, "AreaLink moved ?" );
1633 OUString ScUndoUpdateAreaLink::GetComment() const
1635 return ScResId( STR_UNDO_UPDATELINK ); //! own text ??
1638 void ScUndoUpdateAreaLink::DoChange( const bool bUndo ) const
1640 ScDocument& rDoc = pDocShell->GetDocument();
1642 SCCOL nEndX = std::max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() );
1643 SCROW nEndY = std::max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() );
1644 SCTAB nEndZ = std::max( aOldRange.aEnd.Tab(), aNewRange.aEnd.Tab() ); //?
1646 if ( bUndo )
1648 if ( bWithInsert )
1650 rDoc.FitBlock( aNewRange, aOldRange );
1651 rDoc.DeleteAreaTab( aOldRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1652 xUndoDoc->UndoToDocument(aOldRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1654 else
1656 ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) );
1657 rDoc.DeleteAreaTab( aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1658 xUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1661 else
1663 if ( bWithInsert )
1665 rDoc.FitBlock( aOldRange, aNewRange );
1666 rDoc.DeleteAreaTab( aNewRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1667 xRedoDoc->CopyToDocument(aNewRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1669 else
1671 ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) );
1672 rDoc.DeleteAreaTab( aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1673 xRedoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1677 ScRange aWorkRange( aNewRange.aStart, ScAddress( nEndX, nEndY, nEndZ ) );
1678 rDoc.ExtendMerge( aWorkRange, true );
1680 // Paint
1682 if ( aNewRange.aEnd.Col() != aOldRange.aEnd.Col() )
1683 aWorkRange.aEnd.SetCol(rDoc.MaxCol());
1684 if ( aNewRange.aEnd.Row() != aOldRange.aEnd.Row() )
1685 aWorkRange.aEnd.SetRow(rDoc.MaxRow());
1687 if ( !pDocShell->AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), aWorkRange.aStart.Tab() ) )
1688 pDocShell->PostPaint( aWorkRange, PaintPartFlags::Grid );
1690 pDocShell->PostDataChanged();
1691 ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1692 if (pViewShell)
1693 pViewShell->CellContentChanged();
1696 void ScUndoUpdateAreaLink::Undo()
1698 ScDocument& rDoc = pDocShell->GetDocument();
1699 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1700 ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aNewDoc, aNewFlt, aNewOpt,
1701 aNewArea, aNewRange );
1702 if (pLink)
1704 pLink->SetSource( aOldDoc, aOldFlt, aOldOpt, aOldArea ); // old data in Link
1705 pLink->SetDestArea( aOldRange );
1706 pLink->SetRefreshDelay( nOldRefresh );
1709 DoChange(true);
1712 void ScUndoUpdateAreaLink::Redo()
1714 ScDocument& rDoc = pDocShell->GetDocument();
1715 sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1716 ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aOldDoc, aOldFlt, aOldOpt,
1717 aOldArea, aOldRange );
1718 if (pLink)
1720 pLink->SetSource( aNewDoc, aNewFlt, aNewOpt, aNewArea ); // new values in link
1721 pLink->SetDestArea( aNewRange );
1722 pLink->SetRefreshDelay( nNewRefresh );
1725 DoChange(false);
1728 void ScUndoUpdateAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1730 // makes no sense
1733 bool ScUndoUpdateAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1735 return false;
1738 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */