Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / data / markarr.cxx
blobc457d4ac26a765548c7e853915d8f5373c4416ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "markarr.hxx"
21 #include "global.hxx"
22 #include "address.hxx"
24 // STATIC DATA -----------------------------------------------------------
26 //------------------------------------------------------------------------
28 ScMarkArray::ScMarkArray() :
29 nCount( 0 ),
30 nLimit( 0 ),
31 pData( NULL )
33 // special case "no marks" with pData = NULL
36 //------------------------------------------------------------------------
38 ScMarkArray::~ScMarkArray()
40 delete[] pData;
43 //------------------------------------------------------------------------
45 void ScMarkArray::Reset( sal_Bool bMarked )
47 // always create pData here
48 // (or have separate method to ensure pData)
50 delete[] pData;
52 nCount = nLimit = 1;
53 pData = new ScMarkEntry[1];
54 pData[0].nRow = MAXROW;
55 pData[0].bMarked = bMarked;
58 //------------------------------------------------------------------------
60 sal_Bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
62 long nHi = static_cast<long>(nCount) - 1;
63 long i = 0;
64 sal_Bool bFound = (nCount == 1);
65 if (pData)
67 long nLo = 0;
68 long nStartRow = 0;
69 while ( !bFound && nLo <= nHi )
71 i = (nLo + nHi) / 2;
72 if (i > 0)
73 nStartRow = (long) pData[i - 1].nRow;
74 else
75 nStartRow = -1;
76 long nEndRow = (long) pData[i].nRow;
77 if (nEndRow < (long) nRow)
78 nLo = ++i;
79 else
80 if (nStartRow >= (long) nRow)
81 nHi = --i;
82 else
83 bFound = sal_True;
86 else
87 bFound = false;
89 if (bFound)
90 nIndex=(SCSIZE)i;
91 else
92 nIndex=0;
93 return bFound;
96 sal_Bool ScMarkArray::GetMark( SCROW nRow ) const
98 SCSIZE i;
99 if (Search( nRow, i ))
100 return pData[i].bMarked;
101 else
102 return false;
106 //------------------------------------------------------------------------
108 void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, sal_Bool bMarked )
110 if (ValidRow(nStartRow) && ValidRow(nEndRow))
112 if ((nStartRow == 0) && (nEndRow == MAXROW))
114 Reset(bMarked);
116 else
118 if (!pData)
119 Reset(false); // create pData for further processing - could use special case handling!
121 SCSIZE nNeeded = nCount + 2;
122 if ( nLimit < nNeeded )
124 nLimit += SC_MARKARRAY_DELTA;
125 if ( nLimit < nNeeded )
126 nLimit = nNeeded;
127 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
128 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
129 delete[] pData;
130 pData = pNewData;
133 SCSIZE ni; // number of entries in beginning
134 SCSIZE nInsert; // insert position (MAXROW+1 := no insert)
135 sal_Bool bCombined = false;
136 sal_Bool bSplit = false;
137 if ( nStartRow > 0 )
139 // skip beginning
140 SCSIZE nIndex;
141 Search( nStartRow, nIndex );
142 ni = nIndex;
144 nInsert = MAXROWCOUNT;
145 if ( pData[ni].bMarked != bMarked )
147 if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
148 { // may be a split or a simple insert or just a shrink,
149 // row adjustment is done further down
150 if ( pData[ni].nRow > nEndRow )
151 bSplit = sal_True;
152 ni++;
153 nInsert = ni;
155 else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
156 nInsert = ni;
158 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
159 { // combine
160 pData[ni-1].nRow = nEndRow;
161 nInsert = MAXROWCOUNT;
162 bCombined = sal_True;
165 else
167 nInsert = 0;
168 ni = 0;
171 SCSIZE nj = ni; // stop position of range to replace
172 while ( nj < nCount && pData[nj].nRow <= nEndRow )
173 nj++;
174 if ( !bSplit )
176 if ( nj < nCount && pData[nj].bMarked == bMarked )
177 { // combine
178 if ( ni > 0 )
180 if ( pData[ni-1].bMarked == bMarked )
181 { // adjacent entries
182 pData[ni-1].nRow = pData[nj].nRow;
183 nj++;
185 else if ( ni == nInsert )
186 pData[ni-1].nRow = nStartRow - 1; // shrink
188 nInsert = MAXROWCOUNT;
189 bCombined = sal_True;
191 else if ( ni > 0 && ni == nInsert )
192 pData[ni-1].nRow = nStartRow - 1; // shrink
194 if ( ni < nj )
195 { // remove middle entries
196 if ( !bCombined )
197 { // replace one entry
198 pData[ni].nRow = nEndRow;
199 pData[ni].bMarked = bMarked;
200 ni++;
201 nInsert = MAXROWCOUNT;
203 if ( ni < nj )
204 { // remove entries
205 memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
206 nCount -= nj - ni;
210 if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
211 { // insert or append new entry
212 if ( nInsert <= nCount )
214 if ( !bSplit )
215 memmove( pData + nInsert + 1, pData + nInsert,
216 (nCount - nInsert) * sizeof(ScMarkEntry) );
217 else
219 memmove( pData + nInsert + 2, pData + nInsert,
220 (nCount - nInsert) * sizeof(ScMarkEntry) );
221 pData[nInsert+1] = pData[nInsert-1];
222 nCount++;
225 if ( nInsert )
226 pData[nInsert-1].nRow = nStartRow - 1;
227 pData[nInsert].nRow = nEndRow;
228 pData[nInsert].bMarked = bMarked;
229 nCount++;
235 sal_Bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
237 SCSIZE nStartIndex;
238 SCSIZE nEndIndex;
240 if (Search( nStartRow, nStartIndex ))
241 if (pData[nStartIndex].bMarked)
242 if (Search( nEndRow, nEndIndex ))
243 if (nEndIndex==nStartIndex)
244 return sal_True;
246 return false;
249 sal_Bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
251 sal_Bool bRet = false;
252 if ( nCount == 1 )
254 if ( pData[0].bMarked )
256 rStartRow = 0;
257 rEndRow = MAXROW;
258 bRet = sal_True;
261 else if ( nCount == 2 )
263 if ( pData[0].bMarked )
265 rStartRow = 0;
266 rEndRow = pData[0].nRow;
268 else
270 rStartRow = pData[0].nRow + 1;
271 rEndRow = MAXROW;
273 bRet = sal_True;
275 else if ( nCount == 3 )
277 if ( pData[1].bMarked )
279 rStartRow = pData[0].nRow + 1;
280 rEndRow = pData[1].nRow;
281 bRet = sal_True;
284 return bRet;
287 void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
289 delete[] rDestMarkArray.pData;
291 if (pData)
293 rDestMarkArray.pData = new ScMarkEntry[nCount];
294 memcpy( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
296 else
297 rDestMarkArray.pData = NULL;
299 rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
302 SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, sal_Bool bUp ) const
304 if (!pData)
305 const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
307 SCsROW nRet = nRow;
308 if (ValidRow(nRow))
310 SCSIZE nIndex;
311 Search(nRow, nIndex);
312 if (!pData[nIndex].bMarked)
314 if (bUp)
316 if (nIndex>0)
317 nRet = pData[nIndex-1].nRow;
318 else
319 nRet = -1;
321 else
322 nRet = pData[nIndex].nRow + 1;
325 return nRet;
328 SCROW ScMarkArray::GetMarkEnd( SCROW nRow, sal_Bool bUp ) const
330 if (!pData)
331 const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
333 SCROW nRet;
334 SCSIZE nIndex;
335 Search(nRow, nIndex);
336 OSL_ENSURE( pData[nIndex].bMarked, "GetMarkEnd without bMarked" );
337 if (bUp)
339 if (nIndex>0)
340 nRet = pData[nIndex-1].nRow + 1;
341 else
342 nRet = 0;
344 else
345 nRet = pData[nIndex].nRow;
347 return nRet;
351 // -------------- Iterator ----------------------------------------------
354 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
355 pArray( pNewArray ),
356 nPos( 0 )
360 ScMarkArrayIter::~ScMarkArrayIter()
364 sal_Bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
366 if ( nPos >= pArray->nCount )
367 return false;
368 while (!pArray->pData[nPos].bMarked)
370 ++nPos;
371 if ( nPos >= pArray->nCount )
372 return false;
374 rBottom = pArray->pData[nPos].nRow;
375 if (nPos==0)
376 rTop = 0;
377 else
378 rTop = pArray->pData[nPos-1].nRow + 1;
379 ++nPos;
380 return sal_True;
387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */