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 20 : bool isCellQualified(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, bool bSelectLocked, bool bSelectUnlocked)
52 : {
53 : bool bCellProtected = pDoc->HasAttrib(
54 20 : nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_PROTECTED);
55 :
56 20 : if (bCellProtected && !bSelectLocked)
57 0 : return false;
58 :
59 20 : if (!bCellProtected && !bSelectUnlocked)
60 0 : return false;
61 :
62 20 : return true;
63 : }
64 :
65 4 : void moveCursorByProtRule(
66 : SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, SCTAB nTab, ScDocument* pDoc)
67 : {
68 4 : bool bSelectLocked = true;
69 4 : bool bSelectUnlocked = true;
70 4 : ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
71 4 : 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 4 : if (nMovX > 0)
78 : {
79 12 : for (SCCOL i = 0; i < nMovX && rCol < MAXCOL; ++i)
80 : {
81 10 : SCCOL nNewUnhiddenCol = rCol + 1;
82 10 : SCCOL nEndCol = 0;
83 20 : 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 10 : if (!isCellQualified(pDoc, nNewUnhiddenCol, rRow, nTab, bSelectLocked, bSelectUnlocked))
93 0 : break;
94 10 : rCol = nNewUnhiddenCol;
95 : }
96 : }
97 2 : 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 4 : if (nMovY > 0)
119 : {
120 12 : for (SCROW i = 0; i < nMovY && rRow < MAXROW; ++i)
121 : {
122 10 : SCROW nNewUnhiddenRow = rRow + 1;
123 10 : SCROW nEndRow = 0;
124 20 : 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 10 : if (!isCellQualified(pDoc, rCol, nNewUnhiddenRow, nTab, bSelectLocked, bSelectUnlocked))
134 0 : break;
135 10 : rRow = nNewUnhiddenRow;
136 : }
137 : }
138 2 : 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 8 : bool checkBoundary(SCCOL& rCol, SCROW& rRow)
161 : {
162 8 : bool bGood = true;
163 8 : if (rCol < 0)
164 : {
165 0 : rCol = 0;
166 0 : bGood = false;
167 : }
168 8 : else if (rCol > MAXCOL)
169 : {
170 0 : rCol = MAXCOL;
171 0 : bGood = false;
172 : }
173 :
174 8 : if (rRow < 0)
175 : {
176 0 : rRow = 0;
177 0 : bGood = false;
178 : }
179 8 : else if (rRow > MAXROW)
180 : {
181 0 : rRow = MAXROW;
182 0 : bGood = false;
183 : }
184 8 : return bGood;
185 : }
186 :
187 4 : void moveCursorByMergedCell(
188 : SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, SCTAB nTab,
189 : ScDocument* pDoc, const ScViewData& rViewData)
190 : {
191 4 : SCCOL nOrigX = rViewData.GetCurX();
192 4 : SCROW nOrigY = rViewData.GetCurY();
193 :
194 4 : ScTableProtection* pTabProtection = pDoc->GetTabProtection(nTab);
195 4 : bool bSelectLocked = true;
196 4 : bool bSelectUnlocked = true;
197 4 : 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 4 : pDoc->GetAttr(nOrigX, nOrigY, nTab, ATTR_MERGE));
205 :
206 4 : bool bOriginMerged = false;
207 4 : SCsCOL nColSpan = 1;
208 4 : SCsROW nRowSpan = 1;
209 4 : if (pMergeAttr && pMergeAttr->IsMerged())
210 : {
211 0 : nColSpan = pMergeAttr->GetColMerge();
212 0 : nRowSpan = pMergeAttr->GetRowMerge();
213 0 : bOriginMerged = true;
214 : }
215 :
216 4 : if (nMovX > 0)
217 : {
218 2 : SCCOL nOld = rCol;
219 2 : 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 2 : pDoc->SkipOverlapped(rCol, rRow, nTab);
228 : }
229 :
230 2 : 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 4 : 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 4 : if (nMovY > 0)
261 : {
262 2 : SCROW nOld = rRow;
263 2 : 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 2 : pDoc->SkipOverlapped(rCol, rRow, nTab);
272 : }
273 :
274 2 : 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 4 : 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 4 : }
305 :
306 : }
307 :
308 10 : void ScTabView::PaintMarks(SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow )
309 : {
310 10 : if (!ValidCol(nStartCol)) nStartCol = MAXCOL;
311 10 : if (!ValidRow(nStartRow)) nStartRow = MAXROW;
312 10 : if (!ValidCol(nEndCol)) nEndCol = MAXCOL;
313 10 : if (!ValidRow(nEndRow)) nEndRow = MAXROW;
314 :
315 10 : bool bLeft = (nStartCol==0 && nEndCol==MAXCOL);
316 10 : bool bTop = (nStartRow==0 && nEndRow==MAXROW);
317 :
318 10 : if (bLeft)
319 0 : PaintLeftArea( nStartRow, nEndRow );
320 10 : if (bTop)
321 2 : PaintTopArea( nStartCol, nEndCol );
322 :
323 : aViewData.GetDocument()->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow,
324 10 : aViewData.GetTabNo() );
325 10 : PaintArea( nStartCol, nStartRow, nEndCol, nEndRow, SC_UPDATE_MARKS );
326 10 : }
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 62 : void ScTabView::InitOwnBlockMode()
337 : {
338 62 : if (!IsBlockMode())
339 : {
340 : // Wenn keine (alte) Markierung mehr da ist, Anker in SelectionEngine loeschen:
341 :
342 62 : ScMarkData& rMark = aViewData.GetMarkData();
343 62 : if (!rMark.IsMarked() && !rMark.IsMultiMarked())
344 62 : GetSelEngine()->CursorPosChanging( false, false );
345 :
346 62 : meBlockMode = Own;
347 62 : nBlockStartX = 0;
348 62 : nBlockStartY = 0;
349 62 : nBlockStartZ = 0;
350 62 : nBlockEndX = 0;
351 62 : nBlockEndY = 0;
352 62 : nBlockEndZ = 0;
353 :
354 62 : SelectionChanged(); // Status wird mit gesetzer Markierung abgefragt
355 : }
356 62 : }
357 :
358 134 : void ScTabView::InitBlockMode( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
359 : bool bTestNeg, bool bCols, bool bRows, bool bForceNeg )
360 : {
361 134 : if (!IsBlockMode())
362 : {
363 134 : if (!ValidCol(nCurX)) nCurX = MAXCOL;
364 134 : if (!ValidRow(nCurY)) nCurY = MAXROW;
365 :
366 134 : ScMarkData& rMark = aViewData.GetMarkData();
367 134 : SCTAB nTab = aViewData.GetTabNo();
368 :
369 : // Teil von Markierung aufheben?
370 134 : if (bForceNeg)
371 0 : bBlockNeg = true;
372 134 : else if (bTestNeg)
373 : {
374 2 : if ( bCols )
375 0 : bBlockNeg = rMark.IsColumnMarked( nCurX );
376 2 : else if ( bRows )
377 0 : bBlockNeg = rMark.IsRowMarked( nCurY );
378 : else
379 2 : bBlockNeg = rMark.IsCellMarked( nCurX, nCurY );
380 : }
381 : else
382 132 : bBlockNeg = false;
383 134 : rMark.SetMarkNegative(bBlockNeg);
384 :
385 134 : meBlockMode = Normal;
386 134 : bBlockCols = bCols;
387 134 : bBlockRows = bRows;
388 134 : nBlockStartX = nBlockStartXOrig = nCurX;
389 134 : nBlockStartY = nBlockStartYOrig = nCurY;
390 134 : nBlockStartZ = nCurZ;
391 134 : nBlockEndX = nOldCurX = nBlockStartX;
392 134 : nBlockEndY = nOldCurY = nBlockStartY;
393 134 : nBlockEndZ = nBlockStartZ;
394 :
395 134 : if (bBlockCols)
396 : {
397 0 : nBlockStartY = nBlockStartYOrig = 0;
398 0 : nBlockEndY = MAXROW;
399 : }
400 :
401 134 : if (bBlockRows)
402 : {
403 0 : nBlockStartX = nBlockStartXOrig = 0;
404 0 : nBlockEndX = MAXCOL;
405 : }
406 :
407 134 : rMark.SetMarkArea( ScRange( nBlockStartX,nBlockStartY, nTab, nBlockEndX,nBlockEndY, nTab ) );
408 :
409 134 : UpdateSelectionOverlay();
410 : }
411 134 : }
412 :
413 1036 : 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 1036 : if (IsBlockMode() && !bMoveIsShift)
420 : {
421 184 : ScMarkData& rMark = aViewData.GetMarkData();
422 184 : bool bFlag = rMark.GetMarkingFlag();
423 184 : rMark.SetMarking(false);
424 :
425 184 : if (bBlockNeg && !bContinue)
426 0 : rMark.MarkToMulti();
427 :
428 184 : 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 184 : SCTAB nTab = aViewData.GetTabNo();
437 184 : ScDocument* pDoc = aViewData.GetDocument();
438 184 : if ( pDoc->HasTable(nTab) )
439 184 : PaintBlock( true ); // true -> Block loeschen
440 : else
441 0 : rMark.ResetMark();
442 : }
443 184 : meBlockMode = None;
444 :
445 184 : rMark.SetMarking(bFlag);
446 184 : rMark.SetMarkNegative(false);
447 : }
448 1036 : }
449 :
450 1416 : bool ScTabView::IsBlockMode() const
451 : {
452 1416 : return meBlockMode != None;
453 : }
454 :
455 136 : void ScTabView::MarkCursor( SCCOL nCurX, SCROW nCurY, SCTAB nCurZ,
456 : bool bCols, bool bRows, bool bCellSelection )
457 : {
458 136 : if (!ValidCol(nCurX)) nCurX = MAXCOL;
459 136 : if (!ValidRow(nCurY)) nCurY = MAXROW;
460 :
461 136 : if (!IsBlockMode())
462 : {
463 : OSL_FAIL( "MarkCursor nicht im BlockMode" );
464 0 : InitBlockMode( nCurX, nCurY, nCurZ, false, bCols, bRows );
465 : }
466 :
467 136 : if (bCols)
468 0 : nCurY = MAXROW;
469 136 : if (bRows)
470 0 : nCurX = MAXCOL;
471 :
472 136 : ScMarkData& rMark = aViewData.GetMarkData();
473 : OSL_ENSURE(rMark.IsMarked() || rMark.IsMultiMarked(), "MarkCursor, !IsMarked()");
474 136 : ScRange aMarkRange;
475 136 : rMark.GetMarkArea(aMarkRange);
476 408 : if (( aMarkRange.aStart.Col() != nBlockStartX && aMarkRange.aEnd.Col() != nBlockStartX ) ||
477 408 : ( aMarkRange.aStart.Row() != nBlockStartY && aMarkRange.aEnd.Row() != nBlockStartY ) ||
478 136 : ( 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 136 : if ( nCurX != nOldCurX || nCurY != nOldCurY )
494 : {
495 : // Current cursor has moved
496 :
497 44 : SCTAB nTab = nCurZ;
498 :
499 44 : if ( bCellSelection )
500 : {
501 : // Expand selection area accordingly when the current selection ends
502 : // with a merged cell.
503 4 : SCsCOL nCurXOffset = 0;
504 4 : SCsCOL nBlockStartXOffset = 0;
505 4 : SCsROW nCurYOffset = 0;
506 4 : SCsROW nBlockStartYOffset = 0;
507 4 : bool bBlockStartMerged = false;
508 4 : const ScMergeAttr* pMergeAttr = NULL;
509 4 : 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 4 : pDocument->GetAttr( nBlockStartXOrig, nBlockStartYOrig, nTab, ATTR_MERGE ) );
520 4 : 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 4 : pDocument->GetAttr( nCurX, nCurY, nTab, ATTR_MERGE ) );
546 4 : 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 4 : if ( !bBlockStartMerged )
576 : {
577 4 : nBlockStartX = nBlockStartXOrig;
578 4 : nBlockStartY = nBlockStartYOrig;
579 : }
580 : }
581 :
582 4 : nBlockStartX = nBlockStartX + nBlockStartXOffset >= 0 ? nBlockStartX + nBlockStartXOffset : 0;
583 4 : nBlockStartY = nBlockStartY + nBlockStartYOffset >= 0 ? nBlockStartY + nBlockStartYOffset : 0;
584 4 : nBlockEndX = nCurX + nCurXOffset > MAXCOL ? MAXCOL : nCurX + nCurXOffset;
585 4 : nBlockEndY = nCurY + nCurYOffset > MAXROW ? MAXROW : nCurY + nCurYOffset;
586 : }
587 : else
588 : {
589 40 : nBlockEndX = nCurX;
590 40 : nBlockEndY = nCurY;
591 : }
592 :
593 : // Set new selection area
594 44 : rMark.SetMarkArea( ScRange( nBlockStartX, nBlockStartY, nTab, nBlockEndX, nBlockEndY, nTab ) );
595 :
596 44 : UpdateSelectionOverlay();
597 44 : SelectionChanged();
598 :
599 44 : nOldCurX = nCurX;
600 44 : nOldCurY = nCurY;
601 :
602 44 : aViewData.GetViewShell()->UpdateInputHandler();
603 : }
604 :
605 136 : if ( !bCols && !bRows )
606 136 : aHdrFunc.SetAnchorFlag( false );
607 136 : }
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 22 : void ScTabView::GetAreaMoveEndPosition(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode,
655 : SCsCOL& rAreaX, SCsROW& rAreaY, ScFollowMode& rMode)
656 : {
657 22 : SCCOL nNewX = -1;
658 22 : SCROW nNewY = -1;
659 :
660 : // current cursor position.
661 22 : SCCOL nCurX = aViewData.GetCurX();
662 22 : SCROW nCurY = aViewData.GetCurY();
663 :
664 22 : 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 22 : else if (IsBlockMode())
672 : {
673 : // block end position.
674 22 : nNewX = nBlockEndX;
675 22 : nNewY = nBlockEndY;
676 : }
677 : else
678 : {
679 0 : nNewX = nCurX;
680 0 : nNewY = nCurY;
681 : }
682 :
683 22 : ScDocument* pDoc = aViewData.GetDocument();
684 22 : SCTAB nTab = aViewData.GetTabNo();
685 :
686 : // FindAreaPos kennt nur -1 oder 1 als Richtung
687 22 : ScModule* pScModule = SC_MOD();
688 22 : bool bLegacyCellSelection = pScModule->GetInputOptions().GetLegacyCellSelection();
689 22 : SCCOL nVirtualX = bLegacyCellSelection ? nNewX : nCurX;
690 22 : SCROW nVirtualY = bLegacyCellSelection ? nNewY : nCurY;
691 :
692 : SCsCOLROW i;
693 22 : if ( nMovX > 0 )
694 12 : for ( i=0; i<nMovX; i++ )
695 6 : pDoc->FindAreaPos( nNewX, nVirtualY, nTab, SC_MOVE_RIGHT );
696 22 : if ( nMovX < 0 )
697 12 : for ( i=0; i<-nMovX; i++ )
698 6 : pDoc->FindAreaPos( nNewX, nVirtualY, nTab, SC_MOVE_LEFT );
699 22 : if ( nMovY > 0 )
700 8 : for ( i=0; i<nMovY; i++ )
701 4 : pDoc->FindAreaPos( nVirtualX, nNewY, nTab, SC_MOVE_DOWN );
702 22 : if ( nMovY < 0 )
703 12 : for ( i=0; i<-nMovY; i++ )
704 6 : pDoc->FindAreaPos( nVirtualX, nNewY, nTab, SC_MOVE_UP );
705 :
706 22 : if (eMode==SC_FOLLOW_JUMP) // unten/rechts nicht zuviel grau anzeigen
707 : {
708 22 : if (nMovX != 0 && nNewX == MAXCOL)
709 2 : eMode = SC_FOLLOW_LINE;
710 22 : if (nMovY != 0 && nNewY == MAXROW)
711 0 : eMode = SC_FOLLOW_LINE;
712 : }
713 :
714 22 : if (aViewData.IsRefMode())
715 : {
716 0 : rAreaX = nNewX - aViewData.GetRefEndX();
717 0 : rAreaY = nNewY - aViewData.GetRefEndY();
718 : }
719 22 : else if (IsBlockMode())
720 : {
721 22 : rAreaX = nNewX - nBlockEndX;
722 22 : rAreaY = nNewY - nBlockEndY;
723 : }
724 : else
725 : {
726 0 : rAreaX = nNewX - nCurX;
727 0 : rAreaY = nNewY - nCurY;
728 : }
729 22 : rMode = eMode;
730 22 : }
731 :
732 12 : void ScTabView::SkipCursorHorizontal(SCsCOL& rCurX, SCsROW& rCurY, SCsCOL nOldX, SCsROW nMovX)
733 : {
734 12 : ScDocument* pDoc = aViewData.GetDocument();
735 12 : SCTAB nTab = aViewData.GetTabNo();
736 :
737 12 : bool bSkipProtected = false, bSkipUnprotected = false;
738 12 : ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
739 12 : 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 12 : bool bSkipCell = false;
746 12 : bool bHFlip = false;
747 12 : do
748 : {
749 12 : bSkipCell = pDoc->ColHidden(rCurX, nTab) || pDoc->IsHorOverlapped(rCurX, rCurY, nTab);
750 12 : if (bSkipProtected && !bSkipCell)
751 0 : bSkipCell = pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
752 12 : if (bSkipUnprotected && !bSkipCell)
753 0 : bSkipCell = !pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
754 :
755 12 : 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 12 : 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 12 : }
790 :
791 10 : void ScTabView::SkipCursorVertical(SCsCOL& rCurX, SCsROW& rCurY, SCsROW nOldY, SCsROW nMovY)
792 : {
793 10 : ScDocument* pDoc = aViewData.GetDocument();
794 10 : SCTAB nTab = aViewData.GetTabNo();
795 :
796 10 : bool bSkipProtected = false, bSkipUnprotected = false;
797 10 : ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
798 10 : 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 10 : bool bSkipCell = false;
805 10 : bool bVFlip = false;
806 10 : do
807 : {
808 10 : SCROW nLastRow = -1;
809 10 : bSkipCell = pDoc->RowHidden(rCurY, nTab, NULL, &nLastRow) || pDoc->IsVerOverlapped( rCurX, rCurY, nTab );
810 10 : if (bSkipProtected && !bSkipCell)
811 0 : bSkipCell = pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
812 10 : if (bSkipUnprotected && !bSkipCell)
813 0 : bSkipCell = !pDoc->HasAttrib(rCurX, rCurY, nTab, rCurX, rCurY, nTab, HASATTR_PROTECTED);
814 :
815 10 : 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 10 : 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 10 : }
850 :
851 4 : void ScTabView::ExpandBlock(SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode)
852 : {
853 4 : if (!nMovX && !nMovY)
854 : // Nothing to do. Bail out.
855 4 : return;
856 :
857 4 : ScTabViewShell* pViewShell = aViewData.GetViewShell();
858 4 : bool bRefInputMode = pViewShell && pViewShell->IsRefInputMode();
859 4 : 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 4 : ScDocument* pDoc = aViewData.GetDocument();
864 :
865 4 : 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 4 : SCTAB nTab = aViewData.GetTabNo();
926 4 : SCCOL nOrigX = aViewData.GetCurX();
927 4 : SCROW nOrigY = aViewData.GetCurY();
928 :
929 : // Note that the origin position *never* moves during selection.
930 :
931 4 : if (!IsBlockMode())
932 2 : InitBlockMode(nOrigX, nOrigY, nTab, true);
933 :
934 4 : moveCursorByProtRule(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc);
935 4 : checkBoundary(nBlockEndX, nBlockEndY);
936 4 : moveCursorByMergedCell(nBlockEndX, nBlockEndY, nMovX, nMovY, nTab, pDoc, aViewData);
937 4 : checkBoundary(nBlockEndX, nBlockEndY);
938 :
939 4 : MarkCursor(nBlockEndX, nBlockEndY, nTab, false, false, true);
940 :
941 : // Check if the entire row(s) or column(s) are selected.
942 4 : ScSplitPos eActive = aViewData.GetActivePart();
943 4 : bool bRowSelected = (nBlockStartX == 0 && nBlockEndX == MAXCOL);
944 4 : bool bColSelected = (nBlockStartY == 0 && nBlockEndY == MAXROW);
945 4 : SCsCOL nAlignX = bRowSelected ? aViewData.GetPosX(WhichH(eActive)) : nBlockEndX;
946 4 : SCsROW nAlignY = bColSelected ? aViewData.GetPosY(WhichV(eActive)) : nBlockEndY;
947 4 : AlignToCursor(nAlignX, nAlignY, eMode);
948 :
949 4 : 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 376 : void ScTabView::UpdateSelectionOverlay()
978 : {
979 1880 : for (sal_uInt16 i=0; i<4; i++)
980 1504 : if ( pGridWin[i] && pGridWin[i]->IsVisible() )
981 376 : pGridWin[i]->UpdateSelectionOverlay();
982 376 : }
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 3234 : void ScTabView::UpdateAllOverlays()
992 : {
993 16170 : for (sal_uInt16 i=0; i<4; i++)
994 12936 : if ( pGridWin[i] && pGridWin[i]->IsVisible() )
995 2764 : pGridWin[i]->UpdateAllOverlays();
996 3234 : }
997 :
998 : //!
999 : //! PaintBlock in zwei Methoden aufteilen: RepaintBlock und RemoveBlock o.ae.
1000 : //!
1001 :
1002 1268 : void ScTabView::PaintBlock( bool bReset )
1003 : {
1004 1268 : ScMarkData& rMark = aViewData.GetMarkData();
1005 1268 : SCTAB nTab = aViewData.GetTabNo();
1006 1268 : bool bMulti = rMark.IsMultiMarked();
1007 1268 : if (rMark.IsMarked() || bMulti)
1008 : {
1009 146 : ScRange aMarkRange;
1010 146 : HideAllCursors();
1011 146 : if (bMulti)
1012 : {
1013 6 : bool bFlag = rMark.GetMarkingFlag();
1014 6 : rMark.SetMarking(false);
1015 6 : rMark.MarkToMulti();
1016 6 : rMark.GetMultiMarkArea(aMarkRange);
1017 6 : rMark.MarkToSimple();
1018 6 : rMark.SetMarking(bFlag);
1019 : }
1020 : else
1021 140 : 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 136 : if ( aViewData.IsActive() )
1038 : {
1039 136 : rMark.ResetMark();
1040 136 : UpdateSelectionOverlay();
1041 136 : bDidReset = true;
1042 : }
1043 : }
1044 : else
1045 10 : PaintMarks( nBlockStartX, nBlockStartY, nBlockEndX, nBlockEndY );
1046 : }
1047 :
1048 146 : if ( bReset && !bDidReset )
1049 0 : rMark.ResetMark();
1050 :
1051 146 : ShowAllCursors();
1052 : }
1053 1268 : }
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 = 0; // Ergebnis
1174 :
1175 0 : switch ( eType )
1176 : {
1177 : case SVX_ZOOM_PERCENT: // rZoom ist kein besonderer prozentualer Wert
1178 0 : nZoom = nOldZoom;
1179 0 : break;
1180 :
1181 : case SVX_ZOOM_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 SVX_ZOOM_WHOLEPAGE: // nZoom entspricht der ganzen Seite oder
1276 : case SVX_ZOOM_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] ) return 0;
1302 0 : Size aWinSize = pGridWin[SC_SPLIT_BOTTOMLEFT]->GetOutputSizePixel();
1303 0 : ScSplitMode eHMode = aViewData.GetHSplitMode();
1304 0 : if ( eHMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_BOTTOMRIGHT] )
1305 : {
1306 0 : long nOtherWidth = pGridWin[SC_SPLIT_BOTTOMRIGHT]->
1307 0 : GetOutputSizePixel().Width();
1308 0 : if ( eHMode == SC_SPLIT_FIX )
1309 : {
1310 0 : aWinSize.Width() += nOtherWidth;
1311 0 : for ( SCCOL nCol = aViewData.GetPosX(SC_SPLIT_LEFT);
1312 0 : nCol < aViewData.GetFixPosX(); nCol++ )
1313 0 : aPageSize.Width() += pDoc->GetColWidth( nCol, nCurTab );
1314 : }
1315 0 : else if ( nOtherWidth > aWinSize.Width() )
1316 0 : aWinSize.Width() = nOtherWidth;
1317 : }
1318 0 : ScSplitMode eVMode = aViewData.GetVSplitMode();
1319 0 : if ( eVMode != SC_SPLIT_NONE && pGridWin[SC_SPLIT_TOPLEFT] )
1320 : {
1321 0 : long nOtherHeight = pGridWin[SC_SPLIT_TOPLEFT]->
1322 0 : GetOutputSizePixel().Height();
1323 0 : if ( eVMode == SC_SPLIT_FIX )
1324 : {
1325 0 : aWinSize.Height() += nOtherHeight;
1326 0 : aPageSize.Height() += pDoc->GetRowHeight(
1327 : aViewData.GetPosY(SC_SPLIT_TOP),
1328 0 : aViewData.GetFixPosY()-1, nCurTab);
1329 : }
1330 0 : else if ( nOtherHeight > aWinSize.Height() )
1331 0 : aWinSize.Height() = nOtherHeight;
1332 : }
1333 :
1334 0 : double nPPTX = ScGlobal::nScreenPPTX / aViewData.GetDocShell()->GetOutputFactor();
1335 0 : double nPPTY = ScGlobal::nScreenPPTY;
1336 :
1337 0 : long nZoomX = (long) ( aWinSize.Width() * 100 /
1338 0 : ( aPageSize.Width() * nPPTX ) );
1339 0 : long nZoomY = (long) ( aWinSize.Height() * 100 /
1340 0 : ( aPageSize.Height() * nPPTY ) );
1341 0 : long nNew = nZoomX;
1342 :
1343 0 : if (eType == SVX_ZOOM_WHOLEPAGE && nZoomY < nNew)
1344 0 : nNew = nZoomY;
1345 :
1346 0 : nZoom = (sal_uInt16) nNew;
1347 : }
1348 : }
1349 0 : break;
1350 :
1351 : default:
1352 : OSL_FAIL("Unknown Zoom-Revision");
1353 0 : nZoom = 0;
1354 : }
1355 :
1356 0 : return nZoom;
1357 : }
1358 :
1359 : // wird z.B. gerufen, wenn sich das View-Fenster verschiebt:
1360 :
1361 1104 : void ScTabView::StopMarking()
1362 : {
1363 1104 : ScSplitPos eActive = aViewData.GetActivePart();
1364 1104 : if (pGridWin[eActive])
1365 1104 : pGridWin[eActive]->StopMarking();
1366 :
1367 1104 : ScHSplitPos eH = WhichH(eActive);
1368 1104 : if (pColBar[eH])
1369 1104 : pColBar[eH]->StopMarking();
1370 :
1371 1104 : ScVSplitPos eV = WhichV(eActive);
1372 1104 : if (pRowBar[eV])
1373 1104 : pRowBar[eV]->StopMarking();
1374 1104 : }
1375 :
1376 21514 : void ScTabView::HideNoteMarker()
1377 : {
1378 107570 : for (sal_uInt16 i=0; i<4; i++)
1379 86056 : if (pGridWin[i] && pGridWin[i]->IsVisible())
1380 20968 : pGridWin[i]->HideNoteMarker();
1381 21514 : }
1382 :
1383 546 : void ScTabView::MakeDrawLayer()
1384 : {
1385 546 : if (!pDrawView)
1386 : {
1387 398 : aViewData.GetDocShell()->MakeDrawLayer();
1388 :
1389 : // pDrawView wird per Notify gesetzt
1390 : OSL_ENSURE(pDrawView,"ScTabView::MakeDrawLayer funktioniert nicht");
1391 :
1392 : // #114409#
1393 1990 : for(sal_uInt16 a(0); a < 4; a++)
1394 : {
1395 1592 : if(pGridWin[a])
1396 : {
1397 398 : pGridWin[a]->DrawLayerCreated();
1398 : }
1399 : }
1400 : }
1401 546 : }
1402 :
1403 0 : void ScTabView::ErrorMessage( sal_uInt16 nGlobStrId )
1404 : {
1405 0 : if ( SC_MOD()->IsInExecuteDrop() )
1406 : {
1407 : // #i28468# don't show error message when called from Drag&Drop, silently abort instead
1408 0 : return;
1409 : }
1410 :
1411 0 : StopMarking(); // falls per Focus aus MouseButtonDown aufgerufen
1412 :
1413 0 : vcl::Window* pParent = aViewData.GetDialogParent();
1414 0 : ScWaitCursorOff aWaitOff( pParent );
1415 0 : bool bFocus = pParent && pParent->HasFocus();
1416 :
1417 0 : if(nGlobStrId==STR_PROTECTIONERR)
1418 : {
1419 0 : if(aViewData.GetDocShell()->IsReadOnly())
1420 : {
1421 0 : nGlobStrId=STR_READONLYERR;
1422 : }
1423 : }
1424 :
1425 0 : InfoBox aBox( pParent, ScGlobal::GetRscString( nGlobStrId ) );
1426 0 : aBox.Execute();
1427 0 : if (bFocus)
1428 0 : pParent->GrabFocus();
1429 : }
1430 :
1431 4 : void ScTabView::UpdatePageBreakData( bool bForcePaint )
1432 : {
1433 4 : ScPageBreakData* pNewData = NULL;
1434 :
1435 4 : if (aViewData.IsPagebreakMode())
1436 : {
1437 2 : ScDocShell* pDocSh = aViewData.GetDocShell();
1438 2 : ScDocument& rDoc = pDocSh->GetDocument();
1439 2 : SCTAB nTab = aViewData.GetTabNo();
1440 :
1441 2 : sal_uInt16 nCount = rDoc.GetPrintRangeCount(nTab);
1442 2 : if (!nCount)
1443 0 : nCount = 1;
1444 2 : pNewData = new ScPageBreakData(nCount);
1445 :
1446 2 : ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab, 0,0,NULL, NULL, pNewData );
1447 : // ScPrintFunc fuellt im ctor die PageBreakData
1448 2 : if ( nCount > 1 )
1449 : {
1450 0 : aPrintFunc.ResetBreaks(nTab);
1451 0 : pNewData->AddPages();
1452 : }
1453 :
1454 : // Druckbereiche veraendert?
1455 2 : if ( bForcePaint || ( pPageBreakData && !( *pPageBreakData == *pNewData ) ) )
1456 0 : PaintGrid();
1457 : }
1458 :
1459 4 : delete pPageBreakData;
1460 4 : pPageBreakData = pNewData;
1461 232 : }
1462 :
1463 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|