LibreOffice Module sc (master)  1
viewdata.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <scitems.hxx>
21 #include <editeng/eeitem.hxx>
22 #include <o3tl/safeint.hxx>
23 #include <sfx2/lokhelper.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <editeng/adjustitem.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <svtools/colorcfg.hxx>
28 #include <editeng/editview.hxx>
29 #include <editeng/editstat.hxx>
30 #include <editeng/outliner.hxx>
31 #include <editeng/unolingu.hxx>
32 #include <editeng/justifyitem.hxx>
33 
34 #include <vcl/svapp.hxx>
35 #include <rtl/math.hxx>
36 #include <sal/log.hxx>
37 
38 #include <viewdata.hxx>
39 #include <docoptio.hxx>
40 #include <scmod.hxx>
41 #include <global.hxx>
42 #include <document.hxx>
43 #include <drwlayer.hxx>
44 #include <attrib.hxx>
45 #include <tabview.hxx>
46 #include <tabvwsh.hxx>
47 #include <docsh.hxx>
48 #include <patattr.hxx>
49 #include <editutil.hxx>
50 #include <scextopt.hxx>
51 #include <miscuno.hxx>
52 #include <unonames.hxx>
53 #include <inputopt.hxx>
54 #include <viewutil.hxx>
55 #include <markdata.hxx>
57 #include <gridwin.hxx>
58 #include <comphelper/flagguard.hxx>
59 #include <comphelper/lok.hxx>
61 #include <comphelper/string.hxx>
62 
63 #include <vcl/uitest/logger.hxx>
65 
66 #include <com/sun/star/container/XNameContainer.hpp>
67 #include <com/sun/star/document/NamedPropertyValues.hpp>
68 
69 using namespace com::sun::star;
70 
71 #define SC_GROWY_SMALL_EXTRA 100
72 #define SC_GROWY_BIG_EXTRA 200
73 
74 #define TAG_TABBARWIDTH "tw:"
75 
76 namespace {
77 
78 void lcl_LOKRemoveWindow(ScTabViewShell* pTabViewShell, ScSplitPos eWhich)
79 {
81  {
82  auto lRemoveWindows =
83  [pTabViewShell, eWhich] (ScTabViewShell* pOtherViewShell)
84  { pOtherViewShell->RemoveWindowFromForeignEditView(pTabViewShell, eWhich); };
85 
86  SfxLokHelper::forEachOtherView(pTabViewShell, lRemoveWindows);
87  }
88 }
89 
90 } // anonymous namespace
91 
92 namespace {
93 
94 void collectUIInformation(const std::map<OUString, OUString>& aParameters, const OUString& rAction)
95 {
96  EventDescription aDescription;
97  aDescription.aID = "grid_window";
98  aDescription.aAction = rAction;
99  aDescription.aParameters = aParameters;
100  aDescription.aParent = "MainWindow";
101  aDescription.aKeyWord = "ScGridWinUIObject";
102 
103  UITestLogger::getInstance().logEvent(aDescription);
104 }
105 }
106 
108 
109 bool ScPositionHelper::Comp::operator() (const value_type& rValue1, const value_type& rValue2) const
110 {
111  if (rValue1.first == null || rValue2.first == null)
112  {
113  return rValue1.second < rValue2.second;
114  }
115  else
116  {
117  return rValue1.first < rValue2.first;
118  }
119 }
120 
122  : MAX_INDEX(bColumn ? (pDoc ? pDoc->MaxCol() : -1) : MAXTILEDROW)
123 {
124  mData.insert(std::make_pair(-1, 0));
125 }
126 
127 void ScPositionHelper::setDocument(const ScDocument& rDoc, bool bColumn)
128 {
129  MAX_INDEX = bColumn ? rDoc.MaxCol() : MAXTILEDROW;
130 }
131 
132 void ScPositionHelper::insert(index_type nIndex, long nPos)
133 {
134  if (nIndex < 0) return;
135  SAL_INFO("sc.lok.poshelper", "ScPositionHelper::insert: nIndex: "
136  << nIndex << ", nPos: " << nPos << ", size: " << mData.size());
137  value_type aValue = std::make_pair(nIndex, nPos);
138  mData.erase(aValue);
139  mData.insert(aValue);
140  SAL_INFO("sc.lok.poshelper",
141  "ScPositionHelper::insert: after insert: size: " << mData.size());
142 }
143 
145 {
146  if (nIndex < 0)
147  return;
148  SAL_INFO("sc.lok.poshelper", "ScPositionHelper::remove: nIndex: " << nIndex
149  << ", size: " << mData.size());
150  auto it = mData.find(std::make_pair(nIndex, 0));
151  if (it == mData.end()) return;
152  mData.erase(it);
153  SAL_INFO("sc.lok.poshelper",
154  "ScPositionHelper::remove: after erase: size: " << mData.size());
155 }
156 
158 {
159  SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nIndex: " << nIndex);
160  if (nIndex < 0)
161  {
162  mData.clear();
163  mData.insert(std::make_pair(-1, 0));
164  }
165  else
166  {
167  auto it = mData.lower_bound(std::make_pair(nIndex, 0));
168  mData.erase(it, mData.end());
169  }
170 }
171 
173 {
174  SAL_INFO("sc.lok.poshelper", "ScPositionHelper::invalidate: nPos: " << nPos);
175  if (nPos <= 0)
176  {
177  mData.clear();
178  mData.insert(std::make_pair(-1, 0));
179  }
180  else
181  {
182  auto it = mData.lower_bound(std::make_pair(null, nPos));
183  mData.erase(it, mData.end());
184  }
185 }
186 
189 {
190  SAL_INFO("sc.lok.poshelper",
191  "ScPositionHelper::getNearest: nIndex: " << nIndex << ", size: " << mData.size());
192  auto posUB = mData.upper_bound(std::make_pair(nIndex, 0));
193  if (posUB == mData.begin())
194  {
195  return *posUB;
196  }
197 
198  auto posLB = std::prev(posUB);
199  // coverity[copy_paste_error : FALSE] - posUB is correct
200  if (posUB == mData.end())
201  {
202  return *posLB;
203  }
204 
205  long nDiffUB = posUB->first - nIndex;
206  long nDiffLB = posLB->first - nIndex;
207  if (nDiffUB < -nDiffLB)
208  {
209  return *posUB;
210  }
211  else
212  {
213  return *posLB;
214  }
215 }
216 
219 {
220  SAL_INFO("sc.lok.poshelper",
221  "ScPositionHelper::getNearest: nPos: " << nPos << ", size: " << mData.size());
222  auto posUB = mData.upper_bound(std::make_pair(null, nPos));
223 
224  if (posUB == mData.begin())
225  {
226  return *posUB;
227  }
228 
229  auto posLB = std::prev(posUB);
230  // coverity[copy_paste_error : FALSE] - posUB is correct
231  if (posUB == mData.end())
232  {
233  return *posLB;
234  }
235 
236  long nDiffUB = posUB->second - nPos;
237  long nDiffLB = posLB->second - nPos;
238 
239  if (nDiffUB < -nDiffLB)
240  {
241  return *posUB;
242  }
243  else
244  {
245  return *posLB;
246  }
247 }
248 
250 {
251  auto it = mData.find(std::make_pair(nIndex, 0));
252  if (it == mData.end()) return -1;
253  return it->second;
254 }
255 
256 long ScPositionHelper::computePosition(index_type nIndex, const std::function<long (index_type)>& getSizePx)
257 {
258  assert(MAX_INDEX > 0);
259  if (nIndex < 0) nIndex = 0;
260  if (nIndex > MAX_INDEX) nIndex = MAX_INDEX;
261 
262  const auto& rNearest = getNearestByIndex(nIndex);
263  index_type nStartIndex = rNearest.first;
264  long nTotalPixels = rNearest.second;
265 
266  if (nStartIndex < nIndex)
267  {
268  for (index_type nIdx = nStartIndex + 1; nIdx <= nIndex; ++nIdx)
269  {
270  nTotalPixels += getSizePx(nIdx);
271  }
272  }
273  else
274  {
275  for (index_type nIdx = nStartIndex; nIdx > nIndex; --nIdx)
276  {
277  nTotalPixels -= getSizePx(nIdx);
278  }
279  }
280  return nTotalPixels;
281 }
282 
283 ScBoundsProvider::ScBoundsProvider(const ScViewData &rView, SCTAB nT, bool bColHeader)
284  : rDoc(rView.GetDocument())
285  , nTab(nT)
286  , bColumnHeader(bColHeader)
287  , MAX_INDEX(bColHeader ? rDoc.MaxCol() : MAXTILEDROW)
288  , mfPPTX(rView.GetPPTX())
289  , mfPPTY(rView.GetPPTY())
290  , nFirstIndex(-1)
291  , nSecondIndex(-1)
292  , nFirstPositionPx(-1)
293  , nSecondPositionPx(-1)
294 {}
295 
296 void ScBoundsProvider::GetStartIndexAndPosition(SCCOL& nIndex, long& nPosition) const
297 {
299  nIndex = nFirstIndex;
300  nPosition = nFirstPositionPx;
301 }
302 
303 void ScBoundsProvider::GetEndIndexAndPosition(SCCOL& nIndex, long& nPosition) const
304 {
306  nIndex = nSecondIndex;
307  nPosition = nSecondPositionPx;
308 }
309 
310 void ScBoundsProvider::GetStartIndexAndPosition(SCROW& nIndex, long& nPosition) const
311 {
313  nIndex = nFirstIndex;
314  nPosition = nFirstPositionPx;
315 }
316 
317 void ScBoundsProvider::GetEndIndexAndPosition(SCROW& nIndex, long& nPosition) const
318 {
320  nIndex = nSecondIndex;
321  nPosition = nSecondPositionPx;
322 }
323 
325 {
326  const sal_uInt16 nSize = bColumnHeader ? rDoc.GetColWidth(nIndex, nTab) : rDoc.GetRowHeight(nIndex, nTab);
327  return ScViewData::ToPixel(nSize, bColumnHeader ? mfPPTX : mfPPTY);
328 }
329 
330 void ScBoundsProvider::GetIndexAndPos(index_type nNearestIndex, long nNearestPosition,
331  long nBound, index_type& nFoundIndex, long& nPosition,
332  bool bTowards, long nDiff)
333 {
334  if (nDiff > 0) // nBound < nNearestPosition
335  GeIndexBackwards(nNearestIndex, nNearestPosition, nBound,
336  nFoundIndex, nPosition, bTowards);
337  else
338  GetIndexTowards(nNearestIndex, nNearestPosition, nBound,
339  nFoundIndex, nPosition, bTowards);
340 }
341 
343  value_type aFirstNearest, value_type aSecondNearest,
344  long nFirstBound, long nSecondBound)
345 {
346  SAL_INFO("sc.lok.header", "BoundsProvider: nFirstBound: " << nFirstBound
347  << ", nSecondBound: " << nSecondBound);
348 
349  long nFirstDiff = aFirstNearest.second - nFirstBound;
350  long nSecondDiff = aSecondNearest.second - nSecondBound;
351  SAL_INFO("sc.lok.header", "BoundsProvider: rTopNearest: index: " << aFirstNearest.first
352  << ", pos: " << aFirstNearest.second << ", diff: " << nFirstDiff);
353  SAL_INFO("sc.lok.header", "BoundsProvider: rBottomNearest: index: " << aSecondNearest.first
354  << ", pos: " << aSecondNearest.second << ", diff: " << nSecondDiff);
355 
356  bool bReverse = (std::abs(nFirstDiff) >= std::abs(nSecondDiff));
357 
358  if(bReverse)
359  {
360  std::swap(aFirstNearest, aSecondNearest);
361  std::swap(nFirstBound, nSecondBound);
362  std::swap(nFirstDiff, nSecondDiff);
363  }
364 
365  index_type nNearestIndex = aFirstNearest.first;
366  long nNearestPosition = aFirstNearest.second;
367  SAL_INFO("sc.lok.header", "BoundsProvider: nearest to first bound: nNearestIndex: "
368  << nNearestIndex << ", nNearestPosition: " << nNearestPosition);
369 
370  GetIndexAndPos(nNearestIndex, nNearestPosition, nFirstBound,
371  nFirstIndex, nFirstPositionPx, !bReverse, nFirstDiff);
372  SAL_INFO("sc.lok.header", "BoundsProvider: nFirstIndex: " << nFirstIndex
373  << ", nFirstPositionPx: " << nFirstPositionPx);
374 
375  if (std::abs(nSecondDiff) < std::abs(nSecondBound - nFirstPositionPx))
376  {
377  nNearestIndex = aSecondNearest.first;
378  nNearestPosition = aSecondNearest.second;
379  }
380  else
381  {
382  nNearestPosition = nFirstPositionPx;
383  nNearestIndex = nFirstIndex;
384  nSecondDiff = !bReverse ? -1 : 1;
385  }
386  SAL_INFO("sc.lok.header", "BoundsProvider: nearest to second bound: nNearestIndex: "
387  << nNearestIndex << ", nNearestPosition: " << nNearestPosition
388  << ", diff: " << nSecondDiff);
389 
390  GetIndexAndPos(nNearestIndex, nNearestPosition, nSecondBound,
391  nSecondIndex, nSecondPositionPx, bReverse, nSecondDiff);
392  SAL_INFO("sc.lok.header", "BoundsProvider: nSecondIndex: " << nSecondIndex
393  << ", nSecondPositionPx: " << nSecondPositionPx);
394 
395  if (bReverse)
396  {
397  std::swap(nFirstIndex, nSecondIndex);
399  }
400 }
401 
403 {
404  const index_type nNewFirstIndex =
405  std::max(static_cast<index_type>(-1),
406  static_cast<index_type>(nFirstIndex - nOffset));
407  for (index_type nIndex = nFirstIndex; nIndex > nNewFirstIndex; --nIndex)
408  {
409  const long nSizePx = GetSize(nIndex);
410  nFirstPositionPx -= nSizePx;
411  }
412  nFirstIndex = nNewFirstIndex;
413  SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nFirstIndex: " << nFirstIndex
414  << ", nFirstPositionPx: " << nFirstPositionPx);
415 }
416 
418 {
419  const index_type nNewSecondIndex = std::min(MAX_INDEX, static_cast<index_type>(nSecondIndex + nOffset));
420  for (index_type nIndex = nSecondIndex + 1; nIndex <= nNewSecondIndex; ++nIndex)
421  {
422  const long nSizePx = GetSize(nIndex);
423  nSecondPositionPx += nSizePx;
424  }
425  nSecondIndex = nNewSecondIndex;
426  SAL_INFO("sc.lok.header", "BoundsProvider: added offset: nSecondIndex: " << nSecondIndex
427  << ", nSecondPositionPx: " << nSecondPositionPx);
428 }
429 
431  index_type nNearestIndex, long nNearestPosition,
432  long nBound, index_type& nFoundIndex, long& nPosition, bool bTowards)
433 {
434  nFoundIndex = -1;
435  for (index_type nIndex = nNearestIndex; nIndex >= 0; --nIndex)
436  {
437  if (nBound >= nNearestPosition)
438  {
439  nFoundIndex = nIndex; // last index whose nPosition is less than nBound
440  nPosition = nNearestPosition;
441  break;
442  }
443 
444  const long nSizePx = GetSize(nIndex);
445  nNearestPosition -= nSizePx;
446  }
447  if (!bTowards && nFoundIndex != -1)
448  {
449  nFoundIndex += 1;
450  nPosition += GetSize(nFoundIndex);
451  }
452 }
453 
455  index_type nNearestIndex, long nNearestPosition,
456  long nBound, index_type& nFoundIndex, long& nPosition, bool bTowards)
457 {
458  nFoundIndex = -2;
459  for (index_type nIndex = nNearestIndex + 1; nIndex <= MAX_INDEX; ++nIndex)
460  {
461  const long nSizePx = GetSize(nIndex);
462  nNearestPosition += nSizePx;
463 
464  if (nNearestPosition > nBound)
465  {
466  nFoundIndex = nIndex; // first index whose nPosition is greater than nBound
467  nPosition = nNearestPosition;
468  break;
469  }
470  }
471  if (nFoundIndex == -2)
472  {
473  nFoundIndex = MAX_INDEX;
474  nPosition = nNearestPosition;
475  }
476  else if (bTowards)
477  {
478  nPosition -= GetSize(nFoundIndex);
479  nFoundIndex -= 1;
480  }
481 }
482 
484  eZoomType( SvxZoomType::PERCENT ),
485  aZoomX( 1,1 ),
486  aZoomY( 1,1 ),
487  aPageZoomX( 3,5 ), // Page-Default: 60%
488  aPageZoomY( 3,5 ),
489  nHSplitPos( 0 ),
490  nVSplitPos( 0 ),
491  eHSplitMode( SC_SPLIT_NONE ),
492  eVSplitMode( SC_SPLIT_NONE ),
493  eWhichActive( SC_SPLIT_BOTTOMLEFT ),
494  nFixPosX( 0 ),
495  nFixPosY( 0 ),
496  nCurX( 0 ),
497  nCurY( 0 ),
498  nOldCurX( 0 ),
499  nOldCurY( 0 ),
500  aWidthHelper(pDoc, true),
501  aHeightHelper(pDoc, false),
502  nMaxTiledCol( 20 ),
503  nMaxTiledRow( 50 ),
504  bShowGrid( true ),
505  mbOldCursorValid( false )
506 {
507  nPosX[0]=nPosX[1]=0;
508  nPosY[0]=nPosY[1]=0;
509  nTPosX[0]=nTPosX[1]=0;
510  nTPosY[0]=nTPosY[1]=0;
511  nMPosX[0]=nMPosX[1]=0;
512  nMPosY[0]=nMPosY[1]=0;
513  nPixPosX[0]=nPixPosX[1]=0;
514  nPixPosY[0]=nPixPosY[1]=0;
515 }
516 
518 {
519  aWidthHelper.setDocument(rDoc, true);
520  aHeightHelper.setDocument(rDoc, false);
521 }
522 
523 void ScViewDataTable::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rSettings, const ScViewData& rViewData, SCTAB nTab) const
524 {
525  rSettings.realloc(SC_TABLE_VIEWSETTINGS_COUNT);
526  beans::PropertyValue* pSettings = rSettings.getArray();
527 
528  ScSplitMode eExHSplitMode = eHSplitMode;
529  ScSplitMode eExVSplitMode = eVSplitMode;
530  SCCOL nExFixPosX = nFixPosX;
531  SCROW nExFixPosY = nFixPosY;
532  long nExHSplitPos = nHSplitPos;
533  long nExVSplitPos = nVSplitPos;
534 
536  {
537  rViewData.OverrideWithLOKFreeze(eExHSplitMode, eExVSplitMode,
538  nExFixPosX, nExFixPosY,
539  nExHSplitPos, nExVSplitPos, nTab);
540  }
541 
542  pSettings[SC_CURSOR_X].Name = SC_CURSORPOSITIONX;
543  pSettings[SC_CURSOR_X].Value <<= sal_Int32(nCurX);
544  pSettings[SC_CURSOR_Y].Name = SC_CURSORPOSITIONY;
545  pSettings[SC_CURSOR_Y].Value <<= sal_Int32(nCurY);
547  pSettings[SC_HORIZONTAL_SPLIT_MODE].Value <<= sal_Int16(eExHSplitMode);
549  pSettings[SC_VERTICAL_SPLIT_MODE].Value <<= sal_Int16(eExVSplitMode);
551  if (eExHSplitMode == SC_SPLIT_FIX)
552  pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nExFixPosX);
553  else
554  pSettings[SC_HORIZONTAL_SPLIT_POSITION].Value <<= sal_Int32(nExHSplitPos);
556  if (eExVSplitMode == SC_SPLIT_FIX)
557  pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nExFixPosY);
558  else
559  pSettings[SC_VERTICAL_SPLIT_POSITION].Value <<= sal_Int32(nExVSplitPos);
560  // Prevent writing odd settings that would make crash versions that
561  // don't apply SanitizeWhichActive() when reading the settings.
562  // See tdf#117093
563  const ScSplitPos eActiveSplitRange = SanitizeWhichActive();
564  // And point out to give us a chance to inspect weird things (if anyone
565  // remembers what s/he did).
566  assert(eWhichActive == eActiveSplitRange);
567  pSettings[SC_ACTIVE_SPLIT_RANGE].Name = SC_ACTIVESPLITRANGE;
568  pSettings[SC_ACTIVE_SPLIT_RANGE].Value <<= sal_Int16(eActiveSplitRange);
569  pSettings[SC_POSITION_LEFT].Name = SC_POSITIONLEFT;
570  pSettings[SC_POSITION_LEFT].Value <<= sal_Int32(nPosX[SC_SPLIT_LEFT]);
571  pSettings[SC_POSITION_RIGHT].Name = SC_POSITIONRIGHT;
572  pSettings[SC_POSITION_RIGHT].Value <<= sal_Int32(nPosX[SC_SPLIT_RIGHT]);
573  pSettings[SC_POSITION_TOP].Name = SC_POSITIONTOP;
574  pSettings[SC_POSITION_TOP].Value <<= sal_Int32(nPosY[SC_SPLIT_TOP]);
575  pSettings[SC_POSITION_BOTTOM].Name = SC_POSITIONBOTTOM;
576  pSettings[SC_POSITION_BOTTOM].Value <<= sal_Int32(nPosY[SC_SPLIT_BOTTOM]);
577 
578  sal_Int32 nZoomValue = long(aZoomY * 100);
579  sal_Int32 nPageZoomValue = long(aPageZoomY * 100);
580  pSettings[SC_TABLE_ZOOM_TYPE].Name = SC_ZOOMTYPE;
581  pSettings[SC_TABLE_ZOOM_TYPE].Value <<= sal_Int16(eZoomType);
582  pSettings[SC_TABLE_ZOOM_VALUE].Name = SC_ZOOMVALUE;
583  pSettings[SC_TABLE_ZOOM_VALUE].Value <<= nZoomValue;
585  pSettings[SC_TABLE_PAGE_VIEW_ZOOM_VALUE].Value <<= nPageZoomValue;
586 
587  pSettings[SC_TABLE_SHOWGRID].Name = SC_UNO_SHOWGRID;
588  pSettings[SC_TABLE_SHOWGRID].Value <<= bShowGrid;
589 
590  // Common SdrModel processing
591  rViewData.GetDocument().GetDrawLayer()->WriteUserDataSequence(rSettings);
592 }
593 
594 void ScViewDataTable::ReadUserDataSequence(const uno::Sequence <beans::PropertyValue>& aSettings, ScViewData& rViewData, SCTAB nTab, bool& rHasZoom )
595 {
596  rHasZoom = false;
597 
598  sal_Int32 nTemp32(0);
599  sal_Int16 nTemp16(0);
600  sal_Int32 nTempPosV(0);
601  sal_Int32 nTempPosH(0);
602  sal_Int32 nTempPosVTw(0);
603  sal_Int32 nTempPosHTw(0);
604  bool bHasVSplitInTwips = false;
605  bool bHasHSplitInTwips = false;
606  for (const auto& rSetting : aSettings)
607  {
608  OUString sName(rSetting.Name);
609  if (sName == SC_CURSORPOSITIONX)
610  {
611  rSetting.Value >>= nTemp32;
612  nCurX = rViewData.GetDocument().SanitizeCol( static_cast<SCCOL>(nTemp32));
613  }
614  else if (sName == SC_CURSORPOSITIONY)
615  {
616  rSetting.Value >>= nTemp32;
617  nCurY = rViewData.GetDocument().SanitizeRow( static_cast<SCROW>(nTemp32));
618  }
619  else if (sName == SC_HORIZONTALSPLITMODE)
620  {
621  if ((rSetting.Value >>= nTemp16) && nTemp16 <= ScSplitMode::SC_SPLIT_MODE_MAX_ENUM)
622  eHSplitMode = static_cast<ScSplitMode>(nTemp16);
623  }
624  else if (sName == SC_VERTICALSPLITMODE)
625  {
626  if ((rSetting.Value >>= nTemp16) && nTemp16 <= ScSplitMode::SC_SPLIT_MODE_MAX_ENUM)
627  eVSplitMode = static_cast<ScSplitMode>(nTemp16);
628  }
629  else if (sName == SC_HORIZONTALSPLITPOSITION)
630  {
631  rSetting.Value >>= nTempPosH;
632  bHasHSplitInTwips = false;
633  }
634  else if (sName == SC_VERTICALSPLITPOSITION)
635  {
636  rSetting.Value >>= nTempPosV;
637  bHasVSplitInTwips = false;
638  }
639  else if (sName == SC_HORIZONTALSPLITPOSITION_TWIPS)
640  {
641  rSetting.Value >>= nTempPosHTw;
642  bHasHSplitInTwips = true;
643  }
644  else if (sName == SC_VERTICALSPLITPOSITION_TWIPS)
645  {
646  rSetting.Value >>= nTempPosVTw;
647  bHasVSplitInTwips = true;
648  }
649  else if (sName == SC_ACTIVESPLITRANGE)
650  {
651  if ((rSetting.Value >>= nTemp16) && nTemp16 <= ScSplitPos::SC_SPLIT_POS_MAX_ENUM)
652  eWhichActive = static_cast<ScSplitPos>(nTemp16);
653  }
654  else if (sName == SC_POSITIONLEFT)
655  {
656  rSetting.Value >>= nTemp32;
657  nPosX[SC_SPLIT_LEFT] = rViewData.GetDocument().SanitizeCol( static_cast<SCCOL>(nTemp32));
658  }
659  else if (sName == SC_POSITIONRIGHT)
660  {
661  rSetting.Value >>= nTemp32;
662  nPosX[SC_SPLIT_RIGHT] = rViewData.GetDocument().SanitizeCol( static_cast<SCCOL>(nTemp32));
663  }
664  else if (sName == SC_POSITIONTOP)
665  {
666  rSetting.Value >>= nTemp32;
667  nPosY[SC_SPLIT_TOP] = rViewData.GetDocument().SanitizeRow( static_cast<SCROW>(nTemp32));
668  }
669  else if (sName == SC_POSITIONBOTTOM)
670  {
671  rSetting.Value >>= nTemp32;
672  nPosY[SC_SPLIT_BOTTOM] = rViewData.GetDocument().SanitizeRow( static_cast<SCROW>(nTemp32));
673  }
674  else if (sName == SC_ZOOMTYPE)
675  {
676  rSetting.Value >>= nTemp16;
677  eZoomType = SvxZoomType(nTemp16);
678  rHasZoom = true; // set if there is any zoom information
679  }
680  else if (sName == SC_ZOOMVALUE)
681  {
682  rSetting.Value >>= nTemp32;
683  Fraction aZoom(nTemp32, 100);
684  aZoomX = aZoomY = aZoom;
685  rHasZoom = true;
686  }
687  else if (sName == SC_PAGEVIEWZOOMVALUE)
688  {
689  rSetting.Value >>= nTemp32;
690  Fraction aZoom(nTemp32, 100);
691  aPageZoomX = aPageZoomY = aZoom;
692  rHasZoom = true;
693  }
694  else if (sName == SC_UNO_SHOWGRID)
695  {
696  rSetting.Value >>= bShowGrid;
697  }
698  else if (sName == SC_TABLESELECTED)
699  {
700  bool bSelected = false;
701  rSetting.Value >>= bSelected;
702  rViewData.GetMarkData().SelectTable( nTab, bSelected );
703  }
704  else if (sName == SC_UNONAME_TABCOLOR)
705  {
706  // There are documents out there that have their tab color defined as a view setting.
707  Color aColor = COL_AUTO;
708  rSetting.Value >>= aColor;
709  if (aColor != COL_AUTO)
710  {
711  ScDocument& rDoc = rViewData.GetDocument();
712  rDoc.SetTabBgColor(nTab, aColor);
713  }
714  }
715  // Fallback to common SdrModel processing
716  else rViewData.GetDocument().GetDrawLayer()->ReadUserDataSequenceValue(&rSetting);
717  }
718 
719  if (eHSplitMode == SC_SPLIT_FIX)
720  nFixPosX = rViewData.GetDocument().SanitizeCol( static_cast<SCCOL>( bHasHSplitInTwips ? nTempPosHTw : nTempPosH ));
721  else
722  nHSplitPos = bHasHSplitInTwips ? static_cast< long >( nTempPosHTw * rViewData.GetPPTX() ) : nTempPosH;
723 
724  if (eVSplitMode == SC_SPLIT_FIX)
725  nFixPosY = rViewData.GetDocument().SanitizeRow( static_cast<SCROW>( bHasVSplitInTwips ? nTempPosVTw : nTempPosV ));
726  else
727  nVSplitPos = bHasVSplitInTwips ? static_cast< long >( nTempPosVTw * rViewData.GetPPTY() ) : nTempPosV;
728 
730 }
731 
733 {
736  {
737  SAL_WARN("sc.ui","ScViewDataTable::SanitizeWhichActive - bad eWhichActive " << eWhichActive);
738  // The default always initialized grid window is SC_SPLIT_BOTTOMLEFT.
739  return SC_SPLIT_BOTTOMLEFT;
740  }
741  return eWhichActive;
742 }
743 
745 
747  : ScViewData(nullptr, &rDocSh, pViewSh)
748 {
749 }
750 
752  : ScViewData(&rDoc, nullptr, nullptr)
753 {
754 }
755 
757 {
758  ScViewOptions aOptions;
759  aOptions.SetOption(VOPT_GRID, true);
760  aOptions.SetOption(VOPT_SYNTAX, false);
761  aOptions.SetOption(VOPT_HEADER, true);
762  aOptions.SetOption(VOPT_TABCONTROLS, true);
763  aOptions.SetOption(VOPT_VSCROLL, true);
764  aOptions.SetOption(VOPT_HSCROLL, true);
765  aOptions.SetOption(VOPT_OUTLINER, true);
766  return aOptions;
767 }
768 
769 // Either pDoc or pDocSh must be valid
771  nPPTX(0.0),
772  nPPTY(0.0),
773  maMarkData (pDocSh ? pDocSh->GetDocument().GetSheetLimits() : gaNoShellSheetLimits),
774  pDocShell ( pDocSh ),
775  mrDoc (pDoc ? *pDoc : pDocSh->GetDocument()),
776  pView ( pViewSh ),
777  maOptions (pDocSh ? pDocSh->GetDocument().GetViewOptions() : DefaultOptions()),
778  pSpellingView ( nullptr ),
779  aLogicMode ( MapUnit::Map100thMM ),
780  eDefZoomType( SvxZoomType::PERCENT ),
781  aDefZoomX ( 1,1 ),
782  aDefZoomY ( 1,1 ),
783  aDefPageZoomX( 3,5 ),
784  aDefPageZoomY( 3,5 ),
785  eRefType ( SC_REFTYPE_NONE ),
786  nTabNo ( 0 ),
787  nRefTabNo ( 0 ),
788  nRefStartX(0),
789  nRefStartY(0),
790  nRefStartZ(0),
791  nRefEndX(0),
792  nRefEndY(0),
793  nRefEndZ(0),
794  nFillStartX(0),
795  nFillStartY(0),
796  nFillEndX(0),
797  nFillEndY(0),
798  nPasteFlags ( ScPasteFlags::NONE ),
799  eEditActivePart( SC_SPLIT_BOTTOMLEFT ),
800  nFillMode ( ScFillMode::NONE ),
801  eEditAdjust ( SvxAdjust::Left ),
802  bActive ( true ), // how to initialize?
803  bIsRefMode ( false ),
804  bDelMarkValid( false ),
805  bPagebreak ( false ),
806  bSelCtrlMouseClick( false ),
807  bMoveArea ( false ),
808  bGrowing (false),
809  m_nLOKPageUpDownOffset( 0 )
810 {
811  assert(bool(pDoc) != bool(pDocSh)); // either one or the other, not both
812  maMarkData.SelectOneTable(0); // Sync with nTabNo
813 
815  static_cast<long>( ScGlobal::nStdRowHeight * PIXEL_PER_TWIPS * OLE_STD_CELLS_Y ) );
816  maTabData.emplace_back( new ScViewDataTable(nullptr) );
817  pThisTab = maTabData[nTabNo].get();
818 
820  nEditEndRow = nEditRow = 0;
822 
823  // don't show hidden tables
824  if (!mrDoc.IsVisible(nTabNo))
825  {
826  while (!mrDoc.IsVisible(nTabNo) && mrDoc.HasTable(nTabNo + 1))
827  {
828  ++nTabNo;
829  maTabData.emplace_back(nullptr);
830  }
831  maTabData[nTabNo].reset( new ScViewDataTable(nullptr) );
832  pThisTab = maTabData[nTabNo].get();
833  }
834 
835  SCTAB nTableCount = mrDoc.GetTableCount();
836  EnsureTabDataSize(nTableCount);
837 
838  for (auto& xTabData : maTabData)
839  {
840  if (xTabData)
841  xTabData->InitData(mrDoc);
842  }
843 
844  CalcPPT();
845 }
846 
847 ScViewData::~ScViewData() COVERITY_NOEXCEPT_FALSE
848 {
849  KillEditView();
850 }
851 
852 ScDBFunc* ScViewData::GetView() const { return pView; }
853 
855 {
856  assert(0 <= nTabNo && o3tl::make_unsigned(nTabNo) < maTabData.size());
857  pThisTab = maTabData[nTabNo].get();
858  while (!pThisTab)
859  {
860  if (nTabNo > 0)
861  pThisTab = maTabData[--nTabNo].get();
862  else
863  {
864  maTabData[0].reset(new ScViewDataTable(&mrDoc));
865  pThisTab = maTabData[0].get();
866  }
867  }
868 }
869 
871 {
872  if( nTab >= static_cast<SCTAB>(maTabData.size()))
873  maTabData.resize(nTab+1);
874  else
875  maTabData.insert( maTabData.begin() + nTab, nullptr );
876  CreateTabData( nTab );
877 
879  maMarkData.InsertTab(nTab);
880 
881  collectUIInformation({{}}, "InsertTab");
882 }
883 
884 void ScViewData::InsertTabs( SCTAB nTab, SCTAB nNewSheets )
885 {
886  if (nTab >= static_cast<SCTAB>(maTabData.size()))
887  maTabData.resize(nTab+nNewSheets);
888  else
889  {
890  // insert nNewSheets new tables at position nTab
891  auto prevSize = maTabData.size();
892  maTabData.resize(prevSize + nNewSheets);
893  std::move_backward(maTabData.begin() + nTab, maTabData.begin() + prevSize, maTabData.end());
894  }
895  for (SCTAB i = nTab; i < nTab + nNewSheets; ++i)
896  {
897  CreateTabData( i );
899  }
901 }
902 
904 {
905  assert(nTab < static_cast<SCTAB>(maTabData.size()));
906  maTabData.erase(maTabData.begin() + nTab);
907 
908  if (o3tl::make_unsigned(nTabNo) >= maTabData.size())
909  {
911  nTabNo = maTabData.size() - 1;
912  }
914  maMarkData.DeleteTab(nTab);
915 }
916 
917 void ScViewData::DeleteTabs( SCTAB nTab, SCTAB nSheets )
918 {
919  for (SCTAB i = 0; i < nSheets; ++i)
920  {
921  maMarkData.DeleteTab(nTab + i);
922  }
923  maTabData.erase(maTabData.begin() + nTab, maTabData.begin()+ nTab+nSheets);
924  if (o3tl::make_unsigned(nTabNo) >= maTabData.size())
925  {
927  nTabNo = maTabData.size() - 1;
928  }
930 }
931 
932 void ScViewData::CopyTab( SCTAB nSrcTab, SCTAB nDestTab )
933 {
934  if (nDestTab==SC_TAB_APPEND)
935  nDestTab = mrDoc.GetTableCount() - 1; // something had to have been copied
936 
937  if (nDestTab > MAXTAB)
938  {
939  OSL_FAIL("too many sheets");
940  return;
941  }
942 
943  if (nSrcTab >= static_cast<SCTAB>(maTabData.size()))
944  OSL_FAIL("pTabData out of bounds, FIX IT");
945 
946  EnsureTabDataSize(nDestTab + 1);
947 
948  if ( maTabData[nSrcTab] )
949  maTabData.emplace(maTabData.begin() + nDestTab, new ScViewDataTable( *maTabData[nSrcTab] ));
950  else
951  maTabData.insert(maTabData.begin() + nDestTab, nullptr);
952 
954  maMarkData.InsertTab(nDestTab);
955 }
956 
957 void ScViewData::MoveTab( SCTAB nSrcTab, SCTAB nDestTab )
958 {
959  if (nDestTab==SC_TAB_APPEND)
960  nDestTab = mrDoc.GetTableCount() - 1;
961  std::unique_ptr<ScViewDataTable> pTab;
962  if (nSrcTab < static_cast<SCTAB>(maTabData.size()))
963  {
964  pTab = std::move(maTabData[nSrcTab]);
965  maTabData.erase( maTabData.begin() + nSrcTab );
966  }
967 
968  if (nDestTab < static_cast<SCTAB>(maTabData.size()))
969  maTabData.insert( maTabData.begin() + nDestTab, std::move(pTab) );
970  else
971  {
972  EnsureTabDataSize(nDestTab + 1);
973  maTabData[nDestTab] = std::move(pTab);
974  }
975 
977  maMarkData.DeleteTab(nSrcTab);
978  maMarkData.InsertTab(nDestTab); // adapted if needed
979 }
980 
981 void ScViewData::CreateTabData( std::vector< SCTAB >& rvTabs )
982 {
983  for ( const auto& rTab : rvTabs )
984  CreateTabData(rTab);
985 }
986 
987 void ScViewData::SetZoomType( SvxZoomType eNew, std::vector< SCTAB >& tabs )
988 {
989  bool bAll = tabs.empty();
990 
991  if ( !bAll ) // create associated table data
992  CreateTabData( tabs );
993 
994  if ( bAll )
995  {
996  for ( SCTAB i = 0; i < static_cast<SCTAB>(maTabData.size()); ++i )
997  {
998  if ( maTabData[i] )
999  maTabData[i]->eZoomType = eNew;
1000  }
1001  eDefZoomType = eNew;
1002  }
1003  else
1004  {
1005  for ( const SCTAB& i : tabs )
1006  {
1007  if ( i < static_cast<SCTAB>(maTabData.size()) && maTabData[i] )
1008  maTabData[i]->eZoomType = eNew;
1009  }
1010  }
1011 }
1012 
1013 void ScViewData::SetZoomType( SvxZoomType eNew, bool bAll )
1014 {
1015  std::vector< SCTAB > vTabs; // Empty for all tabs
1016  if ( !bAll ) // get selected tabs
1017  {
1018  ScMarkData::iterator itr = maMarkData.begin(), itrEnd = maMarkData.end();
1019  vTabs.insert(vTabs.begin(), itr, itrEnd);
1020  }
1021  SetZoomType( eNew, vTabs );
1022 }
1023 
1024 void ScViewData::SetZoom( const Fraction& rNewX, const Fraction& rNewY, std::vector< SCTAB >& tabs )
1025 {
1026  bool bAll = tabs.empty();
1027  if ( !bAll ) // create associated table data
1028  CreateTabData( tabs );
1029 
1030  // sanity check - we shouldn't need something this low / big
1031  SAL_WARN_IF(rNewX < Fraction(1, 100) || rNewX > Fraction(100, 1), "sc.viewdata",
1032  "fraction rNewX not sensible: " << static_cast<double>(rNewX));
1033  SAL_WARN_IF(rNewY < Fraction(1, 100) || rNewY > Fraction(100, 1), "sc.viewdata",
1034  "fraction rNewY not sensible: " << static_cast<double>(rNewY));
1035 
1036  if ( bAll )
1037  {
1038  for ( SCTAB i = 0; i < static_cast<SCTAB>(maTabData.size()); ++i )
1039  {
1040  if ( maTabData[i] )
1041  {
1042  if ( bPagebreak )
1043  {
1044  maTabData[i]->aPageZoomX = rNewX;
1045  maTabData[i]->aPageZoomY = rNewY;
1046  }
1047  else
1048  {
1049  maTabData[i]->aZoomX = rNewX;
1050  maTabData[i]->aZoomY = rNewY;
1051  }
1052  }
1053  }
1054  if ( bPagebreak )
1055  {
1056  aDefPageZoomX = rNewX;
1057  aDefPageZoomY = rNewY;
1058  }
1059  else
1060  {
1061  aDefZoomX = rNewX;
1062  aDefZoomY = rNewY;
1063  }
1064  }
1065  else
1066  {
1067  for ( const SCTAB& i : tabs )
1068  {
1069  if ( i < static_cast<SCTAB>(maTabData.size()) && maTabData[i] )
1070  {
1071  if ( bPagebreak )
1072  {
1073  maTabData[i]->aPageZoomX = rNewX;
1074  maTabData[i]->aPageZoomY = rNewY;
1075  }
1076  else
1077  {
1078  maTabData[i]->aZoomX = rNewX;
1079  maTabData[i]->aZoomY = rNewY;
1080  }
1081  }
1082  }
1083  }
1084  RefreshZoom();
1085 }
1086 
1087 void ScViewData::SetZoom( const Fraction& rNewX, const Fraction& rNewY, bool bAll )
1088 {
1089  std::vector< SCTAB > vTabs;
1090  if ( !bAll ) // get selected tabs
1091  {
1092  ScMarkData::iterator itr = maMarkData.begin(), itrEnd = maMarkData.end();
1093  vTabs.insert(vTabs.begin(), itr, itrEnd);
1094  }
1095  SetZoom( rNewX, rNewY, vTabs );
1096 }
1097 
1098 void ScViewData::SetShowGrid( bool bShow )
1099 {
1101  maTabData[nTabNo]->bShowGrid = bShow;
1102 }
1103 
1105 {
1106  // recalculate zoom-dependent values (only for current sheet)
1107 
1108  CalcPPT();
1109  RecalcPixPos();
1110  aScenButSize = Size(0,0);
1113 }
1114 
1116 {
1117  bPagebreak = bSet;
1118 
1119  RefreshZoom();
1120 }
1121 
1123 {
1124  ScMarkType eMarkType = SC_MARK_NONE;
1125 
1126  if ( rNewMark.IsMarked() || rNewMark.IsMultiMarked() )
1127  {
1128  if ( rNewMark.IsMultiMarked() )
1129  rNewMark.MarkToSimple();
1130 
1131  if ( rNewMark.IsMarked() && !rNewMark.IsMultiMarked() )
1132  {
1133  rNewMark.GetMarkArea( rRange );
1134  if (ScViewUtil::HasFiltered(rRange, GetDocument()))
1135  eMarkType = SC_MARK_SIMPLE_FILTERED;
1136  else
1137  eMarkType = SC_MARK_SIMPLE;
1138  }
1139  else
1140  eMarkType = SC_MARK_MULTI;
1141  }
1142  if (eMarkType != SC_MARK_SIMPLE && eMarkType != SC_MARK_SIMPLE_FILTERED)
1143  {
1144  if (eMarkType == SC_MARK_NONE)
1145  eMarkType = SC_MARK_SIMPLE;
1146  const ScPatternAttr* pMarkPattern = mrDoc.GetPattern(GetCurX(), GetCurY(), GetTabNo());
1147  if (pMarkPattern->GetItemSet().GetItemState(ATTR_MERGE, false) == SfxItemState::SET)
1148  {
1149  SCROW nRow = pMarkPattern->GetItem(ATTR_MERGE).GetRowMerge();
1150  SCCOL nCol = pMarkPattern->GetItem(ATTR_MERGE).GetColMerge();
1151  if ( nRow < 1 || nCol < 1 )
1152  {
1153  // This kind of cells do exist. Not sure if that is intended or a bug.
1154  rRange = ScRange(GetCurX(), GetCurY(), GetTabNo());
1155  }
1156  else
1157  {
1158  rRange = ScRange(GetCurX(), GetCurY(), GetTabNo(),
1159  GetCurX() + nCol - 1, GetCurY() + nRow - 1, GetTabNo());
1160  if ( ScViewUtil::HasFiltered(rRange, GetDocument()) )
1161  eMarkType = SC_MARK_SIMPLE_FILTERED;
1162  }
1163  }
1164  else
1165  rRange = ScRange(GetCurX(), GetCurY(), GetTabNo());
1166  }
1167  return eMarkType;
1168 }
1169 
1170 ScMarkType ScViewData::GetSimpleArea( SCCOL& rStartCol, SCROW& rStartRow, SCTAB& rStartTab,
1171  SCCOL& rEndCol, SCROW& rEndRow, SCTAB& rEndTab ) const
1172 {
1173  // parameter bMergeMark is no longer needed: The view's selection is never modified
1174  // (a local copy is used), and a multi selection that adds to a single range can always
1175  // be treated like a single selection (GetSimpleArea isn't used in selection
1176  // handling itself)
1177 
1178  ScRange aRange;
1179  ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple
1180  ScMarkType eMarkType = GetSimpleArea( aRange, aNewMark);
1181  aRange.GetVars( rStartCol, rStartRow, rStartTab, rEndCol, rEndRow, rEndTab);
1182  return eMarkType;
1183 }
1184 
1186 {
1187  // parameter bMergeMark is no longer needed, see above
1188 
1189  ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple
1190  return GetSimpleArea( rRange, aNewMark);
1191 }
1192 
1194 {
1195  // parameter bMergeMark is no longer needed, see GetSimpleArea
1196 
1197  ScMarkData aNewMark(maMarkData); // use a local copy for MarkToSimple
1198 
1199  bool bMulti = aNewMark.IsMultiMarked();
1200  if (bMulti)
1201  {
1202  aNewMark.MarkToSimple();
1203  bMulti = aNewMark.IsMultiMarked();
1204  }
1205  if (bMulti)
1206  {
1207  rRange = new ScRangeList;
1208  aNewMark.FillRangeListWithMarks( rRange.get(), false );
1209  }
1210  else
1211  {
1212  ScRange aSimple;
1213  GetSimpleArea(aSimple);
1214  rRange = new ScRangeList(aSimple);
1215  }
1216 }
1217 
1219 {
1220  SCCOL nStartCol;
1221  SCROW nStartRow;
1222  SCTAB nStartTab;
1223  SCCOL nEndCol;
1224  SCROW nEndRow;
1225  SCTAB nEndTab;
1226  if (GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1227  if (nStartRow == 0 && nEndRow == mrDoc.MaxRow())
1228  return true;
1229 
1230  return false;
1231 }
1232 
1234 {
1235  SCCOL nStartCol;
1236  SCROW nStartRow;
1237  SCTAB nStartTab;
1238  SCCOL nEndCol;
1239  SCROW nEndRow;
1240  SCTAB nEndTab;
1241  if (GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1242  if (nStartCol == 0 && nEndCol == mrDoc.MaxCol())
1243  return true;
1244 
1245  return false;
1246 }
1247 
1249 {
1250  // Test for "real" multi selection, calling MarkToSimple on a local copy,
1251  // and taking filtered in simple area marks into account.
1252 
1253  ScRange aDummy;
1254  ScMarkType eType = GetSimpleArea(aDummy);
1255  return (eType & SC_MARK_SIMPLE) != SC_MARK_SIMPLE;
1256 }
1257 
1259 {
1260  ScRange aSelRange( ScAddress::UNINITIALIZED );
1261  ScMarkType eMarkType = GetSimpleArea( aSelRange);
1262  return eMarkType != SC_MARK_MULTI && SelectionFillDOOM( aSelRange);
1263 }
1264 
1265 // static
1267 {
1268  // Assume that more than 23 full columns (23M cells) will not be
1269  // successful... Even with only 10 bytes per cell that would already be
1270  // 230MB, formula cells would be 100 bytes and more per cell.
1271  // rows * columns > 23m => rows > 23m / columns
1272  // to not overflow in case number of available columns or rows would be
1273  // arbitrarily increased.
1274  // We could refine this and take some actual cell size into account,
1275  // evaluate available memory and what not, but...
1276  const sal_Int32 kMax = 23 * 1024 * 1024; // current MAXROWCOUNT1 is 1024*1024=1048576
1277  return (rRange.aEnd.Row() - rRange.aStart.Row() + 1) > (kMax / (rRange.aEnd.Col() - rRange.aStart.Col() + 1));
1278 }
1279 
1280 void ScViewData::SetFillMode( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
1281 {
1283  nFillStartX = nStartCol;
1284  nFillStartY = nStartRow;
1285  nFillEndX = nEndCol;
1286  nFillEndY = nEndRow;
1287 }
1288 
1289 void ScViewData::SetDragMode( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1290  ScFillMode nMode )
1291 {
1292  nFillMode = nMode;
1293  nFillStartX = nStartCol;
1294  nFillStartY = nStartRow;
1295  nFillEndX = nEndCol;
1296  nFillEndY = nEndRow;
1297 }
1298 
1300 {
1302 }
1303 
1304 void ScViewData::GetFillData( SCCOL& rStartCol, SCROW& rStartRow,
1305  SCCOL& rEndCol, SCROW& rEndRow )
1306 {
1307  rStartCol = nFillStartX;
1308  rStartRow = nFillStartY;
1309  rEndCol = nFillEndX;
1310  rEndRow = nFillEndY;
1311 }
1312 
1314 {
1316  return pThisTab->nOldCurX;
1317  else
1318  return pThisTab->nCurX;
1319 }
1320 
1322 {
1324  return pThisTab->nOldCurY;
1325  else
1326  return pThisTab->nCurY;
1327 }
1328 
1330 {
1331  pThisTab->nOldCurX = nNewX;
1332  pThisTab->nOldCurY = nNewY;
1333  pThisTab->mbOldCursorValid = true;
1334 }
1335 
1337 {
1338  pThisTab->mbOldCursorValid = false;
1339 }
1340 
1341 SCCOL ScViewData::GetPosX( ScHSplitPos eWhich, SCTAB nForTab ) const
1342 {
1344  return 0;
1345 
1346  if (nForTab == -1)
1347  return pThisTab->nPosX[eWhich];
1348 
1349  if (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size())))
1350  return -1;
1351 
1352  return maTabData[nForTab]->nPosX[eWhich];
1353 }
1354 
1355 SCROW ScViewData::GetPosY( ScVSplitPos eWhich, SCTAB nForTab ) const
1356 {
1358  return 0;
1359 
1360  if (nForTab == -1)
1361  return pThisTab->nPosY[eWhich];
1362 
1363  if (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size())))
1364  return -1;
1365 
1366  return maTabData[nForTab]->nPosY[eWhich];
1367 }
1368 
1370 {
1371  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
1372  return -1;
1373 
1374  return maTabData[nTabIndex]->nCurX;
1375 }
1376 
1378 {
1379  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
1380  return -1;
1381 
1382  return maTabData[nTabIndex]->nCurY;
1383 }
1384 
1385 void ScViewData::SetCurXForTab( SCCOL nNewCurX, SCTAB nTabIndex )
1386 {
1387  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
1388  return;
1389 
1390  maTabData[nTabIndex]->nCurX = nNewCurX;
1391 }
1392 
1393 void ScViewData::SetCurYForTab( SCCOL nNewCurY, SCTAB nTabIndex )
1394 {
1395  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
1396  return;
1397 
1398  maTabData[nTabIndex]->nCurY = nNewCurY;
1399 }
1400 
1402 {
1403  nNewMaxCol = std::clamp(nNewMaxCol, SCCOL(0), mrDoc.MaxCol());
1404 
1405  const SCTAB nTab = GetTabNo();
1406  auto GetColWidthPx = [this, nTab](SCCOL nCol) {
1407  const sal_uInt16 nSize = this->mrDoc.GetColWidth(nCol, nTab);
1408  const long nSizePx = ScViewData::ToPixel(nSize, nPPTX);
1409  return nSizePx;
1410  };
1411 
1412  long nTotalPixels = GetLOKWidthHelper().computePosition(nNewMaxCol, GetColWidthPx);
1413 
1414  SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledCol: nNewMaxCol: "
1415  << nNewMaxCol << ", nTotalPixels: " << nTotalPixels);
1416 
1418  GetLOKWidthHelper().insert(nNewMaxCol, nTotalPixels);
1419 
1420  pThisTab->nMaxTiledCol = nNewMaxCol;
1421 }
1422 
1424 {
1425  if (nNewMaxRow < 0)
1426  nNewMaxRow = 0;
1427  if (nNewMaxRow > MAXTILEDROW)
1428  nNewMaxRow = MAXTILEDROW;
1429 
1430  const SCTAB nTab = GetTabNo();
1431  auto GetRowHeightPx = [this, nTab](SCROW nRow) {
1432  const sal_uInt16 nSize = this->mrDoc.GetRowHeight(nRow, nTab);
1433  const long nSizePx = ScViewData::ToPixel(nSize, nPPTY);
1434  return nSizePx;
1435  };
1436 
1437  long nTotalPixels = GetLOKHeightHelper().computePosition(nNewMaxRow, GetRowHeightPx);
1438 
1439  SAL_INFO("sc.lok.docsize", "ScViewData::SetMaxTiledRow: nNewMaxRow: "
1440  << nNewMaxRow << ", nTotalPixels: " << nTotalPixels);
1441 
1443  GetLOKHeightHelper().insert(nNewMaxRow, nTotalPixels);
1444 
1445  pThisTab->nMaxTiledRow = nNewMaxRow;
1446 }
1447 
1449  vcl::Window* pWin, const ScPatternAttr* pPattern,
1450  bool bForceToTop, bool bInPrintTwips )
1451 {
1452  Point aCellTopLeft = bInPrintTwips ?
1453  GetPrintTwipsPos(nPosX, nPosY) : GetScrPos(nPosX, nPosY, eWhich, true);
1454  return ScEditUtil(&mrDoc, nPosX, nPosY, nTabNo, aCellTopLeft,
1455  pWin, nPPTX, nPPTY, GetZoomX(), GetZoomY(), bInPrintTwips ).
1456  GetEditArea( pPattern, bForceToTop );
1457 }
1458 
1460  ScEditEngineDefaulter* pNewEngine,
1461  vcl::Window* pWin, SCCOL nNewX, SCROW nNewY )
1462 {
1463  bool bLayoutRTL = mrDoc.IsLayoutRTL(nTabNo);
1464  ScHSplitPos eHWhich = WhichH(eWhich);
1465  ScVSplitPos eVWhich = WhichV(eWhich);
1466  bool bLOKActive = comphelper::LibreOfficeKit::isActive();
1467  bool bLOKPrintTwips = bLOKActive && comphelper::LibreOfficeKit::isCompatFlagSet(
1468  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
1469 
1470  bool bWasThere = false;
1471  if (pEditView[eWhich])
1472  {
1473  // if the view is already there don't call anything that changes the cursor position
1474  if (bEditActive[eWhich])
1475  {
1476  bWasThere = true;
1477  }
1478  else
1479  {
1480  lcl_LOKRemoveWindow(GetViewShell(), eWhich);
1481  pEditView[eWhich]->SetEditEngine(pNewEngine);
1482  }
1483 
1484  if (pEditView[eWhich]->GetWindow() != pWin)
1485  {
1486  lcl_LOKRemoveWindow(GetViewShell(), eWhich);
1487  pEditView[eWhich]->SetWindow(pWin);
1488  OSL_FAIL("EditView Window has changed");
1489  }
1490  }
1491  else
1492  {
1493  pEditView[eWhich].reset(new EditView( pNewEngine, pWin ));
1494 
1495  if (bLOKActive)
1496  {
1497  // We can broadcast the view-cursor message in print-twips for all views.
1498  pEditView[eWhich]->SetBroadcastLOKViewCursor(bLOKPrintTwips);
1499  pEditView[eWhich]->RegisterViewShell(pView);
1500  }
1501  }
1502 
1503  // add windows from other views
1504  if (!bWasThere && bLOKActive)
1505  {
1506  ScTabViewShell* pThisViewShell = GetViewShell();
1507  SCTAB nThisTabNo = GetTabNo();
1508  auto lAddWindows =
1509  [pThisViewShell, nThisTabNo, eWhich] (ScTabViewShell* pOtherViewShell)
1510  {
1511  ScViewData& rOtherViewData = pOtherViewShell->GetViewData();
1512  SCTAB nOtherTabNo = rOtherViewData.GetTabNo();
1513  if (nThisTabNo == nOtherTabNo)
1514  pOtherViewShell->AddWindowToForeignEditView(pThisViewShell, eWhich);
1515  };
1516 
1517  SfxLokHelper::forEachOtherView(pThisViewShell, lAddWindows);
1518  }
1519 
1520  // if view is gone then during IdleFormat sometimes a cursor is drawn
1521 
1522  EEControlBits nEC = pNewEngine->GetControlWord();
1523  pNewEngine->SetControlWord(nEC & ~EEControlBits::DOIDLEFORMAT);
1524 
1525  EVControlBits nVC = pEditView[eWhich]->GetControlWord();
1526  pEditView[eWhich]->SetControlWord(nVC & ~EVControlBits::AUTOSCROLL);
1527 
1528  bEditActive[eWhich] = true;
1529 
1530  const ScPatternAttr* pPattern = mrDoc.GetPattern(nNewX, nNewY, nTabNo);
1531  SvxCellHorJustify eJust = pPattern->GetItem( ATTR_HOR_JUSTIFY ).GetValue();
1532 
1533  bool bBreak = ( eJust == SvxCellHorJustify::Block ) ||
1534  pPattern->GetItem(ATTR_LINEBREAK).GetValue();
1535 
1536  bool bAsianVertical = pNewEngine->IsVertical(); // set by InputHandler
1537 
1538  tools::Rectangle aPixRect = ScEditUtil(&mrDoc, nNewX, nNewY, nTabNo, GetScrPos(nNewX, nNewY, eWhich),
1539  pWin, nPPTX,nPPTY,GetZoomX(),GetZoomY() ).
1540  GetEditArea( pPattern, true );
1541 
1542  tools::Rectangle aPTwipsRect;
1543  if (bLOKPrintTwips)
1544  {
1545  aPTwipsRect = ScEditUtil(&mrDoc, nNewX, nNewY, nTabNo, GetPrintTwipsPos(nNewX, nNewY),
1546  pWin, nPPTX, nPPTY, GetZoomX(), GetZoomY(), true /* bInPrintTwips */).
1547  GetEditArea(pPattern, true);
1548  }
1549 
1550  // when right-aligned, leave space for the cursor
1551  // in vertical mode, editing is always right-aligned
1552  if ( GetEditAdjust() == SvxAdjust::Right || bAsianVertical )
1553  {
1554  aPixRect.AdjustRight(1 );
1555  if (bLOKPrintTwips)
1556  aPTwipsRect.AdjustRight(TWIPS_PER_PIXEL);
1557  }
1558 
1559  if (bLOKPrintTwips)
1560  {
1561  if (!pEditView[eWhich]->HasLOKSpecialPositioning())
1562  pEditView[eWhich]->InitLOKSpecialPositioning(MapUnit::MapTwip, aPTwipsRect, Point());
1563  else
1564  pEditView[eWhich]->SetLOKSpecialOutputArea(aPTwipsRect);
1565  }
1566 
1567  tools::Rectangle aOutputArea = pWin->PixelToLogic( aPixRect, GetLogicMode() );
1568  pEditView[eWhich]->SetOutputArea( aOutputArea );
1569 
1570  if ( bActive && eWhich == GetActivePart() )
1571  {
1572  // keep the part that has the active edit view available after
1573  // switching sheets or reference input on a different part
1574  eEditActivePart = eWhich;
1575 
1576  // modify members nEditCol etc. only if also extending for needed area
1577  nEditCol = nNewX;
1578  nEditRow = nNewY;
1579  const ScMergeAttr* pMergeAttr = &pPattern->GetItem(ATTR_MERGE);
1581  if (pMergeAttr->GetColMerge() > 1)
1582  nEditEndCol += pMergeAttr->GetColMerge() - 1;
1584  if (pMergeAttr->GetRowMerge() > 1)
1585  nEditEndRow += pMergeAttr->GetRowMerge() - 1;
1587 
1588  // For growing use only the alignment value from the attribute, numbers
1589  // (existing or started) with default alignment extend to the right.
1590  bool bGrowCentered = ( eJust == SvxCellHorJustify::Center );
1591  bool bGrowToLeft = ( eJust == SvxCellHorJustify::Right ); // visual left
1592  if ( bAsianVertical )
1593  bGrowCentered = bGrowToLeft = false; // keep old behavior for asian mode
1594 
1595  long nSizeXPix, nSizeXPTwips = 0;
1596 
1597  const long nGridWidthPx = pView->GetGridWidth(eHWhich);
1598  const long nGridHeightPx = pView->GetGridHeight(eVWhich);
1599  long nGridWidthTwips = 0, nGridHeightTwips = 0;
1600  if (bLOKPrintTwips)
1601  {
1602  Size aGridSize(nGridWidthPx, nGridHeightPx);
1603  const MapMode& rWinMapMode = GetLogicMode();
1604  aGridSize = OutputDevice::LogicToLogic(
1605  pWin->PixelToLogic(aGridSize, rWinMapMode),
1606  rWinMapMode, MapMode(MapUnit::MapTwip));
1607  nGridWidthTwips = aGridSize.Width();
1608  nGridHeightTwips = aGridSize.Height();
1609  }
1610 
1611  if (bBreak && !bAsianVertical)
1612  {
1613  nSizeXPix = aPixRect.GetWidth(); // papersize -> no horizontal scrolling
1614  if (bLOKPrintTwips)
1615  nSizeXPTwips = aPTwipsRect.GetWidth();
1616  }
1617  else
1618  {
1619  OSL_ENSURE(pView,"no View for EditView");
1620 
1621  if ( bGrowCentered )
1622  {
1623  // growing into both directions until one edge is reached
1625  long nLeft = aPixRect.Left();
1626  long nRight = nGridWidthPx - aPixRect.Right();
1627  nSizeXPix = aPixRect.GetWidth() + 2 * std::min( nLeft, nRight );
1628  if (bLOKPrintTwips)
1629  {
1630  long nLeftPTwips = aPTwipsRect.Left();
1631  long nRightPTwips = nGridWidthTwips - aPTwipsRect.Right();
1632  nSizeXPTwips = aPTwipsRect.GetWidth() + 2 * std::min(nLeftPTwips, nRightPTwips);
1633  }
1634  }
1635  else if ( bGrowToLeft )
1636  {
1637  nSizeXPix = aPixRect.Right(); // space that's available in the window when growing to the left
1638  if (bLOKPrintTwips)
1639  nSizeXPTwips = aPTwipsRect.Right();
1640  }
1641  else
1642  {
1643  nSizeXPix = nGridWidthPx - aPixRect.Left();
1644  if (bLOKPrintTwips)
1645  nSizeXPTwips = nGridWidthTwips - aPTwipsRect.Left();
1646  }
1647 
1648  if ( nSizeXPix <= 0 )
1649  {
1650  nSizeXPix = aPixRect.GetWidth(); // editing outside to the right of the window -> keep cell width
1651  if (bLOKPrintTwips)
1652  nSizeXPTwips = aPTwipsRect.GetWidth();
1653  }
1654  }
1655  OSL_ENSURE(pView,"no View for EditView");
1656  long nSizeYPix = nGridHeightPx - aPixRect.Top();
1657  long nSizeYPTwips = bLOKPrintTwips ? (nGridHeightTwips - aPTwipsRect.Top()) : 0;
1658 
1659  if ( nSizeYPix <= 0 )
1660  {
1661  nSizeYPix = aPixRect.GetHeight(); // editing outside below the window -> keep cell height
1662  if (bLOKPrintTwips)
1663  nSizeYPTwips = aPTwipsRect.GetHeight();
1664  }
1665 
1666  Size aPaperSize = pView->GetActiveWin()->PixelToLogic( Size( nSizeXPix, nSizeYPix ), GetLogicMode() );
1667  Size aPaperSizePTwips(nSizeXPTwips, nSizeYPTwips);
1668  if ( bBreak && !bAsianVertical && SC_MOD()->GetInputOptions().GetTextWysiwyg() )
1669  {
1670  // if text is formatted for printer, use the exact same paper width
1671  // (and same line breaks) as for output.
1672 
1673  Fraction aFract(1,1);
1674  tools::Rectangle aUtilRect = ScEditUtil(&mrDoc, nNewX, nNewY, nTabNo, Point(0, 0), pWin,
1675  HMM_PER_TWIPS, HMM_PER_TWIPS, aFract, aFract ).GetEditArea( pPattern, false );
1676  aPaperSize.setWidth( aUtilRect.GetWidth() );
1677  if (bLOKPrintTwips)
1678  aPaperSizePTwips.setWidth(OutputDevice::LogicToLogic(
1679  aUtilRect.GetWidth(), MapUnit::Map100thMM, MapUnit::MapTwip));
1680  }
1681 
1682  pNewEngine->SetPaperSize( aPaperSize );
1683  if (bLOKPrintTwips)
1684  pNewEngine->SetLOKSpecialPaperSize(aPaperSizePTwips);
1685 
1686  // sichtbarer Ausschnitt
1687  Size aPaper = pNewEngine->GetPaperSize();
1688  tools::Rectangle aVis = pEditView[eWhich]->GetVisArea();
1689  tools::Rectangle aVisPTwips;
1690  if (bLOKPrintTwips)
1691  aVisPTwips = pEditView[eWhich]->GetLOKSpecialVisArea();
1692 
1693  long nDiff = aVis.Right() - aVis.Left();
1694  long nDiffPTwips = bLOKPrintTwips ? (aVisPTwips.Right() - aVisPTwips.Left()) : 0;
1695  if ( GetEditAdjust() == SvxAdjust::Right )
1696  {
1697  aVis.SetRight( aPaper.Width() - 1 );
1698  if (bLOKPrintTwips)
1699  aVisPTwips.SetRight( aPaperSizePTwips.Width() - 1 );
1700  bMoveArea = !bLayoutRTL;
1701  }
1702  else if ( GetEditAdjust() == SvxAdjust::Center )
1703  {
1704  aVis.SetRight( ( aPaper.Width() - 1 + nDiff ) / 2 );
1705  if (bLOKPrintTwips)
1706  aVisPTwips.SetRight( ( aPaperSizePTwips.Width() - 1 + nDiffPTwips ) / 2 );
1707  bMoveArea = true; // always
1708  }
1709  else
1710  {
1711  aVis.SetRight( nDiff );
1712  if (bLOKPrintTwips)
1713  aVisPTwips.SetRight(nDiffPTwips);
1714  bMoveArea = bLayoutRTL;
1715  }
1716  aVis.SetLeft( aVis.Right() - nDiff );
1717  if (bLOKPrintTwips)
1718  aVisPTwips.SetLeft(aVisPTwips.Right() - nDiffPTwips);
1719  // #i49561# Important note:
1720  // The set offset of the visible area of the EditView for centered and
1721  // right alignment in horizontal layout is consider by instances of
1722  // class <ScEditObjectViewForwarder> in its methods <LogicToPixel(..)>
1723  // and <PixelToLogic(..)>. This is needed for the correct visibility
1724  // of paragraphs in edit mode at the accessibility API.
1725  pEditView[eWhich]->SetVisArea(aVis);
1726  if (bLOKPrintTwips)
1727  pEditView[eWhich]->SetLOKSpecialVisArea(aVisPTwips);
1728  // UpdateMode has been disabled in ScInputHandler::StartTable
1729  // must be enabled before EditGrowY (GetTextHeight)
1730  pNewEngine->SetUpdateMode( true );
1731 
1732  pNewEngine->SetStatusEventHdl( LINK( this, ScViewData, EditEngineHdl ) );
1733 
1734  EditGrowY( true ); // adjust to existing text content
1735  EditGrowX();
1736 
1737  Point aDocPos = pEditView[eWhich]->GetWindowPosTopLeft(0);
1738  if (aDocPos.Y() < aOutputArea.Top())
1739  pEditView[eWhich]->Scroll( 0, aOutputArea.Top() - aDocPos.Y() );
1740  }
1741 
1742  // here bEditActive needs to be set already
1743  // (due to Map-Mode during Paint)
1744  if (!bWasThere)
1745  pNewEngine->InsertView(pEditView[eWhich].get());
1746 
1747  // background color of the cell
1748  Color aBackCol = pPattern->GetItem(ATTR_BACKGROUND).GetColor();
1749 
1750  ScModule* pScMod = SC_MOD();
1751  if ( aBackCol.GetTransparency() > 0 )
1752  {
1753  aBackCol = pScMod->GetColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
1754  }
1755  pEditView[eWhich]->SetBackgroundColor( aBackCol );
1756 
1757  pEditView[eWhich]->Invalidate(); // needed?
1758  // needed, if position changed
1759 }
1760 
1761 IMPL_LINK( ScViewData, EditEngineHdl, EditStatus&, rStatus, void )
1762 {
1763  EditStatusFlags nStatus = rStatus.GetStatusWord();
1764  if (nStatus & (EditStatusFlags::HSCROLL | EditStatusFlags::TextHeightChanged | EditStatusFlags::TEXTWIDTHCHANGED | EditStatusFlags::CURSOROUT))
1765  {
1766  EditGrowY();
1767  EditGrowX();
1768 
1769  if (nStatus & EditStatusFlags::CURSOROUT)
1770  {
1771  ScSplitPos eWhich = GetActivePart();
1772  if (pEditView[eWhich])
1773  pEditView[eWhich]->ShowCursor(false);
1774  }
1775  }
1776 }
1777 
1779 {
1780  // It is insane to call EditGrowX while the output area is already growing.
1781  // That could occur because of the call to SetDefaultItem later.
1782  // We end up with wrong start/end edit columns and the changes
1783  // to the output area performed by the inner call to this method are
1784  // useless since they are discarded by the outer call.
1785  if (bGrowing)
1786  return;
1787 
1788  comphelper::FlagRestorationGuard aFlagGuard(bGrowing, true);
1789 
1790  bool bLOKActive = comphelper::LibreOfficeKit::isActive();
1791  bool bLOKPrintTwips = bLOKActive && comphelper::LibreOfficeKit::isCompatFlagSet(
1792  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
1793 
1794  ScDocument& rLocalDoc = GetDocument();
1795 
1796  ScSplitPos eWhich = GetActivePart();
1797  ScHSplitPos eHWhich = WhichH(eWhich);
1798  EditView* pCurView = pEditView[eWhich].get();
1799 
1800  if ( !pCurView || !bEditActive[eWhich])
1801  return;
1802 
1803  bool bLayoutRTL = rLocalDoc.IsLayoutRTL( nTabNo );
1804 
1805  ScEditEngineDefaulter* pEngine =
1806  static_cast<ScEditEngineDefaulter*>( pCurView->GetEditEngine() );
1807  vcl::Window* pWin = pCurView->GetWindow();
1808 
1809  // Get the left- and right-most column positions.
1810  SCCOL nLeft = GetPosX(eHWhich);
1811  SCCOL nRight = nLeft + VisibleCellsX(eHWhich);
1812 
1813  Size aSize = pEngine->GetPaperSize();
1814  Size aSizePTwips;
1815  if (bLOKPrintTwips)
1816  aSizePTwips = pEngine->GetLOKSpecialPaperSize();
1817 
1818  tools::Rectangle aArea = pCurView->GetOutputArea();
1819  tools::Rectangle aAreaPTwips;
1820  if (bLOKPrintTwips)
1821  aAreaPTwips = pCurView->GetLOKSpecialOutputArea();
1822 
1823  long nOldRight = aArea.Right();
1824 
1825  // Margin is already included in the original width.
1826  long nTextWidth = pEngine->CalcTextWidth();
1827 
1828  bool bChanged = false;
1829  bool bAsianVertical = pEngine->IsVertical();
1830 
1831  // get bGrow... variables the same way as in SetEditEngine
1832  const ScPatternAttr* pPattern = rLocalDoc.GetPattern( nEditCol, nEditRow, nTabNo );
1833  SvxCellHorJustify eJust = pPattern->GetItem( ATTR_HOR_JUSTIFY ).GetValue();
1834  bool bGrowCentered = ( eJust == SvxCellHorJustify::Center );
1835  bool bGrowToLeft = ( eJust == SvxCellHorJustify::Right ); // visual left
1836  bool bGrowBackwards = bGrowToLeft; // logical left
1837  if ( bLayoutRTL )
1838  bGrowBackwards = !bGrowBackwards; // invert on RTL sheet
1839  if ( bAsianVertical )
1840  bGrowCentered = bGrowToLeft = bGrowBackwards = false; // keep old behavior for asian mode
1841 
1842  bool bUnevenGrow = false;
1843  if ( bGrowCentered )
1844  {
1845  while (aArea.GetWidth() + 0 < nTextWidth && ( nEditStartCol > nLeft || nEditEndCol < nRight ) )
1846  {
1847  long nLogicLeft = 0;
1848  long nLogicLeftPTwips = 0;
1849  if ( nEditStartCol > nLeft )
1850  {
1851  --nEditStartCol;
1852  long nColWidth = rLocalDoc.GetColWidth( nEditStartCol, nTabNo );
1853  long nLeftPix = ToPixel( nColWidth, nPPTX );
1854  nLogicLeft = pWin->PixelToLogic(Size(nLeftPix,0)).Width();
1855  if (bLOKPrintTwips)
1856  nLogicLeftPTwips = nColWidth;
1857  }
1858  long nLogicRight = 0;
1859  long nLogicRightPTwips = 0;
1860  if ( nEditEndCol < nRight )
1861  {
1862  ++nEditEndCol;
1863  long nColWidth = rLocalDoc.GetColWidth( nEditEndCol, nTabNo );
1864  long nRightPix = ToPixel( nColWidth, nPPTX );
1865  nLogicRight = pWin->PixelToLogic(Size(nRightPix,0)).Width();
1866  if (bLOKPrintTwips)
1867  nLogicRightPTwips = nColWidth;
1868  }
1869 
1870  aArea.AdjustLeft( -(bLayoutRTL ? nLogicRight : nLogicLeft) );
1871  aArea.AdjustRight(bLayoutRTL ? nLogicLeft : nLogicRight );
1872  if (bLOKPrintTwips)
1873  {
1874  aAreaPTwips.AdjustLeft( -(bLayoutRTL ? nLogicRightPTwips : nLogicLeftPTwips) );
1875  aAreaPTwips.AdjustRight(bLayoutRTL ? nLogicLeftPTwips : nLogicRightPTwips );
1876  }
1877 
1878  if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 )
1879  {
1880  long nCenter = ( aArea.Left() + aArea.Right() ) / 2;
1881  long nHalf = aSize.Width() / 2;
1882  aArea.SetLeft( nCenter - nHalf + 1 );
1883  aArea.SetRight( nCenter + aSize.Width() - nHalf - 1 );
1884 
1885  if (bLOKPrintTwips)
1886  {
1887  long nCenterPTwips = ( aAreaPTwips.Left() + aAreaPTwips.Right() ) / 2;
1888  long nHalfPTwips = aSizePTwips.Width() / 2;
1889  aAreaPTwips.SetLeft( nCenterPTwips - nHalfPTwips + 1 );
1890  aAreaPTwips.SetRight( nCenterPTwips + aSizePTwips.Width() - nHalfPTwips - 1 );
1891  }
1892  }
1893 
1894  bChanged = true;
1895  if ( nLogicLeft != nLogicRight )
1896  bUnevenGrow = true;
1897  }
1898  }
1899  else if ( bGrowBackwards )
1900  {
1901  while (aArea.GetWidth() + 0 < nTextWidth && nEditStartCol > nLeft)
1902  {
1903  --nEditStartCol;
1904  long nColWidth = rLocalDoc.GetColWidth( nEditStartCol, nTabNo );
1905  long nPix = ToPixel( nColWidth, nPPTX );
1906  long nLogicWidth = pWin->PixelToLogic(Size(nPix,0)).Width();
1907  long& nLogicWidthPTwips = nColWidth;
1908 
1909  if ( !bLayoutRTL )
1910  {
1911  aArea.AdjustLeft( -nLogicWidth );
1912  if (bLOKPrintTwips)
1913  aAreaPTwips.AdjustLeft( -nLogicWidthPTwips );
1914  }
1915  else
1916  {
1917  aArea.AdjustRight(nLogicWidth );
1918  if (bLOKPrintTwips)
1919  aAreaPTwips.AdjustRight(nLogicWidthPTwips);
1920  }
1921 
1922  if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 )
1923  {
1924  if ( !bLayoutRTL )
1925  {
1926  aArea.SetLeft( aArea.Right() - aSize.Width() + 1 );
1927  if (bLOKPrintTwips)
1928  aAreaPTwips.SetLeft( aAreaPTwips.Right() - aSizePTwips.Width() + 1 );
1929  }
1930  else
1931  {
1932  aArea.SetRight( aArea.Left() + aSize.Width() - 1 );
1933  if (bLOKPrintTwips)
1934  aAreaPTwips.SetRight( aAreaPTwips.Left() + aSizePTwips.Width() - 1 );
1935  }
1936  }
1937 
1938  bChanged = true;
1939  }
1940  }
1941  else
1942  {
1943  while (aArea.GetWidth() + 0 < nTextWidth && nEditEndCol < nRight)
1944  {
1945  ++nEditEndCol;
1946  long nColWidth = rLocalDoc.GetColWidth( nEditEndCol, nTabNo );
1947  long nPix = ToPixel( nColWidth, nPPTX );
1948  long nLogicWidth = pWin->PixelToLogic(Size(nPix,0)).Width();
1949  long& nLogicWidthPTwips = nColWidth;
1950  if ( bLayoutRTL )
1951  {
1952  aArea.AdjustLeft( -nLogicWidth );
1953  if (bLOKPrintTwips)
1954  aAreaPTwips.AdjustLeft( -nLogicWidthPTwips );
1955  }
1956  else
1957  {
1958  aArea.AdjustRight(nLogicWidth );
1959  if (bLOKPrintTwips)
1960  aAreaPTwips.AdjustRight(nLogicWidthPTwips);
1961  }
1962 
1963  if ( aArea.Right() > aArea.Left() + aSize.Width() - 1 )
1964  {
1965  if ( bLayoutRTL )
1966  {
1967  aArea.SetLeft( aArea.Right() - aSize.Width() + 1 );
1968  if (bLOKPrintTwips)
1969  aAreaPTwips.SetLeft( aAreaPTwips.Right() - aSizePTwips.Width() + 1 );
1970  }
1971  else
1972  {
1973  aArea.SetRight( aArea.Left() + aSize.Width() - 1 );
1974  if (bLOKPrintTwips)
1975  aAreaPTwips.SetRight( aAreaPTwips.Left() + aSizePTwips.Width() - 1 );
1976  }
1977  }
1978 
1979  bChanged = true;
1980  }
1981  }
1982 
1983  if (!bChanged)
1984  return;
1985 
1986  if ( bMoveArea || bGrowCentered || bGrowBackwards || bLayoutRTL )
1987  {
1988  tools::Rectangle aVis = pCurView->GetVisArea();
1989  tools::Rectangle aVisPTwips;
1990  if (bLOKPrintTwips)
1991  aVisPTwips = pCurView->GetLOKSpecialVisArea();
1992 
1993  if ( bGrowCentered )
1994  {
1995  // switch to center-aligned (undo?) and reset VisArea to center
1996 
1997  pEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Center, EE_PARA_JUST ) );
1998 
1999  long nCenter = aSize.Width() / 2;
2000  long nVisSize = aArea.GetWidth();
2001  aVis.SetLeft( nCenter - nVisSize / 2 );
2002  aVis.SetRight( aVis.Left() + nVisSize - 1 );
2003 
2004  if (bLOKPrintTwips)
2005  {
2006  long nCenterPTwips = aSizePTwips.Width() / 2;
2007  long nVisSizePTwips = aAreaPTwips.GetWidth();
2008  aVisPTwips.SetLeft( nCenterPTwips - nVisSizePTwips / 2 );
2009  aVisPTwips.SetRight( aVisPTwips.Left() + nVisSizePTwips - 1 );
2010  }
2011  }
2012  else if ( bGrowToLeft )
2013  {
2014  // switch to right-aligned (undo?) and reset VisArea to the right
2015 
2016  pEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Right, EE_PARA_JUST ) );
2017 
2018  aVis.SetRight( aSize.Width() - 1 );
2019  aVis.SetLeft( aSize.Width() - aArea.GetWidth() ); // with the new, increased area
2020 
2021  if (bLOKPrintTwips)
2022  {
2023  aVisPTwips.SetRight( aSizePTwips.Width() - 1 );
2024  aVisPTwips.SetLeft( aSizePTwips.Width() - aAreaPTwips.GetWidth() ); // with the new, increased area
2025  }
2026  }
2027  else
2028  {
2029  // switch to left-aligned (undo?) and reset VisArea to the left
2030 
2031  pEngine->SetDefaultItem( SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ) );
2032 
2033  long nMove = aVis.Left();
2034  aVis.SetLeft( 0 );
2035  aVis.AdjustRight( -nMove );
2036 
2037  if (bLOKPrintTwips)
2038  {
2039  long nMovePTwips = aVisPTwips.Left();
2040  aVisPTwips.SetLeft( 0 );
2041  aVisPTwips.AdjustRight( -nMovePTwips );
2042  }
2043  }
2044 
2045  pCurView->SetVisArea( aVis );
2046  if (bLOKPrintTwips)
2047  pCurView->SetLOKSpecialVisArea( aVisPTwips );
2048 
2049  bMoveArea = false;
2050  }
2051 
2052  if (bLOKPrintTwips)
2053  pCurView->SetLOKSpecialOutputArea(aAreaPTwips);
2054 
2055  pCurView->SetOutputArea(aArea);
2056 
2057  // In vertical mode, the whole text is moved to the next cell (right-aligned),
2058  // so everything must be repainted. Otherwise, paint only the new area.
2059  // If growing in centered alignment, if the cells left and right have different sizes,
2060  // the whole text will move, and may not even obscure all of the original display.
2061  if ( bUnevenGrow )
2062  {
2063  aArea.SetLeft( pWin->PixelToLogic( Point(0,0) ).X() );
2064  aArea.SetRight( pWin->PixelToLogic( aScrSize ).Width() );
2065  }
2066  else if ( !bAsianVertical && !bGrowToLeft && !bGrowCentered )
2067  aArea.SetLeft( nOldRight );
2068  pWin->Invalidate(aArea);
2069 
2070  // invalidate other views
2071  pCurView->InvalidateOtherViewWindows(aArea);
2072 }
2073 
2074 void ScViewData::EditGrowY( bool bInitial )
2075 {
2076  if (bGrowing)
2077  return;
2078 
2079  comphelper::FlagRestorationGuard aFlagGuard(bGrowing, true);
2080 
2081  bool bLOKActive = comphelper::LibreOfficeKit::isActive();
2082  bool bLOKPrintTwips = bLOKActive && comphelper::LibreOfficeKit::isCompatFlagSet(
2083  comphelper::LibreOfficeKit::Compat::scPrintTwipsMsgs);
2084 
2085  ScSplitPos eWhich = GetActivePart();
2086  ScVSplitPos eVWhich = WhichV(eWhich);
2087  EditView* pCurView = pEditView[eWhich].get();
2088 
2089  if ( !pCurView || !bEditActive[eWhich])
2090  return;
2091 
2092  EVControlBits nControl = pEditView[eWhich]->GetControlWord();
2093  if ( nControl & EVControlBits::AUTOSCROLL )
2094  {
2095  // if end of screen had already been reached and scrolling enabled,
2096  // don't further try to grow the edit area
2097 
2098  pCurView->SetOutputArea( pCurView->GetOutputArea() ); // re-align to pixels
2099  return;
2100  }
2101 
2102  EditEngine* pEngine = pCurView->GetEditEngine();
2103  vcl::Window* pWin = pCurView->GetWindow();
2104 
2105  SCROW nBottom = GetPosY(eVWhich) + VisibleCellsY(eVWhich);
2106 
2107  Size aSize = pEngine->GetPaperSize();
2108  Size aSizePTwips;
2109  tools::Rectangle aArea = pCurView->GetOutputArea();
2110  tools::Rectangle aAreaPTwips;
2111 
2112  if (bLOKPrintTwips)
2113  {
2114  aSizePTwips = pEngine->GetLOKSpecialPaperSize();
2115  aAreaPTwips = pCurView->GetLOKSpecialOutputArea();
2116  }
2117 
2118  long nOldBottom = aArea.Bottom();
2119  long nTextHeight = pEngine->GetTextHeight();
2120 
2121  // When editing a formula in a cell with optimal height, allow a larger portion
2122  // to be clipped before extending to following rows, to avoid obscuring cells for
2123  // reference input (next row is likely to be useful in formulas).
2124  long nAllowedExtra = SC_GROWY_SMALL_EXTRA;
2126  pEngine->GetParagraphCount() <= 1 )
2127  {
2128  // If the (only) paragraph starts with a '=', it's a formula.
2129  // If this is the initial call and the text is empty, allow the larger value, too,
2130  // because this occurs in the normal progress of editing a formula.
2131  // Subsequent calls with empty text might involve changed attributes (including
2132  // font height), so they are treated like normal text.
2133  OUString aText = pEngine->GetText( 0 );
2134  if ( ( aText.isEmpty() && bInitial ) || aText.startsWith("=") )
2135  nAllowedExtra = SC_GROWY_BIG_EXTRA;
2136  }
2137 
2138  bool bChanged = false;
2139  bool bMaxReached = false;
2140  while (aArea.GetHeight() + nAllowedExtra < nTextHeight && nEditEndRow < nBottom && !bMaxReached)
2141  {
2142  ++nEditEndRow;
2143  ScDocument& rLocalDoc = GetDocument();
2144  long nRowHeight = rLocalDoc.GetRowHeight( nEditEndRow, nTabNo );
2145  long nPix = ToPixel( nRowHeight, nPPTY );
2146  aArea.AdjustBottom(pWin->PixelToLogic(Size(0,nPix)).Height() );
2147  if (bLOKPrintTwips)
2148  aAreaPTwips.AdjustBottom(nRowHeight);
2149 
2150  if ( aArea.Bottom() > aArea.Top() + aSize.Height() - 1 )
2151  {
2152  aArea.SetBottom( aArea.Top() + aSize.Height() - 1 );
2153  if (bLOKPrintTwips)
2154  aAreaPTwips.SetBottom( aAreaPTwips.Top() + aSizePTwips.Height() - 1 );
2155  bMaxReached = true; // don't occupy more cells beyond paper size
2156  }
2157 
2158  bChanged = true;
2159  nAllowedExtra = SC_GROWY_SMALL_EXTRA; // larger value is only for first row
2160  }
2161 
2162  if (!bChanged)
2163  return;
2164 
2165  if (bLOKPrintTwips)
2166  pCurView->SetLOKSpecialOutputArea(aAreaPTwips);
2167 
2168  pCurView->SetOutputArea(aArea);
2169 
2170  if (nEditEndRow >= nBottom || bMaxReached)
2171  {
2172  if (!(nControl & EVControlBits::AUTOSCROLL))
2173  pCurView->SetControlWord( nControl | EVControlBits::AUTOSCROLL );
2174  }
2175 
2176  aArea.SetTop( nOldBottom );
2177  pWin->Invalidate(aArea);
2178 
2179  // invalidate other views
2180  pCurView->InvalidateOtherViewWindows(aArea);
2181 }
2182 
2184 {
2185  EditEngine* pEngine = nullptr;
2186  for (sal_uInt16 i=0; i<4; i++)
2187  if (pEditView[i])
2188  {
2189  if (bEditActive[i])
2190  {
2191  lcl_LOKRemoveWindow(GetViewShell(), static_cast<ScSplitPos>(i));
2192  pEngine = pEditView[i]->GetEditEngine();
2193  pEngine->RemoveView(pEditView[i].get());
2194  pEditView[i]->SetOutputArea( tools::Rectangle() );
2195  }
2196  bEditActive[i] = false;
2197  }
2198 
2199  if (pEngine)
2201 }
2202 
2204 {
2205  EditEngine* pEngine = nullptr;
2206  for (sal_uInt16 i=0; i<4; i++)
2207  if (pEditView[i])
2208  {
2209  if (bEditActive[i])
2210  {
2211  pEngine = pEditView[i]->GetEditEngine();
2212  if (pEngine)
2213  pEngine->RemoveView(pEditView[i].get());
2214  }
2215  pEditView[i].reset();
2216  }
2217 }
2218 
2219 void ScViewData::GetEditView( ScSplitPos eWhich, EditView*& rViewPtr, SCCOL& rCol, SCROW& rRow )
2220 {
2221  rViewPtr = pEditView[eWhich].get();
2222  rCol = nEditCol;
2223  rRow = nEditRow;
2224 }
2225 
2227 {
2228  EnsureTabDataSize(nNewTab + 1);
2229 
2230  if (!maTabData[nNewTab])
2231  {
2232  maTabData[nNewTab].reset(new ScViewDataTable(&mrDoc));
2233 
2234  maTabData[nNewTab]->eZoomType = eDefZoomType;
2235  maTabData[nNewTab]->aZoomX = aDefZoomX;
2236  maTabData[nNewTab]->aZoomY = aDefZoomY;
2237  maTabData[nNewTab]->aPageZoomX = aDefPageZoomX;
2238  maTabData[nNewTab]->aPageZoomY = aDefPageZoomY;
2239  }
2240 }
2241 
2243 {
2244  for (const auto& rTab : maMarkData)
2245  CreateTabData(rTab);
2246 }
2247 
2249 {
2250  if (nSize > maTabData.size())
2251  maTabData.resize(nSize);
2252 }
2253 
2255 {
2256  if (!ValidTab(nNewTab))
2257  {
2258  OSL_FAIL("wrong sheet number");
2259  return;
2260  }
2261 
2262  nTabNo = nNewTab;
2264  pThisTab = maTabData[nTabNo].get();
2265 
2266  CalcPPT(); // for common column width correction
2267  RecalcPixPos();
2268 }
2269 
2271 {
2272  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
2273  {
2274  return nullptr;
2275  }
2276  return &(maTabData[nTabIndex]->aWidthHelper);
2277 }
2278 
2280 {
2281  if (!ValidTab(nTabIndex) || (nTabIndex >= static_cast<SCTAB>(maTabData.size())))
2282  {
2283  return nullptr;
2284  }
2285  return &(maTabData[nTabIndex]->aHeightHelper);
2286 }
2287 
2289 {
2290  pThisTab->eWhichActive = eNewActive;
2291 
2292  // Let's hope we find the culprit for tdf#117093
2293  // Don't sanitize the real value (yet?) because this function might be
2294  // called before setting the then corresponding split modes. For which in
2295  // fact then the order should be changed.
2296  assert(eNewActive == pThisTab->SanitizeWhichActive());
2297 }
2298 
2299 Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScHSplitPos eWhich ) const
2300 {
2301  OSL_ENSURE( eWhich==SC_SPLIT_LEFT || eWhich==SC_SPLIT_RIGHT, "wrong position" );
2303  return GetScrPos( nWhereX, nWhereY, ePos );
2304 }
2305 
2306 Point ScViewData::GetScrPos( SCCOL nWhereX, SCROW nWhereY, ScVSplitPos eWhich ) const
2307 {
2308  OSL_ENSURE( eWhich==SC_SPLIT_TOP || eWhich==SC_SPLIT_BOTTOM, "wrong position" );
2310  return GetScrPos( nWhereX, nWhereY, ePos );
2311 }
2312 
2314  bool bAllowNeg, SCTAB nForTab ) const
2315 {
2316  ScHSplitPos eWhichX = SC_SPLIT_LEFT;
2317  ScVSplitPos eWhichY = SC_SPLIT_BOTTOM;
2318  switch( eWhich )
2319  {
2320  case SC_SPLIT_TOPLEFT:
2321  eWhichX = SC_SPLIT_LEFT;
2322  eWhichY = SC_SPLIT_TOP;
2323  break;
2324  case SC_SPLIT_TOPRIGHT:
2325  eWhichX = SC_SPLIT_RIGHT;
2326  eWhichY = SC_SPLIT_TOP;
2327  break;
2328  case SC_SPLIT_BOTTOMLEFT:
2329  eWhichX = SC_SPLIT_LEFT;
2330  eWhichY = SC_SPLIT_BOTTOM;
2331  break;
2332  case SC_SPLIT_BOTTOMRIGHT:
2333  eWhichX = SC_SPLIT_RIGHT;
2334  eWhichY = SC_SPLIT_BOTTOM;
2335  break;
2336  }
2337 
2338  if (nForTab == -1)
2339  nForTab = nTabNo;
2340  bool bForCurTab = (nForTab == nTabNo);
2341  if (!bForCurTab && (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size()))))
2342  {
2343  SAL_WARN("sc.viewdata", "ScViewData::GetScrPos : invalid nForTab = " << nForTab);
2344  nForTab = nTabNo;
2345  bForCurTab = true;
2346  }
2347 
2348  ScViewDataTable* pViewTable = bForCurTab ? pThisTab : maTabData[nForTab].get();
2349 
2350  if (pView)
2351  {
2352  const_cast<ScViewData*>(this)->aScrSize.setWidth( pView->GetGridWidth(eWhichX) );
2353  const_cast<ScViewData*>(this)->aScrSize.setHeight( pView->GetGridHeight(eWhichY) );
2354  }
2355 
2356  sal_uLong nTSize;
2357  bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
2358 
2359 
2360  SCCOL nPosX = GetPosX(eWhichX, nForTab);
2361  long nScrPosX = 0;
2362 
2363  if (bAllowNeg || nWhereX >= nPosX)
2364  {
2365  SCROW nStartPosX = nPosX;
2366  if (bIsTiledRendering)
2367  {
2368  OSL_ENSURE(nPosX == 0, "Unsupported case.");
2369  const auto& rNearest = pViewTable->aWidthHelper.getNearestByIndex(nWhereX - 1);
2370  nStartPosX = rNearest.first + 1;
2371  nScrPosX = rNearest.second;
2372  }
2373 
2374  if (nWhereX >= nStartPosX)
2375  {
2376  for (SCCOL nX = nStartPosX; nX < nWhereX && (bAllowNeg || bIsTiledRendering || nScrPosX <= aScrSize.Width()); nX++)
2377  {
2378  if (nX > mrDoc.MaxCol())
2379  nScrPosX = 0x7FFFFFFF;
2380  else
2381  {
2382  nTSize = mrDoc.GetColWidth(nX, nForTab);
2383  if (nTSize)
2384  {
2385  long nSizeXPix = ToPixel( nTSize, nPPTX );
2386  nScrPosX += nSizeXPix;
2387  }
2388  }
2389  }
2390  }
2391  else
2392  {
2393  for (SCCOL nX = nStartPosX; nX > nWhereX;)
2394  {
2395  --nX;
2396  nTSize = mrDoc.GetColWidth(nX, nForTab);
2397  if (nTSize)
2398  {
2399  long nSizeXPix = ToPixel( nTSize, nPPTX );
2400  nScrPosX -= nSizeXPix;
2401  }
2402  }
2403  }
2404 
2405  }
2406 
2407 
2408  SCROW nPosY = GetPosY(eWhichY, nForTab);
2409  long nScrPosY = 0;
2410 
2411  if (bAllowNeg || nWhereY >= nPosY)
2412  {
2413  SCROW nStartPosY = nPosY;
2414  if (bIsTiledRendering)
2415  {
2416  OSL_ENSURE(nPosY == 0, "Unsupported case.");
2417  const auto& rNearest = pViewTable->aHeightHelper.getNearestByIndex(nWhereY - 1);
2418  nStartPosY = rNearest.first + 1;
2419  nScrPosY = rNearest.second;
2420  }
2421 
2422  if (nWhereY >= nStartPosY)
2423  {
2424  if (bAllowNeg || bIsTiledRendering || nScrPosY <= aScrSize.Height())
2425  {
2426  if (nWhereY - 1 > mrDoc.MaxRow())
2427  nScrPosY = 0x7FFFFFFF;
2428  else if (bAllowNeg || bIsTiledRendering)
2429  {
2430  sal_uLong nSizeYPix = mrDoc.GetScaledRowHeight(nStartPosY, nWhereY - 1, nForTab, nPPTY);
2431  nScrPosY += nSizeYPix;
2432  }
2433  else
2434  {
2435  sal_uLong nMaxHeight = aScrSize.getHeight() - nScrPosY;
2436  sal_uLong nSizeYPix = mrDoc.GetScaledRowHeight(nStartPosY, nWhereY - 1, nForTab, nPPTY, &nMaxHeight);
2437  nScrPosY += nSizeYPix;
2438  }
2439  }
2440  }
2441  else
2442  {
2443  for (SCROW nY = nStartPosY; nY > nWhereY;)
2444  {
2445  --nY;
2446  nTSize = mrDoc.GetRowHeight(nY, nForTab);
2447  if (nTSize)
2448  {
2449  long nSizeYPix = ToPixel( nTSize, nPPTY );
2450  nScrPosY -= nSizeYPix;
2451  }
2452  }
2453  }
2454  }
2455 
2456  if (mrDoc.IsLayoutRTL(nForTab))
2457  {
2458  // mirror horizontal position
2459  nScrPosX = aScrSize.Width() - 1 - nScrPosX;
2460  }
2461 
2462  return Point( nScrPosX, nScrPosY );
2463 }
2464 
2466 {
2467  // hidden ones are given 0 sizes by these by default.
2468  // TODO: rewrite this to loop over spans (matters for jumbosheets).
2469  long nPosX = nCol ? mrDoc.GetColWidth(0, nCol - 1, nTabNo) : 0;
2470  // This is now fast as it loops over spans.
2471  long nPosY = nRow ? mrDoc.GetRowHeight(0, nRow - 1, nTabNo) : 0;
2472  // TODO: adjust for RTL layout case.
2473 
2474  return Point(nPosX, nPosY);
2475 }
2476 
2477 Point ScViewData::GetPrintTwipsPosFromTileTwips(const Point& rTileTwipsPos) const
2478 {
2479  const long nPixelX = static_cast<long>(rTileTwipsPos.X() * nPPTX);
2480  const long nPixelY = static_cast<long>(rTileTwipsPos.Y() * nPPTY);
2481  SCCOL nCol = 0;
2482  SCROW nRow = 0;
2483 
2484  // The following call (with bTestMerge = false) will not modify any members.
2485  const_cast<ScViewData*>(this)->GetPosFromPixel(nPixelX, nPixelY, SC_SPLIT_TOPLEFT, nCol, nRow, false /* bTestMerge */);
2486  const Point aPixCellPos = GetScrPos(nCol, nRow, SC_SPLIT_TOPLEFT, true /* bAllowNeg */);
2487  const Point aTileTwipsCellPos(aPixCellPos.X() / nPPTX, aPixCellPos.Y() / nPPTY);
2488  const Point aPrintTwipsCellPos = GetPrintTwipsPos(nCol, nRow);
2489  return aPrintTwipsCellPos + (rTileTwipsPos - aTileTwipsCellPos);
2490 }
2491 
2492 OString ScViewData::describeCellCursorAt(SCCOL nX, SCROW nY, bool bPixelAligned) const
2493 {
2494  const bool bPosSizeInPixels = bPixelAligned;
2495  Point aCellPos = bPosSizeInPixels ? GetScrPos( nX, nY, SC_SPLIT_BOTTOMRIGHT, true ) :
2496  GetPrintTwipsPos(nX, nY);
2497 
2498  long nSizeX;
2499  long nSizeY;
2500  if (bPosSizeInPixels)
2501  GetMergeSizePixel( nX, nY, nSizeX, nSizeY );
2502  else
2503  GetMergeSizePrintTwips(nX, nY, nSizeX, nSizeY);
2504 
2505  std::stringstream ss;
2506  if (bPosSizeInPixels)
2507  {
2508  double fPPTX = GetPPTX();
2509  double fPPTY = GetPPTY();
2510 
2511  // make it a slim cell cursor, but not empty
2512  if (nSizeX == 0)
2513  nSizeX = 1;
2514 
2515  if (nSizeY == 0)
2516  nSizeY = 1;
2517 
2518  long nPosXTw = rtl::math::round(aCellPos.getX() / fPPTX);
2519  long nPosYTw = rtl::math::round(aCellPos.getY() / fPPTY);
2520  // look at Rectangle( const Point& rLT, const Size& rSize ) for the '- 1'
2521  long nSizeXTw = rtl::math::round(nSizeX / fPPTX) - 1;
2522  long nSizeYTw = rtl::math::round(nSizeY / fPPTY) - 1;
2523 
2524  ss << nPosXTw << ", " << nPosYTw << ", " << nSizeXTw << ", " << nSizeYTw << ", "
2525  << nX << ", " << nY;
2526  }
2527  else
2528  {
2529  // look at Rectangle( const Point& rLT, const Size& rSize ) for the decrement.
2530  if (nSizeX)
2531  --nSizeX;
2532  if (nSizeY)
2533  --nSizeY;
2534  ss << aCellPos.getX() << ", " << aCellPos.getY()
2535  << ", " << nSizeX << ", " << nSizeY << ", "
2536  << nX << ", " << nY;
2537  }
2538 
2539  return ss.str().c_str();
2540 }
2541 
2542 // Number of cells on a screen
2543 SCCOL ScViewData::CellsAtX( SCCOL nPosX, SCCOL nDir, ScHSplitPos eWhichX, sal_uInt16 nScrSizeX ) const
2544 {
2545  OSL_ENSURE( nDir==1 || nDir==-1, "wrong CellsAt call" );
2546 
2547  if (pView)
2548  const_cast<ScViewData*>(this)->aScrSize.setWidth( pView->GetGridWidth(eWhichX) );
2549 
2550  SCCOL nX;
2551  sal_uInt16 nScrPosX = 0;
2552  if (nScrSizeX == SC_SIZE_NONE) nScrSizeX = static_cast<sal_uInt16>(aScrSize.Width());
2553 
2554  if (nDir==1)
2555  nX = nPosX; // forwards
2556  else
2557  nX = nPosX-1; // backwards
2558 
2559  bool bOut = false;
2560  for ( ; nScrPosX<=nScrSizeX && !bOut; nX = sal::static_int_cast<SCCOL>(nX + nDir) )
2561  {
2562  SCCOL nColNo = nX;
2563  if (nColNo < 0 || nColNo > mrDoc.MaxCol())
2564  bOut = true;
2565  else
2566  {
2567  sal_uInt16 nTSize = mrDoc.GetColWidth(nColNo, nTabNo);
2568  if (nTSize)
2569  {
2570  long nSizeXPix = ToPixel( nTSize, nPPTX );
2571  nScrPosX = sal::static_int_cast<sal_uInt16>( nScrPosX + static_cast<sal_uInt16>(nSizeXPix) );
2572  }
2573  }
2574  }
2575 
2576  if (nDir==1)
2577  nX = sal::static_int_cast<SCCOL>( nX - nPosX );
2578  else
2579  nX = (nPosX-1)-nX;
2580 
2581  if (nX>0) --nX;
2582  return nX;
2583 }
2584 
2585 SCROW ScViewData::CellsAtY( SCROW nPosY, SCROW nDir, ScVSplitPos eWhichY, sal_uInt16 nScrSizeY ) const
2586 {
2587  OSL_ENSURE( nDir==1 || nDir==-1, "wrong CellsAt call" );
2588 
2589  if (pView)
2590  const_cast<ScViewData*>(this)->aScrSize.setHeight( pView->GetGridHeight(eWhichY) );
2591 
2592  if (nScrSizeY == SC_SIZE_NONE) nScrSizeY = static_cast<sal_uInt16>(aScrSize.Height());
2593 
2594  SCROW nY;
2595 
2596  if (nDir==1)
2597  {
2598  // forward
2599  nY = nPosY;
2600  long nScrPosY = 0;
2601  AddPixelsWhile(nScrPosY, nScrSizeY, nY, mrDoc.MaxRow(), nPPTY, &mrDoc, nTabNo);
2602  // Original loop ended on last evaluated +1 or if that was MaxRow even on MaxRow+2.
2603  nY += (nY == mrDoc.MaxRow() ? 2 : 1);
2604  nY -= nPosY;
2605  }
2606  else
2607  {
2608  // backward
2609  nY = nPosY-1;
2610  long nScrPosY = 0;
2611  AddPixelsWhileBackward(nScrPosY, nScrSizeY, nY, 0, nPPTY, &mrDoc, nTabNo);
2612  // Original loop ended on last evaluated -1 or if that was 0 even on -2.
2613  nY -= (nY == 0 ? 2 : 1);
2614  nY = (nPosY-1)-nY;
2615  }
2616 
2617  if (nY>0) --nY;
2618  return nY;
2619 }
2620 
2622 {
2623  return CellsAtX( GetPosX( eWhichX ), 1, eWhichX );
2624 }
2625 
2627 {
2628  return CellsAtY( GetPosY( eWhichY ), 1, eWhichY );
2629 }
2630 
2632 {
2633  return CellsAtX( GetPosX( eWhichX ), -1, eWhichX );
2634 }
2635 
2637 {
2638  return CellsAtY( GetPosY( eWhichY ), -1, eWhichY );
2639 }
2640 
2641 bool ScViewData::GetMergeSizePixel( SCCOL nX, SCROW nY, long& rSizeXPix, long& rSizeYPix ) const
2642 {
2643  const ScMergeAttr* pMerge = mrDoc.GetAttr(nX, nY, nTabNo, ATTR_MERGE);
2644  if ( pMerge->GetColMerge() > 1 || pMerge->GetRowMerge() > 1 )
2645  {
2646  long nOutWidth = 0;
2647  long nOutHeight = 0;
2648  SCCOL nCountX = pMerge->GetColMerge();
2649  for (SCCOL i=0; i<nCountX; i++)
2650  nOutWidth += ToPixel(mrDoc.GetColWidth(nX + i, nTabNo), nPPTX);
2651  SCROW nCountY = pMerge->GetRowMerge();
2652 
2653  for (SCROW nRow = nY; nRow <= nY+nCountY-1; ++nRow)
2654  {
2655  SCROW nLastRow = nRow;
2656  if (mrDoc.RowHidden(nRow, nTabNo, nullptr, &nLastRow))
2657  {
2658  nRow = nLastRow;
2659  continue;
2660  }
2661 
2662  sal_uInt16 nHeight = mrDoc.GetRowHeight(nRow, nTabNo);
2663  nOutHeight += ToPixel(nHeight, nPPTY);
2664  }
2665 
2666  rSizeXPix = nOutWidth;
2667  rSizeYPix = nOutHeight;
2668  return true;
2669  }
2670  else
2671  {
2672  rSizeXPix = ToPixel(mrDoc.GetColWidth(nX, nTabNo), nPPTX);
2673  rSizeYPix = ToPixel(mrDoc.GetRowHeight(nY, nTabNo), nPPTY);
2674  return false;
2675  }
2676 }
2677 
2678 bool ScViewData::GetMergeSizePrintTwips(SCCOL nX, SCROW nY, long& rSizeXTwips, long& rSizeYTwips) const
2679 {
2680  const ScMergeAttr* pMerge = mrDoc.GetAttr(nX, nY, nTabNo, ATTR_MERGE);
2681  SCCOL nCountX = pMerge->GetColMerge();
2682  if (!nCountX)
2683  nCountX = 1;
2684  rSizeXTwips = mrDoc.GetColWidth(nX, nX + nCountX - 1, nTabNo);
2685 
2686  SCROW nCountY = pMerge->GetRowMerge();
2687  if (!nCountY)
2688  nCountY = 1;
2689  rSizeYTwips = mrDoc.GetRowHeight(nY, nY + nCountY - 1, nTabNo);
2690 
2691  return (nCountX > 1 || nCountY > 1);
2692 }
2693 
2694 void ScViewData::GetPosFromPixel( long nClickX, long nClickY, ScSplitPos eWhich,
2695  SCCOL& rPosX, SCROW& rPosY,
2696  bool bTestMerge, bool bRepair, SCTAB nForTab )
2697 {
2698  // special handling of 0 is now in ScViewFunctionSet::SetCursorAtPoint
2699 
2700  if (nForTab == -1)
2701  nForTab = nTabNo;
2702  bool bForCurTab = (nForTab == nTabNo);
2703  if (!bForCurTab && (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size()))))
2704  {
2705  SAL_WARN("sc.viewdata", "ScViewData::GetPosFromPixel : invalid nForTab = " << nForTab);
2706  nForTab = nTabNo;
2707  bForCurTab = true;
2708  }
2709 
2710  ScHSplitPos eHWhich = WhichH(eWhich);
2711  ScVSplitPos eVWhich = WhichV(eWhich);
2712 
2713  if (mrDoc.IsLayoutRTL(nForTab))
2714  {
2715  // mirror horizontal position
2716  if (pView)
2717  aScrSize.setWidth( pView->GetGridWidth(eHWhich) );
2718  nClickX = aScrSize.Width() - 1 - nClickX;
2719  }
2720 
2721  SCCOL nStartPosX = GetPosX(eHWhich, nForTab);
2722  SCROW nStartPosY = GetPosY(eVWhich, nForTab);
2723  rPosX = nStartPosX;
2724  rPosY = nStartPosY;
2725  long nScrX = 0;
2726  long nScrY = 0;
2727 
2728  if (nClickX > 0)
2729  {
2730  while (rPosX <= mrDoc.MaxCol() && nClickX >= nScrX)
2731  {
2732  nScrX += ToPixel(mrDoc.GetColWidth(rPosX, nForTab), nPPTX);
2733  ++rPosX;
2734  }
2735  --rPosX;
2736  }
2737  else
2738  {
2739  while ( rPosX>0 && nClickX < nScrX )
2740  {
2741  --rPosX;
2742  nScrX -= ToPixel(mrDoc.GetColWidth(rPosX, nForTab), nPPTX);
2743  }
2744  }
2745 
2746  if (nClickY > 0)
2747  AddPixelsWhile(nScrY, nClickY, rPosY, mrDoc.MaxRow(), nPPTY, &mrDoc, nForTab);
2748  else
2749  {
2750  /* TODO: could need some "SubPixelsWhileBackward" method */
2751  while ( rPosY>0 && nClickY < nScrY )
2752  {
2753  --rPosY;
2754  nScrY -= ToPixel(mrDoc.GetRowHeight(rPosY, nForTab), nPPTY);
2755  }
2756  }
2757 
2758  // cells too big?
2759  if ( rPosX == nStartPosX && nClickX > 0 )
2760  {
2761  if (pView)
2762  aScrSize.setWidth( pView->GetGridWidth(eHWhich) );
2763  if ( nClickX > aScrSize.Width() )
2764  ++rPosX;
2765  }
2766  if ( rPosY == nStartPosY && nClickY > 0 )
2767  {
2768  if (pView)
2769  aScrSize.setHeight( pView->GetGridHeight(eVWhich) );
2770  if ( nClickY > aScrSize.Height() )
2771  ++rPosY;
2772  }
2773 
2774  rPosX = std::clamp(rPosX, SCCOL(0), mrDoc.MaxCol());
2775  rPosY = std::clamp(rPosY, SCROW(0), mrDoc.MaxRow());
2776 
2777  if (!(bTestMerge && bForCurTab))
2778  return;
2779 
2780  // public method to adapt position
2781  SCCOL nOrigX = rPosX;
2782  SCROW nOrigY = rPosY;
2783  mrDoc.SkipOverlapped(rPosX, rPosY, nTabNo);
2784  bool bHOver = (nOrigX != rPosX);
2785  bool bVOver = (nOrigY != rPosY);
2786 
2787  if ( !(bRepair && ( bHOver || bVOver )) )
2788  return;
2789 
2790  const ScMergeAttr* pMerge = mrDoc.GetAttr(rPosX, rPosY, nTabNo, ATTR_MERGE);
2791  if ( ( bHOver && pMerge->GetColMerge() <= 1 ) ||
2792  ( bVOver && pMerge->GetRowMerge() <= 1 ) )
2793  {
2794  OSL_FAIL("merge error found");
2795 
2796  mrDoc.RemoveFlagsTab(0, 0, mrDoc.MaxCol(), mrDoc.MaxRow(), nTabNo, ScMF::Hor | ScMF::Ver);
2797  SCCOL nEndCol = mrDoc.MaxCol();
2798  SCROW nEndRow = mrDoc.MaxRow();
2799  mrDoc.ExtendMerge(0, 0, nEndCol, nEndRow, nTabNo, true);
2800  if (pDocShell)
2801  pDocShell->PostPaint(ScRange(0, 0, nTabNo, mrDoc.MaxCol(), mrDoc.MaxRow(), nTabNo),
2803  }
2804 }
2805 
2806 void ScViewData::GetMouseQuadrant( const Point& rClickPos, ScSplitPos eWhich,
2807  SCCOL nPosX, SCROW nPosY, bool& rLeft, bool& rTop )
2808 {
2809  bool bLayoutRTL = mrDoc.IsLayoutRTL(nTabNo);
2810  long nLayoutSign = bLayoutRTL ? -1 : 1;
2811 
2812  Point aCellStart = GetScrPos( nPosX, nPosY, eWhich, true );
2813  long nSizeX;
2814  long nSizeY;
2815  GetMergeSizePixel( nPosX, nPosY, nSizeX, nSizeY );
2816  rLeft = ( rClickPos.X() - aCellStart.X() ) * nLayoutSign <= nSizeX / 2;
2817  rTop = rClickPos.Y() - aCellStart.Y() <= nSizeY / 2;
2818 }
2819 
2820 void ScViewData::SetPosX( ScHSplitPos eWhich, SCCOL nNewPosX )
2821 {
2822  // in the tiled rendering case, nPosX [the leftmost visible column] must be 0
2823  bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
2824  if (nNewPosX != 0 && !bIsTiledRendering)
2825  {
2826  SCCOL nOldPosX = pThisTab->nPosX[eWhich];
2827  long nTPosX = pThisTab->nTPosX[eWhich];
2828  long nPixPosX = pThisTab->nPixPosX[eWhich];
2829  SCCOL i;
2830  if ( nNewPosX > nOldPosX )
2831  for ( i=nOldPosX; i<nNewPosX; i++ )
2832  {
2833  long nThis = mrDoc.GetColWidth(i, nTabNo);
2834  nTPosX -= nThis;
2835  nPixPosX -= ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTX);
2836  }
2837  else
2838  for ( i=nNewPosX; i<nOldPosX; i++ )
2839  {
2840  long nThis = mrDoc.GetColWidth(i, nTabNo);
2841  nTPosX += nThis;
2842  nPixPosX += ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTX);
2843  }
2844 
2845  pThisTab->nPosX[eWhich] = nNewPosX;
2846  pThisTab->nTPosX[eWhich] = nTPosX;
2847  pThisTab->nMPosX[eWhich] = static_cast<long>(nTPosX * HMM_PER_TWIPS);
2848  pThisTab->nPixPosX[eWhich] = nPixPosX;
2849  }
2850  else
2851  {
2852  pThisTab->nPixPosX[eWhich] =
2853  pThisTab->nTPosX[eWhich] =
2854  pThisTab->nMPosX[eWhich] =
2855  pThisTab->nPosX[eWhich] = 0;
2856  }
2857 }
2858 
2859 void ScViewData::SetPosY( ScVSplitPos eWhich, SCROW nNewPosY )
2860 {
2861  // in the tiled rendering case, nPosY [the topmost visible row] must be 0
2862  bool bIsTiledRendering = comphelper::LibreOfficeKit::isActive();
2863  if (nNewPosY != 0 && !bIsTiledRendering)
2864  {
2865  SCROW nOldPosY = pThisTab->nPosY[eWhich];
2866  long nTPosY = pThisTab->nTPosY[eWhich];
2867  long nPixPosY = pThisTab->nPixPosY[eWhich];
2868  SCROW i, nHeightEndRow;
2869  if ( nNewPosY > nOldPosY )
2870  for ( i=nOldPosY; i<nNewPosY; i++ )
2871  {
2872  long nThis = mrDoc.GetRowHeight(i, nTabNo, nullptr, &nHeightEndRow);
2873  SCROW nRows = std::min( nNewPosY, nHeightEndRow + 1) - i;
2874  i = nHeightEndRow;
2875  nTPosY -= nThis * nRows;
2876  nPixPosY -= ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTY) * nRows;
2877  }
2878  else
2879  for ( i=nNewPosY; i<nOldPosY; i++ )
2880  {
2881  long nThis = mrDoc.GetRowHeight(i, nTabNo, nullptr, &nHeightEndRow);
2882  SCROW nRows = std::min( nOldPosY, nHeightEndRow + 1) - i;
2883  i = nHeightEndRow;
2884  nTPosY += nThis * nRows;
2885  nPixPosY += ToPixel(sal::static_int_cast<sal_uInt16>(nThis), nPPTY) * nRows;
2886  }
2887 
2888  pThisTab->nPosY[eWhich] = nNewPosY;
2889  pThisTab->nTPosY[eWhich] = nTPosY;
2890  pThisTab->nMPosY[eWhich] = static_cast<long>(nTPosY * HMM_PER_TWIPS);
2891  pThisTab->nPixPosY[eWhich] = nPixPosY;
2892  }
2893  else
2894  {
2895  pThisTab->nPixPosY[eWhich] =
2896  pThisTab->nTPosY[eWhich] =
2897  pThisTab->nMPosY[eWhich] =
2898  pThisTab->nPosY[eWhich] = 0;
2899  }
2900 }
2901 
2902 void ScViewData::RecalcPixPos() // after zoom changes
2903 {
2904  for (sal_uInt16 eWhich=0; eWhich<2; eWhich++)
2905  {
2906  long nPixPosX = 0;
2907  SCCOL nPosX = pThisTab->nPosX[eWhich];
2908  for (SCCOL i=0; i<nPosX; i++)
2909  nPixPosX -= ToPixel(mrDoc.GetColWidth(i, nTabNo), nPPTX);
2910  pThisTab->nPixPosX[eWhich] = nPixPosX;
2911 
2912  long nPixPosY = 0;
2913  SCROW nPosY = pThisTab->nPosY[eWhich];
2914  for (SCROW j=0; j<nPosY; j++)
2915  nPixPosY -= ToPixel(mrDoc.GetRowHeight(j, nTabNo), nPPTY);
2916  pThisTab->nPixPosY[eWhich] = nPixPosY;
2917  }
2918 }
2919 
2921 {
2923  pThisTab->nMPosY[WhichV(eWhich)] ) );
2924  return aLogicMode;
2925 }
2926 
2928 {
2929  aLogicMode.SetOrigin( Point() );
2930  return aLogicMode;
2931 }
2932 
2933 void ScViewData::SetScreen( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
2934 {
2935  SCCOL nCol;
2936  SCROW nRow;
2937  sal_uInt16 nTSize;
2938  long nSizePix;
2939  long nScrPosX = 0;
2940  long nScrPosY = 0;
2941 
2943  SetPosX( SC_SPLIT_LEFT, nCol1 );
2944  SetPosY( SC_SPLIT_BOTTOM, nRow1 );
2945 
2946  for (nCol=nCol1; nCol<=nCol2; nCol++)
2947  {
2948  nTSize = mrDoc.GetColWidth(nCol, nTabNo);
2949  if (nTSize)
2950  {
2951  nSizePix = ToPixel( nTSize, nPPTX );
2952  nScrPosX += static_cast<sal_uInt16>(nSizePix);
2953  }
2954  }
2955 
2956  for (nRow=nRow1; nRow<=nRow2; nRow++)
2957  {
2958  nTSize = mrDoc.GetRowHeight(nRow, nTabNo);
2959  if (nTSize)
2960  {
2961  nSizePix = ToPixel( nTSize, nPPTY );
2962  nScrPosY += static_cast<sal_uInt16>(nSizePix);
2963  }
2964  }
2965 
2966  aScrSize = Size( nScrPosX, nScrPosY );
2967 }
2968 
2969 void ScViewData::SetScreenPos( const Point& rVisAreaStart )
2970 {
2971  long nSize;
2972  long nTwips;
2973  long nAdd;
2974  bool bEnd;
2975 
2976  nSize = 0;
2977  nTwips = static_cast<long>(rVisAreaStart.X() / HMM_PER_TWIPS);
2978  if (mrDoc.IsLayoutRTL(nTabNo))
2979  nTwips = -nTwips;
2980  SCCOL nX1 = 0;
2981  bEnd = false;
2982  while (!bEnd)
2983  {
2984  nAdd = static_cast<long>(mrDoc.GetColWidth(nX1, nTabNo));
2985  if (nSize + nAdd <= nTwips + 1 && nX1 < mrDoc.MaxCol())
2986  {
2987  nSize += nAdd;
2988  ++nX1;
2989  }
2990  else
2991  bEnd = true;
2992  }
2993 
2994  nSize = 0;
2995  nTwips = static_cast<long>(rVisAreaStart.Y() / HMM_PER_TWIPS);
2996  SCROW nY1 = 0;
2997  bEnd = false;
2998  while (!bEnd)
2999  {
3000  nAdd = static_cast<long>(mrDoc.GetRowHeight(nY1, nTabNo));
3001  if (nSize + nAdd <= nTwips + 1 && nY1 < mrDoc.MaxRow())
3002  {
3003  nSize += nAdd;
3004  ++nY1;
3005  }
3006  else
3007  bEnd = true;
3008  }
3009 
3011  SetPosX( SC_SPLIT_LEFT, nX1 );
3012  SetPosY( SC_SPLIT_BOTTOM, nY1 );
3013 
3014  SetCurX( nX1 );
3015  SetCurY( nY1 );
3016 }
3017 
3019 {
3020  SetScreenPos( rVisArea.TopLeft() );
3021 
3022  // here without GetOutputFactor(), since it's for the output into a Metafile
3023 
3024  aScrSize = rVisArea.GetSize();
3025  aScrSize.setWidth( static_cast<long>( aScrSize.Width() * ScGlobal::nScreenPPTX / HMM_PER_TWIPS ) );
3026  aScrSize.setHeight( static_cast<long>( aScrSize.Height() * ScGlobal::nScreenPPTY / HMM_PER_TWIPS ) );
3027 }
3028 
3030 {
3031  return pDocShell->GetDocFunc();
3032 }
3033 
3035 {
3036  assert(pView && "GetBindings() without ViewShell");
3037  return pView->GetViewFrame()->GetBindings();
3038 }
3039 
3041 {
3042  assert(pView && "GetDispatcher() without ViewShell");
3043  return *pView->GetViewFrame()->GetDispatcher();
3044 }
3045 
3047 {
3048  return maMarkData;
3049 }
3050 
3052 {
3053  return maMarkData;
3054 }
3055 
3057 {
3058  assert(pView && "GetDialogParent() without ViewShell");
3059  return pView->GetDialogParent();
3060 }
3061 
3063 {
3064  assert(pView && "GetActiveWin() without View");
3065  return pView->GetActiveWin();
3066 }
3067 
3069 {
3070  assert(pView && "GetActiveWin() without View");
3071  return pView->GetActiveWin();
3072 }
3073 
3075 {
3076  assert(pView && "GetScDrawView() without View");
3077  return pView->GetScDrawView();
3078 }
3079 
3081 {
3082  assert(pView && "IsMinimized() without View");
3083  return pView->IsMinimized();
3084 }
3085 
3086 void ScViewData::UpdateScreenZoom( const Fraction& rNewX, const Fraction& rNewY )
3087 {
3088  Fraction aOldX = GetZoomX();
3089  Fraction aOldY = GetZoomY();
3090 
3091  SetZoom( rNewX, rNewY, false );
3092 
3093  Fraction aWidth = GetZoomX();
3094  aWidth *= Fraction( aScrSize.Width(),1 );
3095  aWidth /= aOldX;
3096 
3097  Fraction aHeight = GetZoomY();
3098  aHeight *= Fraction( aScrSize.Height(),1 );
3099  aHeight /= aOldY;
3100 
3101  aScrSize.setWidth( static_cast<long>(aWidth) );
3102  aScrSize.setHeight( static_cast<long>(aHeight) );
3103 }
3104 
3106 {
3107  double nOldPPTX = nPPTX;
3108  double nOldPPTY = nPPTY;
3109  nPPTX = ScGlobal::nScreenPPTX * static_cast<double>(GetZoomX());
3110  if (pDocShell)
3111  nPPTX = nPPTX / pDocShell->GetOutputFactor(); // Factor is printer to screen
3112  nPPTY = ScGlobal::nScreenPPTY * static_cast<double>(GetZoomY());
3113 
3114  // if detective objects are present,
3115  // try to adjust horizontal scale so the most common column width has minimal rounding errors,
3116  // to avoid differences between cell and drawing layer output
3117 
3119  {
3120  SCCOL nEndCol = 0;
3121  SCROW nDummy = 0;
3122  mrDoc.GetTableArea(nTabNo, nEndCol, nDummy);
3123  if (nEndCol<20)
3124  nEndCol = 20; // same end position as when determining draw scale
3125 
3126  sal_uInt16 nTwips = mrDoc.GetCommonWidth(nEndCol, nTabNo);
3127  if ( nTwips )
3128  {
3129  double fOriginal = nTwips * nPPTX;
3130  if ( fOriginal < static_cast<double>(nEndCol) )
3131  {
3132  // if one column is smaller than the column count,
3133  // rounding errors are likely to add up to a whole column.
3134 
3135  double fRounded = ::rtl::math::approxFloor( fOriginal + 0.5 );
3136  if ( fRounded > 0.0 )
3137  {
3138  double fScale = fRounded / fOriginal + 1E-6;
3139  if ( fScale >= 0.9 && fScale <= 1.1 )
3140  nPPTX *= fScale;
3141  }
3142  }
3143  }
3144  }
3145 
3146  if (nPPTX != nOldPPTX)
3148  if (nPPTY != nOldPPTY)
3150 }
3151 
3152 #define SC_OLD_TABSEP '/'
3153 #define SC_NEW_TABSEP '+'
3154 
3155 void ScViewData::WriteUserData(OUString& rData)
3156 {
3157  // nZoom (until 364v) or nZoom/nPageZoom/bPageMode (from 364w)
3158  // nTab
3159  // Tab control width
3160  // per sheet:
3161  // CursorX/CursorY/HSplitMode/VSplitMode/HSplitPos/VSplitPos/SplitActive/
3162  // PosX[left]/PosX[right]/PosY[top]/PosY[bottom]
3163  // when rows bigger than 8192, "+" instead of "/"
3164 
3165  sal_uInt16 nZoom = static_cast<sal_uInt16>(long(pThisTab->aZoomY * 100));
3166  rData = OUString::number( nZoom ) + "/";
3167  nZoom = static_cast<sal_uInt16>(long(pThisTab->aPageZoomY * 100));
3168  rData += OUString::number( nZoom ) + "/";
3169  if (bPagebreak)
3170  rData += "1";
3171  else
3172  rData += "0";
3173 
3174  rData += ";" + OUString::number( nTabNo ) + ";" TAG_TABBARWIDTH +
3175  OUString::number( pView->GetTabBarWidth() );
3176 
3177  SCTAB nTabCount = mrDoc.GetTableCount();
3178  for (SCTAB i=0; i<nTabCount; i++)
3179  {
3180  rData += ";"; // Numbering must not get mixed up under any circumstances
3181  if (i < static_cast<SCTAB>(maTabData.size()) && maTabData[i])
3182  {
3183  OUString cTabSep(SC_OLD_TABSEP); // like 3.1
3184  if ( maTabData[i]->nCurY > MAXROW_30 ||
3185  maTabData[i]->nPosY[0] > MAXROW_30 || maTabData[i]->nPosY[1] > MAXROW_30 ||
3186  ( maTabData[i]->eVSplitMode == SC_SPLIT_FIX &&
3187  maTabData[i]->nFixPosY > MAXROW_30 ) )
3188  {
3189  cTabSep = OUStringChar(SC_NEW_TABSEP); // in order to not kill a 3.1-version
3190  }
3191 
3192  rData += OUString::number( maTabData[i]->nCurX ) + cTabSep +
3193  OUString::number( maTabData[i]->nCurY ) + cTabSep +
3194  OUString::number( maTabData[i]->eHSplitMode ) + cTabSep +
3195  OUString::number( maTabData[i]->eVSplitMode ) + cTabSep;
3196  if ( maTabData[i]->eHSplitMode == SC_SPLIT_FIX )
3197  rData += OUString::number( maTabData[i]->nFixPosX );
3198  else
3199  rData += OUString::number( maTabData[i]->nHSplitPos );
3200  rData += cTabSep;
3201  if ( maTabData[i]->eVSplitMode == SC_SPLIT_FIX )
3202  rData += OUString::number( maTabData[i]->nFixPosY );
3203  else
3204  rData += OUString::number( maTabData[i]->nVSplitPos );
3205  rData += cTabSep +
3206  OUString::number( maTabData[i]->eWhichActive ) + cTabSep +
3207  OUString::number( maTabData[i]->nPosX[0] ) + cTabSep +
3208  OUString::number( maTabData[i]->nPosX[1] ) + cTabSep +
3209  OUString::number( maTabData[i]->nPosY[0] ) + cTabSep +
3210  OUString::number( maTabData[i]->nPosY[1] );
3211  }
3212  }
3213 }
3214 
3215 void ScViewData::ReadUserData(const OUString& rData)
3216 {
3217  if (rData.isEmpty()) // empty string on "reload"
3218  return; // then exit without assertion
3219 
3220  if ( comphelper::string::getTokenCount(rData, ';') <= 2 )
3221  {
3222  // when reload, in page preview, the preview UserData may have been left intact.
3223  // we don't want the zoom from the page preview here.
3224  OSL_FAIL("ReadUserData: This is not my data");
3225  return;
3226  }
3227 
3228  Fraction aZoomX, aZoomY, aPageZoomX, aPageZoomY; // evaluate (all sheets?)
3229 
3230  sal_Int32 nMainIdx {0};
3231  sal_Int32 nIdx {0};
3232 
3233  OUString aZoomStr = rData.getToken(0, ';', nMainIdx); // Zoom/PageZoom/Mode
3234  sal_uInt16 nNormZoom = sal::static_int_cast<sal_uInt16>(aZoomStr.getToken(0, '/', nIdx).toInt32());
3235  if ( nNormZoom >= MINZOOM && nNormZoom <= MAXZOOM )
3236  aZoomX = aZoomY = Fraction( nNormZoom, 100 ); // "normal" zoom (always)
3237  sal_uInt16 nPageZoom = sal::static_int_cast<sal_uInt16>(aZoomStr.getToken(0, '/', nIdx).toInt32());
3238  if ( nPageZoom >= MINZOOM && nPageZoom <= MAXZOOM )
3239  aPageZoomX = aPageZoomY = Fraction( nPageZoom, 100 ); // Pagebreak zoom, if set
3240  sal_Unicode cMode = aZoomStr.getToken(0, '/', nIdx)[0]; // 0 or "0"/"1"
3241  SetPagebreakMode( cMode == '1' );
3242  // SetPagebreakMode must always be called due to CalcPPT / RecalcPixPos()
3243 
3244  // sheet may have become invalid (for instance last version):
3245  SCTAB nNewTab = static_cast<SCTAB>(rData.getToken(0, ';', nMainIdx).toUInt32());
3246  if (mrDoc.HasTable(nNewTab))
3247  SetTabNo(nNewTab);
3248 
3249  // if available, get tab bar width:
3250  const sal_Int32 nMainIdxRef {nMainIdx};
3251  OUString aTabOpt = rData.getToken(0, ';', nMainIdx);
3252 
3253  OUString aRest;
3254  if (aTabOpt.startsWith(TAG_TABBARWIDTH, &aRest))
3255  {
3256  pView->SetTabBarWidth(aRest.toInt32());
3257  }
3258  else
3259  {
3260  // Tab bar width not specified, token to be processed again
3261  nMainIdx = nMainIdxRef;
3262  }
3263 
3264  // per sheet
3265  SCTAB nPos = 0;
3266  while ( nMainIdx>0 )
3267  {
3268  aTabOpt = rData.getToken(0, ';', nMainIdx);
3269  EnsureTabDataSize(nPos + 1);
3270  if (!maTabData[nPos])
3271  maTabData[nPos].reset(new ScViewDataTable(&mrDoc));
3272 
3273  sal_Unicode cTabSep = 0;
3275  cTabSep = SC_OLD_TABSEP;
3276  else if (comphelper::string::getTokenCount(aTabOpt, SC_NEW_TABSEP) >= 11)
3277  cTabSep = SC_NEW_TABSEP;
3278  // '+' is only allowed, if we can deal with rows > 8192
3279 
3280  if (cTabSep)
3281  {
3282  nIdx = 0;
3283  maTabData[nPos]->nCurX = mrDoc.SanitizeCol(static_cast<SCCOL>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32()));
3284  maTabData[nPos]->nCurY = mrDoc.SanitizeRow(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3285  maTabData[nPos]->eHSplitMode = static_cast<ScSplitMode>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3286  maTabData[nPos]->eVSplitMode = static_cast<ScSplitMode>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3287 
3288  sal_Int32 nTmp{ aTabOpt.getToken(0, cTabSep, nIdx).toInt32() };
3289  if ( maTabData[nPos]->eHSplitMode == SC_SPLIT_FIX )
3290  {
3291  maTabData[nPos]->nFixPosX = mrDoc.SanitizeCol(static_cast<SCCOL>(nTmp));
3292  UpdateFixX(nPos);
3293  }
3294  else
3295  maTabData[nPos]->nHSplitPos = nTmp;
3296 
3297  nTmp = aTabOpt.getToken(0, cTabSep, nIdx).toInt32();
3298  if ( maTabData[nPos]->eVSplitMode == SC_SPLIT_FIX )
3299  {
3300  maTabData[nPos]->nFixPosY = mrDoc.SanitizeRow(nTmp);
3301  UpdateFixY(nPos);
3302  }
3303  else
3304  maTabData[nPos]->nVSplitPos = nTmp;
3305 
3306  maTabData[nPos]->eWhichActive = static_cast<ScSplitPos>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3307  maTabData[nPos]->nPosX[0] = mrDoc.SanitizeCol(static_cast<SCCOL>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32()));
3308  maTabData[nPos]->nPosX[1] = mrDoc.SanitizeCol(static_cast<SCCOL>(aTabOpt.getToken(0, cTabSep, nIdx).toInt32()));
3309  maTabData[nPos]->nPosY[0] = mrDoc.SanitizeRow(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3310  maTabData[nPos]->nPosY[1] = mrDoc.SanitizeRow(aTabOpt.getToken(0, cTabSep, nIdx).toInt32());
3311 
3312  maTabData[nPos]->eWhichActive = maTabData[nPos]->SanitizeWhichActive();
3313  }
3314  ++nPos;
3315  }
3316 
3317  RecalcPixPos();
3318 }
3319 
3321 {
3322  // *** Fill extended document data for export filters ***
3323 
3324  // document settings
3325  ScExtDocSettings& rDocSett = rDocOpt.GetDocSettings();
3326 
3327  // displayed sheet
3328  rDocSett.mnDisplTab = GetTabNo();
3329 
3330  // width of the tabbar, relative to frame window width
3332  if( rDocSett.mfTabBarWidth < 0.0 )
3334 
3335  bool bLOKActive = comphelper::LibreOfficeKit::isActive();
3336 
3337  // sheet settings
3338  for( SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabData.size()); ++nTab )
3339  {
3340  if( const ScViewDataTable* pViewTab = maTabData[ nTab ].get() )
3341  {
3342  ScExtTabSettings& rTabSett = rDocOpt.GetOrCreateTabSettings( nTab );
3343 
3344  // split mode
3345  ScSplitMode eExHSplit = pViewTab->eHSplitMode;
3346  ScSplitMode eExVSplit = pViewTab->eVSplitMode;
3347  SCCOL nExFixPosX = pViewTab->nFixPosX;
3348  SCROW nExFixPosY = pViewTab->nFixPosY;
3349  long nExHSplitPos = pViewTab->nHSplitPos;
3350  long nExVSplitPos = pViewTab->nVSplitPos;
3351 
3352  if (bLOKActive)
3353  {
3354  OverrideWithLOKFreeze(eExHSplit, eExVSplit,
3355  nExFixPosX, nExFixPosY,
3356  nExHSplitPos, nExVSplitPos, nTab);
3357  }
3358 
3359  bool bHSplit = eExHSplit != SC_SPLIT_NONE;
3360  bool bVSplit = eExVSplit != SC_SPLIT_NONE;
3361  bool bRealSplit = (eExHSplit == SC_SPLIT_NORMAL) || (eExVSplit == SC_SPLIT_NORMAL);
3362  bool bFrozen = (eExHSplit == SC_SPLIT_FIX) || (eExVSplit == SC_SPLIT_FIX);
3363  OSL_ENSURE( !bRealSplit || !bFrozen, "ScViewData::WriteExtOptions - split and freeze in same sheet" );
3364  rTabSett.mbFrozenPanes = !bRealSplit && bFrozen;
3365 
3366  // split and freeze position
3367  rTabSett.maSplitPos = Point( 0, 0 );
3368  rTabSett.maFreezePos.Set( 0, 0, nTab );
3369  if( bRealSplit )
3370  {
3371  Point& rSplitPos = rTabSett.maSplitPos;
3372  rSplitPos = Point( bHSplit ? nExHSplitPos : 0, bVSplit ? nExVSplitPos : 0 );
3373  rSplitPos = Application::GetDefaultDevice()->PixelToLogic( rSplitPos, MapMode( MapUnit::MapTwip ) );
3374  if( pDocShell )
3375  rSplitPos.setX( static_cast<long>(static_cast<double>(rSplitPos.X()) / pDocShell->GetOutputFactor()) );
3376  }
3377  else if( bFrozen )
3378  {
3379  if( bHSplit ) rTabSett.maFreezePos.SetCol( nExFixPosX );
3380  if( bVSplit ) rTabSett.maFreezePos.SetRow( nExFixPosY );
3381  }
3382 
3383  // first visible cell in top-left and additional panes
3384  rTabSett.maFirstVis.Set( pViewTab->nPosX[ SC_SPLIT_LEFT ], pViewTab->nPosY[ bVSplit ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM ], nTab );
3385  rTabSett.maSecondVis.Set( pViewTab->nPosX[ SC_SPLIT_RIGHT ], pViewTab->nPosY[ SC_SPLIT_BOTTOM ], nTab );
3386 
3387  // active pane
3388  switch( pViewTab->eWhichActive )
3389  {
3390  // no horizontal split -> always use left panes
3391  // no vertical split -> always use top panes
3392  case SC_SPLIT_TOPLEFT:
3393  rTabSett.meActivePane = SCEXT_PANE_TOPLEFT;
3394  break;
3395  case SC_SPLIT_TOPRIGHT:
3396  rTabSett.meActivePane = bHSplit ? SCEXT_PANE_TOPRIGHT : SCEXT_PANE_TOPLEFT;
3397  break;
3398  case SC_SPLIT_BOTTOMLEFT:
3399  rTabSett.meActivePane = bVSplit ? SCEXT_PANE_BOTTOMLEFT : SCEXT_PANE_TOPLEFT;
3400  break;
3401  case SC_SPLIT_BOTTOMRIGHT:
3402  rTabSett.meActivePane = bHSplit ?
3405  break;
3406  }
3407 
3408  // cursor position
3409  rTabSett.maCursor.Set( pViewTab->nCurX, pViewTab->nCurY, nTab );
3410 
3411  // sheet selection and selected ranges
3412  const ScMarkData& rMarkData = GetMarkData();
3413  rTabSett.mbSelected = rMarkData.GetTableSelect( nTab );
3414  rMarkData.FillRangeListWithMarks( &rTabSett.maSelection, true );
3415 
3416  // grid color
3417  rTabSett.maGridColor = COL_AUTO;
3418  const Color& rGridColor = maOptions.GetGridColor();
3419  if (rGridColor != SC_STD_GRIDCOLOR)
3420  rTabSett.maGridColor = rGridColor;
3421  rTabSett.mbShowGrid = pViewTab->bShowGrid;
3422 
3423  // view mode and zoom
3424  rTabSett.mbPageMode = bPagebreak;
3425  rTabSett.mnNormalZoom = static_cast< long >( pViewTab->aZoomY * Fraction( 100.0 ) );
3426  rTabSett.mnPageZoom = static_cast< long >( pViewTab->aPageZoomY * Fraction( 100.0 ) );
3427  }
3428  }
3429 }
3430 
3432 {
3433  // *** Get extended document data from import filters ***
3434 
3435  if( !rDocOpt.IsChanged() ) return;
3436 
3437  // document settings
3438  const ScExtDocSettings& rDocSett = rDocOpt.GetDocSettings();
3439 
3440  // displayed sheet
3441  SetTabNo( rDocSett.mnDisplTab );
3442 
3443  /* Width of the tabbar, relative to frame window width. We do not have the
3444  correct width of the frame window here -> store in ScTabView, which sets
3445  the size in the next resize. */
3447 
3448  // sheet settings
3449  SCTAB nLastTab = rDocOpt.GetLastTab();
3450  if (static_cast<SCTAB>(maTabData.size()) <= nLastTab)
3451  maTabData.resize(nLastTab+1);
3452 
3453  for( SCTAB nTab = 0; nTab < static_cast<SCTAB>(maTabData.size()); ++nTab )
3454  {
3455  if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nTab ) )
3456  {
3457  if( !maTabData[ nTab ] )
3458  maTabData[nTab].reset(new ScViewDataTable(&mrDoc));
3459 
3460  const ScExtTabSettings& rTabSett = *pTabSett;
3461  ScViewDataTable& rViewTab = *maTabData[ nTab ];
3462 
3463  // split mode initialization
3464  bool bFrozen = rTabSett.mbFrozenPanes;
3465  bool bHSplit = bFrozen ? (rTabSett.maFreezePos.Col() > 0) : (rTabSett.maSplitPos.X() > 0);
3466  bool bVSplit = bFrozen ? (rTabSett.maFreezePos.Row() > 0) : (rTabSett.maSplitPos.Y() > 0);
3467 
3468  // first visible cell of top-left pane and additional panes
3469  if (rTabSett.maFirstVis.IsValid())
3470  {
3471  rViewTab.nPosX[ SC_SPLIT_LEFT ] = rTabSett.maFirstVis.Col();
3472  rViewTab.nPosY[ bVSplit ? SC_SPLIT_TOP : SC_SPLIT_BOTTOM ] = rTabSett.maFirstVis.Row();
3473  }
3474 
3475  if (rTabSett.maSecondVis.IsValid())
3476  {
3477  if (bHSplit)
3478  rViewTab.nPosX[ SC_SPLIT_RIGHT ] = rTabSett.maSecondVis.Col();
3479  if (bVSplit)
3480  rViewTab.nPosY[ SC_SPLIT_BOTTOM ] = rTabSett.maSecondVis.Row();
3481  }
3482 
3483  // split mode, split and freeze position
3484  rViewTab.eHSplitMode = rViewTab.eVSplitMode = SC_SPLIT_NONE;
3485  rViewTab.nHSplitPos = rViewTab.nVSplitPos = 0;
3486  rViewTab.nFixPosX = 0;
3487  rViewTab.nFixPosY = 0;
3488  if( bFrozen )
3489  {
3490  if( bHSplit )
3491  {
3492  rViewTab.eHSplitMode = SC_SPLIT_FIX;
3493  rViewTab.nFixPosX = rTabSett.maFreezePos.Col();
3494  UpdateFixX( nTab );
3495  }
3496  if( bVSplit )
3497  {
3498  rViewTab.eVSplitMode = SC_SPLIT_FIX;
3499  rViewTab.nFixPosY = rTabSett.maFreezePos.Row();
3500  UpdateFixY( nTab );
3501  }
3502  }
3503  else
3504  {
3506  rTabSett.maSplitPos, MapMode( MapUnit::MapTwip ) );
3507  // the test for use of printer metrics for text formatting here
3508  // effectively results in the nFactor = 1.0 regardless of the Option setting.
3509  if( pDocShell && SC_MOD()->GetInputOptions().GetTextWysiwyg())
3510  {
3511  double nFactor = pDocShell->GetOutputFactor();
3512  aPixel.setX( static_cast<long>( aPixel.X() * nFactor + 0.5 ) );
3513  }
3514 
3515  bHSplit = bHSplit && aPixel.X() > 0;
3516  bVSplit = bVSplit && aPixel.Y() > 0;
3517  if( bHSplit )
3518  {
3519  rViewTab.eHSplitMode = SC_SPLIT_NORMAL;
3520  rViewTab.nHSplitPos = aPixel.X();
3521  }
3522  if( bVSplit )
3523  {
3524  rViewTab.eVSplitMode = SC_SPLIT_NORMAL;
3525  rViewTab.nVSplitPos = aPixel.Y();
3526  }
3527  }
3528 
3529  // active pane
3531  switch( rTabSett.meActivePane )
3532  {
3533  // no horizontal split -> always use left panes
3534  // no vertical split -> always use *bottom* panes
3535  case SCEXT_PANE_TOPLEFT:
3536  ePos = bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT;
3537  break;
3538  case SCEXT_PANE_TOPRIGHT:
3539  ePos = bHSplit ?
3540  (bVSplit ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT) :
3541  (bVSplit ? SC_SPLIT_TOPLEFT : SC_SPLIT_BOTTOMLEFT);
3542  break;
3543  case SCEXT_PANE_BOTTOMLEFT:
3544  ePos = SC_SPLIT_BOTTOMLEFT;
3545  break;
3547  ePos = bHSplit ? SC_SPLIT_BOTTOMRIGHT : SC_SPLIT_BOTTOMLEFT;
3548  break;
3549  }
3550  rViewTab.eWhichActive = ePos;
3551 
3552  // cursor position
3553  const ScAddress& rCursor = rTabSett.maCursor;
3554  if( rCursor.IsValid() )
3555  {
3556  rViewTab.nCurX = rCursor.Col();
3557  rViewTab.nCurY = rCursor.Row();
3558  }
3559 
3560  // sheet selection and selected ranges
3561  ScMarkData& rMarkData = GetMarkData();
3562  rMarkData.SelectTable( nTab, rTabSett.mbSelected );
3563 
3564  // zoom for each sheet
3565  if( rTabSett.mnNormalZoom )
3566  rViewTab.aZoomX = rViewTab.aZoomY = Fraction( rTabSett.mnNormalZoom, 100 );
3567  if( rTabSett.mnPageZoom )
3568  rViewTab.aPageZoomX = rViewTab.aPageZoomY = Fraction( rTabSett.mnPageZoom, 100 );
3569 
3570  rViewTab.bShowGrid = rTabSett.mbShowGrid;
3571 
3572  // get some settings from displayed Excel sheet, set at Calc document
3573  if( nTab == GetTabNo() )
3574  {
3575  // grid color -- #i47435# set automatic grid color explicitly
3576  Color aGridColor(rTabSett.maGridColor);
3577  if (aGridColor == COL_AUTO)
3578  aGridColor = SC_STD_GRIDCOLOR;
3579  maOptions.SetGridColor(aGridColor, EMPTY_OUSTRING);
3580 
3581  // view mode and default zoom (for new sheets) from current sheet
3582  if( rTabSett.mnNormalZoom )
3583  aDefZoomX = aDefZoomY = Fraction( rTabSett.mnNormalZoom, 100L );
3584  if( rTabSett.mnPageZoom )
3585  aDefPageZoomX = aDefPageZoomY = Fraction( rTabSett.mnPageZoom, 100L );
3586  /* #i46820# set pagebreak mode via SetPagebreakMode(), this will
3587  update map modes that are needed to draw text correctly. */
3588  SetPagebreakMode( rTabSett.mbPageMode );
3589  }
3590  }
3591  }
3592 
3595 
3596  // RecalcPixPos or so - also nMPos - also for ReadUserData ??!?!
3597 }
3598 
3599 void ScViewData::WriteUserDataSequence(uno::Sequence <beans::PropertyValue>& rSettings) const
3600 {
3601  rSettings.realloc(SC_VIEWSETTINGS_COUNT);
3602  // + 1, because we have to put the view id in the sequence
3603  beans::PropertyValue* pSettings = rSettings.getArray();
3604 
3605  sal_uInt16 nViewID(pView->GetViewFrame()->GetCurViewId());
3606  pSettings[SC_VIEW_ID].Name = SC_VIEWID;
3607  pSettings[SC_VIEW_ID].Value <<= SC_VIEW + OUString::number(nViewID);
3608 
3609  uno::Reference<container::XNameContainer> xNameContainer =
3610  document::NamedPropertyValues::create( comphelper::getProcessComponentContext() );
3611  for (SCTAB nTab=0; nTab<static_cast<SCTAB>(maTabData.size()); nTab++)
3612  {
3613  if (maTabData[nTab])
3614  {
3615  uno::Sequence <beans::PropertyValue> aTableViewSettings;
3616  maTabData[nTab]->WriteUserDataSequence(aTableViewSettings, *this, nTab);
3617  OUString sTabName;
3618  GetDocument().GetName( nTab, sTabName );
3619  try
3620  {
3621  xNameContainer->insertByName(sTabName, uno::Any(aTableViewSettings));
3622  }
3623  //#101739#; two tables with the same name are possible
3624  catch ( container::ElementExistException& )
3625  {
3626  OSL_FAIL("seems there are two tables with the same name");
3627  }
3628  catch ( uno::RuntimeException& )
3629  {
3630  OSL_FAIL("something went wrong");
3631  }
3632  }
3633  }
3634  pSettings[SC_TABLE_VIEWSETTINGS].Name = SC_TABLES;
3635  pSettings[SC_TABLE_VIEWSETTINGS].Value <<= xNameContainer;
3636 
3637  OUString sName;
3638  GetDocument().GetName( nTabNo, sName );
3639  pSettings[SC_ACTIVE_TABLE].Name = SC_ACTIVETABLE;
3640  pSettings[SC_ACTIVE_TABLE].Value <<= sName;
3642  pSettings[SC_HORIZONTAL_SCROLL_BAR_WIDTH].Value <<= sal_Int32(pView->GetTabBarWidth());
3643  sal_Int32 nZoomValue = long(pThisTab->aZoomY * 100);
3644  sal_Int32 nPageZoomValue = long(pThisTab->aPageZoomY * 100);
3645  pSettings[SC_ZOOM_TYPE].Name = SC_ZOOMTYPE;
3646  pSettings[SC_ZOOM_TYPE].Value <<= sal_Int16(pThisTab->eZoomType);
3647  pSettings[SC_ZOOM_VALUE].Name = SC_ZOOMVALUE;
3648  pSettings[SC_ZOOM_VALUE].Value <<= nZoomValue;
3650  pSettings[SC_PAGE_VIEW_ZOOM_VALUE].Value <<= nPageZoomValue;
3652  pSettings[SC_PAGE_BREAK_PREVIEW].Value <<= bPagebreak;
3653 
3654  pSettings[SC_SHOWZERO].Name = SC_UNO_SHOWZERO;
3655  pSettings[SC_SHOWZERO].Value <<= maOptions.GetOption(VOPT_NULLVALS);
3656  pSettings[SC_SHOWNOTES].Name = SC_UNO_SHOWNOTES;
3657  pSettings[SC_SHOWNOTES].Value <<= maOptions.GetOption(VOPT_NOTES);
3658  pSettings[SC_SHOWGRID].Name = SC_UNO_SHOWGRID;
3659  pSettings[SC_SHOWGRID].Value <<= maOptions.GetOption(VOPT_GRID);
3660  pSettings[SC_GRIDCOLOR].Name = SC_UNO_GRIDCOLOR;
3661  OUString aColorName;
3662  Color aColor = maOptions.GetGridColor(&aColorName);
3663  pSettings[SC_GRIDCOLOR].Value <<= aColor;
3664  pSettings[SC_SHOWPAGEBR].Name = SC_UNO_SHOWPAGEBR;
3665  pSettings[SC_SHOWPAGEBR].Value <<= maOptions.GetOption(VOPT_PAGEBREAKS);
3666  pSettings[SC_COLROWHDR].Name = SC_UNO_COLROWHDR;
3667  pSettings[SC_COLROWHDR].Value <<= maOptions.GetOption(VOPT_HEADER);
3668  pSettings[SC_SHEETTABS].Name = SC_UNO_SHEETTABS;
3669  pSettings[SC_SHEETTABS].Value <<= maOptions.GetOption(VOPT_TABCONTROLS);
3670  pSettings[SC_OUTLSYMB].Name = SC_UNO_OUTLSYMB;
3671  pSettings[SC_OUTLSYMB].Value <<= maOptions.GetOption(VOPT_OUTLINER);
3672  pSettings[SC_VALUE_HIGHLIGHTING].Name = SC_UNO_VALUEHIGH;
3673  pSettings[SC_VALUE_HIGHLIGHTING].Value <<= maOptions.GetOption(VOPT_SYNTAX);
3674 
3675  const ScGridOptions& aGridOpt = maOptions.GetGridOptions();
3676  pSettings[SC_SNAPTORASTER].Name = SC_UNO_SNAPTORASTER;
3677  pSettings[SC_SNAPTORASTER].Value <<= aGridOpt.GetUseGridSnap();
3678  pSettings[SC_RASTERVIS].Name = SC_UNO_RASTERVIS;
3679  pSettings[SC_RASTERVIS].Value <<= aGridOpt.GetGridVisible();
3680  pSettings[SC_RASTERRESX].Name = SC_UNO_RASTERRESX;
3681  pSettings[SC_RASTERRESX].Value <<= static_cast<sal_Int32>(aGridOpt.GetFieldDrawX());
3682  pSettings[SC_RASTERRESY].Name = SC_UNO_RASTERRESY;
3683  pSettings[SC_RASTERRESY].Value <<= static_cast<sal_Int32>(aGridOpt.GetFieldDrawY());
3684  pSettings[SC_RASTERSUBX].Name = SC_UNO_RASTERSUBX;
3685  pSettings[SC_RASTERSUBX].Value <<= static_cast<sal_Int32>(aGridOpt.GetFieldDivisionX());
3686  pSettings[SC_RASTERSUBY].Name = SC_UNO_RASTERSUBY;
3687  pSettings[SC_RASTERSUBY].Value <<= static_cast<sal_Int32>(aGridOpt.GetFieldDivisionY());
3688  pSettings[SC_RASTERSYNC].Name = SC_UNO_RASTERSYNC;
3689  pSettings[SC_RASTERSYNC].Value <<= aGridOpt.GetSynchronize();
3690 
3691  // Common SdrModel processing
3693 }
3694 
3695 void ScViewData::ReadUserDataSequence(const uno::Sequence <beans::PropertyValue>& rSettings)
3696 {
3697  std::vector<bool> aHasZoomVect( GetDocument().GetTableCount(), false );
3698 
3699  sal_Int32 nTemp32(0);
3700  sal_Int16 nTemp16(0);
3701  bool bPageMode(false);
3702 
3703  EnsureTabDataSize(GetDocument().GetTableCount());
3704 
3705  for (const auto& rSetting : rSettings)
3706  {
3707  // SC_VIEWID has to parse and use by mba
3708  OUString sName(rSetting.Name);
3709  if (sName == SC_TABLES)
3710  {
3711  uno::Reference<container::XNameContainer> xNameContainer;
3712  if ((rSetting.Value >>= xNameContainer) && xNameContainer->hasElements())
3713  {
3714  const uno::Sequence< OUString > aNames(xNameContainer->getElementNames());
3715  for (const OUString& sTabName : aNames)
3716  {
3717  SCTAB nTab(0);
3718  if (GetDocument().GetTable(sTabName, nTab))
3719  {
3720  uno::Any aAny = xNameContainer->getByName(sTabName);
3721  uno::Sequence<beans::PropertyValue> aTabSettings;
3722  if (aAny >>= aTabSettings)
3723  {
3724  EnsureTabDataSize(nTab + 1);
3725  if (!maTabData[nTab])
3726  maTabData[nTab].reset(new ScViewDataTable(&mrDoc));
3727 
3728  bool bHasZoom = false;
3729  maTabData[nTab]->ReadUserDataSequence(aTabSettings, *this, nTab, bHasZoom);
3730  aHasZoomVect[nTab] = bHasZoom;
3731  }
3732  }
3733  }
3734  }
3735  }
3736  else if (sName == SC_ACTIVETABLE)
3737  {
3738  OUString sTabName;
3739  if(rSetting.Value >>= sTabName)
3740  {
3741  SCTAB nTab(0);
3742  if (GetDocument().GetTable(sTabName, nTab))
3743  nTabNo = nTab;
3744  }
3745  }
3746  else if (sName == SC_HORIZONTALSCROLLBARWIDTH)
3747  {
3748  if (rSetting.Value >>= nTemp32)
3749  pView->SetTabBarWidth(nTemp32);
3750  }
3751  else if (sName == SC_RELHORIZONTALTABBARWIDTH)
3752  {
3753  double fWidth = 0.0;
3754  if (rSetting.Value >>= fWidth)
3755  pView->SetPendingRelTabBarWidth( fWidth );
3756  }
3757  else if (sName == SC_ZOOMTYPE)
3758  {
3759  if (rSetting.Value >>= nTemp16)
3760  eDefZoomType = SvxZoomType(nTemp16);
3761  }
3762  else if (sName == SC_ZOOMVALUE)
3763  {
3764  if (rSetting.Value >>= nTemp32)
3765  {
3766  Fraction aZoom(nTemp32, 100);
3767  aDefZoomX = aDefZoomY = aZoom;
3768  }
3769  }
3770  else if (sName == SC_PAGEVIEWZOOMVALUE)
3771  {
3772  if (rSetting.Value >>= nTemp32)
3773  {
3774  Fraction aZoom(nTemp32, 100);
3775  aDefPageZoomX = aDefPageZoomY = aZoom;
3776  }
3777  }
3778  else if (sName == SC_SHOWPAGEBREAKPREVIEW)
3779  bPageMode = ScUnoHelpFunctions::GetBoolFromAny( rSetting.Value );
3780  else if ( sName == SC_UNO_SHOWZERO )
3782  else if ( sName == SC_UNO_SHOWNOTES )
3784  else if ( sName == SC_UNO_SHOWGRID )
3786  else if ( sName == SC_UNO_GRIDCOLOR )
3787  {
3788  Color aColor;
3789  if (rSetting.Value >>= aColor)
3790  {
3791  // #i47435# set automatic grid color explicitly
3792  if( aColor == COL_AUTO )
3793  aColor = SC_STD_GRIDCOLOR;
3794  maOptions.SetGridColor(aColor, OUString());
3795  }
3796  }
3797  else if ( sName == SC_UNO_SHOWPAGEBR )
3799  else if ( sName == SC_UNO_COLROWHDR )
3801  else if ( sName == SC_UNO_SHEETTABS )
3803  else if ( sName == SC_UNO_OUTLSYMB )
3805  else if ( sName == SC_UNO_SHOWOBJ )
3806  {
3807  // #i80528# placeholders not supported anymore
3808  if ( rSetting.Value >>= nTemp16 )
3810  }
3811  else if ( sName == SC_UNO_SHOWCHARTS )
3812  {
3813  // #i80528# placeholders not supported anymore
3814  if ( rSetting.Value >>= nTemp16 )
3816  }
3817  else if ( sName == SC_UNO_SHOWDRAW )
3818  {
3819  // #i80528# placeholders not supported anymore
3820  if ( rSetting.Value >>= nTemp16 )
3822  }
3823  else if ( sName.compareToAscii( SC_UNO_VALUEHIGH ) == 0 )
3825  else
3826  {
3828  if ( sName == SC_UNO_SNAPTORASTER )
3829  aGridOpt.SetUseGridSnap( ScUnoHelpFunctions::GetBoolFromAny( rSetting.Value ) );
3830  else if ( sName == SC_UNO_RASTERVIS )
3831  aGridOpt.SetGridVisible( ScUnoHelpFunctions::GetBoolFromAny( rSetting.Value ) );
3832  else if ( sName == SC_UNO_RASTERRESX )
3833  aGridOpt.SetFieldDrawX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting.Value ) ) );
3834  else if ( sName == SC_UNO_RASTERRESY )
3835  aGridOpt.SetFieldDrawY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting.Value ) ) );
3836  else if ( sName == SC_UNO_RASTERSUBX )
3837  aGridOpt.SetFieldDivisionX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting.Value ) ) );
3838  else if ( sName == SC_UNO_RASTERSUBY )
3839  aGridOpt.SetFieldDivisionY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( rSetting.Value ) ) );
3840  else if ( sName == SC_UNO_RASTERSYNC )
3841  aGridOpt.SetSynchronize( ScUnoHelpFunctions::GetBoolFromAny( rSetting.Value ) );
3842  // Fallback to common SdrModel processing
3843  else GetDocument().GetDrawLayer()->ReadUserDataSequenceValue(&rSetting);
3844 
3845  maOptions.SetGridOptions(aGridOpt);
3846  }
3847  }
3848 
3849  // copy default zoom to sheets where a different one wasn't specified
3850  for (SCTAB nZoomTab=0; nZoomTab< static_cast<SCTAB>(maTabData.size()); ++nZoomTab)
3851  if (maTabData[nZoomTab] && ( nZoomTab >= static_cast<SCTAB>(aHasZoomVect.size()) || !aHasZoomVect[nZoomTab] ))
3852  {
3853  maTabData[nZoomTab]->eZoomType = eDefZoomType;
3854  maTabData[nZoomTab]->aZoomX = aDefZoomX;
3855  maTabData[nZoomTab]->aZoomY = aDefZoomY;
3856  maTabData[nZoomTab]->aPageZoomX = aDefPageZoomX;
3857  maTabData[nZoomTab]->aPageZoomY = aDefPageZoomY;
3858  }
3859 
3860  if (rSettings.hasElements())
3861  SetPagebreakMode( bPageMode );
3862 
3863  // #i47426# write view options to document, needed e.g. for Excel export
3865 
3868 }
3869 
3871 {
3872  // if visibility of horizontal ScrollBar is changed, TabBar may have to be resized...
3873  bool bHScrollChanged = (rOpt.GetOption(VOPT_HSCROLL) != maOptions.GetOption(VOPT_HSCROLL));
3874 
3875  // if graphics are turned on or off, animation has to be started or stopped
3876  // graphics are controlled by VOBJ_TYPE_OLE
3877  bool bGraphicsChanged = (maOptions.GetObjMode(VOBJ_TYPE_OLE) !=
3878  rOpt.GetObjMode(VOBJ_TYPE_OLE) );
3879 
3880  maOptions = rOpt;
3881  OSL_ENSURE( pView, "No View" );
3882 
3883  if( pView )
3884  {
3885  pView->ViewOptionsHasChanged( bHScrollChanged, bGraphicsChanged );
3886  }
3887 }
3888 
3890 {
3891  OSL_ENSURE( pView, "GetMousePosPixel() without View" );
3892  return pView->GetMousePosPixel();
3893 }
3894 
3896 {
3897  if (pView)
3898  pView->UpdateInputHandler(bForce);
3899 }
3900 
3901 bool ScViewData::IsOle() const
3902 {
3903  return pDocShell && pDocShell->IsOle();
3904 }
3905 
3906 bool ScViewData::UpdateFixX( SCTAB nTab ) // true = value changed
3907 {
3908  if (!ValidTab(nTab)) // Default
3909  nTab=nTabNo; // current table
3910 
3911  if (!pView || maTabData[nTab]->eHSplitMode != SC_SPLIT_FIX)
3912  return false;
3913 
3914  ScDocument& rLocalDoc = GetDocument();
3915  if (!rLocalDoc.HasTable(nTab)) // if called from reload, the sheet may not exist
3916  return false;
3917 
3918  SCCOL nFix = maTabData[nTab]->nFixPosX;
3919  long nNewPos = 0;
3920  for (SCCOL nX=maTabData[nTab]->nPosX[SC_SPLIT_LEFT]; nX<nFix; nX++)
3921  {
3922  sal_uInt16 nTSize = rLocalDoc.GetColWidth( nX, nTab );
3923  if (nTSize)
3924  {
3925  long nPix = ToPixel( nTSize, nPPTX );
3926  nNewPos += nPix;
3927  }
3928  }
3929  nNewPos += pView->GetGridOffset().X();
3930  if (nNewPos != maTabData[nTab]->nHSplitPos)
3931  {
3932  maTabData[nTab]->nHSplitPos = nNewPos;
3933  if (nTab == nTabNo)
3934  RecalcPixPos(); // should not be needed
3935  return true;
3936  }
3937 
3938  return false;
3939 }
3940 
3941 bool ScViewData::UpdateFixY( SCTAB nTab ) // true = value changed
3942 {
3943  if (!ValidTab(nTab)) // Default
3944  nTab=nTabNo; // current table
3945 
3946  if (!pView || maTabData[nTab]->eVSplitMode != SC_SPLIT_FIX)
3947  return false;
3948 
3949  ScDocument& rLocalDoc = GetDocument();
3950  if (!rLocalDoc.HasTable(nTab)) // if called from reload, the sheet may not exist
3951  return false;
3952 
3953  SCROW nFix = maTabData[nTab]->nFixPosY;
3954  long nNewPos = 0;
3955  for (SCROW nY=maTabData[nTab]->nPosY[SC_SPLIT_TOP]; nY<nFix; nY++)
3956  {
3957  sal_uInt16 nTSize = rLocalDoc.GetRowHeight( nY, nTab );
3958  if (nTSize)
3959  {
3960  long nPix = ToPixel( nTSize, nPPTY );
3961  nNewPos += nPix;
3962  }
3963  }
3964  nNewPos += pView->GetGridOffset().Y();
3965  if (nNewPos != maTabData[nTab]->nVSplitPos)
3966  {
3967  maTabData[nTab]->nVSplitPos = nNewPos;
3968  if (nTab == nTabNo)
3969  RecalcPixPos(); // should not be needed
3970  return true;
3971  }
3972 
3973  return false;
3974 }
3975 
3977 {
3978  ScDocument& rLocalDoc = GetDocument();
3979  bool bOnlineSpell = rLocalDoc.GetDocOptions().IsAutoSpell();
3980 
3981  EEControlBits nCntrl = rOutl.GetControlWord();
3982  nCntrl |= EEControlBits::MARKNONURLFIELDS;
3983  nCntrl &= ~EEControlBits::MARKURLFIELDS; // URLs not shaded for output
3984  nCntrl |= EEControlBits::AUTOCORRECT;
3985  if( bOnlineSpell )
3986  nCntrl |= EEControlBits::ONLINESPELLING;
3987  else
3988  nCntrl &= ~EEControlBits::ONLINESPELLING;
3989  rOutl.SetControlWord(nCntrl);
3990 
3991  rOutl.SetCalcFieldValueHdl( LINK( SC_MOD(), ScModule, CalcFieldValueHdl ) );
3992 
3993  // don't call GetSpellChecker if online spelling isn't enabled.
3994  // The language for AutoCorrect etc. is taken from the pool defaults
3995  // (set in ScDocument::UpdateDrawLanguages)
3996 
3997  if ( bOnlineSpell )
3998  {
3999  css::uno::Reference<css::linguistic2::XSpellChecker1> xXSpellChecker1( LinguMgr::GetSpellChecker() );
4000  rOutl.SetSpeller( xXSpellChecker1 );
4001  }
4002 
4004  rLocalDoc.GetEditTextDirection( nTabNo ) );
4005 }
4006 
4008 {
4009  return ScAddress( GetCurX(), GetCurY(), GetTabNo() );
4010 }
4011 
4012 void ScViewData::SetRefStart( SCCOL nNewX, SCROW nNewY, SCTAB nNewZ )
4013 {
4014  nRefStartX = nNewX; nRefStartY = nNewY; nRefStartZ = nNewZ;
4015 }
4016 
4017 void ScViewData::SetRefEnd( SCCOL nNewX, SCROW nNewY, SCTAB nNewZ )
4018 {
4019  nRefEndX = nNewX; nRefEndY = nNewY; nRefEndZ = nNewZ;
4020 }
4021 
4022 void ScViewData::AddPixelsWhile( long & rScrY, long nEndPixels, SCROW & rPosY,
4023  SCROW nEndRow, double nPPTY, const ScDocument * pDoc, SCTAB nTabNo )
4024 {
4025  SCROW nRow = rPosY;
4026  while (rScrY <= nEndPixels && nRow <= nEndRow)
4027  {
4028  SCROW nHeightEndRow;
4029  sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTabNo, nullptr, &nHeightEndRow);
4030  if (nHeightEndRow > nEndRow)
4031  nHeightEndRow = nEndRow;
4032  if (!nHeight)
4033  nRow = nHeightEndRow + 1;
4034  else
4035  {
4036  SCROW nRows = nHeightEndRow - nRow + 1;
4037  sal_Int64 nPixel = ToPixel( nHeight, nPPTY);
4038  sal_Int64 nAdd = nPixel * nRows;
4039  if (nAdd + rScrY > nEndPixels)
4040  {
4041  sal_Int64 nDiff = rScrY + nAdd - nEndPixels;
4042  nRows -= static_cast<SCROW>(nDiff / nPixel);
4043  nAdd = nPixel * nRows;
4044  // We're looking for a value that satisfies loop condition.
4045  if (nAdd + rScrY <= nEndPixels)
4046  {
4047  ++nRows;
4048  nAdd += nPixel;
4049  }
4050  }
4051  rScrY += static_cast<long>(nAdd);
4052  nRow += nRows;
4053  }
4054  }
4055  if (nRow > rPosY)
4056  --nRow;
4057  rPosY = nRow;
4058 }
4059 
4060 void ScViewData::AddPixelsWhileBackward( long & rScrY, long nEndPixels,
4061  SCROW & rPosY, SCROW nStartRow, double nPPTY, const ScDocument * pDoc,
4062  SCTAB nTabNo )
4063 {
4064  SCROW nRow = rPosY;
4065  while (rScrY <= nEndPixels && nRow >= nStartRow)
4066  {
4067  SCROW nHeightStartRow;
4068  sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTabNo, &nHeightStartRow, nullptr);
4069  if (nHeightStartRow < nStartRow)
4070  nHeightStartRow = nStartRow;
4071  if (!nHeight)
4072  nRow = nHeightStartRow - 1;
4073  else
4074  {
4075  SCROW nRows = nRow - nHeightStartRow + 1;
4076  sal_Int64 nPixel = ToPixel( nHeight, nPPTY);
4077  sal_Int64 nAdd = nPixel * nRows;
4078  if (nAdd + rScrY > nEndPixels)
4079  {
4080  sal_Int64 nDiff = nAdd + rScrY - nEndPixels;
4081  nRows -= static_cast<SCROW>(nDiff / nPixel);
4082  nAdd = nPixel * nRows;
4083  // We're looking for a value that satisfies loop condition.
4084  if (nAdd + rScrY <= nEndPixels)
4085  {
4086  ++nRows;
4087  nAdd += nPixel;
4088  }
4089  }
4090  rScrY += static_cast<long>(nAdd);
4091  nRow -= nRows;
4092  }
4093  }
4094  if (nRow < rPosY)
4095  ++nRow;
4096  rPosY = nRow;
4097 }
4098 
4100 {
4101  SCCOLROW nFreezeIndex = bIsCol ? mrDoc.GetLOKFreezeCol(nTabNo) : mrDoc.GetLOKFreezeRow(nTabNo);
4102  return nFreezeIndex >= 0 ? nFreezeIndex : 0;
4103 }
4104 
4105 bool ScViewData::SetLOKSheetFreezeIndex(const SCCOLROW nFreezeIndex, bool bIsCol, SCTAB nForTab)
4106 {
4107  if (nForTab == -1)
4108  {
4109  nForTab = nTabNo;
4110  }
4111  else if (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size())))
4112  {
4113  SAL_WARN("sc.viewdata", "ScViewData::SetLOKSheetFreezeIndex : invalid nForTab = " << nForTab);
4114  return false;
4115  }
4116 
4117  return bIsCol ? mrDoc.SetLOKFreezeCol(static_cast<SCCOL>(nFreezeIndex), nForTab)
4118  : mrDoc.SetLOKFreezeRow(static_cast<SCROW>(nFreezeIndex), nForTab);
4119 }
4120 
4122 {
4123  bool colUnfreezed = SetLOKSheetFreezeIndex(0, true);
4124  bool rowUnfreezed = SetLOKSheetFreezeIndex(0, false);
4125  return colUnfreezed || rowUnfreezed;
4126 }
4127 
4129 {
4130  SCTAB nMaxTab = static_cast<SCTAB>(maTabData.size()) - 1;
4131  for (SCTAB nTab = 0; nTab <= nMaxTab; ++nTab)
4133 }
4134 
4136 {
4137  if (!ValidTab(nForTab) || (nForTab >= static_cast<SCTAB>(maTabData.size())))
4138  {
4139  SAL_WARN("sc.viewdata", "ScViewData::DeriveLOKFreezeIfNeeded : invalid nForTab = " << nForTab);
4140  return;
4141  }
4142 
4143  ScViewDataTable* pViewTable = maTabData[nForTab].get();
4144  if (!pViewTable)
4145  return;
4146 
4147  bool bConvertToFreezeX = false;
4148  bool bConvertToFreezeY = false;
4149  SCCOL nFreezeCol = mrDoc.GetLOKFreezeCol(nForTab);
4150  SCROW nFreezeRow = mrDoc.GetLOKFreezeRow(nForTab);
4151 
4152  if (nFreezeCol == -1)
4153  {
4154  ScSplitMode eSplitMode = pViewTable->eHSplitMode;
4155  if (eSplitMode == SC_SPLIT_FIX)
4156  nFreezeCol = pViewTable->nFixPosX;
4157  else if (eSplitMode == SC_SPLIT_NORMAL)
4158  bConvertToFreezeX = true;
4159  else
4160  nFreezeCol = 0;
4161  }
4162 
4163  if (nFreezeRow == -1)
4164  {
4165  ScSplitMode eSplitMode = pViewTable->eVSplitMode;
4166  if (eSplitMode == SC_SPLIT_FIX)
4167  nFreezeRow = pViewTable->nFixPosY;
4168  else if (eSplitMode == SC_SPLIT_NORMAL)
4169  bConvertToFreezeY = true;
4170  else
4171  nFreezeRow = 0;
4172  }
4173 
4174  if (bConvertToFreezeX || bConvertToFreezeY)
4175  {
4176  SCCOL nCol;
4177  SCROW nRow;
4178  GetPosFromPixel(bConvertToFreezeX ? pViewTable->nHSplitPos : 0,
4179  bConvertToFreezeY ? pViewTable->nVSplitPos : 0,
4180  SC_SPLIT_BOTTOMLEFT, nCol, nRow,
4181  false /* bTestMerge */, false /* bRepair */,
4182  nForTab);
4183  if (bConvertToFreezeX)
4184  nFreezeCol = nCol;
4185  if (bConvertToFreezeY)
4186  nFreezeRow = nRow;
4187  }
4188 
4189  mrDoc.SetLOKFreezeCol(nFreezeCol, nForTab);
4190  mrDoc.SetLOKFreezeRow(nFreezeRow, nForTab);
4191 }
4192 
4193 void ScViewData::OverrideWithLOKFreeze(ScSplitMode& eExHSplitMode, ScSplitMode& eExVSplitMode,
4194  SCCOL& nExFixPosX, SCROW& nExFixPosY,
4195  long& nExHSplitPos, long& nExVSplitPos, SCTAB nForTab) const
4196 {
4197  SCCOL nFreezeCol = mrDoc.GetLOKFreezeCol(nForTab);
4198  SCROW nFreezeRow = mrDoc.GetLOKFreezeRow(nForTab);
4199 
4200  bool bConvertToScrPosX = false;
4201  bool bConvertToScrPosY = false;
4202 
4203  if (nFreezeCol >= 0)
4204  {
4205  if (eExHSplitMode == SC_SPLIT_NONE)
4206  eExHSplitMode = SC_SPLIT_FIX;
4207 
4208  if (eExHSplitMode == SC_SPLIT_FIX)
4209  nExFixPosX = nFreezeCol;
4210  else
4211  bConvertToScrPosX = true;
4212  }
4213 
4214  if (nFreezeRow >= 0)
4215  {
4216  if (eExVSplitMode == SC_SPLIT_NONE)
4217  eExVSplitMode = SC_SPLIT_FIX;
4218 
4219  if (eExVSplitMode == SC_SPLIT_FIX)
4220  nExFixPosY = nFreezeRow;
4221  else
4222  bConvertToScrPosY = true;
4223  }
4224 
4225  if (bConvertToScrPosX || bConvertToScrPosY)
4226  {
4227  Point aExSplitPos = GetScrPos(nFreezeCol, nFreezeRow, SC_SPLIT_BOTTOMLEFT, true, nForTab);
4228  if (bConvertToScrPosX)
4229  nExHSplitPos = aExSplitPos.X();
4230  if (bConvertToScrPosY)
4231  nExVSplitPos = aExSplitPos.Y();
4232  }
4233 }
4234 
4235 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define MAXZOOM
Definition: global.hxx:76
ScMarkData & GetMarkData()
Definition: viewdata.cxx:3046
tools::Rectangle GetEditArea(const ScPatternAttr *pPattern, bool bForceToTop)
Definition: editutil.cxx:285
Point TopLeft() const
#define SC_HORIZONTAL_SPLIT_MODE
SfxViewFrame * GetViewFrame() const
Fraction aZoomY
Definition: viewdata.hxx:213
long Width() const
void DeriveLOKFreezeIfNeeded(SCTAB nForTab)
Definition: viewdata.cxx:4135
tools::Rectangle GetLOKSpecialOutputArea() const
#define SC_UNO_COLROWHDR
Definition: unonames.hxx:535
void SetOption(ScViewOption eOpt, bool bNew)
Definition: viewopti.hxx:87
#define SC_TABLE_SHOWGRID
sal_uInt32 GetFieldDivisionY() const
#define SC_POSITIONLEFT
constexpr double nPPTY
#define SC_TABLE_VIEWSETTINGS
void SetControlWord(EVControlBits nWord)
#define SC_UNO_SHOWCHARTS
Definition: unonames.hxx:542
SCCOL GetColMerge() const
Definition: attrib.hxx:69
SvxCellHorJustify
OUString GetText(LineEnd eEnd=LINEEND_LF) const
ScExtPanePos meActivePane
Active (focused) pane.
Definition: scextopt.hxx:57
long GetWidth() const
#define OLE_STD_CELLS_Y
Definition: global.hxx:115
void KillEditView()
Definition: viewdata.cxx:2203
EEControlBits GetControlWord() const
SCCOL GetOldCurX() const
Definition: viewdata.cxx:1313
#define SC_SHEETTABS
SCCOL SanitizeCol(SCCOL nCol) const
Definition: document.hxx:881
void MarkToSimple()
Definition: markdata.cxx:237
SvxZoomType eDefZoomType
Definition: viewdata.hxx:291
#define SC_CURSORPOSITIONX
index_type nSecondIndex
Definition: viewdata.hxx:166
ScAddress aStart
Definition: address.hxx:500
#define SC_HORIZONTAL_SPLIT_POSITION
long GetHeight() const
todo: It should be possible to have MarkArrays for each table, in order to enable "search all" across...
Definition: markdata.hxx:43
void SetTabBarWidth(long nNewWidth)
Sets an absolute tab bar width (in pixels).
Definition: tabview.cxx:849
#define SC_ZOOMTYPE
void SetCurX(SCCOL nNewCurX)
Definition: viewdata.hxx:431
Bottom, or bottom-left pane.
Definition: scextopt.hxx:43
ScDocShell * pDocShell
Definition: viewdata.hxx:279
ScVSplitPos WhichV(ScSplitPos ePos)
Definition: viewdata.hxx:710
#define EMPTY_OUSTRING
Definition: global.hxx:214
const SCROW MAXROW_30
Definition: address.hxx:91
#define SC_VERTICAL_SPLIT_POSITION
long nMPosY[2]
Definition: viewdata.hxx:220
#define SC_UNO_RASTERSYNC
Definition: unonames.hxx:559
void ReadExtOptions(const ScExtDocOptions &rOpt)
Definition: viewdata.cxx:3431
SAL_DLLPRIVATE void EnsureTabDataSize(size_t nSize)
Definition: viewdata.cxx:2248
#define SC_RASTERSUBY
SCROW Row() const
Definition: address.hxx:262
ScVSplitPos
Definition: viewdata.hxx:47
void GetEndIndexAndPosition(SCCOL &nIndex, long &nPosition) const
Definition: viewdata.cxx:303
#define SC_ACTIVETABLE
EditView * RemoveView(EditView *pEditView)
ScTabViewShell * pView
Definition: viewdata.hxx:281
void SetUpdateMode(bool bUpdate, bool bRestoring=false)
Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
const Fraction & GetZoomX() const
Definition: viewdata.hxx:459
#define SC_RELHORIZONTALTABBARWIDTH
ScPositionHelper aHeightHelper
Definition: viewdata.hxx:239
SAL_DLLPRIVATE void CalcPPT()
Definition: viewdata.cxx:3105
void EnlargeEndBy(long nOffset)
Definition: viewdata.cxx:417
Fraction aDefPageZoomX
Definition: viewdata.hxx:294
#define SC_UNO_RASTERRESX
Definition: unonames.hxx:555
long Height() const
void SetScreenPos(const Point &rVisAreaStart)
Definition: viewdata.cxx:2969
Size aScenButSize
Definition: viewdata.hxx:286
ScAddress maCursor
The cursor position (column/row only).
Definition: scextopt.hxx:52
#define SC_UNO_VALUEHIGH
Definition: unonames.hxx:551
bool IsChanged() const
Definition: scextopt.cxx:160
SC_DLLPUBLIC void SetTabBgColor(SCTAB nTab, const Color &rColor)
Definition: documen3.cxx:450
Fraction aDefPageZoomY
Definition: viewdata.hxx:295
static ScViewOptions DefaultOptions()
Definition: viewdata.cxx:756
SCCOL GetCurXForTab(SCTAB nTabIndex) const
Definition: viewdata.cxx:1369
void invalidateByPosition(long nPos)
Definition: viewdata.cxx:172
Point GetPrintTwipsPos(SCCOL nCol, SCROW nRow) const
returns the position (top-left corner) of the requested cell in print twips coordinates.
Definition: viewdata.cxx:2465
SfxDispatcher * GetDispatcher()
::std::vector< std::unique_ptr< ScViewDataTable > > maTabData
Definition: viewdata.hxx:276
long AdjustLeft(long nHorzMoveDelta)
#define SC_HORIZONTALSCROLLBARWIDTH
#define TWIPS_PER_PIXEL
Definition: global.hxx:88
void InsertTabs(SCTAB nTab, SCTAB nNewSheets)
Definition: viewdata.cxx:884
static bool SelectionFillDOOM(const ScRange &rRange)
Determine DOOM condition, i.e. from selected range.
Definition: viewdata.cxx:1266
void RefreshZoom()
Definition: viewdata.cxx:1104
SCROW GetLOKFreezeRow(SCTAB nTab) const
#define OLE_STD_CELLS_X
Definition: global.hxx:114
#define SC_CURSOR_Y
void SetActivePart(ScSplitPos eNewActive)
Definition: viewdata.cxx:2288
sal_uInt8 GetTransparency() const
sal_uIntPtr sal_uLong
Fraction aPageZoomY
Definition: viewdata.hxx:215
ScAddress maSecondVis
Top-left visible cell in add. panes (column/row only).
Definition: scextopt.hxx:54
sal_uInt32 GetFieldDrawX() const
SCROW GetCurY() const
Definition: viewdata.hxx:402
void EnlargeStartBy(long nOffset)
Definition: viewdata.cxx:402
svtools::ColorConfig & GetColorConfig()
Definition: scmod.cxx:820
ScHSplitPos WhichH(ScSplitPos ePos)
Definition: viewdata.hxx:704
ScDocFunc & GetDocFunc() const
Definition: viewdata.cxx:3029
void SetSpeller(css::uno::Reference< css::linguistic2::XSpellChecker1 > const &xSpeller)
#define SC_PAGE_VIEW_ZOOM_VALUE
const bool bColumnHeader
Definition: viewdata.hxx:160
SCCOL nPosX[2]
X position of the top left cell of the visible area.
Definition: viewdata.hxx:241
SCCOLROW GetLOKSheetFreezeIndex(bool bIsCol) const
Definition: viewdata.cxx:4099
void DeriveLOKFreezeAllSheets()
Definition: viewdata.cxx:4128
double GetOutputFactor() const
Definition: docsh.hxx:352
constexpr OUStringLiteral PERCENT(u"Percent")
ScViewOptions maOptions
Definition: viewdata.hxx:283
bool IsMinimized() const
Definition: tabview.hxx:342
void OverrideWithLOKFreeze(ScSplitMode &eExHSplitMode, ScSplitMode &eExVSplitMode, SCCOL &nExFixPosX, SCROW &nExFixPosY, long &nExHSplitPos, long &nExVSplitPos, SCTAB nForTab) const
Definition: viewdata.cxx:4193
#define SC_TABLE_VIEWSETTINGS_COUNT
void FillRangeListWithMarks(ScRangeList *pList, bool bClear, SCTAB nForTab=-1) const
Create a range list of marks.
Definition: markdata.cxx:387
const SfxItemSet & GetItemSet() const
SvxAdjust GetEditAdjust() const
Definition: viewdata.hxx:501
long nMPosX[2]
Definition: viewdata.hxx:219
double GetPPTX() const
Definition: viewdata.hxx:468
SCCOL nTabStartCol
Definition: viewdata.hxx:316
const ScExtDocSettings & GetDocSettings() const
Definition: scextopt.cxx:170
SCTAB GetTabNo() const
Definition: viewdata.hxx:395
void ViewOptionsHasChanged(bool bHScrollChanged, bool bGraphicsChanged)
Definition: tabview5.cxx:443
#define SC_SHOWZERO
bool SimpleRowMarked()
Definition: viewdata.cxx:1233
ScAddress aEnd
Definition: address.hxx:501
Extended options held by an ScDocument containing additional settings for filters.
Definition: scextopt.hxx:77
ScSplitPos GetActivePart() const
Definition: viewdata.hxx:398
std::unique_ptr< EditView > pEditView[4]
Definition: viewdata.hxx:282
ScDocument & GetDocument() const
Definition: viewdata.hxx:380
void EditGrowY(bool bInitial=false)
Extend the output area for the edit engine view in a vertical direction as needed.
Definition: viewdata.cxx:2074
SCTAB GetLastTab() const
Definition: scextopt.cxx:185
SCCOL nEditEndCol
Definition: viewdata.hxx:314
constexpr TypedWhichId< SvxAdjustItem > EE_PARA_JUST(EE_PARA_START+15)
void GetFillData(SCCOL &rStartCol, SCROW &rStartRow, SCCOL &rEndCol, SCROW &rEndRow)
Definition: viewdata.cxx:1304
const tools::Rectangle & GetOutputArea() const
constexpr TypedWhichId< ScLineBreakCell > ATTR_LINEBREAK(139)
#define SC_CURSOR_X
#define SC_CURSORPOSITIONY
static void forEachOtherView(ViewShellType *pThisViewShell, FunctionType f)
ScSplitPos SanitizeWhichActive() const
Sanitize the active split range value to not point into a grid window that would never be initialized...
Definition: viewdata.cxx:732
EEControlBits
ScRangeList maSelection
Selected cell ranges (columns/rows only).
Definition: scextopt.hxx:51
css::chart::ChartAxisLabelPosition ePos
SCCOL GetPosX(ScHSplitPos eWhich, SCTAB nForTab=-1) const
Definition: viewdata.cxx:1341
#define SC_TABLES
SCCOL CellsAtX(SCCOL nPosX, SCCOL nDir, ScHSplitPos eWhichX, sal_uInt16 nScrSizeY=SC_SIZE_NONE) const
Definition: viewdata.cxx:2543
sal_Int32 getTokenCount(const OString &rIn, char cTok)
std::set< value_type, Comp > mData
Definition: viewdata.hxx:137
#define SC_UNO_SHOWOBJ
Definition: unonames.hxx:548
constexpr TypedWhichId< ScMergeAttr > ATTR_MERGE(144)
static void AddPixelsWhileBackward(long &rScrY, long nEndPixels, SCROW &rPosY, SCROW nStartRow, double nPPTY, const ScDocument *pDoc, SCTAB nTabNo)
while (rScrY <= nEndPixels && rPosY >= nStartRow) add pixels of row heights converted with nPPTY to r...
Definition: viewdata.cxx:4060
SC_DLLPUBLIC sal_uInt16 GetRowHeight(SCROW nRow, SCTAB nTab, bool bHiddenAsZero=true) const
Definition: document.cxx:4161
void ReadUserData(const OUString &rData)
Definition: viewdata.cxx:3215
ScSplitPos
Definition: viewdata.hxx:45
double mfTabBarWidth
Width of the tabbar, relative to frame window width (0.0 ... 1.0).
Definition: scextopt.hxx:31
long AdjustBottom(long nVertMoveDelta)
SCROW GetOldCurY() const
Definition: viewdata.cxx:1321
double nPPTX
Definition: viewdata.hxx:274
void GetIndexAndPos(index_type nNearestIndex, long nNearestPosition, long nBound, index_type &nFoundIndex, long &nPosition, bool bTowards, long nDiff)
Definition: viewdata.cxx:330
void SetVisArea(const tools::Rectangle &rRect)
bool UpdateFixY(SCTAB nTab=MAXTAB+1)
Definition: viewdata.cxx:3941
SCROW nEditEndRow
Definition: viewdata.hxx:315
SAL_DLLPRIVATE void UpdateCurrentTab()
Definition: viewdata.cxx:854
void GetMarkArea(ScRange &rRange) const
Definition: markdata.cxx:112
static OutputDevice * GetDefaultDevice()
void SetPagebreakMode(bool bSet)
Definition: viewdata.cxx:1115
#define SC_HORIZONTALSPLITPOSITION_TWIPS
static UITestLogger & getInstance()
ScPositionHelper(const ScDocument *pDoc, bool bColumn)
Definition: viewdata.cxx:121
constexpr::Color COL_AUTO(0xFF, 0xFF, 0xFF, 0xFF)
void logEvent(const EventDescription &rDescription)
sal_uInt16 sal_Unicode
void UpdateInputHandler(bool bForce=false)
Definition: viewdata.cxx:3895
SCTAB nTabNo
Definition: viewdata.hxx:299
long GetTabBarWidth() const
Returns the current tab bar width in pixels.
Definition: tabview.cxx:873
#define SC_UNO_RASTERRESY
Definition: unonames.hxx:556
long Right() const
#define SC_UNO_SHOWGRID
Definition: unonames.hxx:545
void InsertView(EditView *pEditView, size_t nIndex=EE_APPEND)
bool IsOle() const
Definition: viewdata.cxx:3901
void DeleteTab(SCTAB nTab)
Definition: markdata.cxx:638
#define STD_COL_WIDTH
Definition: global.hxx:93
Fraction aPageZoomX
Definition: viewdata.hxx:214
void SetControlWord(EEControlBits nWord)
long GetGridWidth(ScHSplitPos eWhich)
Definition: tabview3.cxx:2978
void WriteExtOptions(ScExtDocOptions &rOpt) const
Definition: viewdata.cxx:3320
#define SC_VALUE_HIGHLIGHTING
void RecalcPixPos()
Definition: viewdata.cxx:2902
void GetPosFromPixel(long nClickX, long nClickY, ScSplitPos eWhich, SCCOL &rPosX, SCROW &rPosY, bool bTestMerge=true, bool bRepair=false, SCTAB nForTab=-1)
Definition: viewdata.cxx:2694
void SetObjMode(ScVObjType eObj, ScVObjMode eMode)
Definition: viewopti.hxx:90
SC_DLLPUBLIC SCROW MaxRow() const
Definition: document.hxx:873
#define SC_TABLE_ZOOM_VALUE
SCCOL PrevCellsX(ScHSplitPos eWhichX) const
Definition: viewdata.cxx:2631
sal_Int32 SCCOLROW
a type capable of holding either SCCOL or SCROW
Definition: types.hxx:24
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
SC_DLLPUBLIC SCTAB GetTableCount() const
Definition: document.cxx:314
long GetGridHeight(ScVSplitPos eWhich)
Definition: tabview3.cxx:2989
SCCOL nRefStartX
Definition: viewdata.hxx:301
#define SC_SNAPTORASTER
void SetPosX(ScHSplitPos eWhich, SCCOL nNewPosX)
Definition: viewdata.cxx:2820
#define SC_VIEWID
void SetPendingRelTabBarWidth(double fRelTabBarWidth)
Sets a relative tab bar width.
Definition: tabview.cxx:867
SCCOL VisibleCellsX(ScHSplitPos eWhichX) const
Definition: viewdata.cxx:2621
void SetControlWord(EEControlBits nWord)
bool IsMultiMarked() const
Definition: markdata.hxx:83
SCCOLROW index_type
Definition: viewdata.hxx:156
void EditGrowX()
Extend the output area for the edit engine view in a horizontal direction as needed.
Definition: viewdata.cxx:1778
#define SC_HORIZONTALSPLITPOSITION
const SCROW MAXROW
Definition: address.hxx:69
#define SC_TABLE_PAGE_VIEW_ZOOM_VALUE
bool isCompatFlagSet(Compat flag)
void SetOptions(const ScViewOptions &rOpt)
Definition: viewdata.cxx:3870
#define SC_UNO_RASTERVIS
Definition: unonames.hxx:554
SC_DLLPUBLIC bool HasTable(SCTAB nTab) const
Definition: document.cxx:191
void UpdateInputHandler(bool bForce=false, bool bStopEditing=true)
Definition: tabvwsha.cxx:638
#define HMM_PER_TWIPS
Definition: global.hxx:91
void SetRow(SCROW nRowP)
Definition: address.hxx:275
void WriteUserData(OUString &rData)
Definition: viewdata.cxx:3155
void WriteUserDataSequence(css::uno::Sequence< css::beans::PropertyValue > &rSettings) const
Definition: viewdata.cxx:3599
#define PIXEL_PER_TWIPS
Definition: global.hxx:90
long Top() const
bool mbShowGrid
Whether or not to display gridlines.
Definition: scextopt.hxx:64
#define SC_RASTERRESX
EEControlBits GetControlWord() const
#define SC_UNO_RASTERSUBX
Definition: unonames.hxx:557
#define SC_UNO_SHOWPAGEBR
Definition: unonames.hxx:549
#define SC_ACTIVE_TABLE
void GeIndexBackwards(index_type nNearestIndex, long nNearestPosition, long nBound, index_type &nFoundIndex, long &nPosition, bool bTowards)
Definition: viewdata.cxx:430
SCROW GetPosY(ScVSplitPos eWhich, SCTAB nForTab=-1) const
Definition: viewdata.cxx:1355
#define SC_GRIDCOLOR
const Fraction & GetZoomY() const
Definition: viewdata.hxx:460
ScSplitMode eVSplitMode
Definition: viewdata.hxx:227
#define SC_RASTERSUBX
SC_DLLPUBLIC const ScPatternAttr * GetPattern(SCCOL nCol, SCROW nRow, SCTAB nTab) const
Definition: document.cxx:4735
void SetCol(SCCOL nColP)
Definition: address.hxx:279
#define SC_STD_GRIDCOLOR
Definition: viewopti.hxx:61
const char * sName
#define SC_TABLESELECTED
ScDrawView * GetScDrawView()
Definition: viewdata.cxx:3074
#define SC_POSITION_TOP
ScGridWindow * GetActiveWin()
Definition: tabview.cxx:883
SC_DLLPUBLIC const SfxPoolItem * GetAttr(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich) const
Definition: document.cxx:4714
void SetRefStart(SCCOL nNewX, SCROW nNewY, SCTAB nNewZ)
Definition: viewdata.cxx:4012
void GetIndexTowards(index_type nNearestIndex, long nNearestPosition, long nBound, index_type &nFoundIndex, long &nPosition, bool bTowards)
Definition: viewdata.cxx:454
void WriteUserDataSequence(css::uno::Sequence< css::beans::PropertyValue > &rValues)
ScPasteFlags
Definition: viewdata.hxx:81
const SfxPoolItem & GetItem(sal_uInt16 nWhichP) const
Definition: patattr.hxx:70
#define SC_HORIZONTALSPLITMODE
SCROW VisibleCellsY(ScVSplitPos eWhichY) const
Definition: viewdata.cxx:2626
ScDocument & rDoc
Definition: viewdata.hxx:158
DocumentType eType
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
Definition: documen3.cxx:1923
#define SC_RASTERVIS
ScTabViewShell * GetViewShell() const
Definition: viewdata.hxx:357
SCROW nFillStartY
Definition: viewdata.hxx:308
#define SC_UNO_RASTERSUBY
Definition: unonames.hxx:558
bool IsValid() const
Definition: address.hxx:293
constexpr double nPPTX
static SC_DLLPUBLIC sal_uInt16 nStdRowHeight
Definition: global.hxx:583
void InsertTab(SCTAB nTab)
Definition: viewdata.cxx:870
bool mbFrozenPanes
true = Frozen panes; false = Normal splits.
Definition: scextopt.hxx:62
bool HasDetectiveObjects(SCTAB nTab) const
Definition: documen9.cxx:513
void SetDefaultHorizontalTextDirection(EEHorizontalTextDirection eHTextDir)
ScExtTabSettings & GetOrCreateTabSettings(SCTAB nTab)
Definition: scextopt.cxx:190
void SetTabNo(SCTAB nNewTab)
Definition: viewdata.cxx:2254
#define SC_ACTIVESPLITRANGE
bool IsVertical() const
#define SC_ZOOM_TYPE
const Size & GetLOKSpecialPaperSize() const
SC_DLLPUBLIC ScDrawLayer * GetDrawLayer()
Definition: document.hxx:1059
SC_DLLPUBLIC SCCOL MaxCol() const
Definition: document.hxx:872
T * get() const
#define SC_UNO_SHOWDRAW
Definition: unonames.hxx:543
void SetScaleX(const Fraction &rScaleX)
void SetTop(long v)
static css::uno::Reference< css::linguistic2::XSpellChecker1 > GetSpellChecker()
bool GetUseGridSnap() const
static bool HasFiltered(const ScRange &rRange, const ScDocument &rDoc)
Definition: viewutil.cxx:272
void setDocument(const ScDocument &rDoc, bool bColumn)
Definition: viewdata.cxx:127
Size aScrSize
Definition: viewdata.hxx:288
const SCTAB SC_TAB_APPEND
Definition: address.hxx:84
bool IsMarked() const
Definition: markdata.hxx:82
#define nPixel
#define SC_VERTICAL_SPLIT_MODE
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const value_type & getNearestByPosition(long nPos) const
Definition: viewdata.cxx:218
void SetDefaultItem(const SfxPoolItem &rItem)
Set the item in the default ItemSet which is created if it doesn't exist yet.
Definition: editutil.cxx:538
SvxAdjust
int i
void DeleteTab(SCTAB nTab)
Definition: viewdata.cxx:903
void InvalidateOtherViewW