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