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/tabview2.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 <vcl/svapp.hxx>
22
#include <vcl/weld/MessageDialog.hxx>
23
#include <vcl/weld/weld.hxx>
24
#include <sfx2/bindings.hxx>
25
#include <osl/diagnose.h>
26
27
#include <attrib.hxx>
28
#include <pagedata.hxx>
29
#include <tabview.hxx>
30
#include <tabvwsh.hxx>
31
#include <printfun.hxx>
32
#include <stlpool.hxx>
33
#include <docsh.hxx>
34
#include <gridwin.hxx>
35
#include <sc.hrc>
36
#include <viewutil.hxx>
37
#include <colrowba.hxx>
38
#include <globstr.hrc>
39
#include <scresid.hxx>
40
#include <scmod.hxx>
41
#include <table.hxx>
42
#include <tabprotection.hxx>
43
#include <markdata.hxx>
44
#include <inputopt.hxx>
45
#include <comphelper/lok.hxx>
46
47
namespace {
48
49
bool isCellQualified(const ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
50
0
{
51
0
    bool bCellProtected = pDoc->HasAttrib(
52
0
        nCol, nRow, nTab, nCol, nRow, nTab, HasAttrFlags::Protected);
53
54
0
    if (bCellProtected && !bSelectLocked)
55
0
        return false;
56
57
0
    if (!bCellProtected && !bSelectUnlocked)
58
0
        return false;
59
60
0
    return true;
61
0
}
62
63
bool areCellsQualified(const ScDocument* pDoc, SCCOL nColStart, SCROW nRowStart, SCCOL nColEnd,
64
                       SCROW nRowEnd, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
65
0
{
66
0
    PutInOrder(nColStart, nColEnd);
67
0
    PutInOrder(nRowStart, nRowEnd);
68
0
    for (SCCOL col = nColStart; col <= nColEnd; ++col)
69
0
        for (SCROW row = nRowStart; row <= nRowEnd; ++row)
70
0
            if (!isCellQualified(pDoc, col, row, nTab, bSelectLocked, bSelectUnlocked))
71
0
                return false;
72
73
0
    return true;
74
0
}
75
76
void moveCursorByProtRule(
77
    SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCTAB nTab, const ScDocument* pDoc)
78
0
{
79
0
    bool bSelectLocked = true;
80
0
    bool bSelectUnlocked = true;
81
0
    const ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
82
0
    if (pTabProtection && pTabProtection->isProtected())
83
0
    {
84
0
        bSelectLocked   = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
85
0
        bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
86
0
    }
87
88
0
    if (nMovX > 0)
89
0
    {
90
0
        for (SCCOL i = 0; i < nMovX && rCol < pDoc->MaxCol(); ++i)
91
0
        {
92
0
            SCCOL nNewUnhiddenCol = rCol + 1;
93
0
            SCCOL nEndCol = 0;
94
0
            while(pDoc->ColHidden(nNewUnhiddenCol, nTab, nullptr, &nEndCol))
95
0
            {
96
0
                if(nNewUnhiddenCol >= pDoc->MaxCol())
97
0
                    return;
98
99
0
                i += nEndCol - nNewUnhiddenCol + 1;
100
0
                nNewUnhiddenCol = nEndCol +1;
101
0
            }
102
103
0
            if (!isCellQualified(pDoc, nNewUnhiddenCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
104
0
                break;
105
0
            rCol = nNewUnhiddenCol;
106
0
        }
107
0
    }
108
0
    else if (nMovX < 0)
109
0
    {
110
0
        for (SCCOL i = 0; i > nMovX && rCol > 0; --i)
111
0
        {
112
0
            SCCOL nNewUnhiddenCol = rCol - 1;
113
0
            SCCOL nStartCol = 0;
114
0
            while(pDoc->ColHidden(nNewUnhiddenCol, nTab, &nStartCol))
115
0
            {
116
0
                if(nNewUnhiddenCol <= 0)
117
0
                    return;
118
119
0
                i -= nNewUnhiddenCol - nStartCol + 1;
120
0
                nNewUnhiddenCol = nStartCol - 1;
121
0
            }
122
123
0
            if (!isCellQualified(pDoc, nNewUnhiddenCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
124
0
                break;
125
0
            rCol = nNewUnhiddenCol;
126
0
        }
127
0
    }
128
129
0
    if (nMovY > 0)
130
0
    {
131
0
        for (SCROW i = 0; i < nMovY && rRow < pDoc->MaxRow(); ++i)
132
0
        {
133
0
            SCROW nNewUnhiddenRow = rRow + 1;
134
0
            SCROW nEndRow = 0;
135
0
            while(pDoc->RowHidden(nNewUnhiddenRow, nTab, nullptr, &nEndRow))
136
0
            {
137
0
                if(nNewUnhiddenRow >= pDoc->MaxRow())
138
0
                    return;
139
140
0
                i += nEndRow - nNewUnhiddenRow + 1;
141
0
                nNewUnhiddenRow = nEndRow + 1;
142
0
            }
143
144
0
            if (!isCellQualified(pDoc, rCol, nNewUnhiddenRow, nTab, bSelectLocked, bSelectUnlocked))
145
0
                break;
146
0
            rRow = nNewUnhiddenRow;
147
0
        }
148
0
    }
149
0
    else if (nMovY < 0)
150
0
    {
151
0
        for (SCROW i = 0; i > nMovY && rRow > 0; --i)
152
0
        {
153
0
            SCROW nNewUnhiddenRow = rRow - 1;
154
0
            SCROW nStartRow = 0;
155
0
            while(pDoc->RowHidden(nNewUnhiddenRow, nTab, &nStartRow))
156
0
            {
157
0
                if(nNewUnhiddenRow <= 0)
158
0
                    return;
159
160
0
                i -= nNewUnhiddenRow - nStartRow + 1;
161
0
                nNewUnhiddenRow = nStartRow - 1;
162
0
            }
163
164
0
            if (!isCellQualified(pDoc, rCol, nNewUnhiddenRow, nTab, bSelectLocked, bSelectUnlocked))
165
0
                break;
166
0
            rRow = nNewUnhiddenRow;
167
0
        }
168
0
    }
169
0
}
170
171
bool checkBoundary(const ScDocument* pDoc, SCCOL& rCol, SCROW& rRow)
172
0
{
173
0
    bool bGood = true;
174
0
    if (rCol < 0)
175
0
    {
176
0
        rCol = 0;
177
0
        bGood = false;
178
0
    }
179
0
    else if (rCol > pDoc->MaxCol())
180
0
    {
181
0
        rCol = pDoc->MaxCol();
182
0
        bGood = false;
183
0
    }
184
185
0
    if (rRow < 0)
186
0
    {
187
0
        rRow = 0;
188
0
        bGood = false;
189
0
    }
190
0
    else if (rRow > pDoc->MaxRow())
191
0
    {
192
0
        rRow = pDoc->MaxRow();
193
0
        bGood = false;
194
0
    }
195
0
    return bGood;
196
0
}
197
198
void moveRefByCell(SCCOL& rNewX, SCROW& rNewY,
199
                   SCCOL nMovX, SCROW nMovY, SCTAB nRefTab,
200
                   const ScDocument& rDoc)
201
0
{
202
0
    SCCOL nOldX = rNewX;
203
0
    SCROW nOldY = rNewY;
204
0
    bool bSelectLocked = true;
205
0
    bool bSelectUnlocked = true;
206
0
    const ScTableProtection* pTabProtection = rDoc.GetTabProtection(nRefTab);
207
0
    if (pTabProtection && pTabProtection->isProtected())
208
0
    {
209
0
        bSelectLocked   = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
210
0
        bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
211
0
    }
212
213
0
    moveCursorByProtRule(rNewX, rNewY, nMovX, nMovY, nRefTab, &rDoc);
214
0
    checkBoundary(&rDoc, rNewX, rNewY);
215
216
0
    if (nMovX)
217
0
    {
218
0
        SCCOL nTempX = rNewX;
219
0
        while (rDoc.IsHorOverlapped(nTempX, rNewY, nRefTab))
220
0
        {
221
0
            nTempX = (nMovX > 0) ? nTempX + 1 : nTempX - 1;
222
0
            if (!checkBoundary(&rDoc, nTempX, rNewY))
223
0
                break;
224
0
        }
225
0
        if (isCellQualified(&rDoc, nTempX, rNewY, nRefTab, bSelectLocked, bSelectUnlocked))
226
0
            rNewX = nTempX;
227
228
0
        if (nMovX < 0 && rNewX > 0)
229
0
        {
230
0
            const ScMergeAttr& rMergeAttr = rDoc.GetAttr(rNewX, rNewY, nRefTab, ATTR_MERGE);
231
0
            if (rMergeAttr.IsMerged() &&
232
0
                nOldX >= rNewX &&
233
0
                nOldX <= rNewX + rMergeAttr.GetRowMerge() - 1)
234
0
                rNewX = rNewX - 1;
235
0
        }
236
0
    }
237
238
0
    if (nMovY)
239
0
    {
240
0
        SCROW nTempY = rNewY;
241
0
        while (rDoc.IsVerOverlapped(rNewX, nTempY, nRefTab))
242
0
        {
243
0
            nTempY = (nMovY > 0) ? nTempY + 1 : nTempY - 1;
244
0
            if (!checkBoundary(&rDoc, rNewX, nTempY))
245
0
                break;
246
0
        }
247
0
        if (isCellQualified(&rDoc, rNewX, nTempY, nRefTab, bSelectLocked, bSelectUnlocked))
248
0
            rNewY = nTempY;
249
250
0
        if (nMovY < 0 && rNewY > 0)
251
0
        {
252
0
            const ScMergeAttr& rMergeAttr = rDoc.GetAttr(rNewX, rNewY, nRefTab, ATTR_MERGE);
253
0
            if (rMergeAttr.IsMerged() &&
254
0
                nOldY >= rNewY &&
255
0
                nOldY <= rNewY + rMergeAttr.GetRowMerge() - 1)
256
0
                rNewY = rNewY - 1;
257
0
        }
258
0
    }
259
260
0
    rDoc.SkipOverlapped(rNewX, rNewY, nRefTab);
261
0
}
262
263
void moveCursorByMergedCell(SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCCOL nStartX,
264
                            SCROW nStartY, SCTAB nTab, const ScDocument* pDoc)
265
0
{
266
0
    const ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
267
0
    bool bSelectLocked = true;
268
0
    bool bSelectUnlocked = true;
269
0
    if (pTabProtection && pTabProtection->isProtected())
270
0
    {
271
0
        bSelectLocked   = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
272
0
        bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
273
0
    }
274
275
0
    if (nMovX > 0)
276
0
    {
277
0
        SCROW rowStart = std::min(rRow, nStartY);
278
0
        SCROW rowEnd = std::max(rRow, nStartY);
279
280
0
        for (SCROW i = rowStart; i <= rowEnd && rCol < nStartX;)
281
0
        {
282
0
            SCCOL tmpCol = rCol;
283
0
            while (tmpCol < pDoc->MaxCol() && pDoc->IsHorOverlapped(tmpCol, i, nTab))
284
0
                ++tmpCol;
285
0
            if (tmpCol != rCol)
286
0
            {
287
0
                i = rowStart;
288
0
                if (tmpCol > nStartX)
289
0
                    --tmpCol;
290
0
                if (!areCellsQualified(pDoc, rCol + 1, rowStart, tmpCol, rowEnd, nTab,
291
0
                                       bSelectLocked, bSelectUnlocked))
292
0
                    break;
293
0
                rCol = tmpCol;
294
0
            }
295
0
            else
296
0
                ++i;
297
0
        }
298
0
    }
299
0
    else if (nMovX < 0)
300
0
    {
301
0
        SCROW rowStart = std::min(rRow, nStartY);
302
0
        SCROW rowEnd = std::max(rRow, nStartY);
303
304
0
        for (SCROW i = rowStart; i <= rowEnd && rCol > nStartX;)
305
0
        {
306
0
            SCCOL tmpCol = rCol;
307
0
            while (tmpCol >= 0 && pDoc->IsHorOverlapped(tmpCol + 1, i, nTab))
308
0
                --tmpCol;
309
0
            if (tmpCol != rCol)
310
0
            {
311
0
                i = rowStart;
312
0
                if (tmpCol < nStartX)
313
0
                    ++tmpCol;
314
0
                if (!areCellsQualified(pDoc, rCol - 1, rowStart, tmpCol, rowEnd, nTab,
315
0
                                       bSelectLocked, bSelectUnlocked))
316
0
                    break;
317
0
                rCol = tmpCol;
318
0
            }
319
0
            else
320
0
                ++i;
321
0
        }
322
0
    }
323
324
0
    if (nMovY > 0)
325
0
    {
326
0
        SCCOL colStart = std::min(rCol, nStartX);
327
0
        SCCOL colEnd = std::max(rCol, nStartX);
328
329
0
        for (SCCOL i = colStart; i <= colEnd && rRow < nStartY;)
330
0
        {
331
0
            SCROW tmpRow = rRow;
332
0
            while (tmpRow < pDoc->MaxRow() && pDoc->IsVerOverlapped(i, tmpRow, nTab))
333
0
                ++tmpRow;
334
0
            if (tmpRow != rRow)
335
0
            {
336
0
                i = colStart;
337
0
                if (tmpRow > nStartY)
338
0
                    --tmpRow;
339
0
                if (!areCellsQualified(pDoc, colStart, rRow + 1, colEnd, tmpRow, nTab,
340
0
                                       bSelectLocked, bSelectUnlocked))
341
0
                    break;
342
0
                rRow = tmpRow;
343
0
            }
344
0
            else
345
0
                ++i;
346
0
        }
347
0
    }
348
0
    else if (nMovY < 0)
349
0
    {
350
0
        SCCOL colStart = std::min(rCol, nStartX);
351
0
        SCCOL colEnd = std::max(rCol, nStartX);
352
353
0
        for (SCCOL i = colStart; i <= colEnd && rRow > nStartY;)
354
0
        {
355
0
            SCROW tmpRow = rRow;
356
0
            while (tmpRow >= 0 && pDoc->IsVerOverlapped(i, tmpRow + 1, nTab))
357
0
                --tmpRow;
358
0
            if (tmpRow != rRow)
359
0
            {
360
0
                i = colStart;
361
0
                if (tmpRow < nStartY)
362
0
                    ++tmpRow;
363
0
                if (!areCellsQualified(pDoc, colStart, rRow - 1, colEnd, tmpRow, nTab,
364
0
                                       bSelectLocked, bSelectUnlocked))
365
0
                    break;
366
0
                rRow = tmpRow;
367
0
            }
368
0
            else
369
0
                ++i;
370
0
        }
371
0
    }
372
0
}
373
374
void moveCursorToProperSide(SCCOL& rCol, SCROW& rRow, SCCOL nMovX, SCROW nMovY, SCCOL nStartX,
375
                            SCROW nStartY, SCTAB nTab, const ScDocument* pDoc)
376
0
{
377
0
    SCCOL tmpCol = rCol;
378
0
    SCROW tmpRow = rRow;
379
380
0
    if (nMovX > 0 && nStartX < pDoc->MaxCol() && rCol < nStartX)
381
0
    {
382
0
        SCROW rowStart = std::min(rRow, nStartY);
383
0
        SCROW rowEnd = std::max(rRow, nStartY);
384
0
        for (SCROW i = rowStart; i <= rowEnd && tmpCol < nStartX;)
385
0
        {
386
0
            if (pDoc->IsHorOverlapped(tmpCol + 1, i, nTab))
387
0
            {
388
0
                do
389
0
                {
390
0
                    ++tmpCol;
391
0
                } while (pDoc->IsHorOverlapped(tmpCol + 1, i, nTab));
392
0
                i = rowStart;
393
0
            }
394
0
            else
395
0
                ++i;
396
0
        }
397
0
        if (tmpCol < nStartX)
398
0
            tmpCol = rCol;
399
0
    }
400
0
    else if (nMovX < 0 && nStartX > 0 && rCol > nStartX)
401
0
    {
402
0
        SCROW rowStart = std::min(rRow, nStartY);
403
0
        SCROW rowEnd = std::max(rRow, nStartY);
404
0
        for (SCROW i = rowStart; i <= rowEnd && tmpCol > nStartX;)
405
0
        {
406
0
            if (pDoc->IsHorOverlapped(tmpCol, i, nTab))
407
0
            {
408
0
                do
409
0
                {
410
0
                    --tmpCol;
411
0
                } while (pDoc->IsHorOverlapped(tmpCol, i, nTab));
412
0
                i = rowStart;
413
0
            }
414
0
            else
415
0
                ++i;
416
0
        }
417
0
        if (tmpCol > nStartX)
418
0
            tmpCol = rCol;
419
0
    }
420
421
0
    if (nMovY > 0 && nStartY < pDoc->MaxRow() && rRow < nStartY)
422
0
    {
423
0
        SCCOL colStart = std::min(rCol, nStartX);
424
0
        SCCOL colEnd = std::max(rCol, nStartX);
425
0
        for (SCCOL i = colStart; i <= colEnd && tmpRow < nStartY;)
426
0
        {
427
0
            if (pDoc->IsVerOverlapped(i, tmpRow + 1, nTab))
428
0
            {
429
0
                do
430
0
                {
431
0
                    ++tmpRow;
432
0
                } while (pDoc->IsVerOverlapped(i, tmpRow + 1, nTab));
433
0
                i = colStart;
434
0
            }
435
0
            else
436
0
                ++i;
437
0
        }
438
0
        if (tmpRow < nStartY)
439
0
            tmpRow = rRow;
440
0
    }
441
0
    else if (nMovY < 0 && nStartY > 0 && rRow > nStartY)
442
0
    {
443
0
        SCCOL colStart = std::min(rCol, nStartX);
444
0
        SCCOL colEnd = std::max(rCol, nStartX);
445
0
        for (SCCOL i = colStart; i <= colEnd && tmpRow > nStartY;)
446
0
        {
447
0
            if (pDoc->IsVerOverlapped(i, tmpRow, nTab))
448
0
            {
449
0
                do
450
0
                {
451
0
                    --tmpRow;
452
0
                } while (pDoc->IsVerOverlapped(i, tmpRow, nTab));
453
0
                i = colStart;
454
0
            }
455
0
            else
456
0
                ++i;
457
0
        }
458
0
        if (tmpRow > nStartY)
459
0
            tmpRow = rRow;
460
0
    }
461
462
0
    if (tmpCol != rCol)
463
0
        rCol = tmpCol;
464
0
    if (tmpRow != rRow)
465
0
        rRow = tmpRow;
466
0
}
467
}
468
469
void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
470
0
{
471
0
    auto& rDoc = aViewData.GetDocument();
472
0
    if (!rDoc.ValidCol(nStartCol)) nStartCol = rDoc.MaxCol();
473
0
    if (!rDoc.ValidRow(nStartRow)) nStartRow = rDoc.MaxRow();
474
0
    if (!rDoc.ValidCol(nEndCol)) nEndCol = rDoc.MaxCol();
475
0
    if (!rDoc.ValidRow(nEndRow)) nEndRow = rDoc.MaxRow();
476
477
0
    bool bLeft = (nStartCol==0 && nEndCol==rDoc.MaxCol());
478
0
    bool bTop = (nStartRow==0 && nEndRow==rDoc.MaxRow());
479
480
0
    if (bLeft)
481
0
        PaintLeftArea( nStartRow, nEndRow );
482
0
    if (bTop)
483
0
        PaintTopArea( nStartCol, nEndCol );
484
485
0
    aViewData.GetDocument().ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
486
0
                                            aViewData.CurrentTabForData() );
487
0
    PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, ScUpdateMode::Marks );
488
0
}
489
490
bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
491
0
{
492
0
    return IsBlockMode()
493
0
        && nBlockStartX == nCol
494
0
        && nBlockStartY == nRow
495
0
        && nBlockStartZ == nTab;
496
0
}
497
498
void ScTabView::InitOwnBlockMode( const ScRange& rMarkRange )
499
0
{
500
0
    if (IsBlockMode())
501
0
        return;
502
503
    // when there is no (old) selection anymore, delete anchor in SelectionEngine:
504
0
    ScMarkData& rMark = aViewData.GetMarkData();
505
0
    if (!rMark.IsMarked() && !rMark.IsMultiMarked())
506
0
        GetSelEngine()->CursorPosChanging( false, false );
507
508
0
    meBlockMode = Own;
509
0
    nBlockStartX = rMarkRange.aStart.Col();
510
0
    nBlockStartY = rMarkRange.aStart.Row();
511
0
    nBlockStartZ = rMarkRange.aStart.Tab();
512
0
    nBlockEndX = rMarkRange.aEnd.Col();
513
0
    nBlockEndY = rMarkRange.aEnd.Row();
514
0
    nBlockEndZ = rMarkRange.aEnd.Tab();
515
516
0
    SelectionChanged();     // status is checked with mark set
517
0
}
518
519
void ScTabView::InitBlockModeHighlight( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
520
                                        bool bCols, bool bRows )
521
0
{
522
0
    if (meHighlightBlockMode != None)
523
0
        return;
524
525
0
    auto& rDoc = aViewData.GetDocument();
526
0
    if (!rDoc.ValidCol(nCurX)) nCurX = rDoc.MaxCol();
527
0
    if (!rDoc.ValidRow(nCurY)) nCurY = rDoc.MaxRow();
528
529
0
    ScMarkData& rMark = aViewData.GetHighlightData();
530
0
    meHighlightBlockMode = Normal;
531
532
0
    SCROW nStartY = nCurY;
533
0
    SCCOL nStartX = nCurX;
534
0
    SCROW nEndY = nCurY;
535
0
    SCCOL nEndX = nCurX;
536
537
0
    if (bCols)
538
0
    {
539
0
        nStartY = 0;
540
0
        nEndY = rDoc.MaxRow();
541
0
    }
542
543
0
    if (bRows)
544
0
    {
545
0
        nStartX = 0;
546
0
        nEndX = rDoc.MaxCol();
547
0
    }
548
549
0
    rMark.SetMarkArea( ScRange( nStartX, nStartY, nCurZ, nEndX, nEndY, nCurZ ) );
550
0
    UpdateHighlightOverlay();
551
0
}
552
553
void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
554
                               bool bTestNeg, bool bCols, bool bRows, bool bForceNeg )
555
0
{
556
0
    if (IsBlockMode())
557
0
        return;
558
559
0
    auto& rDoc = aViewData.GetDocument();
560
0
    if (!rDoc.ValidCol(nCurX)) nCurX = rDoc.MaxCol();
561
0
    if (!rDoc.ValidRow(nCurY)) nCurY = rDoc.MaxRow();
562
563
0
    ScMarkData& rMark = aViewData.GetMarkData();
564
0
    SCTAB nTab = aViewData.CurrentTabForData();
565
566
    //  unmark part?
567
0
    if (bForceNeg)
568
0
        bBlockNeg = true;
569
0
    else if (bTestNeg)
570
0
    {
571
0
        if ( bCols )
572
0
            bBlockNeg = rMark.IsColumnMarked( nCurX );
573
0
        else if ( bRows )
574
0
            bBlockNeg = rMark.IsRowMarked( nCurY );
575
0
        else
576
0
            bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
577
0
    }
578
0
    else
579
0
        bBlockNeg = false;
580
0
    rMark.SetMarkNegative(bBlockNeg);
581
582
0
    meBlockMode = Normal;
583
0
    bBlockCols = bCols;
584
0
    bBlockRows = bRows;
585
0
    nBlockStartX = nBlockStartXOrig = nCurX;
586
0
    nBlockStartY = nBlockStartYOrig = nCurY;
587
0
    nBlockStartZ = nCurZ;
588
0
    nBlockEndX = nOldCurX = nBlockStartX;
589
0
    nBlockEndY = nOldCurY = nBlockStartY;
590
0
    nBlockEndZ = nBlockStartZ;
591
592
0
    if (bBlockCols)
593
0
    {
594
0
        nBlockStartY = nBlockStartYOrig = 0;
595
0
        nBlockEndY = rDoc.MaxRow();
596
0
    }
597
598
0
    if (bBlockRows)
599
0
    {
600
0
        nBlockStartX = nBlockStartXOrig = 0;
601
0
        nBlockEndX = rDoc.MaxCol();
602
0
    }
603
604
0
    rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
605
606
0
    UpdateSelectionOverlay();
607
0
}
608
609
void ScTabView::DoneBlockModeHighlight( bool bContinue )
610
0
{
611
0
    if (meHighlightBlockMode == None)
612
0
        return;
613
614
0
    ScMarkData& rMark = aViewData.GetHighlightData();
615
0
    bool bFlag = rMark.GetMarkingFlag();
616
0
    rMark.SetMarking(false);
617
618
0
    if (bContinue)
619
0
        rMark.MarkToMulti();
620
0
    else
621
0
    {
622
0
        SCTAB nTab = aViewData.CurrentTabForData();
623
0
        ScDocument& rDoc = aViewData.GetDocument();
624
0
        if ( rDoc.HasTable(nTab) )
625
0
            rMark.ResetMark();
626
0
    }
627
0
    meHighlightBlockMode = None;
628
629
0
    rMark.SetMarking(bFlag);
630
0
    if (bContinue)
631
0
        rMark.SetMarking(false);
632
0
}
633
634
void ScTabView::DoneBlockMode( bool bContinue )
635
0
{
636
    // When switching between sheet and header SelectionEngine DeselectAll may be called,
637
    // because the other engine does not have any anchor.
638
    // bMoveIsShift prevents the selection to be canceled.
639
640
0
    if (!IsBlockMode() || bMoveIsShift)
641
0
        return;
642
643
0
    ScMarkData& rMark = aViewData.GetMarkData();
644
0
    bool bFlag = rMark.GetMarkingFlag();
645
0
    rMark.SetMarking(false);
646
647
0
    if (bBlockNeg && !bContinue)
648
0
        rMark.MarkToMulti();
649
650
0
    if (bContinue)
651
0
        rMark.MarkToMulti();
652
0
    else
653
0
    {
654
        // the sheet may be invalid at this point because DoneBlockMode from SetTabNo is
655
        // called (for example, when the current sheet is closed from another View)
656
0
        SCTAB nTab = aViewData.CurrentTabForData();
657
0
        ScDocument& rDoc = aViewData.GetDocument();
658
0
        if ( rDoc.HasTable(nTab) )
659
0
            PaintBlock( true );                             // true -> delete block
660
0
        else
661
0
            rMark.ResetMark();
662
0
    }
663
0
    meBlockMode = None;
664
665
0
    rMark.SetMarking(bFlag);
666
0
    rMark.SetMarkNegative(false);
667
0
}
668
669
bool ScTabView::IsBlockMode() const
670
0
{
671
0
    return meBlockMode != None;
672
0
}
673
674
void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
675
                            bool bCols, bool bRows, bool bCellSelection )
676
0
{
677
0
    ScDocument& rDocument = aViewData.GetDocument();
678
0
    if (!rDocument.ValidCol(nCurX)) nCurX = rDocument.MaxCol();
679
0
    if (!rDocument.ValidRow(nCurY)) nCurY = rDocument.MaxRow();
680
681
0
    if (!IsBlockMode())
682
0
    {
683
0
        OSL_FAIL( "MarkCursor not in BlockMode" );
684
0
        InitBlockMode( nCurX, nCurY, nCurZ, false, bCols, bRows );
685
0
    }
686
687
0
    if (bCols)
688
0
        nCurY = rDocument.MaxRow();
689
0
    if (bRows)
690
0
        nCurX = rDocument.MaxCol();
691
692
0
    ScMarkData& rMark = aViewData.GetMarkData();
693
0
    OSL_ENSURE(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
694
0
    const ScRange& aMarkRange = rMark.GetMarkArea();
695
0
    if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
696
0
        ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
697
0
        ( meBlockMode == Own ))
698
0
    {
699
        //  Mark has been changed
700
        // (Eg MarkToSimple if by negative everything was erased, except for a rectangle)
701
        // or after InitOwnBlockMode is further marked with shift-
702
0
        bool bOldShift = bMoveIsShift;
703
0
        bMoveIsShift = false;          //  really move
704
0
        DoneBlockMode();               //! Set variables directly? (-> no flicker)
705
0
        bMoveIsShift = bOldShift;
706
707
0
        InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
708
0
                        nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows );
709
0
    }
710
711
0
    if ( nCurX != nOldCurX || nCurY != nOldCurY )
712
0
    {
713
        // Current cursor has moved
714
715
0
        SCTAB nTab = nCurZ;
716
717
0
        if ( bCellSelection )
718
0
        {
719
            // Expand selection area accordingly when the current selection cuts
720
            // through a merged cell.
721
0
            ScRange cellSel(nBlockStartXOrig, nBlockStartYOrig, nTab, nCurX, nCurY, nTab);
722
0
            cellSel.PutInOrder();
723
0
            ScRange oldSel;
724
0
            do
725
0
            {
726
0
                oldSel = cellSel;
727
0
                rDocument.ExtendOverlapped(cellSel);
728
0
                rDocument.ExtendMerge(cellSel);
729
0
            } while (oldSel != cellSel);
730
731
            // Preserve the directionality of the selection
732
0
            if (nCurX >= nBlockStartXOrig)
733
0
            {
734
0
                nBlockStartX = cellSel.aStart.Col();
735
0
                nBlockEndX = cellSel.aEnd.Col();
736
0
            }
737
0
            else
738
0
            {
739
0
                nBlockStartX = cellSel.aEnd.Col();
740
0
                nBlockEndX = cellSel.aStart.Col();
741
0
            }
742
0
            if (nCurY >= nBlockStartYOrig)
743
0
            {
744
0
                nBlockStartY = cellSel.aStart.Row();
745
0
                nBlockEndY = cellSel.aEnd.Row();
746
0
            }
747
0
            else
748
0
            {
749
0
                nBlockStartY = cellSel.aEnd.Row();
750
0
                nBlockEndY = cellSel.aStart.Row();
751
0
            }
752
0
        }
753
0
        else
754
0
        {
755
0
            nBlockEndX = nCurX;
756
0
            nBlockEndY = nCurY;
757
0
        }
758
759
        // Set new selection area
760
0
        rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
761
762
0
        UpdateSelectionOverlay();
763
0
        SelectionChanged();
764
765
0
        nOldCurX = nBlockEndX;
766
0
        nOldCurY = nBlockEndY;
767
768
0
        aViewData.GetViewShell()->UpdateInputHandler();
769
0
    }
770
771
0
    if ( !bCols && !bRows )
772
0
        aHdrFunc.SetAnchorFlag( false );
773
0
}
774
775
void ScTabView::GetPageMoveEndPosition(SCCOL nMovX, SCROW nMovY, SCCOL& rPageX, SCROW& rPageY)
776
0
{
777
0
    SCCOL nCurX;
778
0
    SCROW nCurY;
779
0
    if (aViewData.IsRefMode())
780
0
    {
781
0
        nCurX = aViewData.GetRefEndX();
782
0
        nCurY = aViewData.GetRefEndY();
783
0
    }
784
0
    else if (IsBlockMode())
785
0
    {
786
        // block end position.
787
0
        nCurX = nBlockEndX;
788
0
        nCurY = nBlockEndY;
789
0
    }
790
0
    else
791
0
    {
792
        // cursor position
793
0
        nCurX = aViewData.GetCurX();
794
0
        nCurY = aViewData.GetCurY();
795
0
    }
796
797
0
    ScSplitPos eWhich = aViewData.GetActivePart();
798
0
    ScHSplitPos eWhichX = WhichH( eWhich );
799
0
    ScVSplitPos eWhichY = WhichV( eWhich );
800
801
0
    auto nScrSizeY = SC_SIZE_NONE;
802
0
    if (comphelper::LibreOfficeKit::isActive() && aViewData.GetPageUpDownOffset() > 0) {
803
0
        nScrSizeY = ScViewData::ToPixel( aViewData.GetPageUpDownOffset(), aViewData.GetPPTX() );
804
0
    }
805
806
0
    SCCOL nPageX;
807
0
    SCROW nPageY;
808
0
    if (nMovX >= 0)
809
0
        nPageX = aViewData.CellsAtX( nCurX, 1, eWhichX ) * nMovX;
810
0
    else
811
0
        nPageX = aViewData.CellsAtX( nCurX, -1, eWhichX ) * nMovX;
812
813
0
    if (nMovY >= 0)
814
0
        nPageY = aViewData.CellsAtY( nCurY, 1, eWhichY, nScrSizeY ) * nMovY;
815
0
    else
816
0
        nPageY = aViewData.CellsAtY( nCurY, -1, eWhichY, nScrSizeY ) * nMovY;
817
818
0
    if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1;
819
0
    if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1;
820
821
0
    rPageX = nPageX;
822
0
    rPageY = nPageY;
823
0
}
824
825
void ScTabView::GetAreaMoveEndPosition(SCCOL nMovX, SCROW nMovY, ScFollowMode eMode,
826
                                       SCCOL& rAreaX, SCROW& rAreaY, ScFollowMode& rMode,
827
                                       bool bInteractiveByUser)
828
0
{
829
0
    SCCOL nNewX = -1;
830
0
    SCROW nNewY = -1;
831
832
    // current cursor position.
833
0
    SCCOL nCurX = aViewData.GetCurX();
834
0
    SCROW nCurY = aViewData.GetCurY();
835
836
0
    ScModule* pScModule = ScModule::get();
837
0
    bool bLegacyCellSelection = pScModule->GetInputOptions().GetLegacyCellSelection();
838
0
    bool bIncrementallyExpandToDocLimits(false);
839
840
0
    if (aViewData.IsRefMode())
841
0
    {
842
0
        nNewX = aViewData.GetRefEndX();
843
0
        nNewY = aViewData.GetRefEndY();
844
0
        nCurX = aViewData.GetRefStartX();
845
0
        nCurY = aViewData.GetRefStartY();
846
0
    }
847
0
    else if (IsBlockMode())
848
0
    {
849
        // block end position.
850
0
        nNewX = nBlockEndX;
851
0
        nNewY = nBlockEndY;
852
0
    }
853
0
    else
854
0
    {
855
0
        nNewX = nCurX;
856
0
        nNewY = nCurY;
857
        // cool#6931 on ctrl+[right/down] don't immediately leap to the far limits of the document when no more data,
858
        // instead jump a generous block of emptiness. Limit to direct interaction by user and the simple
859
        // case.
860
0
        bIncrementallyExpandToDocLimits = bInteractiveByUser && (nMovX == 1 || nMovY == 1) &&
861
0
                                          !bLegacyCellSelection && comphelper::LibreOfficeKit::isActive();
862
0
    }
863
864
0
    ScDocument& rDoc = aViewData.GetDocument();
865
0
    SCTAB nTab = aViewData.CurrentTabForData();
866
867
    // FindAreaPos knows only -1 or 1 as direction
868
0
    SCCOL nVirtualX = bLegacyCellSelection ? nNewX : nCurX;
869
0
    SCROW nVirtualY = bLegacyCellSelection ? nNewY : nCurY;
870
871
0
    SCCOLROW i;
872
0
    if ( nMovX > 0 )
873
0
        for ( i=0; i<nMovX; i++ )
874
0
            rDoc.FindAreaPos( nNewX, nVirtualY, nTab,  SC_MOVE_RIGHT );
875
0
    if ( nMovX < 0 )
876
0
        for ( i=0; i<-nMovX; i++ )
877
0
            rDoc.FindAreaPos( nNewX, nVirtualY, nTab,  SC_MOVE_LEFT );
878
0
    if ( nMovY > 0 )
879
0
        for ( i=0; i<nMovY; i++ )
880
0
            rDoc.FindAreaPos( nVirtualX, nNewY, nTab,  SC_MOVE_DOWN );
881
0
    if ( nMovY < 0 )
882
0
        for ( i=0; i<-nMovY; i++ )
883
0
            rDoc.FindAreaPos( nVirtualX, nNewY, nTab,  SC_MOVE_UP );
884
885
0
    if (eMode==SC_FOLLOW_JUMP)                  // bottom right do not show too much grey
886
0
    {
887
0
        if (nMovX != 0 && nNewX == rDoc.MaxCol())
888
0
        {
889
0
            eMode = SC_FOLLOW_LINE;
890
0
            if (bIncrementallyExpandToDocLimits)
891
0
            {
892
0
                if (const ScTable* pTab = rDoc.FetchTable(nTab))
893
0
                {
894
0
                    if (!pTab->HasData(nNewX, nCurY))
895
0
                    {
896
0
                        SCCOL nLastUsedCol(0);
897
0
                        SCROW nLastUsedRow(0);
898
0
                        rDoc.GetPrintArea(nTab, nLastUsedCol, nLastUsedRow);
899
0
                        SCCOL nJumpFrom = std::max(nCurX, nLastUsedCol);
900
0
                        nNewX = ((nJumpFrom / 13) + 2) * 13 - 1;
901
0
                    }
902
0
                }
903
0
            }
904
0
        }
905
0
        if (nMovY != 0 && nNewY == rDoc.MaxRow())
906
0
        {
907
0
            eMode = SC_FOLLOW_LINE;
908
0
            if (bIncrementallyExpandToDocLimits)
909
0
            {
910
0
                if (const ScTable* pTab = rDoc.FetchTable(nTab))
911
0
                {
912
0
                    if (!pTab->HasData(nCurX, nNewY))
913
0
                    {
914
0
                        SCCOL nLastUsedCol(0);
915
0
                        SCROW nLastUsedRow(0);
916
0
                        rDoc.GetPrintArea(nTab, nLastUsedCol, nLastUsedRow);
917
0
                        SCROW nJumpFrom = std::max(nCurY, nLastUsedRow);
918
0
                        nNewY = ((nJumpFrom / 500) + 2) * 500 - 1;
919
0
                    }
920
0
                }
921
0
            }
922
0
        }
923
0
    }
924
925
0
    if (aViewData.IsRefMode())
926
0
    {
927
0
        rAreaX = nNewX - aViewData.GetRefEndX();
928
0
        rAreaY = nNewY - aViewData.GetRefEndY();
929
0
    }
930
0
    else if (IsBlockMode())
931
0
    {
932
0
        rAreaX = nNewX - nBlockEndX;
933
0
        rAreaY = nNewY - nBlockEndY;
934
0
    }
935
0
    else
936
0
    {
937
0
        rAreaX = nNewX - nCurX;
938
0
        rAreaY = nNewY - nCurY;
939
0
    }
940
0
    rMode = eMode;
941
0
}
942
943
void ScTabView::SkipCursorHorizontal(SCCOL& rCurX, SCROW& rCurY, SCCOL nOldX, SCCOL nMovX)
944
0
{
945
0
    ScDocument& rDoc = aViewData.GetDocument();
946
0
    SCTAB nTab = aViewData.CurrentTabForData();
947
948
0
    bool bSkipProtected = false, bSkipUnprotected = false;
949
0
    const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
950
0
    if (pProtect && pProtect->isProtected())
951
0
    {
952
0
        bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
953
0
        bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
954
0
    }
955
956
0
    bool bSkipCell = false;
957
0
    bool bHFlip = false;
958
    // If a number of last columns are hidden, search up to and including the first of them,
959
    // because after it nothing changes.
960
0
    SCCOL nMaxCol;
961
0
    if(rDoc.ColHidden(rDoc.MaxCol(), nTab, &nMaxCol))
962
0
        ++nMaxCol;
963
0
    else
964
0
        nMaxCol = rDoc.MaxCol();
965
    // Search also at least up to and including the first unallocated column (all unallocated columns
966
    // share a set of attrs).
967
0
    nMaxCol = std::max( nMaxCol, std::min<SCCOL>( rDoc.GetAllocatedColumnsCount(nTab) + 1, rDoc.MaxCol()));
968
0
    do
969
0
    {
970
0
        bSkipCell = rDoc.ColHidden(rCurX, nTab) || rDoc.IsHorOverlapped(rCurX, rCurY, nTab);
971
0
        if (bSkipProtected && !bSkipCell)
972
0
            bSkipCell = rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected);
973
0
        if (bSkipUnprotected && !bSkipCell)
974
0
            bSkipCell = !rDoc.HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HasAttrFlags::Protected);
975
976
0
        if (bSkipCell)
977
0
        {
978
0
            if (rCurX <= 0 || rCurX >= nMaxCol)
979
0
            {
980
0
                if (bHFlip)
981
0
                {
982
0
                    rCurX = nOldX;
983
0
                    bSkipCell = false;
984
0
                }
985
0
                else
986
0
                {
987
0
                    nMovX = -nMovX;
988
0
                    if (nMovX > 0)
989
0
                        ++rCurX;
990
0
                    else
991
0
                        --rCurX;
992
0
                    bHFlip = true;
993
0
                }
994
0
            }
995
0
            else
996
0
                if (nMovX > 0)
997
0
                    ++rCurX;
998
0
                else
999
0
                    --rCurX;
1000
0
        }
1001
0
    }
1002
0
    while (bSkipCell);
1003
1004
0
    if (rDoc.IsVerOverlapped(rCurX, rCurY, nTab))
1005
0
    {
1006
0
        aViewData.SetOldCursor(rCurX, rCurY);
1007
0
        while (rDoc.IsVerOverlapped(rCurX, rCurY, nTab))
1008
0
            --rCurY;
1009
0
    }
1010
0
}
1011
1012
void ScTabView::SkipCursorVertical(SCCOL& rCurX, SCROW& rCurY, SCROW nOldY, SCROW nMovY)
1013
0
{
1014
0
    ScDocument& rDoc = aViewData.GetDocument();
1015
0
    SCTAB nTab = aViewData.CurrentTabForData();
1016
1017
0
    bool bSkipProtected = false, bSkipUnprotected = false;
1018
0
    const ScTableProtection* pProtect = rDoc.GetTabProtection(nTab);
1019
0
    if (pProtect && pProtect->isProtected())
1020
0
    {
1021
0
        bSkipProtected   = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
1022
0
        bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
1023
0
    }
1024
1025
0
    bool bSkipCell = false;
1026
0
    bool bVFlip = false;
1027
    // Avoid repeated calls to RowHidden(), IsVerOverlapped() and HasAttrib().
1028
0
    SCROW nFirstSameHiddenRow = -1;
1029
0
    SCROW nLastSameHiddenRow = -1;
1030
0
    bool bRowHidden = false;
1031
0
    SCROW nFirstSameIsVerOverlapped = -1;
1032
0
    SCROW nLastSameIsVerOverlapped = -1;
1033
0
    bool bIsVerOverlapped = false;
1034
0
    SCROW nFirstSameHasAttribRow = -1;
1035
0
    SCROW nLastSameHasAttribRow = -1;
1036
0
    bool bHasAttribProtected = false;
1037
0
    do
1038
0
    {
1039
0
        if( rCurY < nFirstSameHiddenRow || rCurY > nLastSameHiddenRow )
1040
0
            bRowHidden = rDoc.RowHidden(rCurY, nTab, &nFirstSameHiddenRow, &nLastSameHiddenRow);
1041
0
        bSkipCell = bRowHidden;
1042
0
        if( !bSkipCell )
1043
0
        {
1044
0
            if( rCurY < nFirstSameIsVerOverlapped || rCurY > nLastSameIsVerOverlapped )
1045
0
                bIsVerOverlapped = rDoc.IsVerOverlapped(rCurX, rCurY, nTab, &nFirstSameIsVerOverlapped, &nLastSameIsVerOverlapped);
1046
0
            bSkipCell = bIsVerOverlapped;
1047
0
        }
1048
0
        if (bSkipProtected && !bSkipCell)
1049
0
        {
1050
0
            if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow )
1051
0
                bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected,
1052
0
                                                     &nFirstSameHasAttribRow, &nLastSameHasAttribRow);
1053
0
            bSkipCell = bHasAttribProtected;
1054
0
        }
1055
0
        if (bSkipUnprotected && !bSkipCell)
1056
0
        {
1057
0
            if( rCurY < nFirstSameHasAttribRow || rCurY > nLastSameHasAttribRow )
1058
0
                bHasAttribProtected = rDoc.HasAttrib(rCurX, rCurY, nTab, HasAttrFlags::Protected,
1059
0
                                                     &nFirstSameHasAttribRow, &nLastSameHasAttribRow);
1060
0
            bSkipCell = !bHasAttribProtected;
1061
0
        }
1062
1063
0
        if (bSkipCell)
1064
0
        {
1065
0
            if (rCurY <= 0 || rCurY >= rDoc.MaxRow())
1066
0
            {
1067
0
                if (bVFlip)
1068
0
                {
1069
0
                    rCurY = nOldY;
1070
0
                    bSkipCell = false;
1071
0
                }
1072
0
                else
1073
0
                {
1074
0
                    nMovY = -nMovY;
1075
0
                    if (nMovY > 0)
1076
0
                        ++rCurY;
1077
0
                    else
1078
0
                        --rCurY;
1079
0
                    bVFlip = true;
1080
0
                }
1081
0
            }
1082
0
            else
1083
0
                if (nMovY > 0)
1084
0
                    ++rCurY;
1085
0
                else
1086
0
                    --rCurY;
1087
0
        }
1088
0
    }
1089
0
    while (bSkipCell);
1090
1091
0
    if (rDoc.IsHorOverlapped(rCurX, rCurY, nTab))
1092
0
    {
1093
0
        aViewData.SetOldCursor(rCurX, rCurY);
1094
0
        while (rDoc.IsHorOverlapped(rCurX, rCurY, nTab))
1095
0
            --rCurX;
1096
0
    }
1097
0
}
1098
1099
void ScTabView::ExpandBlock(SCCOL nMovX, SCROW nMovY, ScFollowMode eMode)
1100
0
{
1101
0
    if (!nMovX && !nMovY)
1102
        // Nothing to do.  Bail out.
1103
0
        return;
1104
1105
0
    ScTabViewShell* pViewShell = aViewData.GetViewShell();
1106
0
    bool bRefInputMode = pViewShell && pViewShell->IsRefInputMode();
1107
0
    if (bRefInputMode && !aViewData.IsRefMode())
1108
        // initialize formula reference mode if it hasn't already.
1109
0
        InitRefMode(aViewData.GetCurX(), aViewData.GetCurY(), aViewData.CurrentTabForData(), SC_REFTYPE_REF);
1110
1111
0
    ScDocument& rDoc = aViewData.GetDocument();
1112
1113
0
    if (aViewData.IsRefMode())
1114
0
    {
1115
        // formula reference mode
1116
1117
0
        SCCOL nNewX = aViewData.GetRefEndX();
1118
0
        SCROW nNewY = aViewData.GetRefEndY();
1119
0
        SCTAB nRefTab = aViewData.GetRefEndZ();
1120
1121
0
        moveRefByCell(nNewX, nNewY, nMovX, nMovY, nRefTab, rDoc);
1122
1123
0
        UpdateRef(nNewX, nNewY, nRefTab);
1124
0
        SCCOL nTargetCol = nNewX;
1125
0
        SCROW nTargetRow = nNewY;
1126
0
        if (((aViewData.GetRefStartX() == 0) || (aViewData.GetRefStartY() == 0)) &&
1127
0
            ((nNewX != rDoc.MaxCol()) || (nNewY != rDoc.MaxRow())))
1128
0
        {
1129
            // Row selection
1130
0
            if ((aViewData.GetRefStartX() == 0) && (nNewX == rDoc.MaxCol()))
1131
0
                nTargetCol = aViewData.GetCurX();
1132
            // Column selection
1133
0
            if ((aViewData.GetRefStartY() == 0) && (nNewY == rDoc.MaxRow()))
1134
0
                nTargetRow = aViewData.GetCurY();
1135
0
        }
1136
0
        AlignToCursor(nTargetCol, nTargetRow, eMode);
1137
0
    }
1138
0
    else
1139
0
    {
1140
        // normal selection mode
1141
1142
0
        SCTAB nTab = aViewData.CurrentTabForData();
1143
0
        SCCOL nOrigX = aViewData.GetCurX();
1144
0
        SCROW nOrigY = aViewData.GetCurY();
1145
1146
        // Note that the origin position *never* moves during selection.
1147
1148
0
        if (!IsBlockMode())
1149
0
        {
1150
0
            InitBlockMode(nOrigX, nOrigY, nTab, true);
1151
0
            const ScMergeAttr& rMergeAttr = rDoc.GetAttr(nOrigX, nOrigY, nTab, ATTR_MERGE);
1152
0
            if (rMergeAttr.IsMerged())
1153
0
            {
1154
0
                nBlockEndX = nOrigX + rMergeAttr.GetColMerge() - 1;
1155
0
                nBlockEndY = nOrigY + rMergeAttr.GetRowMerge() - 1;
1156
0
            }
1157
0
        }
1158
1159
0
        moveCursorToProperSide(nBlockEndX, nBlockEndY, nMovX, nMovY, nBlockStartX, nBlockStartY,
1160
0
                               nTab, &rDoc);
1161
0
        moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, &rDoc);
1162
0
        checkBoundary(&rDoc, nBlockEndX, nBlockEndY);
1163
0
        moveCursorByMergedCell(nBlockEndX, nBlockEndY, nMovX, nMovY, nBlockStartX, nBlockStartY,
1164
0
                               nTab, &rDoc);
1165
0
        checkBoundary(&rDoc, nBlockEndX, nBlockEndY);
1166
1167
0
        MarkCursor(nBlockEndX, nBlockEndY, nTab, false, false, true);
1168
1169
        // Check if the entire row(s) or column(s) are selected.
1170
0
        ScSplitPos eActive = aViewData.GetActivePart();
1171
0
        bool bRowSelected = (nBlockStartX == 0 && nBlockEndX == rDoc.MaxCol());
1172
0
        bool bColSelected = (nBlockStartY == 0 && nBlockEndY == rDoc.MaxRow());
1173
0
        SCCOL nAlignX = bRowSelected ? aViewData.GetPosX(WhichH(eActive)) : nBlockEndX;
1174
0
        SCROW nAlignY = bColSelected ? aViewData.GetPosY(WhichV(eActive)) : nBlockEndY;
1175
0
        AlignToCursor(nAlignX, nAlignY, eMode);
1176
1177
0
        SelectionChanged();
1178
0
    }
1179
0
}
1180
1181
void ScTabView::ExpandBlockPage(SCCOL nMovX, SCROW nMovY)
1182
0
{
1183
0
    SCCOL nPageX;
1184
0
    SCROW nPageY;
1185
0
    GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
1186
0
    ExpandBlock(nPageX, nPageY, SC_FOLLOW_FIX);
1187
0
}
1188
1189
void ScTabView::ExpandBlockArea(SCCOL nMovX, SCROW nMovY)
1190
0
{
1191
0
    SCCOL nAreaX;
1192
0
    SCROW nAreaY;
1193
0
    ScFollowMode eMode;
1194
0
    GetAreaMoveEndPosition(nMovX, nMovY, SC_FOLLOW_JUMP, nAreaX, nAreaY, eMode);
1195
0
    ExpandBlock(nAreaX, nAreaY, eMode);
1196
0
}
1197
1198
void ScTabView::UpdateCopySourceOverlay()
1199
0
{
1200
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1201
0
        if (pWin && pWin->IsVisible())
1202
0
            pWin->UpdateCopySourceOverlay();
1203
0
}
1204
1205
void ScTabView::UpdateSelectionOverlay()
1206
0
{
1207
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1208
0
        if ( pWin && pWin->IsVisible() )
1209
0
            pWin->UpdateSelectionOverlay();
1210
0
}
1211
1212
void ScTabView::UpdateHighlightOverlay()
1213
0
{
1214
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1215
0
        if ( pWin && pWin->IsVisible() )
1216
0
            pWin->UpdateHighlightOverlay();
1217
0
}
1218
1219
void ScTabView::UpdateShrinkOverlay()
1220
0
{
1221
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1222
0
        if ( pWin && pWin->IsVisible() )
1223
0
            pWin->UpdateShrinkOverlay();
1224
0
}
1225
1226
void ScTabView::UpdateAllOverlays()
1227
0
{
1228
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1229
0
        if ( pWin && pWin->IsVisible() )
1230
0
            pWin->UpdateAllOverlays();
1231
0
}
1232
1233
//!
1234
//! divide PaintBlock into two methods: RepaintBlock and RemoveBlock or similar
1235
//!
1236
1237
void ScTabView::PaintBlock( bool bReset )
1238
0
{
1239
0
    ScMarkData& rMark = aViewData.GetMarkData();
1240
0
    SCTAB nTab = aViewData.CurrentTabForData();
1241
0
    bool bMulti = rMark.IsMultiMarked();
1242
0
    if (!(rMark.IsMarked() || bMulti))
1243
0
        return;
1244
1245
0
    ScRange aMarkRange;
1246
0
    HideAllCursors();
1247
0
    if (bMulti)
1248
0
    {
1249
0
        bool bFlag = rMark.GetMarkingFlag();
1250
0
        rMark.SetMarking(false);
1251
0
        rMark.MarkToMulti();
1252
0
        aMarkRange = rMark.GetMultiMarkArea();
1253
0
        rMark.MarkToSimple();
1254
0
        rMark.SetMarking(bFlag);
1255
0
    }
1256
0
    else
1257
0
        aMarkRange = rMark.GetMarkArea();
1258
1259
0
    nBlockStartX = aMarkRange.aStart.Col();
1260
0
    nBlockStartY = aMarkRange.aStart.Row();
1261
0
    nBlockStartZ = aMarkRange.aStart.Tab();
1262
0
    nBlockEndX = aMarkRange.aEnd.Col();
1263
0
    nBlockEndY = aMarkRange.aEnd.Row();
1264
0
    nBlockEndZ = aMarkRange.aEnd.Tab();
1265
1266
0
    bool bDidReset = false;
1267
1268
0
    if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ )
1269
0
    {
1270
0
        if ( bReset )
1271
0
        {
1272
            // Inverting when deleting only on active View
1273
0
            if ( aViewData.IsActive() )
1274
0
            {
1275
0
                rMark.ResetMark();
1276
0
                UpdateSelectionOverlay();
1277
0
                bDidReset = true;
1278
0
            }
1279
0
        }
1280
0
        else
1281
0
            PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
1282
0
    }
1283
1284
0
    if ( bReset && !bDidReset )
1285
0
        rMark.ResetMark();
1286
1287
0
    ShowAllCursors();
1288
0
}
1289
1290
void ScTabView::SelectAll( bool bContinue )
1291
0
{
1292
0
    ScDocument& rDoc = aViewData.GetDocument();
1293
0
    ScMarkData& rMark = aViewData.GetMarkData();
1294
0
    SCTAB nTab = aViewData.CurrentTabForData();
1295
1296
0
    if (rMark.IsMarked())
1297
0
    {
1298
0
        if ( rMark.GetMarkArea() == ScRange( 0,0,nTab, rDoc.MaxCol(),rDoc.MaxRow(),nTab ) )
1299
0
            return;
1300
0
    }
1301
1302
0
    DoneBlockMode( bContinue );
1303
0
    InitBlockMode( 0,0,nTab );
1304
0
    MarkCursor( rDoc.MaxCol(),rDoc.MaxRow(),nTab );
1305
1306
0
    SelectionChanged();
1307
0
}
1308
1309
void ScTabView::SelectAllTables()
1310
0
{
1311
0
    ScDocument& rDoc = aViewData.GetDocument();
1312
0
    ScMarkData& rMark = aViewData.GetMarkData();
1313
0
    SCTAB nCount = rDoc.GetTableCount();
1314
1315
0
    if (nCount>1)
1316
0
    {
1317
0
        for (SCTAB i=0; i<nCount; i++)
1318
0
            rMark.SelectTable( i, true );
1319
1320
0
        aViewData.GetDocShell()->PostPaintExtras();
1321
0
        SfxBindings& rBind = aViewData.GetBindings();
1322
0
        rBind.Invalidate( FID_FILL_TAB );
1323
0
        rBind.Invalidate( FID_TAB_DESELECTALL );
1324
0
    }
1325
0
}
1326
1327
void ScTabView::DeselectAllTables()
1328
0
{
1329
0
    ScDocument& rDoc = aViewData.GetDocument();
1330
0
    ScMarkData& rMark = aViewData.GetMarkData();
1331
0
    SCTAB nTab = aViewData.CurrentTabForData();
1332
0
    SCTAB nCount = rDoc.GetTableCount();
1333
1334
0
    for (SCTAB i=0; i<nCount; i++)
1335
0
        rMark.SelectTable( i, ( i == nTab ) );
1336
1337
0
    aViewData.GetDocShell()->PostPaintExtras();
1338
0
    SfxBindings& rBind = aViewData.GetBindings();
1339
0
    rBind.Invalidate( FID_FILL_TAB );
1340
0
    rBind.Invalidate( FID_TAB_DESELECTALL );
1341
0
}
1342
1343
static bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom,
1344
                        tools::Long nWindowX, tools::Long nWindowY, const ScDocument* pDoc, SCTAB nTab,
1345
                        SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1346
                        SCCOL nFixPosX, SCROW nFixPosY )
1347
0
{
1348
0
    double fZoomFactor = static_cast<double>(Fraction(nZoom,100));
1349
0
    fScaleX *= fZoomFactor;
1350
0
    fScaleY *= fZoomFactor;
1351
1352
0
    tools::Long nBlockX = 0;
1353
0
    SCCOL nCol;
1354
0
    for (nCol=0; nCol<nFixPosX; nCol++)
1355
0
    {
1356
        //  for frozen panes, add both parts
1357
0
        sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
1358
0
        if (nColTwips)
1359
0
        {
1360
0
            nBlockX += static_cast<tools::Long>(nColTwips * fScaleX);
1361
0
            if (nBlockX > nWindowX)
1362
0
                return false;
1363
0
        }
1364
0
    }
1365
0
    for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1366
0
    {
1367
0
        sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
1368
0
        if (nColTwips)
1369
0
        {
1370
0
            nBlockX += static_cast<tools::Long>(nColTwips * fScaleX);
1371
0
            if (nBlockX > nWindowX)
1372
0
                return false;
1373
0
        }
1374
0
    }
1375
1376
0
    tools::Long nBlockY = 0;
1377
0
    for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
1378
0
    {
1379
0
        if (pDoc->RowHidden(nRow, nTab))
1380
0
            continue;
1381
1382
        //  for frozen panes, add both parts
1383
0
        sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
1384
0
        if (nRowTwips)
1385
0
        {
1386
0
            nBlockY += static_cast<tools::Long>(nRowTwips * fScaleY);
1387
0
            if (nBlockY > nWindowY)
1388
0
                return false;
1389
0
        }
1390
0
    }
1391
0
    for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
1392
0
    {
1393
0
        sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
1394
0
        if (nRowTwips)
1395
0
        {
1396
0
            nBlockY += static_cast<tools::Long>(nRowTwips * fScaleY);
1397
0
            if (nBlockY > nWindowY)
1398
0
                return false;
1399
0
        }
1400
0
    }
1401
1402
0
    return true;
1403
0
}
1404
1405
sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom )
1406
0
{
1407
0
    sal_uInt16 nZoom = 100;
1408
1409
0
    switch ( eType )
1410
0
    {
1411
0
        case SvxZoomType::PERCENT: // rZoom is no particular percent value
1412
0
            nZoom = nOldZoom;
1413
0
            break;
1414
1415
0
        case SvxZoomType::OPTIMAL:  // nZoom corresponds to the optimal size
1416
0
            {
1417
0
                ScMarkData& rMark = aViewData.GetMarkData();
1418
0
                ScDocument& rDoc = aViewData.GetDocument();
1419
1420
0
                if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1421
0
                    nZoom = 100;                // nothing selected
1422
0
                else
1423
0
                {
1424
0
                    SCTAB   nTab = aViewData.CurrentTabForData();
1425
0
                    ScRange aMarkRange;
1426
0
                    if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE )
1427
0
                        aMarkRange = rMark.GetMultiMarkArea();
1428
1429
0
                    SCCOL   nStartCol = aMarkRange.aStart.Col();
1430
0
                    SCROW   nStartRow = aMarkRange.aStart.Row();
1431
0
                    SCTAB   nStartTab = aMarkRange.aStart.Tab();
1432
0
                    SCCOL   nEndCol = aMarkRange.aEnd.Col();
1433
0
                    SCROW   nEndRow = aMarkRange.aEnd.Row();
1434
0
                    SCTAB   nEndTab = aMarkRange.aEnd.Tab();
1435
1436
0
                    if ( nTab < nStartTab && nTab > nEndTab )
1437
0
                        nTab = nStartTab;
1438
1439
0
                    ScSplitPos eUsedPart = aViewData.GetActivePart();
1440
1441
0
                    SCCOL nFixPosX = 0;
1442
0
                    SCROW nFixPosY = 0;
1443
0
                    if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
1444
0
                    {
1445
                        //  use right part
1446
0
                        eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
1447
0
                        nFixPosX = aViewData.GetFixPosX();
1448
0
                        if ( nStartCol < nFixPosX )
1449
0
                            nStartCol = nFixPosX;
1450
0
                    }
1451
0
                    if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
1452
0
                    {
1453
                        //  use bottom part
1454
0
                        eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
1455
0
                        nFixPosY = aViewData.GetFixPosY();
1456
0
                        if ( nStartRow < nFixPosY )
1457
0
                            nStartRow = nFixPosY;
1458
0
                    }
1459
1460
0
                    if (pGridWin[eUsedPart])
1461
0
                    {
1462
                        //  Because scale is rounded to pixels, the only reliable way to find
1463
                        //  the right scale is to check if a zoom fits
1464
1465
0
                        Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel();
1466
1467
                        //  for frozen panes, use sum of both parts for calculation
1468
1469
0
                        if ( nFixPosX != 0 )
1470
0
                            aWinSize.AdjustWidth(GetGridWidth( SC_SPLIT_LEFT ) );
1471
0
                        if ( nFixPosY != 0 )
1472
0
                            aWinSize.AdjustHeight(GetGridHeight( SC_SPLIT_TOP ) );
1473
1474
0
                        ScDocShell* pDocSh = aViewData.GetDocShell();
1475
0
                        double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor();
1476
0
                        double nPPTY = ScGlobal::nScreenPPTY;
1477
1478
0
                        sal_uInt16 nMin = MINZOOM;
1479
0
                        sal_uInt16 nMax = MAXZOOM;
1480
0
                        while ( nMax > nMin )
1481
0
                        {
1482
0
                            sal_uInt16 nTest = (nMin+nMax+1)/2;
1483
0
                            if ( lcl_FitsInWindow(
1484
0
                                        nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(),
1485
0
                                        &rDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow,
1486
0
                                        nFixPosX, nFixPosY ) )
1487
0
                                nMin = nTest;
1488
0
                            else
1489
0
                                nMax = nTest-1;
1490
0
                        }
1491
0
                        OSL_ENSURE( nMin == nMax, "Nesting is wrong" );
1492
0
                        nZoom = nMin;
1493
1494
0
                        if ( nZoom != nOldZoom )
1495
0
                        {
1496
                            // scroll to block only in active split part
1497
                            // (the part for which the size was calculated)
1498
1499
0
                            if ( nStartCol <= nEndCol )
1500
0
                                aViewData.SetPosX( WhichH(eUsedPart), nStartCol );
1501
0
                            if ( nStartRow <= nEndRow )
1502
0
                                aViewData.SetPosY( WhichV(eUsedPart), nStartRow );
1503
0
                        }
1504
0
                    }
1505
0
                }
1506
0
            }
1507
0
            break;
1508
1509
0
            case SvxZoomType::WHOLEPAGE:    // nZoom corresponds to the whole page or
1510
0
            case SvxZoomType::PAGEWIDTH:    // nZoom corresponds to the page width
1511
0
                {
1512
0
                    SCTAB               nCurTab     = aViewData.CurrentTabForData();
1513
0
                    ScDocument&         rDoc        = aViewData.GetDocument();
1514
0
                    ScStyleSheetPool*   pStylePool  = rDoc.GetStyleSheetPool();
1515
0
                    SfxStyleSheetBase*  pStyleSheet =
1516
0
                                            pStylePool->Find( rDoc.GetPageStyle( nCurTab ),
1517
0
                                                              SfxStyleFamily::Page );
1518
1519
0
                    OSL_ENSURE( pStyleSheet, "PageStyle not found :-/" );
1520
1521
0
                    if ( pStyleSheet )
1522
0
                    {
1523
0
                        ScPrintFunc aPrintFunc( *aViewData.GetDocShell(),
1524
0
                                                aViewData.GetViewShell()->GetPrinter(true),
1525
0
                                                nCurTab );
1526
1527
0
                        Size aPageSize = aPrintFunc.GetDataSize();
1528
1529
                        //  use the size of the largest GridWin for normal split,
1530
                        //  or both combined for frozen panes, with the (document) size
1531
                        //  of the frozen part added to the page size
1532
                        //  (with frozen panes, the size of the individual parts
1533
                        //  depends on the scale that is to be calculated)
1534
1535
0
                        if (!pGridWin[SC_SPLIT_BOTTOMLEFT])
1536
0
                            return nZoom;
1537
1538
0
                        Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
1539
0
                        ScSplitMode eHMode = aViewData.GetHSplitMode();
1540
0
                        if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
1541
0
                        {
1542
0
                            tools::Long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
1543
0
                                                        GetOutputSizePixel().Width();
1544
0
                            if ( eHMode == SC_SPLIT_FIX )
1545
0
                            {
1546
0
                                aWinSize.AdjustWidth(nOtherWidth );
1547
0
                                for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
1548
0
                                        nCol < aViewData.GetFixPosX(); nCol++ )
1549
0
                                    aPageSize.AdjustWidth(rDoc.GetColWidth( nCol, nCurTab ) );
1550
0
                            }
1551
0
                            else if ( nOtherWidth > aWinSize.Width() )
1552
0
                                aWinSize.setWidth( nOtherWidth );
1553
0
                        }
1554
0
                        ScSplitMode eVMode = aViewData.GetVSplitMode();
1555
0
                        if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
1556
0
                        {
1557
0
                            tools::Long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
1558
0
                                                        GetOutputSizePixel().Height();
1559
0
                            if ( eVMode == SC_SPLIT_FIX )
1560
0
                            {
1561
0
                                aWinSize.AdjustHeight(nOtherHeight );
1562
0
                                aPageSize.AdjustHeight(rDoc.GetRowHeight(
1563
0
                                        aViewData.GetPosY(SC_SPLIT_TOP),
1564
0
                                        aViewData.GetFixPosY()-1, nCurTab) );
1565
0
                            }
1566
0
                            else if ( nOtherHeight > aWinSize.Height() )
1567
0
                                aWinSize.setHeight( nOtherHeight );
1568
0
                        }
1569
1570
0
                        double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
1571
0
                        double nPPTY = ScGlobal::nScreenPPTY;
1572
1573
0
                        tools::Long nZoomX = static_cast<tools::Long>( aWinSize.Width() * 100 /
1574
0
                                               ( aPageSize.Width() * nPPTX ) );
1575
0
                        tools::Long nZoomY = static_cast<tools::Long>( aWinSize.Height() * 100 /
1576
0
                                               ( aPageSize.Height() * nPPTY ) );
1577
1578
0
                        if (nZoomX > 0)
1579
0
                            nZoom = static_cast<sal_uInt16>(nZoomX);
1580
1581
0
                        if (eType == SvxZoomType::WHOLEPAGE && nZoomY > 0 && nZoomY < nZoom)
1582
0
                            nZoom = static_cast<sal_uInt16>(nZoomY);
1583
0
                    }
1584
0
                }
1585
0
                break;
1586
1587
0
        default:
1588
0
            OSL_FAIL("Unknown Zoom-Revision");
1589
0
    }
1590
1591
0
    return nZoom;
1592
0
}
1593
1594
// is called for instance when the view window is shifted:
1595
1596
void ScTabView::StopMarking()
1597
0
{
1598
0
    ScSplitPos eActive = aViewData.GetActivePart();
1599
0
    if (pGridWin[eActive])
1600
0
        pGridWin[eActive]->StopMarking();
1601
1602
0
    ScHSplitPos eH = WhichH(eActive);
1603
0
    if (pColBar[eH])
1604
0
        pColBar[eH]->StopMarking();
1605
1606
0
    ScVSplitPos eV = WhichV(eActive);
1607
0
    if (pRowBar[eV])
1608
0
        pRowBar[eV]->StopMarking();
1609
0
}
1610
1611
void ScTabView::HideNoteOverlay()
1612
0
{
1613
0
    for (VclPtr<ScGridWindow> & pWin : pGridWin)
1614
0
        if (pWin && pWin->IsVisible())
1615
0
            pWin->HideNoteOverlay();
1616
0
}
1617
1618
void ScTabView::MakeDrawLayer()
1619
0
{
1620
0
    if (pDrawView)
1621
0
        return;
1622
1623
0
    aViewData.GetDocShell()->MakeDrawLayer();
1624
1625
    // pDrawView is set per Notify
1626
0
    OSL_ENSURE(pDrawView,"ScTabView::MakeDrawLayer does not work");
1627
1628
0
    for(VclPtr<ScGridWindow> & pWin : pGridWin)
1629
0
    {
1630
0
        if(pWin)
1631
0
        {
1632
0
            pWin->DrawLayerCreated();
1633
0
        }
1634
0
    }
1635
0
}
1636
1637
IMPL_STATIC_LINK_NOARG(ScTabView, InstallLOKNotifierHdl, void*, vcl::ILibreOfficeKitNotifier*)
1638
0
{
1639
0
    return GetpApp();
1640
0
}
1641
1642
void ScTabView::ErrorMessage(TranslateId pGlobStrId)
1643
0
{
1644
0
    if (ScModule::get()->IsInExecuteDrop())
1645
0
    {
1646
        // #i28468# don't show error message when called from Drag&Drop, silently abort instead
1647
0
        return;
1648
0
    }
1649
1650
0
    StopMarking();      // if called by Focus from MouseButtonDown
1651
1652
0
    weld::Window* pParent = aViewData.GetDialogParent();
1653
0
    weld::WaitObject aWaitOff( pParent );
1654
0
    bool bFocus = pParent && pParent->has_focus();
1655
1656
0
    if (pGlobStrId && pGlobStrId == STR_PROTECTIONERR)
1657
0
    {
1658
0
        if (aViewData.GetDocShell()->IsReadOnly())
1659
0
        {
1660
0
            pGlobStrId = STR_READONLYERR;
1661
0
        }
1662
0
    }
1663
1664
0
    m_xMessageBox.reset(Application::CreateMessageDialog(pParent,
1665
0
                                                         VclMessageType::Info, VclButtonsType::Ok,
1666
0
                                                         ScResId(pGlobStrId)));
1667
1668
0
    if (comphelper::LibreOfficeKit::isActive())
1669
0
        m_xMessageBox->SetInstallLOKNotifierHdl(LINK(this, ScTabView, InstallLOKNotifierHdl));
1670
1671
0
    weld::Window* pGrabOnClose = bFocus ? pParent : nullptr;
1672
0
    m_xMessageBox->runAsync(m_xMessageBox, [this, pGrabOnClose](sal_Int32 /*nResult*/) {
1673
0
        m_xMessageBox.reset();
1674
0
        if (pGrabOnClose)
1675
0
            pGrabOnClose->grab_focus();
1676
0
    });
1677
0
}
1678
1679
void ScTabView::UpdatePageBreakData( bool bForcePaint )
1680
0
{
1681
0
    std::unique_ptr<ScPageBreakData> pNewData;
1682
1683
0
    if (aViewData.IsPagebreakMode())
1684
0
    {
1685
0
        ScDocShell* pDocSh = aViewData.GetDocShell();
1686
0
        ScDocument& rDoc = pDocSh->GetDocument();
1687
0
        SCTAB nTab = aViewData.CurrentTabForData();
1688
1689
0
        sal_uInt16 nCount = rDoc.GetPrintRangeCount(nTab);
1690
0
        if (!nCount)
1691
0
            nCount = 1;
1692
0
        pNewData.reset( new ScPageBreakData(nCount) );
1693
1694
0
        ScPrintFunc aPrintFunc( *pDocSh, pDocSh->GetPrinter(), nTab, 0,0,nullptr, nullptr, pNewData.get() );
1695
        // ScPrintFunc fills the PageBreakData in ctor
1696
0
        if ( nCount > 1 )
1697
0
        {
1698
0
            aPrintFunc.ResetBreaks(nTab);
1699
0
            pNewData->AddPages();
1700
0
        }
1701
1702
        // print area changed?
1703
0
        if ( bForcePaint || ( pPageBreakData && !( *pPageBreakData == *pNewData ) ) )
1704
0
            PaintGrid();
1705
0
    }
1706
1707
0
    pPageBreakData = std::move(pNewData);
1708
0
}
1709
1710
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */