Coverage Report

Created: 2026-06-30 11:14

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/undo/undoblk3.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <memory>
23
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>
34
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>
55
56
// TODO:
57
/*A*/   // SetOptimalHeight on Document, when no View
58
59
ScUndoDeleteContents::ScUndoDeleteContents(
60
                ScDocShell& rNewDocShell,
61
                const ScMarkData& rMark, const ScRange& rRange,
62
                ScDocumentUniquePtr&& pNewUndoDoc, bool bNewMulti,
63
                InsertDeleteFlags nNewFlags, bool bObjects )
64
0
    :   ScSimpleUndo( rNewDocShell ),
65
0
        aRange      ( rRange ),
66
0
        aMarkData   ( rMark ),
67
0
        pUndoDoc    ( std::move(pNewUndoDoc) ),
68
0
        nFlags      ( nNewFlags ),
69
0
        bMulti      ( bNewMulti )   // unnecessary
70
0
{
71
0
    if (bObjects)
72
0
        pDrawUndo = GetSdrUndoAction( &rDocShell.GetDocument() );
73
74
0
    if ( !(aMarkData.IsMarked() || aMarkData.IsMultiMarked()) )     // if no cell is selected:
75
0
        aMarkData.SetMarkArea( aRange );                            // select cell under cursor
76
77
0
    SetChangeTrack();
78
0
}
79
80
ScUndoDeleteContents::~ScUndoDeleteContents()
81
0
{
82
0
    pUndoDoc.reset();
83
0
    pDrawUndo.reset();
84
0
}
85
86
OUString ScUndoDeleteContents::GetComment() const
87
0
{
88
0
    return ScResId( STR_UNDO_DELETECONTENTS );    // "Delete"
89
0
}
90
91
void ScUndoDeleteContents::SetDataSpans( const std::shared_ptr<DataSpansType>& pSpans )
92
0
{
93
0
    mpDataSpans = pSpans;
94
0
}
95
96
void ScUndoDeleteContents::SetRestoreExpandedMatrices(std::vector<ScAddress> const& rPositions)
97
0
{
98
0
    maRestoreExpandedMatrices = rPositions;
99
0
}
100
101
void ScUndoDeleteContents::SetChangeTrack()
102
0
{
103
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
104
0
    if ( pChangeTrack && (nFlags & InsertDeleteFlags::CONTENTS) )
105
0
        pChangeTrack->AppendContentRange( aRange, *pUndoDoc,
106
0
            nStartChangeAction, nEndChangeAction );
107
0
    else
108
0
        nStartChangeAction = nEndChangeAction = 0;
109
0
}
110
111
void ScUndoDeleteContents::DoChange( const bool bUndo )
112
0
{
113
0
    ScDocument& rDoc = rDocShell.GetDocument();
114
115
0
    SetViewMarkData( aMarkData );
116
117
0
    sal_uInt16 nExtFlags = 0;
118
119
0
    if (bUndo)  // only Undo
120
0
    {
121
0
        InsertDeleteFlags nUndoFlags = InsertDeleteFlags::NONE; // copy either all or none of the content
122
0
        if (nFlags & InsertDeleteFlags::CONTENTS)        // (Only the correct ones have been copied into UndoDoc)
123
0
            nUndoFlags |= InsertDeleteFlags::CONTENTS;
124
0
        if (nFlags & InsertDeleteFlags::ATTRIB)
125
0
            nUndoFlags |= InsertDeleteFlags::ATTRIB;
126
0
        if (nFlags & InsertDeleteFlags::EDITATTR)          // Edit-Engine attribute
127
0
            nUndoFlags |= InsertDeleteFlags::STRING;       // -> Cells will be changed
128
0
        if (nFlags & InsertDeleteFlags::SPARKLINES)
129
0
            nUndoFlags |= InsertDeleteFlags::SPARKLINES;
130
        // do not create clones of note captions, they will be restored via drawing undo
131
0
        nUndoFlags |= InsertDeleteFlags::NOCAPTIONS;
132
133
0
        ScRange aCopyRange = aRange;
134
0
        SCTAB nTabCount = rDoc.GetTableCount();
135
0
        aCopyRange.aStart.SetTab(0);
136
0
        aCopyRange.aEnd.SetTab(nTabCount-1);
137
138
0
        pUndoDoc->CopyToDocument(aCopyRange, nUndoFlags, bMulti, rDoc, &aMarkData);
139
140
        // Restore the document-level matrix tracking. Re-add any multi-cell 
141
        // matrix masters captured before the delete.
142
0
        for (const ScAddress& rPosition : maRestoreExpandedMatrices)
143
0
            rDoc.MarkExpandedDynamicArray(rPosition);
144
145
0
        DoSdrUndoAction( pDrawUndo.get(), &rDoc );
146
147
0
        ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
148
0
        if ( pChangeTrack )
149
0
            pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
150
151
0
        rDocShell.UpdatePaintExt( nExtFlags, aRange );             // content after the change
152
0
    }
153
0
    else        // only Redo
154
0
    {
155
0
        rDocShell.UpdatePaintExt( nExtFlags, aRange );             // content before the change
156
157
0
        aMarkData.MarkToMulti();
158
0
        RedoSdrUndoAction( pDrawUndo.get() );
159
        // do not delete objects and note captions, they have been removed via drawing undo
160
0
        InsertDeleteFlags nRedoFlags = (nFlags & ~InsertDeleteFlags::OBJECTS) | InsertDeleteFlags::NOCAPTIONS;
161
0
        rDoc.DeleteSelection( nRedoFlags, aMarkData );
162
0
        aMarkData.MarkToSimple();
163
164
0
        SetChangeTrack();
165
0
    }
166
167
0
    if (nFlags & InsertDeleteFlags::CONTENTS)
168
0
    {
169
        // Broadcast only when the content changes. fdo#74687
170
0
        if (mpDataSpans)
171
0
            BroadcastChanges(*mpDataSpans);
172
0
        else
173
0
            BroadcastChanges(aRange);
174
0
    }
175
176
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
177
0
    if ( !( pViewShell && pViewShell->AdjustRowHeight(
178
0
                                aRange.aStart.Row(), aRange.aEnd.Row(), true ) ) )
179
0
/*A*/   rDocShell.PostPaint( aRange, PaintPartFlags::Grid | PaintPartFlags::Extras, nExtFlags );
180
181
0
    if (pViewShell)
182
0
        pViewShell->CellContentChanged();
183
184
0
    ShowTable( aRange );
185
0
}
186
187
void ScUndoDeleteContents::Undo()
188
0
{
189
0
    BeginUndo();
190
0
    DoChange( true );
191
0
    EndUndo();
192
193
    // Need to replay spill resolution so an undo that restored a blocker
194
    // re-spills the affected dynamic array master, and an undo that cleared
195
    // a blocker expands it.
196
0
    rDocShell.ResolveSpilledOutputs();
197
198
0
    HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, aRange, u"undo"_ustr);
199
0
}
200
201
void ScUndoDeleteContents::Redo()
202
0
{
203
0
    BeginRedo();
204
0
    DoChange( false );
205
0
    EndRedo();
206
207
0
    rDocShell.ResolveSpilledOutputs();
208
209
0
    HelperNotifyChanges::NotifyIfChangesListeners(rDocShell, aRange, u"redo"_ustr);
210
0
}
211
212
void ScUndoDeleteContents::Repeat(SfxRepeatTarget& rTarget)
213
0
{
214
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
215
0
        pViewTarget->GetViewShell().DeleteContents( nFlags );
216
0
}
217
218
bool ScUndoDeleteContents::CanRepeat(SfxRepeatTarget& rTarget) const
219
0
{
220
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
221
0
}
222
223
ScUndoFillTable::ScUndoFillTable( ScDocShell& rNewDocShell,
224
                const ScMarkData& rMark,
225
                SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
226
                SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
227
                ScDocumentUniquePtr pNewUndoDoc, bool bNewMulti, SCTAB nSrc,
228
                InsertDeleteFlags nFlg, ScPasteFunc nFunc, bool bSkip, bool bLink )
229
0
    :   ScSimpleUndo( rNewDocShell ),
230
0
        aRange      ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
231
0
        aMarkData   ( rMark ),
232
0
        pUndoDoc    ( std::move(pNewUndoDoc) ),
233
0
        nFlags      ( nFlg ),
234
0
        nFunction   ( nFunc ),
235
0
        nSrcTab     ( nSrc ),
236
0
        bMulti      ( bNewMulti ),
237
0
        bSkipEmpty  ( bSkip ),
238
0
        bAsLink     ( bLink )
