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 <limits.h>
21 :
22 : #include "olinetab.hxx"
23 : #include "global.hxx"
24 : #include "rechead.hxx"
25 : #include "address.hxx"
26 : #include "table.hxx"
27 :
28 : //------------------------------------------------------------------------
29 :
30 32 : ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) :
31 : nStart ( nNewStart ),
32 : nSize ( nNewSize ),
33 : bHidden ( bNewHidden ),
34 32 : bVisible( true )
35 : {
36 32 : }
37 :
38 641 : ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) :
39 : nStart ( rEntry.nStart ),
40 : nSize ( rEntry.nSize ),
41 : bHidden ( rEntry.bHidden ),
42 641 : bVisible( rEntry.bVisible )
43 : {
44 641 : }
45 :
46 1307 : SCCOLROW ScOutlineEntry::GetStart() const
47 : {
48 1307 : return nStart;
49 : }
50 :
51 0 : SCSIZE ScOutlineEntry::GetSize() const
52 : {
53 0 : return nSize;
54 : }
55 :
56 540 : SCCOLROW ScOutlineEntry::GetEnd() const
57 : {
58 540 : return nStart+nSize-1;
59 : }
60 35 : bool ScOutlineEntry::IsHidden() const
61 : {
62 35 : return bHidden;
63 : }
64 :
65 20 : bool ScOutlineEntry::IsVisible() const
66 : {
67 20 : return bVisible;
68 : }
69 :
70 0 : void ScOutlineEntry::Move( SCsCOLROW nDelta )
71 : {
72 0 : SCCOLROW nNewPos = nStart + nDelta;
73 0 : if (nNewPos<0)
74 : {
75 : OSL_FAIL("OutlineEntry < 0");
76 0 : nNewPos = 0;
77 : }
78 0 : nStart = nNewPos;
79 0 : }
80 :
81 0 : void ScOutlineEntry::SetSize( SCSIZE nNewSize )
82 : {
83 0 : if (nNewSize>0)
84 0 : nSize = nNewSize;
85 : else
86 : {
87 : OSL_FAIL("ScOutlineEntry Size == 0");
88 : }
89 0 : }
90 :
91 0 : void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize )
92 : {
93 0 : nStart = nNewPos;
94 0 : SetSize( nNewSize );
95 0 : }
96 :
97 59 : void ScOutlineEntry::SetHidden( bool bNewHidden )
98 : {
99 59 : bHidden = bNewHidden;
100 59 : }
101 :
102 100 : void ScOutlineEntry::SetVisible( bool bNewVisible )
103 : {
104 100 : bVisible = bNewVisible;
105 100 : }
106 :
107 : //------------------------------------------------------------------------
108 :
109 9520 : ScOutlineCollection::ScOutlineCollection() {}
110 :
111 375 : size_t ScOutlineCollection::size() const
112 : {
113 375 : return maEntries.size();
114 : }
115 :
116 2 : void ScOutlineCollection::clear()
117 : {
118 2 : maEntries.clear();
119 2 : }
120 :
121 673 : void ScOutlineCollection::insert(ScOutlineEntry* pEntry)
122 : {
123 673 : SCCOLROW nStart = pEntry->GetStart();
124 673 : maEntries.insert(nStart, pEntry);
125 673 : }
126 :
127 428 : ScOutlineCollection::iterator ScOutlineCollection::begin()
128 : {
129 428 : return maEntries.begin();
130 : }
131 :
132 217 : ScOutlineCollection::iterator ScOutlineCollection::end()
133 : {
134 217 : return maEntries.end();
135 : }
136 :
137 748 : ScOutlineCollection::const_iterator ScOutlineCollection::begin() const
138 : {
139 748 : return maEntries.begin();
140 : }
141 :
142 700 : ScOutlineCollection::const_iterator ScOutlineCollection::end() const
143 : {
144 700 : return maEntries.end();
145 : }
146 :
147 32 : void ScOutlineCollection::erase(iterator pos)
148 : {
149 32 : maEntries.erase(pos);
150 32 : }
151 :
152 42 : bool ScOutlineCollection::empty() const
153 : {
154 42 : return maEntries.empty();
155 : }
156 :
157 4 : ScOutlineCollection::iterator ScOutlineCollection::FindStart(SCCOLROW nMinStart)
158 : {
159 4 : return maEntries.lower_bound(nMinStart);
160 : }
161 :
162 : //------------------------------------------------------------------------
163 :
164 320 : ScOutlineArray::ScOutlineArray() :
165 320 : nDepth(0) {}
166 :
167 1040 : ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) :
168 1040 : nDepth( rArray.nDepth )
169 : {
170 1623 : for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
171 : {
172 583 : const ScOutlineCollection& rColl = rArray.aCollections[nLevel];
173 583 : ScOutlineCollection::const_iterator it = rColl.begin(), itEnd = rColl.end();
174 1196 : for (; it != itEnd; ++it)
175 : {
176 613 : const ScOutlineEntry* pEntry = it->second;
177 613 : aCollections[nLevel].insert(new ScOutlineEntry(*pEntry));
178 : }
179 : }
180 1040 : }
181 :
182 67 : void ScOutlineArray::FindEntry(
183 : SCCOLROW nSearchPos, size_t& rFindLevel, size_t& rFindIndex,
184 : size_t nMaxLevel )
185 : {
186 67 : rFindLevel = rFindIndex = 0;
187 :
188 67 : if (nMaxLevel > nDepth)
189 64 : nMaxLevel = nDepth;
190 :
191 159 : for (size_t nLevel = 0; nLevel < nMaxLevel; ++nLevel) //! rueckwaerts suchen ?
192 : {
193 92 : ScOutlineCollection* pCollect = &aCollections[nLevel];
194 92 : ScOutlineCollection::iterator it = pCollect->begin(), itEnd = pCollect->end();
195 186 : for (; it != itEnd; ++it)
196 : {
197 94 : ScOutlineEntry* pEntry = it->second;
198 94 : if (pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos)
199 : {
200 7 : rFindLevel = nLevel + 1; // naechster Level (zum Einfuegen)
201 7 : rFindIndex = std::distance(pCollect->begin(), it);
202 : }
203 : }
204 : }
205 67 : }
206 :
207 32 : bool ScOutlineArray::Insert(
208 : SCCOLROW nStartCol, SCCOLROW nEndCol, bool& rSizeChanged, bool bHidden, bool bVisible )
209 : {
210 32 : rSizeChanged = false;
211 :
212 : size_t nStartLevel, nEndLevel, nStartIndex, nEndIndex;
213 32 : bool bFound = false;
214 :
215 : bool bCont;
216 : sal_uInt16 nFindMax;
217 32 : FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = neuer Level (alter+1) !!!
218 32 : FindEntry( nEndCol, nEndLevel, nEndIndex );
219 32 : nFindMax = std::max(nStartLevel,nEndLevel);
220 35 : do
221 : {
222 35 : bCont = false;
223 :
224 35 : if (nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH)
225 32 : bFound = true;
226 :
227 35 : if (!bFound)
228 : {
229 3 : if (nFindMax>0)
230 : {
231 3 : --nFindMax;
232 3 : if (nStartLevel)
233 : {
234 3 : ScOutlineCollection::const_iterator it = aCollections[nStartLevel-1].begin();
235 3 : std::advance(it, nStartIndex);
236 3 : if (it->second->GetStart() == nStartCol)
237 3 : FindEntry(nStartCol, nStartLevel, nStartIndex, nFindMax);
238 : }
239 :
240 3 : if (nEndLevel)
241 : {
242 0 : ScOutlineCollection::const_iterator it = aCollections[nEndLevel-1].begin();
243 0 : std::advance(it, nEndIndex);
244 0 : if (it->second->GetEnd() == nEndCol)
245 0 : FindEntry(nEndCol, nEndLevel, nEndIndex, nFindMax);
246 : }
247 3 : bCont = true;
248 : }
249 : }
250 : }
251 38 : while ( !bFound && bCont );
252 :
253 32 : if (!bFound)
254 0 : return false;
255 :
256 32 : size_t nLevel = nStartLevel;
257 :
258 : // untere verschieben
259 :
260 32 : bool bNeedSize = false;
261 32 : if (nDepth > 0)
262 : {
263 46 : for (size_t nMoveLevel = nDepth-1; nMoveLevel >= nLevel; --nMoveLevel)
264 : {
265 44 : ScOutlineCollection& rColl = aCollections[nMoveLevel];
266 44 : ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
267 133 : while (it != itEnd)
268 : {
269 45 : ScOutlineEntry* pEntry = it->second;
270 45 : SCCOLROW nEntryStart = pEntry->GetStart();
271 45 : if (nEntryStart >= nStartCol && nEntryStart <= nEndCol)
272 : {
273 28 : if (nMoveLevel >= SC_OL_MAXDEPTH - 1)
274 : {
275 0 : rSizeChanged = false; // kein Platz
276 0 : return false;
277 : }
278 28 : aCollections[nMoveLevel+1].insert(new ScOutlineEntry(*pEntry));
279 28 : size_t nPos = std::distance(rColl.begin(), it);
280 28 : rColl.erase(it);
281 28 : it = rColl.begin();
282 28 : std::advance(it, nPos);
283 28 : itEnd = rColl.end();
284 28 : if (nMoveLevel == nDepth - 1)
285 16 : bNeedSize = true;
286 : }
287 : else
288 17 : ++it;
289 : }
290 44 : if (nMoveLevel == 0)
291 20 : break;
292 : }
293 : }
294 :
295 32 : if (bNeedSize)
296 : {
297 15 : ++nDepth;
298 15 : rSizeChanged = true;
299 : }
300 :
301 32 : if (nDepth <= nLevel)
302 : {
303 12 : nDepth = nLevel+1;
304 12 : rSizeChanged = true;
305 : }
306 :
307 32 : ScOutlineEntry* pNewEntry = new ScOutlineEntry( nStartCol, nEndCol+1-nStartCol, bHidden );
308 32 : pNewEntry->SetVisible( bVisible );
309 32 : aCollections[nLevel].insert(pNewEntry);
310 :
311 32 : return true;
312 : }
313 :
314 2672 : size_t ScOutlineArray::GetDepth() const
315 : {
316 2672 : return nDepth;
317 : }
318 :
319 26 : bool ScOutlineArray::FindTouchedLevel(
320 : SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rFindLevel) const
321 : {
322 26 : bool bFound = false;
323 26 : rFindLevel = 0;
324 :
325 119 : for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
326 : {
327 93 : const ScOutlineCollection* pCollect = &aCollections[nLevel];
328 93 : ScOutlineCollection::const_iterator it = pCollect->begin(), itEnd = pCollect->end();
329 194 : for (; it != itEnd; ++it)
330 : {
331 101 : const ScOutlineEntry* pEntry = it->second;
332 101 : SCCOLROW nStart = pEntry->GetStart();
333 101 : SCCOLROW nEnd = pEntry->GetEnd();
334 :
335 101 : if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) ||
336 37 : ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) )
337 : {
338 26 : rFindLevel = nLevel; // wirklicher Level
339 26 : bFound = true;
340 : }
341 : }
342 : }
343 :
344 26 : return bFound;
345 : }
346 :
347 0 : void ScOutlineArray::RemoveSub(SCCOLROW nStartPos, SCCOLROW nEndPos, size_t nLevel)
348 : {
349 0 : if ( nLevel >= nDepth )
350 0 : return;
351 :
352 0 : ScOutlineCollection& rColl = aCollections[nLevel];
353 :
354 0 : ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
355 0 : while (it != itEnd)
356 : {
357 0 : ScOutlineEntry* pEntry = it->second;
358 0 : SCCOLROW nStart = pEntry->GetStart();
359 0 : SCCOLROW nEnd = pEntry->GetEnd();
360 0 : if (nStart >= nStartPos && nEnd <= nEndPos)
361 : {
362 : // Overlaps.
363 0 : RemoveSub( nStart, nEnd, nLevel+1 );
364 :
365 : // Re-calc iterator positions after the tree gets invalidated.
366 0 : size_t nPos = std::distance(rColl.begin(), it);
367 0 : rColl.erase(it);
368 0 : it = rColl.begin();
369 0 : std::advance(it, nPos);
370 0 : itEnd = rColl.end();
371 : }
372 : else
373 0 : ++it;
374 : }
375 :
376 0 : it = rColl.begin();
377 0 : itEnd = rColl.end();
378 :
379 0 : while (it != itEnd)
380 : {
381 0 : ScOutlineEntry* pEntry = it->second;
382 0 : SCCOLROW nStart = pEntry->GetStart();
383 0 : SCCOLROW nEnd = pEntry->GetEnd();
384 :
385 0 : if (nStart >= nStartPos && nEnd <= nEndPos)
386 : {
387 0 : RemoveSub( nStart, nEnd, nLevel+1 );
388 :
389 : // Re-calc iterator positions after the tree gets invalidated.
390 0 : size_t nPos = std::distance(rColl.begin(), it);
391 0 : rColl.erase(it);
392 0 : it = rColl.begin();
393 0 : std::advance(it, nPos);
394 0 : itEnd = rColl.end();
395 : }
396 : else
397 0 : ++it;
398 : }
399 : }
400 :
401 4 : void ScOutlineArray::PromoteSub(SCCOLROW nStartPos, SCCOLROW nEndPos, size_t nStartLevel)
402 : {
403 4 : if (nStartLevel==0)
404 : {
405 : OSL_FAIL("PromoteSub mit Level 0");
406 4 : return;
407 : }
408 :
409 10 : for (size_t nLevel = nStartLevel; nLevel < nDepth; ++nLevel)
410 : {
411 6 : ScOutlineCollection& rColl = aCollections[nLevel];
412 6 : ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
413 18 : while (it != itEnd)
414 : {
415 6 : ScOutlineEntry* pEntry = it->second;
416 6 : SCCOLROW nStart = pEntry->GetStart();
417 6 : SCCOLROW nEnd = pEntry->GetEnd();
418 6 : if (nStart >= nStartPos && nEnd <= nEndPos)
419 : {
420 0 : aCollections[nLevel-1].insert(new ScOutlineEntry(*pEntry));
421 :
422 : // Re-calc iterator positions after the tree gets invalidated.
423 0 : size_t nPos = std::distance(rColl.begin(), it);
424 0 : rColl.erase(it);
425 0 : it = rColl.begin();
426 0 : std::advance(it, nPos);
427 0 : itEnd = rColl.end();
428 : }
429 : else
430 6 : ++it;
431 : }
432 :
433 6 : it = rColl.begin();
434 6 : itEnd = rColl.end();
435 :
436 18 : while (it != itEnd)
437 : {
438 6 : ScOutlineEntry* pEntry = it->second;
439 6 : SCCOLROW nStart = pEntry->GetStart();
440 6 : SCCOLROW nEnd = pEntry->GetEnd();
441 6 : if (nStart >= nStartPos && nEnd <= nEndPos)
442 : {
443 0 : aCollections[nLevel-1].insert(new ScOutlineEntry(*pEntry));
444 :
445 : // Re-calc iterator positions after the tree gets invalidated.
446 0 : size_t nPos = std::distance(rColl.begin(), it);
447 0 : rColl.erase(it);
448 0 : it = rColl.begin();
449 0 : std::advance(it, nPos);
450 0 : itEnd = rColl.end();
451 : }
452 : else
453 6 : ++it;
454 : }
455 : }
456 : }
457 :
458 4 : bool ScOutlineArray::DecDepth() // nDepth auf leere Levels anpassen
459 : {
460 4 : bool bChanged = false;
461 : bool bCont;
462 6 : do
463 : {
464 6 : bCont = false;
465 6 : if (nDepth)
466 : {
467 5 : if (aCollections[nDepth-1].empty())
468 : {
469 2 : --nDepth;
470 2 : bChanged = true;
471 2 : bCont = true;
472 : }
473 : }
474 : }
475 : while (bCont);
476 :
477 4 : return bChanged;
478 : }
479 :
480 4 : bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, bool& rSizeChanged )
481 : {
482 : size_t nLevel;
483 4 : FindTouchedLevel( nBlockStart, nBlockEnd, nLevel );
484 :
485 4 : ScOutlineCollection* pCollect = &aCollections[nLevel];
486 4 : ScOutlineCollection::iterator it = pCollect->begin(), itEnd = pCollect->end();
487 4 : bool bAny = false;
488 14 : while (it != itEnd)
489 : {
490 6 : ScOutlineEntry* pEntry = it->second;
491 6 : SCCOLROW nStart = pEntry->GetStart();
492 6 : SCCOLROW nEnd = pEntry->GetEnd();
493 6 : if (nBlockStart <= nEnd && nBlockEnd >= nStart)
494 : {
495 : // Overlaps.
496 4 : pCollect->erase(it);
497 4 : PromoteSub( nStart, nEnd, nLevel+1 );
498 4 : itEnd = pCollect->end();
499 4 : it = pCollect->FindStart( nEnd+1 );
500 4 : bAny = true;
501 : }
502 : else
503 2 : ++it;
504 : }
505 :
506 4 : if (bAny) // Depth anpassen
507 4 : if (DecDepth())
508 2 : rSizeChanged = true;
509 :
510 4 : return bAny;
511 : }
512 :
513 72 : ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex)
514 : {
515 72 : if (nLevel >= nDepth)
516 0 : return NULL;
517 :
518 72 : ScOutlineCollection& rColl = aCollections[nLevel];
519 72 : if (nIndex >= rColl.size())
520 0 : return NULL;
521 :
522 72 : ScOutlineCollection::iterator it = rColl.begin();
523 72 : std::advance(it, nIndex);
524 72 : return it->second;
525 : }
526 :
527 38 : const ScOutlineEntry* ScOutlineArray::GetEntry(size_t nLevel, size_t nIndex) const
528 : {
529 38 : if (nLevel >= nDepth)
530 0 : return NULL;
531 :
532 38 : const ScOutlineCollection& rColl = aCollections[nLevel];
533 38 : if (nIndex >= rColl.size())
534 0 : return NULL;
535 :
536 38 : ScOutlineCollection::const_iterator it = rColl.begin();
537 38 : std::advance(it, nIndex);
538 38 : return it->second;
539 : }
540 :
541 49 : size_t ScOutlineArray::GetCount(size_t nLevel) const
542 : {
543 49 : if (nLevel >= nDepth)
544 1 : return 0;
545 :
546 48 : return aCollections[nLevel].size();
547 : }
548 :
549 3 : const ScOutlineEntry* ScOutlineArray::GetEntryByPos(size_t nLevel, SCCOLROW nPos) const
550 : {
551 3 : if (nLevel >= nDepth)
552 0 : return NULL;
553 :
554 3 : const ScOutlineCollection& rColl = aCollections[nLevel];
555 3 : ScOutlineCollection::const_iterator it = rColl.begin(), itEnd = rColl.end();
556 3 : for (; it != itEnd; ++it)
557 : {
558 3 : const ScOutlineEntry* pEntry = it->second;
559 3 : if (pEntry->GetStart() <= nPos && nPos <= pEntry->GetEnd())
560 3 : return pEntry;
561 : }
562 :
563 0 : return NULL;
564 : }
565 :
566 0 : bool ScOutlineArray::GetEntryIndex(size_t nLevel, SCCOLROW nPos, size_t& rnIndex) const
567 : {
568 0 : if (nLevel >= nDepth)
569 0 : return false;
570 :
571 : // found entry contains passed position
572 0 : const ScOutlineCollection& rColl = aCollections[nLevel];
573 0 : ScOutlineCollection::const_iterator it = rColl.begin(), itEnd = rColl.end();
574 0 : for (; it != itEnd; ++it)
575 : {
576 0 : const ScOutlineEntry* p = it->second;
577 0 : if (p->GetStart() <= nPos && nPos <= p->GetEnd())
578 : {
579 0 : rnIndex = std::distance(rColl.begin(), it);
580 0 : return true;
581 : }
582 : }
583 0 : return false;
584 : }
585 :
586 0 : bool ScOutlineArray::GetEntryIndexInRange(
587 : size_t nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, size_t& rnIndex) const
588 : {
589 0 : if (nLevel >= nDepth)
590 0 : return false;
591 :
592 : // found entry will be completely inside of passed range
593 0 : const ScOutlineCollection& rColl = aCollections[nLevel];
594 0 : ScOutlineCollection::const_iterator it = rColl.begin(), itEnd = rColl.end();
595 0 : for (; it != itEnd; ++it)
596 : {
597 0 : const ScOutlineEntry* p = it->second;
598 0 : if (nBlockStart <= p->GetStart() && p->GetEnd() <= nBlockEnd)
599 : {
600 0 : rnIndex = std::distance(rColl.begin(), it);
601 0 : return true;
602 : }
603 : }
604 0 : return false;
605 : }
606 :
607 16 : void ScOutlineArray::SetVisibleBelow(
608 : size_t nLevel, size_t nEntry, bool bValue, bool bSkipHidden)
609 : {
610 16 : const ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry );
611 16 : if (!pEntry)
612 16 : return;
613 :
614 16 : SCCOLROW nStart = pEntry->GetStart();
615 16 : SCCOLROW nEnd = pEntry->GetEnd();
616 :
617 49 : for (size_t nSubLevel = nLevel+1; nSubLevel < nDepth; ++nSubLevel)
618 : {
619 33 : ScOutlineCollection& rColl = aCollections[nSubLevel];
620 33 : ScOutlineCollection::iterator it = rColl.begin(), itEnd = rColl.end();
621 67 : for (; it != itEnd; ++it)
622 : {
623 34 : ScOutlineEntry* p = it->second;
624 34 : if (p->GetStart() >= nStart && p->GetEnd() <= nEnd)
625 : {
626 22 : p->SetVisible(bValue);
627 22 : if (bSkipHidden && !p->IsHidden())
628 : {
629 0 : size_t nPos = std::distance(rColl.begin(), it);
630 0 : SetVisibleBelow(nSubLevel, nPos, bValue, true);
631 : }
632 : }
633 : }
634 :
635 33 : if (bSkipHidden)
636 0 : nSubLevel = nDepth; // Abbruch
637 : }
638 : }
639 :
640 37 : void ScOutlineArray::GetRange(SCCOLROW& rStart, SCCOLROW& rEnd) const
641 : {
642 37 : const ScOutlineCollection& rColl = aCollections[0];
643 37 : if (!rColl.empty())
644 : {
645 10 : ScOutlineCollection::const_iterator it = rColl.begin();
646 10 : rStart = it->second->GetStart();
647 10 : std::advance(it, rColl.size()-1);
648 10 : rEnd = it->second->GetEnd();
649 : }
650 : else
651 27 : rStart = rEnd = 0;
652 37 : }
653 :
654 22 : void ScOutlineArray::ExtendBlock(size_t nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd)
655 : {
656 22 : if (nLevel >= nDepth)
657 23 : return;
658 :
659 21 : const ScOutlineCollection& rColl = aCollections[nLevel];
660 21 : ScOutlineCollection::const_iterator it = rColl.begin(), itEnd = rColl.end();
661 47 : for (; it != itEnd; ++it)
662 : {
663 26 : const ScOutlineEntry* pEntry = it->second;
664 26 : SCCOLROW nStart = pEntry->GetStart();
665 26 : SCCOLROW nEnd = pEntry->GetEnd();
666 :
667 26 : if (rBlkStart <= nEnd && rBlkEnd >= nStart)
668 : {
669 14 : if (nStart < rBlkStart)
670 0 : rBlkStart = nStart;
671 14 : if (nEnd > rBlkEnd)
672 3 : rBlkEnd = nEnd;
673 : }
674 : }
675 : }
676 :
677 0 : bool ScOutlineArray::TestInsertSpace(SCSIZE nSize, SCCOLROW nMaxVal) const
678 : {
679 0 : const ScOutlineCollection& rColl = aCollections[0];
680 0 : if (rColl.empty())
681 0 : return true;
682 :
683 0 : ScOutlineCollection::const_iterator it = rColl.begin();
684 0 : std::advance(it, rColl.size()-1);
685 0 : SCCOLROW nEnd = it->second->GetEnd();
686 0 : return sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal;
687 : }
688 :
689 0 : void ScOutlineArray::InsertSpace(SCCOLROW nStartPos, SCSIZE nSize)
690 : {
691 0 : ScSubOutlineIterator aIter( this );
692 : ScOutlineEntry* pEntry;
693 0 : while ((pEntry = aIter.GetNext()) != NULL)
694 : {
695 0 : if ( pEntry->GetStart() >= nStartPos )
696 0 : pEntry->Move(static_cast<SCsCOLROW>(nSize));
697 : else
698 : {
699 0 : SCCOLROW nEnd = pEntry->GetEnd();
700 : // immer erweitern, wenn innerhalb der Gruppe eingefuegt
701 : // beim Einfuegen am Ende nur, wenn die Gruppe nicht ausgeblendet ist
702 0 : if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) )
703 : {
704 0 : SCSIZE nEntrySize = pEntry->GetSize();
705 0 : nEntrySize += nSize;
706 0 : pEntry->SetSize( nEntrySize );
707 : }
708 : }
709 : }
710 0 : }
711 :
712 3 : bool ScOutlineArray::DeleteSpace(SCCOLROW nStartPos, SCSIZE nSize)
713 : {
714 3 : SCCOLROW nEndPos = nStartPos + nSize - 1;
715 3 : sal_Bool bNeedSave = false; // Original fuer Undo benoetigt?
716 3 : sal_Bool bChanged = false; // fuer Test auf Level
717 :
718 3 : ScSubOutlineIterator aIter( this );
719 : ScOutlineEntry* pEntry;
720 6 : while((pEntry=aIter.GetNext())!=NULL)
721 : {
722 0 : SCCOLROW nEntryStart = pEntry->GetStart();
723 0 : SCCOLROW nEntryEnd = pEntry->GetEnd();
724 0 : SCSIZE nEntrySize = pEntry->GetSize();
725 :
726 0 : if ( nEntryEnd >= nStartPos )
727 : {
728 0 : if ( nEntryStart > nEndPos ) // rechts
729 0 : pEntry->Move(-(static_cast<SCsCOLROW>(nSize)));
730 0 : else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // aussen
731 0 : pEntry->SetSize( nEntrySize-nSize );
732 : else
733 : {
734 0 : bNeedSave = true;
735 0 : if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // innen
736 : {
737 0 : aIter.DeleteLast();
738 0 : bChanged = true;
739 : }
740 0 : else if ( nEntryStart >= nStartPos ) // rechts ueber
741 0 : pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) );
742 : else // links ueber
743 0 : pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) );
744 : }
745 : }
746 : }
747 :
748 3 : if (bChanged)
749 0 : DecDepth();
750 :
751 3 : return bNeedSave;
752 : }
753 :
754 61 : bool ScOutlineArray::ManualAction(
755 : SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, const ScTable& rTable, bool bCol)
756 : {
757 61 : bool bModified = false;
758 61 : ScSubOutlineIterator aIter( this );
759 : ScOutlineEntry* pEntry;
760 134 : while((pEntry=aIter.GetNext())!=NULL)
761 : {
762 12 : SCCOLROW nEntryStart = pEntry->GetStart();
763 12 : SCCOLROW nEntryEnd = pEntry->GetEnd();
764 :
765 12 : if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos)
766 : {
767 0 : if ( pEntry->IsHidden() == bShow )
768 : {
769 : // #i12341# hide if all columns/rows are hidden, show if at least one
770 : // is visible
771 0 : SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol);
772 0 : bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
773 0 : ::std::numeric_limits<SCCOLROW>::max());
774 :
775 0 : bool bToggle = ( bShow != bAllHidden );
776 0 : if ( bToggle )
777 : {
778 0 : pEntry->SetHidden( !bShow );
779 0 : SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow );
780 0 : bModified = true;
781 : }
782 : }
783 : }
784 : }
785 61 : return bModified;
786 : }
787 :
788 1 : void ScOutlineArray::RemoveAll()
789 : {
790 3 : for (size_t nLevel = 0; nLevel < nDepth; ++nLevel)
791 2 : aCollections[nLevel].clear();
792 :
793 1 : nDepth = 0;
794 1 : }
795 :
796 : //------------------------------------------------------------------------
797 :
798 160 : ScOutlineTable::ScOutlineTable()
799 : {
800 160 : }
801 :
802 520 : ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) :
803 : aColOutline( rOutline.aColOutline ),
804 520 : aRowOutline( rOutline.aRowOutline )
805 : {
806 520 : }
807 :
808 0 : sal_Bool ScOutlineTable::TestInsertCol( SCSIZE nSize )
809 : {
810 0 : return aColOutline.TestInsertSpace( nSize, MAXCOL );
811 : }
812 :
813 0 : void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize )
814 : {
815 0 : aColOutline.InsertSpace( nStartCol, nSize );
816 0 : }
817 :
818 0 : sal_Bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize )
819 : {
820 0 : return aColOutline.DeleteSpace( nStartCol, nSize );
821 : }
822 :
823 0 : sal_Bool ScOutlineTable::TestInsertRow( SCSIZE nSize )
824 : {
825 0 : return aRowOutline.TestInsertSpace( nSize, MAXROW );
826 : }
827 :
828 0 : void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize )
829 : {
830 0 : aRowOutline.InsertSpace( nStartRow, nSize );
831 0 : }
832 :
833 3 : sal_Bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize )
834 : {
835 3 : return aRowOutline.DeleteSpace( nStartRow, nSize );
836 : }
837 :
838 : //------------------------------------------------------------------------
839 :
840 93 : ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) :
841 : pArray( pOutlineArray ),
842 : nStart( 0 ),
843 : nEnd( SCCOLROW_MAX ), // alle durchgehen
844 : nSubLevel( 0 ),
845 93 : nSubEntry( 0 )
846 : {
847 93 : nDepth = pArray->nDepth;
848 93 : }
849 :
850 0 : ScSubOutlineIterator::ScSubOutlineIterator(
851 : ScOutlineArray* pOutlineArray, size_t nLevel, size_t nEntry ) :
852 0 : pArray( pOutlineArray )
853 : {
854 0 : const ScOutlineCollection& rColl = pArray->aCollections[nLevel];
855 0 : ScOutlineCollection::const_iterator it = rColl.begin();
856 0 : std::advance(it, nEntry);
857 0 : const ScOutlineEntry* pEntry = it->second;
858 0 : nStart = pEntry->GetStart();
859 0 : nEnd = pEntry->GetEnd();
860 0 : nSubLevel = nLevel + 1;
861 0 : nSubEntry = 0;
862 0 : nDepth = pArray->nDepth;
863 0 : }
864 :
865 198 : ScOutlineEntry* ScSubOutlineIterator::GetNext()
866 : {
867 198 : ScOutlineEntry* pEntry = NULL;
868 198 : bool bFound = false;
869 207 : do
870 : {
871 300 : if (nSubLevel >= nDepth)
872 93 : return NULL;
873 :
874 207 : ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
875 207 : if (nSubEntry < rColl.size())
876 : {
877 105 : ScOutlineCollection::iterator it = rColl.begin();
878 105 : std::advance(it, nSubEntry);
879 105 : pEntry = it->second;
880 :
881 105 : if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd)
882 105 : bFound = true;
883 :
884 105 : ++nSubEntry;
885 : }
886 : else
887 : {
888 : // Go to the next sub-level.
889 102 : nSubEntry = 0;
890 102 : ++nSubLevel;
891 : }
892 : }
893 207 : while (!bFound);
894 105 : return pEntry; // nSubLevel gueltig, wenn pEntry != 0
895 : }
896 :
897 18 : size_t ScSubOutlineIterator::LastLevel() const
898 : {
899 18 : return nSubLevel;
900 : }
901 :
902 0 : size_t ScSubOutlineIterator::LastEntry() const
903 : {
904 0 : if (nSubEntry == 0)
905 : {
906 : OSL_FAIL("ScSubOutlineIterator::LastEntry before GetNext");
907 0 : return 0;
908 : }
909 0 : return nSubEntry-1;
910 : }
911 :
912 0 : void ScSubOutlineIterator::DeleteLast()
913 : {
914 0 : if (nSubLevel >= nDepth)
915 : {
916 : OSL_FAIL("ScSubOutlineIterator::DeleteLast after End");
917 0 : return;
918 : }
919 0 : if (nSubEntry == 0)
920 : {
921 : OSL_FAIL("ScSubOutlineIterator::DeleteLast before GetNext");
922 0 : return;
923 : }
924 :
925 0 : --nSubEntry;
926 0 : ScOutlineCollection& rColl = pArray->aCollections[nSubLevel];
927 : OSL_ASSERT(nSubEntry < rColl.size());
928 0 : ScOutlineCollection::iterator it = rColl.begin();
929 0 : std::advance(it, nSubEntry);
930 0 : rColl.erase(it);
931 93 : }
932 :
933 :
934 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|