fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / data / markarr.cxx
blob6a83437216fc1842a9722729383cb915a4315132
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 #include <osl/diagnose.h>
26 // STATIC DATA -----------------------------------------------------------
28 ScMarkArray::ScMarkArray() :
29 nCount( 0 ),
30 nLimit( 0 ),
31 pData( NULL )
33 // special case "no marks" with pData = NULL
36 ScMarkArray::~ScMarkArray()
38 delete[] pData;
41 void ScMarkArray::Reset( bool bMarked )
43 // always create pData here
44 // (or have separate method to ensure pData)
46 delete[] pData;
48 nCount = nLimit = 1;
49 pData = new ScMarkEntry[1];
50 pData[0].nRow = MAXROW;
51 pData[0].bMarked = bMarked;
54 bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
56 long nHi = static_cast<long>(nCount) - 1;
57 long i = 0;
58 bool bFound = (nCount == 1);
59 if (pData)
61 long nLo = 0;
62 long nStartRow = 0;
63 while ( !bFound && nLo <= nHi )
65 i = (nLo + nHi) / 2;
66 if (i > 0)
67 nStartRow = (long) pData[i - 1].nRow;
68 else
69 nStartRow = -1;
70 long nEndRow = (long) pData[i].nRow;
71 if (nEndRow < (long) nRow)
72 nLo = ++i;
73 else
74 if (nStartRow >= (long) nRow)
75 nHi = --i;
76 else
77 bFound = true;
80 else
81 bFound = false;
83 if (bFound)
84 nIndex=(SCSIZE)i;
85 else
86 nIndex=0;
87 return bFound;
90 bool ScMarkArray::GetMark( SCROW nRow ) const
92 SCSIZE i;
93 if (Search( nRow, i ))
94 return pData[i].bMarked;
95 else
96 return false;
100 void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, bool bMarked )
102 if (ValidRow(nStartRow) && ValidRow(nEndRow))
104 if ((nStartRow == 0) && (nEndRow == MAXROW))
106 Reset(bMarked);
108 else
110 if (!pData)
111 Reset(false); // create pData for further processing - could use special case handling!
113 SCSIZE nNeeded = nCount + 2;
114 if ( nLimit < nNeeded )
116 nLimit += SC_MARKARRAY_DELTA;
117 if ( nLimit < nNeeded )
118 nLimit = nNeeded;
119 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
120 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
121 delete[] pData;
122 pData = pNewData;
125 SCSIZE ni; // number of entries in beginning
126 SCSIZE nInsert; // insert position (MAXROW+1 := no insert)
127 bool bCombined = false;
128 bool bSplit = false;
129 if ( nStartRow > 0 )
131 // skip beginning
132 SCSIZE nIndex;
133 Search( nStartRow, nIndex );
134 ni = nIndex;
136 nInsert = MAXROWCOUNT;
137 if ( pData[ni].bMarked != bMarked )
139 if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
140 { // may be a split or a simple insert or just a shrink,
141 // row adjustment is done further down
142 if ( pData[ni].nRow > nEndRow )
143 bSplit = true;
144 ni++;
145 nInsert = ni;
147 else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
148 nInsert = ni;
150 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
151 { // combine
152 pData[ni-1].nRow = nEndRow;
153 nInsert = MAXROWCOUNT;
154 bCombined = true;
157 else
159 nInsert = 0;
160 ni = 0;
163 SCSIZE nj = ni; // stop position of range to replace
164 while ( nj < nCount && pData[nj].nRow <= nEndRow )
165 nj++;
166 if ( !bSplit )
168 if ( nj < nCount && pData[nj].bMarked == bMarked )
169 { // combine
170 if ( ni > 0 )
172 if ( pData[ni-1].bMarked == bMarked )
173 { // adjacent entries
174 pData[ni-1].nRow = pData[nj].nRow;
175 nj++;
177 else if ( ni == nInsert )
178 pData[ni-1].nRow = nStartRow - 1; // shrink
180 nInsert = MAXROWCOUNT;
181 bCombined = true;
183 else if ( ni > 0 && ni == nInsert )
184 pData[ni-1].nRow = nStartRow - 1; // shrink
186 if ( ni < nj )
187 { // remove middle entries
188 if ( !bCombined )
189 { // replace one entry
190 pData[ni].nRow = nEndRow;
191 pData[ni].bMarked = bMarked;
192 ni++;
193 nInsert = MAXROWCOUNT;
195 if ( ni < nj )
196 { // remove entries
197 memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
198 nCount -= nj - ni;
202 if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
203 { // insert or append new entry
204 if ( nInsert <= nCount )
206 if ( !bSplit )
207 memmove( pData + nInsert + 1, pData + nInsert,
208 (nCount - nInsert) * sizeof(ScMarkEntry) );
209 else
211 memmove( pData + nInsert + 2, pData + nInsert,
212 (nCount - nInsert) * sizeof(ScMarkEntry) );
213 pData[nInsert+1] = pData[nInsert-1];
214 nCount++;
217 if ( nInsert )
218 pData[nInsert-1].nRow = nStartRow - 1;
219 pData[nInsert].nRow = nEndRow;
220 pData[nInsert].bMarked = bMarked;
221 nCount++;
227 bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
229 SCSIZE nStartIndex;
230 SCSIZE nEndIndex;
232 if (Search( nStartRow, nStartIndex ))
233 if (pData[nStartIndex].bMarked)
234 if (Search( nEndRow, nEndIndex ))
235 if (nEndIndex==nStartIndex)
236 return true;
238 return false;
241 bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
243 bool bRet = false;
244 if ( nCount == 1 )
246 if ( pData[0].bMarked )
248 rStartRow = 0;
249 rEndRow = MAXROW;
250 bRet = true;
253 else if ( nCount == 2 )
255 if ( pData[0].bMarked )
257 rStartRow = 0;
258 rEndRow = pData[0].nRow;
260 else
262 rStartRow = pData[0].nRow + 1;
263 rEndRow = MAXROW;
265 bRet = true;
267 else if ( nCount == 3 )
269 if ( pData[1].bMarked )
271 rStartRow = pData[0].nRow + 1;
272 rEndRow = pData[1].nRow;
273 bRet = true;
276 return bRet;
279 bool ScMarkArray::HasEqualRowsMarked( const ScMarkArray& rOther ) const
281 if (nCount != rOther.nCount)
282 return false;
284 for (size_t i=0; i < nCount; ++i)
286 if (pData[i].bMarked != rOther.pData[i].bMarked ||
287 pData[i].nRow != rOther.pData[i].nRow)
288 return false;
291 return true;
294 void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
296 delete[] rDestMarkArray.pData;
298 if (pData)
300 rDestMarkArray.pData = new ScMarkEntry[nCount];
301 memcpy( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
303 else
304 rDestMarkArray.pData = NULL;
306 rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
309 SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, bool bUp ) const
311 if (!pData)
312 const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
314 SCsROW nRet = nRow;
315 if (ValidRow(nRow))
317 SCSIZE nIndex;
318 Search(nRow, nIndex);
319 if (!pData[nIndex].bMarked)
321 if (bUp)
323 if (nIndex>0)
324 nRet = pData[nIndex-1].nRow;
325 else
326 nRet = -1;
328 else
329 nRet = pData[nIndex].nRow + 1;
332 return nRet;
335 SCROW ScMarkArray::GetMarkEnd( SCROW nRow, bool bUp ) const
337 if (!pData)
338 const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
340 SCROW nRet;
341 SCSIZE nIndex;
342 Search(nRow, nIndex);
343 OSL_ENSURE( pData[nIndex].bMarked, "GetMarkEnd without bMarked" );
344 if (bUp)
346 if (nIndex>0)
347 nRet = pData[nIndex-1].nRow + 1;
348 else
349 nRet = 0;
351 else
352 nRet = pData[nIndex].nRow;
354 return nRet;
357 // -------------- Iterator ----------------------------------------------
359 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
360 pArray( pNewArray ),
361 nPos( 0 )
365 ScMarkArrayIter::~ScMarkArrayIter()
369 bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
371 if ( nPos >= pArray->nCount )
372 return false;
373 while (!pArray->pData[nPos].bMarked)
375 ++nPos;
376 if ( nPos >= pArray->nCount )
377 return false;
379 rBottom = pArray->pData[nPos].nRow;
380 if (nPos==0)
381 rTop = 0;
382 else
383 rTop = pArray->pData[nPos-1].nRow + 1;
384 ++nPos;
385 return true;
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */