1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
22 #include "address.hxx"
24 #include <osl/diagnose.h>
26 // STATIC DATA -----------------------------------------------------------
28 ScMarkArray::ScMarkArray() :
33 // special case "no marks" with pData = NULL
36 ScMarkArray::~ScMarkArray()
41 void ScMarkArray::Reset( bool bMarked
)
43 // always create pData here
44 // (or have separate method to ensure pData)
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;
58 bool bFound
= (nCount
== 1);
63 while ( !bFound
&& nLo
<= nHi
)
67 nStartRow
= (long) pData
[i
- 1].nRow
;
70 long nEndRow
= (long) pData
[i
].nRow
;
71 if (nEndRow
< (long) nRow
)
74 if (nStartRow
>= (long) nRow
)
90 bool ScMarkArray::GetMark( SCROW nRow
) const
93 if (Search( nRow
, i
))
94 return pData
[i
].bMarked
;
100 void ScMarkArray::SetMarkArea( SCROW nStartRow
, SCROW nEndRow
, bool bMarked
)
102 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
104 if ((nStartRow
== 0) && (nEndRow
== MAXROW
))
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
)
119 ScMarkEntry
* pNewData
= new ScMarkEntry
[nLimit
];
120 memcpy( pNewData
, pData
, nCount
*sizeof(ScMarkEntry
) );
125 SCSIZE ni
; // number of entries in beginning
126 SCSIZE nInsert
; // insert position (MAXROW+1 := no insert)
127 bool bCombined
= false;
133 Search( nStartRow
, 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
)
147 else if ( ni
> 0 && pData
[ni
-1].nRow
== nStartRow
- 1 )
150 if ( ni
> 0 && pData
[ni
-1].bMarked
== bMarked
)
152 pData
[ni
-1].nRow
= nEndRow
;
153 nInsert
= MAXROWCOUNT
;
163 SCSIZE nj
= ni
; // stop position of range to replace
164 while ( nj
< nCount
&& pData
[nj
].nRow
<= nEndRow
)
168 if ( nj
< nCount
&& pData
[nj
].bMarked
== bMarked
)
172 if ( pData
[ni
-1].bMarked
== bMarked
)
173 { // adjacent entries
174 pData
[ni
-1].nRow
= pData
[nj
].nRow
;
177 else if ( ni
== nInsert
)
178 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
180 nInsert
= MAXROWCOUNT
;
183 else if ( ni
> 0 && ni
== nInsert
)
184 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
187 { // remove middle entries
189 { // replace one entry
190 pData
[ni
].nRow
= nEndRow
;
191 pData
[ni
].bMarked
= bMarked
;
193 nInsert
= MAXROWCOUNT
;
197 memmove( pData
+ ni
, pData
+ nj
, (nCount
- nj
) * sizeof(ScMarkEntry
) );
202 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(MAXROWCOUNT
) )
203 { // insert or append new entry
204 if ( nInsert
<= nCount
)
207 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
208 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
211 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
212 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
213 pData
[nInsert
+1] = pData
[nInsert
-1];
218 pData
[nInsert
-1].nRow
= nStartRow
- 1;
219 pData
[nInsert
].nRow
= nEndRow
;
220 pData
[nInsert
].bMarked
= bMarked
;
227 bool ScMarkArray::IsAllMarked( SCROW nStartRow
, SCROW nEndRow
) const
232 if (Search( nStartRow
, nStartIndex
))
233 if (pData
[nStartIndex
].bMarked
)
234 if (Search( nEndRow
, nEndIndex
))
235 if (nEndIndex
==nStartIndex
)
241 bool ScMarkArray::HasOneMark( SCROW
& rStartRow
, SCROW
& rEndRow
) const
246 if ( pData
[0].bMarked
)
253 else if ( nCount
== 2 )
255 if ( pData
[0].bMarked
)
258 rEndRow
= pData
[0].nRow
;
262 rStartRow
= pData
[0].nRow
+ 1;
267 else if ( nCount
== 3 )
269 if ( pData
[1].bMarked
)
271 rStartRow
= pData
[0].nRow
+ 1;
272 rEndRow
= pData
[1].nRow
;
279 bool ScMarkArray::HasEqualRowsMarked( const ScMarkArray
& rOther
) const
281 if (nCount
!= rOther
.nCount
)
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
)
294 void ScMarkArray::CopyMarksTo( ScMarkArray
& rDestMarkArray
) const
296 delete[] rDestMarkArray
.pData
;
300 rDestMarkArray
.pData
= new ScMarkEntry
[nCount
];
301 memcpy( rDestMarkArray
.pData
, pData
, nCount
* sizeof(ScMarkEntry
) );
304 rDestMarkArray
.pData
= NULL
;
306 rDestMarkArray
.nCount
= rDestMarkArray
.nLimit
= nCount
;
309 SCsROW
ScMarkArray::GetNextMarked( SCsROW nRow
, bool bUp
) const
312 const_cast<ScMarkArray
*>(this)->Reset(false); // create pData for further processing
318 Search(nRow
, nIndex
);
319 if (!pData
[nIndex
].bMarked
)
324 nRet
= pData
[nIndex
-1].nRow
;
329 nRet
= pData
[nIndex
].nRow
+ 1;
335 SCROW
ScMarkArray::GetMarkEnd( SCROW nRow
, bool bUp
) const
338 const_cast<ScMarkArray
*>(this)->Reset(false); // create pData for further processing
342 Search(nRow
, nIndex
);
343 OSL_ENSURE( pData
[nIndex
].bMarked
, "GetMarkEnd without bMarked" );
347 nRet
= pData
[nIndex
-1].nRow
+ 1;
352 nRet
= pData
[nIndex
].nRow
;
357 // -------------- Iterator ----------------------------------------------
359 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray
* pNewArray
) :
365 ScMarkArrayIter::~ScMarkArrayIter()
369 bool ScMarkArrayIter::Next( SCROW
& rTop
, SCROW
& rBottom
)
371 if ( nPos
>= pArray
->nCount
)
373 while (!pArray
->pData
[nPos
].bMarked
)
376 if ( nPos
>= pArray
->nCount
)
379 rBottom
= pArray
->pData
[nPos
].nRow
;
383 rTop
= pArray
->pData
[nPos
-1].nRow
+ 1;
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */