Coverage Report

Created: 2026-07-10 11:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/cellsh.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 <scitems.hxx>
21
22
#include <svl/slstitm.hxx>
23
#include <svl/stritem.hxx>
24
#include <svl/whiter.hxx>
25
#include <svtools/cliplistener.hxx>
26
#include <svtools/insdlg.hxx>
27
#include <sot/formats.hxx>
28
#include <svx/hlnkitem.hxx>
29
#include <sfx2/bindings.hxx>
30
#include <sfx2/childwin.hxx>
31
#include <sfx2/objface.hxx>
32
#include <sfx2/request.hxx>
33
#include <sfx2/toolbarids.hxx>
34
#include <sfx2/viewfrm.hxx>
35
#include <vcl/EnumContext.hxx>
36
#include <vcl/svapp.hxx>
37
#include <vcl/weld/Dialog.hxx>
38
#include <svx/clipfmtitem.hxx>
39
#include <svx/statusitem.hxx>
40
41
#include <cellsh.hxx>
42
#include <sc.hrc>
43
#include <docsh.hxx>
44
#include <attrib.hxx>
45
#include <tabvwsh.hxx>
46
#include <formulacell.hxx>
47
#include <scmod.hxx>
48
#include <globstr.hrc>
49
#include <scresid.hxx>
50
#include <transobj.hxx>
51
#include <drwtrans.hxx>
52
#include <scabstdlg.hxx>
53
#include <postit.hxx>
54
#include <cliputil.hxx>
55
#include <clipparam.hxx>
56
#include <markdata.hxx>
57
#include <gridwin.hxx>
58
59
#define ShellClass_ScCellShell
60
#define ShellClass_CellMovement
61
#include <scslots.hxx>
62
63
64
SFX_IMPL_INTERFACE(ScCellShell, ScFormatShell)
65
66
void ScCellShell::InitInterface_Impl()
67
11
{
68
11
    GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_OBJECT,
69
11
                                            SfxVisibilityFlags::Standard | SfxVisibilityFlags::Server,
70
11
                                            ToolbarId::Objectbar_Format);
71
72
11
    GetStaticInterface()->RegisterPopupMenu(u"cell"_ustr);
73
11
}
74
75
ScCellShell::ScCellShell(ScViewData& rData, const VclPtr<vcl::Window>& frameWin) :
76
0
    ScFormatShell(rData),
77
0
    pImpl( new CellShell_Impl() ),
78
0
    bPastePossible(false),
79
0
    pFrameWin(frameWin)
80
0
{
81
0
    SetName(u"Cell"_ustr);
82
0
    SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::Cell));
83
0
}
84
85
ScCellShell::~ScCellShell()
86
0
{
87
0
    if ( pImpl->m_xClipEvtLstnr.is() )
88
0
    {
89
0
        pImpl->m_xClipEvtLstnr->RemoveListener( GetViewData().GetActiveWin() );
90
91
        //  The listener may just now be waiting for the SolarMutex and call the link
92
        //  afterwards, in spite of RemoveListener. So the link has to be reset, too.
93
0
        pImpl->m_xClipEvtLstnr->ClearCallbackLink();
94
95
0
        pImpl->m_xClipEvtLstnr.clear();
96
0
    }
97
98
0
    pImpl->m_pLinkedDlg.disposeAndClear();
99
0
    delete pImpl->m_pRequest;
100
0
}
101
102
void ScCellShell::GetBlockState( SfxItemSet& rSet )
103
0
{
104
0
    ScTabViewShell* pTabViewShell   = GetViewData().GetViewShell();
105
0
    ScRange aMarkRange;
106
0
    ScMarkType eMarkType = GetViewData().GetSimpleArea( aMarkRange );
107
    // tdf#48274 - enable fill operations including filtered rows
108
0
    bool bSimpleArea = (eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED);
109
0
    bool bOnlyNotBecauseOfMatrix;
110
0
    bool bEditable = pTabViewShell->SelectionEditable( &bOnlyNotBecauseOfMatrix );
111
0
    ScDocument& rDoc = GetViewData().GetDocument();
112
0
    ScDocShell* pDocShell = GetViewData().GetDocShell();
113
0
    ScMarkData& rMark = GetViewData().GetMarkData();
114
0
    SCCOL nCol1, nCol2;
115
0
    SCROW nRow1, nRow2;
116
0
    nCol1 = aMarkRange.aStart.Col();
117
0
    nRow1 = aMarkRange.aStart.Row();
118
0
    nCol2 = aMarkRange.aEnd.Col();
119
0
    nRow2 = aMarkRange.aEnd.Row();
120
0
    SCTAB nTab = GetViewData().CurrentTabForData();
121
122
0
    SfxWhichIter aIter(rSet);
123
0
    sal_uInt16 nWhich = aIter.FirstWhich();
124
0
    while ( nWhich )
125
0
    {
126
0
        bool bDisable = false;
127
0
        bool bNeedEdit = true;      // need selection be editable?
128
0
        switch ( nWhich )
129
0
        {
130
0
            case FID_FILL_TO_BOTTOM:    // fill to top / bottom
131
0
            {
132
0
                bDisable = !bSimpleArea || (nRow1 == 0 && nRow2 == 0);
133
0
                if (!bDisable && GetViewData().SelectionForbidsCellFill())
134
0
                    bDisable = true;
135
0
                if ( !bDisable && bEditable )
136
0
                {   // do not damage matrix
137
0
                    bDisable = rDoc.HasSelectedBlockMatrixFragment(
138
0
                        nCol1, nRow1, nCol2, nRow1, rMark );    // first row
139
0
                }
140
0
            }
141
0
            break;
142
0
            case FID_FILL_TO_TOP:
143
0
            {
144
0
                bDisable = (!bSimpleArea) || (nRow1 == rDoc.MaxRow() && nRow2 == rDoc.MaxRow());
145
0
                if (!bDisable && GetViewData().SelectionForbidsCellFill())
146
0
                    bDisable = true;
147
0
                if ( !bDisable && bEditable )
148
0
                {   // do not damage matrix
149
0
                    bDisable = rDoc.HasSelectedBlockMatrixFragment(
150
0
                        nCol1, nRow2, nCol2, nRow2, rMark );    // last row
151
0
                }
152
0
            }
153
0
            break;
154
0
            case FID_FILL_TO_RIGHT:     // fill to left / right
155
0
            {
156
0
                bDisable = !bSimpleArea || (nCol1 == 0 && nCol2 == 0);
157
0
                if (!bDisable && GetViewData().SelectionForbidsCellFill())
158
0
                    bDisable = true;
159
0
                if ( !bDisable && bEditable )
160
0
                {   // do not damage matrix
161
0
                    bDisable = rDoc.HasSelectedBlockMatrixFragment(
162
0
                            nCol1, nRow1, nCol1, nRow2, rMark );    // first column
163
0
                }
164
0
            }
165
0
            break;
166
0
            case FID_FILL_TO_LEFT:
167
0
            {
168
0
                bDisable = (!bSimpleArea) || (nCol1 == rDoc.MaxCol() && nCol2 == rDoc.MaxCol());
169
0
                if (!bDisable && GetViewData().SelectionForbidsCellFill())
170
0
                    bDisable = true;
171
0
                if ( !bDisable && bEditable )
172
0
                {   // do not damage matrix
173
0
                    bDisable = rDoc.HasSelectedBlockMatrixFragment(
174
0
                        nCol2, nRow1, nCol2, nRow2, rMark );    // last column
175
0
                }
176
0
            }
177
0
            break;
178
179
0
            case SID_RANDOM_NUMBER_GENERATOR_DIALOG:
180
0
                bDisable = !bSimpleArea || GetViewData().SelectionForbidsCellFill();
181
0
            break;
182
0
            case SID_SAMPLING_DIALOG:
183
0
            case SID_DESCRIPTIVE_STATISTICS_DIALOG:
184
0
            case SID_ANALYSIS_OF_VARIANCE_DIALOG:
185
0
            case SID_CORRELATION_DIALOG:
186
0
            case SID_COVARIANCE_DIALOG:
187
0
            case SID_INSERT_SPARKLINE:
188
0
            {
189
0
                bDisable = !bSimpleArea;
190
0
            }
191
0
            break;
192
0
            case SID_GROUP_SPARKLINES:
193
0
            case SID_UNGROUP_SPARKLINES:
194
0
            {
195
0
                bDisable = !bSimpleArea;
196
0
            }
197
0
            break;
198
199
0
            case SID_EDIT_SPARKLINE:
200
0
            {
201
0
                bDisable = !rDoc.HasSparkline(GetViewData().GetCurPos());
202
0
            }
203
0
            break;
204
205
0
            case SID_DELETE_SPARKLINE:
206
0
            case SID_EDIT_SPARKLINE_GROUP:
207
0
            case SID_DELETE_SPARKLINE_GROUP:
208
0
            {
209
0
                bDisable = !rDoc.HasOneSparklineGroup(ScRange(nCol1, nRow1, nTab, nCol2, nRow2, nTab));
210
0
            }
211
0
            break;
212
213
0
            case FID_FILL_SERIES:       // fill block
214
0
            case SID_OPENDLG_TABOP:     // multiple-cell operations, are at least 2 cells marked?
215
0
                if (rDoc.GetChangeTrack()!=nullptr &&nWhich ==SID_OPENDLG_TABOP)
216
0
                    bDisable = true;
217
0
                else
218
0
                    bDisable = (!bSimpleArea) || (nCol1 == nCol2 && nRow1 == nRow2);
219
220
0
                if (!bDisable && GetViewData().SelectionForbidsCellFill())
221
0
                    bDisable = true;
222
223
0
                if ( !bDisable && bEditable && nWhich == FID_FILL_SERIES )
224
0
                {   // do not damage matrix
225
0
                    bDisable = rDoc.HasSelectedBlockMatrixFragment(
226
0
                            nCol1, nRow1, nCol2, nRow1, rMark )     // first row
227
0
                        ||  rDoc.HasSelectedBlockMatrixFragment(
228
0
                            nCol1, nRow2, nCol2, nRow2, rMark )     // last row
229
0
                        ||  rDoc.HasSelectedBlockMatrixFragment(
230
0
                            nCol1, nRow1, nCol1, nRow2, rMark )     // first column
231
0
                        ||  rDoc.HasSelectedBlockMatrixFragment(
232
0
                            nCol2, nRow1, nCol2, nRow2, rMark );    // last column
233
0
                }
234
0
                break;
235
0
            case FID_FILL_SINGLE_EDIT:
236
0
                bDisable = false;
237
0
                break;
238
0
            case SID_CUT:               // cut
239
0
            case SID_COPYDELETE:
240
0
                bDisable = !bSimpleArea || GetObjectShell()->isContentExtractionLocked();
241
0
                break;
242
0
            case FID_INS_CELL:          // insert cells, just simple selection
243
0
                bDisable = (!bSimpleArea);
244
0
                break;
245
246
0
            case SID_PASTE:
247
0
            case SID_PASTE_SPECIAL:
248
0
            case SID_PASTE_UNFORMATTED:
249
0
            case SID_PASTE_ONLY_VALUE:
250
0
            case SID_PASTE_ONLY_TEXT:
251
0
            case SID_PASTE_ONLY_FORMULA:
252
0
            case SID_PASTE_TRANSPOSED:
253
0
            case SID_PASTE_AS_LINK:
254
0
            case SID_PASTE_TEXTIMPORT_DIALOG:
255
0
                bDisable = GetViewData().SelectionForbidsPaste();
256
0
                break;
257
258
0
            case FID_INS_ROW:
259
0
            case FID_INS_ROWS_BEFORE:           // insert rows
260
0
            case FID_INS_ROWS_AFTER:
261
0
            {
262
0
                sc::EditAction eAction = sc::EditAction::InsertRowsBefore;
263
0
                if (nWhich == FID_INS_ROWS_AFTER)
264
0
                    eAction = sc::EditAction::InsertRowsAfter;
265
266
0
                bDisable = (!bSimpleArea) || GetViewData().SimpleColMarked();
267
0
                if (!bEditable && nCol1 == 0 && nCol2 == rDoc.MaxCol())
268
0
                {
269
                    // See if row insertions are allowed.
270
0
                    bEditable = rDoc.IsEditActionAllowed(eAction, rMark, nCol1, nRow1, nCol2, nRow2);
271
0
                }
272
0
                break;
273
0
            }
274
0
            case FID_INS_CELLSDOWN:
275
0
                bDisable = (!bSimpleArea) || GetViewData().SimpleColMarked();
276
0
                break;
277
278
0
            case FID_INS_COLUMN:
279
0
            case FID_INS_COLUMNS_BEFORE:        // insert columns
280
0
            case FID_INS_COLUMNS_AFTER:
281
0
            {
282
0
                sc::EditAction eAction = sc::EditAction::InsertColumnsBefore;
283
0
                if (nWhich == FID_INS_COLUMNS_AFTER)
284
0
                    eAction = sc::EditAction::InsertColumnsAfter;
285
286
0
                bDisable = (!bSimpleArea && eMarkType != SC_MARK_SIMPLE_FILTERED)
287
0
                           || GetViewData().SimpleRowMarked();
288
0
                if (!bEditable && nRow1 == 0 && nRow2 == rDoc.MaxRow())
289
0
                {
290
                    // See if row insertions are allowed.
291
0
                    bEditable = rDoc.IsEditActionAllowed(eAction, rMark, nCol1, nRow1, nCol2, nRow2);
292
0
                }
293
0
                break;
294
0
            }
295
0
            case FID_INS_CELLSRIGHT:
296
0
                bDisable = (!bSimpleArea) || GetViewData().SimpleRowMarked();
297
0
                break;
298
299
0
            case SID_COPY:              // copy
300
0
            case SID_COPY_HYPERLINK_LOCATION:
301
                // Copy is a read-only operation — it never requires an
302
                // editable selection.  The only reason to grey it out is
303
                // content-extraction lock (DRM).
304
0
                bNeedEdit = false;
305
0
                bDisable = GetObjectShell()->isContentExtractionLocked();
306
0
                break;
307
308
0
            case SID_AUTOFORMAT:        // Autoformat, at least 3x3 selected
309
0
                bDisable =    (!bSimpleArea)
310
0
                           || ((nCol2 - nCol1) < 2) || ((nRow2 - nRow1) < 2);
311
0
                break;
312
313
0
            case SID_CELL_FORMAT_RESET :
314
0
            case FID_CELL_FORMAT :
315
0
            case SID_ENABLE_HYPHENATION :
316
                // not editable because of matrix only? Attribute ok nonetheless
317
0
                if ( !bEditable && bOnlyNotBecauseOfMatrix )
318
0
                    bNeedEdit = false;
319
0
                break;
320
321
0
            case FID_CURRENTVALIDATION:
322
0
            case FID_VALIDATION:
323
0
                {
324
0
                    if ( pDocShell && pDocShell->IsDocShared() )
325
0
                    {
326
0
                        bDisable = true;
327
0
                    }
328
0
                }
329
0
                break;
330
0
            case SID_TRANSLITERATE_HALFWIDTH:
331
0
            case SID_TRANSLITERATE_FULLWIDTH:
332
0
            case SID_TRANSLITERATE_HIRAGANA:
333
0
            case SID_TRANSLITERATE_KATAKANA:
334
0
                ScViewUtil::HideDisabledSlot( rSet, GetViewData().GetBindings(), nWhich );
335
0
            break;
336
0
            case SID_CONVERT_FORMULA_TO_VALUE:
337
0
            {
338
                // Check and see if the marked range has at least one formula cell.
339
0
                bDisable = !rDoc.HasFormulaCell(aMarkRange);
340
0
            }
341
0
            break;
342
0
        }
343
0
        if (!bDisable && bNeedEdit && !bEditable)
344
0
            bDisable = true;
345
346
0
        if (bDisable)
347
0
            rSet.DisableItem(nWhich);
348
0
        else if (nWhich == SID_ENABLE_HYPHENATION)
349
0
        {
350
            // toggle slots need a bool item
351
0
            rSet.Put( SfxBoolItem( nWhich, false ) );
352
0
        }
353
0
        nWhich = aIter.NextWhich();
354
0
    }
355
0
}
356
357
// functions, disabled depending on cursor position
358
// Default:
359
//     SID_INSERT_POSTIT, SID_CHARMAP, SID_OPENDLG_FUNCTION
360
361
void ScCellShell::GetCellState( SfxItemSet& rSet )
362
0
{
363
0
    ScDocShell* pDocShell = GetViewData().GetDocShell();
364
0
    ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
365
0
    ScAddress aCursor( GetViewData().GetCurX(), GetViewData().GetCurY(),
366
0
                        GetViewData().CurrentTabForData() );
367
0
    SfxWhichIter aIter(rSet);
368
0
    sal_uInt16 nWhich = aIter.FirstWhich();
369
0
    while ( nWhich )
370
0
    {
371
0
        bool bDisable = false;
372
0
        bool bNeedEdit = true;      // need cursor position be editable?
373
0
        switch ( nWhich )
374
0
        {
375
0
            case SID_THESAURUS:
376
0
                {
377
0
                    CellType eType = rDoc.GetCellType( aCursor );
378
0
                    bDisable = ( eType != CELLTYPE_STRING && eType != CELLTYPE_EDIT);
379
0
                    if (!bDisable)
380
0
                    {
381
                        //  test for available languages
382
0
                        LanguageType nLang = ScViewUtil::GetEffLanguage( rDoc, aCursor );
383
0
                        bDisable = !ScModule::HasThesaurusLanguage( nLang );
384
0
                    }
385
0
                }
386
0
                break;
387
0
            case SID_OPENDLG_FUNCTION:
388
0
                {
389
0
                    ScMarkData aMarkData = GetViewData().GetMarkData();
390
0
                    aMarkData.MarkToSimple();
391
0
                    const ScRange& aRange = aMarkData.GetMarkArea();
392
0
                    if(aMarkData.IsMarked())
393
0
                    {
394
0
                        if (!rDoc.IsBlockEditable( aCursor.Tab(), aRange.aStart.Col(),aRange.aStart.Row(),
395
0
                                            aRange.aEnd.Col(),aRange.aEnd.Row() ))
396
0
                        {
397
0
                            bDisable = true;
398
0
                        }
399
0
                        bNeedEdit=false;
400
0
                    }
401
402
0
                }
403
0
                break;
404
0
            case SID_INSERT_POSTIT:
405
0
                {
406
0
                    ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().CurrentTabForData() );
407
0
                    if( rDoc.GetNote(aPos) )
408
0
                    {
409
0
                        bDisable = true;
410
0
                    }
411
0
                    else
412
0
                    {
413
0
                        bDisable = false;
414
0
                        if ( pDocShell && pDocShell->IsDocShared() )
415
0
                        {
416
0
                            bDisable = true;
417
0
                        }
418
0
                    }
419
0
                }
420
0
                break;
421
0
            case SID_EDIT_POSTIT:
422
0
                {
423
0
                    ScAddress aPos( GetViewData().GetCurX(), GetViewData().GetCurY(), GetViewData().CurrentTabForData() );
424
0
                    bDisable = rDoc.GetNote(aPos) == nullptr;
425
0
                }
426
0
                break;
427
0
        }
428
0
        if (!bDisable && bNeedEdit)
429
0
            if (!rDoc.IsBlockEditable( aCursor.Tab(), aCursor.Col(),aCursor.Row(),
430
0
                                        aCursor.Col(),aCursor.Row() ))
431
0
                bDisable = true;
432
0
        if (bDisable)
433
0
            rSet.DisableItem(nWhich);
434
0
        nWhich = aIter.NextWhich();
435
0
    }
436
0
}
437
438
static bool lcl_TestFormat( SvxClipboardFormatItem& rFormats, const TransferableDataHelper& rDataHelper,
439
                        SotClipboardFormatId nFormatId )
440
0
{
441
0
    if ( rDataHelper.HasFormat( nFormatId ) )
442
0
    {
443
        //  translated format name strings are no longer inserted here,
444
        //  handled by "paste special" dialog / toolbox controller instead.
445
        //  Only the object type name has to be set here:
446
0
        OUString aStrVal;
447
0
        if ( nFormatId == SotClipboardFormatId::EMBED_SOURCE )
448
0
        {
449
0
            TransferableObjectDescriptor aDesc;
450
0
            if ( rDataHelper.GetTransferableObjectDescriptor(
451
0
                                        SotClipboardFormatId::OBJECTDESCRIPTOR, aDesc ) )
452
0
                aStrVal = aDesc.maTypeName;
453
0
        }
454
0
        else if ( nFormatId == SotClipboardFormatId::EMBED_SOURCE_OLE
455
0
          || nFormatId == SotClipboardFormatId::EMBEDDED_OBJ_OLE )
456
0
        {
457
0
            OUString aSource;
458
0
            SvPasteObjectHelper::GetEmbeddedName( rDataHelper, aStrVal, aSource, nFormatId );
459
0
        }
460
461
0
        if ( !aStrVal.isEmpty() )
462
0
            rFormats.AddClipbrdFormat( nFormatId, aStrVal );
463
0
        else
464
0
            rFormats.AddClipbrdFormat( nFormatId );
465
466
0
        return true;
467
0
    }
468
469
0
    return false;
470
0
}
471
472
void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats )
473
0
{
474
0
    vcl::Window* pWin = GetViewData().GetActiveWin();
475
0
    bool bDraw = ScDrawTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin)) != nullptr;
476
477
0
    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
478
479
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::DRAWING );
480
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::SVXB );
481
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::GDIMETAFILE );
482
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::PNG );
483
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BITMAP );
484
0
    lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::EMBED_SOURCE );
485
486
0
    if ( !bDraw )
487
0
    {
488
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::LINK );
489
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::STRING );
490
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::STRING_TSVC );
491
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::DIF );
492
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::RTF );
493
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::RICHTEXT );
494
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::HTML );
495
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::HTML_SIMPLE );
496
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_12 );
497
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_8 );
498
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::BIFF_5 );
499
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::MARKDOWN );
500
0
    }
501
502
0
    if ( !lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::EMBED_SOURCE_OLE ) )
503
0
        lcl_TestFormat( rFormats, aDataHelper, SotClipboardFormatId::EMBEDDED_OBJ_OLE );
504
0
}
505
506
//  insert, insert contents
507
508
static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData )
509
0
{
510
0
    bool bPossible = false;
511
0
    css::uno::Reference< css::datatransfer::XTransferable2 > xTransferable(rData.GetXTransferable(), css::uno::UNO_QUERY);
512
0
    if ( ScTransferObj::GetOwnClipboard(xTransferable) || ScDrawTransferObj::GetOwnClipboard(xTransferable) )
513
0
        bPossible = true;
514
0
    else
515
0
    {
516
0
        if ( rData.HasFormat( SotClipboardFormatId::PNG ) ||
517
0
             rData.HasFormat( SotClipboardFormatId::BITMAP ) ||
518
0
             rData.HasFormat( SotClipboardFormatId::GDIMETAFILE ) ||
519
0
             rData.HasFormat( SotClipboardFormatId::SVXB ) ||
520
0
             rData.HasFormat( SotClipboardFormatId::PRIVATE ) ||
521
0
             rData.HasFormat( SotClipboardFormatId::RTF ) ||
522
0
             rData.HasFormat( SotClipboardFormatId::RICHTEXT ) ||
523
0
             rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE ) ||
524
0
             rData.HasFormat( SotClipboardFormatId::LINK_SOURCE ) ||
525
0
             rData.HasFormat( SotClipboardFormatId::EMBED_SOURCE_OLE ) ||
526
0
             rData.HasFormat( SotClipboardFormatId::LINK_SOURCE_OLE ) ||
527
0
             rData.HasFormat( SotClipboardFormatId::EMBEDDED_OBJ_OLE ) ||
528
0
             rData.HasFormat( SotClipboardFormatId::STRING ) ||
529
0
             rData.HasFormat( SotClipboardFormatId::STRING_TSVC ) ||
530
0
             rData.HasFormat( SotClipboardFormatId::SYLK ) ||
531
0
             rData.HasFormat( SotClipboardFormatId::LINK ) ||
532
0
             rData.HasFormat( SotClipboardFormatId::HTML ) ||
533
0
             rData.HasFormat( SotClipboardFormatId::HTML_SIMPLE ) ||
534
0
             rData.HasFormat( SotClipboardFormatId::DIF ) ||
535
0
             rData.HasFormat( SotClipboardFormatId::MARKDOWN ) )
536
0
        {
537
0
            bPossible = true;
538
0
        }
539
0
    }
540
0
    return bPossible;
541
0
}
542
543
bool ScCellShell::HasClipboardFormat( SotClipboardFormatId nFormatId )
544
0
{
545
0
    vcl::Window* pWin = GetViewData().GetActiveWin();
546
0
    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ));
547
0
    return aDataHelper.HasFormat( nFormatId );
548
0
}
549
550
IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
551
0
{
552
0
    bPastePossible = lcl_IsCellPastePossible( *pDataHelper );
553
554
0
    SfxBindings& rBindings = GetViewData().GetBindings();
555
0
    rBindings.Invalidate( SID_PASTE );
556
0
    rBindings.Invalidate( SID_PASTE_SPECIAL );
557
0
    rBindings.Invalidate( SID_PASTE_UNFORMATTED );
558
0
    rBindings.Invalidate( SID_PASTE_ONLY_VALUE );
559
0
    rBindings.Invalidate( SID_PASTE_ONLY_TEXT );
560
0
    rBindings.Invalidate( SID_PASTE_ONLY_FORMULA );
561
0
    rBindings.Invalidate( SID_PASTE_TRANSPOSED );
562
0
    rBindings.Invalidate( SID_PASTE_AS_LINK );
563
0
    rBindings.Invalidate( SID_PASTE_TEXTIMPORT_DIALOG );
564
0
    rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
565
0
}
566
567
namespace {
568
569
bool checkDestRanges(ScViewData& rViewData)
570
0
{
571
0
    ScRange aDummy;
572
0
    ScMarkType eMarkType = rViewData.GetSimpleArea( aDummy);
573
0
    if (eMarkType != SC_MARK_MULTI)
574
0
    {
575
        // Single destination range.
576
0
        if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
577
0
            return false;
578
0
    }
579
580
    // Multiple destination ranges.
581
582
    // Same as ScViewData::SelectionForbidsPaste() in
583
    // sc/source/ui/view/viewdata.cxx but different return details.
584
585
0
    vcl::Window* pWin = rViewData.GetActiveWin();
586
0
    if (!pWin)
587
0
        return false;
588
589
0
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin));
590
0
    if (!pOwnClip)
591
        // If it's not a Calc document, we won't be picky.
592
0
        return true;
593
594
0
    ScDocument* pClipDoc = pOwnClip->GetDocument();
595
0
    if (!pClipDoc)
596
0
        return false;
597
598
0
    ScRange aSrcRange = pClipDoc->GetClipParam().getWholeRange();
599
0
    SCROW nRowSize = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1;
600
0
    SCCOL nColSize = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1;
601
602
0
    if (rViewData.SelectionForbidsPaste( nColSize, nRowSize))
603
0
        return false;
604
605
0
    ScMarkData aMark = rViewData.GetMarkData();
606
0
    ScRangeList aRanges;
607
0
    aMark.MarkToSimple();
608
0
    aMark.FillRangeListWithMarks(&aRanges, false);
609
610
0
    return ScClipUtil::CheckDestRanges(rViewData.GetDocument(), nColSize, nRowSize, aMark, aRanges);
611
0
}
612
613
}
614
615
void ScCellShell::GetClipState( SfxItemSet& rSet )
616
0
{
617
// SID_PASTE
618
// SID_PASTE_SPECIAL
619
// SID_PASTE_UNFORMATTED
620
// SID_CLIPBOARD_FORMAT_ITEMS
621
622
0
    if ( !pImpl->m_xClipEvtLstnr.is() )
623
0
    {
624
        // create listener
625
0
        pImpl->m_xClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScCellShell, ClipboardChanged ) );
626
0
        vcl::Window* pWin = GetViewData().GetActiveWin();
627
0
        pImpl->m_xClipEvtLstnr->AddListener( pWin );
628
629
        // get initial state
630
0
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
631
0
        bPastePossible = lcl_IsCellPastePossible( aDataHelper );
632
0
    }
633
634
0
    bool bDisable = !bPastePossible;
635
0
    bool bOnlyNotBecauseOfMatrix = false;
636
637
    //  cell protection / multiple selection
638
639
0
    if (!bDisable)
640
0
    {
641
0
        SCCOL nCol = GetViewData().GetCurX();
642
0
        SCROW nRow = GetViewData().GetCurY();
643
0
        SCTAB nTab = GetViewData().CurrentTabForData();
644
0
        ScDocument& rDoc = GetViewData().GetDocShell()->GetDocument();
645
0
        if (!rDoc.IsBlockEditable( nTab, nCol,nRow, nCol,nRow,
646
0
                                   &bOnlyNotBecauseOfMatrix ))
647
0
            bDisable = true;
648
649
0
        if (!bDisable && !checkDestRanges(GetViewData()))
650
0
            bDisable = true;
651
0
    }
652
653
0
    if (!ScTransferObj::GetOwnClipboard(
654
0
        ScTabViewShell::GetClipData(GetViewData().GetActiveWin())))
655
0
    {
656
0
        rSet.DisableItem( SID_PASTE_TRANSPOSED );
657
0
    }
658
659
0
    if (bDisable)
660
0
    {
661
0
        rSet.DisableItem( SID_PASTE );
662
0
        rSet.DisableItem( SID_PASTE_SPECIAL );
663
0
        rSet.DisableItem( SID_PASTE_UNFORMATTED );
664
0
        rSet.DisableItem( SID_PASTE_ONLY_VALUE );
665
0
        rSet.DisableItem( SID_PASTE_ONLY_TEXT );
666
0
        rSet.DisableItem( SID_PASTE_ONLY_FORMULA );
667
0
        rSet.DisableItem( SID_PASTE_TRANSPOSED );
668
0
        rSet.DisableItem( SID_PASTE_AS_LINK );
669
0
        rSet.DisableItem( SID_PASTE_TEXTIMPORT_DIALOG );
670
        // tdf#164461: don't disable clipboard format items when the
671
        // cursor is on a matrix cell — the clipboard content is still
672
        // valid and must stay populated so the paste-special toolbar
673
        // dropdown works after the cursor moves to an editable cell.
674
0
        if (!bOnlyNotBecauseOfMatrix)
675
0
            rSet.DisableItem( SID_CLIPBOARD_FORMAT_ITEMS );
676
0
    }
677
678
    // tdf#164461: populate format items even when paste is disabled
679
    // due to a matrix cell, so the dropdown keeps its format list.
680
0
    bool bHasFormatItems = rSet.GetItemState(SID_CLIPBOARD_FORMAT_ITEMS) != SfxItemState::UNKNOWN;
681
0
    if ( bHasFormatItems && ( !bDisable || bOnlyNotBecauseOfMatrix ) )
682
0
    {
683
0
        SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
684
0
        GetPossibleClipboardFormats( aFormats );
685
0
        rSet.Put( aFormats );
686
0
    }
687
0
}
688
689
//  only SID_HYPERLINK_GETLINK:
690
691
void ScCellShell::GetHLinkState( SfxItemSet& rSet )
692
0
{
693
    //  always return an item (or inserting will be disabled)
694
    //  if the cell at the cursor contains only a link, return that link
695
696
0
    SvxHyperlinkItem aHLinkItem;
697
0
    aHLinkItem.SetShowName(false);
698
0
    if ( !GetViewData().GetView()->HasBookmarkAtCursor( &aHLinkItem ) )
699
0
    {
700
        // tdf#80043 - put selected text into item
701
0
        ScViewData& rData       = GetViewData();
702
0
        ScDocument& rDoc        = rData.GetDocument();
703
0
        SCCOL       nPosX       = rData.GetCurX();
704
0
        SCROW       nPosY       = rData.GetCurY();
705
0
        SCTAB       nTab        = rData.CurrentTabForData();
706
0
        aHLinkItem.SetName(rDoc.GetString(nPosX, nPosY, nTab));
707
0
    }
708
709
0
    rSet.Put(aHLinkItem);
710
0
}
711
712
void ScCellShell::GetState(SfxItemSet &rSet)
713
0
{
714
0
    ScTabViewShell* pTabViewShell   = GetViewData().GetViewShell();
715
0
    ScDocShell* pDocSh = GetViewData().GetDocShell();
716
0
    ScViewData& rData       = GetViewData();
717
0
    ScDocument& rDoc        = rData.GetDocument();
718
0
    ScMarkData& rMark       = rData.GetMarkData();
719
0
    SCCOL       nPosX       = rData.GetCurX();
720
0
    SCROW       nPosY       = rData.GetCurY();
721
0
    SCTAB       nTab        = rData.CurrentTabForData();
722
723
0
    SCTAB nTabCount = rDoc.GetTableCount();
724
0
    SCTAB nTabSelCount = rMark.GetSelectCount();
725
726
0
    SfxWhichIter aIter(rSet);
727
0
    sal_uInt16 nWhich = aIter.FirstWhich();
728
0
    while ( nWhich )
729
0
    {
730
0
        switch ( nWhich )
731
0
        {
732
0
            case SID_DETECTIVE_REFRESH:
733
0
                if (!rDoc.HasDetectiveOperations())
734
0
                    rSet.DisableItem( nWhich );
735
0
                break;
736
737
0
            case SID_RANGE_ADDRESS:
738
0
                {
739
0
                    ScRange aRange;
740
0
                    if ( rData.GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
741
0
                    {
742
0
                        OUString aStr(aRange.Format(rDoc, ScRefFlags::VALID | ScRefFlags::TAB_3D));
743
0
                        rSet.Put( SfxStringItem( nWhich, aStr ) );
744
0
                    }
745
0
                }
746
0
                break;
747
748
0
            case SID_RANGE_NOTETEXT:
749
0
                {
750
                    //  always take cursor position, do not use top-left cell of selection
751
0
                    OUString aNoteText;
752
0
                    if ( const ScPostIt* pNote = rDoc.GetNote(nPosX, nPosY, nTab) )
753
0
                        aNoteText = pNote->GetText();
754
0
                    rSet.Put( SfxStringItem( nWhich, aNoteText ) );
755
0
                }
756
0
                break;
757
758
0
            case SID_RANGE_ROW:
759
0
                rSet.Put( SfxInt32Item( SID_RANGE_ROW, nPosY+1 ) );
760
0
                break;
761
762
0
            case SID_RANGE_COL:
763
0
                rSet.Put( SfxInt16Item( SID_RANGE_COL, nPosX+1 ) );
764
0
                break;
765
766
0
            case SID_RANGE_TABLE:
767
0
                rSet.Put( SfxInt16Item( SID_RANGE_TABLE, nTab+1 ) );
768
0
                break;
769
770
0
            case SID_RANGE_FORMULA:
771
0
                {
772
0
                    OUString aString = rDoc.GetFormula( nPosX, nPosY, nTab );
773
0
                    if( aString.isEmpty() )
774
0
                    {
775
0
                        aString = rDoc.GetInputString( nPosX, nPosY, nTab );
776
0
                    }
777
0
                    rSet.Put( SfxStringItem( nWhich, aString ) );
778
0
                }
779
0
                break;
780
781
0
            case SID_RANGE_TEXTVALUE:
782
0
                {
783
0
                    OUString aString = rDoc.GetString(nPosX, nPosY, nTab);
784
0
                    rSet.Put( SfxStringItem( nWhich, aString ) );
785
0
                }
786
0
                break;
787
788
0
            case SID_STATUS_SELMODE:
789
0
                {
790
                    /* 0: STD   Click cancels Sel
791
                     * 1: ER    Click extends selection
792
                     * 2: ERG   Click defines further selection
793
                     */
794
0
                    sal_uInt16 nMode = pTabViewShell->GetLockedModifiers();
795
796
0
                    switch ( nMode )
797
0
                    {
798
0
                        case KEY_SHIFT: nMode = 1;  break;
799
0
                        case KEY_MOD1:  nMode = 2;  break; // Control-key
800
0
                        case 0:
801
0
                        default:
802
0
                            nMode = 0;
803
0
                    }
804
805
0
                    rSet.Put( SfxUInt16Item( nWhich, nMode ) );
806
0
                }
807
0
                break;
808
809
0
            case SID_STATUS_DOCPOS:
810
0
                {
811
0
                    OUString aStr = ScResId( STR_TABLE_COUNT );
812
813
0
                    aStr = aStr.replaceFirst("%1", OUString::number( nTab + 1  ) );
814
0
                    aStr = aStr.replaceFirst("%2", OUString::number( nTabCount ) );
815
816
0
                    rSet.Put( SfxStringItem( nWhich, aStr ) );                }
817
0
                break;
818
819
0
            case SID_ROWCOL_SELCOUNT:
820
0
                {
821
0
                    ScRangeListRef aMarkRanges;
822
0
                    GetViewData().GetMultiArea(aMarkRanges);
823
0
                    const SCCOL nCol1 = aMarkRanges->front().aStart.Col();
824
0
                    const SCROW nRow1 = aMarkRanges->front().aStart.Row();
825
0
                    const SCCOL nCol2 = aMarkRanges->front().aEnd.Col();
826
0
                    const SCROW nRow2 = aMarkRanges->front().aEnd.Row();
827
0
                    const size_t nRanges = aMarkRanges->size();
828
829
0
                    if ((nRanges == 1 && (nCol2 != nCol1 || nRow1 != nRow2)) || nRanges > 1)
830
0
                    {
831
0
                        bool bSameRows = true;
832
0
                        bool bSameCols = true;
833
0
                        SCROW nRowsSum = 0;
834
0
                        SCCOL nColsSum = 0;
835
0
                        for (size_t i = 0; i < nRanges; ++i)
836
0
                        {
837
0
                            const ScRange& rRange = (*aMarkRanges)[i];
838
0
                            const SCCOL nRangeCol1 = rRange.aStart.Col();
839
0
                            const SCROW nRangeRow1 = rRange.aStart.Row();
840
0
                            const SCCOL nRangeCol2 = rRange.aEnd.Col();
841
0
                            const SCROW nRangeRow2 = rRange.aEnd.Row();
842
0
                            bSameRows &= (nRow1 == nRangeRow1 && nRow2 == nRangeRow2);
843
0
                            bSameCols &= (nCol1 == nRangeCol1 && nCol2 == nRangeCol2);
844
                            // Sum rows if the number of cols is the same or
845
                            // sum columns if the number of rows is the same,
846
                            // otherwise do not show any count of selected cells.
847
0
                            if (bSameRows || bSameCols)
848
0
                            {
849
0
                                const auto nCols = nRangeCol2 - nRangeCol1 + 1;
850
0
                                const auto nRows = (bSameCols || nRowsSum == 0) ?
851
0
                                    rDoc.CountNonFilteredRows( nRangeRow1, nRangeRow2, rRange.aStart.Tab()) :
852
0
                                    nRowsSum;
853
0
                                if (bSameRows)
854
0
                                {
855
0
                                    nRowsSum = nRows;
856
0
                                    nColsSum += nCols;
857
0
                                }
858
0
                                else if (bSameCols)
859
0
                                {
860
0
                                    nRowsSum += nRows;
861
0
                                    nColsSum = nCols;
862
0
                                }
863
0
                            }
864
0
                            else
865
0
                                break;
866
0
                        }
867
                        // Either the rows or columns are the same among selections
868
0
                        if (bSameRows || bSameCols)
869
0
                        {
870
0
                            const LocaleDataWrapper& rLocaleData
871
0
                                = Application::GetSettings().GetUILocaleDataWrapper();
872
0
                            OUString aRowArg
873
0
                                = ScResId(STR_SELCOUNT_ROWARG, nRowsSum)
874
0
                                      .replaceAll("%d", rLocaleData.getNum(nRowsSum, 0));
875
0
                            OUString aColArg
876
0
                                = ScResId(STR_SELCOUNT_COLARG, nColsSum)
877
0
                                      .replaceAll("%d", rLocaleData.getNum(nColsSum, 0));
878
0
                            OUString aStr = ScResId(STR_SELCOUNT);
879
0
                            aStr = aStr.replaceAll("%1", aRowArg);
880
0
                            aStr = aStr.replaceAll("%2", aColArg);
881
0
                            rSet.Put(SfxStringItem(nWhich, aStr));
882
0
                        }
883
0
                    }
884
0
                    else
885
0
                    {
886
0
                        SCSIZE nSelected, nTotal;
887
0
                        rDoc.GetFilterSelCount( nPosX, nPosY, nTab, nSelected, nTotal );
888
0
                        if( nTotal && nSelected != SCSIZE_MAX )
889
0
                        {
890
0
                            OUString aStr = ScResId( STR_FILTER_SELCOUNT );
891
0
                            aStr = aStr.replaceAll( "%1", OUString::number( nSelected ) );
892
0
                            aStr = aStr.replaceAll( "%2", OUString::number( nTotal ) );
893
0
                            rSet.Put( SfxStringItem( nWhich, aStr ) );
894
0
                        }
895
0
                    }
896
0
                }
897
0
                break;
898
899
            //  calculations etc. with date/time/Fail/position&size together
900
901
            // #i34458# The SvxStatusItem belongs only into SID_TABLE_CELL. It no longer has to be
902
            // duplicated in SID_ATTR_POSITION or SID_ATTR_SIZE for SvxPosSizeStatusBarControl.
903
0
            case SID_TABLE_CELL:
904
0
                {
905
                    //  Test, if error under cursor
906
                    //  (not rDoc.GetErrCode, to avoid erasing circular references)
907
908
                    // In interpreter may happen via rescheduled Basic
909
0
                    if ( rDoc.IsInInterpreter() )
910
0
                        rSet.Put( SvxStatusItem( SID_TABLE_CELL, u"..."_ustr, StatusCategory::Formula ) );
911
0
                    else
912
0
                    {
913
0
                        FormulaError nErrCode = FormulaError::NONE;
914
0
                        ScFormulaCell* pCell = rDoc.GetFormulaCell(ScAddress(nPosX, nPosY, nTab));
915
0
                        if (pCell && !pCell->IsRunning())
916
0
                            nErrCode = pCell->GetErrCode();
917
918
0
                        OUString aFuncStr;
919
0
                        if ( pTabViewShell->GetFunction( aFuncStr, nErrCode ) )
920
0
                        {
921
0
                            rSet.Put( SvxStatusItem( SID_TABLE_CELL, aFuncStr, StatusCategory::Formula ) );
922
0
                        }
923
0
                    }
924
0
                }
925
0
                break;
926
927
0
            case SID_DATA_SELECT:
928
                // HasSelectionData includes column content and validity,
929
                // page fields have to be checked separately.
930
0
                if ( !rDoc.HasSelectionData( nPosX, nPosY, nTab ) &&
931
0
                     !pTabViewShell->HasPageFieldDataAtCursor() )
932
0
                    rSet.DisableItem( nWhich );
933
0
                break;
934
935
0
            case FID_CURRENTVALIDATION:
936
0
                if ( !rDoc.HasValidationData( nPosX, nPosY, nTab ))
937
0
                    rSet.DisableItem( nWhich );
938
0
                break;
939
940
0
            case SID_STATUS_SUM:
941
0
                {
942
0
                    OUString aFuncStr;
943
0
                    if ( pTabViewShell->GetFunction( aFuncStr, FormulaError::NONE ) )
944
0
                        rSet.Put( SfxStringItem( nWhich, aFuncStr ) );
945
0
                }
946
0
                break;
947
948
0
            case FID_MERGE_ON:
949
0
                if ( rDoc.GetChangeTrack() || !pTabViewShell->TestMergeCells() )
950
0
                    rSet.DisableItem( nWhich );
951
0
                break;
952
953
0
            case FID_MERGE_OFF:
954
0
                if ( rDoc.GetChangeTrack() || !pTabViewShell->TestRemoveMerge() )
955
0
                    rSet.DisableItem( nWhich );
956
0
                break;
957
958
0
            case FID_MERGE_TOGGLE:
959
0
                if ( rDoc.GetChangeTrack() )
960
0
                    rSet.DisableItem( nWhich );
961
0
                else
962
0
                {
963
0
                    bool bCanMerge = pTabViewShell->TestMergeCells();
964
0
                    bool bCanSplit = pTabViewShell->TestRemoveMerge();
965
0
                    if( !bCanMerge && !bCanSplit )
966
0
                        rSet.DisableItem( nWhich );
967
0
                    else
968
0
                        rSet.Put( SfxBoolItem( nWhich, bCanSplit ) );
969
0
                }
970
0
                break;
971
972
0
            case FID_INS_ROWBRK:
973
0
                if ( nPosY==0 || (rDoc.HasRowBreak(nPosY, nTab) & ScBreakType::Manual) || rDoc.IsTabProtected(nTab) )
974
0
                    rSet.DisableItem( nWhich );
975
0
                break;
976
977
0
            case FID_INS_COLBRK:
978
0
                if ( nPosX==0 || (rDoc.HasColBreak(nPosX, nTab) & ScBreakType::Manual) || rDoc.IsTabProtected(nTab) )
979
0
                    rSet.DisableItem( nWhich );
980
0
                break;
981
982
0
            case FID_DEL_ROWBRK:
983
0
                if ( nPosY==0 || !(rDoc.HasRowBreak(nPosY, nTab) & ScBreakType::Manual) || rDoc.IsTabProtected(nTab) )
984
0
                    rSet.DisableItem( nWhich );
985
0
                break;
986
987
0
            case FID_DEL_COLBRK:
988
0
                if ( nPosX==0 || !(rDoc.HasColBreak(nPosX, nTab) & ScBreakType::Manual) || rDoc.IsTabProtected(nTab) )
989
0
                    rSet.DisableItem( nWhich );
990
0
                break;
991
992
0
            case FID_FILL_TAB:
993
0
                if ( nTabSelCount < 2 )
994
0
                    rSet.DisableItem( nWhich );
995
0
                break;
996
997
0
            case SID_INSERT_CURRENT_DATE:
998
0
            case SID_INSERT_CURRENT_TIME:
999
0
                {
1000
0
                    if ( rDoc.IsTabProtected(nTab) &&
1001
0
                            rDoc.HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HasAttrFlags::Protected))
1002
0
                        rSet.DisableItem( nWhich );
1003
0
                }
1004
0
                break;
1005
1006
0
            case SID_SELECT_SCENARIO:
1007
0
                {
1008
0
                    std::vector<OUString> aList;
1009
0
                    Color   aDummyCol;
1010
1011
0
                    if ( !rDoc.IsScenario(nTab) )
1012
0
                    {
1013
0
                        OUString aStr;
1014
0
                        ScScenarioFlags nFlags;
1015
0
                        SCTAB nScTab = nTab + 1;
1016
0
                        bool bSheetProtected = rDoc.IsTabProtected(nTab);
1017
1018
0
                        while ( rDoc.IsScenario(nScTab) )
1019
0
                        {
1020
0
                            rDoc.GetName( nScTab, aStr );
1021
0
                            aList.push_back(aStr);
1022
0
                            rDoc.GetScenarioData( nScTab, aStr, aDummyCol, nFlags );
1023
0
                            aList.push_back(aStr);
1024
                            // Protection is sal_True if both Sheet and Scenario are protected
1025
0
                            aList.push_back((bSheetProtected && (nFlags & ScScenarioFlags::Protected)) ? u"1"_ustr : u"0"_ustr);
1026
0
                            ++nScTab;
1027
0
                        }
1028
0
                    }
1029
0
                    else
1030
0
                    {
1031
0
                        OUString aComment;
1032
0
                        ScScenarioFlags nDummyFlags;
1033
0
                        rDoc.GetScenarioData( nTab, aComment, aDummyCol, nDummyFlags );
1034
0
                        OSL_ENSURE( aList.empty(), "List not empty!" );
1035
0
                        aList.push_back(aComment);
1036
0
                    }
1037
1038
0
                    rSet.Put( SfxStringListItem( nWhich, &aList ) );
1039
0
                }
1040
0
                break;
1041
1042
0
            case FID_ROW_HIDE:
1043
0
            case FID_ROW_SHOW:
1044
0
            case FID_COL_HIDE:
1045
0
            case FID_COL_SHOW:
1046
0
            case FID_COL_OPT_WIDTH:
1047
0
            case FID_ROW_OPT_HEIGHT:
1048
0
            case FID_DELETE_CELL:
1049
0
                if ( rDoc.IsTabProtected(nTab) || pDocSh->IsReadOnly())
1050
0
                    rSet.DisableItem( nWhich );
1051
0
                break;
1052
1053
0
            case SID_OUTLINE_MAKE:
1054
0
                {
1055
0
                    if ( GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1056
0
                                            GetViewData().GetCurY(), GetViewData().CurrentTabForData() ) )
1057
0
                    {
1058
                        //! test for data pilot operation
1059
0
                    }
1060
0
                    else if (rDoc.GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked())
1061
0
                    {
1062
0
                        rSet.DisableItem( nWhich );
1063
0
                    }
1064
0
                }
1065
0
                break;
1066
0
            case SID_OUTLINE_SHOW:
1067
0
                if ( GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1068
0
                                        GetViewData().GetCurY(), GetViewData().CurrentTabForData() ) )
1069
0
                {
1070
                    //! test for data pilot operation
1071
0
                }
1072
0
                else if (!pTabViewShell->OutlinePossible(false))
1073
0
                    rSet.DisableItem( nWhich );
1074
0
                break;
1075
1076
0
            case SID_OUTLINE_HIDE:
1077
0
                if ( GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1078
0
                                        GetViewData().GetCurY(), GetViewData().CurrentTabForData() ) )
1079
0
                {
1080
                    //! test for data pilot operation
1081
0
                }
1082
0
                else if (!pTabViewShell->OutlinePossible(true))
1083
0
                    rSet.DisableItem( nWhich );
1084
0
                break;
1085
1086
0
            case SID_OUTLINE_REMOVE:
1087
0
                {
1088
0
                    if ( GetViewData().GetDocument().GetDPAtCursor( GetViewData().GetCurX(),
1089
0
                                            GetViewData().GetCurY(), GetViewData().CurrentTabForData() ) )
1090
0
                    {
1091
                        //! test for data pilot operation
1092
0
                    }
1093
0
                    else
1094
0
                    {
1095
0
                        bool bCol, bRow;
1096
0
                        pTabViewShell->TestRemoveOutline( bCol, bRow );
1097
0
                        if ( !bCol && !bRow )
1098
0
                            rSet.DisableItem( nWhich );
1099
0
                    }
1100
0
                }
1101
0
                break;
1102
1103
0
            case FID_COL_WIDTH:
1104
0
                {
1105
0
                    SfxUInt16Item aWidthItem( FID_COL_WIDTH, rDoc.GetColWidth( nPosX , nTab) );
1106
0
                    rSet.Put( aWidthItem );
1107
0
                    if ( pDocSh->IsReadOnly())
1108
0
                        rSet.DisableItem( nWhich );
1109
1110
                    //XXX disable if not conclusive
1111
0
                }
1112
0
                break;
1113
1114
0
            case FID_ROW_HEIGHT:
1115
0
                {
1116
0
                    SfxUInt16Item aHeightItem( FID_ROW_HEIGHT, rDoc.GetRowHeight( nPosY , nTab) );
1117
0
                    rSet.Put( aHeightItem );
1118
                    //XXX disable if not conclusive
1119
0
                    if ( pDocSh->IsReadOnly())
1120
0
                        rSet.DisableItem( nWhich );
1121
0
                }
1122
0
                break;
1123
1124
0
            case SID_DETECTIVE_FILLMODE:
1125
0
                rSet.Put(SfxBoolItem( nWhich, pTabViewShell->IsAuditShell() ));
1126
0
                break;
1127
1128
0
            case FID_INPUTLINE_STATUS:
1129
0
                OSL_FAIL( "Old update method. Use ScTabViewShell::UpdateInputHandler()." );
1130
0
                break;
1131
1132
0
            case SID_SCENARIOS:                                     // scenarios:
1133
0
                if (!(rMark.IsMarked() || rMark.IsMultiMarked()))   // only, if something selected
1134
0
                    rSet.DisableItem( nWhich );
1135
0
                break;
1136
1137
0
            case FID_NOTE_VISIBLE:
1138
0
                {
1139
0
                    const ScPostIt* pNote = rDoc.GetNote(nPosX, nPosY, nTab);
1140
0
                    if ( pNote && rDoc.IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
1141
0
                        rSet.Put( SfxBoolItem( nWhich, pNote->IsCaptionShown() ) );
1142
0
                    else
1143
0
                        rSet.DisableItem( nWhich );
1144
0
                }
1145
0
                break;
1146
1147
0
            case FID_HIDE_NOTE:
1148
0
            case FID_SHOW_NOTE:
1149
0
                {
1150
0
                    bool bEnable = false;
1151
0
                    bool bSearchForHidden = nWhich == FID_SHOW_NOTE;
1152
0
                    if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1153
0
                    {
1154
                        // Check current cell
1155
0
                        const ScPostIt* pNote = rDoc.GetNote(nPosX, nPosY, nTab);
1156
0
                        if ( pNote && rDoc.IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) )
1157
0
                            if ( pNote->IsCaptionShown() != bSearchForHidden)
1158
0
                                bEnable = true;
1159
0
                    }
1160
0
                    else
1161
0
                    {
1162
                        // Check selection range
1163
0
                        ScRangeListRef aRangesRef;
1164
0
                        rData.GetMultiArea(aRangesRef);
1165
0
                        ScRangeList aRanges = *aRangesRef;
1166
0
                        std::vector<sc::NoteEntry> aNotes;
1167
0
                        rDoc.GetNotesInRange(aRanges, aNotes);
1168
0
                        for(const auto& rNote : aNotes)
1169
0
                        {
1170
0
                            const ScAddress& rAdr = rNote.maPos;
1171
0
                            if( rDoc.IsBlockEditable( rAdr.Tab(), rAdr.Col(), rAdr.Row(), rAdr.Col(), rAdr.Row() ))
1172
0
                            {
1173
0
                                if (rNote.mpNote->IsCaptionShown() != bSearchForHidden)
1174
0
                                {
1175
0
                                    bEnable = true;
1176
0
                                    break;
1177
0
                                }
1178
0
                            }
1179
0
                        }
1180
1181
0
                    }
1182
0
                    if ( !bEnable )
1183
0
                        rSet.DisableItem( nWhich );
1184
0
                }
1185
0
                break;
1186
1187
0
            case FID_SHOW_ALL_NOTES:
1188
0
            case FID_HIDE_ALL_NOTES:
1189
0
            case FID_DELETE_ALL_NOTES:
1190
0
                {
1191
0
                    bool bHasNotes = false;
1192
1193
0
                    for (auto const& rTab : rMark.GetSelectedTabs())
1194
0
                    {
1195
0
                        if (rDoc.HasTabNotes( rTab ))
1196
0
                        {
1197
0
                            bHasNotes = true;
1198
0
                            break;
1199
0
                        }
1200
0
                    }
1201
1202
0
                    if ( !bHasNotes )
1203
0
                        rSet.DisableItem( nWhich );
1204
0
                }
1205
0
                break;
1206
1207
0
            case SID_TOGGLE_NOTES:
1208
0
                {
1209
0
                    bool bHasNotes = false;
1210
0
                    ScRangeList aRanges;
1211
1212
0
                    for (auto const& rTab : rMark.GetSelectedTabs())
1213
0
                    {
1214
0
                        if (rDoc.HasTabNotes( rTab ))
1215
0
                        {
1216
0
                            bHasNotes = true;
1217
0
                            aRanges.push_back(ScRange(0,0,rTab,rDoc.MaxCol(),rDoc.MaxRow(),rTab));
1218
0
                        }
1219
0
                    }
1220
1221
0
                    if ( !bHasNotes )
1222
0
                        rSet.DisableItem( nWhich );
1223
0
                    else
1224
0
                    {
1225
0
                         CommentCaptionState eState = rDoc.GetAllNoteCaptionsState( aRanges );
1226
0
                         bool bAllNotesInShown = (eState != ALLHIDDEN && eState != MIXED);
1227
0
                         rSet.Put( SfxBoolItem( SID_TOGGLE_NOTES, bAllNotesInShown) );
1228
0
                    }
1229
0
                }
1230
0
                break;
1231
1232
0
            case SID_DELETE_NOTE:
1233
0
                {
1234
0
                    bool bEnable = false;
1235
0
                    if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1236
0
                    {
1237
0
                        if ( rDoc.IsSelectionEditable( rMark ) )
1238
0
                        {
1239
                            // look for at least one note in selection
1240
0
                            ScRangeList aRanges;
1241
0
                            rMark.FillRangeListWithMarks( &aRanges, false );
1242
0
                            bEnable = rDoc.ContainsNotesInRange( aRanges );
1243
0
                        }
1244
0
                    }
1245
0
                    else
1246
0
                    {
1247
0
                        bEnable = rDoc.IsBlockEditable( nTab, nPosX,nPosY, nPosX,nPosY ) &&
1248
0
                                  rDoc.GetNote(nPosX, nPosY, nTab);
1249
0
                    }
1250
0
                    if ( !bEnable )
1251
0
                        rSet.DisableItem( nWhich );
1252
0
                }
1253
0
                break;
1254
1255
0
            case SID_OPENDLG_CONSOLIDATE:
1256
0
            case SCITEM_CONSOLIDATEDATA:
1257
0
                {
1258
0
                    if (rDoc.GetChangeTrack()!=nullptr)
1259
0
                        rSet.DisableItem( nWhich);
1260
0
                }
1261
0
                break;
1262
1263
0
            case SID_CHINESE_CONVERSION:
1264
0
            case SID_HANGUL_HANJA_CONVERSION:
1265
0
                ScViewUtil::HideDisabledSlot( rSet, rData.GetBindings(), nWhich );
1266
0
            break;
1267
1268
0
            case FID_USE_NAME:
1269
0
                {
1270
0
                    if ( pDocSh->IsDocShared() )
1271
0
                        rSet.DisableItem( nWhich );
1272
0
                    else
1273
0
                    {
1274
0
                        ScRange aRange;
1275
0
                        if ( rData.GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
1276
0
                            rSet.DisableItem( nWhich );
1277
0
                    }
1278
0
                }
1279
0
                break;
1280
1281
0
            case FID_DEFINE_NAME:
1282
0
            case FID_INSERT_NAME:
1283
0
            case FID_ADD_NAME:
1284
0
            case SID_DEFINE_COLROWNAMERANGES:
1285
0
                {
1286
0
                    if ( pDocSh->IsDocShared() )
1287
0
                    {
1288
0
                        rSet.DisableItem( nWhich );
1289
0
                    }
1290
0
                }
1291
0
                break;
1292
1293
0
            case FID_DEFINE_CURRENT_NAME:
1294
0
            {
1295
0
                ScAddress aCurrentAddress( nPosX, nPosY, nTab );
1296
1297
0
                if ( !rDoc.IsAddressInRangeName( RangeNameScope::GLOBAL, aCurrentAddress ) &&
1298
0
                     !rDoc.IsAddressInRangeName( RangeNameScope::SHEET, aCurrentAddress ))
1299
0
                {
1300
0
                    rSet.DisableItem( nWhich );
1301
0
                }
1302
0
            }
1303
0
            break;
1304
1305
0
            case SID_SPELL_DIALOG:
1306
0
                {
1307
0
                    if (rDoc.IsTabProtected(rData.CurrentTabForData()))
1308
0
                    {
1309
0
                        bool bVisible = false;
1310
0
                        SfxViewFrame* pViewFrame = ( pTabViewShell ? &pTabViewShell->GetViewFrame() : nullptr );
1311
0
                        if ( pViewFrame && pViewFrame->HasChildWindow( nWhich ) )
1312
0
                        {
1313
0
                            SfxChildWindow* pChild = pViewFrame->GetChildWindow( nWhich );
1314
0
                            std::shared_ptr<SfxDialogController> xController = pChild ? pChild->GetController() : nullptr;
1315
0
                            if (xController && xController->getDialog()->get_visible())
1316
0
                            {
1317
0
                                bVisible = true;
1318
0
                            }
1319
0
                        }
1320
0
                        if ( !bVisible )
1321
0
                        {
1322
0
                            rSet.DisableItem( nWhich );
1323
0
                        }
1324
0
                    }
1325
0
                }
1326
0
                break;
1327
1328
0
            case SID_OPENDLG_CURRENTCONDFRMT:
1329
0
            case SID_OPENDLG_CURRENTCONDFRMT_MANAGER:
1330
0
                {
1331
0
                    const ScCondFormatItem& rCondFormatItem = rDoc.GetAttr(nPosX, nPosY, nTab, ATTR_CONDITIONAL);
1332
1333
0
                    if ( rCondFormatItem.GetCondFormatData().empty() )
1334
0
                        rSet.DisableItem( nWhich );
1335
0
                    else if ( rCondFormatItem.GetCondFormatData().size() == 1 )
1336
0
                        rSet.DisableItem( SID_OPENDLG_CURRENTCONDFRMT_MANAGER );
1337
0
                    else if ( rCondFormatItem.GetCondFormatData().size() > 1 )
1338
0
                        rSet.DisableItem( SID_OPENDLG_CURRENTCONDFRMT );
1339
0
                }
1340
0
                break;
1341
1342
0
        } // switch ( nWitch )
1343
0
        nWhich = aIter.NextWhich();
1344
0
    } // while ( nWitch )
1345
0
}
1346
1347
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */