Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sc/source/ui/view/viewutil.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
#include <sfx2/bindings.hxx>
22
#include <sfx2/viewsh.hxx>
23
#include <sfx2/dispatch.hxx>
24
#include <editeng/fontitem.hxx>
25
#include <editeng/langitem.hxx>
26
#include <editeng/scriptsetitem.hxx>
27
#include <i18nutil/transliteration.hxx>
28
#include <svl/itempool.hxx>
29
#include <svl/itemset.hxx>
30
#include <svl/cjkoptions.hxx>
31
#include <svl/ctloptions.hxx>
32
#include <vcl/svapp.hxx>
33
#include <vcl/settings.hxx>
34
#include <sfx2/objsh.hxx>
35
#include <sfx2/viewfrm.hxx>
36
#include <svl/eitem.hxx>
37
#include <osl/diagnose.h>
38
39
#include <viewutil.hxx>
40
#include <chgtrack.hxx>
41
#include <chgviset.hxx>
42
#include <markdata.hxx>
43
#include <document.hxx>
44
#include <tabvwsh.hxx>
45
46
#include <svx/svxdlg.hxx>
47
#include <svx/svxids.hrc>
48
#include <memory>
49
50
void ScViewUtil::PutItemScript( SfxItemSet& rShellSet, const SfxItemSet& rCoreSet,
51
                                sal_uInt16 nWhichId, SvtScriptType nScript )
52
0
{
53
    //  take the effective item from rCoreSet according to nScript
54
    //  and put in rShellSet under the (base) nWhichId
55
56
0
    SfxItemPool& rPool = *rShellSet.GetPool();
57
0
    SvxScriptSetItem aSetItem( rPool.GetSlotId(nWhichId), rPool );
58
    //  use PutExtended with eDefaultAs = SfxItemState::SET, so defaults from rCoreSet
59
    //  (document pool) are read and put into rShellSet (MessagePool)
60
0
    aSetItem.GetItemSet().PutExtended( rCoreSet, SfxItemState::INVALID, SfxItemState::SET );
61
0
    const SfxPoolItem* pI = aSetItem.GetItemOfScript( nScript );
62
0
    if (pI)
63
0
    {
64
0
        rShellSet.Put( pI->CloneSetWhich(nWhichId) );
65
0
    }
66
0
    else
67
0
        rShellSet.InvalidateItem( nWhichId );
68
0
}
69
70
LanguageType ScViewUtil::GetEffLanguage( ScDocument& rDoc, const ScAddress& rPos )
71
0
{
72
    //  used for thesaurus
73
74
0
    SvtScriptType nScript = rDoc.GetScriptType(rPos.Col(), rPos.Row(), rPos.Tab());
75
0
    sal_uInt16 nWhich = ( nScript == SvtScriptType::ASIAN ) ? ATTR_CJK_FONT_LANGUAGE :
76
0
                    ( ( nScript == SvtScriptType::COMPLEX ) ? ATTR_CTL_FONT_LANGUAGE : ATTR_FONT_LANGUAGE );
77
0
    const SfxPoolItem& rItem = rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), nWhich);
78
0
    const SvxLanguageItem* pLangIt = dynamic_cast<const SvxLanguageItem*>(&rItem);
79
0
    LanguageType eLnge;
80
0
    if (pLangIt)
81
0
    {
82
0
        eLnge = pLangIt->GetValue();
83
0
        if (eLnge == LANGUAGE_DONTKNOW)                 //! can this happen?
84
0
        {
85
0
            LanguageType eLatin, eCjk, eCtl;
86
0
            rDoc.GetLanguage( eLatin, eCjk, eCtl );
87
0
            eLnge = ( nScript == SvtScriptType::ASIAN ) ? eCjk :
88
0
                    ( ( nScript == SvtScriptType::COMPLEX ) ? eCtl : eLatin );
89
0
        }
90
0
    }
91
0
    else
92
0
        eLnge = LANGUAGE_ENGLISH_US;
93
0
    if ( eLnge == LANGUAGE_SYSTEM )
94
0
        eLnge = Application::GetSettings().GetLanguageTag().getLanguageType();   // never use SYSTEM for spelling
95
96
0
    return eLnge;
97
0
}
98
99
TransliterationFlags ScViewUtil::GetTransliterationType( sal_uInt16 nSlotID )
100
0
{
101
0
    TransliterationFlags nType = TransliterationFlags::NONE;
102
0
    switch ( nSlotID )
103
0
    {
104
0
        case SID_TRANSLITERATE_SENTENCE_CASE:
105
0
            nType = TransliterationFlags::SENTENCE_CASE;
106
0
            break;
107
0
        case SID_TRANSLITERATE_TITLE_CASE:
108
0
            nType = TransliterationFlags::TITLE_CASE;
109
0
            break;
110
0
        case SID_TRANSLITERATE_TOGGLE_CASE:
111
0
            nType = TransliterationFlags::TOGGLE_CASE;
112
0
            break;
113
0
        case SID_TRANSLITERATE_UPPER:
114
0
            nType = TransliterationFlags::LOWERCASE_UPPERCASE;
115
0
            break;
116
0
        case SID_TRANSLITERATE_LOWER:
117
0
            nType = TransliterationFlags::UPPERCASE_LOWERCASE;
118
0
            break;
119
0
        case SID_TRANSLITERATE_HALFWIDTH:
120
0
            nType = TransliterationFlags::FULLWIDTH_HALFWIDTH;
121
0
            break;
122
0
        case SID_TRANSLITERATE_FULLWIDTH:
123
0
            nType = TransliterationFlags::HALFWIDTH_FULLWIDTH;
124
0
            break;
125
0
        case SID_TRANSLITERATE_HIRAGANA:
126
0
            nType = TransliterationFlags::KATAKANA_HIRAGANA;
127
0
            break;
128
0
        case SID_TRANSLITERATE_KATAKANA:
129
0
            nType = TransliterationFlags::HIRAGANA_KATAKANA;
130
0
            break;
131
0
    }
132
0
    return nType;
133
0
}
134
135
bool ScViewUtil::IsActionShown( const ScChangeAction& rAction,
136
                                const ScChangeViewSettings& rSettings,
137
                                ScDocument& rDocument )
138
0
{
139
    // discarded are displayed as inverted accepted action, because of this
140
    // order of ShowRejected/ShowAccepted is important
141
142
0
    if ( !rSettings.IsShowRejected() && rAction.IsRejecting() )
143
0
        return false;
144
145
0
    if ( !rSettings.IsShowAccepted() && rAction.IsAccepted() && !rAction.IsRejecting() )
146
0
        return false;
147
148
0
    if ( rSettings.HasAuthor() && rAction.GetUser() != rSettings.GetTheAuthorToShow() )
149
0
        return false;
150
151
0
    if ( rSettings.HasComment() )
152
0
    {
153
0
        OUString aTmp = rAction.GetDescription(rDocument);
154
0
        OUString aComStr = rAction.GetComment() + " (" + aTmp + ")";
155
156
0
        if(!rSettings.IsValidComment(&aComStr))
157
0
            return false;
158
0
    }
159
160
0
    if ( rSettings.HasRange() )
161
0
        if ( !rSettings.GetTheRangeList().Intersects( rAction.GetBigRange().MakeRange( rDocument ) ) )
162
0
            return false;
163
164
0
    if (rSettings.HasDate() && rSettings.GetTheDateMode() != SvxRedlineDateMode::NONE)
165
0
    {
166
0
        DateTime aDateTime = rAction.GetDateTime();
167
0
        const DateTime& rFirst = rSettings.GetTheFirstDateTime();
168
0
        const DateTime& rLast  = rSettings.GetTheLastDateTime();
169
0
        switch ( rSettings.GetTheDateMode() )
170
0
        {   // corresponds with ScHighlightChgDlg::OKBtnHdl
171
0
            case SvxRedlineDateMode::BEFORE:
172
0
                if ( aDateTime > rFirst )
173
0
                    return false;
174
0
                break;
175
176
0
            case SvxRedlineDateMode::SINCE:
177
0
                if ( aDateTime < rFirst )
178
0
                    return false;
179
0
                break;
180
181
0
            case SvxRedlineDateMode::EQUAL:
182
0
            case SvxRedlineDateMode::BETWEEN:
183
0
                if ( aDateTime < rFirst || aDateTime > rLast )
184
0
                    return false;
185
0
                break;
186
187
0
            case SvxRedlineDateMode::NOTEQUAL:
188
0
                if ( aDateTime >= rFirst && aDateTime <= rLast )
189
0
                    return false;
190
0
                break;
191
192
0
            case SvxRedlineDateMode::SAVE:
193
0
                {
194
0
                ScChangeTrack* pTrack = rDocument.GetChangeTrack();
195
0
                if ( !pTrack || pTrack->GetLastSavedActionNumber() >=
196
0
                        rAction.GetActionNumber() )
197
0
                    return false;
198
0
                }
199
0
                break;
200
201
0
            default:
202
0
            {
203
                // added to avoid warnings
204
0
            }
205
0
        }
206
0
    }
207
208
0
    if ( rSettings.HasActionRange() )
209
0
    {
210
0
        sal_uLong nAction = rAction.GetActionNumber();
211
0
        sal_uLong nFirstAction;
212
0
        sal_uLong nLastAction;
213
0
        rSettings.GetTheActionRange( nFirstAction, nLastAction );
214
0
        if ( nAction < nFirstAction || nAction > nLastAction )
215
0
        {
216
0
            return false;
217
0
        }
218
0
    }
219
220
0
    return true;
221
0
}
222
223
void ScViewUtil::UnmarkFiltered( ScMarkData& rMark, const ScDocument& rDoc )
224
0
{
225
0
    rMark.MarkToMulti();
226
227
0
    const ScRange& aMultiArea = rMark.GetMultiMarkArea();
228
0
    SCCOL nStartCol = aMultiArea.aStart.Col();
229
0
    SCROW nStartRow = aMultiArea.aStart.Row();
230
0
    SCCOL nEndCol = aMultiArea.aEnd.Col();
231
0
    SCROW nEndRow = aMultiArea.aEnd.Row();
232
233
0
    bool bChanged = false;
234
0
    for (const SCTAB& nTab : rMark)
235
0
    {
236
0
        for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
237
0
        {
238
0
            SCROW nLastRow = nRow;
239
0
            if (rDoc.RowFiltered(nRow, nTab, nullptr, &nLastRow))
240
0
            {
241
                // use nStartCol/nEndCol, so the multi mark area isn't extended to all columns
242
                // (visible in repaint for indentation)
243
0
                rMark.SetMultiMarkArea(
244
0
                    ScRange(nStartCol, nRow, nTab, nEndCol, nLastRow, nTab), false);
245
0
                bChanged = true;
246
0
                nRow = nLastRow;
247
0
            }
248
0
        }
249
0
    }
250
251
0
    if ( bChanged && !rMark.HasAnyMultiMarks() )
252
0
        rMark.ResetMark();
253
254
0
    rMark.MarkToSimple();
255
0
}
256
257
bool ScViewUtil::FitToUnfilteredRows( ScRange & rRange, const ScDocument& rDoc, size_t nRows )
258
0
{
259
0
    SCTAB nTab = rRange.aStart.Tab();
260
0
    bool bOneTabOnly = (nTab == rRange.aEnd.Tab());
261
    // Always fit the range on its first sheet.
262
0
    OSL_ENSURE( bOneTabOnly, "ScViewUtil::ExtendToUnfilteredRows: works only on one sheet");
263
0
    SCROW nStartRow = rRange.aStart.Row();
264
0
    SCROW nLastRow = rDoc.LastNonFilteredRow(nStartRow, rDoc.MaxRow(), nTab);
265
0
    if (rDoc.ValidRow(nLastRow))
266
0
        rRange.aEnd.SetRow(nLastRow);
267
0
    SCROW nCount = rDoc.CountNonFilteredRows(nStartRow, rDoc.MaxRow(), nTab);
268
0
    return static_cast<size_t>(nCount) == nRows && bOneTabOnly;
269
0
}
270
271
bool ScViewUtil::HasFiltered( const ScRange& rRange, const ScDocument& rDoc )
272
0
{
273
0
    SCROW nStartRow = rRange.aStart.Row();
274
0
    SCROW nEndRow = rRange.aEnd.Row();
275
0
    for (SCTAB nTab=rRange.aStart.Tab(); nTab<=rRange.aEnd.Tab(); nTab++)
276
0
    {
277
0
        if (rDoc.HasFilteredRows(nStartRow, nEndRow, nTab))
278
0
            return true;
279
0
    }
280
281
0
    return false;
282
0
}
283
284
void ScViewUtil::HideDisabledSlot( SfxItemSet& rSet, SfxBindings& rBindings, sal_uInt16 nSlotId )
285
0
{
286
0
    SvtCTLOptions aCTLOptions;
287
0
    bool bEnabled = true;
288
289
0
    switch( nSlotId )
290
0
    {
291
0
        case SID_CHINESE_CONVERSION:
292
0
        case SID_HANGUL_HANJA_CONVERSION:
293
0
            bEnabled = SvtCJKOptions::IsAnyEnabled();
294
0
        break;
295
296
0
        case SID_TRANSLITERATE_HALFWIDTH:
297
0
        case SID_TRANSLITERATE_FULLWIDTH:
298
0
        case SID_TRANSLITERATE_HIRAGANA:
299
0
        case SID_TRANSLITERATE_KATAKANA:
300
0
            bEnabled = SvtCJKOptions::IsChangeCaseMapEnabled();
301
0
        break;
302
303
0
        case SID_INSERT_RLM:
304
0
        case SID_INSERT_LRM:
305
0
            bEnabled = SvtCTLOptions::IsCTLFontEnabled();
306
0
        break;
307
308
0
        default:
309
0
            OSL_FAIL( "ScViewUtil::HideDisabledSlot - unknown slot ID" );
310
0
            return;
311
0
    }
312
313
0
    rBindings.SetVisibleState( nSlotId, bEnabled );
314
0
    if( !bEnabled )
315
0
        rSet.DisableItem( nSlotId );
316
0
}
317
318
void ScViewUtil::ExecuteCharMap(const SvxFontItem& rOldFont,
319
                                const ScTabViewShell& rShell)
320
0
{
321
0
    SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
322
0
    SfxViewFrame& rFrame = rShell.GetViewFrame();
323
0
    SfxAllItemSet aSet( rFrame.GetObjectShell()->GetPool() );
324
0
    aSet.Put( SfxBoolItem( FN_PARAM_1, false ) );
325
0
    aSet.Put( SvxFontItem( rOldFont.GetFamily(), rOldFont.GetFamilyName(), rOldFont.GetStyleName(), rOldFont.GetPitch(), rOldFont.GetCharSet(), aSet.GetPool()->GetWhichIDFromSlotID( SID_ATTR_CHAR_FONT ) ) );
326
0
    auto xFrame = rFrame.GetFrame().GetFrameInterface();
327
0
    VclPtr<SfxAbstractDialog> pDlg(pFact->CreateCharMapDialog(rShell.GetFrameWeld(), aSet, xFrame));
328
0
    pDlg->StartExecuteAsync(
329
0
        [pDlg] (sal_Int32 /*nResult*/)->void
330
0
        {
331
0
            pDlg->disposeOnce();
332
0
        }
333
0
    );
334
0
}
335
336
bool ScViewUtil::IsFullScreen( const SfxViewShell& rViewShell )
337
0
{
338
0
    SfxBindings&    rBindings       = rViewShell.GetViewFrame().GetBindings();
339
0
    std::unique_ptr<SfxBoolItem> pItem;
340
0
    bool            bIsFullScreen   = false;
341
342
0
    if (rBindings.QueryState( SID_WIN_FULLSCREEN, pItem ) >= SfxItemState::DEFAULT)
343
0
        bIsFullScreen = pItem->GetValue();
344
345
0
    return bIsFullScreen;
346
0
}
347
348
void ScViewUtil::SetFullScreen( const SfxViewShell& rViewShell, bool bSet )
349
0
{
350
0
    if( IsFullScreen( rViewShell ) != bSet )
351
0
    {
352
0
        SfxBoolItem aItem( SID_WIN_FULLSCREEN, bSet );
353
0
        rViewShell.GetDispatcher()->ExecuteList(SID_WIN_FULLSCREEN,
354
0
                SfxCallMode::RECORD, { &aItem });
355
0
    }
356
0
}
357
358
ScUpdateRect::ScUpdateRect( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
359
0
    : nNewStartX(0)
360
0
    , nNewStartY(0)
361
0
    , nNewEndX(0)
362
0
    , nNewEndY(0)
363
0
{
364
0
    PutInOrder( nX1, nX2 );
365
0
    PutInOrder( nY1, nY2 );
366
367
0
    nOldStartX = nX1;
368
0
    nOldStartY = nY1;
369
0
    nOldEndX = nX2;
370
0
    nOldEndY = nY2;
371
0
}
372
373
void ScUpdateRect::SetNew( SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2 )
374
0
{
375
0
    PutInOrder( nX1, nX2 );
376
0
    PutInOrder( nY1, nY2 );
377
378
0
    nNewStartX = nX1;
379
0
    nNewStartY = nY1;
380
0
    nNewEndX = nX2;
381
0
    nNewEndY = nY2;
382
0
}
383
384
bool ScUpdateRect::GetDiff( SCCOL& rX1, SCROW& rY1, SCCOL& rX2, SCROW& rY2 )
385
0
{
386
0
    if ( nNewStartX == nOldStartX && nNewEndX == nOldEndX &&
387
0
         nNewStartY == nOldStartY && nNewEndY == nOldEndY )
388
0
    {
389
0
        rX1 = nNewStartX;
390
0
        rY1 = nNewStartY;
391
0
        rX2 = nNewStartX;
392
0
        rY2 = nNewStartY;
393
0
        return false;
394
0
    }
395
396
0
    rX1 = std::min(nNewStartX,nOldStartX);
397
0
    rY1 = std::min(nNewStartY,nOldStartY);
398
0
    rX2 = std::max(nNewEndX,nOldEndX);
399
0
    rY2 = std::max(nNewEndY,nOldEndY);
400
401
0
    if ( nNewStartX == nOldStartX && nNewEndX == nOldEndX )
402
0
    {
403
0
        if ( nNewStartY == nOldStartY )
404
0
        {
405
0
            rY1 = std::min( nNewEndY, nOldEndY );
406
0
            rY2 = std::max( nNewEndY, nOldEndY );
407
0
        }
408
0
        else if ( nNewEndY == nOldEndY )
409
0
        {
410
0
            rY1 = std::min( nNewStartY, nOldStartY );
411
0
            rY2 = std::max( nNewStartY, nOldStartY );
412
0
        }
413
0
    }
414
0
    else if ( nNewStartY == nOldStartY && nNewEndY == nOldEndY )
415
0
    {
416
0
        if ( nNewStartX == nOldStartX )
417
0
        {
418
0
            rX1 = std::min( nNewEndX, nOldEndX );
419
0
            rX2 = std::max( nNewEndX, nOldEndX );
420
0
        }
421
0
        else if ( nNewEndX == nOldEndX )
422
0
        {
423
0
            rX1 = std::min( nNewStartX, nOldStartX );
424
0
            rX2 = std::max( nNewStartX, nOldStartX );
425
0
        }
426
0
    }
427
428
0
    return true;
429
0
}
430
431
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */