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