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 // STATIC DATA -----------------------------------------------------------
26 //------------------------------------------------------------------------
28 ScMarkArray::ScMarkArray() :
33 // special case "no marks" with pData = NULL
36 //------------------------------------------------------------------------
38 ScMarkArray::~ScMarkArray()
43 //------------------------------------------------------------------------
45 void ScMarkArray::Reset( sal_Bool bMarked
)
47 // always create pData here
48 // (or have separate method to ensure pData)
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;
64 sal_Bool bFound
= (nCount
== 1);
69 while ( !bFound
&& nLo
<= nHi
)
73 nStartRow
= (long) pData
[i
- 1].nRow
;
76 long nEndRow
= (long) pData
[i
].nRow
;
77 if (nEndRow
< (long) nRow
)
80 if (nStartRow
>= (long) nRow
)
96 sal_Bool
ScMarkArray::GetMark( SCROW nRow
) const
99 if (Search( nRow
, i
))
100 return pData
[i
].bMarked
;
106 //------------------------------------------------------------------------
108 void ScMarkArray::SetMarkArea( SCROW nStartRow
, SCROW nEndRow
, sal_Bool bMarked
)
110 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
112 if ((nStartRow
== 0) && (nEndRow
== MAXROW
))
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
)
127 ScMarkEntry
* pNewData
= new ScMarkEntry
[nLimit
];
128 memcpy( pNewData
, pData
, nCount
*sizeof(ScMarkEntry
) );
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;
141 Search( nStartRow
, 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
)
155 else if ( ni
> 0 && pData
[ni
-1].nRow
== nStartRow
- 1 )
158 if ( ni
> 0 && pData
[ni
-1].bMarked
== bMarked
)
160 pData
[ni
-1].nRow
= nEndRow
;
161 nInsert
= MAXROWCOUNT
;
162 bCombined
= sal_True
;
171 SCSIZE nj
= ni
; // stop position of range to replace
172 while ( nj
< nCount
&& pData
[nj
].nRow
<= nEndRow
)
176 if ( nj
< nCount
&& pData
[nj
].bMarked
== bMarked
)
180 if ( pData
[ni
-1].bMarked
== bMarked
)
181 { // adjacent entries
182 pData
[ni
-1].nRow
= pData
[nj
].nRow
;
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
195 { // remove middle entries
197 { // replace one entry
198 pData
[ni
].nRow
= nEndRow
;
199 pData
[ni
].bMarked
= bMarked
;
201 nInsert
= MAXROWCOUNT
;
205 memmove( pData
+ ni
, pData
+ nj
, (nCount
- nj
) * sizeof(ScMarkEntry
) );
210 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(MAXROWCOUNT
) )
211 { // insert or append new entry
212 if ( nInsert
<= nCount
)
215 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
216 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
219 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
220 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
221 pData
[nInsert
+1] = pData
[nInsert
-1];
226 pData
[nInsert
-1].nRow
= nStartRow
- 1;
227 pData
[nInsert
].nRow
= nEndRow
;
228 pData
[nInsert
].bMarked
= bMarked
;
235 sal_Bool
ScMarkArray::IsAllMarked( SCROW nStartRow
, SCROW nEndRow
) const
240 if (Search( nStartRow
, nStartIndex
))
241 if (pData
[nStartIndex
].bMarked
)
242 if (Search( nEndRow
, nEndIndex
))
243 if (nEndIndex
==nStartIndex
)
249 sal_Bool
ScMarkArray::HasOneMark( SCROW
& rStartRow
, SCROW
& rEndRow
) const
251 sal_Bool bRet
= false;
254 if ( pData
[0].bMarked
)
261 else if ( nCount
== 2 )
263 if ( pData
[0].bMarked
)
266 rEndRow
= pData
[0].nRow
;
270 rStartRow
= pData
[0].nRow
+ 1;
275 else if ( nCount
== 3 )
277 if ( pData
[1].bMarked
)
279 rStartRow
= pData
[0].nRow
+ 1;
280 rEndRow
= pData
[1].nRow
;
287 void ScMarkArray::CopyMarksTo( ScMarkArray
& rDestMarkArray
) const
289 delete[] rDestMarkArray
.pData
;
293 rDestMarkArray
.pData
= new ScMarkEntry
[nCount
];
294 memcpy( rDestMarkArray
.pData
, pData
, nCount
* sizeof(ScMarkEntry
) );
297 rDestMarkArray
.pData
= NULL
;
299 rDestMarkArray
.nCount
= rDestMarkArray
.nLimit
= nCount
;
302 SCsROW
ScMarkArray::GetNextMarked( SCsROW nRow
, sal_Bool bUp
) const
305 const_cast<ScMarkArray
*>(this)->Reset(false); // create pData for further processing
311 Search(nRow
, nIndex
);
312 if (!pData
[nIndex
].bMarked
)
317 nRet
= pData
[nIndex
-1].nRow
;
322 nRet
= pData
[nIndex
].nRow
+ 1;
328 SCROW
ScMarkArray::GetMarkEnd( SCROW nRow
, sal_Bool bUp
) const
331 const_cast<ScMarkArray
*>(this)->Reset(false); // create pData for further processing
335 Search(nRow
, nIndex
);
336 OSL_ENSURE( pData
[nIndex
].bMarked
, "GetMarkEnd without bMarked" );
340 nRet
= pData
[nIndex
-1].nRow
+ 1;
345 nRet
= pData
[nIndex
].nRow
;
351 // -------------- Iterator ----------------------------------------------
354 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray
* pNewArray
) :
360 ScMarkArrayIter::~ScMarkArrayIter()
364 sal_Bool
ScMarkArrayIter::Next( SCROW
& rTop
, SCROW
& rBottom
)
366 if ( nPos
>= pArray
->nCount
)
368 while (!pArray
->pData
[nPos
].bMarked
)
371 if ( nPos
>= pArray
->nCount
)
374 rBottom
= pArray
->pData
[nPos
].nRow
;
378 rTop
= pArray
->pData
[nPos
-1].nRow
+ 1;
387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */