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