1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <o3tl/safeint.hxx>
23 #include <o3tl/unit_conversion.hxx>
24 #include <o3tl/string_view.hxx>
25 #include <sfx2/lokhelper.hxx>
26 #include <sfx2/viewfrm.hxx>
27 #include <editeng/adjustitem.hxx>
28 #include <editeng/brushitem.hxx>
29 #include <svtools/colorcfg.hxx>
30 #include <editeng/editview.hxx>
31 #include <editeng/editstat.hxx>
32 #include <editeng/outliner.hxx>
33 #include <editeng/unolingu.hxx>
34 #include <editeng/justifyitem.hxx>
36 #include <vcl/svapp.hxx>
37 #include <rtl/math.hxx>
38 #include <sal/log.hxx>
40 #include <viewdata.hxx>
43 #include <document.hxx>
44 #include <drwlayer.hxx>
46 #include <tabview.hxx>
47 #include <tabvwsh.hxx>
48 #include <docpool.hxx>
50 #include <patattr.hxx>
51 #include <editutil.hxx>
52 #include <scextopt.hxx>
53 #include <miscuno.hxx>
54 #include <unonames.hxx>
55 #include <inputopt.hxx>
56 #include <inputhdl.hxx>
57 #include <inputwin.hxx>
58 #include <viewutil.hxx>
59 #include <markdata.hxx>
60 #include <ViewSettingsSequenceDefines.hxx>
61 #include <gridwin.hxx>
62 #include <transobj.hxx>
63 #include <clipparam.hxx>
64 #include <comphelper/flagguard.hxx>
65 #include <comphelper/lok.hxx>
66 #include <comphelper/processfactory.hxx>
67 #include <comphelper/string.hxx>
69 #include <vcl/uitest/logger.hxx>
70 #include <vcl/uitest/eventdescription.hxx>
72 #include <com/sun/star/container/XNameContainer.hpp>
73 #include <com/sun/star/document/NamedPropertyValues.hpp>
74 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
76 using namespace com::sun::star
;
78 #define SC_GROWY_SMALL_EXTRA 100
79 #define SC_GROWY_BIG_EXTRA 200
81 constexpr OUString TAG_TABBARWIDTH
= u
"tw:"_ustr
;
85 void lcl_LOKRemoveWindow(ScTabViewShell
* pTabViewShell
, ScSplitPos eWhich
)
87 if (comphelper::LibreOfficeKit::isActive())
90 [pTabViewShell
, eWhich
] (ScTabViewShell
* pOtherViewShell
)
91 { pOtherViewShell
->RemoveWindowFromForeignEditView(pTabViewShell
, eWhich
); };
93 SfxLokHelper::forEachOtherView(pTabViewShell
, lRemoveWindows
);
97 } // anonymous namespace
101 void collectUIInformation(std::map
<OUString
, OUString
>&& aParameters
, const OUString
& rAction
)
103 EventDescription aDescription
;
104 aDescription
.aID
= "grid_window";
105 aDescription
.aAction
= rAction
;
106 aDescription
.aParameters
= std::move(aParameters
);
107 aDescription
.aParent
= "MainWindow";
108 aDescription
.aKeyWord
= "ScGridWinUIObject";
110 UITestLogger::getInstance().logEvent(aDescription
);
114 const ScPositionHelper::index_type
ScPositionHelper::null
; // definition
116 bool ScPositionHelper::Comp::operator() (const value_type
& rValue1
, const value_type
& rValue2
) const
118 if (rValue1
.first
== null
|| rValue2
.first
== null
)
120 return rValue1
.second
< rValue2
.second
;
124 return rValue1
.first
< rValue2
.first
;
128 ScPositionHelper::ScPositionHelper(const ScDocument
*pDoc
, bool bColumn
)
129 : MAX_INDEX(bColumn
? (pDoc
? pDoc
->MaxCol() : -1) : MAXTILEDROW
)
131 mData
.insert(std::make_pair(-1, 0));
134 void ScPositionHelper::setDocument(const ScDocument
& rDoc
, bool bColumn
)
136 MAX_INDEX
= bColumn
? rDoc
.MaxCol() : MAXTILEDROW
;
139 void ScPositionHelper::insert(index_type nIndex
, tools::Long nPos
)
141 if (nIndex
< 0) return;
142 SAL_INFO("sc.lok.poshelper", "ScPositionHelper::insert: nIndex: "
143 << nIndex
<< ", nPos: " << nPos
<< ", size: " << mData
.size());
144 value_type aValue
= std::make_pair(nIndex
, nPos
);
146 mData
.insert(aValue
);
147 SAL_INFO("sc.lok.poshelper",
148 "ScPositionHelper::insert: after insert: size: " << mData
.size());
151 void ScPositionHelper::removeByIndex(index_type nIndex
)
155 SAL_INFO("sc.lok.poshelper", "ScPositionHelper::remove: nIndex: " << nIndex
156 << ", size: " << mData
.size());
157 auto it
= mData
.find(std::make_pair(nIndex
, 0));
158 if (it
== mData
.end()) return;
160 SAL_INFO("sc.lok.poshelper",
161 "ScPositionHelper::remove: after erase: size: " << mData
.size());
164 void ScPositionHelper::invalidateByIndex(index_type nIndex
)
166 SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nIndex: " << nIndex
);
170 mData
.insert(std::make_pair(-1, 0));
174 auto it
= mData
.lower_bound(std::make_pair(nIndex
, 0));
175 mData
.erase(it
, mData
.end());
179 void ScPositionHelper::invalidateByPosition(tools::Long nPos
)
181 SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nPos: " << nPos
);
185 mData
.insert(std::make_pair(-1, 0));
189 auto it
= mData
.lower_bound(std::make_pair(null
, nPos
));
190 mData
.erase(it
, mData
.end());
194 const ScPositionHelper::value_type
&
195 ScPositionHelper::getNearestByIndex(index_type nIndex
) const
197 SAL_INFO("sc.lok.poshelper",
198 "ScPositionHelper::getNearest: nIndex: " << nIndex
<< ", size: " << mData
.size());
199 auto posUB
= mData
.upper_bound(std::make_pair(nIndex
, 0));
200 if (posUB
== mData
.begin())
205 auto posLB
= std::prev(posUB
);
206 // coverity[copy_paste_error : FALSE] - posUB is correct
207 if (posUB
== mData
.end())
212 tools::Long nDiffUB
= posUB
->first
- nIndex
;
213 tools::Long nDiffLB
= posLB
->first
- nIndex
;
214 if (nDiffUB
< -nDiffLB
)
224 const ScPositionHelper::value_type
&
225 ScPositionHelper::getNearestByPosition(tools::Long nPos
) const
227 SAL_INFO("sc.lok.poshelper",
228 "ScPositionHelper::getNearest: nPos: " << nPos
<< ", size: " << mData
.size());
229 auto posUB
= mData
.upper_bound(std::make_pair(null
, nPos
));
231 if (posUB
== mData
.begin())
236 auto posLB
= std::prev(posUB
);
237 // coverity[copy_paste_error : FALSE] - posUB is correct
238 if (posUB
== mData
.end())
243 tools::Long nDiffUB
= posUB
->second
- nPos
;
244 tools::Long nDiffLB
= posLB
->second
- nPos
;
246 if (nDiffUB
< -nDiffLB
)
256 tools::Long
ScPositionHelper::getPosition(index_type nIndex
) const
258 auto it
= mData
.find(std::make_pair(nIndex
, 0));
259 if (it
== mData
.end()) return -1;
263 tools::Long
ScPositionHelper::computePosition(index_type nIndex
, const std::function
<long (index_type
)>& getSizePx
)
265 assert(MAX_INDEX
> 0);
266 if (nIndex
< 0) nIndex
= 0;
267 if (nIndex
> MAX_INDEX
) nIndex
= MAX_INDEX
;
269 const auto& rNearest
= getNearestByIndex(nIndex
);
270 index_type nStartIndex
= rNearest
.first
;
271 tools::Long nTotalPixels
= rNearest
.second
;
273 if (nStartIndex
< nIndex
)
275 for (index_type nIdx
= nStartIndex
+ 1; nIdx
<= nIndex
; ++nIdx
)
277 nTotalPixels
+= getSizePx(nIdx
);
282 for (index_type nIdx
= nStartIndex
; nIdx
> nIndex
; --nIdx
)
284 nTotalPixels
-= getSizePx(nIdx
);
290 ScBoundsProvider::ScBoundsProvider(const ScViewData
&rView
, SCTAB nT
, bool bColHeader
)
291 : rDoc(rView
.GetDocument())
293 , bColumnHeader(bColHeader
)
294 , MAX_INDEX(bColHeader
? rDoc
.MaxCol() : MAXTILEDROW
)
295 , mfPPTX(rView
.GetPPTX())
296 , mfPPTY(rView
.GetPPTY())
299 , nFirstPositionPx(-1)
300 , nSecondPositionPx(-1)
303 void ScBoundsProvider::GetStartIndexAndPosition(SCCOL
& nIndex
, tools::Long
& nPosition
) const
305 assert(bColumnHeader
);
306 nIndex
= nFirstIndex
;
307 nPosition
= nFirstPositionPx
;
310 void ScBoundsProvider::GetEndIndexAndPosition(SCCOL
& nIndex
, tools::Long
& nPosition
) const
312 assert(bColumnHeader
);
313 nIndex
= nSecondIndex
;
314 nPosition
= nSecondPositionPx
;
317 void ScBoundsProvider::GetStartIndexAndPosition(SCROW
& nIndex
, tools::Long
& nPosition
) const
319 assert(!bColumnHeader
);
320 nIndex
= nFirstIndex
;
321 nPosition
= nFirstPositionPx
;
324 void ScBoundsProvider::GetEndIndexAndPosition(SCROW
& nIndex
, tools::Long
& nPosition
) const
326 assert(!bColumnHeader
);
327 nIndex
= nSecondIndex
;
328 nPosition
= nSecondPositionPx
;
331 tools::Long
ScBoundsProvider::GetSize(index_type nIndex
) const
333 const sal_uInt16 nSize
= bColumnHeader
? rDoc
.GetColWidth(nIndex
, nTab
) : rDoc
.GetRowHeight(nIndex
, nTab
);
334 return ScViewData::ToPixel(nSize
, bColumnHeader
? mfPPTX
: mfPPTY
);
337 void ScBoundsProvider::GetIndexAndPos(index_type nNearestIndex
, tools::Long nNearestPosition
,
338 tools::Long nBound
, index_type
& nFoundIndex
, tools::Long
& nPosition
,
339 bool bTowards
, tools::Long nDiff
)
341 if (nDiff
> 0) // nBound < nNearestPosition
342 GeIndexBackwards(nNearestIndex
, nNearestPosition
, nBound
,
343 nFoundIndex
, nPosition
, bTowards
);
345 GetIndexTowards(nNearestIndex
, nNearestPosition
, nBound
,
346 nFoundIndex
, nPosition
, bTowards
);
349 void ScBoundsProvider::Compute(
350 value_type aFirstNearest
, value_type aSecondNearest
,
351 tools::Long nFirstBound
, tools::Long nSecondBound
)
353 SAL_INFO("sc.lok.header", "BoundsProvider: nFirstBound: " << nFirstBound
354 << ", nSecondBound: " << nSecondBound
);
356 tools::Long nFirstDiff
= aFirstNearest
.second
- nFirstBound
;
357 tools::Long nSecondDiff
= aSecondNearest
.second
- nSecondBound
;
358 SAL_INFO("sc.lok.header", "BoundsProvider: rTopNearest: index: " << aFirstNearest
.first
359 << ", pos: " << aFirstNearest
.second
<< ", diff: " << nFirstDiff
);
360 SAL_INFO("sc.lok.header", "BoundsProvider: rBottomNearest: index: " << aSecondNearest
.first
361 << ", pos: " << aSecondNearest
.second
<< ", diff: " << nSecondDiff
);
363 bool bReverse
= (std::abs(nFirstDiff
) >= std::abs(nSecondDiff
));
367 std::swap(aFirstNearest
, aSecondNearest
);
368 std::swap(nFirstBound
, nSecondBound
);
369 std::swap(nFirstDiff
, nSecondDiff
);
372 index_type nNearestIndex
= aFirstNearest
.first
;
373 tools::Long nNearestPosition
= aFirstNearest
.second
;
374 SAL_INFO("sc.lok.header", "BoundsProvider: nearest to first bound: nNearestIndex: "
375 << nNearestIndex
<< ", nNearestPosition: " << nNearestPosition
);
377 GetIndexAndPos(nNearestIndex
, nNearestPosition
, nFirstBound
,
378 nFirstIndex
, nFirstPositionPx
, !bReverse
, nFirstDiff
);
379 SAL_INFO("sc.lok.header", "BoundsProvider: nFirstIndex: " << nFirstIndex
380 << ", nFirstPositionPx: " << nFirstPositionPx
);
382 if (std::abs(nSecondDiff
) < std::abs(nSecondBound
- nFirstPositionPx
))
384 nNearestIndex
= aSecondNearest
.first
;
385 nNearestPosition
= aSecondNearest
.second
;
389 nNearestPosition
= nFirstPositionPx
;
390 nNearestIndex
= nFirstIndex
;
391 nSecondDiff
= !bReverse
? -1 : 1;
393 SAL_INFO("sc.lok.header", "BoundsProvider: nearest to second bound: nNearestIndex: "
394 << nNearestIndex
<< ", nNearestPosition: " << nNearestPosition
395 << ", diff: " << nSecondDiff
);
397 GetIndexAndPos(nNearestIndex
, nNearestPosition
, nSecondBound
,
398 nSecondIndex
, nSecondPositionPx
, bReverse
, nSecondDiff
);
399 SAL_INFO("sc.lok.header", "BoundsProvider: nSecondIndex: " << nSecondIndex
400 << ", nSecondPositionPx: " << nSecondPositionPx
);
404 std::swap(nFirstIndex
, nSecondIndex
);
405 std::swap(nFirstPositionPx
, nSecondPositionPx
);
409 void ScBoundsProvider::EnlargeStartBy(tools::Long nOffset
)
411 const index_type nNewFirstIndex
=
412 std::max(static_cast<index_type
>(-1),
413 static_cast<index_type
>(nFirstIndex
- nOffset
));
414 for (index_type nIndex
= nFirstIndex
; nIndex
> nNewFirstIndex
; --nIndex
)
416 const tools::Long nSizePx
= GetSize(nIndex
);
417 nFirstPositionPx
-= nSizePx
;
419 nFirstIndex
= nNewFirstIndex
;
420 SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nFirstIndex: " << nFirstIndex
421 << ", nFirstPositionPx: " << nFirstPositionPx
);
424 void ScBoundsProvider::EnlargeEndBy(tools::Long nOffset
)
426 const index_type nNewSecondIndex
= std::min(MAX_INDEX
, static_cast<index_type
>(nSecondIndex
+ nOffset
));
427 for (index_type nIndex
= nSecondIndex
+ 1; nIndex
<= nNewSecondIndex
; ++nIndex
)
429 const tools::Long nSizePx
= GetSize(nIndex
);
430 nSecondPositionPx
+= nSizePx
;
432 nSecondIndex
= nNewSecondIndex
;
433 SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nSecondIndex: " << nSecondIndex
434 << ", nSecondPositionPx: " << nSecondPositionPx
);
437 void ScBoundsProvider::GeIndexBackwards(
438 index_type nNearestIndex
, tools::Long nNearestPosition
,
439 tools::Long nBound
, index_type
& nFoundIndex
, tools::Long
& nPosition
, bool bTowards
)
442 for (index_type nIndex
= nNearestIndex
; nIndex
>= 0; --nIndex
)
444 if (nBound
>= nNearestPosition
)
446 nFoundIndex
= nIndex
; // last index whose nPosition is less than nBound
447 nPosition
= nNearestPosition
;
451 const tools::Long nSizePx
= GetSize(nIndex
);
452 nNearestPosition
-= nSizePx
;
454 if (!bTowards
&& nFoundIndex
!= -1)
457 nPosition
+= GetSize(nFoundIndex
);
461 void ScBoundsProvider::GetIndexTowards(
462 index_type nNearestIndex
, tools::Long nNearestPosition
,
463 tools::Long nBound
, index_type
& nFoundIndex
, tools::Long
& nPosition
, bool bTowards
)
466 for (index_type nIndex
= nNearestIndex
+ 1; nIndex
<= MAX_INDEX
; ++nIndex
)
468 const tools::Long nSizePx
= GetSize(nIndex
);
469 nNearestPosition
+= nSizePx
;
471 if (nNearestPosition
> nBound
)
473 nFoundIndex
= nIndex
; // first index whose nPosition is greater than nBound
474 nPosition
= nNearestPosition
;
478 if (nFoundIndex
== -2)
480 nFoundIndex
= MAX_INDEX
;
481 nPosition
= nNearestPosition
;
485 nPosition
-= GetSize(nFoundIndex
);
490 ScViewDataTable::ScViewDataTable(const ScDocument
*pDoc
) :
491 eZoomType( SvxZoomType::PERCENT
),
494 aPageZoomX( 3,5 ), // Page-Default: 60%
498 eHSplitMode( SC_SPLIT_NONE
),
499 eVSplitMode( SC_SPLIT_NONE
),
500 eWhichActive( SC_SPLIT_BOTTOMLEFT
),
507 aWidthHelper(pDoc
, true),
508 aHeightHelper(pDoc
, false),
512 mbOldCursorValid( false )
516 nTPosX
[0]=nTPosX
[1]=0;
517 nTPosY
[0]=nTPosY
[1]=0;
518 nMPosX
[0]=nMPosX
[1]=0;
519 nMPosY
[0]=nMPosY
[1]=0;
520 nPixPosX
[0]=nPixPosX
[1]=0;
521 nPixPosY
[0]=nPixPosY
[1]=0;
524 void ScViewDataTable::InitData(const ScDocument
& rDoc
)
526 aWidthHelper
.setDocument(rDoc
, true);
527 aHeightHelper
.setDocument(rDoc
, false);
530 void ScViewDataTable::WriteUserDataSequence(uno::Sequence
<beans::PropertyValue
>& rSettings
, const ScViewData
& rViewData
, SCTAB nTab
) const
532 rSettings
.realloc(SC_TABLE_VIEWSETTINGS_COUNT
);
533 beans::PropertyValue
* pSettings
= rSettings
.getArray();
535 ScSplitMode eExHSplitMode
= eHSplitMode
;
536 ScSplitMode eExVSplitMode
= eVSplitMode
;
537 SCCOL nExFixPosX
= nFixPosX
;
538 SCROW nExFixPosY
= nFixPosY
;
539 tools::Long nExHSplitPos
= nHSplitPos
;
540 tools::Long nExVSplitPos
= nVSplitPos
;
542 if (comphelper::LibreOfficeKit::isActive())
544 rViewData
.OverrideWithLOKFreeze(eExHSplitMode
, eExVSplitMode
,
545 nExFixPosX
, nExFixPosY
,
546 nExHSplitPos
, nExVSplitPos
, nTab
);
549 pSettings
[SC_CURSOR_X
].Name
= SC_CURSORPOSITIONX
;
550 pSettings
[SC_CURSOR_X
].Value
<<= sal_Int32(nCurX
);
551 pSettings
[SC_CURSOR_Y
].Name
= SC_CURSORPOSITIONY
;
552 pSettings
[SC_CURSOR_Y
].Value
<<= sal_Int32(nCurY
);
554 // Write freezepan data only when freeze pans are set
555 if(nExFixPosX
!= 0 || nExFixPosY
!= 0 || nExHSplitPos
!= 0 || nExVSplitPos
!= 0)
557 pSettings
[SC_HORIZONTAL_SPLIT_MODE
].Name
= SC_HORIZONTALSPLITMODE
;
558 pSettings
[SC_HORIZONTAL_SPLIT_MODE
].Value
<<= sal_Int16(eExHSplitMode
);
559 pSettings
[SC_VERTICAL_SPLIT_MODE
].Name
= SC_VERTICALSPLITMODE
;
560 pSettings
[SC_VERTICAL_SPLIT_MODE
].Value
<<= sal_Int16(eExVSplitMode
);
561 pSettings
[SC_HORIZONTAL_SPLIT_POSITION
].Name
= SC_HORIZONTALSPLITPOSITION
;
562 if (eExHSplitMode
== SC_SPLIT_FIX
)
563 pSettings
[SC_HORIZONTAL_SPLIT_POSITION
].Value
<<= sal_Int32(nExFixPosX
);
565 pSettings
[SC_HORIZONTAL_SPLIT_POSITION
].Value
<<= sal_Int32(nExHSplitPos
);
566 pSettings
[SC_VERTICAL_SPLIT_POSITION
].Name
= SC_VERTICALSPLITPOSITION
;
567 if (eExVSplitMode
== SC_SPLIT_FIX
)
568 pSettings
[SC_VERTICAL_SPLIT_POSITION
].Value
<<= sal_Int32(nExFixPosY
);
570 pSettings
[SC_VERTICAL_SPLIT_POSITION
].Value
<<= sal_Int32(nExVSplitPos
);
573 // Prevent writing odd settings that would make crash versions that
574 // don't apply SanitizeWhichActive() when reading the settings.
576 const ScSplitPos eActiveSplitRange
= SanitizeWhichActive();
577 // And point out to give us a chance to inspect weird things (if anyone
578 // remembers what s/he did).
579 assert(eWhichActive
== eActiveSplitRange
);
580 pSettings
[SC_ACTIVE_SPLIT_RANGE
].Name
= SC_ACTIVESPLITRANGE
;
581 pSettings
[SC_ACTIVE_SPLIT_RANGE
].Value
<<= sal_Int16(eActiveSplitRange
);
582 pSettings
[SC_POSITION_LEFT
].Name
= SC_POSITIONLEFT
;
583 pSettings
[SC_POSITION_LEFT
].Value
<<= sal_Int32(nPosX
[SC_SPLIT_LEFT
]);
584 pSettings
[SC_POSITION_RIGHT
].Name
= SC_POSITIONRIGHT
;
585 pSettings
[SC_POSITION_RIGHT
].Value
<<= sal_Int32(nPosX
[SC_SPLIT_RIGHT
]);
586 pSettings
[SC_POSITION_TOP
].Name
= SC_POSITIONTOP
;
587 pSettings
[SC_POSITION_TOP
].Value
<<= sal_Int32(nPosY
[SC_SPLIT_TOP
]);
588 pSettings
[SC_POSITION_BOTTOM
].Name
= SC_POSITIONBOTTOM
;
589 pSettings
[SC_POSITION_BOTTOM
].Value
<<= sal_Int32(nPosY
[SC_SPLIT_BOTTOM
]);
591 sal_Int32 nZoomValue
= tools::Long(aZoomY
* 100);
592 sal_Int32 nPageZoomValue
= tools::Long(aPageZoomY
* 100);
593 pSettings
[SC_TABLE_ZOOM_TYPE
].Name
= SC_ZOOMTYPE
;
594 pSettings
[SC_TABLE_ZOOM_TYPE
].Value
<<= sal_Int16(eZoomType
);
595 pSettings
[SC_TABLE_ZOOM_VALUE
].Name
= SC_ZOOMVALUE
;
596 pSettings
[SC_TABLE_ZOOM_VALUE
].Value
<<= nZoomValue
;
597 pSettings
[SC_TABLE_PAGE_VIEW_ZOOM_VALUE
].Name
= SC_PAGEVIEWZOOMVALUE
;
598 pSettings
[SC_TABLE_PAGE_VIEW_ZOOM_VALUE
].Value
<<= nPageZoomValue
;
600 pSettings
[SC_TABLE_SHOWGRID
].Name
= SC_UNO_SHOWGRID
;
601 pSettings
[SC_TABLE_SHOWGRID
].Value
<<= bShowGrid
;
603 // Common SdrModel processing
604 rViewData
.GetDocument().GetDrawLayer()->WriteUserDataSequence(rSettings
);
607 void ScViewDataTable::ReadUserDataSequence(const uno::Sequence
<beans::PropertyValue
>& aSettings
, ScViewData
& rViewData
, SCTAB nTab
, bool& rHasZoom
)
611 sal_Int32
nTemp32(0);
612 sal_Int16
nTemp16(0);
613 sal_Int32
nTempPosV(0);
614 sal_Int32
nTempPosH(0);
615 sal_Int32
nTempPosVTw(0);
616 sal_Int32
nTempPosHTw(0);
617 bool bHasVSplitInTwips
= false;
618 bool bHasHSplitInTwips
= false;
619 for (const auto& rSetting
: aSettings
)
621 OUString
sName(rSetting
.Name
);
622 if (sName
== SC_CURSORPOSITIONX
)
624 rSetting
.Value
>>= nTemp32
;
625 nCurX
= rViewData
.GetDocument().SanitizeCol( static_cast<SCCOL
>(nTemp32
));
627 else if (sName
== SC_CURSORPOSITIONY
)
629 rSetting
.Value
>>= nTemp32
;
630 nCurY
= rViewData
.GetDocument().SanitizeRow( static_cast<SCROW
>(nTemp32
));
632 else if (sName
== SC_HORIZONTALSPLITMODE
)
634 if ((rSetting
.Value
>>= nTemp16
) && nTemp16
<= ScSplitMode::SC_SPLIT_MODE_MAX_ENUM
)
635 eHSplitMode
= static_cast<ScSplitMode
>(nTemp16
);
637 else if (sName
== SC_VERTICALSPLITMODE
)
639 if ((rSetting
.Value
>>= nTemp16
) && nTemp16
<= ScSplitMode::SC_SPLIT_MODE_MAX_ENUM
)
640 eVSplitMode
= static_cast<ScSplitMode
>(nTemp16
);
642 else if (sName
== SC_HORIZONTALSPLITPOSITION
)
644 rSetting
.Value
>>= nTempPosH
;
645 bHasHSplitInTwips
= false;
647 else if (sName
== SC_VERTICALSPLITPOSITION
)
649 rSetting
.Value
>>= nTempPosV
;
650 bHasVSplitInTwips
= false;
652 else if (sName
== SC_HORIZONTALSPLITPOSITION_TWIPS
)
654 rSetting
.Value
>>= nTempPosHTw
;
655 bHasHSplitInTwips
= true;
657 else if (sName
== SC_VERTICALSPLITPOSITION_TWIPS
)
659 rSetting
.Value
>>= nTempPosVTw
;
660 bHasVSplitInTwips
= true;
662 else if (sName
== SC_ACTIVESPLITRANGE
)
664 if ((rSetting
.Value
>>= nTemp16
) && nTemp16
<= ScSplitPos::SC_SPLIT_POS_MAX_ENUM
)
665 eWhichActive
= static_cast<ScSplitPos
>(nTemp16
);
667 else if (sName
== SC_POSITIONLEFT
)
669 rSetting
.Value
>>= nTemp32
;
670 nPosX
[SC_SPLIT_LEFT
] = rViewData
.GetDocument().SanitizeCol( static_cast<SCCOL
>(nTemp32
));
672 else if (sName
== SC_POSITIONRIGHT
)
674 rSetting
.Value
>>= nTemp32
;
675 nPosX
[SC_SPLIT_RIGHT
] = rViewData
.GetDocument().SanitizeCol( static_cast<SCCOL
>(nTemp32
));
677 else if (sName
== SC_POSITIONTOP
)
679 rSetting
.Value
>>= nTemp32
;
680 nPosY
[SC_SPLIT_TOP
] = rViewData
.GetDocument().SanitizeRow( static_cast<SCROW
>(nTemp32
));
682 else if (sName
== SC_POSITIONBOTTOM
)
684 rSetting
.Value
>>= nTemp32
;
685 nPosY
[SC_SPLIT_BOTTOM
] = rViewData
.GetDocument().SanitizeRow( static_cast<SCROW
>(nTemp32
));
687 else if (sName
== SC_ZOOMTYPE
)
689 rSetting
.Value
>>= nTemp16
;
690 eZoomType
= SvxZoomType(nTemp16
);
691 rHasZoom
= true; // set if there is any zoom information
693 else if (sName
== SC_ZOOMVALUE
)
695 rSetting
.Value
>>= nTemp32
;
696 Fraction
aZoom(nTemp32
, 100);
697 aZoomX
= aZoomY
= aZoom
;
700 else if (sName
== SC_PAGEVIEWZOOMVALUE
)
702 rSetting
.Value
>>= nTemp32
;
703 Fraction
aZoom(nTemp32
, 100);
704 aPageZoomX
= aPageZoomY
= aZoom
;
707 else if (sName
== SC_UNO_SHOWGRID
)
709 rSetting
.Value
>>= bShowGrid
;
711 else if (sName
== SC_TABLESELECTED
)
713 bool bSelected
= false;
714 rSetting
.Value
>>= bSelected
;
715 rViewData
.GetMarkData().SelectTable( nTab
, bSelected
);
717 else if (sName
== SC_UNONAME_TABCOLOR
)
719 // There are documents out there that have their tab color defined as a view setting.
720 Color aColor
= COL_AUTO
;
721 rSetting
.Value
>>= aColor
;
722 if (aColor
!= COL_AUTO
)
724 ScDocument
& rDoc
= rViewData
.GetDocument();
725 rDoc
.SetTabBgColor(nTab
, aColor
);
728 // Fallback to common SdrModel processing
729 else rViewData
.GetDocument().GetDrawLayer()->ReadUserDataSequenceValue(&rSetting
);
732 if (eHSplitMode
== SC_SPLIT_FIX
)
733 nFixPosX
= rViewData
.GetDocument().SanitizeCol( static_cast<SCCOL
>( bHasHSplitInTwips
? nTempPosHTw
: nTempPosH
));
735 nHSplitPos
= bHasHSplitInTwips
? static_cast< tools::Long
>( nTempPosHTw
* rViewData
.GetPPTX() ) : nTempPosH
;
737 if (eVSplitMode
== SC_SPLIT_FIX
)
738 nFixPosY
= rViewData
.GetDocument().SanitizeRow( static_cast<SCROW
>( bHasVSplitInTwips
? nTempPosVTw
: nTempPosV
));
740 nVSplitPos
= bHasVSplitInTwips
? static_cast< tools::Long
>( nTempPosVTw
* rViewData
.GetPPTY() ) : nTempPosV
;
742 eWhichActive
= SanitizeWhichActive();
745 ScSplitPos
ScViewDataTable::SanitizeWhichActive() const
747 if ((WhichH(eWhichActive
) == SC_SPLIT_RIGHT
&& eHSplitMode
== SC_SPLIT_NONE
) ||
748 (WhichV(eWhichActive
) == SC_SPLIT_TOP
&& eVSplitMode
== SC_SPLIT_NONE
))
750 SAL_WARN("sc.ui","ScViewDataTable::SanitizeWhichActive - bad eWhichActive " << eWhichActive
);
751 // The default always initialized grid window is SC_SPLIT_BOTTOMLEFT.
752 return SC_SPLIT_BOTTOMLEFT
;
757 ScViewData::ScViewData(ScDocShell
& rDocSh
, ScTabViewShell
* pViewSh
)
758 : ScViewData(nullptr, &rDocSh
, pViewSh
)
762 ScViewData::ScViewData(ScDocument
& rDoc
)
763 : ScViewData(&rDoc
, nullptr, nullptr)
767 static ScViewOptions
DefaultOptions()
769 ScViewOptions aOptions
;
770 aOptions
.SetOption(VOPT_GRID
, true);
771 aOptions
.SetOption(VOPT_SYNTAX
, false);
772 aOptions
.SetOption(VOPT_HEADER
, true);
773 aOptions
.SetOption(VOPT_TABCONTROLS
, true);
774 aOptions
.SetOption(VOPT_VSCROLL
, true);
775 aOptions
.SetOption(VOPT_HSCROLL
, true);
776 aOptions
.SetOption(VOPT_OUTLINER
, true);
780 // Either pDoc or pDocSh must be valid
781 ScViewData::ScViewData(ScDocument
* pDoc
, ScDocShell
* pDocSh
, ScTabViewShell
* pViewSh
) :
784 maMarkData (pDocSh
? pDocSh
->GetDocument().GetSheetLimits() : pDoc
->GetSheetLimits()),
785 maHighlightData (pDocSh
? pDocSh
->GetDocument().GetSheetLimits() : pDoc
->GetSheetLimits()),
786 pDocShell ( pDocSh
),
787 mrDoc (pDocSh
? pDocSh
->GetDocument() : *pDoc
),
789 maOptions (pDocSh
? pDocSh
->GetDocument().GetViewOptions() : DefaultOptions()),
790 pSpellingView ( nullptr ),
791 aLogicMode ( MapUnit::Map100thMM
),
792 eDefZoomType( SvxZoomType::PERCENT
),
795 aDefPageZoomX( 3,5 ),
796 aDefPageZoomY( 3,5 ),
797 eRefType ( SC_REFTYPE_NONE
),
810 nPasteFlags ( ScPasteFlags::NONE
),
811 eEditActivePart( SC_SPLIT_BOTTOMLEFT
),
812 nFillMode ( ScFillMode::NONE
),
813 eEditAdjust ( SvxAdjust::Left
),
814 bActive ( true ), // how to initialize?
815 bIsRefMode ( false ),
816 bDelMarkValid( false ),
817 bPagebreak ( false ),
818 bSelCtrlMouseClick( false ),
820 bEditHighlight ( false ),
823 m_nLOKPageUpDownOffset( 0 )
825 assert(bool(pDoc
) != bool(pDocSh
)); // either one or the other, not both
826 maMarkData
.SelectOneTable(0); // Sync with nTabNo
828 aScrSize
= Size( o3tl::convert(STD_COL_WIDTH
* OLE_STD_CELLS_X
, o3tl::Length::twip
, o3tl::Length::px
),
829 o3tl::convert(mrDoc
.GetSheetOptimalMinRowHeight(nTabNo
) * OLE_STD_CELLS_Y
,
830 o3tl::Length::twip
, o3tl::Length::px
));
831 maTabData
.emplace_back( new ScViewDataTable(nullptr) );
832 pThisTab
= maTabData
[nTabNo
].get();
834 nEditEndCol
= nEditStartCol
= nEditCol
= 0;
835 nEditEndRow
= nEditRow
= 0;
836 nTabStartCol
= SC_TABSTART_NONE
;
838 // don't show hidden tables
839 if (!mrDoc
.IsVisible(nTabNo
))
841 while (!mrDoc
.IsVisible(nTabNo
) && mrDoc
.HasTable(nTabNo
+ 1))
844 maTabData
.emplace_back(nullptr);
846 maTabData
[nTabNo
].reset( new ScViewDataTable(nullptr) );
847 pThisTab
= maTabData
[nTabNo
].get();
850 SCTAB nTableCount
= mrDoc
.GetTableCount();
851 EnsureTabDataSize(nTableCount
);
853 for (auto& xTabData
: maTabData
)
856 xTabData
->InitData(mrDoc
);
862 ScViewData::~ScViewData() COVERITY_NOEXCEPT_FALSE
867 ScDBFunc
* ScViewData::GetView() const { return pView
; }
869 void ScViewData::UpdateCurrentTab()
871 assert(0 <= nTabNo
&& o3tl::make_unsigned(nTabNo
) < maTabData
.size());
872 pThisTab
= maTabData
[nTabNo
].get();
876 pThisTab
= maTabData
[--nTabNo
].get();
879 maTabData
[0].reset(new ScViewDataTable(&mrDoc
));
880 pThisTab
= maTabData
[0].get();
885 void ScViewData::InsertTab( SCTAB nTab
)
887 if( nTab
>= static_cast<SCTAB
>(maTabData
.size()))
888 maTabData
.resize(nTab
+1);
890 maTabData
.insert( maTabData
.begin() + nTab
, nullptr );
891 CreateTabData( nTab
);
894 maMarkData
.InsertTab(nTab
);
896 collectUIInformation({{}}, u
"InsertTab"_ustr
);
899 void ScViewData::InsertTabs( SCTAB nTab
, SCTAB nNewSheets
)
901 if (nTab
>= static_cast<SCTAB
>(maTabData
.size()))
902 maTabData
.resize(nTab
+nNewSheets
);
905 // insert nNewSheets new tables at position nTab
906 auto prevSize
= maTabData
.size();
907 maTabData
.resize(prevSize
+ nNewSheets
);
908 std::move_backward(maTabData
.begin() + nTab
, maTabData
.begin() + prevSize
, maTabData
.end());
910 for (SCTAB i
= nTab
; i
< nTab
+ nNewSheets
; ++i
)
913 maMarkData
.InsertTab(i
);
918 void ScViewData::DeleteTab( SCTAB nTab
)
920 assert(nTab
< static_cast<SCTAB
>(maTabData
.size()));
921 maTabData
.erase(maTabData
.begin() + nTab
);
923 if (o3tl::make_unsigned(nTabNo
) >= maTabData
.size())
925 EnsureTabDataSize(1);
926 nTabNo
= maTabData
.size() - 1;
929 maMarkData
.DeleteTab(nTab
);
932 void ScViewData::DeleteTabs( SCTAB nTab
, SCTAB nSheets
)
934 for (SCTAB i
= 0; i
< nSheets
; ++i
)
936 maMarkData
.DeleteTab(nTab
+ i
);
938 maTabData
.erase(maTabData
.begin() + nTab
, maTabData
.begin()+ nTab
+nSheets
);
939 if (o3tl::make_unsigned(nTabNo
) >= maTabData
.size())
941 EnsureTabDataSize(1);
942 nTabNo
= maTabData
.size() - 1;
947 void ScViewData::CopyTab( SCTAB nSrcTab
, SCTAB nDestTab
)
949 if (nDestTab
==SC_TAB_APPEND
)
950 nDestTab
= mrDoc
.GetTableCount() - 1; // something had to have been copied
952 if (nDestTab
> MAXTAB
)
954 OSL_FAIL("too many sheets");
958 if (nSrcTab
>= static_cast<SCTAB
>(maTabData
.size()))
959 OSL_FAIL("pTabData out of bounds, FIX IT");
961 EnsureTabDataSize(nDestTab
+ 1);
963 if ( maTabData
[nSrcTab
] )
964 maTabData
.emplace(maTabData
.begin() + nDestTab
, new ScViewDataTable( *maTabData
[nSrcTab
] ));
966 maTabData
.insert(maTabData
.begin() + nDestTab
, nullptr);
969 maMarkData
.InsertTab(nDestTab
);
972 void ScViewData::MoveTab( SCTAB nSrcTab
, SCTAB nDestTab
)
974 if (nDestTab
==SC_TAB_APPEND
)
975 nDestTab
= mrDoc
.GetTableCount() - 1;
976 std::unique_ptr
<ScViewDataTable
> pTab
;
977 if (nSrcTab
< static_cast<SCTAB
>(maTabData
.size()))
979 pTab
= std::move(maTabData
[nSrcTab
]);
980 maTabData
.erase( maTabData
.begin() + nSrcTab
);
983 if (nDestTab
< static_cast<SCTAB
>(maTabData
.size()))
984 maTabData
.insert( maTabData
.begin() + nDestTab
, std::move(pTab
) );
987 EnsureTabDataSize(nDestTab
+ 1);
988 maTabData
[nDestTab
] = std::move(pTab
);
992 maMarkData
.DeleteTab(nSrcTab
);
993 maMarkData
.InsertTab(nDestTab
); // adapted if needed
996 void ScViewData::CreateTabData( std::vector
< SCTAB
>& rvTabs
)
998 for ( const auto& rTab
: rvTabs
)
1002 void ScViewData::SetZoomType( SvxZoomType eNew
, std::vector
< SCTAB
>& tabs
)
1004 bool bAll
= tabs
.empty();
1006 if ( !bAll
) // create associated table data
1007 CreateTabData( tabs
);
1011 for ( auto & i
: maTabData
)
1014 i
->eZoomType
= eNew
;
1016 eDefZoomType
= eNew
;
1020 for ( const SCTAB
& i
: tabs
)
1022 if ( i
< static_cast<SCTAB
>(maTabData
.size()) && maTabData
[i
] )
1023 maTabData
[i
]->eZoomType
= eNew
;
1028 void ScViewData::SetZoomType( SvxZoomType eNew
, bool bAll
)
1030 std::vector
< SCTAB
> vTabs
; // Empty for all tabs
1031 if ( !bAll
) // get selected tabs
1033 ScMarkData::const_iterator itr
= maMarkData
.begin(), itrEnd
= maMarkData
.end();
1034 vTabs
.insert(vTabs
.begin(), itr
, itrEnd
);
1036 SetZoomType( eNew
, vTabs
);
1039 void ScViewData::SetZoom( const Fraction
& rNewX
, const Fraction
& rNewY
, std::vector
< SCTAB
>& tabs
)
1041 bool bAll
= tabs
.empty();
1042 if ( !bAll
) // create associated table data
1043 CreateTabData( tabs
);
1045 // sanity check - we shouldn't need something this low / big
1046 SAL_WARN_IF(rNewX
< Fraction(1, 100) || rNewX
> Fraction(100, 1), "sc.viewdata",
1047 "fraction rNewX not sensible: " << static_cast<double>(rNewX
));
1048 SAL_WARN_IF(rNewY
< Fraction(1, 100) || rNewY
> Fraction(100, 1), "sc.viewdata",
1049 "fraction rNewY not sensible: " << static_cast<double>(rNewY
));
1053 for ( auto & i
: maTabData
)
1059 i
->aPageZoomX
= rNewX
;
1060 i
->aPageZoomY
= rNewY
;
1071 aDefPageZoomX
= rNewX
;
1072 aDefPageZoomY
= rNewY
;
1082 for ( const SCTAB
& i
: tabs
)
1084 if ( i
< static_cast<SCTAB
>(maTabData
.size()) && maTabData
[i
] )
1088 maTabData
[i
]->aPageZoomX
= rNewX
;
1089 maTabData
[i
]->aPageZoomY
= rNewY
;
1093 maTabData
[i
]->aZoomX
= rNewX
;
1094 maTabData
[i
]->aZoomY
= rNewY
;
1102 void ScViewData::SetZoom( const Fraction
& rNewX
, const Fraction
& rNewY
, bool bAll
)
1104 std::vector
< SCTAB
> vTabs
;
1105 if ( !bAll
) // get selected tabs
1107 ScMarkData::const_iterator itr
= maMarkData
.begin(), itrEnd
= maMarkData
.end();
1108 vTabs
.insert(vTabs
.begin(), itr
, itrEnd
);
1110 SetZoom( rNewX
, rNewY
, vTabs
);
1113 void ScViewData::SetShowGrid( bool bShow
)
1115 CreateSelectedTabData();
1116 maTabData
[nTabNo
]->bShowGrid
= bShow
;
1119 void ScViewData::RefreshZoom()
1121 // recalculate zoom-dependent values (only for current sheet)
1125 aScenButSize
= Size(0,0);
1126 aLogicMode
.SetScaleX( GetZoomX() );
1127 aLogicMode
.SetScaleY( GetZoomY() );
1130 void ScViewData::SetPagebreakMode( bool bSet
)
1137 ScMarkType
ScViewData::GetSimpleArea( ScRange
& rRange
, ScMarkData
& rNewMark
) const
1139 ScMarkType eMarkType
= SC_MARK_NONE
;
1141 if ( rNewMark
.IsMarked() || rNewMark
.IsMultiMarked() )
1143 if ( rNewMark
.IsMultiMarked() )
1144 rNewMark
.MarkToSimple();
1146 if ( rNewMark
.IsMarked() && !rNewMark
.IsMultiMarked() )
1148 rRange
= rNewMark
.GetMarkArea();
1149 if (ScViewUtil::HasFiltered(rRange
, GetDocument()))
1150 eMarkType
= SC_MARK_SIMPLE_FILTERED
;
1152 eMarkType
= SC_MARK_SIMPLE
;
1155 eMarkType
= SC_MARK_MULTI
;
1157 if (eMarkType
!= SC_MARK_SIMPLE
&& eMarkType
!= SC_MARK_SIMPLE_FILTERED
)
1159 if (eMarkType
== SC_MARK_NONE
)
1160 eMarkType
= SC_MARK_SIMPLE
;
1161 const ScPatternAttr
* pMarkPattern
= mrDoc
.GetPattern(GetCurX(), GetCurY(), GetTabNo());
1162 const ScMergeAttr
* pMergeItem
= nullptr;
1163 if (pMarkPattern
&& pMarkPattern
->GetItemSet().GetItemState(ATTR_MERGE
, false, &pMergeItem
) == SfxItemState::SET
)
1165 SCROW nRow
= pMergeItem
->GetRowMerge();
1166 SCCOL nCol
= pMergeItem
->GetColMerge();
1167 if ( nRow
< 1 || nCol
< 1 )
1169 // This kind of cells do exist. Not sure if that is intended or a bug.
1170 rRange
= ScRange(GetCurX(), GetCurY(), GetTabNo());
1174 rRange
= ScRange(GetCurX(), GetCurY(), GetTabNo(),
1175 GetCurX() + nCol
- 1, GetCurY() + nRow
- 1, GetTabNo());
1176 if ( ScViewUtil::HasFiltered(rRange
, GetDocument()) )
1177 eMarkType
= SC_MARK_SIMPLE_FILTERED
;
1181 rRange
= ScRange(GetCurX(), GetCurY(), GetTabNo());
1186 ScMarkType
ScViewData::GetSimpleArea( SCCOL
& rStartCol
, SCROW
& rStartRow
, SCTAB
& rStartTab
,
1187 SCCOL
& rEndCol
, SCROW
& rEndRow
, SCTAB
& rEndTab
) const
1189 // parameter bMergeMark is no longer needed: The view's selection is never modified
1190 // (a local copy is used), and a multi selection that adds to a single range can always
1191 // be treated like a single selection (GetSimpleArea isn't used in selection
1195 ScMarkData
aNewMark(maMarkData
); // use a local copy for MarkToSimple
1196 ScMarkType eMarkType
= GetSimpleArea( aRange
, aNewMark
);
1197 aRange
.GetVars( rStartCol
, rStartRow
, rStartTab
, rEndCol
, rEndRow
, rEndTab
);
1201 ScMarkType
ScViewData::GetSimpleArea( ScRange
& rRange
) const
1203 // parameter bMergeMark is no longer needed, see above
1205 ScMarkData
aNewMark(maMarkData
); // use a local copy for MarkToSimple
1206 return GetSimpleArea( rRange
, aNewMark
);
1209 void ScViewData::GetMultiArea( ScRangeListRef
& rRange
) const
1211 // parameter bMergeMark is no longer needed, see GetSimpleArea
1213 ScMarkData
aNewMark(maMarkData
); // use a local copy for MarkToSimple
1215 bool bMulti
= aNewMark
.IsMultiMarked();
1218 aNewMark
.MarkToSimple();
1219 bMulti
= aNewMark
.IsMultiMarked();
1223 rRange
= new ScRangeList
;
1224 aNewMark
.FillRangeListWithMarks( rRange
.get(), false );
1229 GetSimpleArea(aSimple
);
1230 rRange
= new ScRangeList(aSimple
);
1234 bool ScViewData::SimpleColMarked()
1242 if (GetSimpleArea(nStartCol
,nStartRow
,nStartTab
,nEndCol
,nEndRow
,nEndTab
) == SC_MARK_SIMPLE
)
1243 if (nStartRow
== 0 && nEndRow
== mrDoc
.MaxRow())
1249 bool ScViewData::SimpleRowMarked()
1257 if (GetSimpleArea(nStartCol
,nStartRow
,nStartTab
,nEndCol
,nEndRow
,nEndTab
) == SC_MARK_SIMPLE
)
1258 if (nStartCol
== 0 && nEndCol
== mrDoc
.MaxCol())
1264 bool ScViewData::IsMultiMarked() const
1266 // Test for "real" multi selection, calling MarkToSimple on a local copy,
1267 // and taking filtered in simple area marks into account.
1270 ScMarkType eType
= GetSimpleArea(aDummy
);
1271 return (eType
& SC_MARK_SIMPLE
) != SC_MARK_SIMPLE
;
1274 bool ScViewData::SelectionForbidsPaste( ScDocument
* pClipDoc
)
1278 // Same as checkDestRanges() in sc/source/ui/view/cellsh.cxx but
1279 // different return details.
1281 vcl::Window
* pWin
= GetActiveWin();
1283 // No window doesn't mean paste would be forbidden.
1286 const ScTransferObj
* pOwnClip
= ScTransferObj::GetOwnClipboard(ScTabViewShell::GetClipData(pWin
));
1288 // Foreign content does not get repeatedly replicated.
1291 pClipDoc
= pOwnClip
->GetDocument();
1293 // No clipdoc doesn't mean paste would be forbidden.
1297 const ScRange aSrcRange
= pClipDoc
->GetClipParam().getWholeRange();
1298 const SCROW nRowSize
= aSrcRange
.aEnd
.Row() - aSrcRange
.aStart
.Row() + 1;
1299 const SCCOL nColSize
= aSrcRange
.aEnd
.Col() - aSrcRange
.aStart
.Col() + 1;
1301 return SelectionForbidsPaste( nColSize
, nRowSize
);
1304 bool ScViewData::SelectionForbidsPaste( SCCOL nSrcCols
, SCROW nSrcRows
)
1306 ScRange
aSelRange( ScAddress::UNINITIALIZED
);
1307 ScMarkType eMarkType
= GetSimpleArea( aSelRange
);
1309 if (eMarkType
== SC_MARK_MULTI
)
1310 // Not because of DOOM.
1313 if (aSelRange
.aEnd
.Row() - aSelRange
.aStart
.Row() + 1 == nSrcRows
)
1314 // This also covers entire col(s) copied to be pasted on entire cols.
1317 if (aSelRange
.aEnd
.Col() - aSelRange
.aStart
.Col() + 1 == nSrcCols
)
1318 // This also covers entire row(s) copied to be pasted on entire rows.
1321 return SelectionFillDOOM( aSelRange
);
1324 bool ScViewData::SelectionForbidsCellFill()
1326 ScRange
aSelRange( ScAddress::UNINITIALIZED
);
1327 ScMarkType eMarkType
= GetSimpleArea( aSelRange
);
1328 return eMarkType
!= SC_MARK_MULTI
&& SelectionFillDOOM( aSelRange
);
1332 bool ScViewData::SelectionFillDOOM( const ScRange
& rRange
)
1334 // Assume that more than 23 full columns (23M cells) will not be
1335 // successful... Even with only 10 bytes per cell that would already be
1336 // 230MB, formula cells would be 100 bytes and more per cell.
1337 // rows * columns > 23m => rows > 23m / columns
1338 // to not overflow in case number of available columns or rows would be
1339 // arbitrarily increased.
1340 // We could refine this and take some actual cell size into account,
1341 // evaluate available memory and what not, but...
1342 const sal_Int32 kMax
= 23 * 1024 * 1024; // current MAXROWCOUNT1 is 1024*1024=1048576
1343 return (rRange
.aEnd
.Row() - rRange
.aStart
.Row() + 1) > (kMax
/ (rRange
.aEnd
.Col() - rRange
.aStart
.Col() + 1));
1346 void ScViewData::SetFillMode( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
)
1348 nFillMode
= ScFillMode::FILL
;
1349 nFillStartX
= nStartCol
;
1350 nFillStartY
= nStartRow
;
1351 nFillEndX
= nEndCol
;
1352 nFillEndY
= nEndRow
;
1355 void ScViewData::SetDragMode( SCCOL nStartCol
, SCROW nStartRow
, SCCOL nEndCol
, SCROW nEndRow
,
1359 nFillStartX
= nStartCol
;
1360 nFillStartY
= nStartRow
;
1361 nFillEndX
= nEndCol
;
1362 nFillEndY
= nEndRow
;
1365 void ScViewData::ResetFillMode()
1367 nFillMode
= ScFillMode::NONE
;
1370 void ScViewData::GetFillData( SCCOL
& rStartCol
, SCROW
& rStartRow
,
1371 SCCOL
& rEndCol
, SCROW
& rEndRow
)
1373 rStartCol
= nFillStartX
;
1374 rStartRow
= nFillStartY
;
1375 rEndCol
= nFillEndX
;
1376 rEndRow
= nFillEndY
;
1379 SCCOL
ScViewData::GetOldCurX() const
1381 if (pThisTab
->mbOldCursorValid
)
1382 return pThisTab
->nOldCurX
;
1384 return pThisTab
->nCurX
;
1387 SCROW
ScViewData::GetOldCurY() const
1389 if (pThisTab
->mbOldCursorValid
)
1390 return pThisTab
->nOldCurY
;
1392 return pThisTab
->nCurY
;
1395 void ScViewData::SetOldCursor( SCCOL nNewX
, SCROW nNewY
)
1397 pThisTab
->nOldCurX
= nNewX
;
1398 pThisTab
->nOldCurY
= nNewY
;
1399 pThisTab
->mbOldCursorValid
= true;
1402 void ScViewData::ResetOldCursor()
1404 pThisTab
->mbOldCursorValid
= false;
1407 SCCOL
ScViewData::GetPosX( ScHSplitPos eWhich
, SCTAB nForTab
) const
1409 if (comphelper::LibreOfficeKit::isActive())
1413 return pThisTab
->nPosX
[eWhich
];
1415 if (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size())))
1418 return maTabData
[nForTab
]->nPosX
[eWhich
];
1421 SCROW
ScViewData::GetPosY( ScVSplitPos eWhich
, SCTAB nForTab
) const
1423 if (comphelper::LibreOfficeKit::isActive())
1427 return pThisTab
->nPosY
[eWhich
];
1429 if (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size())))
1432 return maTabData
[nForTab
]->nPosY
[eWhich
];
1435 ScViewDataTable
* ScViewData::FetchTableData(SCTAB nTabIndex
) const
1437 if (!ValidTab(nTabIndex
) || (nTabIndex
>= static_cast<SCTAB
>(maTabData
.size())))
1439 ScViewDataTable
* pRet
= maTabData
[nTabIndex
].get();
1440 SAL_WARN_IF(!pRet
, "sc.viewdata", "ScViewData::FetchTableData: hidden sheet = " << nTabIndex
);
1444 SCCOL
ScViewData::GetCurXForTab( SCTAB nTabIndex
) const
1446 ScViewDataTable
* pTabData
= FetchTableData(nTabIndex
);
1447 return pTabData
? pTabData
->nCurX
: -1;
1450 SCROW
ScViewData::GetCurYForTab( SCTAB nTabIndex
) const
1452 ScViewDataTable
* pTabData
= FetchTableData(nTabIndex
);
1453 return pTabData
? pTabData
->nCurY
: -1;
1456 void ScViewData::SetCurXForTab( SCCOL nNewCurX
, SCTAB nTabIndex
)
1458 if (ScViewDataTable
* pTabData
= FetchTableData(nTabIndex
))
1459 pTabData
->nCurX
= nNewCurX
;
1462 void ScViewData::SetCurYForTab( SCCOL nNewCurY
, SCTAB nTabIndex
)
1464 if (ScViewDataTable
* pTabData
= FetchTableData(nTabIndex
))
1465 pTabData
->nCurY
= nNewCurY
;
1468 void ScViewData::SetMaxTiledCol( SCCOL nNewMaxCol
)
1470 nNewMaxCol
= std::clamp(nNewMaxCol
, SCCOL(0), mrDoc
.MaxCol());
1472 const SCTAB nTab
= GetTabNo();
1473 auto GetColWidthPx
= [this, nTab
](SCCOL nCol
) {
1474 const sal_uInt16 nSize
= this->mrDoc
.GetColWidth(nCol
, nTab
);
1475 const tools::Long nSizePx
= ScViewData::ToPixel(nSize
, nPPTX
);
1479 tools::Long nTotalPixels
= GetLOKWidthHelper().computePosition(nNewMaxCol
, GetColWidthPx
);
1481 SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledCol: nNewMaxCol: "
1482 << nNewMaxCol
<< ", nTotalPixels: " << nTotalPixels
);
1484 GetLOKWidthHelper().removeByIndex(pThisTab
->nMaxTiledCol
);
1485 GetLOKWidthHelper().insert(nNewMaxCol
, nTotalPixels
);
1487 pThisTab
->nMaxTiledCol
= nNewMaxCol
;
1490 void ScViewData::SetMaxTiledRow( SCROW nNewMaxRow
)
1494 if (nNewMaxRow
> MAXTILEDROW
)
1495 nNewMaxRow
= MAXTILEDROW
;
1497 const SCTAB nTab
= GetTabNo();
1498 auto GetRowHeightPx
= [this, nTab
](SCROW nRow
) {
1499 const sal_uInt16 nSize
= this->mrDoc
.GetRowHeight(nRow
, nTab
);
1500 const tools::Long nSizePx
= ScViewData::ToPixel(nSize
, nPPTY
);
1504 tools::Long nTotalPixels
= GetLOKHeightHelper().computePosition(nNewMaxRow
, GetRowHeightPx
);
1506 SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledRow: nNewMaxRow: "
1507 << nNewMaxRow
<< ", nTotalPixels: " << nTotalPixels
);
1509 GetLOKHeightHelper().removeByIndex(pThisTab
->nMaxTiledRow
);
1510 GetLOKHeightHelper().insert(nNewMaxRow
, nTotalPixels
);
1512 pThisTab
->nMaxTiledRow
= nNewMaxRow
;
1515 tools::Rectangle
ScViewData::GetEditArea( ScSplitPos eWhich
, SCCOL nPosX
, SCROW nPosY
,
1516 vcl::Window
* pWin
, const ScPatternAttr
* pPattern
,
1517 bool bForceToTop
, bool bInPrintTwips
)
1519 Point aCellTopLeft
= bInPrintTwips
?
1520 GetPrintTwipsPos(nPosX
, nPosY
) : GetScrPos(nPosX
, nPosY
, eWhich
, true);
1521 return ScEditUtil(&mrDoc
, nPosX
, nPosY
, nTabNo
, aCellTopLeft
,
1522 pWin
->GetOutDev(), nPPTX
, nPPTY
, GetZoomX(), GetZoomY(), bInPrintTwips
).
1523 GetEditArea( pPattern
, bForceToTop
);
1528 void notifyCellCursorAt(const ScTabViewShell
* pViewShell
, SCCOL nCol
, SCROW nRow
,
1529 const tools::Rectangle
& rCursor
)
1531 std::stringstream ss
;
1532 ss
<< rCursor
.getX() << ", " << rCursor
.getY() << ", " << rCursor
.GetWidth() << ", "
1533 << rCursor
.GetHeight() << ", " << nCol
<< ", " << nRow
;
1535 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_CURSOR
, ss
.str().c_str());
1536 SfxLokHelper::notifyOtherViews(pViewShell
, LOK_CALLBACK_CELL_VIEW_CURSOR
, "rectangle",
1542 void ScViewData::SetEditEngine( ScSplitPos eWhich
,
1543 ScEditEngineDefaulter
* pNewEngine
,
1544 vcl::Window
* pWin
, SCCOL nNewX
, SCROW nNewY
)
1546 bool bLayoutRTL
= mrDoc
.IsLayoutRTL(nTabNo
);
1547 ScHSplitPos eHWhich
= WhichH(eWhich
);
1548 ScVSplitPos eVWhich
= WhichV(eWhich
);
1549 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
1550 bool bLOKPrintTwips
= bLOKActive
&& comphelper::LibreOfficeKit::isCompatFlagSet(
1551 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
1552 bool bLOKLayoutRTL
= bLOKActive
&& bLayoutRTL
;
1554 bool bWasThere
= false;
1555 if (pEditView
[eWhich
])
1557 // if the view is already there don't call anything that changes the cursor position
1558 if (bEditActive
[eWhich
])
1564 lcl_LOKRemoveWindow(GetViewShell(), eWhich
);
1565 pEditView
[eWhich
]->setEditEngine(pNewEngine
);
1568 if (pEditView
[eWhich
]->GetWindow() != pWin
)
1570 lcl_LOKRemoveWindow(GetViewShell(), eWhich
);
1571 pEditView
[eWhich
]->SetWindow(pWin
);
1572 OSL_FAIL("EditView Window has changed");
1577 pEditView
[eWhich
].reset(new EditView(pNewEngine
, pWin
));
1581 // We can broadcast the view-cursor message in print-twips for all views.
1582 pEditView
[eWhich
]->SetBroadcastLOKViewCursor(bLOKPrintTwips
);
1583 pEditView
[eWhich
]->RegisterViewShell(pView
);
1587 // add windows from other views
1588 if (!bWasThere
&& bLOKActive
)
1590 ScTabViewShell
* pThisViewShell
= GetViewShell();
1591 SCTAB nThisTabNo
= GetTabNo();
1593 [pThisViewShell
, nThisTabNo
, eWhich
] (ScTabViewShell
* pOtherViewShell
)
1595 ScViewData
& rOtherViewData
= pOtherViewShell
->GetViewData();
1596 SCTAB nOtherTabNo
= rOtherViewData
.GetTabNo();
1597 if (nThisTabNo
== nOtherTabNo
)
1598 pOtherViewShell
->AddWindowToForeignEditView(pThisViewShell
, eWhich
);
1601 SfxLokHelper::forEachOtherView(pThisViewShell
, lAddWindows
);
1604 // if view is gone then during IdleFormat sometimes a cursor is drawn
1606 EEControlBits nEC
= pNewEngine
->GetControlWord();
1607 pNewEngine
->SetControlWord(nEC
& ~EEControlBits::DOIDLEFORMAT
);
1609 EVControlBits nVC
= pEditView
[eWhich
]->GetControlWord();
1610 pEditView
[eWhich
]->SetControlWord(nVC
& ~EVControlBits::AUTOSCROLL
);
1612 bEditActive
[eWhich
] = true;
1614 const ScPatternAttr
* pPattern
= mrDoc
.GetPattern(nNewX
, nNewY
, nTabNo
);
1617 SAL_WARN("sc.viewdata", "No Pattern Found for: Col: " << nNewX
<< ", Row: " << nNewY
<< ", Tab: " << nTabNo
);
1618 pPattern
= &mrDoc
.getCellAttributeHelper().getDefaultCellAttribute();
1620 SvxCellHorJustify eJust
= pPattern
->GetItem( ATTR_HOR_JUSTIFY
).GetValue();
1622 bool bBreak
= ( eJust
== SvxCellHorJustify::Block
) ||
1623 pPattern
->GetItem(ATTR_LINEBREAK
).GetValue();
1625 bool bAsianVertical
= pNewEngine
->IsEffectivelyVertical(); // set by InputHandler
1627 tools::Rectangle aPixRect
= ScEditUtil(&mrDoc
, nNewX
, nNewY
, nTabNo
, GetScrPos(nNewX
, nNewY
, eWhich
),
1628 pWin
->GetOutDev(), nPPTX
,nPPTY
,GetZoomX(),GetZoomY() ).
1629 GetEditArea( pPattern
, true );
1631 tools::Rectangle aPTwipsRect
;
1634 aPTwipsRect
= ScEditUtil(&mrDoc
, nNewX
, nNewY
, nTabNo
, GetPrintTwipsPos(nNewX
, nNewY
),
1635 pWin
->GetOutDev(), nPPTX
, nPPTY
, GetZoomX(), GetZoomY(), true /* bInPrintTwips */).
1636 GetEditArea(pPattern
, true);
1639 // when right-aligned, leave space for the cursor
1640 // in vertical mode, editing is always right-aligned
1641 if ( GetEditAdjust() == SvxAdjust::Right
|| bAsianVertical
)
1643 aPixRect
.AdjustRight(1 );
1645 aPTwipsRect
.AdjustRight(o3tl::convert(1, o3tl::Length::px
, o3tl::Length::twip
));
1650 if (!pEditView
[eWhich
]->HasLOKSpecialPositioning())
1651 pEditView
[eWhich
]->InitLOKSpecialPositioning(MapUnit::MapTwip
, aPTwipsRect
, Point());
1653 pEditView
[eWhich
]->SetLOKSpecialOutputArea(aPTwipsRect
);
1656 if (bLOKActive
&& pEditView
[eWhich
]->HasLOKSpecialPositioning())
1657 pEditView
[eWhich
]->SetLOKSpecialFlags(bLOKLayoutRTL
? LOKSpecialFlags::LayoutRTL
: LOKSpecialFlags::NONE
);
1659 tools::Rectangle aOutputArea
= pWin
->PixelToLogic( aPixRect
, GetLogicMode() );
1660 pEditView
[eWhich
]->SetOutputArea( aOutputArea
);
1663 notifyCellCursorAt(GetViewShell(), nNewX
, nNewY
, aPTwipsRect
);
1665 ScModule
* pScMod
= ScModule::get();
1666 if ( bActive
&& eWhich
== GetActivePart() )
1668 // keep the part that has the active edit view available after
1669 // switching sheets or reference input on a different part
1670 eEditActivePart
= eWhich
;
1672 // modify members nEditCol etc. only if also extending for needed area
1675 const ScMergeAttr
* pMergeAttr
= &pPattern
->GetItem(ATTR_MERGE
);
1676 nEditEndCol
= nEditCol
;
1677 if (pMergeAttr
->GetColMerge() > 1)
1678 nEditEndCol
+= pMergeAttr
->GetColMerge() - 1;
1679 nEditEndRow
= nEditRow
;
1680 if (pMergeAttr
->GetRowMerge() > 1)
1681 nEditEndRow
+= pMergeAttr
->GetRowMerge() - 1;
1682 nEditStartCol
= nEditCol
;
1684 // For growing use only the alignment value from the attribute, numbers
1685 // (existing or started) with default alignment extend to the right.
1686 bool bGrowCentered
= ( eJust
== SvxCellHorJustify::Center
);
1687 bool bGrowToLeft
= ( eJust
== SvxCellHorJustify::Right
); // visual left
1688 bool bLOKRTLInvert
= (bLOKActive
&& bLayoutRTL
);
1689 if ( bAsianVertical
)
1690 bGrowCentered
= bGrowToLeft
= false; // keep old behavior for asian mode
1692 tools::Long nSizeXPix
, nSizeXPTwips
= 0;
1694 const tools::Long nGridWidthPx
= pView
->GetGridWidth(eHWhich
);
1695 const tools::Long nGridHeightPx
= pView
->GetGridHeight(eVWhich
);
1696 tools::Long nGridWidthTwips
= 0, nGridHeightTwips
= 0;
1699 Size
aGridSize(nGridWidthPx
, nGridHeightPx
);
1700 const MapMode
& rWinMapMode
= GetLogicMode();
1701 aGridSize
= OutputDevice::LogicToLogic(
1702 pWin
->PixelToLogic(aGridSize
, rWinMapMode
),
1703 rWinMapMode
, MapMode(MapUnit::MapTwip
));
1704 nGridWidthTwips
= aGridSize
.Width();
1705 nGridHeightTwips
= aGridSize
.Height();
1708 if (bBreak
&& !bAsianVertical
)
1710 nSizeXPix
= aPixRect
.GetWidth(); // papersize -> no horizontal scrolling
1712 nSizeXPTwips
= aPTwipsRect
.GetWidth();
1716 OSL_ENSURE(pView
,"no View for EditView");
1718 if ( bGrowCentered
)
1720 // growing into both directions until one edge is reached
1721 //! should be limited to whole cells in both directions
1722 tools::Long nLeft
= aPixRect
.Left();
1723 tools::Long nRight
= nGridWidthPx
- aPixRect
.Right();
1724 nSizeXPix
= aPixRect
.GetWidth() + 2 * std::min( nLeft
, nRight
);
1727 tools::Long nLeftPTwips
= aPTwipsRect
.Left();
1728 tools::Long nRightPTwips
= nGridWidthTwips
- aPTwipsRect
.Right();
1729 nSizeXPTwips
= aPTwipsRect
.GetWidth() + 2 * std::min(nLeftPTwips
, nRightPTwips
);
1732 else if ( (bGrowToLeft
&& !bLOKRTLInvert
) || (!bGrowToLeft
&& bLOKRTLInvert
) )
1734 nSizeXPix
= aPixRect
.Right(); // space that's available in the window when growing to the left
1736 nSizeXPTwips
= aPTwipsRect
.Right();
1740 nSizeXPix
= nGridWidthPx
- aPixRect
.Left();
1742 nSizeXPTwips
= nGridWidthTwips
- aPTwipsRect
.Left();
1745 if ( nSizeXPix
<= 0 )
1747 nSizeXPix
= aPixRect
.GetWidth(); // editing outside to the right of the window -> keep cell width
1749 nSizeXPTwips
= aPTwipsRect
.GetWidth();
1752 OSL_ENSURE(pView
,"no View for EditView");
1753 tools::Long nSizeYPix
= nGridHeightPx
- aPixRect
.Top();
1754 tools::Long nSizeYPTwips
= bLOKPrintTwips
? (nGridHeightTwips
- aPTwipsRect
.Top()) : 0;
1756 if ( nSizeYPix
<= 0 )
1758 nSizeYPix
= aPixRect
.GetHeight(); // editing outside below the window -> keep cell height
1760 nSizeYPTwips
= aPTwipsRect
.GetHeight();
1763 Size aPaperSize
= pView
->GetActiveWin()->PixelToLogic( Size( nSizeXPix
, nSizeYPix
), GetLogicMode() );
1764 Size
aPaperSizePTwips(nSizeXPTwips
, nSizeYPTwips
);
1765 // In the LOK case the following code can make the cell background and visible area larger
1766 // than needed which makes selecting the adjacent right cell impossible in some cases.
1767 if (bBreak
&& !bAsianVertical
&& pScMod
->GetInputOptions().GetTextWysiwyg() && !bLOKActive
)
1769 // if text is formatted for printer, use the exact same paper width
1770 // (and same line breaks) as for output.
1772 Fraction
aFract(1,1);
1773 constexpr auto HMM_PER_TWIPS
= o3tl::convert(1.0, o3tl::Length::twip
, o3tl::Length::mm100
);
1774 tools::Rectangle aUtilRect
= ScEditUtil(&mrDoc
, nNewX
, nNewY
, nTabNo
, Point(0, 0), pWin
->GetOutDev(),
1775 HMM_PER_TWIPS
, HMM_PER_TWIPS
, aFract
, aFract
).GetEditArea( pPattern
, false );
1776 aPaperSize
.setWidth( aUtilRect
.GetWidth() );
1779 aPaperSizePTwips
.setWidth(o3tl::convert(aUtilRect
.GetWidth(), o3tl::Length::mm100
, o3tl::Length::twip
));
1783 pNewEngine
->SetPaperSize( aPaperSize
);
1785 pNewEngine
->SetLOKSpecialPaperSize(aPaperSizePTwips
);
1787 // sichtbarer Ausschnitt
1788 Size aPaper
= pNewEngine
->GetPaperSize();
1789 tools::Rectangle aVis
= pEditView
[eWhich
]->GetVisArea();
1790 tools::Rectangle aVisPTwips
;
1792 aVisPTwips
= pEditView
[eWhich
]->GetLOKSpecialVisArea();
1794 tools::Long nDiff
= aVis
.Right() - aVis
.Left();
1795 tools::Long nDiffPTwips
= bLOKPrintTwips
? (aVisPTwips
.Right() - aVisPTwips
.Left()) : 0;
1796 if ( GetEditAdjust() == SvxAdjust::Right
)
1798 aVis
.SetRight( aPaper
.Width() - 1 );
1800 aVisPTwips
.SetRight( aPaperSizePTwips
.Width() - 1 );
1801 bMoveArea
= !bLayoutRTL
;
1803 else if ( GetEditAdjust() == SvxAdjust::Center
)
1805 aVis
.SetRight( ( aPaper
.Width() - 1 + nDiff
) / 2 );
1807 aVisPTwips
.SetRight( ( aPaperSizePTwips
.Width() - 1 + nDiffPTwips
) / 2 );
1808 bMoveArea
= true; // always
1812 aVis
.SetRight( nDiff
);
1814 aVisPTwips
.SetRight(nDiffPTwips
);
1815 bMoveArea
= bLayoutRTL
;
1817 aVis
.SetLeft( aVis
.Right() - nDiff
);
1819 aVisPTwips
.SetLeft(aVisPTwips
.Right() - nDiffPTwips
);
1820 // #i49561# Important note:
1821 // The set offset of the visible area of the EditView for centered and
1822 // right alignment in horizontal layout is consider by instances of
1823 // class <ScEditObjectViewForwarder> in its methods <LogicToPixel(..)>
1824 // and <PixelToLogic(..)>. This is needed for the correct visibility
1825 // of paragraphs in edit mode at the accessibility API.
1826 pEditView
[eWhich
]->SetVisArea(aVis
);
1828 pEditView
[eWhich
]->SetLOKSpecialVisArea(aVisPTwips
);
1829 // UpdateMode has been disabled in ScInputHandler::StartTable
1830 // must be enabled before EditGrowY (GetTextHeight)
1831 pNewEngine
->SetUpdateLayout( true );
1833 pNewEngine
->SetStatusEventHdl( LINK( this, ScViewData
, EditEngineHdl
) );
1835 EditGrowY( true ); // adjust to existing text content
1838 Point aDocPos
= pEditView
[eWhich
]->GetWindowPosTopLeft(0);
1839 if (aDocPos
.Y() < aOutputArea
.Top())
1840 pEditView
[eWhich
]->Scroll( 0, aOutputArea
.Top() - aDocPos
.Y() );
1843 // here bEditActive needs to be set already
1844 // (due to Map-Mode during Paint)
1846 pNewEngine
->InsertView(pEditView
[eWhich
].get());
1848 // background color of the cell
1849 Color aBackCol
= pPattern
->GetItem(ATTR_BACKGROUND
).GetColor();
1851 if ( aBackCol
.IsTransparent() )
1853 aBackCol
= pScMod
->GetColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
1855 pEditView
[eWhich
]->SetBackgroundColor( aBackCol
);
1857 pEditView
[eWhich
]->Invalidate(); // needed?
1858 // needed, if position changed
1861 IMPL_LINK( ScViewData
, EditEngineHdl
, EditStatus
&, rStatus
, void )
1863 EditStatusFlags nStatus
= rStatus
.GetStatusWord();
1864 if (nStatus
& (EditStatusFlags::HSCROLL
| EditStatusFlags::TextHeightChanged
| EditStatusFlags::TEXTWIDTHCHANGED
| EditStatusFlags::CURSOROUT
))
1869 if (nStatus
& EditStatusFlags::CURSOROUT
)
1871 ScSplitPos eWhich
= GetActivePart();
1872 if (pEditView
[eWhich
])
1873 pEditView
[eWhich
]->ShowCursor(false);
1878 void ScViewData::EditGrowX()
1880 // It is insane to call EditGrowX while the output area is already growing.
1881 // That could occur because of the call to SetDefaultItem later.
1882 // We end up with wrong start/end edit columns and the changes
1883 // to the output area performed by the inner call to this method are
1884 // useless since they are discarded by the outer call.
1888 comphelper::FlagRestorationGuard
aFlagGuard(bGrowing
, true);
1890 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
1891 bool bLOKPrintTwips
= bLOKActive
&& comphelper::LibreOfficeKit::isCompatFlagSet(
1892 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
1894 ScDocument
& rLocalDoc
= GetDocument();
1896 ScSplitPos eWhich
= GetActivePart();
1897 ScHSplitPos eHWhich
= WhichH(eWhich
);
1898 EditView
* pCurView
= pEditView
[eWhich
].get();
1900 if ( !pCurView
|| !bEditActive
[eWhich
])
1903 bool bLayoutRTL
= rLocalDoc
.IsLayoutRTL( nTabNo
);
1905 ScEditEngineDefaulter
* pEngine
= static_cast<ScEditEngineDefaulter
*>(&pCurView
->getEditEngine());
1906 vcl::Window
* pWin
= pCurView
->GetWindow();
1908 // Get the left- and right-most column positions.
1909 SCCOL nLeft
= GetPosX(eHWhich
);
1910 SCCOL nRight
= nLeft
+ VisibleCellsX(eHWhich
);
1912 Size aSize
= pEngine
->GetPaperSize();
1915 aSizePTwips
= pEngine
->GetLOKSpecialPaperSize();
1917 tools::Rectangle aArea
= pCurView
->GetOutputArea();
1918 tools::Rectangle aAreaPTwips
;
1920 aAreaPTwips
= pCurView
->GetLOKSpecialOutputArea();
1922 tools::Long nOldRight
= aArea
.Right();
1924 // Margin is already included in the original width.
1925 tools::Long nTextWidth
= pEngine
->CalcTextWidth();
1927 bool bChanged
= false;
1928 bool bAsianVertical
= pEngine
->IsEffectivelyVertical();
1930 // get bGrow... variables the same way as in SetEditEngine
1931 const ScPatternAttr
* pPattern
= rLocalDoc
.GetPattern( nEditCol
, nEditRow
, nTabNo
);
1932 SvxCellHorJustify eJust
= pPattern
->GetItem( ATTR_HOR_JUSTIFY
).GetValue();
1933 bool bGrowCentered
= ( eJust
== SvxCellHorJustify::Center
);
1934 bool bGrowToLeft
= ( eJust
== SvxCellHorJustify::Right
); // visual left
1935 bool bGrowBackwards
= bGrowToLeft
; // logical left
1937 bGrowBackwards
= !bGrowBackwards
; // invert on RTL sheet
1938 if ( bAsianVertical
)
1939 bGrowCentered
= bGrowToLeft
= bGrowBackwards
= false; // keep old behavior for asian mode
1941 bool bUnevenGrow
= false;
1942 if ( bGrowCentered
)
1944 while (aArea
.GetWidth() + 0 < nTextWidth
&& ( nEditStartCol
> nLeft
|| nEditEndCol
< nRight
) )
1946 tools::Long nLogicLeft
= 0;
1947 tools::Long nLogicLeftPTwips
= 0;
1948 if ( nEditStartCol
> nLeft
)
1951 tools::Long nColWidth
= rLocalDoc
.GetColWidth( nEditStartCol
, nTabNo
);
1952 tools::Long nLeftPix
= ToPixel( nColWidth
, nPPTX
);
1953 nLogicLeft
= pWin
->PixelToLogic(Size(nLeftPix
,0)).Width();
1955 nLogicLeftPTwips
= nColWidth
;
1957 tools::Long nLogicRight
= 0;
1958 tools::Long nLogicRightPTwips
= 0;
1959 if ( nEditEndCol
< nRight
)
1962 tools::Long nColWidth
= rLocalDoc
.GetColWidth( nEditEndCol
, nTabNo
);
1963 tools::Long nRightPix
= ToPixel( nColWidth
, nPPTX
);
1964 nLogicRight
= pWin
->PixelToLogic(Size(nRightPix
,0)).Width();
1966 nLogicRightPTwips
= nColWidth
;
1969 aArea
.AdjustLeft( -((bLayoutRTL
&& !bLOKActive
) ? nLogicRight
: nLogicLeft
) );
1970 aArea
.AdjustRight((bLayoutRTL
&& !bLOKActive
) ? nLogicLeft
: nLogicRight
);
1973 aAreaPTwips
.AdjustLeft(-nLogicLeftPTwips
);
1974 aAreaPTwips
.AdjustRight(nLogicRightPTwips
);
1977 if ( aArea
.Right() > aArea
.Left() + aSize
.Width() - 1 )
1979 tools::Long nCenter
= ( aArea
.Left() + aArea
.Right() ) / 2;
1980 tools::Long nHalf
= aSize
.Width() / 2;
1981 aArea
.SetLeft( nCenter
- nHalf
+ 1 );
1982 aArea
.SetRight( nCenter
+ aSize
.Width() - nHalf
- 1 );
1986 tools::Long nCenterPTwips
= ( aAreaPTwips
.Left() + aAreaPTwips
.Right() ) / 2;
1987 tools::Long nHalfPTwips
= aSizePTwips
.Width() / 2;
1988 aAreaPTwips
.SetLeft( nCenterPTwips
- nHalfPTwips
+ 1 );
1989 aAreaPTwips
.SetRight( nCenterPTwips
+ aSizePTwips
.Width() - nHalfPTwips
- 1 );
1994 if ( nLogicLeft
!= nLogicRight
)
1998 else if ( bGrowBackwards
)
2000 while (aArea
.GetWidth() + 0 < nTextWidth
&& nEditStartCol
> nLeft
)
2003 tools::Long nColWidth
= rLocalDoc
.GetColWidth( nEditStartCol
, nTabNo
);
2004 tools::Long nPix
= ToPixel( nColWidth
, nPPTX
);
2005 tools::Long nLogicWidth
= pWin
->PixelToLogic(Size(nPix
,0)).Width();
2006 tools::Long
& nLogicWidthPTwips
= nColWidth
;
2008 if ( !bLayoutRTL
|| bLOKActive
)
2010 aArea
.AdjustLeft( -nLogicWidth
);
2012 aAreaPTwips
.AdjustLeft( -nLogicWidthPTwips
);
2016 aArea
.AdjustRight(nLogicWidth
);
2018 aAreaPTwips
.AdjustRight(nLogicWidthPTwips
);
2021 if ( aArea
.Right() > aArea
.Left() + aSize
.Width() - 1 )
2023 if ( !bLayoutRTL
|| bLOKActive
)
2025 aArea
.SetLeft( aArea
.Right() - aSize
.Width() + 1 );
2027 aAreaPTwips
.SetLeft( aAreaPTwips
.Right() - aSizePTwips
.Width() + 1 );
2031 aArea
.SetRight( aArea
.Left() + aSize
.Width() - 1 );
2033 aAreaPTwips
.SetRight( aAreaPTwips
.Left() + aSizePTwips
.Width() - 1 );
2042 while (aArea
.GetWidth() + 0 < nTextWidth
&& nEditEndCol
< nRight
)
2045 tools::Long nColWidth
= rLocalDoc
.GetColWidth( nEditEndCol
, nTabNo
);
2046 tools::Long nPix
= ToPixel( nColWidth
, nPPTX
);
2047 tools::Long nLogicWidth
= pWin
->PixelToLogic(Size(nPix
,0)).Width();
2048 tools::Long
& nLogicWidthPTwips
= nColWidth
;
2049 if ( bLayoutRTL
&& !bLOKActive
)
2051 aArea
.AdjustLeft( -nLogicWidth
);
2055 aArea
.AdjustRight(nLogicWidth
);
2057 aAreaPTwips
.AdjustRight(nLogicWidthPTwips
);
2060 if ( aArea
.Right() > aArea
.Left() + aSize
.Width() - 1 )
2062 if ( bLayoutRTL
&& !bLOKActive
)
2064 aArea
.SetLeft( aArea
.Right() - aSize
.Width() + 1 );
2068 aArea
.SetRight( aArea
.Left() + aSize
.Width() - 1 );
2070 aAreaPTwips
.SetRight( aAreaPTwips
.Left() + aSizePTwips
.Width() - 1 );
2081 if ( bMoveArea
|| bGrowCentered
|| bGrowBackwards
|| bLayoutRTL
)
2083 tools::Rectangle aVis
= pCurView
->GetVisArea();
2084 tools::Rectangle aVisPTwips
;
2086 aVisPTwips
= pCurView
->GetLOKSpecialVisArea();
2088 if ( bGrowCentered
)
2090 // switch to center-aligned (undo?) and reset VisArea to center
2092 pEngine
->SetDefaultItem( SvxAdjustItem( SvxAdjust::Center
, EE_PARA_JUST
) );
2094 tools::Long nCenter
= aSize
.Width() / 2;
2095 tools::Long nVisSize
= aArea
.GetWidth();
2096 aVis
.SetLeft( nCenter
- nVisSize
/ 2 );
2097 aVis
.SetRight( aVis
.Left() + nVisSize
- 1 );
2101 tools::Long nCenterPTwips
= aSizePTwips
.Width() / 2;
2102 tools::Long nVisSizePTwips
= aAreaPTwips
.GetWidth();
2103 aVisPTwips
.SetLeft( nCenterPTwips
- nVisSizePTwips
/ 2 );
2104 aVisPTwips
.SetRight( aVisPTwips
.Left() + nVisSizePTwips
- 1 );
2107 else if ( bGrowToLeft
)
2109 // switch to right-aligned (undo?) and reset VisArea to the right
2111 pEngine
->SetDefaultItem( SvxAdjustItem( SvxAdjust::Right
, EE_PARA_JUST
) );
2113 aVis
.SetRight( aSize
.Width() - 1 );
2114 aVis
.SetLeft( aSize
.Width() - aArea
.GetWidth() ); // with the new, increased area
2118 aVisPTwips
.SetRight( aSizePTwips
.Width() - 1 );
2119 aVisPTwips
.SetLeft( aSizePTwips
.Width() - aAreaPTwips
.GetWidth() ); // with the new, increased area
2124 // switch to left-aligned (undo?) and reset VisArea to the left
2126 pEngine
->SetDefaultItem( SvxAdjustItem( SvxAdjust::Left
, EE_PARA_JUST
) );
2128 tools::Long nMove
= aVis
.Left();
2130 aVis
.AdjustRight( -nMove
);
2134 tools::Long nMovePTwips
= aVisPTwips
.Left();
2135 aVisPTwips
.SetLeft( 0 );
2136 aVisPTwips
.AdjustRight( -nMovePTwips
);
2140 pCurView
->SetVisArea( aVis
);
2142 pCurView
->SetLOKSpecialVisArea( aVisPTwips
);
2148 pCurView
->SetLOKSpecialOutputArea(aAreaPTwips
);
2150 pCurView
->SetOutputArea(aArea
);
2153 notifyCellCursorAt(GetViewShell(), nEditCol
, nEditRow
, aAreaPTwips
);
2155 // In vertical mode, the whole text is moved to the next cell (right-aligned),
2156 // so everything must be repainted. Otherwise, paint only the new area.
2157 // If growing in centered alignment, if the cells left and right have different sizes,
2158 // the whole text will move, and may not even obscure all of the original display.
2161 aArea
.SetLeft( pWin
->PixelToLogic( Point(0,0) ).X() );
2162 aArea
.SetRight( pWin
->PixelToLogic( aScrSize
).Width() );
2164 else if ( !bAsianVertical
&& !bGrowToLeft
&& !bGrowCentered
)
2165 aArea
.SetLeft( nOldRight
);
2166 pWin
->Invalidate(aArea
);
2168 // invalidate other views
2169 pCurView
->InvalidateOtherViewWindows(aArea
);
2172 void ScViewData::EditGrowY( bool bInitial
)
2177 comphelper::FlagRestorationGuard
aFlagGuard(bGrowing
, true);
2179 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
2180 bool bLOKPrintTwips
= bLOKActive
&& comphelper::LibreOfficeKit::isCompatFlagSet(
2181 comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs
);
2183 ScSplitPos eWhich
= GetActivePart();
2184 ScVSplitPos eVWhich
= WhichV(eWhich
);
2185 EditView
* pCurView
= pEditView
[eWhich
].get();
2187 if ( !pCurView
|| !bEditActive
[eWhich
])
2190 EVControlBits nControl
= pEditView
[eWhich
]->GetControlWord();
2191 if ( nControl
& EVControlBits::AUTOSCROLL
)
2193 // if end of screen had already been reached and scrolling enabled,
2194 // don't further try to grow the edit area
2196 pCurView
->SetOutputArea( pCurView
->GetOutputArea() ); // re-align to pixels
2200 EditEngine
& rEngine
= pCurView
->getEditEngine();
2201 vcl::Window
* pWin
= pCurView
->GetWindow();
2203 SCROW nBottom
= GetPosY(eVWhich
) + VisibleCellsY(eVWhich
);
2205 Size aSize
= rEngine
.GetPaperSize();
2207 tools::Rectangle aArea
= pCurView
->GetOutputArea();
2208 tools::Rectangle aAreaPTwips
;
2212 aSizePTwips
= rEngine
.GetLOKSpecialPaperSize();
2213 aAreaPTwips
= pCurView
->GetLOKSpecialOutputArea();
2216 tools::Long nOldBottom
= aArea
.Bottom();
2217 tools::Long nTextHeight
= rEngine
.GetTextHeight();
2219 // When editing a formula in a cell with optimal height, allow a larger portion
2220 // to be clipped before extending to following rows, to avoid obscuring cells for
2221 // reference input (next row is likely to be useful in formulas).
2222 tools::Long nAllowedExtra
= SC_GROWY_SMALL_EXTRA
;
2223 if (nEditEndRow
== nEditRow
&& !(mrDoc
.GetRowFlags(nEditRow
, nTabNo
) & CRFlags::ManualSize
) &&
2224 rEngine
.GetParagraphCount() <= 1 )
2226 // If the (only) paragraph starts with a '=', it's a formula.
2227 // If this is the initial call and the text is empty, allow the larger value, too,
2228 // because this occurs in the normal progress of editing a formula.
2229 // Subsequent calls with empty text might involve changed attributes (including
2230 // font height), so they are treated like normal text.
2231 OUString aText
= rEngine
.GetText( 0 );
2232 if ( ( aText
.isEmpty() && bInitial
) || aText
.startsWith("=") )
2233 nAllowedExtra
= SC_GROWY_BIG_EXTRA
;
2236 bool bChanged
= false;
2237 bool bMaxReached
= false;
2238 while (aArea
.GetHeight() + nAllowedExtra
< nTextHeight
&& nEditEndRow
< nBottom
&& !bMaxReached
)
2241 ScDocument
& rLocalDoc
= GetDocument();
2242 tools::Long nRowHeight
= rLocalDoc
.GetRowHeight( nEditEndRow
, nTabNo
);
2243 tools::Long nPix
= ToPixel( nRowHeight
, nPPTY
);
2244 aArea
.AdjustBottom(pWin
->PixelToLogic(Size(0,nPix
)).Height() );
2246 aAreaPTwips
.AdjustBottom(nRowHeight
);
2248 if ( aArea
.Bottom() > aArea
.Top() + aSize
.Height() - 1 )
2250 aArea
.SetBottom( aArea
.Top() + aSize
.Height() - 1 );
2252 aAreaPTwips
.SetBottom( aAreaPTwips
.Top() + aSizePTwips
.Height() - 1 );
2253 bMaxReached
= true; // don't occupy more cells beyond paper size
2257 nAllowedExtra
= SC_GROWY_SMALL_EXTRA
; // larger value is only for first row
2264 pCurView
->SetLOKSpecialOutputArea(aAreaPTwips
);
2266 pCurView
->SetOutputArea(aArea
);
2269 notifyCellCursorAt(GetViewShell(), nEditCol
, nEditRow
, aAreaPTwips
);
2271 if (nEditEndRow
>= nBottom
|| bMaxReached
)
2273 if (!(nControl
& EVControlBits::AUTOSCROLL
))
2274 pCurView
->SetControlWord( nControl
| EVControlBits::AUTOSCROLL
);
2277 aArea
.SetTop( nOldBottom
);
2278 pWin
->Invalidate(aArea
);
2280 // invalidate other views
2281 pCurView
->InvalidateOtherViewWindows(aArea
);
2284 void ScViewData::ResetEditView()
2286 LOKEditViewHistory::Update(/*bRemove: */ true);
2287 EditEngine
* pEngine
= nullptr;
2288 for (sal_uInt16 i
=0; i
<4; i
++)
2294 lcl_LOKRemoveWindow(GetViewShell(), static_cast<ScSplitPos
>(i
));
2295 pEngine
= &pEditView
[i
]->getEditEngine();
2296 pEngine
->RemoveView(pEditView
[i
].get());
2297 pEditView
[i
]->SetOutputArea( tools::Rectangle() );
2299 bEditActive
[i
] = false;
2304 pEngine
->SetStatusEventHdl( Link
<EditStatus
&,void>() );
2307 void ScViewData::KillEditView()
2309 LOKEditViewHistory::Update(/*bRemove: */ true);
2310 for (sal_uInt16 i
=0; i
<4; i
++)
2315 EditEngine
& rEngine
= pEditView
[i
]->getEditEngine();
2316 rEngine
.RemoveView(pEditView
[i
].get());
2318 pEditView
[i
].reset();
2322 void ScViewData::GetEditView( ScSplitPos eWhich
, EditView
*& rViewPtr
, SCCOL
& rCol
, SCROW
& rRow
)
2324 rViewPtr
= pEditView
[eWhich
].get();
2329 void ScViewData::CreateTabData( SCTAB nNewTab
)
2331 EnsureTabDataSize(nNewTab
+ 1);
2333 if (!maTabData
[nNewTab
])
2335 maTabData
[nNewTab
].reset(new ScViewDataTable(&mrDoc
));
2337 maTabData
[nNewTab
]->eZoomType
= eDefZoomType
;
2338 maTabData
[nNewTab
]->aZoomX
= aDefZoomX
;
2339 maTabData
[nNewTab
]->aZoomY
= aDefZoomY
;
2340 maTabData
[nNewTab
]->aPageZoomX
= aDefPageZoomX
;
2341 maTabData
[nNewTab
]->aPageZoomY
= aDefPageZoomY
;
2345 void ScViewData::CreateSelectedTabData()
2347 for (const auto& rTab
: maMarkData
)
2348 CreateTabData(rTab
);
2351 void ScViewData::EnsureTabDataSize(size_t nSize
)
2353 if (nSize
> maTabData
.size())
2354 maTabData
.resize(nSize
);
2357 void ScViewData::SetTabNo( SCTAB nNewTab
)
2359 if (!ValidTab(nNewTab
))
2361 OSL_FAIL("wrong sheet number");
2366 CreateTabData(nTabNo
);
2367 pThisTab
= maTabData
[nTabNo
].get();
2369 CalcPPT(); // for common column width correction
2370 RecalcPixPos(); //! not always needed!
2373 ScPositionHelper
* ScViewData::GetLOKWidthHelper(SCTAB nTabIndex
)
2375 if (!ValidTab(nTabIndex
) || (nTabIndex
>= static_cast<SCTAB
>(maTabData
.size())) ||
2376 !maTabData
[nTabIndex
])
2380 return &(maTabData
[nTabIndex
]->aWidthHelper
);
2383 ScPositionHelper
* ScViewData::GetLOKHeightHelper(SCTAB nTabIndex
)
2385 if (!ValidTab(nTabIndex
) || (nTabIndex
>= static_cast<SCTAB
>(maTabData
.size())) ||
2386 !maTabData
[nTabIndex
])
2390 return &(maTabData
[nTabIndex
]->aHeightHelper
);
2393 void ScViewData::SetActivePart( ScSplitPos eNewActive
)
2395 pThisTab
->eWhichActive
= eNewActive
;
2397 // Let's hope we find the culprit for tdf#117093
2398 // Don't sanitize the real value (yet?) because this function might be
2399 // called before setting the then corresponding split modes. For which in
2400 // fact then the order should be changed.
2401 assert(eNewActive
== pThisTab
->SanitizeWhichActive());
2404 Point
ScViewData::GetScrPos( SCCOL nWhereX
, SCROW nWhereY
, ScHSplitPos eWhich
) const
2406 OSL_ENSURE( eWhich
==SC_SPLIT_LEFT
|| eWhich
==SC_SPLIT_RIGHT
, "wrong position" );
2407 ScSplitPos ePos
= ( eWhich
== SC_SPLIT_LEFT
) ? SC_SPLIT_BOTTOMLEFT
: SC_SPLIT_BOTTOMRIGHT
;
2408 return GetScrPos( nWhereX
, nWhereY
, ePos
);
2411 Point
ScViewData::GetScrPos( SCCOL nWhereX
, SCROW nWhereY
, ScVSplitPos eWhich
) const
2413 OSL_ENSURE( eWhich
==SC_SPLIT_TOP
|| eWhich
==SC_SPLIT_BOTTOM
, "wrong position" );
2414 ScSplitPos ePos
= ( eWhich
== SC_SPLIT_TOP
) ? SC_SPLIT_TOPLEFT
: SC_SPLIT_BOTTOMLEFT
;
2415 return GetScrPos( nWhereX
, nWhereY
, ePos
);
2418 Point
ScViewData::GetScrPos( SCCOL nWhereX
, SCROW nWhereY
, ScSplitPos eWhich
,
2419 bool bAllowNeg
, SCTAB nForTab
) const
2421 ScHSplitPos eWhichX
= SC_SPLIT_LEFT
;
2422 ScVSplitPos eWhichY
= SC_SPLIT_BOTTOM
;
2425 case SC_SPLIT_TOPLEFT
:
2426 eWhichX
= SC_SPLIT_LEFT
;
2427 eWhichY
= SC_SPLIT_TOP
;
2429 case SC_SPLIT_TOPRIGHT
:
2430 eWhichX
= SC_SPLIT_RIGHT
;
2431 eWhichY
= SC_SPLIT_TOP
;
2433 case SC_SPLIT_BOTTOMLEFT
:
2434 eWhichX
= SC_SPLIT_LEFT
;
2435 eWhichY
= SC_SPLIT_BOTTOM
;
2437 case SC_SPLIT_BOTTOMRIGHT
:
2438 eWhichX
= SC_SPLIT_RIGHT
;
2439 eWhichY
= SC_SPLIT_BOTTOM
;
2445 bool bForCurTab
= (nForTab
== nTabNo
);
2446 if (!bForCurTab
&& (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size()))))
2448 SAL_WARN("sc.viewdata", "ScViewData::GetScrPos : invalid nForTab = " << nForTab
);
2453 ScViewDataTable
* pViewTable
= bForCurTab
? pThisTab
: maTabData
[nForTab
].get();
2457 const_cast<ScViewData
*>(this)->aScrSize
.setWidth( pView
->GetGridWidth(eWhichX
) );
2458 const_cast<ScViewData
*>(this)->aScrSize
.setHeight( pView
->GetGridHeight(eWhichY
) );
2462 bool bIsTiledRendering
= comphelper::LibreOfficeKit::isActive();
2464 SCCOL nPosX
= GetPosX(eWhichX
, nForTab
);
2465 tools::Long nScrPosX
= 0;
2467 if (bAllowNeg
|| nWhereX
>= nPosX
)
2469 SCROW nStartPosX
= nPosX
;
2470 if (bIsTiledRendering
)
2472 OSL_ENSURE(nPosX
== 0, "Unsupported case.");
2473 const auto& rNearest
= pViewTable
->aWidthHelper
.getNearestByIndex(nWhereX
- 1);
2474 nStartPosX
= rNearest
.first
+ 1;
2475 nScrPosX
= rNearest
.second
;
2478 if (nWhereX
>= nStartPosX
)
2480 for (SCCOL nX
= nStartPosX
; nX
< nWhereX
&& (bAllowNeg
|| bIsTiledRendering
|| nScrPosX
<= aScrSize
.Width()); nX
++)
2482 if (nX
> mrDoc
.MaxCol())
2483 nScrPosX
= 0x7FFFFFFF;
2486 nTSize
= mrDoc
.GetColWidth(nX
, nForTab
);
2489 tools::Long nSizeXPix
= ToPixel( nTSize
, nPPTX
);
2490 nScrPosX
+= nSizeXPix
;
2493 { // If the width is zero, the column is possibly hidden, skips groups of such columns.
2494 SCCOL lastHidden
= -1;
2495 if(mrDoc
.ColHidden(nX
, nForTab
, nullptr, &lastHidden
) && lastHidden
> nX
)
2496 nX
= lastHidden
- 1;
2503 for (SCCOL nX
= nStartPosX
; nX
> nWhereX
;)
2506 nTSize
= mrDoc
.GetColWidth(nX
, nForTab
);
2509 tools::Long nSizeXPix
= ToPixel( nTSize
, nPPTX
);
2510 nScrPosX
-= nSizeXPix
;
2513 { // If the width is zero, the column is possibly hidden, skips groups of such columns.
2514 SCCOL firstHidden
= -1;
2515 if(mrDoc
.ColHidden(nX
, nForTab
, &firstHidden
, nullptr) && firstHidden
>= 0)
2524 SCROW nPosY
= GetPosY(eWhichY
, nForTab
);
2525 tools::Long nScrPosY
= 0;
2527 if (bAllowNeg
|| nWhereY
>= nPosY
)
2529 SCROW nStartPosY
= nPosY
;
2530 if (bIsTiledRendering
)
2532 OSL_ENSURE(nPosY
== 0, "Unsupported case.");
2533 const auto& rNearest
= pViewTable
->aHeightHelper
.getNearestByIndex(nWhereY
- 1);
2534 nStartPosY
= rNearest
.first
+ 1;
2535 nScrPosY
= rNearest
.second
;
2538 if (nWhereY
>= nStartPosY
)
2540 for (SCROW nY
= nStartPosY
; nY
< nWhereY
&& (bAllowNeg
|| bIsTiledRendering
|| nScrPosY
<= aScrSize
.Height()); nY
++)
2542 if ( nY
> mrDoc
.MaxRow() )
2543 nScrPosY
= 0x7FFFFFFF;
2546 nTSize
= mrDoc
.GetRowHeight( nY
, nTabNo
);
2549 tools::Long nSizeYPix
= ToPixel( nTSize
, nPPTY
);
2550 nScrPosY
+= nSizeYPix
;
2552 else if ( nY
< mrDoc
.MaxRow() )
2554 // skip multiple hidden rows (forward only for now)
2555 SCROW nNext
= mrDoc
.FirstVisibleRow(nY
+ 1, mrDoc
.MaxRow(), nTabNo
);
2556 if ( nNext
> mrDoc
.MaxRow() )
2557 nY
= mrDoc
.MaxRow();
2559 nY
= nNext
- 1; // +=nDir advances to next visible row
2566 for (SCROW nY
= nStartPosY
; nY
> nWhereY
;)
2569 nTSize
= mrDoc
.GetRowHeight(nY
, nForTab
);
2572 tools::Long nSizeYPix
= ToPixel( nTSize
, nPPTY
);
2573 nScrPosY
-= nSizeYPix
;
2576 { // If the height is zero, the row is possibly hidden, skips groups of such rows.
2577 SCROW firstHidden
= -1;
2578 if(mrDoc
.RowHidden(nY
, nForTab
, &firstHidden
, nullptr) && firstHidden
>= 0)
2585 if (mrDoc
.IsLayoutRTL(nForTab
) && !bIsTiledRendering
)
2587 // mirror horizontal position
2588 nScrPosX
= aScrSize
.Width() - 1 - nScrPosX
;
2591 return Point( nScrPosX
, nScrPosY
);
2594 Point
ScViewData::GetPrintTwipsPos(SCCOL nCol
, SCROW nRow
) const
2596 // hidden ones are given 0 sizes by these by default.
2597 // TODO: rewrite this to loop over spans (matters for jumbosheets).
2598 tools::Long nPosX
= nCol
? mrDoc
.GetColWidth(0, nCol
- 1, nTabNo
) : 0;
2599 // This is now fast as it loops over spans.
2600 tools::Long nPosY
= nRow
? mrDoc
.GetRowHeight(0, nRow
- 1, nTabNo
) : 0;
2601 // TODO: adjust for RTL layout case.
2603 return Point(nPosX
, nPosY
);
2606 Point
ScViewData::GetPrintTwipsPosFromTileTwips(const Point
& rTileTwipsPos
) const
2608 const tools::Long nPixelX
= static_cast<tools::Long
>(rTileTwipsPos
.X() * nPPTX
);
2609 const tools::Long nPixelY
= static_cast<tools::Long
>(rTileTwipsPos
.Y() * nPPTY
);
2613 // The following call (with bTestMerge = false) will not modify any members.
2614 const_cast<ScViewData
*>(this)->GetPosFromPixel(nPixelX
, nPixelY
, SC_SPLIT_TOPLEFT
, nCol
, nRow
, false /* bTestMerge */);
2615 const Point aPixCellPos
= GetScrPos(nCol
, nRow
, SC_SPLIT_TOPLEFT
, true /* bAllowNeg */);
2616 const Point
aTileTwipsCellPos(aPixCellPos
.X() / nPPTX
, aPixCellPos
.Y() / nPPTY
);
2617 const Point aPrintTwipsCellPos
= GetPrintTwipsPos(nCol
, nRow
);
2618 return aPrintTwipsCellPos
+ (rTileTwipsPos
- aTileTwipsCellPos
);
2621 OString
ScViewData::describeCellCursorAt(SCCOL nX
, SCROW nY
, bool bPixelAligned
) const
2623 const bool bPosSizeInPixels
= bPixelAligned
;
2624 Point aCellPos
= bPosSizeInPixels
? GetScrPos( nX
, nY
, SC_SPLIT_BOTTOMRIGHT
, true ) :
2625 GetPrintTwipsPos(nX
, nY
);
2629 if (bPosSizeInPixels
)
2630 GetMergeSizePixel( nX
, nY
, nSizeX
, nSizeY
);
2632 GetMergeSizePrintTwips(nX
, nY
, nSizeX
, nSizeY
);
2634 std::stringstream ss
;
2635 if (bPosSizeInPixels
)
2637 double fPPTX
= GetPPTX();
2638 double fPPTY
= GetPPTY();
2640 // make it a slim cell cursor, but not empty
2647 tools::Long nPosXTw
= rtl::math::round(aCellPos
.getX() / fPPTX
);
2648 tools::Long nPosYTw
= rtl::math::round(aCellPos
.getY() / fPPTY
);
2649 // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
2650 tools::Long nSizeXTw
= rtl::math::round(nSizeX
/ fPPTX
) - 1;
2651 tools::Long nSizeYTw
= rtl::math::round(nSizeY
/ fPPTY
) - 1;
2653 ss
<< nPosXTw
<< ", " << nPosYTw
<< ", " << nSizeXTw
<< ", " << nSizeYTw
<< ", "
2654 << nX
<< ", " << nY
;
2658 // look at Rectangle( const Point& rLT, const Size& rSize ) for the decrement.
2663 ss
<< aCellPos
.getX() << ", " << aCellPos
.getY()
2664 << ", " << nSizeX
<< ", " << nSizeY
<< ", "
2665 << nX
<< ", " << nY
;
2668 return OString(ss
.str());
2671 // Number of cells on a screen
2672 SCCOL
ScViewData::CellsAtX( SCCOL nPosX
, SCCOL nDir
, ScHSplitPos eWhichX
, sal_uInt16 nScrSizeX
) const
2674 OSL_ENSURE( nDir
==1 || nDir
==-1, "wrong CellsAt call" );
2677 const_cast<ScViewData
*>(this)->aScrSize
.setWidth( pView
->GetGridWidth(eWhichX
) );
2680 sal_uInt16 nScrPosX
= 0;
2681 if (nScrSizeX
== SC_SIZE_NONE
) nScrSizeX
= static_cast<sal_uInt16
>(aScrSize
.Width());
2684 nX
= nPosX
; // forwards
2686 nX
= nPosX
-1; // backwards
2689 for ( ; nScrPosX
<=nScrSizeX
&& !bOut
; nX
= sal::static_int_cast
<SCCOL
>(nX
+ nDir
) )
2692 if (nColNo
< 0 || nColNo
> mrDoc
.MaxCol())
2696 sal_uInt16 nTSize
= mrDoc
.GetColWidth(nColNo
, nTabNo
);
2699 tools::Long nSizeXPix
= ToPixel( nTSize
, nPPTX
);
2700 nScrPosX
= sal::static_int_cast
<sal_uInt16
>( nScrPosX
+ static_cast<sal_uInt16
>(nSizeXPix
) );
2706 nX
= sal::static_int_cast
<SCCOL
>( nX
- nPosX
);
2714 SCROW
ScViewData::CellsAtY( SCROW nPosY
, SCROW nDir
, ScVSplitPos eWhichY
, sal_uInt16 nScrSizeY
) const
2716 OSL_ENSURE( nDir
==1 || nDir
==-1, "wrong CellsAt call" );
2719 const_cast<ScViewData
*>(this)->aScrSize
.setHeight( pView
->GetGridHeight(eWhichY
) );
2721 if (nScrSizeY
== SC_SIZE_NONE
) nScrSizeY
= static_cast<sal_uInt16
>(aScrSize
.Height());
2729 tools::Long nScrPosY
= 0;
2730 AddPixelsWhile(nScrPosY
, nScrSizeY
, nY
, mrDoc
.MaxRow(), nPPTY
, &mrDoc
, nTabNo
);
2731 // Original loop ended on last evaluated +1 or if that was MaxRow even on MaxRow+2.
2732 nY
+= (nY
== mrDoc
.MaxRow() ? 2 : 1);
2739 tools::Long nScrPosY
= 0;
2740 AddPixelsWhileBackward(nScrPosY
, nScrSizeY
, nY
, 0, nPPTY
, &mrDoc
, nTabNo
);
2741 // Original loop ended on last evaluated -1 or if that was 0 even on -2.
2742 nY
-= (nY
== 0 ? 2 : 1);
2750 SCCOL
ScViewData::VisibleCellsX( ScHSplitPos eWhichX
) const
2752 return CellsAtX( GetPosX( eWhichX
), 1, eWhichX
);
2755 SCROW
ScViewData::VisibleCellsY( ScVSplitPos eWhichY
) const
2757 return CellsAtY( GetPosY( eWhichY
), 1, eWhichY
);
2760 SCCOL
ScViewData::PrevCellsX( ScHSplitPos eWhichX
) const
2762 return CellsAtX( GetPosX( eWhichX
), -1, eWhichX
);
2765 SCROW
ScViewData::PrevCellsY( ScVSplitPos eWhichY
) const
2767 return CellsAtY( GetPosY( eWhichY
), -1, eWhichY
);
2770 bool ScViewData::GetMergeSizePixel( SCCOL nX
, SCROW nY
, tools::Long
& rSizeXPix
, tools::Long
& rSizeYPix
) const
2772 const ScMergeAttr
* pMerge
= mrDoc
.GetAttr(nX
, nY
, nTabNo
, ATTR_MERGE
);
2773 if ( pMerge
->GetColMerge() > 1 || pMerge
->GetRowMerge() > 1 )
2775 tools::Long nOutWidth
= 0;
2776 tools::Long nOutHeight
= 0;
2777 SCCOL nCountX
= pMerge
->GetColMerge();
2778 for (SCCOL i
=0; i
<nCountX
; i
++)
2779 nOutWidth
+= ToPixel(mrDoc
.GetColWidth(nX
+ i
, nTabNo
), nPPTX
);
2780 SCROW nCountY
= pMerge
->GetRowMerge();
2782 for (SCROW nRow
= nY
; nRow
<= nY
+nCountY
-1; ++nRow
)
2784 SCROW nLastRow
= nRow
;
2785 if (mrDoc
.RowHidden(nRow
, nTabNo
, nullptr, &nLastRow
))
2791 sal_uInt16 nHeight
= mrDoc
.GetRowHeight(nRow
, nTabNo
);
2792 nOutHeight
+= ToPixel(nHeight
, nPPTY
);
2795 rSizeXPix
= nOutWidth
;
2796 rSizeYPix
= nOutHeight
;
2801 rSizeXPix
= ToPixel(mrDoc
.GetColWidth(nX
, nTabNo
), nPPTX
);
2802 rSizeYPix
= ToPixel(mrDoc
.GetRowHeight(nY
, nTabNo
), nPPTY
);
2807 bool ScViewData::GetMergeSizePrintTwips(SCCOL nX
, SCROW nY
, tools::Long
& rSizeXTwips
, tools::Long
& rSizeYTwips
) const
2809 const ScMergeAttr
* pMerge
= mrDoc
.GetAttr(nX
, nY
, nTabNo
, ATTR_MERGE
);
2810 SCCOL nCountX
= pMerge
->GetColMerge();
2813 rSizeXTwips
= mrDoc
.GetColWidth(nX
, nX
+ nCountX
- 1, nTabNo
);
2815 SCROW nCountY
= pMerge
->GetRowMerge();
2818 rSizeYTwips
= mrDoc
.GetRowHeight(nY
, nY
+ nCountY
- 1, nTabNo
);
2820 return (nCountX
> 1 || nCountY
> 1);
2823 void ScViewData::GetPosFromPixel( tools::Long nClickX
, tools::Long nClickY
, ScSplitPos eWhich
,
2824 SCCOL
& rPosX
, SCROW
& rPosY
,
2825 bool bTestMerge
, bool bRepair
, SCTAB nForTab
)
2827 // special handling of 0 is now in ScViewFunctionSet::SetCursorAtPoint
2831 bool bForCurTab
= (nForTab
== nTabNo
);
2832 if (!bForCurTab
&& (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size()))))
2834 SAL_WARN("sc.viewdata", "ScViewData::GetPosFromPixel : invalid nForTab = " << nForTab
);
2839 ScHSplitPos eHWhich
= WhichH(eWhich
);
2840 ScVSplitPos eVWhich
= WhichV(eWhich
);
2842 if (mrDoc
.IsLayoutRTL(nForTab
))
2844 if (!comphelper::LibreOfficeKit::isActive())
2846 // mirror horizontal position
2848 aScrSize
.setWidth( pView
->GetGridWidth(eHWhich
) );
2849 nClickX
= aScrSize
.Width() - 1 - nClickX
;
2853 SCCOL nStartPosX
= GetPosX(eHWhich
, nForTab
);
2854 SCROW nStartPosY
= GetPosY(eVWhich
, nForTab
);
2857 tools::Long nScrX
= 0;
2858 tools::Long nScrY
= 0;
2862 while (rPosX
<= mrDoc
.MaxCol() && nClickX
>= nScrX
)
2864 nScrX
+= ToPixel(mrDoc
.GetColWidth(rPosX
, nForTab
), nPPTX
);
2871 while ( rPosX
>0 && nClickX
< nScrX
)
2874 nScrX
-= ToPixel(mrDoc
.GetColWidth(rPosX
, nForTab
), nPPTX
);
2879 AddPixelsWhile(nScrY
, nClickY
, rPosY
, mrDoc
.MaxRow(), nPPTY
, &mrDoc
, nForTab
);
2882 /* TODO: could need some "SubPixelsWhileBackward" method */
2883 while ( rPosY
>0 && nClickY
< nScrY
)
2886 nScrY
-= ToPixel(mrDoc
.GetRowHeight(rPosY
, nForTab
), nPPTY
);
2891 if (rPosX
== nStartPosX
&& nClickX
> 0)
2894 aScrSize
.setWidth( pView
->GetGridWidth(eHWhich
) );
2895 if ( nClickX
> aScrSize
.Width() )
2898 if (rPosY
== nStartPosY
&& nClickY
> 0)
2901 aScrSize
.setHeight( pView
->GetGridHeight(eVWhich
) );
2902 if ( nClickY
> aScrSize
.Height() )
2906 rPosX
= std::clamp(rPosX
, SCCOL(0), mrDoc
.MaxCol());
2907 rPosY
= std::clamp(rPosY
, SCROW(0), mrDoc
.MaxRow());
2909 if (!(bTestMerge
&& bForCurTab
))
2912 // public method to adapt position
2913 SCCOL nOrigX
= rPosX
;
2914 SCROW nOrigY
= rPosY
;
2915 mrDoc
.SkipOverlapped(rPosX
, rPosY
, nTabNo
);
2916 bool bHOver
= (nOrigX
!= rPosX
);
2917 bool bVOver
= (nOrigY
!= rPosY
);
2919 if ( !(bRepair
&& ( bHOver
|| bVOver
)) )
2922 const ScMergeAttr
* pMerge
= mrDoc
.GetAttr(rPosX
, rPosY
, nTabNo
, ATTR_MERGE
);
2923 if ( ( bHOver
&& pMerge
->GetColMerge() <= 1 ) ||
2924 ( bVOver
&& pMerge
->GetRowMerge() <= 1 ) )
2926 OSL_FAIL("merge error found");
2928 mrDoc
.RemoveFlagsTab(0, 0, mrDoc
.MaxCol(), mrDoc
.MaxRow(), nTabNo
, ScMF::Hor
| ScMF::Ver
);
2929 SCCOL nEndCol
= mrDoc
.MaxCol();
2930 SCROW nEndRow
= mrDoc
.MaxRow();
2931 mrDoc
.ExtendMerge(0, 0, nEndCol
, nEndRow
, nTabNo
, true);
2933 pDocShell
->PostPaint(ScRange(0, 0, nTabNo
, mrDoc
.MaxCol(), mrDoc
.MaxRow(), nTabNo
),
2934 PaintPartFlags::Grid
);
2938 void ScViewData::GetMouseQuadrant( const Point
& rClickPos
, ScSplitPos eWhich
,
2939 SCCOL nPosX
, SCROW nPosY
, bool& rLeft
, bool& rTop
)
2941 bool bLayoutRTL
= mrDoc
.IsLayoutRTL(nTabNo
);
2942 tools::Long nLayoutSign
= bLayoutRTL
? -1 : 1;
2944 Point aCellStart
= GetScrPos( nPosX
, nPosY
, eWhich
, true );
2947 GetMergeSizePixel( nPosX
, nPosY
, nSizeX
, nSizeY
);
2948 rLeft
= ( rClickPos
.X() - aCellStart
.X() ) * nLayoutSign
<= nSizeX
/ 2;
2949 rTop
= rClickPos
.Y() - aCellStart
.Y() <= nSizeY
/ 2;
2952 void ScViewData::SetPosX( ScHSplitPos eWhich
, SCCOL nNewPosX
)
2954 // in the tiled rendering case, nPosX [the leftmost visible column] must be 0
2955 bool bIsTiledRendering
= comphelper::LibreOfficeKit::isActive();
2956 if (nNewPosX
!= 0 && !bIsTiledRendering
)
2958 SCCOL nOldPosX
= pThisTab
->nPosX
[eWhich
];
2959 tools::Long nTPosX
= pThisTab
->nTPosX
[eWhich
];
2960 tools::Long nPixPosX
= pThisTab
->nPixPosX
[eWhich
];
2962 if ( nNewPosX
> nOldPosX
)
2963 for ( i
=nOldPosX
; i
<nNewPosX
; i
++ )
2965 tools::Long nThis
= mrDoc
.GetColWidth(i
, nTabNo
);
2967 nPixPosX
-= ToPixel(sal::static_int_cast
<sal_uInt16
>(nThis
), nPPTX
);
2970 for ( i
=nNewPosX
; i
<nOldPosX
; i
++ )
2972 tools::Long nThis
= mrDoc
.GetColWidth(i
, nTabNo
);
2974 nPixPosX
+= ToPixel(sal::static_int_cast
<sal_uInt16
>(nThis
), nPPTX
);
2977 pThisTab
->nPosX
[eWhich
] = nNewPosX
;
2978 pThisTab
->nTPosX
[eWhich
] = nTPosX
;
2979 pThisTab
->nMPosX
[eWhich
] = o3tl::convert(nTPosX
, o3tl::Length::twip
, o3tl::Length::mm100
);
2980 pThisTab
->nPixPosX
[eWhich
] = nPixPosX
;
2984 pThisTab
->nPixPosX
[eWhich
] =
2985 pThisTab
->nTPosX
[eWhich
] =
2986 pThisTab
->nMPosX
[eWhich
] =
2987 pThisTab
->nPosX
[eWhich
] = 0;
2991 void ScViewData::SetPosY( ScVSplitPos eWhich
, SCROW nNewPosY
)
2993 // in the tiled rendering case, nPosY [the topmost visible row] must be 0
2994 bool bIsTiledRendering
= comphelper::LibreOfficeKit::isActive();
2995 if (nNewPosY
!= 0 && !bIsTiledRendering
)
2997 SCROW nOldPosY
= pThisTab
->nPosY
[eWhich
];
2998 tools::Long nTPosY
= pThisTab
->nTPosY
[eWhich
];
2999 tools::Long nPixPosY
= pThisTab
->nPixPosY
[eWhich
];
3000 SCROW i
, nHeightEndRow
;
3001 if ( nNewPosY
> nOldPosY
)
3002 for ( i
=nOldPosY
; i
<nNewPosY
; i
++ )
3004 tools::Long nThis
= mrDoc
.GetRowHeight(i
, nTabNo
, nullptr, &nHeightEndRow
);
3005 SCROW nRows
= std::min( nNewPosY
, nHeightEndRow
+ 1) - i
;
3007 nTPosY
-= nThis
* nRows
;
3008 nPixPosY
-= ToPixel(sal::static_int_cast
<sal_uInt16
>(nThis
), nPPTY
) * nRows
;
3011 for ( i
=nNewPosY
; i
<nOldPosY
; i
++ )
3013 tools::Long nThis
= mrDoc
.GetRowHeight(i
, nTabNo
, nullptr, &nHeightEndRow
);
3014 SCROW nRows
= std::min( nOldPosY
, nHeightEndRow
+ 1) - i
;
3016 nTPosY
+= nThis
* nRows
;
3017 nPixPosY
+= ToPixel(sal::static_int_cast
<sal_uInt16
>(nThis
), nPPTY
) * nRows
;
3020 pThisTab
->nPosY
[eWhich
] = nNewPosY
;
3021 pThisTab
->nTPosY
[eWhich
] = nTPosY
;
3022 pThisTab
->nMPosY
[eWhich
] = o3tl::convert(nTPosY
, o3tl::Length::twip
, o3tl::Length::mm100
);
3023 pThisTab
->nPixPosY
[eWhich
] = nPixPosY
;
3027 pThisTab
->nPixPosY
[eWhich
] =
3028 pThisTab
->nTPosY
[eWhich
] =
3029 pThisTab
->nMPosY
[eWhich
] =
3030 pThisTab
->nPosY
[eWhich
] = 0;
3034 void ScViewData::RecalcPixPos() // after zoom changes
3036 for (sal_uInt16 eWhich
=0; eWhich
<2; eWhich
++)
3038 tools::Long nPixPosX
= 0;
3039 SCCOL nPosX
= pThisTab
->nPosX
[eWhich
];
3040 for (SCCOL i
=0; i
<nPosX
; i
++)
3041 nPixPosX
-= ToPixel(mrDoc
.GetColWidth(i
, nTabNo
), nPPTX
);
3042 pThisTab
->nPixPosX
[eWhich
] = nPixPosX
;
3044 tools::Long nPixPosY
= 0;
3045 SCROW nPosY
= pThisTab
->nPosY
[eWhich
];
3046 tools::Long nRowHeight
= -1;
3047 SCROW nLastSameHeightRow
= -1;
3048 for (SCROW j
=0; j
<nPosY
; j
++)
3050 if(nLastSameHeightRow
< j
)
3051 nRowHeight
= ToPixel(mrDoc
.GetRowHeight(j
, nTabNo
, nullptr, &nLastSameHeightRow
), nPPTY
);
3052 nPixPosY
-= nRowHeight
;
3054 pThisTab
->nPixPosY
[eWhich
] = nPixPosY
;
3058 const MapMode
& ScViewData::GetLogicMode( ScSplitPos eWhich
)
3060 aLogicMode
.SetOrigin( Point( pThisTab
->nMPosX
[WhichH(eWhich
)],
3061 pThisTab
->nMPosY
[WhichV(eWhich
)] ) );
3065 const MapMode
& ScViewData::GetLogicMode()
3067 aLogicMode
.SetOrigin( Point() );
3071 void ScViewData::SetScreen( SCCOL nCol1
, SCROW nRow1
, SCCOL nCol2
, SCROW nRow2
)
3076 tools::Long nSizePix
;
3077 tools::Long nScrPosX
= 0;
3078 tools::Long nScrPosY
= 0;
3080 SetActivePart( SC_SPLIT_BOTTOMLEFT
);
3081 SetPosX( SC_SPLIT_LEFT
, nCol1
);
3082 SetPosY( SC_SPLIT_BOTTOM
, nRow1
);
3084 for (nCol
=nCol1
; nCol
<=nCol2
; nCol
++)
3086 nTSize
= mrDoc
.GetColWidth(nCol
, nTabNo
);
3089 nSizePix
= ToPixel( nTSize
, nPPTX
);
3090 nScrPosX
+= static_cast<sal_uInt16
>(nSizePix
);
3094 for (nRow
=nRow1
; nRow
<=nRow2
; nRow
++)
3096 nTSize
= mrDoc
.GetRowHeight(nRow
, nTabNo
);
3099 nSizePix
= ToPixel( nTSize
, nPPTY
);
3100 nScrPosY
+= static_cast<sal_uInt16
>(nSizePix
);
3104 aScrSize
= Size( nScrPosX
, nScrPosY
);
3107 void ScViewData::SetScreenPos( const Point
& rVisAreaStart
)
3115 nTwips
= o3tl::convert(rVisAreaStart
.X(), o3tl::Length::mm100
, o3tl::Length::twip
);
3116 if (mrDoc
.IsLayoutRTL(nTabNo
))
3122 nAdd
= static_cast<tools::Long
>(mrDoc
.GetColWidth(nX1
, nTabNo
));
3123 if (nSize
+ nAdd
<= nTwips
+ 1 && nX1
< mrDoc
.MaxCol())
3133 nTwips
= o3tl::convert(rVisAreaStart
.Y(), o3tl::Length::mm100
, o3tl::Length::twip
);
3138 nAdd
= static_cast<tools::Long
>(mrDoc
.GetRowHeight(nY1
, nTabNo
));
3139 if (nSize
+ nAdd
<= nTwips
+ 1 && nY1
< mrDoc
.MaxRow())
3148 SetActivePart( SC_SPLIT_BOTTOMLEFT
);
3149 SetPosX( SC_SPLIT_LEFT
, nX1
);
3150 SetPosY( SC_SPLIT_BOTTOM
, nY1
);
3156 void ScViewData::SetScreen( const tools::Rectangle
& rVisArea
)
3158 SetScreenPos( rVisArea
.TopLeft() );
3160 // here without GetOutputFactor(), since it's for the output into a Metafile
3162 aScrSize
= rVisArea
.GetSize();
3163 aScrSize
.setWidth(std::round(o3tl::convert( aScrSize
.Width(), o3tl::Length::mm100
, o3tl::Length::twip
) * ScGlobal::nScreenPPTX
));
3164 aScrSize
.setHeight(std::round(o3tl::convert( aScrSize
.Height(), o3tl::Length::mm100
, o3tl::Length::twip
) * ScGlobal::nScreenPPTY
));
3167 ScDocFunc
& ScViewData::GetDocFunc() const
3169 return pDocShell
->GetDocFunc();
3172 SfxBindings
& ScViewData::GetBindings()
3174 assert(pView
&& "GetBindings() without ViewShell");
3175 return pView
->GetViewFrame().GetBindings();
3178 SfxDispatcher
& ScViewData::GetDispatcher()
3180 assert(pView
&& "GetDispatcher() without ViewShell");
3181 return *pView
->GetViewFrame().GetDispatcher();
3184 ScMarkData
& ScViewData::GetMarkData()
3189 ScMarkData
& ScViewData::GetHighlightData()
3191 return maHighlightData
;
3194 const ScMarkData
& ScViewData::GetMarkData() const
3199 weld::Window
* ScViewData::GetDialogParent()
3201 assert(pView
&& "GetDialogParent() without ViewShell");
3202 return pView
->GetDialogParent();
3205 ScGridWindow
* ScViewData::GetActiveWin()
3207 assert(pView
&& "GetActiveWin() without View");
3208 return pView
->GetActiveWin();
3211 const ScGridWindow
* ScViewData::GetActiveWin() const
3213 assert(pView
&& "GetActiveWin() without View");
3214 return pView
->GetActiveWin();
3217 ScDrawView
* ScViewData::GetScDrawView()
3219 assert(pView
&& "GetScDrawView() without View");
3220 return pView
->GetScDrawView();
3223 bool ScViewData::IsMinimized() const
3225 assert(pView
&& "IsMinimized() without View");
3226 return pView
->IsMinimized();
3229 void ScViewData::UpdateScreenZoom( const Fraction
& rNewX
, const Fraction
& rNewY
)
3231 Fraction aOldX
= GetZoomX();
3232 Fraction aOldY
= GetZoomY();
3234 SetZoom( rNewX
, rNewY
, false );
3236 Fraction aWidth
= GetZoomX();
3237 aWidth
*= Fraction( aScrSize
.Width(),1 );
3240 Fraction aHeight
= GetZoomY();
3241 aHeight
*= Fraction( aScrSize
.Height(),1 );
3244 aScrSize
.setWidth( static_cast<tools::Long
>(aWidth
) );
3245 aScrSize
.setHeight( static_cast<tools::Long
>(aHeight
) );
3248 void ScViewData::CalcPPT()
3250 double nOldPPTX
= nPPTX
;
3251 double nOldPPTY
= nPPTY
;
3252 nPPTX
= ScGlobal::nScreenPPTX
* static_cast<double>(GetZoomX());
3254 nPPTX
= nPPTX
/ pDocShell
->GetOutputFactor(); // Factor is printer to screen
3255 nPPTY
= ScGlobal::nScreenPPTY
* static_cast<double>(GetZoomY());
3257 // if detective objects are present,
3258 // try to adjust horizontal scale so the most common column width has minimal rounding errors,
3259 // to avoid differences between cell and drawing layer output
3261 if (mrDoc
.HasDetectiveObjects(nTabNo
))
3265 mrDoc
.GetTableArea(nTabNo
, nEndCol
, nDummy
);
3267 nEndCol
= 20; // same end position as when determining draw scale
3269 sal_uInt16 nTwips
= mrDoc
.GetCommonWidth(nEndCol
, nTabNo
);
3272 double fOriginal
= nTwips
* nPPTX
;
3273 if ( fOriginal
< static_cast<double>(nEndCol
) )
3275 // if one column is smaller than the column count,
3276 // rounding errors are likely to add up to a whole column.
3278 double fRounded
= ::rtl::math::approxFloor( fOriginal
+ 0.5 );
3279 if ( fRounded
> 0.0 )
3281 double fScale
= fRounded
/ fOriginal
+ 1E-6;
3282 if ( fScale
>= 0.9 && fScale
<= 1.1 )
3289 if (!comphelper::LibreOfficeKit::isActive())
3292 SCTAB nTabCount
= maTabData
.size();
3293 bool bResetWidths
= (nPPTX
!= nOldPPTX
);
3294 bool bResetHeights
= (nPPTY
!= nOldPPTY
);
3295 for (SCTAB nTabIdx
= 0; nTabIdx
< nTabCount
; ++nTabIdx
)
3297 if (!maTabData
[nTabIdx
])
3301 if (auto* pWHelper
= GetLOKWidthHelper(nTabIdx
))
3302 pWHelper
->invalidateByPosition(0L);
3305 if (auto* pHHelper
= GetLOKHeightHelper(nTabIdx
))
3306 pHHelper
->invalidateByPosition(0L);
3310 #define SC_OLD_TABSEP '/'
3311 #define SC_NEW_TABSEP '+'
3313 void ScViewData::WriteUserData(OUString
& rData
)
3315 // nZoom (until 364v) or nZoom/nPageZoom/bPageMode (from 364w)
3317 // Tab control width
3319 // CursorX/CursorY/HSplitMode/VSplitMode/HSplitPos/VSplitPos/SplitActive/
3320 // PosX[left]/PosX[right]/PosY[top]/PosY[bottom]
3321 // when rows bigger than 8192, "+" instead of "/"
3323 sal_uInt16 nZoom
= static_cast<sal_uInt16
>(tools::Long(pThisTab
->aZoomY
* 100));
3324 rData
= OUString::number( nZoom
) + "/";
3325 nZoom
= static_cast<sal_uInt16
>(tools::Long(pThisTab
->aPageZoomY
* 100));
3326 rData
+= OUString::number( nZoom
) + "/";
3332 rData
+= ";" + OUString::number( nTabNo
) + ";" + TAG_TABBARWIDTH
+
3333 OUString::number( pView
->GetTabBarWidth() );
3335 SCTAB nTabCount
= mrDoc
.GetTableCount();
3336 for (SCTAB i
=0; i
<nTabCount
; i
++)
3338 rData
+= ";"; // Numbering must not get mixed up under any circumstances
3339 if (i
< static_cast<SCTAB
>(maTabData
.size()) && maTabData
[i
])
3341 OUString
cTabSep(SC_OLD_TABSEP
); // like 3.1
3342 if ( maTabData
[i
]->nCurY
> MAXROW_30
||
3343 maTabData
[i
]->nPosY
[0] > MAXROW_30
|| maTabData
[i
]->nPosY
[1] > MAXROW_30
||
3344 ( maTabData
[i
]->eVSplitMode
== SC_SPLIT_FIX
&&
3345 maTabData
[i
]->nFixPosY
> MAXROW_30
) )
3347 cTabSep
= OUStringChar(SC_NEW_TABSEP
); // in order to not kill a 3.1-version
3350 rData
+= OUString::number( maTabData
[i
]->nCurX
) + cTabSep
+
3351 OUString::number( maTabData
[i
]->nCurY
) + cTabSep
+
3352 OUString::number( maTabData
[i
]->eHSplitMode
) + cTabSep
+
3353 OUString::number( maTabData
[i
]->eVSplitMode
) + cTabSep
;
3354 if ( maTabData
[i
]->eHSplitMode
== SC_SPLIT_FIX
)
3355 rData
+= OUString::number( maTabData
[i
]->nFixPosX
);
3357 rData
+= OUString::number( maTabData
[i
]->nHSplitPos
);
3359 if ( maTabData
[i
]->eVSplitMode
== SC_SPLIT_FIX
)
3360 rData
+= OUString::number( maTabData
[i
]->nFixPosY
);
3362 rData
+= OUString::number( maTabData
[i
]->nVSplitPos
);
3364 OUString::number( maTabData
[i
]->eWhichActive
) + cTabSep
+
3365 OUString::number( maTabData
[i
]->nPosX
[0] ) + cTabSep
+
3366 OUString::number( maTabData
[i
]->nPosX
[1] ) + cTabSep
+
3367 OUString::number( maTabData
[i
]->nPosY
[0] ) + cTabSep
+
3368 OUString::number( maTabData
[i
]->nPosY
[1] );
3373 void ScViewData::ReadUserData(std::u16string_view rData
)
3375 if (rData
.empty()) // empty string on "reload"
3376 return; // then exit without assertion
3378 if ( comphelper::string::getTokenCount(rData
, ';') <= 2 )
3380 // when reload, in page preview, the preview UserData may have been left intact.
3381 // we don't want the zoom from the page preview here.
3382 OSL_FAIL("ReadUserData: This is not my data");
3386 sal_Int32 nMainIdx
{0};
3389 std::u16string_view aZoomStr
= o3tl::getToken(rData
, 0, ';', nMainIdx
); // Zoom/PageZoom/Mode
3390 sal_Unicode cMode
= o3tl::getToken(aZoomStr
, 2, '/', nIdx
)[0]; // 0 or "0"/"1"
3391 SetPagebreakMode( cMode
== '1' );
3392 // SetPagebreakMode must always be called due to CalcPPT / RecalcPixPos()
3394 // sheet may have become invalid (for instance last version):
3395 SCTAB nNewTab
= static_cast<SCTAB
>(o3tl::toUInt32(o3tl::getToken(rData
, 0, ';', nMainIdx
)));
3396 if (mrDoc
.HasTable(nNewTab
))
3399 // if available, get tab bar width:
3400 const sal_Int32 nMainIdxRef
{nMainIdx
};
3401 std::u16string_view aTabOpt
= o3tl::getToken(rData
, 0, ';', nMainIdx
);
3403 std::u16string_view aRest
;
3404 if (o3tl::starts_with(aTabOpt
, TAG_TABBARWIDTH
, &aRest
))
3406 pView
->SetTabBarWidth(o3tl::toInt32(aRest
));
3410 // Tab bar width not specified, token to be processed again
3411 nMainIdx
= nMainIdxRef
;
3416 while ( nMainIdx
>0 )
3418 aTabOpt
= o3tl::getToken(rData
, 0, ';', nMainIdx
);
3419 EnsureTabDataSize(nPos
+ 1);
3420 if (!maTabData
[nPos
])
3421 maTabData
[nPos
].reset(new ScViewDataTable(&mrDoc
));
3423 sal_Unicode cTabSep
= 0;
3424 if (comphelper::string::getTokenCount(aTabOpt
, SC_OLD_TABSEP
) >= 11)
3425 cTabSep
= SC_OLD_TABSEP
;
3426 else if (comphelper::string::getTokenCount(aTabOpt
, SC_NEW_TABSEP
) >= 11)
3427 cTabSep
= SC_NEW_TABSEP
;
3428 // '+' is only allowed, if we can deal with rows > 8192
3433 maTabData
[nPos
]->nCurX
= mrDoc
.SanitizeCol(static_cast<SCCOL
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
))));
3434 maTabData
[nPos
]->nCurY
= mrDoc
.SanitizeRow(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3435 maTabData
[nPos
]->eHSplitMode
= static_cast<ScSplitMode
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3436 maTabData
[nPos
]->eVSplitMode
= static_cast<ScSplitMode
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3438 sal_Int32 nTmp
= o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
));
3439 if ( maTabData
[nPos
]->eHSplitMode
== SC_SPLIT_FIX
)
3441 maTabData
[nPos
]->nFixPosX
= mrDoc
.SanitizeCol(static_cast<SCCOL
>(nTmp
));
3445 maTabData
[nPos
]->nHSplitPos
= nTmp
;
3447 nTmp
= o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
));
3448 if ( maTabData
[nPos
]->eVSplitMode
== SC_SPLIT_FIX
)
3450 maTabData
[nPos
]->nFixPosY
= mrDoc
.SanitizeRow(nTmp
);
3454 maTabData
[nPos
]->nVSplitPos
= nTmp
;
3456 maTabData
[nPos
]->eWhichActive
= static_cast<ScSplitPos
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3457 maTabData
[nPos
]->nPosX
[0] = mrDoc
.SanitizeCol(static_cast<SCCOL
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
))));
3458 maTabData
[nPos
]->nPosX
[1] = mrDoc
.SanitizeCol(static_cast<SCCOL
>(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
))));
3459 maTabData
[nPos
]->nPosY
[0] = mrDoc
.SanitizeRow(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3460 maTabData
[nPos
]->nPosY
[1] = mrDoc
.SanitizeRow(o3tl::toInt32(o3tl::getToken(aTabOpt
, 0, cTabSep
, nIdx
)));
3462 maTabData
[nPos
]->eWhichActive
= maTabData
[nPos
]->SanitizeWhichActive();
3470 void ScViewData::WriteExtOptions( ScExtDocOptions
& rDocOpt
) const
3472 // *** Fill extended document data for export filters ***
3474 // document settings
3475 ScExtDocSettings
& rDocSett
= rDocOpt
.GetDocSettings();
3478 rDocSett
.mnDisplTab
= GetTabNo();
3480 // width of the tabbar, relative to frame window width
3481 rDocSett
.mfTabBarWidth
= pView
->GetPendingRelTabBarWidth();
3482 if( rDocSett
.mfTabBarWidth
< 0.0 )
3483 rDocSett
.mfTabBarWidth
= ScTabView::GetRelTabBarWidth();
3485 bool bLOKActive
= comphelper::LibreOfficeKit::isActive();
3488 for( SCTAB nTab
= 0; nTab
< static_cast<SCTAB
>(maTabData
.size()); ++nTab
)
3490 if( const ScViewDataTable
* pViewTab
= maTabData
[ nTab
].get() )
3492 ScExtTabSettings
& rTabSett
= rDocOpt
.GetOrCreateTabSettings( nTab
);
3495 ScSplitMode eExHSplit
= pViewTab
->eHSplitMode
;
3496 ScSplitMode eExVSplit
= pViewTab
->eVSplitMode
;
3497 SCCOL nExFixPosX
= pViewTab
->nFixPosX
;
3498 SCROW nExFixPosY
= pViewTab
->nFixPosY
;
3499 tools::Long nExHSplitPos
= pViewTab
->nHSplitPos
;
3500 tools::Long nExVSplitPos
= pViewTab
->nVSplitPos
;
3504 OverrideWithLOKFreeze(eExHSplit
, eExVSplit
,
3505 nExFixPosX
, nExFixPosY
,
3506 nExHSplitPos
, nExVSplitPos
, nTab
);
3509 bool bHSplit
= eExHSplit
!= SC_SPLIT_NONE
;
3510 bool bVSplit
= eExVSplit
!= SC_SPLIT_NONE
;
3511 bool bRealSplit
= (eExHSplit
== SC_SPLIT_NORMAL
) || (eExVSplit
== SC_SPLIT_NORMAL
);
3512 bool bFrozen
= (eExHSplit
== SC_SPLIT_FIX
) || (eExVSplit
== SC_SPLIT_FIX
);
3513 OSL_ENSURE( !bRealSplit
|| !bFrozen
, "ScViewData::WriteExtOptions - split and freeze in same sheet" );
3514 rTabSett
.mbFrozenPanes
= !bRealSplit
&& bFrozen
;
3516 // split and freeze position
3517 rTabSett
.maSplitPos
= Point( 0, 0 );
3518 rTabSett
.maFreezePos
.Set( 0, 0, nTab
);
3521 Point
& rSplitPos
= rTabSett
.maSplitPos
;
3522 rSplitPos
= Point( bHSplit
? nExHSplitPos
: 0, bVSplit
? nExVSplitPos
: 0 );
3523 rSplitPos
= Application::GetDefaultDevice()->PixelToLogic( rSplitPos
, MapMode( MapUnit::MapTwip
) );
3525 rSplitPos
.setX( static_cast<tools::Long
>(static_cast<double>(rSplitPos
.X()) / pDocShell
->GetOutputFactor()) );
3529 if( bHSplit
) rTabSett
.maFreezePos
.SetCol( nExFixPosX
);
3530 if( bVSplit
) rTabSett
.maFreezePos
.SetRow( nExFixPosY
);
3533 // first visible cell in top-left and additional panes
3534 rTabSett
.maFirstVis
.Set( pViewTab
->nPosX
[ SC_SPLIT_LEFT
], pViewTab
->nPosY
[ bVSplit
? SC_SPLIT_TOP
: SC_SPLIT_BOTTOM
], nTab
);
3535 rTabSett
.maSecondVis
.Set( pViewTab
->nPosX
[ SC_SPLIT_RIGHT
], pViewTab
->nPosY
[ SC_SPLIT_BOTTOM
], nTab
);
3538 switch( pViewTab
->eWhichActive
)
3540 // no horizontal split -> always use left panes
3541 // no vertical split -> always use top panes
3542 case SC_SPLIT_TOPLEFT
:
3543 rTabSett
.meActivePane
= SCEXT_PANE_TOPLEFT
;
3545 case SC_SPLIT_TOPRIGHT
:
3546 rTabSett
.meActivePane
= bHSplit
? SCEXT_PANE_TOPRIGHT
: SCEXT_PANE_TOPLEFT
;
3548 case SC_SPLIT_BOTTOMLEFT
:
3549 rTabSett
.meActivePane
= bVSplit
? SCEXT_PANE_BOTTOMLEFT
: SCEXT_PANE_TOPLEFT
;
3551 case SC_SPLIT_BOTTOMRIGHT
:
3552 rTabSett
.meActivePane
= bHSplit
?
3553 (bVSplit
? SCEXT_PANE_BOTTOMRIGHT
: SCEXT_PANE_TOPRIGHT
) :
3554 (bVSplit
? SCEXT_PANE_BOTTOMLEFT
: SCEXT_PANE_TOPLEFT
);
3559 rTabSett
.maCursor
.Set( pViewTab
->nCurX
, pViewTab
->nCurY
, nTab
);
3561 // sheet selection and selected ranges
3562 const ScMarkData
& rMarkData
= GetMarkData();
3563 rTabSett
.mbSelected
= rMarkData
.GetTableSelect( nTab
);
3564 rMarkData
.FillRangeListWithMarks( &rTabSett
.maSelection
, true );
3565 rTabSett
.mbShowGrid
= pViewTab
->bShowGrid
;
3567 // view mode and zoom
3568 rTabSett
.mbPageMode
= bPagebreak
;
3569 rTabSett
.mnNormalZoom
= static_cast< tools::Long
>( pViewTab
->aZoomY
* Fraction( 100.0 ) );
3570 rTabSett
.mnPageZoom
= static_cast< tools::Long
>( pViewTab
->aPageZoomY
* Fraction( 100.0 ) );
3575 void ScViewData::ReadExtOptions( const ScExtDocOptions
& rDocOpt
)
3577 // *** Get extended document data from import filters ***
3579 if( !rDocOpt
.IsChanged() ) return;
3581 // document settings
3582 const ScExtDocSettings
& rDocSett
= rDocOpt
.GetDocSettings();
3585 SetTabNo( rDocSett
.mnDisplTab
);
3587 /* Width of the tabbar, relative to frame window width. We do not have the
3588 correct width of the frame window here -> store in ScTabView, which sets
3589 the size in the next resize. */
3590 pView
->SetPendingRelTabBarWidth( rDocSett
.mfTabBarWidth
);
3593 SCTAB nLastTab
= rDocOpt
.GetLastTab();
3594 if (static_cast<SCTAB
>(maTabData
.size()) <= nLastTab
)
3595 maTabData
.resize(nLastTab
+1);
3597 for( SCTAB nTab
= 0; nTab
< static_cast<SCTAB
>(maTabData
.size()); ++nTab
)
3599 if( const ScExtTabSettings
* pTabSett
= rDocOpt
.GetTabSettings( nTab
) )
3601 if( !maTabData
[ nTab
] )
3602 maTabData
[nTab
].reset(new ScViewDataTable(&mrDoc
));
3604 const ScExtTabSettings
& rTabSett
= *pTabSett
;
3605 ScViewDataTable
& rViewTab
= *maTabData
[ nTab
];
3607 // split mode initialization
3608 bool bFrozen
= rTabSett
.mbFrozenPanes
;
3609 bool bHSplit
= bFrozen
? (rTabSett
.maFreezePos
.Col() > 0) : (rTabSett
.maSplitPos
.X() > 0);
3610 bool bVSplit
= bFrozen
? (rTabSett
.maFreezePos
.Row() > 0) : (rTabSett
.maSplitPos
.Y() > 0);
3612 // first visible cell of top-left pane and additional panes
3613 if (rTabSett
.maFirstVis
.IsValid())
3615 rViewTab
.nPosX
[ SC_SPLIT_LEFT
] = rTabSett
.maFirstVis
.Col();
3616 rViewTab
.nPosY
[ bVSplit
? SC_SPLIT_TOP
: SC_SPLIT_BOTTOM
] = rTabSett
.maFirstVis
.Row();
3619 if (rTabSett
.maSecondVis
.IsValid())
3622 rViewTab
.nPosX
[ SC_SPLIT_RIGHT
] = rTabSett
.maSecondVis
.Col();
3624 rViewTab
.nPosY
[ SC_SPLIT_BOTTOM
] = rTabSett
.maSecondVis
.Row();
3627 // split mode, split and freeze position
3628 rViewTab
.eHSplitMode
= rViewTab
.eVSplitMode
= SC_SPLIT_NONE
;
3629 rViewTab
.nHSplitPos
= rViewTab
.nVSplitPos
= 0;
3630 rViewTab
.nFixPosX
= 0;
3631 rViewTab
.nFixPosY
= 0;
3636 rViewTab
.eHSplitMode
= SC_SPLIT_FIX
;
3637 rViewTab
.nFixPosX
= rTabSett
.maFreezePos
.Col();
3642 rViewTab
.eVSplitMode
= SC_SPLIT_FIX
;
3643 rViewTab
.nFixPosY
= rTabSett
.maFreezePos
.Row();
3649 Point aPixel
= Application::GetDefaultDevice()->LogicToPixel(
3650 rTabSett
.maSplitPos
, MapMode( MapUnit::MapTwip
) ); //! Zoom?
3651 // the test for use of printer metrics for text formatting here
3652 // effectively results in the nFactor = 1.0 regardless of the Option setting.
3653 if (pDocShell
&& ScModule::get()->GetInputOptions().GetTextWysiwyg())
3655 double nFactor
= pDocShell
->GetOutputFactor();
3656 aPixel
.setX( static_cast<tools::Long
>( aPixel
.X() * nFactor
+ 0.5 ) );
3659 bHSplit
= bHSplit
&& aPixel
.X() > 0;
3660 bVSplit
= bVSplit
&& aPixel
.Y() > 0;
3663 rViewTab
.eHSplitMode
= SC_SPLIT_NORMAL
;
3664 rViewTab
.nHSplitPos
= aPixel
.X();
3668 rViewTab
.eVSplitMode
= SC_SPLIT_NORMAL
;
3669 rViewTab
.nVSplitPos
= aPixel
.Y();
3674 ScSplitPos ePos
= SC_SPLIT_BOTTOMLEFT
;
3675 switch( rTabSett
.meActivePane
)
3677 // no horizontal split -> always use left panes
3678 // no vertical split -> always use *bottom* panes
3679 case SCEXT_PANE_TOPLEFT
:
3680 ePos
= bVSplit
? SC_SPLIT_TOPLEFT
: SC_SPLIT_BOTTOMLEFT
;
3682 case SCEXT_PANE_TOPRIGHT
:
3684 (bVSplit
? SC_SPLIT_TOPRIGHT
: SC_SPLIT_BOTTOMRIGHT
) :
3685 (bVSplit
? SC_SPLIT_TOPLEFT
: SC_SPLIT_BOTTOMLEFT
);
3687 case SCEXT_PANE_BOTTOMLEFT
:
3688 ePos
= SC_SPLIT_BOTTOMLEFT
;
3690 case SCEXT_PANE_BOTTOMRIGHT
:
3691 ePos
= bHSplit
? SC_SPLIT_BOTTOMRIGHT
: SC_SPLIT_BOTTOMLEFT
;
3694 rViewTab
.eWhichActive
= ePos
;
3697 const ScAddress
& rCursor
= rTabSett
.maCursor
;
3698 if( rCursor
.IsValid() )
3700 rViewTab
.nCurX
= rCursor
.Col();
3701 rViewTab
.nCurY
= rCursor
.Row();
3704 // sheet selection and selected ranges
3705 ScMarkData
& rMarkData
= GetMarkData();
3706 rMarkData
.SelectTable( nTab
, rTabSett
.mbSelected
);
3708 // zoom for each sheet
3709 if( rTabSett
.mnNormalZoom
)
3710 rViewTab
.aZoomX
= rViewTab
.aZoomY
= Fraction( rTabSett
.mnNormalZoom
, 100 );
3711 if( rTabSett
.mnPageZoom
)
3712 rViewTab
.aPageZoomX
= rViewTab
.aPageZoomY
= Fraction( rTabSett
.mnPageZoom
, 100 );
3714 rViewTab
.bShowGrid
= rTabSett
.mbShowGrid
;
3716 // get some settings from displayed Excel sheet, set at Calc document
3717 if( nTab
== GetTabNo() )
3719 // view mode and default zoom (for new sheets) from current sheet
3720 if( rTabSett
.mnNormalZoom
)
3721 aDefZoomX
= aDefZoomY
= Fraction( rTabSett
.mnNormalZoom
, 100L );
3722 if( rTabSett
.mnPageZoom
)
3723 aDefPageZoomX
= aDefPageZoomY
= Fraction( rTabSett
.mnPageZoom
, 100L );
3724 /* #i46820# set pagebreak mode via SetPagebreakMode(), this will
3725 update map modes that are needed to draw text correctly. */
3726 SetPagebreakMode( rTabSett
.mbPageMode
);
3731 if (comphelper::LibreOfficeKit::isActive())
3732 DeriveLOKFreezeAllSheets();
3734 // RecalcPixPos or so - also nMPos - also for ReadUserData ??!?!
3737 void ScViewData::WriteUserDataSequence(uno::Sequence
<beans::PropertyValue
>& rSettings
) const
3739 rSettings
.realloc(SC_VIEWSETTINGS_COUNT
);
3740 // + 1, because we have to put the view id in the sequence
3741 beans::PropertyValue
* pSettings
= rSettings
.getArray();
3743 sal_uInt16
nViewID(pView
->GetViewFrame().GetCurViewId());
3744 pSettings
[SC_VIEW_ID
].Name
= SC_VIEWID
;
3745 pSettings
[SC_VIEW_ID
].Value
<<= SC_VIEW
+ OUString::number(nViewID
);
3747 uno::Reference
<container::XNameContainer
> xNameContainer
=
3748 document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
3749 for (SCTAB nTab
=0; nTab
<static_cast<SCTAB
>(maTabData
.size()); nTab
++)
3751 if (maTabData
[nTab
])
3753 uno::Sequence
<beans::PropertyValue
> aTableViewSettings
;
3754 maTabData
[nTab
]->WriteUserDataSequence(aTableViewSettings
, *this, nTab
);
3756 GetDocument().GetName( nTab
, sTabName
);
3759 xNameContainer
->insertByName(sTabName
, uno::Any(aTableViewSettings
));
3761 //#101739#; two tables with the same name are possible
3762 catch ( container::ElementExistException
& )
3764 OSL_FAIL("seems there are two tables with the same name");
3766 catch ( uno::RuntimeException
& )
3768 OSL_FAIL("something went wrong");
3772 pSettings
[SC_TABLE_VIEWSETTINGS
].Name
= SC_TABLES
;
3773 pSettings
[SC_TABLE_VIEWSETTINGS
].Value
<<= xNameContainer
;
3776 GetDocument().GetName( nTabNo
, sName
);
3777 pSettings
[SC_ACTIVE_TABLE
].Name
= SC_ACTIVETABLE
;
3778 pSettings
[SC_ACTIVE_TABLE
].Value
<<= sName
;
3779 pSettings
[SC_HORIZONTAL_SCROLL_BAR_WIDTH
].Name
= SC_HORIZONTALSCROLLBARWIDTH
;
3780 pSettings
[SC_HORIZONTAL_SCROLL_BAR_WIDTH
].Value
<<= sal_Int32(pView
->GetTabBarWidth());
3781 sal_Int32 nZoomValue
= tools::Long(pThisTab
->aZoomY
* 100);
3782 sal_Int32 nPageZoomValue
= tools::Long(pThisTab
->aPageZoomY
* 100);
3783 pSettings
[SC_ZOOM_TYPE
].Name
= SC_ZOOMTYPE
;
3784 pSettings
[SC_ZOOM_TYPE
].Value
<<= sal_Int16(pThisTab
->eZoomType
);
3785 pSettings
[SC_ZOOM_VALUE
].Name
= SC_ZOOMVALUE
;
3786 pSettings
[SC_ZOOM_VALUE
].Value
<<= nZoomValue
;
3787 pSettings
[SC_PAGE_VIEW_ZOOM_VALUE
].Name
= SC_PAGEVIEWZOOMVALUE
;
3788 pSettings
[SC_PAGE_VIEW_ZOOM_VALUE
].Value
<<= nPageZoomValue
;
3789 pSettings
[SC_PAGE_BREAK_PREVIEW
].Name
= SC_SHOWPAGEBREAKPREVIEW
;
3790 pSettings
[SC_PAGE_BREAK_PREVIEW
].Value
<<= bPagebreak
;
3792 pSettings
[SC_SHOWZERO
].Name
= SC_UNO_SHOWZERO
;
3793 pSettings
[SC_SHOWZERO
].Value
<<= maOptions
.GetOption(VOPT_NULLVALS
);
3794 pSettings
[SC_SHOWNOTES
].Name
= SC_UNO_SHOWNOTES
;
3795 pSettings
[SC_SHOWNOTES
].Value
<<= maOptions
.GetOption(VOPT_NOTES
);
3796 pSettings
[SC_SHOWNOTEAUTHOR
].Name
= SC_UNO_SHOWNOTEAUTHOR
;
3797 pSettings
[SC_SHOWNOTEAUTHOR
].Value
<<= maOptions
.GetOption(VOPT_NOTEAUTHOR
);
3798 pSettings
[SC_SHOWFORMULASMARKS
].Name
= SC_UNO_SHOWFORMULASMARKS
;
3799 pSettings
[SC_SHOWFORMULASMARKS
].Value
<<= maOptions
.GetOption(VOPT_FORMULAS_MARKS
);
3800 pSettings
[SC_SHOWGRID
].Name
= SC_UNO_SHOWGRID
;
3801 pSettings
[SC_SHOWGRID
].Value
<<= maOptions
.GetOption(VOPT_GRID
);
3802 pSettings
[SC_GRIDCOLOR
].Name
= SC_UNO_GRIDCOLOR
;
3803 OUString aColorName
;
3804 Color aColor
= maOptions
.GetGridColor(&aColorName
);
3805 pSettings
[SC_GRIDCOLOR
].Value
<<= aColor
;
3806 pSettings
[SC_SHOWPAGEBR
].Name
= SC_UNO_SHOWPAGEBR
;
3807 pSettings
[SC_SHOWPAGEBR
].Value
<<= maOptions
.GetOption(VOPT_PAGEBREAKS
);
3808 pSettings
[SC_COLROWHDR
].Name
= SC_UNO_COLROWHDR
;
3809 pSettings
[SC_COLROWHDR
].Value
<<= maOptions
.GetOption(VOPT_HEADER
);
3810 pSettings
[SC_SHEETTABS
].Name
= SC_UNO_SHEETTABS
;
3811 pSettings
[SC_SHEETTABS
].Value
<<= maOptions
.GetOption(VOPT_TABCONTROLS
);
3812 pSettings
[SC_OUTLSYMB
].Name
= SC_UNO_OUTLSYMB
;
3813 pSettings
[SC_OUTLSYMB
].Value
<<= maOptions
.GetOption(VOPT_OUTLINER
);
3814 pSettings
[SC_VALUE_HIGHLIGHTING
].Name
= SC_UNO_VALUEHIGH
;
3815 pSettings
[SC_VALUE_HIGHLIGHTING
].Value
<<= maOptions
.GetOption(VOPT_SYNTAX
);
3816 pSettings
[SC_FORMULA_BAR_HEIGHT
].Name
= SC_FORMULABARHEIGHT
;
3817 pSettings
[SC_FORMULA_BAR_HEIGHT
].Value
<<= GetFormulaBarLines();;
3819 const ScGridOptions
& aGridOpt
= maOptions
.GetGridOptions();
3820 pSettings
[SC_SNAPTORASTER
].Name
= SC_UNO_SNAPTORASTER
;
3821 pSettings
[SC_SNAPTORASTER
].Value
<<= aGridOpt
.GetUseGridSnap();
3822 pSettings
[SC_RASTERVIS
].Name
= SC_UNO_RASTERVIS
;
3823 pSettings
[SC_RASTERVIS
].Value
<<= aGridOpt
.GetGridVisible();
3824 pSettings
[SC_RASTERRESX
].Name
= SC_UNO_RASTERRESX
;
3825 pSettings
[SC_RASTERRESX
].Value
<<= static_cast<sal_Int32
>(aGridOpt
.GetFieldDrawX());
3826 pSettings
[SC_RASTERRESY
].Name
= SC_UNO_RASTERRESY
;
3827 pSettings
[SC_RASTERRESY
].Value
<<= static_cast<sal_Int32
>(aGridOpt
.GetFieldDrawY());
3828 pSettings
[SC_RASTERSUBX
].Name
= SC_UNO_RASTERSUBX
;
3829 pSettings
[SC_RASTERSUBX
].Value
<<= static_cast<sal_Int32
>(aGridOpt
.GetFieldDivisionX());
3830 pSettings
[SC_RASTERSUBY
].Name
= SC_UNO_RASTERSUBY
;
3831 pSettings
[SC_RASTERSUBY
].Value
<<= static_cast<sal_Int32
>(aGridOpt
.GetFieldDivisionY());
3832 pSettings
[SC_RASTERSYNC
].Name
= SC_UNO_RASTERSYNC
;
3833 pSettings
[SC_RASTERSYNC
].Value
<<= aGridOpt
.GetSynchronize();
3835 // Common SdrModel processing
3836 GetDocument().GetDrawLayer()->WriteUserDataSequence(rSettings
);
3839 void ScViewData::ReadUserDataSequence(const uno::Sequence
<beans::PropertyValue
>& rSettings
)
3841 std::vector
<bool> aHasZoomVect( GetDocument().GetTableCount(), false );
3843 sal_Int32
nTemp32(0);
3844 sal_Int16
nTemp16(0);
3845 sal_Int16
nFormulaBarLineCount(0);
3846 bool bPageMode(false);
3848 EnsureTabDataSize(GetDocument().GetTableCount());
3850 for (const auto& rSetting
: rSettings
)
3852 // SC_VIEWID has to parse and use by mba
3853 OUString
sName(rSetting
.Name
);
3854 if (sName
== SC_TABLES
)
3856 uno::Reference
<container::XNameContainer
> xNameContainer
;
3857 if ((rSetting
.Value
>>= xNameContainer
) && xNameContainer
->hasElements())
3859 const uno::Sequence
< OUString
> aNames(xNameContainer
->getElementNames());
3860 for (const OUString
& sTabName
: aNames
)
3863 if (GetDocument().GetTable(sTabName
, nTab
))
3865 uno::Any aAny
= xNameContainer
->getByName(sTabName
);
3866 uno::Sequence
<beans::PropertyValue
> aTabSettings
;
3867 if (aAny
>>= aTabSettings
)
3869 EnsureTabDataSize(nTab
+ 1);
3870 if (!maTabData
[nTab
])
3871 maTabData
[nTab
].reset(new ScViewDataTable(&mrDoc
));
3873 bool bHasZoom
= false;
3874 maTabData
[nTab
]->ReadUserDataSequence(aTabSettings
, *this, nTab
, bHasZoom
);
3875 aHasZoomVect
[nTab
] = bHasZoom
;
3881 else if (sName
== SC_ACTIVETABLE
)
3884 if(rSetting
.Value
>>= sTabName
)
3887 if (GetDocument().GetTable(sTabName
, nTab
))
3891 else if (sName
== SC_HORIZONTALSCROLLBARWIDTH
)
3893 if (rSetting
.Value
>>= nTemp32
)
3894 pView
->SetTabBarWidth(nTemp32
);
3896 else if (sName
== SC_RELHORIZONTALTABBARWIDTH
)
3898 double fWidth
= 0.0;
3899 if (rSetting
.Value
>>= fWidth
)
3900 pView
->SetPendingRelTabBarWidth( fWidth
);
3902 else if (sName
== SC_ZOOMTYPE
)
3904 if (rSetting
.Value
>>= nTemp16
)
3905 eDefZoomType
= SvxZoomType(nTemp16
);
3907 else if (sName
== SC_ZOOMVALUE
)
3909 if (rSetting
.Value
>>= nTemp32
)
3911 Fraction
aZoom(nTemp32
, 100);
3912 aDefZoomX
= aDefZoomY
= aZoom
;
3915 else if (sName
== SC_PAGEVIEWZOOMVALUE
)
3917 if (rSetting
.Value
>>= nTemp32
)
3919 Fraction
aZoom(nTemp32
, 100);
3920 aDefPageZoomX
= aDefPageZoomY
= aZoom
;
3923 else if (sName
== SC_FORMULABARHEIGHT
)
3925 if (rSetting
.Value
>>= nFormulaBarLineCount
)
3927 SetFormulaBarLines(nFormulaBarLineCount
);
3928 // Notify formula bar about changed lines
3929 ScInputHandler
* pInputHdl
= ScModule::get()->GetInputHdl();
3932 ScInputWindow
* pInputWin
= pInputHdl
->GetInputWindow();
3934 pInputWin
->NumLinesChanged();
3938 else if (sName
== SC_SHOWPAGEBREAKPREVIEW
)
3939 bPageMode
= ScUnoHelpFunctions::GetBoolFromAny( rSetting
.Value
);
3940 else if ( sName
== SC_UNO_SHOWZERO
)
3941 maOptions
.SetOption(VOPT_NULLVALS
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3942 else if ( sName
== SC_UNO_SHOWNOTES
)
3943 maOptions
.SetOption(VOPT_NOTES
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3944 else if ( sName
== SC_UNO_SHOWNOTEAUTHOR
)
3945 maOptions
.SetOption(VOPT_NOTEAUTHOR
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3946 else if ( sName
== SC_UNO_SHOWFORMULASMARKS
)
3947 maOptions
.SetOption(VOPT_FORMULAS_MARKS
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3948 else if ( sName
== SC_UNO_SHOWGRID
)
3949 maOptions
.SetOption(VOPT_GRID
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3950 else if ( sName
== SC_UNO_GRIDCOLOR
)
3953 if (rSetting
.Value
>>= aColor
)
3954 maOptions
.SetGridColor(aColor
, OUString());
3956 else if ( sName
== SC_UNO_SHOWPAGEBR
)
3957 maOptions
.SetOption(VOPT_PAGEBREAKS
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3958 else if ( sName
== SC_UNO_COLROWHDR
)
3959 maOptions
.SetOption(VOPT_HEADER
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3960 else if ( sName
== SC_UNO_SHEETTABS
)
3961 maOptions
.SetOption(VOPT_TABCONTROLS
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3962 else if ( sName
== SC_UNO_OUTLSYMB
)
3963 maOptions
.SetOption(VOPT_OUTLINER
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3964 else if ( sName
== SC_UNO_SHOWOBJ
)
3966 // #i80528# placeholders not supported anymore
3967 if ( rSetting
.Value
>>= nTemp16
)
3968 maOptions
.SetObjMode(VOBJ_TYPE_OLE
, (nTemp16
== 1) ? VOBJ_MODE_HIDE
: VOBJ_MODE_SHOW
);
3970 else if ( sName
== SC_UNO_SHOWCHARTS
)
3972 // #i80528# placeholders not supported anymore
3973 if ( rSetting
.Value
>>= nTemp16
)
3974 maOptions
.SetObjMode(VOBJ_TYPE_CHART
, (nTemp16
== 1) ? VOBJ_MODE_HIDE
: VOBJ_MODE_SHOW
);
3976 else if ( sName
== SC_UNO_SHOWDRAW
)
3978 // #i80528# placeholders not supported anymore
3979 if ( rSetting
.Value
>>= nTemp16
)
3980 maOptions
.SetObjMode(VOBJ_TYPE_DRAW
, (nTemp16
== 1) ? VOBJ_MODE_HIDE
: VOBJ_MODE_SHOW
);
3982 else if ( sName
== SC_UNO_VALUEHIGH
&& !comphelper::LibreOfficeKit::isActive() )
3983 maOptions
.SetOption(VOPT_SYNTAX
, ScUnoHelpFunctions::GetBoolFromAny(rSetting
.Value
));
3986 ScGridOptions
aGridOpt(maOptions
.GetGridOptions());
3987 if ( sName
== SC_UNO_SNAPTORASTER
)
3988 aGridOpt
.SetUseGridSnap( ScUnoHelpFunctions::GetBoolFromAny( rSetting
.Value
) );
3989 else if ( sName
== SC_UNO_RASTERVIS
)
3990 aGridOpt
.SetGridVisible( ScUnoHelpFunctions::GetBoolFromAny( rSetting
.Value
) );
3991 else if ( sName
== SC_UNO_RASTERRESX
)
3992 aGridOpt
.SetFieldDrawX( static_cast <sal_uInt32
> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting
.Value
) ) );
3993 else if ( sName
== SC_UNO_RASTERRESY
)
3994 aGridOpt
.SetFieldDrawY( static_cast <sal_uInt32
> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting
.Value
) ) );
3995 else if ( sName
== SC_UNO_RASTERSUBX
)
3996 aGridOpt
.SetFieldDivisionX( static_cast <sal_uInt32
> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting
.Value
) ) );
3997 else if ( sName
== SC_UNO_RASTERSUBY
)
3998 aGridOpt
.SetFieldDivisionY( static_cast <sal_uInt32
> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting
.Value
) ) );
3999 else if ( sName
== SC_UNO_RASTERSYNC
)
4000 aGridOpt
.SetSynchronize( ScUnoHelpFunctions::GetBoolFromAny( rSetting
.Value
) );
4001 // Fallback to common SdrModel processing
4002 else GetDocument().GetDrawLayer()->ReadUserDataSequenceValue(&rSetting
);
4004 maOptions
.SetGridOptions(aGridOpt
);
4008 // copy default zoom to sheets where a different one wasn't specified
4009 for (SCTAB nZoomTab
=0; nZoomTab
< static_cast<SCTAB
>(maTabData
.size()); ++nZoomTab
)
4010 if (maTabData
[nZoomTab
] && ( nZoomTab
>= static_cast<SCTAB
>(aHasZoomVect
.size()) || !aHasZoomVect
[nZoomTab
] ))
4012 maTabData
[nZoomTab
]->eZoomType
= eDefZoomType
;
4013 maTabData
[nZoomTab
]->aZoomX
= aDefZoomX
;
4014 maTabData
[nZoomTab
]->aZoomY
= aDefZoomY
;
4015 maTabData
[nZoomTab
]->aPageZoomX
= aDefPageZoomX
;
4016 maTabData
[nZoomTab
]->aPageZoomY
= aDefPageZoomY
;
4019 if (rSettings
.hasElements())
4020 SetPagebreakMode( bPageMode
);
4022 // #i47426# write view options to document, needed e.g. for Excel export
4023 mrDoc
.SetViewOptions(maOptions
);
4025 if (comphelper::LibreOfficeKit::isActive())
4026 DeriveLOKFreezeAllSheets();
4029 void ScViewData::SetOptions( const ScViewOptions
& rOpt
)
4031 // if visibility of horizontal ScrollBar is changed, TabBar may have to be resized...
4032 bool bHScrollChanged
= (rOpt
.GetOption(VOPT_HSCROLL
) != maOptions
.GetOption(VOPT_HSCROLL
));
4034 // if graphics are turned on or off, animation has to be started or stopped
4035 // graphics are controlled by VOBJ_TYPE_OLE
4036 bool bGraphicsChanged
= (maOptions
.GetObjMode(VOBJ_TYPE_OLE
) !=
4037 rOpt
.GetObjMode(VOBJ_TYPE_OLE
) );
4040 OSL_ENSURE( pView
, "No View" );
4044 pView
->ViewOptionsHasChanged( bHScrollChanged
, bGraphicsChanged
);
4048 Point
ScViewData::GetMousePosPixel()
4050 OSL_ENSURE( pView
, "GetMousePosPixel() without View" );
4051 return pView
->GetMousePosPixel();
4054 void ScViewData::UpdateInputHandler( bool bForce
)
4057 pView
->UpdateInputHandler(bForce
);
4060 bool ScViewData::IsOle() const
4062 return pDocShell
&& pDocShell
->IsOle();
4065 bool ScViewData::UpdateFixX( SCTAB nTab
) // true = value changed
4067 if (!ValidTab(nTab
)) // Default
4068 nTab
=nTabNo
; // current table
4070 if (!pView
|| maTabData
[nTab
]->eHSplitMode
!= SC_SPLIT_FIX
)
4073 ScDocument
& rLocalDoc
= GetDocument();
4074 if (!rLocalDoc
.HasTable(nTab
)) // if called from reload, the sheet may not exist
4077 SCCOL nFix
= maTabData
[nTab
]->nFixPosX
;
4078 tools::Long nNewPos
= 0;
4079 for (SCCOL nX
=maTabData
[nTab
]->nPosX
[SC_SPLIT_LEFT
]; nX
<nFix
; nX
++)
4081 sal_uInt16 nTSize
= rLocalDoc
.GetColWidth( nX
, nTab
);
4084 tools::Long nPix
= ToPixel( nTSize
, nPPTX
);
4088 nNewPos
+= pView
->GetGridOffset().X();
4089 if (nNewPos
!= maTabData
[nTab
]->nHSplitPos
)
4091 maTabData
[nTab
]->nHSplitPos
= nNewPos
;
4093 RecalcPixPos(); // should not be needed
4100 bool ScViewData::UpdateFixY( SCTAB nTab
) // true = value changed
4102 if (!ValidTab(nTab
)) // Default
4103 nTab
=nTabNo
; // current table
4105 if (!pView
|| maTabData
[nTab
]->eVSplitMode
!= SC_SPLIT_FIX
)
4108 ScDocument
& rLocalDoc
= GetDocument();
4109 if (!rLocalDoc
.HasTable(nTab
)) // if called from reload, the sheet may not exist
4112 SCROW nFix
= maTabData
[nTab
]->nFixPosY
;
4113 tools::Long nNewPos
= 0;
4114 for (SCROW nY
=maTabData
[nTab
]->nPosY
[SC_SPLIT_TOP
]; nY
<nFix
; nY
++)
4116 sal_uInt16 nTSize
= rLocalDoc
.GetRowHeight( nY
, nTab
);
4119 tools::Long nPix
= ToPixel( nTSize
, nPPTY
);
4123 nNewPos
+= pView
->GetGridOffset().Y();
4124 if (nNewPos
!= maTabData
[nTab
]->nVSplitPos
)
4126 maTabData
[nTab
]->nVSplitPos
= nNewPos
;
4128 RecalcPixPos(); // should not be needed
4135 void ScViewData::UpdateOutlinerFlags( Outliner
& rOutl
) const
4137 ScDocument
& rLocalDoc
= GetDocument();
4138 const ScTabViewShell
* pTabViewShell
= GetViewShell();
4139 const bool bOnlineSpell
= pTabViewShell
&& pTabViewShell
->IsAutoSpell();
4141 EEControlBits nCntrl
= rOutl
.GetControlWord();
4142 nCntrl
|= EEControlBits::MARKNONURLFIELDS
;
4143 nCntrl
&= ~EEControlBits::MARKURLFIELDS
; // URLs not shaded for output
4144 nCntrl
|= EEControlBits::AUTOCORRECT
;
4146 nCntrl
|= EEControlBits::ONLINESPELLING
;
4148 nCntrl
&= ~EEControlBits::ONLINESPELLING
;
4149 rOutl
.SetControlWord(nCntrl
);
4151 rOutl
.SetCalcFieldValueHdl(LINK(ScModule::get(), ScModule
, CalcFieldValueHdl
));
4153 // don't call GetSpellChecker if online spelling isn't enabled.
4154 // The language for AutoCorrect etc. is taken from the pool defaults
4155 // (set in ScDocument::UpdateDrawLanguages)
4159 css::uno::Reference
<css::linguistic2::XSpellChecker1
> xXSpellChecker1( LinguMgr::GetSpellChecker() );
4160 rOutl
.SetSpeller( xXSpellChecker1
);
4163 rOutl
.SetDefaultHorizontalTextDirection(
4164 rLocalDoc
.GetEditTextDirection( nTabNo
) );
4167 ScAddress
ScViewData::GetCurPos() const
4169 return ScAddress( GetCurX(), GetCurY(), GetTabNo() );
4172 void ScViewData::SetRefStart( SCCOL nNewX
, SCROW nNewY
, SCTAB nNewZ
)
4174 nRefStartX
= nNewX
; nRefStartY
= nNewY
; nRefStartZ
= nNewZ
;
4177 void ScViewData::SetRefEnd( SCCOL nNewX
, SCROW nNewY
, SCTAB nNewZ
)
4179 nRefEndX
= nNewX
; nRefEndY
= nNewY
; nRefEndZ
= nNewZ
;
4182 void ScViewData::AddPixelsWhile( tools::Long
& rScrY
, tools::Long nEndPixels
, SCROW
& rPosY
,
4183 SCROW nEndRow
, double nPPTY
, const ScDocument
* pDoc
, SCTAB nTabNo
)
4186 while (rScrY
<= nEndPixels
&& nRow
<= nEndRow
)
4188 SCROW nHeightEndRow
;
4189 sal_uInt16 nHeight
= pDoc
->GetRowHeight( nRow
, nTabNo
, nullptr, &nHeightEndRow
);
4190 if (nHeightEndRow
> nEndRow
)
4191 nHeightEndRow
= nEndRow
;
4194 if (ValidTab(nTabNo
) && nTabNo
<= pDoc
->GetMaxTableNumber())
4195 nRow
= nHeightEndRow
+ 1;
4201 SCROW nRows
= nHeightEndRow
- nRow
+ 1;
4202 sal_Int64 nPixel
= ToPixel( nHeight
, nPPTY
);
4203 sal_Int64 nAdd
= nPixel
* nRows
;
4204 if (nAdd
+ rScrY
> nEndPixels
)
4206 sal_Int64 nDiff
= rScrY
+ nAdd
- nEndPixels
;
4207 nRows
-= static_cast<SCROW
>(nDiff
/ nPixel
);
4208 nAdd
= nPixel
* nRows
;
4209 // We're looking for a value that satisfies loop condition.
4210 if (nAdd
+ rScrY
<= nEndPixels
)
4216 rScrY
+= static_cast<tools::Long
>(nAdd
);
4225 void ScViewData::AddPixelsWhileBackward( tools::Long
& rScrY
, tools::Long nEndPixels
,
4226 SCROW
& rPosY
, SCROW nStartRow
, double nPPTY
, const ScDocument
* pDoc
,
4230 while (rScrY
<= nEndPixels
&& nRow
>= nStartRow
)
4232 SCROW nHeightStartRow
;
4233 sal_uInt16 nHeight
= pDoc
->GetRowHeight( nRow
, nTabNo
, &nHeightStartRow
, nullptr);
4234 if (nHeightStartRow
< nStartRow
)
4235 nHeightStartRow
= nStartRow
;
4237 nRow
= nHeightStartRow
- 1;
4240 SCROW nRows
= nRow
- nHeightStartRow
+ 1;
4241 sal_Int64 nPixel
= ToPixel( nHeight
, nPPTY
);
4242 sal_Int64 nAdd
= nPixel
* nRows
;
4243 if (nAdd
+ rScrY
> nEndPixels
)
4245 sal_Int64 nDiff
= nAdd
+ rScrY
- nEndPixels
;
4246 nRows
-= static_cast<SCROW
>(nDiff
/ nPixel
);
4247 nAdd
= nPixel
* nRows
;
4248 // We're looking for a value that satisfies loop condition.
4249 if (nAdd
+ rScrY
<= nEndPixels
)
4255 rScrY
+= static_cast<tools::Long
>(nAdd
);
4264 SCCOLROW
ScViewData::GetLOKSheetFreezeIndex(bool bIsCol
) const
4266 SCCOLROW nFreezeIndex
= bIsCol
? mrDoc
.GetLOKFreezeCol(nTabNo
) : mrDoc
.GetLOKFreezeRow(nTabNo
);
4267 return nFreezeIndex
>= 0 ? nFreezeIndex
: 0;
4270 bool ScViewData::SetLOKSheetFreezeIndex(const SCCOLROW nFreezeIndex
, bool bIsCol
, SCTAB nForTab
)
4276 else if (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size())))
4278 SAL_WARN("sc.viewdata", "ScViewData::SetLOKSheetFreezeIndex : invalid nForTab = " << nForTab
);
4282 return bIsCol
? mrDoc
.SetLOKFreezeCol(static_cast<SCCOL
>(nFreezeIndex
), nForTab
)
4283 : mrDoc
.SetLOKFreezeRow(static_cast<SCROW
>(nFreezeIndex
), nForTab
);
4286 bool ScViewData::RemoveLOKFreeze()
4288 bool colUnfreezed
= SetLOKSheetFreezeIndex(0, true);
4289 bool rowUnfreezed
= SetLOKSheetFreezeIndex(0, false);
4290 return colUnfreezed
|| rowUnfreezed
;
4293 void ScViewData::DeriveLOKFreezeAllSheets()
4295 SCTAB nMaxTab
= static_cast<SCTAB
>(maTabData
.size()) - 1;
4296 for (SCTAB nTab
= 0; nTab
<= nMaxTab
; ++nTab
)
4297 DeriveLOKFreezeIfNeeded(nTab
);
4300 void ScViewData::DeriveLOKFreezeIfNeeded(SCTAB nForTab
)
4302 if (!ValidTab(nForTab
) || (nForTab
>= static_cast<SCTAB
>(maTabData
.size())))
4304 SAL_WARN("sc.viewdata", "ScViewData::DeriveLOKFreezeIfNeeded : invalid nForTab = " << nForTab
);
4308 ScViewDataTable
* pViewTable
= maTabData
[nForTab
].get();
4312 bool bConvertToFreezeX
= false;
4313 bool bConvertToFreezeY
= false;
4314 SCCOL nFreezeCol
= mrDoc
.GetLOKFreezeCol(nForTab
);
4315 SCROW nFreezeRow
= mrDoc
.GetLOKFreezeRow(nForTab
);
4317 if (nFreezeCol
== -1)
4319 ScSplitMode eSplitMode
= pViewTable
->eHSplitMode
;
4320 if (eSplitMode
== SC_SPLIT_FIX
)
4321 nFreezeCol
= pViewTable
->nFixPosX
;
4322 else if (eSplitMode
== SC_SPLIT_NORMAL
)
4323 bConvertToFreezeX
= true;
4328 if (nFreezeRow
== -1)
4330 ScSplitMode eSplitMode
= pViewTable
->eVSplitMode
;
4331 if (eSplitMode
== SC_SPLIT_FIX
)
4332 nFreezeRow
= pViewTable
->nFixPosY
;
4333 else if (eSplitMode
== SC_SPLIT_NORMAL
)
4334 bConvertToFreezeY
= true;
4339 if (bConvertToFreezeX
|| bConvertToFreezeY
)
4343 GetPosFromPixel(bConvertToFreezeX
? pViewTable
->nHSplitPos
: 0,
4344 bConvertToFreezeY
? pViewTable
->nVSplitPos
: 0,
4345 SC_SPLIT_BOTTOMLEFT
, nCol
, nRow
,
4346 false /* bTestMerge */, false /* bRepair */,
4348 if (bConvertToFreezeX
)
4350 if (bConvertToFreezeY
)
4354 mrDoc
.SetLOKFreezeCol(nFreezeCol
, nForTab
);
4355 mrDoc
.SetLOKFreezeRow(nFreezeRow
, nForTab
);
4358 void ScViewData::OverrideWithLOKFreeze(ScSplitMode
& eExHSplitMode
, ScSplitMode
& eExVSplitMode
,
4359 SCCOL
& nExFixPosX
, SCROW
& nExFixPosY
,
4360 tools::Long
& nExHSplitPos
, tools::Long
& nExVSplitPos
, SCTAB nForTab
) const
4362 SCCOL nFreezeCol
= mrDoc
.GetLOKFreezeCol(nForTab
);
4363 SCROW nFreezeRow
= mrDoc
.GetLOKFreezeRow(nForTab
);
4365 bool bConvertToScrPosX
= false;
4366 bool bConvertToScrPosY
= false;
4368 if (nFreezeCol
>= 0)
4370 if (eExHSplitMode
== SC_SPLIT_NONE
)
4371 eExHSplitMode
= SC_SPLIT_FIX
;
4373 if (eExHSplitMode
== SC_SPLIT_FIX
)
4375 nExFixPosX
= nFreezeCol
;
4376 pThisTab
->nPosX
[SC_SPLIT_RIGHT
] = nFreezeCol
;
4379 bConvertToScrPosX
= true;
4382 if (nFreezeRow
>= 0)
4384 if (eExVSplitMode
== SC_SPLIT_NONE
)
4385 eExVSplitMode
= SC_SPLIT_FIX
;
4387 if (eExVSplitMode
== SC_SPLIT_FIX
)
4389 nExFixPosY
= nFreezeRow
;
4390 pThisTab
->nPosY
[SC_SPLIT_BOTTOM
] = nFreezeRow
;
4393 bConvertToScrPosY
= true;
4396 if (bConvertToScrPosX
|| bConvertToScrPosY
)
4398 Point aExSplitPos
= GetScrPos(nFreezeCol
, nFreezeRow
, SC_SPLIT_BOTTOMLEFT
, true, nForTab
);
4399 if (bConvertToScrPosX
)
4400 nExHSplitPos
= aExSplitPos
.X();
4401 if (bConvertToScrPosY
)
4402 nExVSplitPos
= aExSplitPos
.Y();
4406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */