1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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"
42 #include "address.hxx"
44 // STATIC DATA -----------------------------------------------------------
46 //------------------------------------------------------------------------
48 ScMarkArray::ScMarkArray() :
53 // special case "no marks" with pData = NULL
56 //------------------------------------------------------------------------
58 ScMarkArray::~ScMarkArray()
63 //------------------------------------------------------------------------
65 void ScMarkArray::Reset( BOOL bMarked
)
67 // always create pData here
68 // (or have separate method to ensure pData)
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
83 long nHi
= static_cast<long>(nCount
) - 1;
87 BOOL bFound
= (nCount
== 1);
90 while ( !bFound
&& nLo
<= nHi
)
94 nStartRow
= (long) pData
[i
- 1].nRow
;
97 nEndRow
= (long) pData
[i
].nRow
;
98 if (nEndRow
< (long) nRow
)
101 if (nStartRow
>= (long) nRow
)
117 BOOL
ScMarkArray::GetMark( SCROW nRow
) const
120 if (Search( nRow
, i
))
121 return pData
[i
].bMarked
;
127 //------------------------------------------------------------------------
129 void ScMarkArray::SetMarkArea( SCROW nStartRow
, SCROW nEndRow
, BOOL bMarked
)
131 if (ValidRow(nStartRow
) && ValidRow(nEndRow
))
133 if ((nStartRow
== 0) && (nEndRow
== MAXROW
))
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
)
148 ScMarkEntry
* pNewData
= new ScMarkEntry
[nLimit
];
149 memcpy( pNewData
, pData
, nCount
*sizeof(ScMarkEntry
) );
154 SCSIZE ni
; // number of entries in beginning
155 SCSIZE nInsert
; // insert position (MAXROW+1 := no insert)
156 BOOL bCombined
= FALSE
;
162 Search( nStartRow
, 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
)
176 else if ( ni
> 0 && pData
[ni
-1].nRow
== nStartRow
- 1 )
179 if ( ni
> 0 && pData
[ni
-1].bMarked
== bMarked
)
181 pData
[ni
-1].nRow
= nEndRow
;
182 nInsert
= MAXROWCOUNT
;
192 SCSIZE nj
= ni
; // stop position of range to replace
193 while ( nj
< nCount
&& pData
[nj
].nRow
<= nEndRow
)
197 if ( nj
< nCount
&& pData
[nj
].bMarked
== bMarked
)
201 if ( pData
[ni
-1].bMarked
== bMarked
)
202 { // adjacent entries
203 pData
[ni
-1].nRow
= pData
[nj
].nRow
;
206 else if ( ni
== nInsert
)
207 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
209 nInsert
= MAXROWCOUNT
;
212 else if ( ni
> 0 && ni
== nInsert
)
213 pData
[ni
-1].nRow
= nStartRow
- 1; // shrink
216 { // remove middle entries
218 { // replace one entry
219 pData
[ni
].nRow
= nEndRow
;
220 pData
[ni
].bMarked
= bMarked
;
222 nInsert
= MAXROWCOUNT
;
226 memmove( pData
+ ni
, pData
+ nj
, (nCount
- nj
) * sizeof(ScMarkEntry
) );
231 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(MAXROWCOUNT
) )
232 { // insert or append new entry
233 if ( nInsert
<= nCount
)
236 memmove( pData
+ nInsert
+ 1, pData
+ nInsert
,
237 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
240 memmove( pData
+ nInsert
+ 2, pData
+ nInsert
,
241 (nCount
- nInsert
) * sizeof(ScMarkEntry
) );
242 pData
[nInsert
+1] = pData
[nInsert
-1];
247 pData
[nInsert
-1].nRow
= nStartRow
- 1;
248 pData
[nInsert
].nRow
= nEndRow
;
249 pData
[nInsert
].bMarked
= bMarked
;
254 // InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
257 //UNUSED2009-05 void ScMarkArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
259 //UNUSED2009-05 SetMarkArea(nStartRow, nEndRow, FALSE);
262 BOOL
ScMarkArray::IsAllMarked( SCROW nStartRow
, SCROW nEndRow
) const
267 if (Search( nStartRow
, nStartIndex
))
268 if (pData
[nStartIndex
].bMarked
)
269 if (Search( nEndRow
, nEndIndex
))
270 if (nEndIndex
==nStartIndex
)
276 BOOL
ScMarkArray::HasOneMark( SCROW
& rStartRow
, SCROW
& rEndRow
) const
281 if ( pData
[0].bMarked
)
288 else if ( nCount
== 2 )
290 if ( pData
[0].bMarked
)
293 rEndRow
= pData
[0].nRow
;
297 rStartRow
= pData
[0].nRow
+ 1;
302 else if ( nCount
== 3 )
304 if ( pData
[1].bMarked
)
306 rStartRow
= pData
[0].nRow
+ 1;
307 rEndRow
= pData
[1].nRow
;
314 void ScMarkArray::CopyMarksTo( ScMarkArray
& rDestMarkArray
) const
316 delete[] rDestMarkArray
.pData
;
320 rDestMarkArray
.pData
= new ScMarkEntry
[nCount
];
321 memmove( rDestMarkArray
.pData
, pData
, nCount
* sizeof(ScMarkEntry
) );
324 rDestMarkArray
.pData
= NULL
;
326 rDestMarkArray
.nCount
= rDestMarkArray
.nLimit
= nCount
;
329 SCsROW
ScMarkArray::GetNextMarked( SCsROW nRow
, BOOL bUp
) const
332 const_cast<ScMarkArray
*>(this)->Reset(FALSE
); // create pData for further processing
338 Search(nRow
, nIndex
);
339 if (!pData
[nIndex
].bMarked
)
344 nRet
= pData
[nIndex
-1].nRow
;
349 nRet
= pData
[nIndex
].nRow
+ 1;
355 SCROW
ScMarkArray::GetMarkEnd( SCROW nRow
, BOOL bUp
) const
358 const_cast<ScMarkArray
*>(this)->Reset(FALSE
); // create pData for further processing
362 Search(nRow
, nIndex
);
363 DBG_ASSERT( pData
[nIndex
].bMarked
, "GetMarkEnd ohne bMarked" );
367 nRet
= pData
[nIndex
-1].nRow
+ 1;
372 nRet
= pData
[nIndex
].nRow
;
378 // -------------- Iterator ----------------------------------------------
381 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray
* pNewArray
) :
387 ScMarkArrayIter::~ScMarkArrayIter()
391 BOOL
ScMarkArrayIter::Next( SCROW
& rTop
, SCROW
& rBottom
)
393 if ( nPos
>= pArray
->nCount
)
395 while (!pArray
->pData
[nPos
].bMarked
)
398 if ( nPos
>= pArray
->nCount
)
401 rBottom
= pArray
->pData
[nPos
].nRow
;
405 rTop
= pArray
->pData
[nPos
-1].nRow
+ 1;