Line data Source code
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 :
21 : #include "scitems.hxx"
22 : #include <editeng/eeitem.hxx>
23 : #include <vcl/timer.hxx>
24 : #include <vcl/msgbox.hxx>
25 : #include <sfx2/app.hxx>
26 : #include <sfx2/viewfrm.hxx>
27 : #include <sfx2/bindings.hxx>
28 : #include <sfx2/childwin.hxx>
29 :
30 : #include "attrib.hxx"
31 : #include "pagedata.hxx"
32 : #include "tabview.hxx"
33 : #include "tabvwsh.hxx"
34 : #include "printfun.hxx"
35 : #include "stlpool.hxx"
36 : #include "docsh.hxx"
37 : #include "gridwin.hxx"
38 : #include "olinewin.hxx"
39 : #include "uiitems.hxx"
40 : #include "sc.hrc"
41 : #include "viewutil.hxx"
42 : #include "colrowba.hxx"
43 : #include "waitoff.hxx"
44 : #include "globstr.hrc"
45 : #include "scmod.hxx"
46 : #include "tabprotection.hxx"
47 : #include "markdata.hxx"
48 :
49 : namespace {
50 :
51 0 : bool isCellQualified(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
52 : {
53 : bool bCellProtected = pDoc->HasAttrib(
54 0 : nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_PROTECTED);
55 :
56 0 : if (bCellProtected && !bSelectLocked)
57 0 : return false;
58 :
59 0 : if (!bCellProtected && !bSelectUnlocked)
60 0 : return false;
61 :
62 0 : return true;
63 : }
64 :
65 0 : void moveCursorByProtRule(
66 : SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, SCTAB nTab, ScDocument* pDoc)
67 : {
68 0 : bool bSelectLocked = true;
69 0 : bool bSelectUnlocked = true;
70 0 : ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
71 0 : if (pTabProtection && pTabProtection->isProtected())
72 : {
73 0 : bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
74 0 : bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
75 : }
76 :
77 0 : if (nMovX > 0)
78 : {
79 0 : for (SCCOL i = 0; i < nMovX && rCol < MAXCOL; ++i)
80 : {
81 0 : if (!isCellQualified(pDoc, rCol+1, rRow, nTab, bSelectLocked, bSelectUnlocked))
82 0 : break;
83 0 : ++rCol;
84 : }
85 : }
86 0 : else if (nMovX < 0)
87 : {
88 0 : for (SCCOL i = 0; i > nMovX && rCol > 0; --i)
89 : {
90 0 : if (!isCellQualified(pDoc, rCol-1, rRow, nTab, bSelectLocked, bSelectUnlocked))
91 0 : break;
92 0 : --rCol;
93 : }
94 : }
95 :
96 0 : if (nMovY > 0)
97 : {
98 0 : for (SCROW i = 0; i < nMovY && rRow < MAXROW; ++i)
99 : {
100 0 : if (!isCellQualified(pDoc, rCol, rRow+1, nTab, bSelectLocked, bSelectUnlocked))
101 0 : break;
102 0 : ++rRow;
103 : }
104 : }
105 0 : else if (nMovY < 0)
106 : {
107 0 : for (SCROW i = 0; i > nMovY && rRow > 0; --i)
108 : {
109 0 : if (!isCellQualified(pDoc, rCol, rRow-1, nTab, bSelectLocked, bSelectUnlocked))
110 0 : break;
111 0 : --rRow;
112 : }
113 : }
114 0 : }
115 :
116 0 : bool checkBoundary(SCCOL& rCol, SCROW& rRow)
117 : {
118 0 : bool bGood = true;
119 0 : if (rCol < 0)
120 : {
121 0 : rCol = 0;
122 0 : bGood = false;
123 : }
124 0 : else if (rCol > MAXCOL)
125 : {
126 0 : rCol = MAXCOL;
127 0 : bGood = false;
128 : }
129 :
130 0 : if (rRow < 0)
131 : {
132 0 : rRow = 0;
133 0 : bGood = false;
134 : }
135 0 : else if (rRow > MAXROW)
136 : {
137 0 : rRow = MAXROW;
138 0 : bGood = false;
139 : }
140 0 : return bGood;
141 : }
142 :
143 0 : void moveCursorByMergedCell(
144 : SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, SCTAB nTab,
145 : ScDocument* pDoc, const ScViewData& rViewData)
146 : {
147 0 : SCCOL nOrigX = rViewData.GetCurX();
148 0 : SCROW nOrigY = rViewData.GetCurY();
149 :
150 0 : ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
151 0 : bool bSelectLocked = true;
152 0 : bool bSelectUnlocked = true;
153 0 : if (pTabProtection && pTabProtection->isProtected())
154 : {
155 0 : bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
156 0 : bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
157 : }
158 :
159 : const ScMergeAttr* pMergeAttr = static_cast<const ScMergeAttr*>(
160 0 : pDoc->GetAttr(nOrigX, nOrigY, nTab, ATTR_MERGE));
161 :
162 0 : bool bOriginMerged = false;
163 0 : SCsCOL nColSpan = 1;
164 0 : SCsROW nRowSpan = 1;
165 0 : if (pMergeAttr && pMergeAttr->IsMerged())
166 : {
167 0 : nColSpan = pMergeAttr->GetColMerge();
168 0 : nRowSpan = pMergeAttr->GetRowMerge();
169 0 : bOriginMerged = true;
170 : }
171 :
172 0 : if (nMovX > 0)
173 : {
174 0 : SCCOL nOld = rCol;
175 0 : if (bOriginMerged)
176 : {
177 : // Original cell is merged. Push the block end outside the merged region.
178 0 : if (nOrigX < MAXCOL && nOrigX < rCol && rCol <= nOrigX + nColSpan - 1)
179 0 : rCol = nOrigX + nColSpan;
180 : }
181 : else
182 : {
183 0 : pDoc->SkipOverlapped(rCol, rRow, nTab);
184 : }
185 :
186 0 : if (nOld < rCol)
187 : {
188 : // The block end has moved. Check the protection setting and move back if needed.
189 0 : checkBoundary(rCol, rRow);
190 0 : if (!isCellQualified(pDoc, rCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
191 0 : --rCol;
192 : }
193 : }
194 0 : if (nMovX < 0)
195 : {
196 0 : SCCOL nOld = rCol;
197 0 : if (bOriginMerged)
198 : {
199 0 : if (nOrigX > 0 && nOrigX <= rCol && rCol < nOrigX + nColSpan - 1)
200 : // Block end is still within the merged region. Push it outside.
201 0 : rCol = nOrigX - 1;
202 : }
203 : else
204 : {
205 0 : pDoc->SkipOverlapped(rCol, rRow, nTab);
206 : }
207 :
208 0 : if (nOld > rCol)
209 : {
210 : // The block end has moved. Check the protection setting and move back if needed.
211 0 : checkBoundary(rCol, rRow);
212 0 : if (!isCellQualified(pDoc, rCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
213 0 : ++rCol;
214 : }
215 : }
216 0 : if (nMovY > 0)
217 : {
218 0 : SCROW nOld = rRow;
219 0 : if (bOriginMerged)
220 : {
221 : // Original cell is merged. Push the block end outside the merged region.
222 0 : if (nOrigY < MAXROW && nOrigY < rRow && rRow <= nOrigY + nRowSpan - 1)
223 0 : rRow = nOrigY + nRowSpan;
224 : }
225 : else
226 : {
227 0 : pDoc->SkipOverlapped(rCol, rRow, nTab);
228 : }
229 :
230 0 : if (nOld < rRow)
231 : {
232 : // The block end has moved. Check the protection setting and move back if needed.
233 0 : checkBoundary(rCol, rRow);
234 0 : if (!isCellQualified(pDoc, rCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
235 0 : --rRow;
236 : }
237 : }
238 0 : if (nMovY < 0)
239 : {
240 0 : SCROW nOld = rRow;
241 0 : if (bOriginMerged)
242 : {
243 0 : if (nOrigY > 0 && nOrigY <= rRow && rRow < nOrigY + nRowSpan - 1)
244 : // Block end is still within the merged region. Push it outside.
245 0 : rRow = nOrigY - 1;
246 : }
247 : else
248 : {
249 0 : pDoc->SkipOverlapped(rCol, rRow, nTab);
250 : }
251 :
252 0 : if (nOld > rRow)
253 : {
254 : // The block end has moved. Check the protection setting and move back if needed.
255 0 : checkBoundary(rCol, rRow);
256 0 : if (!isCellQualified(pDoc, rCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
257 0 : ++rRow;
258 : }
259 : }
260 0 : }
261 :
262 : }
263 :
264 0 : void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
265 : {
266 0 : if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
267 0 : if (!ValidRow(nStartRow)) nStartRow = MAXROW;
268 0 : if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
269 0 : if (!ValidRow(nEndRow)) nEndRow = MAXROW;
270 :
271 0 : bool bLeft = (nStartCol==0 && nEndCol==MAXCOL);
272 0 : bool bTop = (nStartRow==0 && nEndRow==MAXROW);
273 :
274 0 : if (bLeft)
275 0 : PaintLeftArea( nStartRow, nEndRow );
276 0 : if (bTop)
277 0 : PaintTopArea( nStartCol, nEndCol );
278 :
279 : aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
280 0 : aViewData.GetTabNo() );
281 0 : PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS );
282 0 : }
283 :
284 0 : bool ScTabView::IsMarking( SCCOL nCol, SCROW nRow, SCTAB nTab ) const
285 : {
286 0 : return IsBlockMode()
287 : && nBlockStartX == nCol
288 : && nBlockStartY == nRow
289 0 : && nBlockStartZ == nTab;
290 : }
291 :
292 0 : void ScTabView::InitOwnBlockMode()
293 : {
294 0 : if (!IsBlockMode())
295 : {
296 : // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen:
297 :
298 0 : ScMarkData& rMark = aViewData.GetMarkData();
299 0 : if (!rMark.IsMarked() && !rMark.IsMultiMarked())
300 0 : GetSelEngine()->CursorPosChanging( false, false );
301 :
302 0 : meBlockMode = Own;
303 0 : nBlockStartX = 0;
304 0 : nBlockStartY = 0;
305 0 : nBlockStartZ = 0;
306 0 : nBlockEndX = 0;
307 0 : nBlockEndY = 0;
308 0 : nBlockEndZ = 0;
309 :
310 0 : SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt
311 : }
312 0 : }
313 :
314 0 : void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
315 : bool bTestNeg, bool bCols, bool bRows )
316 : {
317 0 : if (!IsBlockMode())
318 : {
319 0 : if (!ValidCol(nCurX)) nCurX = MAXCOL;
320 0 : if (!ValidRow(nCurY)) nCurY = MAXROW;
321 :
322 0 : ScMarkData& rMark = aViewData.GetMarkData();
323 0 : SCTAB nTab = aViewData.GetTabNo();
324 :
325 : // Teil von Markierung aufheben?
326 0 : if (bTestNeg)
327 : {
328 0 : if ( bCols )
329 0 : bBlockNeg = rMark.IsColumnMarked( nCurX );
330 0 : else if ( bRows )
331 0 : bBlockNeg = rMark.IsRowMarked( nCurY );
332 : else
333 0 : bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
334 : }
335 : else
336 0 : bBlockNeg = false;
337 0 : rMark.SetMarkNegative(bBlockNeg);
338 :
339 0 : meBlockMode = Normal;
340 0 : bBlockCols = bCols;
341 0 : bBlockRows = bRows;
342 0 : nBlockStartX = nBlockStartXOrig = nCurX;
343 0 : nBlockStartY = nBlockStartYOrig = nCurY;
344 0 : nBlockStartZ = nCurZ;
345 0 : nBlockEndX = nOldCurX = nBlockStartX;
346 0 : nBlockEndY = nOldCurY = nBlockStartY;
347 0 : nBlockEndZ = nBlockStartZ;
348 :
349 0 : if (bBlockCols)
350 : {
351 0 : nBlockStartY = nBlockStartYOrig = 0;
352 0 : nBlockEndY = MAXROW;
353 : }
354 :
355 0 : if (bBlockRows)
356 : {
357 0 : nBlockStartX = nBlockStartXOrig = 0;
358 0 : nBlockEndX = MAXCOL;
359 : }
360 :
361 0 : rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
362 :
363 0 : UpdateSelectionOverlay();
364 : }
365 0 : }
366 :
367 0 : void ScTabView::DoneBlockMode( bool bContinue )
368 : {
369 : // Wenn zwischen Tabellen- und Header SelectionEngine gewechselt wird,
370 : // wird evtl. DeselectAll gerufen, weil die andere Engine keinen Anker hat.
371 : // Mit bMoveIsShift wird verhindert, dass dann die Selektion aufgehoben wird.
372 :
373 0 : if (IsBlockMode() && !bMoveIsShift)
374 : {
375 0 : ScMarkData& rMark = aViewData.GetMarkData();
376 0 : bool bFlag = rMark.GetMarkingFlag();
377 0 : rMark.SetMarking(false);
378 :
379 0 : if (bBlockNeg && !bContinue)
380 0 : rMark.MarkToMulti();
381 :
382 0 : if (bContinue)
383 0 : rMark.MarkToMulti();
384 : else
385 : {
386 : // Die Tabelle kann an dieser Stelle ungueltig sein, weil DoneBlockMode
387 : // aus SetTabNo aufgerufen wird
388 : // (z.B. wenn die aktuelle Tabelle von einer anderen View aus geloescht wird)
389 :
390 0 : SCTAB nTab = aViewData.GetTabNo();
391 0 : ScDocument* pDoc = aViewData.GetDocument();
392 0 : if ( pDoc->HasTable(nTab) )
393 0 : PaintBlock( true ); // true -> Block loeschen
394 : else
395 0 : rMark.ResetMark();
396 : }
397 0 : meBlockMode = None;
398 :
399 0 : rMark.SetMarking(bFlag);
400 0 : rMark.SetMarkNegative(false);
401 : }
402 0 : }
403 :
404 0 : bool ScTabView::IsBlockMode() const
405 : {
406 0 : return meBlockMode != None;
407 : }
408 :
409 0 : void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
410 : bool bCols, bool bRows, bool bCellSelection )
411 : {
412 0 : if (!ValidCol(nCurX)) nCurX = MAXCOL;
413 0 : if (!ValidRow(nCurY)) nCurY = MAXROW;
414 :
415 0 : if (!IsBlockMode())
416 : {
417 : OSL_FAIL( "MarkCursor nicht im BlockMode" );
418 0 : InitBlockMode( nCurX, nCurY, nCurZ, false, bCols, bRows );
419 : }
420 :
421 0 : if (bCols)
422 0 : nCurY = MAXROW;
423 0 : if (bRows)
424 0 : nCurX = MAXCOL;
425 :
426 0 : ScMarkData& rMark = aViewData.GetMarkData();
427 : OSL_ENSURE(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
428 0 : ScRange aMarkRange;
429 0 : rMark.GetMarkArea(aMarkRange);
430 0 : if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
431 0 : ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
432 : ( meBlockMode == Own ))
433 : {
434 : // Markierung ist veraendert worden
435 : // (z.B. MarkToSimple, wenn per negativ alles bis auf ein Rechteck geloescht wurde)
436 : // oder nach InitOwnBlockMode wird mit Shift-Klick weitermarkiert...
437 :
438 0 : bool bOldShift = bMoveIsShift;
439 0 : bMoveIsShift = false; // wirklich umsetzen
440 0 : DoneBlockMode(false); //! direkt Variablen setzen? (-> kein Geflacker)
441 0 : bMoveIsShift = bOldShift;
442 :
443 0 : InitBlockMode( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
444 0 : nBlockStartZ, rMark.IsMarkNegative(), bCols, bRows );
445 : }
446 :
447 0 : if ( nCurX != nOldCurX || nCurY != nOldCurY )
448 : {
449 : // Current cursor has moved
450 :
451 0 : SCTAB nTab = nCurZ;
452 :
453 0 : if ( bCellSelection )
454 : {
455 : // Expand selection area accordingly when the current selection ends
456 : // with a merged cell.
457 0 : SCsCOL nCurXOffset = 0;
458 0 : SCsCOL nBlockStartXOffset = 0;
459 0 : SCsROW nCurYOffset = 0;
460 0 : SCsROW nBlockStartYOffset = 0;
461 0 : bool bBlockStartMerged = false;
462 0 : const ScMergeAttr* pMergeAttr = NULL;
463 0 : ScDocument* pDocument = aViewData.GetDocument();
464 :
465 : // The following block checks whether or not the "BlockStart" (anchor)
466 : // cell is merged. If it's merged, it'll then move the position of the
467 : // anchor cell to the corner that's diagonally opposite of the
468 : // direction of a current selection area. For instance, if a current
469 : // selection is moving in the upperleft direction, the anchor cell will
470 : // move to the lower-right corner of the merged anchor cell, and so on.
471 :
472 : pMergeAttr = static_cast<const ScMergeAttr*>(
473 0 : pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) );
474 0 : if ( pMergeAttr->IsMerged() )
475 : {
476 0 : SCsCOL nColSpan = pMergeAttr->GetColMerge();
477 0 : SCsROW nRowSpan = pMergeAttr->GetRowMerge();
478 :
479 0 : if ( !( nCurX >= nBlockStartXOrig + nColSpan - 1 && nCurY >= nBlockStartYOrig + nRowSpan - 1 ) )
480 : {
481 0 : nBlockStartX = nCurX >= nBlockStartXOrig ? nBlockStartXOrig : nBlockStartXOrig + nColSpan - 1;
482 0 : nBlockStartY = nCurY >= nBlockStartYOrig ? nBlockStartYOrig : nBlockStartYOrig + nRowSpan - 1;
483 : nCurXOffset = (nCurX >= nBlockStartXOrig && nCurX < nBlockStartXOrig + nColSpan - 1) ?
484 0 : nBlockStartXOrig - nCurX + nColSpan - 1 : 0;
485 : nCurYOffset = (nCurY >= nBlockStartYOrig && nCurY < nBlockStartYOrig + nRowSpan - 1) ?
486 0 : nBlockStartYOrig - nCurY + nRowSpan - 1 : 0;
487 0 : bBlockStartMerged = sal_True;
488 : }
489 : }
490 :
491 : // The following block checks whether or not the current cell is
492 : // merged. If it is, it'll then set the appropriate X & Y offset
493 : // values (nCurXOffset & nCurYOffset) such that the selection area will
494 : // grow by those specified offset amounts. Note that the values of
495 : // nCurXOffset/nCurYOffset may also be specified in the previous code
496 : // block, in which case whichever value is greater will take on.
497 :
498 : pMergeAttr = static_cast<const ScMergeAttr*>(
499 0 : pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) );
500 0 : if ( pMergeAttr->IsMerged() )
501 : {
502 0 : SCsCOL nColSpan = pMergeAttr->GetColMerge();
503 0 : SCsROW nRowSpan = pMergeAttr->GetRowMerge();
504 :
505 0 : if ( !( nBlockStartX >= nCurX + nColSpan - 1 && nBlockStartY >= nCurY + nRowSpan - 1 ) )
506 : {
507 0 : if ( nBlockStartX <= nCurX + nColSpan - 1 )
508 : {
509 0 : SCsCOL nCurXOffsetTemp = (nCurX < nCurX + nColSpan - 1) ? nColSpan - 1 : 0;
510 0 : nCurXOffset = nCurXOffset > nCurXOffsetTemp ? nCurXOffset : nCurXOffsetTemp;
511 : }
512 0 : if ( nBlockStartY <= nCurY + nRowSpan - 1 )
513 : {
514 0 : SCsROW nCurYOffsetTemp = (nCurY < nCurY + nRowSpan - 1) ? nRowSpan - 1 : 0;
515 0 : nCurYOffset = nCurYOffset > nCurYOffsetTemp ? nCurYOffset : nCurYOffsetTemp;
516 : }
517 0 : if ( !( nBlockStartX <= nCurX && nBlockStartY <= nCurY ) &&
518 0 : !( nBlockStartX > nCurX + nColSpan - 1 && nBlockStartY > nCurY + nRowSpan - 1 ) )
519 : {
520 0 : nBlockStartXOffset = (nBlockStartX > nCurX && nBlockStartX <= nCurX + nColSpan - 1) ? nCurX - nBlockStartX : 0;
521 0 : nBlockStartYOffset = (nBlockStartY > nCurY && nBlockStartY <= nCurY + nRowSpan - 1) ? nCurY - nBlockStartY : 0;
522 : }
523 : }
524 : }
525 : else
526 : {
527 : // The current cell is not merged. Move the anchor cell to its
528 : // original position.
529 0 : if ( !bBlockStartMerged )
530 : {
531 0 : nBlockStartX = nBlockStartXOrig;
532 0 : nBlockStartY = nBlockStartYOrig;
533 : }
534 : }
535 :
536 0 : nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0;
537 0 : nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0;
538 0 : nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset;
539 0 : nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset;
540 : }
541 : else
542 : {
543 0 : nBlockEndX = nCurX;
544 0 : nBlockEndY = nCurY;
545 : }
546 :
547 : // Set new selection area
548 0 : rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
549 :
550 0 : UpdateSelectionOverlay();
551 0 : SelectionChanged();
552 :
553 0 : nOldCurX = nCurX;
554 0 : nOldCurY = nCurY;
555 :
556 0 : aViewData.GetViewShell()->UpdateInputHandler();
557 : }
558 :
559 0 : if ( !bCols && !bRows )
560 0 : aHdrFunc.SetAnchorFlag( false );
561 0 : }
562 :
563 0 : void ScTabView::GetPageMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, SCsCOL& rPageX, SCsROW& rPageY)
564 : {
565 : SCCOL nCurX;
566 : SCROW nCurY;
567 0 : if (aViewData.IsRefMode())
568 : {
569 0 : nCurX = aViewData.GetRefEndX();
570 0 : nCurY = aViewData.GetRefEndY();
571 : }
572 0 : else if (IsBlockMode())
573 : {
574 : // block end position.
575 0 : nCurX = nBlockEndX;
576 0 : nCurY = nBlockEndY;
577 : }
578 : else
579 : {
580 : // cursor position
581 0 : nCurX = aViewData.GetCurX();
582 0 : nCurY = aViewData.GetCurY();
583 : }
584 :
585 0 : ScSplitPos eWhich = aViewData.GetActivePart();
586 0 : ScHSplitPos eWhichX = WhichH( eWhich );
587 0 : ScVSplitPos eWhichY = WhichV( eWhich );
588 :
589 : SCsCOL nPageX;
590 : SCsROW nPageY;
591 0 : if (nMovX >= 0)
592 0 : nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, 1, eWhichX )) * nMovX;
593 : else
594 0 : nPageX = ((SCsCOL) aViewData.CellsAtX( nCurX, -1, eWhichX )) * nMovX;
595 :
596 0 : if (nMovY >= 0)
597 0 : nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, 1, eWhichY )) * nMovY;
598 : else
599 0 : nPageY = ((SCsROW) aViewData.CellsAtY( nCurY, -1, eWhichY )) * nMovY;
600 :
601 0 : if (nMovX != 0 && nPageX == 0) nPageX = (nMovX>0) ? 1 : -1;
602 0 : if (nMovY != 0 && nPageY == 0) nPageY = (nMovY>0) ? 1 : -1;
603 :
604 0 : rPageX = nPageX;
605 0 : rPageY = nPageY;
606 0 : }
607 :
608 0 : void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
609 : SCsCOL& rAreaX, SCsROW& rAreaY, ScFollowMode& rMode)
610 : {
611 0 : SCCOL nNewX = -1;
612 0 : SCROW nNewY = -1;
613 : // current cursor position.
614 0 : SCCOL nCurX = aViewData.GetCurX();
615 0 : SCROW nCurY = aViewData.GetCurY();
616 :
617 0 : if (aViewData.IsRefMode())
618 : {
619 0 : nNewX = aViewData.GetRefEndX();
620 0 : nNewY = aViewData.GetRefEndY();
621 0 : nCurX = aViewData.GetRefStartX();
622 0 : nCurY = aViewData.GetRefStartY();
623 : }
624 0 : else if (IsBlockMode())
625 : {
626 : // block end position.
627 0 : nNewX = nBlockEndX;
628 0 : nNewY = nBlockEndY;
629 : }
630 : else
631 : {
632 0 : nNewX = nCurX;
633 0 : nNewY = nCurY;
634 : }
635 :
636 0 : ScDocument* pDoc = aViewData.GetDocument();
637 0 : SCTAB nTab = aViewData.GetTabNo();
638 :
639 : // FindAreaPos kennt nur -1 oder 1 als Richtung
640 :
641 : SCsCOLROW i;
642 0 : if ( nMovX > 0 )
643 0 : for ( i=0; i<nMovX; i++ )
644 0 : pDoc->FindAreaPos( nNewX, nCurY, nTab, SC_MOVE_RIGHT );
645 0 : if ( nMovX < 0 )
646 0 : for ( i=0; i<-nMovX; i++ )
647 0 : pDoc->FindAreaPos( nNewX, nCurY, nTab, SC_MOVE_LEFT );
648 0 : if ( nMovY > 0 )
649 0 : for ( i=0; i<nMovY; i++ )
650 0 : pDoc->FindAreaPos( nCurX, nNewY, nTab, SC_MOVE_DOWN );
651 0 : if ( nMovY < 0 )
652 0 : for ( i=0; i<-nMovY; i++ )
653 0 : pDoc->FindAreaPos( nCurX, nNewY, nTab, SC_MOVE_UP );
654 :
655 0 : if (eMode==SC_FOLLOW_JUMP) // unten/rechts nicht zuviel grau anzeigen
656 : {
657 0 : if (nMovX != 0 && nNewX == MAXCOL)
658 0 : eMode = SC_FOLLOW_LINE;
659 0 : if (nMovY != 0 && nNewY == MAXROW)
660 0 : eMode = SC_FOLLOW_LINE;
661 : }
662 :
663 0 : if (aViewData.IsRefMode())
664 : {
665 0 : rAreaX = nNewX - aViewData.GetRefEndX();
666 0 : rAreaY = nNewY - aViewData.GetRefEndY();
667 : }
668 0 : else if (IsBlockMode())
669 : {
670 0 : rAreaX = nNewX - nBlockEndX;
671 0 : rAreaY = nNewY - nBlockEndY;
672 : }
673 : else
674 : {
675 0 : rAreaX = nNewX - nCurX;
676 0 : rAreaY = nNewY - nCurY;
677 : }
678 0 : rMode = eMode;
679 0 : }
680 :
681 0 : void ScTabView::SkipCursorHorizontal(SCsCOL& rCurX, SCsROW& rCurY, SCsCOL nOldX, SCsROW nMovX)
682 : {
683 0 : ScDocument* pDoc = aViewData.GetDocument();
684 0 : SCTAB nTab = aViewData.GetTabNo();
685 :
686 0 : bool bSkipProtected = false, bSkipUnprotected = false;
687 0 : ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
688 0 : if (pProtect && pProtect->isProtected())
689 : {
690 0 : bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
691 0 : bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
692 : }
693 :
694 0 : bool bSkipCell = false;
695 0 : bool bHFlip = false;
696 0 : do
697 : {
698 0 : bSkipCell = pDoc->ColHidden(rCurX, nTab) || pDoc->IsHorOverlapped(rCurX, rCurY, nTab);
699 0 : if (bSkipProtected && !bSkipCell)
700 0 : bSkipCell = pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
701 0 : if (bSkipUnprotected && !bSkipCell)
702 0 : bSkipCell = !pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
703 :
704 0 : if (bSkipCell)
705 : {
706 0 : if (rCurX <= 0 || rCurX >= MAXCOL)
707 : {
708 0 : if (bHFlip)
709 : {
710 0 : rCurX = nOldX;
711 0 : bSkipCell = false;
712 : }
713 : else
714 : {
715 0 : nMovX = -nMovX;
716 0 : if (nMovX > 0)
717 0 : ++rCurX;
718 : else
719 0 : --rCurX;
720 0 : bHFlip = true;
721 : }
722 : }
723 : else
724 0 : if (nMovX > 0)
725 0 : ++rCurX;
726 : else
727 0 : --rCurX;
728 : }
729 : }
730 : while (bSkipCell);
731 :
732 0 : if (pDoc->IsVerOverlapped(rCurX, rCurY, nTab))
733 : {
734 0 : aViewData.SetOldCursor(rCurX, rCurY);
735 0 : while (pDoc->IsVerOverlapped(rCurX, rCurY, nTab))
736 0 : --rCurY;
737 : }
738 0 : }
739 :
740 0 : void ScTabView::SkipCursorVertical(SCsCOL& rCurX, SCsROW& rCurY, SCsROW nOldY, SCsROW nMovY)
741 : {
742 0 : ScDocument* pDoc = aViewData.GetDocument();
743 0 : SCTAB nTab = aViewData.GetTabNo();
744 :
745 0 : bool bSkipProtected = false, bSkipUnprotected = false;
746 0 : ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
747 0 : if (pProtect && pProtect->isProtected())
748 : {
749 0 : bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
750 0 : bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
751 : }
752 :
753 0 : bool bSkipCell = false;
754 0 : bool bVFlip = false;
755 0 : do
756 : {
757 0 : SCROW nLastRow = -1;
758 0 : bSkipCell = pDoc->RowHidden(rCurY, nTab, NULL, &nLastRow) || pDoc->IsVerOverlapped( rCurX, rCurY, nTab );
759 0 : if (bSkipProtected && !bSkipCell)
760 0 : bSkipCell = pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
761 0 : if (bSkipUnprotected && !bSkipCell)
762 0 : bSkipCell = !pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
763 :
764 0 : if (bSkipCell)
765 : {
766 0 : if (rCurY <= 0 || rCurY >= MAXROW)
767 : {
768 0 : if (bVFlip)
769 : {
770 0 : rCurY = nOldY;
771 0 : bSkipCell = false;
772 : }
773 : else
774 : {
775 0 : nMovY = -nMovY;
776 0 : if (nMovY > 0)
777 0 : ++rCurY;
778 : else
779 0 : --rCurY;
780 0 : bVFlip = true;
781 : }
782 : }
783 : else
784 0 : if (nMovY > 0)
785 0 : ++rCurY;
786 : else
787 0 : --rCurY;
788 : }
789 : }
790 : while (bSkipCell);
791 :
792 0 : if (pDoc->IsHorOverlapped(rCurX, rCurY, nTab))
793 : {
794 0 : aViewData.SetOldCursor(rCurX, rCurY);
795 0 : while (pDoc->IsHorOverlapped(rCurX, rCurY, nTab))
796 0 : --rCurX;
797 : }
798 0 : }
799 :
800 0 : void ScTabView::ExpandBlock(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode)
801 : {
802 0 : if (!nMovX && !nMovY)
803 : // Nothing to do. Bail out.
804 0 : return;
805 :
806 0 : ScTabViewShell* pViewShell = aViewData.GetViewShell();
807 0 : bool bRefInputMode = pViewShell && pViewShell->IsRefInputMode();
808 0 : if (bRefInputMode && !aViewData.IsRefMode())
809 : // initialize formula reference mode if it hasn't already.
810 0 : InitRefMode(aViewData.GetCurX(), aViewData.GetCurY(), aViewData.GetTabNo(), SC_REFTYPE_REF);
811 :
812 0 : ScDocument* pDoc = aViewData.GetDocument();
813 :
814 0 : if (aViewData.IsRefMode())
815 : {
816 : // formula reference mode
817 :
818 0 : SCCOL nNewX = aViewData.GetRefEndX();
819 0 : SCROW nNewY = aViewData.GetRefEndY();
820 0 : SCTAB nRefTab = aViewData.GetRefEndZ();
821 :
822 0 : bool bSelectLocked = true;
823 0 : bool bSelectUnlocked = true;
824 0 : ScTableProtection* pTabProtection = pDoc->GetTabProtection(nRefTab);
825 0 : if (pTabProtection && pTabProtection->isProtected())
826 : {
827 0 : bSelectLocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS);
828 0 : bSelectUnlocked = pTabProtection->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS);
829 : }
830 :
831 0 : moveCursorByProtRule(nNewX, nNewY, nMovX, nMovY, nRefTab, pDoc);
832 0 : checkBoundary(nNewX, nNewY);
833 :
834 0 : if (nMovX)
835 : {
836 0 : SCCOL nTempX = nNewX;
837 0 : while (pDoc->IsHorOverlapped(nTempX, nNewY, nRefTab))
838 : {
839 0 : if (nMovX > 0)
840 0 : ++nTempX;
841 : else
842 0 : --nTempX;
843 0 : if (!checkBoundary(nTempX, nNewY))
844 0 : break;
845 : }
846 0 : if (isCellQualified(pDoc, nTempX, nNewY, nRefTab, bSelectLocked, bSelectUnlocked))
847 0 : nNewX = nTempX;
848 : }
849 :
850 0 : if (nMovY)
851 : {
852 0 : SCROW nTempY = nNewY;
853 0 : while (pDoc->IsVerOverlapped(nNewX, nTempY, nRefTab))
854 : {
855 0 : if (nMovY > 0)
856 0 : ++nTempY;
857 : else
858 0 : --nTempY;
859 0 : if (!checkBoundary(nNewX, nTempY))
860 0 : break;
861 : }
862 0 : if (isCellQualified(pDoc, nNewX, nTempY, nRefTab, bSelectLocked, bSelectUnlocked))
863 0 : nNewY = nTempY;
864 : }
865 :
866 0 : pDoc->SkipOverlapped(nNewX, nNewY, nRefTab);
867 0 : UpdateRef(nNewX, nNewY, nRefTab);
868 0 : AlignToCursor(nNewX, nNewY, eMode);
869 : }
870 : else
871 : {
872 : // normal selection mode
873 :
874 0 : SCTAB nTab = aViewData.GetTabNo();
875 0 : SCCOL nOrigX = aViewData.GetCurX();
876 0 : SCROW nOrigY = aViewData.GetCurY();
877 :
878 : // Note that the origin position *never* moves during selection.
879 :
880 0 : if (!IsBlockMode())
881 0 : InitBlockMode(nOrigX, nOrigY, nTab, true);
882 :
883 0 : moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc);
884 0 : checkBoundary(nBlockEndX, nBlockEndY);
885 0 : moveCursorByMergedCell(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc, aViewData);
886 0 : checkBoundary(nBlockEndX, nBlockEndY);
887 :
888 0 : MarkCursor(nBlockEndX, nBlockEndY, nTab, false, false, true);
889 :
890 : // Check if the entire row(s) or column(s) are selected.
891 0 : ScSplitPos eActive = aViewData.GetActivePart();
892 0 : bool bRowSelected = (nBlockStartX == 0 && nBlockEndX == MAXCOL);
893 0 : bool bColSelected = (nBlockStartY == 0 && nBlockEndY == MAXROW);
894 0 : SCsCOL nAlignX = bRowSelected ? aViewData.GetPosX(WhichH(eActive)) : nBlockEndX;
895 0 : SCsROW nAlignY = bColSelected ? aViewData.GetPosY(WhichV(eActive)) : nBlockEndY;
896 0 : AlignToCursor(nAlignX, nAlignY, eMode);
897 :
898 0 : SelectionChanged();
899 : }
900 : }
901 :
902 0 : void ScTabView::ExpandBlockPage(SCsCOL nMovX, SCsROW nMovY)
903 : {
904 : SCsCOL nPageX;
905 : SCsROW nPageY;
906 0 : GetPageMoveEndPosition(nMovX, nMovY, nPageX, nPageY);
907 0 : ExpandBlock(nPageX, nPageY, SC_FOLLOW_FIX);
908 0 : }
909 :
910 0 : void ScTabView::ExpandBlockArea(SCsCOL nMovX, SCsROW nMovY)
911 : {
912 : SCsCOL nAreaX;
913 : SCsROW nAreaY;
914 : ScFollowMode eMode;
915 0 : GetAreaMoveEndPosition(nMovX, nMovY, SC_FOLLOW_JUMP, nAreaX, nAreaY, eMode);
916 0 : ExpandBlock(nAreaX, nAreaY, eMode);
917 0 : }
918 :
919 0 : void ScTabView::UpdateCopySourceOverlay()
920 : {
921 0 : for (sal_uInt8 i = 0; i < 4; ++i)
922 0 : if (pGridWin[i] && pGridWin[i]->IsVisible())
923 0 : pGridWin[i]->UpdateCopySourceOverlay();
924 0 : }
925 :
926 0 : void ScTabView::UpdateSelectionOverlay()
927 : {
928 0 : for (sal_uInt16 i=0; i<4; i++)
929 0 : if ( pGridWin[i] && pGridWin[i]->IsVisible() )
930 0 : pGridWin[i]->UpdateSelectionOverlay();
931 0 : }
932 :
933 0 : void ScTabView::UpdateShrinkOverlay()
934 : {
935 0 : for (sal_uInt16 i=0; i<4; i++)
936 0 : if ( pGridWin[i] && pGridWin[i]->IsVisible() )
937 0 : pGridWin[i]->UpdateShrinkOverlay();
938 0 : }
939 :
940 0 : void ScTabView::UpdateAllOverlays()
941 : {
942 0 : for (sal_uInt16 i=0; i<4; i++)
943 0 : if ( pGridWin[i] && pGridWin[i]->IsVisible() )
944 0 : pGridWin[i]->UpdateAllOverlays();
945 0 : }
946 :
947 : //!
948 : //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
949 : //!
950 :
951 0 : void ScTabView::PaintBlock( bool bReset )
952 : {
953 0 : ScMarkData& rMark = aViewData.GetMarkData();
954 0 : SCTAB nTab = aViewData.GetTabNo();
955 0 : bool bMark = rMark.IsMarked();
956 0 : bool bMulti = rMark.IsMultiMarked();
957 0 : if (bMark || bMulti)
958 : {
959 0 : ScRange aMarkRange;
960 0 : HideAllCursors();
961 0 : if (bMulti)
962 : {
963 0 : bool bFlag = rMark.GetMarkingFlag();
964 0 : rMark.SetMarking(false);
965 0 : rMark.MarkToMulti();
966 0 : rMark.GetMultiMarkArea(aMarkRange);
967 0 : rMark.MarkToSimple();
968 0 : rMark.SetMarking(bFlag);
969 :
970 0 : bMark = rMark.IsMarked();
971 : }
972 : else
973 0 : rMark.GetMarkArea(aMarkRange);
974 :
975 0 : nBlockStartX = aMarkRange.aStart.Col();
976 0 : nBlockStartY = aMarkRange.aStart.Row();
977 0 : nBlockStartZ = aMarkRange.aStart.Tab();
978 0 : nBlockEndX = aMarkRange.aEnd.Col();
979 0 : nBlockEndY = aMarkRange.aEnd.Row();
980 0 : nBlockEndZ = aMarkRange.aEnd.Tab();
981 :
982 0 : bool bDidReset = false;
983 :
984 0 : if ( nTab>=nBlockStartZ && nTab<=nBlockEndZ )
985 : {
986 0 : if ( bReset )
987 : {
988 : // Invertieren beim Loeschen nur auf aktiver View
989 0 : if ( aViewData.IsActive() )
990 : {
991 0 : rMark.ResetMark();
992 0 : UpdateSelectionOverlay();
993 0 : bDidReset = true;
994 : }
995 : }
996 : else
997 0 : PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
998 : }
999 :
1000 0 : if ( bReset && !bDidReset )
1001 0 : rMark.ResetMark();
1002 :
1003 0 : ShowAllCursors();
1004 : }
1005 0 : }
1006 :
1007 0 : void ScTabView::SelectAll( bool bContinue )
1008 : {
1009 0 : ScMarkData& rMark = aViewData.GetMarkData();
1010 0 : SCTAB nTab = aViewData.GetTabNo();
1011 :
1012 0 : if (rMark.IsMarked())
1013 : {
1014 0 : ScRange aMarkRange;
1015 0 : rMark.GetMarkArea( aMarkRange );
1016 0 : if ( aMarkRange == ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) )
1017 0 : return;
1018 : }
1019 :
1020 0 : DoneBlockMode( bContinue );
1021 0 : InitBlockMode( 0,0,nTab );
1022 0 : MarkCursor( MAXCOL,MAXROW,nTab );
1023 :
1024 0 : SelectionChanged();
1025 : }
1026 :
1027 0 : void ScTabView::SelectAllTables()
1028 : {
1029 0 : ScDocument* pDoc = aViewData.GetDocument();
1030 0 : ScMarkData& rMark = aViewData.GetMarkData();
1031 0 : SCTAB nCount = pDoc->GetTableCount();
1032 :
1033 0 : if (nCount>1)
1034 : {
1035 0 : for (SCTAB i=0; i<nCount; i++)
1036 0 : rMark.SelectTable( i, true );
1037 :
1038 0 : aViewData.GetDocShell()->PostPaintExtras();
1039 0 : SfxBindings& rBind = aViewData.GetBindings();
1040 0 : rBind.Invalidate( FID_FILL_TAB );
1041 0 : rBind.Invalidate( FID_TAB_DESELECTALL );
1042 : }
1043 0 : }
1044 :
1045 0 : void ScTabView::DeselectAllTables()
1046 : {
1047 0 : ScDocument* pDoc = aViewData.GetDocument();
1048 0 : ScMarkData& rMark = aViewData.GetMarkData();
1049 0 : SCTAB nTab = aViewData.GetTabNo();
1050 0 : SCTAB nCount = pDoc->GetTableCount();
1051 :
1052 0 : for (SCTAB i=0; i<nCount; i++)
1053 0 : rMark.SelectTable( i, ( i == nTab ) );
1054 :
1055 0 : aViewData.GetDocShell()->PostPaintExtras();
1056 0 : SfxBindings& rBind = aViewData.GetBindings();
1057 0 : rBind.Invalidate( FID_FILL_TAB );
1058 0 : rBind.Invalidate( FID_TAB_DESELECTALL );
1059 0 : }
1060 :
1061 0 : static bool lcl_FitsInWindow( double fScaleX, double fScaleY, sal_uInt16 nZoom,
1062 : long nWindowX, long nWindowY, ScDocument* pDoc, SCTAB nTab,
1063 : SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow,
1064 : SCCOL nFixPosX, SCROW nFixPosY )
1065 : {
1066 0 : double fZoomFactor = (double)Fraction(nZoom,100);
1067 0 : fScaleX *= fZoomFactor;
1068 0 : fScaleY *= fZoomFactor;
1069 :
1070 0 : long nBlockX = 0;
1071 : SCCOL nCol;
1072 0 : for (nCol=0; nCol<nFixPosX; nCol++)
1073 : {
1074 : // for frozen panes, add both parts
1075 0 : sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
1076 0 : if (nColTwips)
1077 : {
1078 0 : nBlockX += (long)(nColTwips * fScaleX);
1079 0 : if (nBlockX > nWindowX)
1080 0 : return false;
1081 : }
1082 : }
1083 0 : for (nCol=nStartCol; nCol<=nEndCol; nCol++)
1084 : {
1085 0 : sal_uInt16 nColTwips = pDoc->GetColWidth( nCol, nTab );
1086 0 : if (nColTwips)
1087 : {
1088 0 : nBlockX += (long)(nColTwips * fScaleX);
1089 0 : if (nBlockX > nWindowX)
1090 0 : return false;
1091 : }
1092 : }
1093 :
1094 0 : long nBlockY = 0;
1095 0 : for (SCROW nRow = 0; nRow <= nFixPosY-1; ++nRow)
1096 : {
1097 0 : if (pDoc->RowHidden(nRow, nTab))
1098 0 : continue;
1099 :
1100 : // for frozen panes, add both parts
1101 0 : sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
1102 0 : if (nRowTwips)
1103 : {
1104 0 : nBlockY += (long)(nRowTwips * fScaleY);
1105 0 : if (nBlockY > nWindowY)
1106 0 : return false;
1107 : }
1108 : }
1109 0 : for (SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow)
1110 : {
1111 0 : sal_uInt16 nRowTwips = pDoc->GetRowHeight(nRow, nTab);
1112 0 : if (nRowTwips)
1113 : {
1114 0 : nBlockY += (long)(nRowTwips * fScaleY);
1115 0 : if (nBlockY > nWindowY)
1116 0 : return false;
1117 : }
1118 : }
1119 :
1120 0 : return true;
1121 : }
1122 :
1123 0 : sal_uInt16 ScTabView::CalcZoom( SvxZoomType eType, sal_uInt16 nOldZoom )
1124 : {
1125 0 : sal_uInt16 nZoom = 0; // Ergebnis
1126 :
1127 0 : switch ( eType )
1128 : {
1129 : case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert
1130 0 : nZoom = nOldZoom;
1131 0 : break;
1132 :
1133 : case SVX_ZOOM_OPTIMAL: // nZoom entspricht der optimalen Gr"o\se
1134 : {
1135 0 : ScMarkData& rMark = aViewData.GetMarkData();
1136 0 : ScDocument* pDoc = aViewData.GetDocument();
1137 :
1138 0 : if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1139 0 : nZoom = 100; // nothing selected
1140 : else
1141 : {
1142 0 : SCTAB nTab = aViewData.GetTabNo();
1143 0 : ScRange aMarkRange;
1144 0 : if ( aViewData.GetSimpleArea( aMarkRange ) != SC_MARK_SIMPLE )
1145 0 : rMark.GetMultiMarkArea( aMarkRange );
1146 :
1147 0 : SCCOL nStartCol = aMarkRange.aStart.Col();
1148 0 : SCROW nStartRow = aMarkRange.aStart.Row();
1149 0 : SCTAB nStartTab = aMarkRange.aStart.Tab();
1150 0 : SCCOL nEndCol = aMarkRange.aEnd.Col();
1151 0 : SCROW nEndRow = aMarkRange.aEnd.Row();
1152 0 : SCTAB nEndTab = aMarkRange.aEnd.Tab();
1153 :
1154 0 : if ( nTab < nStartTab && nTab > nEndTab )
1155 0 : nTab = nStartTab;
1156 :
1157 0 : ScSplitPos eUsedPart = aViewData.GetActivePart();
1158 :
1159 0 : SCCOL nFixPosX = 0;
1160 0 : SCROW nFixPosY = 0;
1161 0 : if ( aViewData.GetHSplitMode() == SC_SPLIT_FIX )
1162 : {
1163 : // use right part
1164 0 : eUsedPart = (WhichV(eUsedPart)==SC_SPLIT_TOP) ? SC_SPLIT_TOPRIGHT : SC_SPLIT_BOTTOMRIGHT;
1165 0 : nFixPosX = aViewData.GetFixPosX();
1166 0 : if ( nStartCol < nFixPosX )
1167 0 : nStartCol = nFixPosX;
1168 : }
1169 0 : if ( aViewData.GetVSplitMode() == SC_SPLIT_FIX )
1170 : {
1171 : // use bottom part
1172 0 : eUsedPart = (WhichH(eUsedPart)==SC_SPLIT_LEFT) ? SC_SPLIT_BOTTOMLEFT : SC_SPLIT_BOTTOMRIGHT;
1173 0 : nFixPosY = aViewData.GetFixPosY();
1174 0 : if ( nStartRow < nFixPosY )
1175 0 : nStartRow = nFixPosY;
1176 : }
1177 :
1178 0 : if (pGridWin[eUsedPart])
1179 : {
1180 : // Because scale is rounded to pixels, the only reliable way to find
1181 : // the right scale is to check if a zoom fits
1182 :
1183 0 : Size aWinSize = pGridWin[eUsedPart]->GetOutputSizePixel();
1184 :
1185 : // for frozen panes, use sum of both parts for calculation
1186 :
1187 0 : if ( nFixPosX != 0 )
1188 0 : aWinSize.Width() += GetGridWidth( SC_SPLIT_LEFT );
1189 0 : if ( nFixPosY != 0 )
1190 0 : aWinSize.Height() += GetGridHeight( SC_SPLIT_TOP );
1191 :
1192 0 : ScDocShell* pDocSh = aViewData.GetDocShell();
1193 0 : double nPPTX = ScGlobal::nScreenPPTX / pDocSh->GetOutputFactor();
1194 0 : double nPPTY = ScGlobal::nScreenPPTY;
1195 :
1196 0 : sal_uInt16 nMin = MINZOOM;
1197 0 : sal_uInt16 nMax = MAXZOOM;
1198 0 : while ( nMax > nMin )
1199 : {
1200 0 : sal_uInt16 nTest = (nMin+nMax+1)/2;
1201 0 : if ( lcl_FitsInWindow(
1202 0 : nPPTX, nPPTY, nTest, aWinSize.Width(), aWinSize.Height(),
1203 : pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow,
1204 0 : nFixPosX, nFixPosY ) )
1205 0 : nMin = nTest;
1206 : else
1207 0 : nMax = nTest-1;
1208 : }
1209 : OSL_ENSURE( nMin == nMax, "Schachtelung ist falsch" );
1210 0 : nZoom = nMin;
1211 :
1212 0 : if ( nZoom != nOldZoom )
1213 : {
1214 : // scroll to block only in active split part
1215 : // (the part for which the size was calculated)
1216 :
1217 0 : if ( nStartCol <= nEndCol )
1218 0 : aViewData.SetPosX( WhichH(eUsedPart), nStartCol );
1219 0 : if ( nStartRow <= nEndRow )
1220 0 : aViewData.SetPosY( WhichV(eUsedPart), nStartRow );
1221 : }
1222 : }
1223 : }
1224 : }
1225 0 : break;
1226 :
1227 : case SVX_ZOOM_WHOLEPAGE: // nZoom entspricht der ganzen Seite oder
1228 : case SVX_ZOOM_PAGEWIDTH: // nZoom entspricht der Seitenbreite
1229 : {
1230 0 : SCTAB nCurTab = aViewData.GetTabNo();
1231 0 : ScDocument* pDoc = aViewData.GetDocument();
1232 0 : ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
1233 : SfxStyleSheetBase* pStyleSheet =
1234 : pStylePool->Find( pDoc->GetPageStyle( nCurTab ),
1235 0 : SFX_STYLE_FAMILY_PAGE );
1236 :
1237 : OSL_ENSURE( pStyleSheet, "PageStyle not found :-/" );
1238 :
1239 0 : if ( pStyleSheet )
1240 : {
1241 : ScPrintFunc aPrintFunc( aViewData.GetDocShell(),
1242 0 : aViewData.GetViewShell()->GetPrinter(true),
1243 0 : nCurTab );
1244 :
1245 0 : Size aPageSize = aPrintFunc.GetDataSize();
1246 :
1247 : // use the size of the largest GridWin for normal split,
1248 : // or both combined for frozen panes, with the (document) size
1249 : // of the frozen part added to the page size
1250 : // (with frozen panes, the size of the individual parts
1251 : // depends on the scale that is to be calculated)
1252 :
1253 0 : if ( !pGridWin[SC_SPLIT_BOTTOMLEFT] ) return 0;
1254 0 : Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
1255 0 : ScSplitMode eHMode = aViewData.GetHSplitMode();
1256 0 : if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
1257 : {
1258 0 : long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
1259 0 : GetOutputSizePixel().Width();
1260 0 : if ( eHMode == SC_SPLIT_FIX )
1261 : {
1262 0 : aWinSize.Width() += nOtherWidth;
1263 0 : for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
1264 0 : nCol < aViewData.GetFixPosX(); nCol++ )
1265 0 : aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab );
1266 : }
1267 0 : else if ( nOtherWidth > aWinSize.Width() )
1268 0 : aWinSize.Width() = nOtherWidth;
1269 : }
1270 0 : ScSplitMode eVMode = aViewData.GetVSplitMode();
1271 0 : if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
1272 : {
1273 0 : long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
1274 0 : GetOutputSizePixel().Height();
1275 0 : if ( eVMode == SC_SPLIT_FIX )
1276 : {
1277 0 : aWinSize.Height() += nOtherHeight;
1278 0 : aPageSize.Height() += pDoc->GetRowHeight(
1279 : aViewData.GetPosY(SC_SPLIT_TOP),
1280 0 : aViewData.GetFixPosY()-1, nCurTab);
1281 : }
1282 0 : else if ( nOtherHeight > aWinSize.Height() )
1283 0 : aWinSize.Height() = nOtherHeight;
1284 : }
1285 :
1286 0 : double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
1287 0 : double nPPTY = ScGlobal::nScreenPPTY;
1288 :
1289 0 : long nZoomX = (long) ( aWinSize.Width() * 100 /
1290 0 : ( aPageSize.Width() * nPPTX ) );
1291 0 : long nZoomY = (long) ( aWinSize.Height() * 100 /
1292 0 : ( aPageSize.Height() * nPPTY ) );
1293 0 : long nNew = nZoomX;
1294 :
1295 0 : if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew)
1296 0 : nNew = nZoomY;
1297 :
1298 0 : nZoom = (sal_uInt16) nNew;
1299 : }
1300 : }
1301 0 : break;
1302 :
1303 : default:
1304 : OSL_FAIL("Unknown Zoom-Revision");
1305 0 : nZoom = 0;
1306 : }
1307 :
1308 0 : return nZoom;
1309 : }
1310 :
1311 : // wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
1312 :
1313 0 : void ScTabView::StopMarking()
1314 : {
1315 0 : ScSplitPos eActive = aViewData.GetActivePart();
1316 0 : if (pGridWin[eActive])
1317 0 : pGridWin[eActive]->StopMarking();
1318 :
1319 0 : ScHSplitPos eH = WhichH(eActive);
1320 0 : if (pColBar[eH])
1321 0 : pColBar[eH]->StopMarking();
1322 :
1323 0 : ScVSplitPos eV = WhichV(eActive);
1324 0 : if (pRowBar[eV])
1325 0 : pRowBar[eV]->StopMarking();
1326 0 : }
1327 :
1328 0 : void ScTabView::HideNoteMarker()
1329 : {
1330 0 : for (sal_uInt16 i=0; i<4; i++)
1331 0 : if (pGridWin[i] && pGridWin[i]->IsVisible())
1332 0 : pGridWin[i]->HideNoteMarker();
1333 0 : }
1334 :
1335 0 : void ScTabView::MakeDrawLayer()
1336 : {
1337 0 : if (!pDrawView)
1338 : {
1339 0 : aViewData.GetDocShell()->MakeDrawLayer();
1340 :
1341 : // pDrawView wird per Notify gesetzt
1342 : OSL_ENSURE(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht");
1343 :
1344 : // #114409#
1345 0 : for(sal_uInt16 a(0); a < 4; a++)
1346 : {
1347 0 : if(pGridWin[a])
1348 : {
1349 0 : pGridWin[a]->DrawLayerCreated();
1350 : }
1351 : }
1352 : }
1353 0 : }
1354 :
1355 0 : void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId )
1356 : {
1357 0 : if ( SC_MOD()->IsInExecuteDrop() )
1358 : {
1359 : // #i28468# don't show error message when called from Drag&Drop, silently abort instead
1360 0 : return;
1361 : }
1362 :
1363 0 : StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen
1364 :
1365 0 : Window* pParent = aViewData.GetDialogParent();
1366 0 : ScWaitCursorOff aWaitOff( pParent );
1367 0 : bool bFocus = pParent && pParent->HasFocus();
1368 :
1369 0 : if(nGlobStrId==STR_PROTECTIONERR)
1370 : {
1371 0 : if(aViewData.GetDocShell()->IsReadOnly())
1372 : {
1373 0 : nGlobStrId=STR_READONLYERR;
1374 : }
1375 : }
1376 :
1377 0 : InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
1378 0 : aBox.Execute();
1379 0 : if (bFocus)
1380 0 : pParent->GrabFocus();
1381 : }
1382 :
1383 0 : Window* ScTabView::GetParentOrChild( sal_uInt16 nChildId )
1384 : {
1385 0 : SfxViewFrame* pViewFrm = aViewData.GetViewShell()->GetViewFrame();
1386 :
1387 0 : if ( pViewFrm->HasChildWindow(nChildId) )
1388 : {
1389 0 : SfxChildWindow* pChild = pViewFrm->GetChildWindow(nChildId);
1390 0 : if (pChild)
1391 : {
1392 0 : Window* pWin = pChild->GetWindow();
1393 0 : if (pWin && pWin->IsVisible())
1394 0 : return pWin;
1395 : }
1396 : }
1397 :
1398 0 : return aViewData.GetDialogParent();
1399 : }
1400 :
1401 0 : void ScTabView::UpdatePageBreakData( bool bForcePaint )
1402 : {
1403 0 : ScPageBreakData* pNewData = NULL;
1404 :
1405 0 : if (aViewData.IsPagebreakMode())
1406 : {
1407 0 : ScDocShell* pDocSh = aViewData.GetDocShell();
1408 0 : ScDocument* pDoc = pDocSh->GetDocument();
1409 0 : SCTAB nTab = aViewData.GetTabNo();
1410 :
1411 0 : sal_uInt16 nCount = pDoc->GetPrintRangeCount(nTab);
1412 0 : if (!nCount)
1413 0 : nCount = 1;
1414 0 : pNewData = new ScPageBreakData(nCount);
1415 :
1416 0 : ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData );
1417 : // ScPrintFunc fuellt im ctor die PageBreakData
1418 0 : if ( nCount > 1 )
1419 : {
1420 0 : aPrintFunc.ResetBreaks(nTab);
1421 0 : pNewData->AddPages();
1422 : }
1423 :
1424 : // Druckbereiche veraendert?
1425 0 : if ( bForcePaint || ( pPageBreakData && !pPageBreakData->IsEqual( *pNewData ) ) )
1426 0 : PaintGrid();
1427 : }
1428 :
1429 0 : delete pPageBreakData;
1430 0 : pPageBreakData = pNewData;
1431 15 : }
1432 :
1433 :
1434 :
1435 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|