Coverage Report

Created: 2026-03-31 11:00

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