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