239
0
{
240
0
    SetChangeTrack();
241
0
}
242
243
ScUndoFillTable::~ScUndoFillTable()
244
0
{
245
0
}
246
247
OUString ScUndoFillTable::GetComment() const
248
0
{
249
0
    return ScResId( STR_FILL_TAB );
250
0
}
251
252
void ScUndoFillTable::SetChangeTrack()
253
0
{
254
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
255
0
    if ( pChangeTrack )
256
0
    {
257
0
        SCTAB nTabCount = rDocShell.GetDocument().GetTableCount();
258
0
        ScRange aWorkRange(aRange);
259
0
        nStartChangeAction = 0;
260
0
        sal_uLong nTmpAction;
261
0
        for (const auto& rTab : aMarkData)
262
0
        {
263
0
            if (rTab >= nTabCount)
264
0
                break;
265
0
            if (rTab != nSrcTab)
266
0
            {
267
0
                aWorkRange.aStart.SetTab(rTab);
268
0
                aWorkRange.aEnd.SetTab(rTab);
269
0
                pChangeTrack->AppendContentRange( aWorkRange, *pUndoDoc,
270
0
                    nTmpAction, nEndChangeAction );
271
0
                if ( !nStartChangeAction )
272
0
                    nStartChangeAction = nTmpAction;
273
0
            }
274
0
        }
275
0
    }
276
0
    else
277
0
        nStartChangeAction = nEndChangeAction = 0;
278
0
}
279
280
void ScUndoFillTable::DoChange( const bool bUndo )
281
0
{
282
0
    ScDocument& rDoc = rDocShell.GetDocument();
283
284
0
    SetViewMarkData( aMarkData );
285
286
0
    if (bUndo)  // only Undo
287
0
    {
288
0
        SCTAB nTabCount = rDoc.GetTableCount();
289
0
        ScRange aWorkRange(aRange);
290
0
        for (const auto& rTab : aMarkData)
291
0
        {
292
0
            if (rTab >= nTabCount)
293
0
                break;
294
0
            if (rTab != nSrcTab)
295
0
            {
296
0
                aWorkRange.aStart.SetTab(rTab);
297
0
                aWorkRange.aEnd.SetTab(rTab);
298
0
                if (bMulti)
299
0
                    rDoc.DeleteSelectionTab( rTab, InsertDeleteFlags::ALL, aMarkData );
300
0
                else
301
0
                    rDoc.DeleteAreaTab( aWorkRange, InsertDeleteFlags::ALL );
302
0
                pUndoDoc->CopyToDocument(aWorkRange, InsertDeleteFlags::ALL, bMulti, rDoc, &aMarkData);
303
0
            }
304
0
        }
305
306
0
        ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
307
0
        if ( pChangeTrack )
308
0
            pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
309
0
    }
310
0
    else        // only Redo
311
0
    {
312
0
        aMarkData.MarkToMulti();
313
0
        rDoc.FillTabMarked( nSrcTab, aMarkData, nFlags, nFunction, bSkipEmpty, bAsLink );
314
0
        aMarkData.MarkToSimple();
315
0
        SetChangeTrack();
316
0
    }
317
318
0
    rDocShell.PostPaint(0,0,0,rDoc.MaxCol(),rDoc.MaxRow(),MAXTAB, PaintPartFlags::Grid|PaintPartFlags::Extras);
319
0
    rDocShell.PostDataChanged();
320
321
    //  CellContentChanged comes with the selection
322
323
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
324
0
    if (pViewShell)
325
0
    {
326
0
        SCTAB nTab = pViewShell->GetViewData().CurrentTabForData();
327
0
        if ( !aMarkData.GetTableSelect(nTab) )
328
0
            pViewShell->SetTabNo( nSrcTab );
329
330
0
        pViewShell->DoneBlockMode();    // causes problems otherwise since selection is on the wrong sheet.
331
0
    }
332
0
}
333
334
void ScUndoFillTable::Undo()
335
0
{
336
0
    BeginUndo();
337
0
    DoChange( true );
338
0
    EndUndo();
339
0
}
340
341
void ScUndoFillTable::Redo()
342
0
{
343
0
    BeginRedo();
344
0
    DoChange( false );
345
0
    EndRedo();
346
0
}
347
348
void ScUndoFillTable::Repeat(SfxRepeatTarget& rTarget)
349
0
{
350
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
351
0
        pViewTarget->GetViewShell().FillTab( nFlags, nFunction, bSkipEmpty, bAsLink );
352
0
}
353
354
bool ScUndoFillTable::CanRepeat(SfxRepeatTarget& rTarget) const
355
0
{
356
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
357
0
}
358
359
ScUndoSelectionAttr::ScUndoSelectionAttr( ScDocShell& rNewDocShell,
360
                const ScMarkData& rMark,
361
                SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
362
                SCCOL nEndX, SCROW nEndY, SCTAB nEndZ,
363
                ScDocumentUniquePtr pNewUndoDoc, bool bNewMulti,
364
                const ScPatternAttr* pNewApply,
365
                const SvxBoxItem* pNewOuter, const SvxBoxInfoItem* pNewInner,
366
                const ScRange* pRangeCover )
367
0
    :   ScSimpleUndo( rNewDocShell ),
368
0
        aMarkData   ( rMark ),
369
0
        aRange      ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
370
0
        mpDataArray(new ScEditDataArray),
371
0
        pUndoDoc    ( std::move(pNewUndoDoc) ),
372
0
        bMulti      ( bNewMulti ),
373
0
        aApplyPattern( pNewApply ),
374
0
        maLineOuter(*rDocShell.GetDocument().GetPool(), pNewOuter),
375
0
        maLineInner(*rDocShell.GetDocument().GetPool(), pNewInner)
376
0
{
377
0
    aRangeCover = pRangeCover ? *pRangeCover : aRange;
378
0
}
379
380
ScUndoSelectionAttr::~ScUndoSelectionAttr()
381
0
{
382
0
    pUndoDoc.reset();
383
0
}
384
385
OUString ScUndoSelectionAttr::GetComment() const
386
0
{
387
    //"Attribute" "/Lines"
388
0
    return ScResId( maLineOuter.getItem() ? STR_UNDO_SELATTRLINES : STR_UNDO_SELATTR );
389
0
}
390
391
ScEditDataArray* ScUndoSelectionAttr::GetDataArray()
392
0
{
393
0
    return mpDataArray.get();
394
0
}
395
396
void ScUndoSelectionAttr::DoChange( const bool bUndo )
397
0
{
398
0
    ScDocument& rDoc = rDocShell.GetDocument();
399
400
0
    SetViewMarkData( aMarkData );
401
402
0
    ScRange aEffRange( aRangeCover );
403
0
    if ( rDoc.HasAttrib( aEffRange, HasAttrFlags::Merged ) )         // merged cells?
404
0
        rDoc.ExtendMerge( aEffRange );
405
406
0
    sal_uInt16 nExtFlags = 0;
407
0
    rDocShell.UpdatePaintExt( nExtFlags, aEffRange );
408
409
0
    ChangeEditData(bUndo);
410
411
0
    if (bUndo)  // only for Undo
412
0
    {
413
0
        ScRange aCopyRange = aRangeCover;
414
0
        SCTAB nTabCount = rDoc.GetTableCount();
415
0
        aCopyRange.aStart.SetTab(0);
416
0
        aCopyRange.aEnd.SetTab(nTabCount-1);
417
0
        pUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, bMulti, rDoc, &aMarkData);
418
0
    }
419
0
    else        // only for Redo
420
0
    {
421
0
        aMarkData.MarkToMulti();
422
0
        rDoc.ApplySelectionPattern( *aApplyPattern.getScPatternAttr(), aMarkData );
423
0
        aMarkData.MarkToSimple();
424
425
0
        if (maLineOuter.getItem())
426
0
            rDoc.ApplySelectionFrame(aMarkData,
427
0
                *static_cast<const SvxBoxItem*>(maLineOuter.getItem()),
428
0
                static_cast<const SvxBoxInfoItem*>(maLineInner.getItem()));
429
0
    }
430
431
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
432
0
    if ( !( pViewShell && pViewShell->AdjustBlockHeight() ) )
433
0
/*A*/   rDocShell.PostPaint( aEffRange, PaintPartFlags::Grid | PaintPartFlags::Extras, nExtFlags );
434
435
0
    ShowTable( aRange );
436
0
}
437
438
void ScUndoSelectionAttr::ChangeEditData( const bool bUndo )
439
0
{
440
0
    ScDocument& rDoc = rDocShell.GetDocument();
441
0
    for (const ScEditDataArray::Item* pItem = mpDataArray->First(); pItem; pItem = mpDataArray->Next())
442
0
    {
443
0
        ScAddress aPos(pItem->GetCol(), pItem->GetRow(), pItem->GetTab());
444
0
        if (rDoc.GetCellType(aPos) != CELLTYPE_EDIT)
445
0
            continue;
446
447
0
        if (bUndo)
448
0
        {
449
0
            if (pItem->GetOldData())
450
0
                rDoc.SetEditText(aPos, *pItem->GetOldData(), nullptr);
451
0
            else
452
0
                rDoc.SetEmptyCell(aPos);
453
0
        }
454
0
        else
455
0
        {
456
0
            if (pItem->GetNewData())
457
0
                rDoc.SetEditText(aPos, *pItem->GetNewData(), nullptr);
458
0
            else
459
0
                rDoc.SetEmptyCell(aPos);
460
0
        }
461
0
    }
462
0
}
463
464
void ScUndoSelectionAttr::Undo()
465
0
{
466
0
    BeginUndo();
467
0
    DoChange( true );
468
0
    EndUndo();
469
0
}
470
471
void ScUndoSelectionAttr::Redo()
472
0
{
473
0
    BeginRedo();
474
0
    DoChange( false );
475
0
    EndRedo();
476
0
}
477
478
void ScUndoSelectionAttr::Repeat(SfxRepeatTarget& rTarget)
479
0
{
480
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
481
0
    {
482
0
        ScTabViewShell& rViewShell = pViewTarget->GetViewShell();
483
0
        if (maLineOuter.getItem())
484
0
            rViewShell.ApplyPatternLines(*aApplyPattern.getScPatternAttr(),
485
0
                *static_cast<const SvxBoxItem*>(maLineOuter.getItem()),
486
0
                static_cast<const SvxBoxInfoItem*>(maLineInner.getItem()));
487
0
        else
488
0
            rViewShell.ApplySelectionPattern( *aApplyPattern.getScPatternAttr() );
489
0
    }
490
0
}
491
492
bool ScUndoSelectionAttr::CanRepeat(SfxRepeatTarget& rTarget) const
493
0
{
494
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
495
0
}
496
497
ScUndoAutoFill::ScUndoAutoFill( ScDocShell& rNewDocShell,
498
                const ScRange& rRange, const ScRange& rSourceArea,
499
                ScDocumentUniquePtr pNewUndoDoc, const ScMarkData& rMark,
500
                FillDir eNewFillDir, FillCmd eNewFillCmd, FillDateCmd eNewFillDateCmd,
501
                double fNewStartValue, double fNewStepValue, double fNewMaxValue )
502
0
    :   ScBlockUndo( rNewDocShell, rRange, SC_UNDO_AUTOHEIGHT ),
503
0
        aSource         ( rSourceArea ),
504
0
        aMarkData       ( rMark ),
505
0
        pUndoDoc        ( std::move(pNewUndoDoc) ),
506
0
        eFillDir        ( eNewFillDir ),
507
0
        eFillCmd        ( eNewFillCmd ),
508
0
        eFillDateCmd    ( eNewFillDateCmd ),
509
0
        fStartValue     ( fNewStartValue ),
510
0
        fStepValue      ( fNewStepValue ),
511
0
        fMaxValue       ( fNewMaxValue )
512
0
{
513
0
    SetChangeTrack();
514
0
}
515
516
ScUndoAutoFill::~ScUndoAutoFill()
517
0
{
518
0
}
519
520
OUString ScUndoAutoFill::GetComment() const
521
0
{
522
0
    return ScResId( STR_UNDO_AUTOFILL ); //"Fill"
523
0
}
524
525
void ScUndoAutoFill::SetChangeTrack()
526
0
{
527
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
528
0
    if ( pChangeTrack )
529
0
        pChangeTrack->AppendContentRange( aBlockRange, *pUndoDoc,
530
0
            nStartChangeAction, nEndChangeAction );
531
0
    else
532
0
        nStartChangeAction = nEndChangeAction = 0;
533
0
}
534
535
void ScUndoAutoFill::Undo()
536
0
{
537
0
    BeginUndo();
538
539
0
    ScDocument& rDoc = rDocShell.GetDocument();
540
541
0
    SCTAB nTabCount = rDoc.GetTableCount();
542
0
    for (const auto& rTab : aMarkData)
543
0
    {
544
0
        if (rTab >= nTabCount)
545
0
            break;
546
0
        ScRange aWorkRange = aBlockRange;
547
0
        aWorkRange.aStart.SetTab(rTab);
548
0
        aWorkRange.aEnd.SetTab(rTab);
549
550
0
        sal_uInt16 nExtFlags = 0;
551
0
        rDocShell.UpdatePaintExt( nExtFlags, aWorkRange );
552
0
        rDoc.DeleteAreaTab( aWorkRange, InsertDeleteFlags::AUTOFILL );
553
0
        pUndoDoc->CopyToDocument(aWorkRange, InsertDeleteFlags::AUTOFILL, false, rDoc);
554
555
        // Actually we'd only need to broadcast the cells inserted during
556
        // CopyToDocument(), as DeleteAreaTab() broadcasts deleted cells. For
557
        // this we'd need to either record the span sets or let
558
        // CopyToDocument() broadcast.
559
0
        BroadcastChanges( aWorkRange);
560
561
0
        rDoc.ExtendMerge( aWorkRange, true );
562
0
        rDocShell.PostPaint( aWorkRange, PaintPartFlags::Grid, nExtFlags );
563
0
    }
564
0
    rDocShell.PostDataChanged();
565
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
566
0
    if (pViewShell)
567
0
        pViewShell->CellContentChanged();
568
569
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
570
0
    if ( pChangeTrack )
571
0
        pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
572
573
0
    EndUndo();
574
0
}
575
576
void ScUndoAutoFill::Redo()
577
0
{
578
0
    BeginRedo();
579
580
//! Select sheet
581
582
0
    SCCOLROW nCount = 0;
583
0
    switch (eFillDir)
584
0
    {
585
0
        case FILL_TO_BOTTOM:
586
0
            nCount = aBlockRange.aEnd.Row() - aSource.aEnd.Row();
587
0
            break;
588
0
        case FILL_TO_RIGHT:
589
0
            nCount = aBlockRange.aEnd.Col() - aSource.aEnd.Col();
590
0
            break;
591
0
        case FILL_TO_TOP:
592
0
            nCount = aSource.aStart.Row() - aBlockRange.aStart.Row();
593
0
            break;
594
0
        case FILL_TO_LEFT:
595
0
            nCount = aSource.aStart.Col() - aBlockRange.aStart.Col();
596
0
            break;
597
0
    }
598
599
0
    ScDocument& rDoc = rDocShell.GetDocument();
600
0
    if ( fStartValue != MAXDOUBLE )
601
0
    {
602
0
        SCCOL nValX = (eFillDir == FILL_TO_LEFT) ? aSource.aEnd.Col() : aSource.aStart.Col();
603
0
        SCROW nValY = (eFillDir == FILL_TO_TOP ) ? aSource.aEnd.Row() : aSource.aStart.Row();
604
0
        SCTAB nTab = aSource.aStart.Tab();
605
0
        rDoc.SetValue( nValX, nValY, nTab, fStartValue );
606
0
    }
607
0
    sal_uLong nProgCount;
608
0
    if (eFillDir == FILL_TO_BOTTOM || eFillDir == FILL_TO_TOP)
609
0
        nProgCount = aSource.aEnd.Col() - aSource.aStart.Col() + 1;
610
0
    else
611
0
        nProgCount = aSource.aEnd.Row() - aSource.aStart.Row() + 1;
612
0
    nProgCount *= nCount;
613
0
    ScProgress aProgress( rDoc.GetDocumentShell(),
614
0
            ScResId(STR_FILL_SERIES_PROGRESS), nProgCount, true );
615
616
0
    rDoc.Fill( aSource.aStart.Col(), aSource.aStart.Row(),
617
0
            aSource.aEnd.Col(), aSource.aEnd.Row(), &aProgress,
618
0
            aMarkData, nCount,
619
0
            eFillDir, eFillCmd, eFillDateCmd,
620
0
            fStepValue, fMaxValue );
621
622
0
    SetChangeTrack();
623
624
0
    rDocShell.PostPaint( aBlockRange, PaintPartFlags::Grid );
625
0
    rDocShell.PostDataChanged();
626
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
627
0
    if (pViewShell)
628
0
        pViewShell->CellContentChanged();
629
630
0
    EndRedo();
631
0
}
632
633
void ScUndoAutoFill::Repeat(SfxRepeatTarget& rTarget)
634
0
{
635
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
636
0
    {
637
0
        ScTabViewShell& rViewShell = pViewTarget->GetViewShell();
638
0
        if (eFillCmd==FILL_SIMPLE)
639
0
            rViewShell.FillSimple( eFillDir );
640
0
        else
641
0
            rViewShell.FillSeries( eFillDir, eFillCmd, eFillDateCmd,
642
0
                                   fStartValue, fStepValue, fMaxValue );
643
0
    }
644
0
}
645
646
bool ScUndoAutoFill::CanRepeat(SfxRepeatTarget& rTarget) const
647
0
{
648
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
649
0
}
650
651
ScUndoMerge::ScUndoMerge(ScDocShell& rNewDocShell, ScCellMergeOption aOption,
652
                         bool bMergeContents, ScDocumentUniquePtr pUndoDoc, std::unique_ptr<SdrUndoAction> pDrawUndo)
653
0
    : ScSimpleUndo(rNewDocShell)
654
0
    , maOption(std::move(aOption))
655
0
    , mbMergeContents(bMergeContents)
656
0
    , mxUndoDoc(std::move(pUndoDoc))
657
0
    , mpDrawUndo(std::move(pDrawUndo))
658
0
{
659
0
}
660
661
ScUndoMerge::~ScUndoMerge()
662
0
{
663
0
    mpDrawUndo.reset();
664
0
}
665
666
OUString ScUndoMerge::GetComment() const
667
0
{
668
0
    return ScResId( STR_UNDO_MERGE );
669
0
}
670
671
void ScUndoMerge::DoChange( bool bUndo ) const
672
0
{
673
0
    if (maOption.maTabs.empty())
674
        // Nothing to do.
675
0
        return;
676
677
0
    ScDocument& rDoc = rDocShell.GetDocument();
678
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
679
680
0
    ScRange aCurRange = maOption.getSingleRange(ScDocShell::GetCurTab());
681
0
    ScUndoUtil::MarkSimpleBlock(rDocShell, aCurRange);
682
683
0
    for (const SCTAB nTab : maOption.maTabs)
684
0
    {
685
0
        ScRange aRange = maOption.getSingleRange(nTab);
686
687
0
        if (bUndo)
688
            // remove merge (contents are copied back below from undo document)
689
0
            rDoc.RemoveMerge( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aStart.Tab() );
690
0
        else
691
0
        {
692
            // repeat merge, but do not remove note captions (will be done by drawing redo below)
693
0
            rDoc.DoMerge( aRange.aStart.Col(), aRange.aStart.Row(),
694
0
                          aRange.aEnd.Col(),   aRange.aEnd.Row(),
695
0
                          aRange.aStart.Tab(), false );
696
697
0
            if (maOption.mbCenter)
698
0
            {
699
0
                rDoc.ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
700
0
                                 aRange.aStart.Tab(),
701
0
                                 SvxHorJustifyItem( SvxCellHorJustify::Center, ATTR_HOR_JUSTIFY ) );
702
0
                rDoc.ApplyAttr( aRange.aStart.Col(), aRange.aStart.Row(),
703
0
                                 aRange.aStart.Tab(),
704
0
                                 SvxVerJustifyItem( SvxCellVerJustify::Center, ATTR_VER_JUSTIFY ) );
705
0
            }
706
0
        }
707
708
        // undo -> copy back deleted contents
709
0
        if (bUndo && mxUndoDoc)
710
0
        {
711
            // If there are note captions to be deleted during Undo they were
712
            // kept or moved during the merge and copied to the Undo document
713
            // without cloning the caption. Forget the target area's caption
714
            // pointer that is identical to the one in the Undo document
715
            // instead of deleting it.
716
0
            rDoc.DeleteAreaTab( aRange,
717
0
                    InsertDeleteFlags::CONTENTS | InsertDeleteFlags::NOCAPTIONS | InsertDeleteFlags::FORGETCAPTIONS );
718
0
            mxUndoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL|InsertDeleteFlags::NOCAPTIONS, false, rDoc);
719
0
        }
720
721
        // redo -> merge contents again
722
0
        else if (!bUndo && mbMergeContents)
723
0
        {
724
0
            rDoc.DoMergeContents( aRange.aStart.Col(), aRange.aStart.Row(),
725
0
                                  aRange.aEnd.Col(), aRange.aEnd.Row(),
726
0
                                  aRange.aStart.Tab() );
727
0
        }
728
729
0
        if (bUndo)
730
0
            DoSdrUndoAction( mpDrawUndo.get(), &rDoc );
731
0
        else
732
0
            RedoSdrUndoAction( mpDrawUndo.get() );
733
734
0
        bool bDidPaint = false;
735
0
        if ( pViewShell )
736
0
        {
737
0
            pViewShell->SetTabNo(nTab);
738
0
            bDidPaint = pViewShell->AdjustRowHeight(maOption.mnStartRow, maOption.mnEndRow, true);
739
0
        }
740
741
0
        if (!bDidPaint)
742
0
            ScUndoUtil::PaintMore(rDocShell, aRange);
743
744
0
        rDoc.BroadcastCells(aRange, SfxHintId::ScDataChanged);
745
0
    }
746
747
0
    ShowTable(aCurRange);
748
0
}
749
750
void ScUndoMerge::Undo()
751
0
{
752
0
    BeginUndo();
753
0
    DoChange( true );
754
0
    EndUndo();
755
0
}
756
757
void ScUndoMerge::Redo()
758
0
{
759
0
    BeginRedo();
760
0
    DoChange( false );
761
0
    EndRedo();
762
0
}
763
764
void ScUndoMerge::Repeat(SfxRepeatTarget& rTarget)
765
0
{
766
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
767
0
    {
768
0
        ScTabViewShell& rViewShell = pViewTarget->GetViewShell();
769
0
        rViewShell.MergeCells( false, false, false, 0 );
770
0
    }
771
0
}
772
773
bool ScUndoMerge::CanRepeat(SfxRepeatTarget& rTarget) const
774
0
{
775
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
776
0
}
777
778
ScUndoAutoFormat::ScUndoAutoFormat( ScDocShell& rNewDocShell,
779
                        const ScRange& rRange, ScDocumentUniquePtr pNewUndoDoc,
780
                        const ScMarkData& rMark, bool bNewSize, sal_uInt16 nNewFormatNo )
781
0
    :   ScBlockUndo( rNewDocShell, rRange, bNewSize ? SC_UNDO_MANUALHEIGHT : SC_UNDO_AUTOHEIGHT ),
782
0
        pUndoDoc    ( std::move(pNewUndoDoc) ),
783
0
        aMarkData   ( rMark ),
784
0
        bSize       ( bNewSize ),
785
0
        nFormatNo   ( nNewFormatNo )
786
0
{
787
0
}
788
789
ScUndoAutoFormat::~ScUndoAutoFormat()
790
0
{
791
0
}
792
793
OUString ScUndoAutoFormat::GetComment() const
794
0
{
795
0
    return ScResId( STR_UNDO_AUTOFORMAT );   //"Auto-Format"
796
0
}
797
798
void ScUndoAutoFormat::Undo()
799
0
{
800
0
    BeginUndo();
801
802
0
    ScDocument& rDoc = rDocShell.GetDocument();
803
804
0
    SCTAB nTabCount = rDoc.GetTableCount();
805
0
    rDoc.DeleteArea( aBlockRange.aStart.Col(), aBlockRange.aStart.Row(),
806
0
                      aBlockRange.aEnd.Col(), aBlockRange.aEnd.Row(),
807
0
                      aMarkData, InsertDeleteFlags::ATTRIB );
808
0
    ScRange aCopyRange = aBlockRange;
809
0
    aCopyRange.aStart.SetTab(0);
810
0
    aCopyRange.aEnd.SetTab(nTabCount-1);
811
0
    pUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ATTRIB, false, rDoc, &aMarkData);
812
813
    // cell heights and widths (InsertDeleteFlags::NONE)
814
0
    if (bSize)
815
0
    {
816
0
        SCCOL nStartX = aBlockRange.aStart.Col();
817
0
        SCROW nStartY = aBlockRange.aStart.Row();
818
0
        SCTAB nStartZ = aBlockRange.aStart.Tab();
819
0
        SCCOL nEndX = aBlockRange.aEnd.Col();
820
0
        SCROW nEndY = aBlockRange.aEnd.Row();
821
0
        SCTAB nEndZ = aBlockRange.aEnd.Tab();
822
823
0
        pUndoDoc->CopyToDocument( nStartX, 0, 0, nEndX, rDoc.MaxRow(), nTabCount-1,
824
0
                                    InsertDeleteFlags::NONE, false, rDoc, &aMarkData );
825
0
        pUndoDoc->CopyToDocument( 0, nStartY, 0, rDoc.MaxCol(), nEndY, nTabCount-1,
826
0
                                    InsertDeleteFlags::NONE, false, rDoc, &aMarkData );
827
0
        rDocShell.PostPaint( 0, 0, nStartZ, rDoc.MaxCol(), rDoc.MaxRow(), nEndZ,
828
0
                              PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top, SC_PF_LINES );
829
0
    }
830
0
    else
831
0
        rDocShell.PostPaint( aBlockRange, PaintPartFlags::Grid, SC_PF_LINES );
832
833
0
    EndUndo();
834
0
}
835
836
void ScUndoAutoFormat::Redo()
837
0
{
838
0
    BeginRedo();
839
840
0
    ScDocument& rDoc = rDocShell.GetDocument();
841
842
0
    SCCOL nStartX = aBlockRange.aStart.Col();
843
0
    SCROW nStartY = aBlockRange.aStart.Row();
844
0
    SCTAB nStartZ = aBlockRange.aStart.Tab();
845
0
    SCCOL nEndX = aBlockRange.aEnd.Col();
846
0
    SCROW nEndY = aBlockRange.aEnd.Row();
847
0
    SCTAB nEndZ = aBlockRange.aEnd.Tab();
848
849
0
    rDoc.AutoFormat( nStartX, nStartY, nEndX, nEndY, nFormatNo, aMarkData );
850
851
0
    if (bSize)
852
0
    {
853
0
        ScopedVclPtrInstance< VirtualDevice > pVirtDev;
854
0
        double fZoomX(1.0);
855
0
        double fZoomY = fZoomX;
856
0
        double nPPTX,nPPTY;
857
0
        ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
858
0
        if (pViewShell)
859
0
        {
860
0
            ScViewData& rData = pViewShell->GetViewData();
861
0
            nPPTX = rData.GetPPTX();
862
0
            nPPTY = rData.GetPPTY();
863
0
            fZoomX = rData.GetZoomX();
864
0
            fZoomY = rData.GetZoomY();
865
0
        }
866
0
        else
867
0
        {
868
            // Keep zoom at 100
869
0
            nPPTX = ScGlobal::nScreenPPTX;
870
0
            nPPTY = ScGlobal::nScreenPPTY;
871
0
        }
872
873
0
        sc::RowHeightContext aCxt(rDoc.MaxRow(), nPPTX, nPPTY, fZoomX, fZoomY, pVirtDev);
874
0
        for (SCTAB nTab=nStartZ; nTab<=nEndZ; nTab++)
875
0
        {
876
0
            ScMarkData aDestMark(rDoc.GetSheetLimits());
877
0
            aDestMark.SelectOneTable( nTab );
878
0
            aDestMark.SetMarkArea( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) );
879
0
            aDestMark.MarkToMulti();
880
881
            // as SC_SIZE_VISOPT
882
0
            for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
883
0
            {
884
0
                CRFlags nOld = rDoc.GetRowFlags(nRow,nTab);
885
0
                bool bHidden = rDoc.RowHidden(nRow, nTab);
886
0
                if ( !bHidden && ( nOld & CRFlags::ManualSize ) )
887
0
                    rDoc.SetRowFlags( nRow, nTab, nOld & ~CRFlags::ManualSize );
888
0
            }
889
890
0
            bool bChanged = rDoc.SetOptimalHeight(aCxt, nStartY, nEndY, nTab, true);
891
892
0
            for (SCCOL nCol=nStartX; nCol<=nEndX; nCol++)
893
0
                if (!rDoc.ColHidden(nCol, nTab))
894
0
                {
895
0
                    sal_uInt16 nThisSize = STD_EXTRA_WIDTH + rDoc.GetOptimalColWidth( nCol, nTab,
896
0
                                                pVirtDev, nPPTX, nPPTY, fZoomX, fZoomY, false/*bFormula*/,
897
0
                                                &aDestMark );
898
0
                    rDoc.SetColWidth( nCol, nTab, nThisSize );
899
0
                    rDoc.ShowCol( nCol, nTab, true );
900
0
                }
901
902
            // tdf#76183: recalculate objects' positions
903
0
            if (bChanged)
904
0
                rDoc.SetDrawPageSize(nTab);
905
0
        }
906
907
0
        rDocShell.PostPaint( 0,      0,      nStartZ,
908
0
                              rDoc.MaxCol(), rDoc.MaxRow(), nEndZ,
909
0
                              PaintPartFlags::Grid | PaintPartFlags::Left | PaintPartFlags::Top, SC_PF_LINES);
910
0
    }
911
0
    else
912
0
        rDocShell.PostPaint( aBlockRange, PaintPartFlags::Grid, SC_PF_LINES );
913
914
0
    EndRedo();
915
0
}
916
917
void ScUndoAutoFormat::Repeat(SfxRepeatTarget& rTarget)
918
0
{
919
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
920
0
        pViewTarget->GetViewShell().AutoFormat( nFormatNo );
921
0
}
922
923
bool ScUndoAutoFormat::CanRepeat(SfxRepeatTarget& rTarget) const
924
0
{
925
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
926
0
}
927
928
ScUndoReplace::ScUndoReplace( ScDocShell& rNewDocShell, const ScMarkData& rMark,
929
                                    SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
930
                                    OUString aNewUndoStr, ScDocumentUniquePtr pNewUndoDoc,
931
                                    const SvxSearchItem* pItem )
932
0
    :   ScSimpleUndo( rNewDocShell ),
933
0
        aCursorPos  ( nCurX, nCurY, nCurZ ),
934
0
        aMarkData   ( rMark ),
935
0
        aUndoStr    (std::move( aNewUndoStr )),
936
0
        pUndoDoc    ( std::move(pNewUndoDoc) )
937
0
{
938
0
    pSearchItem.reset( new SvxSearchItem( *pItem ) );
939
0
    SetChangeTrack();
940
0
}
941
942
ScUndoReplace::~ScUndoReplace()
943
0
{
944
0
    pUndoDoc.reset();
945
0
    pSearchItem.reset();
946
0
}
947
948
void ScUndoReplace::SetChangeTrack()
949
0
{
950
0
    ScDocument& rDoc = rDocShell.GetDocument();
951
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
952
0
    if ( pChangeTrack )
953
0
    {
954
0
        if ( pUndoDoc )
955
0
        {   //! UndoDoc includes only the changed cells,
956
            // that is why an Iterator can be used
957
0
            pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
958
0
                nStartChangeAction, nEndChangeAction );
959
0
        }
960
0
        else
961
0
        {
962
0
            nStartChangeAction = pChangeTrack->GetActionMax() + 1;
963
0
            ScChangeActionContent* pContent = new ScChangeActionContent(
964
0
                ScRange( aCursorPos) );
965
0
            ScCellValue aCell;
966
0
            aCell.assign(rDoc, aCursorPos);
967
0
            pContent->SetOldValue( aUndoStr, &rDoc );
968
0
            pContent->SetNewValue(aCell, &rDoc);
969
0
            pChangeTrack->Append( pContent );
970
0
            nEndChangeAction = pChangeTrack->GetActionMax();
971
0
        }
972
0
    }
973
0
    else
974
0
        nStartChangeAction = nEndChangeAction = 0;
975
0
}
976
977
OUString ScUndoReplace::GetComment() const
978
0
{
979
0
    return ScResId( STR_UNDO_REPLACE );  // "Replace"
980
0
}
981
982
void ScUndoReplace::Undo()
983
0
{
984
0
    BeginUndo();
985
986
0
    ScDocument& rDoc = rDocShell.GetDocument();
987
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
988
989
0
    ShowTable( aCursorPos.Tab() );
990
991
0
    if (pUndoDoc)       // only for ReplaceAll !!
992
0
    {
993
0
        OSL_ENSURE(pSearchItem->GetCommand() == SvxSearchCmd::REPLACE_ALL,
994
0
                   "ScUndoReplace:: Wrong Mode");
995
996
0
        SetViewMarkData( aMarkData );
997
998
//! selected sheet
999
//! select range ?
1000
1001
        // Undo document has no row/column information, thus copy with
1002
        // bColRowFlags = FALSE to not destroy Outline groups
1003
1004
0
        InsertDeleteFlags nUndoFlags = (pSearchItem->GetPattern()) ? InsertDeleteFlags::ATTRIB : InsertDeleteFlags::CONTENTS;
1005
0
        pUndoDoc->CopyToDocument( 0,      0,      0,
1006
0
                                  rDoc.MaxCol(), rDoc.MaxRow(), MAXTAB,
1007
0
                                  nUndoFlags, false, rDoc, nullptr, false );   // without row flags
1008
0
        rDocShell.PostPaintGridAll();
1009
0
    }
1010
0
    else if (pSearchItem->GetPattern() &&
1011
0
             pSearchItem->GetCommand() == SvxSearchCmd::REPLACE)
1012
0
    {
1013
0
        OUString aTempStr = pSearchItem->GetSearchString();       // toggle
1014
0
        pSearchItem->SetSearchString(pSearchItem->GetReplaceString());
1015
0
        pSearchItem->SetReplaceString(aTempStr);
1016
0
        rDoc.ReplaceStyle( *pSearchItem,
1017
0
                            aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
1018
0
                            aMarkData);
1019
0
        pSearchItem->SetReplaceString(pSearchItem->GetSearchString());
1020
0
        pSearchItem->SetSearchString(aTempStr);
1021
0
        if (pViewShell)
1022
0
            pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1023
0
                                       SC_FOLLOW_JUMP, false, false );
1024
0
        rDocShell.PostPaintGridAll();
1025
0
    }
1026
0
    else if (pSearchItem->GetCellType() == SvxSearchCellType::NOTE)
1027
0
    {
1028
0
        ScPostIt* pNote = rDoc.GetNote(aCursorPos);
1029
0
        OSL_ENSURE( pNote, "ScUndoReplace::Undo - cell does not contain a note" );
1030
0
        if (pNote)
1031
0
            pNote->SetText( aCursorPos, aUndoStr );
1032
0
        if (pViewShell)
1033
0
            pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1034
0
                                       SC_FOLLOW_JUMP, false, false );
1035
0
    }
1036
0
    else
1037
0
    {
1038
        // aUndoStr may contain line breaks
1039
0
        if ( aUndoStr.indexOf('\n') != -1 )
1040
0
        {
1041
0
            ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
1042
0
            rEngine.SetTextCurrentDefaults(aUndoStr);
1043
0
            rDoc.SetEditText(aCursorPos, rEngine.CreateTextObject());
1044
0
        }
1045
0
        else
1046
0
            rDoc.SetString( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), aUndoStr );
1047
0
        if (pViewShell)
1048
0
            pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1049
0
                                       SC_FOLLOW_JUMP, false, false );
1050
0
        rDocShell.PostPaintGridAll();
1051
0
    }
1052
1053
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
1054
0
    if ( pChangeTrack )
1055
0
        pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1056
1057
0
    EndUndo();
1058
0
}
1059
1060
void ScUndoReplace::Redo()
1061
0
{
1062
0
    BeginRedo();
1063
1064
0
    ScDocument& rDoc = rDocShell.GetDocument();
1065
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1066
1067
0
    if (pViewShell)
1068
0
        pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(),
1069
0
                                   SC_FOLLOW_JUMP, false, false );
1070
0
    if (pUndoDoc)
1071
0
    {
1072
0
        if (pViewShell)
1073
0
        {
1074
0
            SetViewMarkData( aMarkData );
1075
1076
0
            pViewShell->SearchAndReplace( pSearchItem.get(), false, true );
1077
0
        }
1078
0
    }
1079
0
    else if (pSearchItem->GetPattern() &&
1080
0
             pSearchItem->GetCommand() == SvxSearchCmd::REPLACE)
1081
0
    {
1082
0
        rDoc.ReplaceStyle( *pSearchItem,
1083
0
                            aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
1084
0
                            aMarkData);
1085
0
        rDocShell.PostPaintGridAll();
1086
0
    }
1087
0
    else
1088
0
        if (pViewShell)
1089
0
            pViewShell->SearchAndReplace( pSearchItem.get(), false, true );
1090
1091
0
    SetChangeTrack();
1092
1093
0
    EndRedo();
1094
0
}
1095
1096
void ScUndoReplace::Repeat(SfxRepeatTarget& rTarget)
1097
0
{
1098
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1099
0
        pViewTarget->GetViewShell().SearchAndReplace( pSearchItem.get(), true, false );
1100
0
}
1101
1102
bool ScUndoReplace::CanRepeat(SfxRepeatTarget& rTarget) const
1103
0
{
1104
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
1105
0
}
1106
1107
// multi-operation (only simple blocks)
1108
ScUndoTabOp::ScUndoTabOp( ScDocShell& rNewDocShell,
1109
                SCCOL nStartX, SCROW nStartY, SCTAB nStartZ,
1110
                SCCOL nEndX, SCROW nEndY, SCTAB nEndZ, ScDocumentUniquePtr pNewUndoDoc,
1111
                const ScRefAddress& rFormulaCell,
1112
                const ScRefAddress& rFormulaEnd,
1113
                const ScRefAddress& rRowCell,
1114
                const ScRefAddress& rColCell,
1115
                ScTabOpParam::Mode eMode )
1116
0
    :   ScSimpleUndo( rNewDocShell ),
1117
0
        aRange          ( nStartX, nStartY, nStartZ, nEndX, nEndY, nEndZ ),
1118
0
        pUndoDoc        ( std::move(pNewUndoDoc) ),
1119
0
        theFormulaCell  ( rFormulaCell ),
1120
0
        theFormulaEnd   ( rFormulaEnd ),
1121
0
        theRowCell      ( rRowCell ),
1122
0
        theColCell      ( rColCell ),
1123
0
        meMode(eMode)
1124
0
{
1125
0
}
1126
1127
ScUndoTabOp::~ScUndoTabOp()
1128
0
{
1129
0
}
1130
1131
OUString ScUndoTabOp::GetComment() const
1132
0
{
1133
0
    return ScResId( STR_UNDO_TABOP );    // "Multiple operation"
1134
0
}
1135
1136
void ScUndoTabOp::Undo()
1137
0
{
1138
0
    BeginUndo();
1139
1140
0
    ScUndoUtil::MarkSimpleBlock( rDocShell, aRange );
1141
1142
0
    sal_uInt16 nExtFlags = 0;
1143
0
    rDocShell.UpdatePaintExt( nExtFlags, aRange );
1144
1145
0
    ScDocument& rDoc = rDocShell.GetDocument();
1146
0
    rDoc.DeleteAreaTab( aRange,InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1147
0
    pUndoDoc->CopyToDocument( aRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc );
1148
0
    rDocShell.PostPaint( aRange, PaintPartFlags::Grid, nExtFlags );
1149
0
    rDocShell.PostDataChanged();
1150
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1151
0
    if (pViewShell)
1152
0
        pViewShell->CellContentChanged();
1153
1154
0
    EndUndo();
1155
0
}
1156
1157
void ScUndoTabOp::Redo()
1158
0
{
1159
0
    BeginRedo();
1160
1161
0
    ScUndoUtil::MarkSimpleBlock( rDocShell, aRange );
1162
1163
0
    ScTabOpParam aParam(theFormulaCell, theFormulaEnd, theRowCell, theColCell, meMode);
1164
1165
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1166
0
    if (pViewShell)
1167
0
        pViewShell->TabOp( aParam, false);
1168
1169
0
    EndRedo();
1170
0
}
1171
1172
void ScUndoTabOp::Repeat(SfxRepeatTarget& /* rTarget */)
1173
0
{
1174
0
}
1175
1176
bool ScUndoTabOp::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1177
0
{
1178
0
    return false;
1179
0
}
1180
1181
ScUndoConversion::ScUndoConversion(
1182
        ScDocShell& rNewDocShell, const ScMarkData& rMark,
1183
        SCCOL nCurX, SCROW nCurY, SCTAB nCurZ, ScDocumentUniquePtr pNewUndoDoc,
1184
        SCCOL nNewX, SCROW nNewY, SCTAB nNewZ, ScDocumentUniquePtr pNewRedoDoc,
1185
        ScConversionParam aConvParam ) :
1186
0
    ScSimpleUndo( rNewDocShell ),
1187
0
    aMarkData( rMark ),
1188
0
    aCursorPos( nCurX, nCurY, nCurZ ),
1189
0
    pUndoDoc( std::move(pNewUndoDoc) ),
1190
0
    aNewCursorPos( nNewX, nNewY, nNewZ ),
1191
0
    pRedoDoc( std::move(pNewRedoDoc) ),
1192
0
    maConvParam(std::move( aConvParam ))
1193
0
{
1194
0
    SetChangeTrack();
1195
0
}
1196
1197
ScUndoConversion::~ScUndoConversion()
1198
0
{
1199
0
    pUndoDoc.reset();
1200
0
    pRedoDoc.reset();
1201
0
}
1202
1203
void ScUndoConversion::SetChangeTrack()
1204
0
{
1205
0
    ScDocument& rDoc = rDocShell.GetDocument();
1206
0
    ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
1207
0
    if ( pChangeTrack )
1208
0
    {
1209
0
        if ( pUndoDoc )
1210
0
            pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
1211
0
                nStartChangeAction, nEndChangeAction );
1212
0
        else
1213
0
        {
1214
0
            OSL_FAIL( "ScUndoConversion::SetChangeTrack: no UndoDoc" );
1215
0
            nStartChangeAction = nEndChangeAction = 0;
1216
0
        }
1217
0
    }
1218
0
    else
1219
0
        nStartChangeAction = nEndChangeAction = 0;
1220
0
}
1221
1222
OUString ScUndoConversion::GetComment() const
1223
0
{
1224
0
    OUString aText;
1225
0
    switch( maConvParam.GetType() )
1226
0
    {
1227
0
        case SC_CONVERSION_SPELLCHECK:      aText = ScResId( STR_UNDO_SPELLING );    break;
1228
0
        case SC_CONVERSION_HANGULHANJA:     aText = ScResId( STR_UNDO_HANGULHANJA ); break;
1229
0
        case SC_CONVERSION_CHINESE_TRANSL:  aText = ScResId( STR_UNDO_CHINESE_TRANSLATION ); break;
1230
0
    }
1231
0
    return aText;
1232
0
}
1233
1234
void ScUndoConversion::DoChange( ScDocument* pRefDoc, const ScAddress& rCursorPos )
1235
0
{
1236
0
    if (pRefDoc)
1237
0
    {
1238
0
        ScDocument& rDoc = rDocShell.GetDocument();
1239
0
        ShowTable( rCursorPos.Tab() );
1240
1241
0
        SetViewMarkData( aMarkData );
1242
1243
0
        SCTAB nTabCount = rDoc.GetTableCount();
1244
        //  Undo/Redo-doc has only selected tables
1245
1246
0
        bool bMulti = aMarkData.IsMultiMarked();
1247
0
        pRefDoc->CopyToDocument( 0,      0,      0,
1248
0
                                 rDoc.MaxCol(), rDoc.MaxRow(), nTabCount-1,
1249
0
                                 InsertDeleteFlags::CONTENTS, bMulti, rDoc, &aMarkData );
1250
1251
        // Reset the spell checking results to re-check on paint, otherwise
1252
        // we show the previous spelling markers (or lack thereof on misspellings).
1253
0
        if (ScViewData* pViewData = ScDocShell::GetViewData())
1254
0
            pViewData->GetActiveWin()->ResetAutoSpell();
1255
0
        rDocShell.PostPaintGridAll();
1256
0
    }
1257
0
    else
1258
0
    {
1259
0
        OSL_FAIL("no Un-/RedoDoc for Un-/RedoSpelling");
1260
0
    }
1261
0
}
1262
1263
void ScUndoConversion::Undo()
1264
0
{
1265
0
    BeginUndo();
1266
0
    DoChange( pUndoDoc.get(), aCursorPos );
1267
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
1268
0
    if ( pChangeTrack )
1269
0
        pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1270
0
    EndUndo();
1271
0
}
1272
1273
void ScUndoConversion::Redo()
1274
0
{
1275
0
    BeginRedo();
1276
0
    DoChange( pRedoDoc.get(), aNewCursorPos );
1277
0
    SetChangeTrack();
1278
0
    EndRedo();
1279
0
}
1280
1281
void ScUndoConversion::Repeat( SfxRepeatTarget& rTarget )
1282
0
{
1283
0
    if( auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget) )
1284
0
        pViewTarget->GetViewShell().DoSheetConversion( maConvParam );
1285
0
}
1286
1287
bool ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const
1288
0
{
1289
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
1290
0
}
1291
1292
ScUndoRefConversion::ScUndoRefConversion( ScDocShell& rNewDocShell,
1293
                                         const ScRange& aMarkRange, const ScMarkData& rMark,
1294
                                         ScDocumentUniquePtr pNewUndoDoc, ScDocumentUniquePtr pNewRedoDoc, bool bNewMulti) :
1295
0
ScSimpleUndo( rNewDocShell ),
1296
0
aMarkData   ( rMark ),
1297
0
pUndoDoc    ( std::move(pNewUndoDoc) ),
1298
0
pRedoDoc    ( std::move(pNewRedoDoc) ),
1299
0
aRange      ( aMarkRange ),
1300
0
bMulti      ( bNewMulti )
1301
0
{
1302
0
    assert(pUndoDoc && pRedoDoc);
1303
0
    SetChangeTrack();
1304
0
}
1305
1306
ScUndoRefConversion::~ScUndoRefConversion()
1307
0
{
1308
0
    pUndoDoc.reset();
1309
0
    pRedoDoc.reset();
1310
0
}
1311
1312
OUString ScUndoRefConversion::GetComment() const
1313
0
{
1314
0
    return ScResId( STR_UNDO_ENTERDATA ); // "Input"
1315
0
}
1316
1317
void ScUndoRefConversion::SetChangeTrack()
1318
0
{
1319
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
1320
0
    if ( pChangeTrack )
1321
0
        pChangeTrack->AppendContentsIfInRefDoc( *pUndoDoc,
1322
0
            nStartChangeAction, nEndChangeAction );
1323
0
    else
1324
0
        nStartChangeAction = nEndChangeAction = 0;
1325
0
}
1326
1327
void ScUndoRefConversion::DoChange( ScDocument* pRefDoc)
1328
0
{
1329
0
    ScDocument& rDoc = rDocShell.GetDocument();
1330
1331
0
    ShowTable(aRange);
1332
1333
0
    SetViewMarkData( aMarkData );
1334
1335
0
    ScRange aCopyRange = aRange;
1336
0
    SCTAB nTabCount = rDoc.GetTableCount();
1337
0
    aCopyRange.aStart.SetTab(0);
1338
0
    aCopyRange.aEnd.SetTab(nTabCount-1);
1339
0
    pRefDoc->CopyToDocument( aCopyRange, InsertDeleteFlags::ALL, bMulti, rDoc, &aMarkData );
1340
0
    rDocShell.PostPaint( aRange, PaintPartFlags::Grid);
1341
0
    rDocShell.PostDataChanged();
1342
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1343
0
    if (pViewShell)
1344
0
        pViewShell->CellContentChanged();
1345
0
}
1346
1347
void ScUndoRefConversion::Undo()
1348
0
{
1349
0
    BeginUndo();
1350
0
    if (pUndoDoc)
1351
0
        DoChange(pUndoDoc.get());
1352
0
    ScChangeTrack* pChangeTrack = rDocShell.GetDocument().GetChangeTrack();
1353
0
    if ( pChangeTrack )
1354
0
        pChangeTrack->Undo( nStartChangeAction, nEndChangeAction );
1355
0
    EndUndo();
1356
0
}
1357
1358
void ScUndoRefConversion::Redo()
1359
0
{
1360
0
    BeginRedo();
1361
0
    if (pRedoDoc)
1362
0
        DoChange(pRedoDoc.get());
1363
0
    SetChangeTrack();
1364
0
    EndRedo();
1365
0
}
1366
1367
void ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget)
1368
0
{
1369
0
    if (auto pViewTarget = dynamic_cast<ScTabViewTarget*>( &rTarget))
1370
0
        pViewTarget->GetViewShell().DoRefConversion();
1371
0
}
1372
1373
bool ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const
1374
0
{
1375
0
    return dynamic_cast<const ScTabViewTarget*>( &rTarget) !=  nullptr;
1376
0
}
1377
1378
ScUndoRefreshLink::ScUndoRefreshLink(ScDocShell& rNewDocShell,
1379
                                     ScDocumentUniquePtr pNewUndoDoc)
1380
0
    : ScSimpleUndo(rNewDocShell)
1381
0
    , xUndoDoc(std::move(pNewUndoDoc))
1382
0
{
1383
0
}
1384
1385
OUString ScUndoRefreshLink::GetComment() const
1386
0
{
1387
0
    return ScResId( STR_UNDO_UPDATELINK );
1388
0
}
1389
1390
void ScUndoRefreshLink::Undo()
1391
0
{
1392
0
    BeginUndo();
1393
1394
0
    bool bMakeRedo = !xRedoDoc;
1395
0
    if (bMakeRedo)
1396
0
        xRedoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1397
1398
0
    bool bFirst = true;
1399
0
    ScDocument& rDoc = rDocShell.GetDocument();
1400
0
    SCTAB nCount = rDoc.GetTableCount();
1401
0
    for (SCTAB nTab=0; nTab<nCount; nTab++)
1402
0
        if (xUndoDoc->HasTable(nTab))
1403
0
        {
1404
0
            ScRange aRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab);
1405
0
            if (bMakeRedo)
1406
0
            {
1407
0
                if (bFirst)
1408
0
                    xRedoDoc->InitUndo(rDoc, nTab, nTab, true, true);
1409
0
                else
1410
0
                    xRedoDoc->AddUndoTab(nTab, nTab, true, true);
1411
0
                bFirst = false;
1412
0
                rDoc.CopyToDocument(aRange, InsertDeleteFlags::ALL, false, *xRedoDoc);
1413
0
                xRedoDoc->SetLink(nTab,
1414
0
                                  rDoc.GetLinkMode(nTab),
1415
0
                                  rDoc.GetLinkDoc(nTab),
1416
0
                                  rDoc.GetLinkFlt(nTab),
1417
0
                                  rDoc.GetLinkOpt(nTab),
1418
0
                                  rDoc.GetLinkTab(nTab),
1419
0
                                  rDoc.GetLinkRefreshDelay(nTab));
1420
0
                xRedoDoc->SetTabBgColor( nTab, rDoc.GetTabBgColor(nTab) );
1421
0
            }
1422
1423
0
            rDoc.DeleteAreaTab( aRange,InsertDeleteFlags::ALL );
1424
0
            xUndoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL, false, rDoc);
1425
0
            rDoc.SetLink(nTab, xUndoDoc->GetLinkMode(nTab), xUndoDoc->GetLinkDoc(nTab),
1426
0
                               xUndoDoc->GetLinkFlt(nTab),  xUndoDoc->GetLinkOpt(nTab),
1427
0
                               xUndoDoc->GetLinkTab(nTab),
1428
0
                               xUndoDoc->GetLinkRefreshDelay(nTab) );
1429
0
            rDoc.SetTabBgColor(nTab, xUndoDoc->GetTabBgColor(nTab));
1430
0
        }
1431
1432
0
    rDocShell.PostPaintGridAll();
1433
0
    rDocShell.PostPaintExtras();
1434
1435
0
    EndUndo();
1436
0
}
1437
1438
void ScUndoRefreshLink::Redo()
1439
0
{
1440
0
    OSL_ENSURE(xRedoDoc, "No RedoDoc for ScUndoRefreshLink::Redo");
1441
1442
0
    BeginUndo();
1443
1444
0
    ScDocument& rDoc = rDocShell.GetDocument();
1445
0
    SCTAB nCount = rDoc.GetTableCount();
1446
0
    for (SCTAB nTab=0; nTab<nCount; nTab++)
1447
0
        if (xRedoDoc->HasTable(nTab))
1448
0
        {
1449
0
            ScRange aRange(0,0,nTab,rDoc.MaxCol(),rDoc.MaxRow(),nTab);
1450
1451
0
            rDoc.DeleteAreaTab( aRange, InsertDeleteFlags::ALL );
1452
0
            xRedoDoc->CopyToDocument(aRange, InsertDeleteFlags::ALL, false, rDoc);
1453
0
            rDoc.SetLink(nTab,
1454
0
                         xRedoDoc->GetLinkMode(nTab),
1455
0
                         xRedoDoc->GetLinkDoc(nTab),
1456
0
                         xRedoDoc->GetLinkFlt(nTab),
1457
0
                         xRedoDoc->GetLinkOpt(nTab),
1458
0
                         xRedoDoc->GetLinkTab(nTab),
1459
0
                         xRedoDoc->GetLinkRefreshDelay(nTab) );
1460
0
            rDoc.SetTabBgColor(nTab, xRedoDoc->GetTabBgColor(nTab));
1461
0
        }
1462
1463
0
    rDocShell.PostPaintGridAll();
1464
0
    rDocShell.PostPaintExtras();
1465
1466
0
    EndUndo();
1467
0
}
1468
1469
void ScUndoRefreshLink::Repeat(SfxRepeatTarget& /* rTarget */)
1470
0
{
1471
    // makes no sense
1472
0
}
1473
1474
bool ScUndoRefreshLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1475
0
{
1476
0
    return false;
1477
0
}
1478
1479
static ScAreaLink* lcl_FindAreaLink( const sfx2::LinkManager* pLinkManager, std::u16string_view rDoc,
1480
                            std::u16string_view rFlt, std::u16string_view rOpt,
1481
                            std::u16string_view rSrc, const ScRange& rDest )
1482
0
{
1483
0
    const ::sfx2::SvBaseLinks& rLinks = pLinkManager->GetLinks();
1484
0
    sal_uInt16 nCount = pLinkManager->GetLinks().size();
1485
0
    for (sal_uInt16 i=0; i<nCount; i++)
1486
0
    {
1487
0
        ::sfx2::SvBaseLink* pBase = rLinks[i].get();
1488
0
        if (auto pAreaLink = dynamic_cast<ScAreaLink*>( pBase))
1489
0
            if ( pAreaLink->IsEqual( rDoc, rFlt, rOpt, rSrc, rDest ) )
1490
0
                return pAreaLink;
1491
0
    }
1492
1493
0
    OSL_FAIL("ScAreaLink not found");
1494
0
    return nullptr;
1495
0
}
1496
1497
ScUndoInsertAreaLink::ScUndoInsertAreaLink( ScDocShell& rShell,
1498
                            OUString aDoc,
1499
                            OUString aFlt, OUString aOpt,
1500
                            OUString aArea, const ScRange& rDestRange,
1501
                            sal_uLong nRefresh )
1502
0
    :   ScSimpleUndo    ( rShell ),
1503
0
        aDocName        (std::move( aDoc )),
1504
0
        aFltName        (std::move( aFlt )),
1505
0
        aOptions        (std::move( aOpt )),
1506
0
        aAreaName       (std::move( aArea )),
1507
0
        aRange          ( rDestRange ),
1508
0
        nRefreshDelay   ( nRefresh )
1509
0
{
1510
0
}
1511
1512
ScUndoInsertAreaLink::~ScUndoInsertAreaLink()
1513
0
{
1514
0
}
1515
1516
OUString ScUndoInsertAreaLink::GetComment() const
1517
0
{
1518
0
    return ScResId( STR_UNDO_INSERTAREALINK );
1519
0
}
1520
1521
void ScUndoInsertAreaLink::Undo()
1522
0
{
1523
0
    ScDocument& rDoc = rDocShell.GetDocument();
1524
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1525
1526
0
    ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions,
1527
0
                                            aAreaName, aRange );
1528
0
    if (pLink)
1529
0
        pLinkManager->Remove( pLink );
1530
1531
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );     // Navigator
1532
0
}
1533
1534
void ScUndoInsertAreaLink::Redo()
1535
0
{
1536
0
    ScDocument& rDoc = rDocShell.GetDocument();
1537
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1538
1539
0
    ScAreaLink* pLink = new ScAreaLink( rDocShell, aDocName, aFltName, aOptions,
1540
0
                                            aAreaName, ScRange(aRange.aStart), nRefreshDelay );
1541
0
    pLink->SetInCreate( true );
1542
0
    pLink->SetDestArea( aRange );
1543
0
    pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, aDocName, &aFltName, &aAreaName );
1544
0
    pLink->Update();
1545
0
    pLink->SetInCreate( false );
1546
1547
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );     // Navigator
1548
0
}
1549
1550
void ScUndoInsertAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1551
0
{
1552
    // makes no sense
1553
0
}
1554
1555
bool ScUndoInsertAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1556
0
{
1557
0
    return false;
1558
0
}
1559
1560
ScUndoRemoveAreaLink::ScUndoRemoveAreaLink( ScDocShell& rShell,
1561
                            OUString aDoc, OUString aFlt, OUString aOpt,
1562
                            OUString aArea, const ScRange& rDestRange,
1563
                            sal_uLong nRefresh )
1564
0
    :   ScSimpleUndo    ( rShell ),
1565
0
        aDocName        (std::move( aDoc )),
1566
0
        aFltName        (std::move( aFlt )),
1567
0
        aOptions        (std::move( aOpt )),
1568
0
        aAreaName       (std::move( aArea )),
1569
0
        aRange          ( rDestRange ),
1570
0
        nRefreshDelay   ( nRefresh )
1571
0
{
1572
0
}
1573
1574
ScUndoRemoveAreaLink::~ScUndoRemoveAreaLink()
1575
0
{
1576
0
}
1577
1578
OUString ScUndoRemoveAreaLink::GetComment() const
1579
0
{
1580
0
    return ScResId( STR_UNDO_REMOVELINK );   //! own text ??
1581
0
}
1582
1583
void ScUndoRemoveAreaLink::Undo()
1584
0
{
1585
0
    ScDocument& rDoc = rDocShell.GetDocument();
1586
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1587
1588
0
    ScAreaLink* pLink = new ScAreaLink( rDocShell, aDocName, aFltName, aOptions,
1589
0
                                        aAreaName, ScRange(aRange.aStart), nRefreshDelay );
1590
0
    pLink->SetInCreate( true );
1591
0
    pLink->SetDestArea( aRange );
1592
0
    pLinkManager->InsertFileLink( *pLink, sfx2::SvBaseLinkObjectType::ClientFile, aDocName, &aFltName, &aAreaName );
1593
0
    pLink->Update();
1594
0
    pLink->SetInCreate( false );
1595
1596
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );     // Navigator
1597
0
}
1598
1599
void ScUndoRemoveAreaLink::Redo()
1600
0
{
1601
0
    ScDocument& rDoc = rDocShell.GetDocument();
1602
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1603
1604
0
    ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aDocName, aFltName, aOptions,
1605
0
                                            aAreaName, aRange );
1606
0
    if (pLink)
1607
0
        pLinkManager->Remove( pLink );
1608
1609
0
    SfxGetpApp()->Broadcast( SfxHint( SfxHintId::ScAreaLinksChanged ) );     // Navigator
1610
0
}
1611
1612
void ScUndoRemoveAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1613
0
{
1614
    // makes no sense
1615
0
}
1616
1617
bool ScUndoRemoveAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1618
0
{
1619
0
    return false;
1620
0
}
1621
1622
ScUndoUpdateAreaLink::ScUndoUpdateAreaLink( ScDocShell& rShell,
1623
                            OUString aOldD, OUString aOldF, OUString aOldO,
1624
                            OUString aOldA, const ScRange& rOldR, sal_uLong nOldRD,
1625
                            OUString aNewD, OUString aNewF, OUString aNewO,
1626
                            OUString aNewA, const ScRange& rNewR, sal_uLong nNewRD,
1627
                            ScDocumentUniquePtr pUndo, ScDocumentUniquePtr pRedo, bool bDoInsert )
1628
0
    :   ScSimpleUndo( rShell ),
1629
0
        aOldDoc     (std::move( aOldD )),
1630
0
        aOldFlt     (std::move( aOldF )),
1631
0
        aOldOpt     (std::move( aOldO )),
1632
0
        aOldArea    (std::move( aOldA )),
1633
0
        aOldRange   ( rOldR ),
1634
0
        aNewDoc     (std::move( aNewD )),
1635
0
        aNewFlt     (std::move( aNewF )),
1636
0
        aNewOpt     (std::move( aNewO )),
1637
0
        aNewArea    (std::move( aNewA )),
1638
0
        aNewRange   ( rNewR ),
1639
0
        xUndoDoc    ( std::move(pUndo) ),
1640
0
        xRedoDoc    ( std::move(pRedo) ),
1641
0
        nOldRefresh ( nOldRD ),
1642
0
        nNewRefresh ( nNewRD ),
1643
0
        bWithInsert ( bDoInsert )
1644
0
{
1645
0
    OSL_ENSURE( aOldRange.aStart == aNewRange.aStart, "AreaLink moved ?" );
1646
0
}
1647
1648
OUString ScUndoUpdateAreaLink::GetComment() const
1649
0
{
1650
0
    return ScResId( STR_UNDO_UPDATELINK );   //! own text ??
1651
0
}
1652
1653
void ScUndoUpdateAreaLink::DoChange( const bool bUndo ) const
1654
0
{
1655
0
    ScDocument& rDoc = rDocShell.GetDocument();
1656
1657
0
    SCCOL nEndX = std::max( aOldRange.aEnd.Col(), aNewRange.aEnd.Col() );
1658
0
    SCROW nEndY = std::max( aOldRange.aEnd.Row(), aNewRange.aEnd.Row() );
1659
0
    SCTAB nEndZ = std::max( aOldRange.aEnd.Tab(), aNewRange.aEnd.Tab() );    //?
1660
1661
0
    if ( bUndo )
1662
0
    {
1663
0
        if ( bWithInsert )
1664
0
        {
1665
0
            rDoc.FitBlock( aNewRange, aOldRange );
1666
0
            rDoc.DeleteAreaTab( aOldRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1667
0
            xUndoDoc->UndoToDocument(aOldRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1668
0
        }
1669
0
        else
1670
0
        {
1671
0
            ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) );
1672
0
            rDoc.DeleteAreaTab( aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1673
0
            xUndoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1674
0
        }
1675
0
    }
1676
0
    else
1677
0
    {
1678
0
        if ( bWithInsert )
1679
0
        {
1680
0
            rDoc.FitBlock( aOldRange, aNewRange );
1681
0
            rDoc.DeleteAreaTab( aNewRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1682
0
            xRedoDoc->CopyToDocument(aNewRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1683
0
        }
1684
0
        else
1685
0
        {
1686
0
            ScRange aCopyRange( aOldRange.aStart, ScAddress(nEndX,nEndY,nEndZ) );
1687
0
            rDoc.DeleteAreaTab( aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE );
1688
0
            xRedoDoc->CopyToDocument(aCopyRange, InsertDeleteFlags::ALL & ~InsertDeleteFlags::NOTE, false, rDoc);
1689
0
        }
1690
0
    }
1691
1692
0
    ScRange aWorkRange( aNewRange.aStart, ScAddress( nEndX, nEndY, nEndZ ) );
1693
0
    rDoc.ExtendMerge( aWorkRange, true );
1694
1695
    //  Paint
1696
1697
0
    if ( aNewRange.aEnd.Col() != aOldRange.aEnd.Col() )
1698
0
        aWorkRange.aEnd.SetCol(rDoc.MaxCol());
1699
0
    if ( aNewRange.aEnd.Row() != aOldRange.aEnd.Row() )
1700
0
        aWorkRange.aEnd.SetRow(rDoc.MaxRow());
1701
1702
0
    if ( !rDocShell.AdjustRowHeight( aWorkRange.aStart.Row(), aWorkRange.aEnd.Row(), aWorkRange.aStart.Tab() ) )
1703
0
        rDocShell.PostPaint( aWorkRange, PaintPartFlags::Grid );
1704
1705
0
    rDocShell.PostDataChanged();
1706
0
    ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell();
1707
0
    if (pViewShell)
1708
0
        pViewShell->CellContentChanged();
1709
0
}
1710
1711
void ScUndoUpdateAreaLink::Undo()
1712
0
{
1713
0
    ScDocument& rDoc = rDocShell.GetDocument();
1714
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1715
0
    ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aNewDoc, aNewFlt, aNewOpt,
1716
0
                                            aNewArea, aNewRange );
1717
0
    if (pLink)
1718
0
    {
1719
0
        pLink->SetSource( aOldDoc, aOldFlt, aOldOpt, aOldArea );        // old data in Link
1720
0
        pLink->SetDestArea( aOldRange );
1721
0
        pLink->SetRefreshDelay( nOldRefresh );
1722
0
    }
1723
1724
0
    DoChange(true);
1725
0
}
1726
1727
void ScUndoUpdateAreaLink::Redo()
1728
0
{
1729
0
    ScDocument& rDoc = rDocShell.GetDocument();
1730
0
    sfx2::LinkManager* pLinkManager = rDoc.GetLinkManager();
1731
0
    ScAreaLink* pLink = lcl_FindAreaLink( pLinkManager, aOldDoc, aOldFlt, aOldOpt,
1732
0
                                            aOldArea, aOldRange );
1733
0
    if (pLink)
1734
0
    {
1735
0
        pLink->SetSource( aNewDoc, aNewFlt, aNewOpt, aNewArea );        // new values in link
1736
0
        pLink->SetDestArea( aNewRange );
1737
0
        pLink->SetRefreshDelay( nNewRefresh );
1738
0
    }
1739
1740
0
    DoChange(false);
1741
0
}
1742
1743
void ScUndoUpdateAreaLink::Repeat(SfxRepeatTarget& /* rTarget */)
1744
0
{
1745
    // makes no sense
1746
0
}
1747
1748
bool ScUndoUpdateAreaLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const
1749
0
{
1750
0
    return false;
1751
0
}
1752
1753
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */