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