Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/viewfun6.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 <formula/token.hxx>
21
#include <svx/svdocapt.hxx>
22
#include <sfx2/bindings.hxx>
23
#include <sfx2/dispatch.hxx>
24
#include <sfx2/lokhelper.hxx>
25
#include <svl/stritem.hxx>
26
#include <svl/numformat.hxx>
27
#include <svl/zforlist.hxx>
28
#include <svl/zformat.hxx>
29
#include <vcl/uitest/logger.hxx>
30
#include <vcl/uitest/eventdescription.hxx>
31
#include <vcl/keycod.hxx>
32
#include <vcl/keycodes.hxx>
33
#include <editeng/editview.hxx>
34
#include <rtl/math.hxx>
35
#include <sal/log.hxx>
36
37
#include <viewfunc.hxx>
38
#include <viewdata.hxx>
39
#include <drwlayer.hxx>
40
#include <docsh.hxx>
41
#include <futext.hxx>
42
#include <docfunc.hxx>
43
#include <sc.hrc>
44
#include <reftokenhelper.hxx>
45
#include <externalrefmgr.hxx>
46
#include <markdata.hxx>
47
#include <drawview.hxx>
48
#include <inputhdl.hxx>
49
#include <tabvwsh.hxx>
50
#include <scmod.hxx>
51
#include <postit.hxx>
52
#include <comphelper/scopeguard.hxx>
53
54
#include <vector>
55
56
namespace
57
{
58
59
void collectUIInformation( const OUString& aevent )
60
0
{
61
0
    EventDescription aDescription;
62
0
    aDescription.aID =  "grid_window";
63
0
    aDescription.aParameters = {{ aevent ,  ""}};
64
0
    aDescription.aAction = "COMMENT";
65
0
    aDescription.aParent = "MainWindow";
66
0
    aDescription.aKeyWord = "ScGridWinUIObject";
67
0
    UITestLogger::getInstance().logEvent(aDescription);
68
0
}
69
70
}
71
72
void ScViewFunc::DetectiveAddPred()
73
0
{
74
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
75
0
    pDocSh->GetDocFunc().DetectiveAddPred( GetViewData().GetCurPos() );
76
0
    RecalcPPT();    //! use broadcast in DocFunc instead?
77
0
}
78
79
void ScViewFunc::DetectiveDelPred()
80
0
{
81
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
82
0
    pDocSh->GetDocFunc().DetectiveDelPred( GetViewData().GetCurPos() );
83
0
    RecalcPPT();
84
0
}
85
86
void ScViewFunc::DetectiveAddSucc()
87
0
{
88
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
89
0
    pDocSh->GetDocFunc().DetectiveAddSucc( GetViewData().GetCurPos() );
90
0
    RecalcPPT();
91
0
}
92
93
void ScViewFunc::DetectiveDelSucc()
94
0
{
95
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
96
0
    pDocSh->GetDocFunc().DetectiveDelSucc( GetViewData().GetCurPos() );
97
0
    RecalcPPT();
98
0
}
99
100
void ScViewFunc::DetectiveAddError()
101
0
{
102
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
103
0
    pDocSh->GetDocFunc().DetectiveAddError( GetViewData().GetCurPos() );
104
0
    RecalcPPT();
105
0
}
106
107
void ScViewFunc::DetectiveDelAll()
108
0
{
109
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
110
0
    pDocSh->GetDocFunc().DetectiveDelAll( GetViewData().CurrentTabForData() );
111
0
    RecalcPPT();
112
0
}
113
114
void ScViewFunc::DetectiveMarkInvalid()
115
0
{
116
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
117
0
    pDocSh->GetDocFunc().DetectiveMarkInvalid( GetViewData().CurrentTabForData() );
118
0
    RecalcPPT();
119
0
}
120
121
void ScViewFunc::DetectiveRefresh()
122
0
{
123
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
124
0
    pDocSh->GetDocFunc().DetectiveRefresh();
125
0
    RecalcPPT();
126
0
}
127
128
static void lcl_jumpToRange(const ScRange& rRange, ScViewData* pView, const ScDocument& rDoc)
129
0
{
130
0
    OUString aAddrText(rRange.Format(rDoc, ScRefFlags::RANGE_ABS_3D));
131
0
    SfxStringItem aPosItem(SID_CURRENTCELL, aAddrText);
132
0
    SfxBoolItem aUnmarkItem(FN_PARAM_1, true);        // remove existing selection
133
0
    pView->GetDispatcher().ExecuteList(
134
0
        SID_CURRENTCELL, SfxCallMode::SYNCHRON | SfxCallMode::RECORD,
135
0
        { &aPosItem, &aUnmarkItem });
136
0
}
137
138
void ScViewFunc::MarkAndJumpToRanges(const ScRangeList& rRanges)
139
0
{
140
0
    ScViewData& rView = GetViewData();
141
0
    ScDocShell* pDocSh = rView.GetDocShell();
142
143
0
    ScRangeList aRangesToMark;
144
0
    ScAddress aCurPos = rView.GetCurPos();
145
0
    size_t ListSize = rRanges.size();
146
0
    for ( size_t i = 0; i < ListSize; ++i )
147
0
    {
148
0
        const ScRange & r = rRanges[i];
149
        // Collect only those ranges that are on the same sheet as the current
150
        // cursor.
151
0
        if (r.aStart.Tab() == aCurPos.Tab())
152
0
            aRangesToMark.push_back(r);
153
0
    }
154
155
0
    if (aRangesToMark.empty())
156
0
        return;
157
158
    // Jump to the first range of all precedent ranges.
159
0
    const ScRange & r = aRangesToMark.front();
160
0
    lcl_jumpToRange(r, &rView, pDocSh->GetDocument());
161
162
0
    ListSize = aRangesToMark.size();
163
0
    for ( size_t i = 0; i < ListSize; ++i )
164
0
    {
165
0
        MarkRange(aRangesToMark[i], false, true);
166
0
    }
167
0
}
168
169
void ScViewFunc::DetectiveMarkPred()
170
0
{
171
0
    ScViewData& rView = GetViewData();
172
0
    ScDocShell* pDocSh = rView.GetDocShell();
173
0
    ScDocument& rDoc = pDocSh->GetDocument();
174
0
    ScMarkData& rMarkData = rView.GetMarkData();
175
0
    ScAddress aCurPos = rView.GetCurPos();
176
0
    ScRangeList aRanges;
177
0
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
178
0
        rMarkData.FillRangeListWithMarks(&aRanges, false);
179
0
    else
180
0
        aRanges.push_back(ScRange(aCurPos));
181
182
0
    std::vector<ScTokenRef> aRefTokens;
183
0
    pDocSh->GetDocFunc().DetectiveCollectAllPreds(aRanges, aRefTokens);
184
185
0
    if (aRefTokens.empty())
186
        // No precedents found.  Nothing to do.
187
0
        return;
188
189
0
    ScTokenRef p = aRefTokens.front();
190
0
    if (ScRefTokenHelper::isExternalRef(p))
191
0
    {
192
        // This is external.  Open the external document if available, and
193
        // jump to the destination.
194
195
0
        sal_uInt16 nFileId = p->GetIndex();
196
0
        ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
197
0
        const OUString* pPath = pRefMgr->getExternalFileName(nFileId);
198
199
0
        ScRange aRange;
200
0
        if (pPath && ScRefTokenHelper::getRangeFromToken(&rDoc, aRange, p, aCurPos, true))
201
0
        {
202
0
            OUString aTabName = p->GetString().getString();
203
0
            OUString aRangeStr(aRange.Format(rDoc, ScRefFlags::VALID));
204
0
            OUString sUrl =
205
0
                *pPath +
206
0
                "#" +
207
0
                aTabName +
208
0
                "." +
209
0
                aRangeStr;
210
211
0
            ScGlobal::OpenURL(sUrl, OUString());
212
0
        }
213
0
        return;
214
0
    }
215
0
    else
216
0
    {
217
0
        ScRange aRange;
218
0
        ScRefTokenHelper::getRangeFromToken(&rDoc, aRange, p, aCurPos);
219
0
        if (aRange.aStart.Tab() != aCurPos.Tab())
220
0
        {
221
            // The first precedent range is on a different sheet.  Jump to it
222
            // immediately and forget the rest.
223
0
            lcl_jumpToRange(aRange, &rView, rDoc);
224
0
            return;
225
0
        }
226
0
    }
227
228
0
    ScRangeList aDestRanges;
229
0
    ScRefTokenHelper::getRangeListFromTokens(&rDoc, aDestRanges, aRefTokens, aCurPos);
230
0
    MarkAndJumpToRanges(aDestRanges);
231
0
}
232
233
void ScViewFunc::DetectiveMarkSucc()
234
0
{
235
0
    ScViewData& rView = GetViewData();
236
0
    ScDocShell* pDocSh = rView.GetDocShell();
237
0
    ScMarkData& rMarkData = rView.GetMarkData();
238
0
    ScAddress aCurPos = rView.GetCurPos();
239
0
    ScRangeList aRanges;
240
0
    if (rMarkData.IsMarked() || rMarkData.IsMultiMarked())
241
0
        rMarkData.FillRangeListWithMarks(&aRanges, false);
242
0
    else
243
0
        aRanges.push_back(ScRange(aCurPos));
244
245
0
    std::vector<ScTokenRef> aRefTokens;
246
0
    pDocSh->GetDocFunc().DetectiveCollectAllSuccs(aRanges, aRefTokens);
247
248
0
    if (aRefTokens.empty())
249
        // No dependents found.  Nothing to do.
250
0
        return;
251
252
0
    ScRangeList aDestRanges;
253
0
    ScRefTokenHelper::getRangeListFromTokens(&rView.GetDocument(), aDestRanges, aRefTokens, aCurPos);
254
0
    MarkAndJumpToRanges(aDestRanges);
255
0
}
256
257
/** Insert date or time into current cell.
258
259
    If cell is in input or edit mode, insert date/time at cursor position, else
260
    create a date or time or date+time cell as follows:
261
262
    - key date on time cell  =>  current date + time of cell  =>  date+time formatted cell
263
      - unless time cell was empty or 00:00 time  =>  current date  =>  date formatted cell
264
    - key date on date+time cell  =>  current date + 00:00 time  =>  date+time formatted cell
265
      - unless date was current date  =>  current date  =>  date formatted cell
266
    - key date on other cell  =>  current date  =>  date formatted cell
267
    - key time on date cell  =>  date of cell + current time  =>  date+time formatted cell
268
      - unless date cell was empty  =>  current time  =>  time formatted cell
269
    - key time on date+time cell  =>  current time  =>  time formatted cell
270
      - unless cell was empty  =>  current date+time  =>  date+time formatted cell
271
    - key time on other cell  =>  current time  =>  time formatted cell
272
 */
273
void ScViewFunc::InsertCurrentTime(SvNumFormatType nReqFmt, const OUString& rUndoStr)
274
0
{
275
0
    ScViewData& rViewData = GetViewData();
276
277
0
    ScInputHandler* pInputHdl = ScModule::get()->GetInputHdl(rViewData.GetViewShell());
278
0
    bool bInputMode = (pInputHdl && pInputHdl->IsInputMode());
279
280
0
    ScDocShell* pDocSh = rViewData.GetDocShell();
281
0
    ScDocument& rDoc = pDocSh->GetDocument();
282
0
    ScAddress aCurPos = rViewData.GetCurPos();
283
0
    const sal_uInt32 nCurNumFormat = rDoc.GetNumberFormat(ScRange(aCurPos));
284
0
    SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
285
0
    const SvNumberformat* pCurNumFormatEntry = pFormatter->GetEntry(nCurNumFormat);
286
0
    const SvNumFormatType nCurNumFormatType = (pCurNumFormatEntry ?
287
0
            pCurNumFormatEntry->GetMaskedType() : SvNumFormatType::UNDEFINED);
288
289
0
    const int nView(comphelper::LibreOfficeKit::isActive() ? SfxLokHelper::getCurrentView() : -1);
290
0
    if (nView >= 0)
291
0
    {
292
0
        const auto [isTimezoneSet, aTimezone] = SfxLokHelper::getViewTimezone(nView);
293
0
        comphelper::LibreOfficeKit::setTimezone(isTimezoneSet, aTimezone);
294
0
    }
295
296
0
    comphelper::ScopeGuard aAutoUserTimezone(
297
0
        [nView]()
298
0
        {
299
0
            if (nView >= 0)
300
0
            {
301
0
                const auto [isTimezoneSet, aTimezone] = SfxLokHelper::getDefaultTimezone();
302
0
                comphelper::LibreOfficeKit::setTimezone(isTimezoneSet, aTimezone);
303
0
            }
304
0
        });
305
306
0
    if (bInputMode)
307
0
    {
308
0
        double fVal = 0.0;
309
0
        sal_uInt32 nFormat = 0;
310
0
        switch (nReqFmt)
311
0
        {
312
0
            case SvNumFormatType::DATE:
313
0
                {
314
0
                    Date aActDate( Date::SYSTEM );
315
0
                    fVal = aActDate - pFormatter->GetNullDate();
316
0
                    if (nCurNumFormatType == SvNumFormatType::DATE)
317
0
                        nFormat = nCurNumFormat;
318
0
                }
319
0
                break;
320
0
            case SvNumFormatType::TIME:
321
0
                {
322
0
                    tools::Time aActTime( tools::Time::SYSTEM );
323
0
                    fVal = aActTime.GetTimeInDays();
324
0
                    if (nCurNumFormatType == SvNumFormatType::TIME)
325
0
                        nFormat = nCurNumFormat;
326
0
                }
327
0
                break;
328
0
            default:
329
0
                SAL_WARN("sc.ui","unhandled current date/time request");
330
0
                nReqFmt = SvNumFormatType::DATETIME;
331
0
                [[fallthrough]];
332
0
            case SvNumFormatType::DATETIME:
333
0
                {
334
0
                    DateTime aActDateTime( DateTime::SYSTEM );
335
0
                    fVal = DateTime::Sub( aActDateTime, DateTime( pFormatter->GetNullDate()));
336
0
                    if (nCurNumFormatType == SvNumFormatType::DATETIME)
337
0
                        nFormat = nCurNumFormat;
338
0
                }
339
0
                break;
340
0
        }
341
342
0
        if (!nFormat)
343
0
        {
344
0
            const LanguageType nLang = (pCurNumFormatEntry ? pCurNumFormatEntry->GetLanguage() : ScGlobal::eLnge);
345
0
            nFormat = pFormatter->GetStandardFormat( nReqFmt, nLang);
346
            // This would return a more precise format with seconds and 100th
347
            // seconds for a time request.
348
            //nFormat = pFormatter->GetStandardFormat( fVal, nFormat, nReqFmt, nLang);
349
0
        }
350
0
        OUString aString;
351
0
        const Color* pColor;
352
0
        pFormatter->GetOutputString( fVal, nFormat, aString, &pColor);
353
354
0
        pInputHdl->DataChanging();
355
0
        EditView* pTopView = pInputHdl->GetTopView();
356
0
        if (pTopView)
357
0
            pTopView->InsertText( aString);
358
0
        EditView* pTableView = pInputHdl->GetTableView();
359
0
        if (pTableView)
360
0
            pTableView->InsertText( aString);
361
0
        pInputHdl->DataChanged();
362
0
    }
363
0
    else
364
0
    {
365
        // Clear "Enter pastes" mode.
366
0
        rViewData.SetPasteMode( ScPasteFlags::NONE );
367
        // Clear CopySourceOverlay in each window of a split/frozen tabview.
368
0
        rViewData.GetViewShell()->UpdateCopySourceOverlay();
369
370
0
        bool bForceReqFmt = false;
371
0
        const double fCell = rDoc.GetValue( aCurPos);
372
        // Combine requested date/time stamp with existing cell time/date, if any.
373
0
        switch (nReqFmt)
374
0
        {
375
0
            case SvNumFormatType::DATE:
376
0
                switch (nCurNumFormatType)
377
0
                {
378
0
                    case SvNumFormatType::TIME:
379
                        // An empty cell formatted as time (or 00:00 time) shall
380
                        // not result in the current date with 00:00 time, but only
381
                        // in current date.
382
0
                        if (fCell != 0.0)
383
0
                            nReqFmt = SvNumFormatType::DATETIME;
384
0
                        break;
385
0
                    case SvNumFormatType::DATETIME:
386
0
                        {
387
                            // Force to only date if the existing date+time is the
388
                            // current date. This way inserting current date twice
389
                            // on an existing date+time cell can be used to force
390
                            // date, which otherwise would only be possible by
391
                            // applying a date format.
392
0
                            double fDate = rtl::math::approxFloor( fCell);
393
0
                            if (fDate == (Date( Date::SYSTEM) - pFormatter->GetNullDate()))
394
0
                                bForceReqFmt = true;
395
0
                        }
396
0
                        break;
397
0
                    default: break;
398
0
                }
399
0
                break;
400
0
            case SvNumFormatType::TIME:
401
0
                switch (nCurNumFormatType)
402
0
                {
403
0
                    case SvNumFormatType::DATE:
404
                        // An empty cell formatted as date shall not result in the
405
                        // null date and current time, but only in current time.
406
0
                        if (fCell != 0.0)
407
0
                            nReqFmt = SvNumFormatType::DATETIME;
408
0
                        break;
409
0
                    case SvNumFormatType::DATETIME:
410
                        // Requesting current time on an empty date+time cell
411
                        // inserts both current date+time.
412
0
                        if (fCell == 0.0)
413
0
                            nReqFmt = SvNumFormatType::DATETIME;
414
0
                        else
415
0
                        {
416
                            // Add current time to an existing date+time where time is
417
                            // zero and date is current date, else force time only.
418
0
                            double fDate = rtl::math::approxFloor( fCell);
419
0
                            double fTime = fCell - fDate;
420
0
                            if (fTime == 0.0 && fDate == (Date( Date::SYSTEM) - pFormatter->GetNullDate()))
421
0
                                nReqFmt = SvNumFormatType::DATETIME;
422
0
                            else
423
0
                                bForceReqFmt = true;
424
0
                        }
425
0
                        break;
426
0
                    default: break;
427
0
                }
428
0
                break;
429
0
            default:
430
0
                SAL_WARN("sc.ui","unhandled current date/time request");
431
0
                nReqFmt = SvNumFormatType::DATETIME;
432
0
                [[fallthrough]];
433
0
            case SvNumFormatType::DATETIME:
434
0
                break;
435
0
        }
436
0
        double fVal = 0.0;
437
0
        switch (nReqFmt)
438
0
        {
439
0
            case SvNumFormatType::DATE:
440
0
                {
441
0
                    Date aActDate( Date::SYSTEM );
442
0
                    fVal = aActDate - pFormatter->GetNullDate();
443
0
                }
444
0
                break;
445
0
            case SvNumFormatType::TIME:
446
0
                {
447
0
                    tools::Time aActTime( tools::Time::SYSTEM );
448
0
                    fVal = aActTime.GetTimeInDays();
449
0
                }
450
0
                break;
451
0
            case SvNumFormatType::DATETIME:
452
0
                switch (nCurNumFormatType)
453
0
                {
454
0
                    case SvNumFormatType::DATE:
455
0
                        {
456
0
                            double fDate = rtl::math::approxFloor( fCell);
457
0
                            tools::Time aActTime( tools::Time::SYSTEM );
458
0
                            fVal = fDate + aActTime.GetTimeInDays();
459
0
                        }
460
0
                        break;
461
0
                    case SvNumFormatType::TIME:
462
0
                        {
463
0
                            double fTime = fCell - rtl::math::approxFloor( fCell);
464
0
                            Date aActDate( Date::SYSTEM );
465
0
                            fVal = (aActDate - pFormatter->GetNullDate()) + fTime;
466
0
                        }
467
0
                        break;
468
0
                    default:
469
0
                        {
470
0
                            DateTime aActDateTime( DateTime::SYSTEM );
471
0
                            fVal = DateTime::Sub( aActDateTime, DateTime( pFormatter->GetNullDate()));
472
0
                        }
473
0
                }
474
0
                break;
475
0
            default: break;
476
477
0
        }
478
479
0
        SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
480
0
        pUndoMgr->EnterListAction(rUndoStr, rUndoStr, 0, rViewData.GetViewShell()->GetViewShellId());
481
482
0
        pDocSh->GetDocFunc().SetValueCell(aCurPos, fVal, true);
483
484
        // Set the new cell format only when it differs from the current cell
485
        // format type. Preserve a date+time format unless we force a format
486
        // through.
487
0
        if (bForceReqFmt || (nReqFmt != nCurNumFormatType && nCurNumFormatType != SvNumFormatType::DATETIME))
488
0
            SetNumberFormat(nReqFmt);
489
0
        else
490
0
            rViewData.UpdateInputHandler();     // update input bar with new value
491
492
0
        pUndoMgr->LeaveListAction();
493
0
    }
494
0
}
495
496
void ScViewFunc::ShowNote( bool bShow )
497
0
{
498
0
    if( bShow )
499
0
        HideNoteOverlay();
500
0
    const ScViewData& rViewData = GetViewData();
501
0
    ScAddress aPos( rViewData.GetCurX(), rViewData.GetCurY(), rViewData.CurrentTabForData() );
502
    // show note moved to ScDocFunc, to be able to use it in notesuno.cxx
503
0
    rViewData.GetDocShell()->GetDocFunc().ShowNote( aPos, bShow );
504
0
}
505
506
void ScViewFunc::EditNote()
507
0
{
508
    // HACK: If another text object is selected, make sure it gets unselected
509
0
    if (FuText* pOldFuText = dynamic_cast<FuText*>(GetDrawFuncPtr()))
510
0
        pOldFuText->KeyInput(KeyEvent(0, vcl::KeyCode(KEY_ESCAPE)));
511
512
    // for editing display and activate
513
514
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
515
0
    ScDocument& rDoc = pDocSh->GetDocument();
516
0
    SCCOL nCol = GetViewData().GetCurX();
517
0
    SCROW nRow = GetViewData().GetCurY();
518
0
    SCTAB nTab = GetViewData().CurrentTabForData();
519
0
    ScAddress aPos( nCol, nRow, nTab );
520
521
    // start drawing undo to catch undo action for insertion of the caption object
522
0
    pDocSh->MakeDrawLayer();
523
0
    ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
524
0
    pDrawLayer->BeginCalcUndo(true);
525
    // generated undo action is processed in FuText::StopEditMode
526
527
    // get existing note or create a new note (including caption drawing object)
528
0
    ScPostIt* pNote = rDoc.GetOrCreateNote( aPos );
529
0
    if(!pNote)
530
0
        return;
531
532
    // hide temporary note caption
533
0
    HideNoteOverlay();
534
    // show caption object without changing internal visibility state
535
0
    pNote->ShowCaptionTemp( aPos );
536
537
    /*  Drawing object has been created in ScDocument::GetOrCreateNote() or
538
        in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should
539
        return a caption object. */
540
0
    SdrCaptionObj* pCaption = pNote->GetCaption();
541
0
    if( !pCaption )
542
0
        return;
543
544
0
    if ( ScDrawView* pScDrawView = GetScDrawView() )
545
0
       pScDrawView->SyncForGrid( pCaption );
546
547
    // activate object (as in FuSelection::TestComment)
548
0
    GetViewData().GetDispatcher().Execute( SID_DRAW_NOTEEDIT, SfxCallMode::SYNCHRON | SfxCallMode::RECORD );
549
    // now get the created FuText and set into EditMode
550
0
    FuText* pFuText = dynamic_cast<FuText*>(GetDrawFuncPtr());
551
0
    if (pFuText)
552
0
    {
553
0
        ScrollToObject( pCaption );         // make object fully visible
554
0
        pFuText->SetInEditMode( pCaption );
555
556
0
        ScTabView::OnLOKNoteStateChanged( pNote );
557
0
    }
558
0
    collectUIInformation(u"OPEN"_ustr);
559
0
}
560
561
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */