merge the formfield patch from ooo-build
[ooovba.git] / sc / source / core / data / markarr.cxx
blob343c0927cb2e32df4eb01b5460bb8bd551f20c2f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: markarr.cxx,v $
10 * $Revision: 1.11.32.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 // INCLUDE ---------------------------------------------------------------
38 #include <tools/debug.hxx>
40 #include "markarr.hxx"
41 #include "global.hxx"
42 #include "address.hxx"
44 // STATIC DATA -----------------------------------------------------------
46 //------------------------------------------------------------------------
48 ScMarkArray::ScMarkArray() :
49 nCount( 0 ),
50 nLimit( 0 ),
51 pData( NULL )
53 // special case "no marks" with pData = NULL
56 //------------------------------------------------------------------------
58 ScMarkArray::~ScMarkArray()
60 delete[] pData;
63 //------------------------------------------------------------------------
65 void ScMarkArray::Reset( BOOL bMarked )
67 // always create pData here
68 // (or have separate method to ensure pData)
70 delete[] pData;
72 nCount = nLimit = 1;
73 pData = new ScMarkEntry[1];
74 pData[0].nRow = MAXROW;
75 pData[0].bMarked = bMarked;
78 //------------------------------------------------------------------------
80 BOOL ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
82 long nLo = 0;
83 long nHi = static_cast<long>(nCount) - 1;
84 long nStartRow = 0;
85 long nEndRow = 0;
86 long i = 0;
87 BOOL bFound = (nCount == 1);
88 if (pData)
90 while ( !bFound && nLo <= nHi )
92 i = (nLo + nHi) / 2;
93 if (i > 0)
94 nStartRow = (long) pData[i - 1].nRow;
95 else
96 nStartRow = -1;
97 nEndRow = (long) pData[i].nRow;
98 if (nEndRow < (long) nRow)
99 nLo = ++i;
100 else
101 if (nStartRow >= (long) nRow)
102 nHi = --i;
103 else
104 bFound = TRUE;
107 else
108 bFound = FALSE;
110 if (bFound)
111 nIndex=(SCSIZE)i;
112 else
113 nIndex=0;
114 return bFound;
117 BOOL ScMarkArray::GetMark( SCROW nRow ) const
119 SCSIZE i;
120 if (Search( nRow, i ))
121 return pData[i].bMarked;
122 else
123 return FALSE;
127 //------------------------------------------------------------------------
129 void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, BOOL bMarked )
131 if (ValidRow(nStartRow) && ValidRow(nEndRow))
133 if ((nStartRow == 0) && (nEndRow == MAXROW))
135 Reset(bMarked);
137 else
139 if (!pData)
140 Reset(FALSE); // create pData for further processing - could use special case handling!
142 SCSIZE nNeeded = nCount + 2;
143 if ( nLimit < nNeeded )
145 nLimit += SC_MARKARRAY_DELTA;
146 if ( nLimit < nNeeded )
147 nLimit = nNeeded;
148 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
149 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
150 delete[] pData;
151 pData = pNewData;
154 SCSIZE ni; // number of entries in beginning
155 SCSIZE nInsert; // insert position (MAXROW+1 := no insert)
156 BOOL bCombined = FALSE;
157 BOOL bSplit = FALSE;
158 if ( nStartRow > 0 )
160 // skip beginning
161 SCSIZE nIndex;
162 Search( nStartRow, nIndex );
163 ni = nIndex;
165 nInsert = MAXROWCOUNT;
166 if ( pData[ni].bMarked != bMarked )
168 if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
169 { // may be a split or a simple insert or just a shrink,
170 // row adjustment is done further down
171 if ( pData[ni].nRow > nEndRow )
172 bSplit = TRUE;
173 ni++;
174 nInsert = ni;
176 else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
177 nInsert = ni;
179 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
180 { // combine
181 pData[ni-1].nRow = nEndRow;
182 nInsert = MAXROWCOUNT;
183 bCombined = TRUE;
186 else
188 nInsert = 0;
189 ni = 0;
192 SCSIZE nj = ni; // stop position of range to replace
193 while ( nj < nCount && pData[nj].nRow <= nEndRow )
194 nj++;
195 if ( !bSplit )
197 if ( nj < nCount && pData[nj].bMarked == bMarked )
198 { // combine
199 if ( ni > 0 )
201 if ( pData[ni-1].bMarked == bMarked )
202 { // adjacent entries
203 pData[ni-1].nRow = pData[nj].nRow;
204 nj++;
206 else if ( ni == nInsert )
207 pData[ni-1].nRow = nStartRow - 1; // shrink
209 nInsert = MAXROWCOUNT;
210 bCombined = TRUE;
212 else if ( ni > 0 && ni == nInsert )
213 pData[ni-1].nRow = nStartRow - 1; // shrink
215 if ( ni < nj )
216 { // remove middle entries
217 if ( !bCombined )
218 { // replace one entry
219 pData[ni].nRow = nEndRow;
220 pData[ni].bMarked = bMarked;
221 ni++;
222 nInsert = MAXROWCOUNT;
224 if ( ni < nj )
225 { // remove entries
226 memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
227 nCount -= nj - ni;
231 if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
232 { // insert or append new entry
233 if ( nInsert <= nCount )
235 if ( !bSplit )
236 memmove( pData + nInsert + 1, pData + nInsert,
237 (nCount - nInsert) * sizeof(ScMarkEntry) );
238 else
240 memmove( pData + nInsert + 2, pData + nInsert,
241 (nCount - nInsert) * sizeof(ScMarkEntry) );
242 pData[nInsert+1] = pData[nInsert-1];
243 nCount++;
246 if ( nInsert )
247 pData[nInsert-1].nRow = nStartRow - 1;
248 pData[nInsert].nRow = nEndRow;
249 pData[nInsert].bMarked = bMarked;
250 nCount++;
254 // InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
257 //UNUSED2009-05 void ScMarkArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
258 //UNUSED2009-05 {
259 //UNUSED2009-05 SetMarkArea(nStartRow, nEndRow, FALSE);
260 //UNUSED2009-05 }
262 BOOL ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
264 SCSIZE nStartIndex;
265 SCSIZE nEndIndex;
267 if (Search( nStartRow, nStartIndex ))
268 if (pData[nStartIndex].bMarked)
269 if (Search( nEndRow, nEndIndex ))
270 if (nEndIndex==nStartIndex)
271 return TRUE;
273 return FALSE;
276 BOOL ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
278 BOOL bRet = FALSE;
279 if ( nCount == 1 )
281 if ( pData[0].bMarked )
283 rStartRow = 0;
284 rEndRow = MAXROW;
285 bRet = TRUE;
288 else if ( nCount == 2 )
290 if ( pData[0].bMarked )
292 rStartRow = 0;
293 rEndRow = pData[0].nRow;
295 else
297 rStartRow = pData[0].nRow + 1;
298 rEndRow = MAXROW;
300 bRet = TRUE;
302 else if ( nCount == 3 )
304 if ( pData[1].bMarked )
306 rStartRow = pData[0].nRow + 1;
307 rEndRow = pData[1].nRow;
308 bRet = TRUE;
311 return bRet;
314 void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
316 delete[] rDestMarkArray.pData;
318 if (pData)
320 rDestMarkArray.pData = new ScMarkEntry[nCount];
321 memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
323 else
324 rDestMarkArray.pData = NULL;
326 rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
329 SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, BOOL bUp ) const
331 if (!pData)
332 const_cast<ScMarkArray*>(this)->Reset(FALSE); // create pData for further processing
334 SCsROW nRet = nRow;
335 if (VALIDROW(nRow))
337 SCSIZE nIndex;
338 Search(nRow, nIndex);
339 if (!pData[nIndex].bMarked)
341 if (bUp)
343 if (nIndex>0)
344 nRet = pData[nIndex-1].nRow;
345 else
346 nRet = -1;
348 else
349 nRet = pData[nIndex].nRow + 1;
352 return nRet;
355 SCROW ScMarkArray::GetMarkEnd( SCROW nRow, BOOL bUp ) const
357 if (!pData)
358 const_cast<ScMarkArray*>(this)->Reset(FALSE); // create pData for further processing
360 SCROW nRet;
361 SCSIZE nIndex;
362 Search(nRow, nIndex);
363 DBG_ASSERT( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
364 if (bUp)
366 if (nIndex>0)
367 nRet = pData[nIndex-1].nRow + 1;
368 else
369 nRet = 0;
371 else
372 nRet = pData[nIndex].nRow;
374 return nRet;
378 // -------------- Iterator ----------------------------------------------
381 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
382 pArray( pNewArray ),
383 nPos( 0 )
387 ScMarkArrayIter::~ScMarkArrayIter()
391 BOOL ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
393 if ( nPos >= pArray->nCount )
394 return FALSE;
395 while (!pArray->pData[nPos].bMarked)
397 ++nPos;
398 if ( nPos >= pArray->nCount )
399 return FALSE;
401 rBottom = pArray->pData[nPos].nRow;
402 if (nPos==0)
403 rTop = 0;
404 else
405 rTop = pArray->pData[nPos-1].nRow + 1;
406 ++nPos;
407 return TRUE;