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>
21 #include <address.hxx>
22 #include <sheetlimits.hxx>
25 ScMarkArray::ScMarkArray(const ScSheetLimits
& rLimits
) :
26 mrSheetLimits(rLimits
)
32 ScMarkArray::ScMarkArray( ScMarkArray
&& rOther
) noexcept
33 : mrSheetLimits(rOther
.mrSheetLimits
)
35 operator=(std::move(rOther
));
39 ScMarkArray::ScMarkArray( const ScMarkArray
& rOther
)
40 : mrSheetLimits(rOther
.mrSheetLimits
)
45 void ScMarkArray::Reset( bool bMarked
, SCSIZE nNeeded
)
47 // always create pData here
48 // (or have separate method to ensure pData)
52 mvData
.reserve(nNeeded
);
53 mvData
[0].nRow
= mrSheetLimits
.mnMaxRow
;
54 mvData
[0].bMarked
= bMarked
;
57 // Iterative implementation of Binary Search
58 bool ScMarkArray::Search( SCROW nRow
, SCSIZE
& nIndex
) const
60 assert(mvData
.size() > 0);
61 SCSIZE nHi
= mvData
.size() - 1;
66 SCSIZE i
= (nLo
+ nHi
) / 2;
68 if (mvData
[i
].nRow
< nRow
)
70 // If [nRow] greater, ignore left half
73 else if ((i
> 0) && (mvData
[i
- 1].nRow
>= nRow
))
75 // If [nRow] is smaller, ignore right half
91 bool ScMarkArray::GetMark( SCROW nRow
) const
94 if (Search( nRow
, i
))
95 return mvData
[i
].bMarked
;
101 void ScMarkArray::SetMarkArea( SCROW nStartRow
, SCROW nEndRow
, bool bMarked
)
103 if (!(mrSheetLimits
.ValidRow(nStartRow
) && mrSheetLimits
.ValidRow(nEndRow
)))
106 if ((nStartRow
== 0) && (nEndRow
== mrSheetLimits
.mnMaxRow
))
112 SCSIZE ni
; // number of entries in beginning
113 SCSIZE nInsert
; // insert position (mnMaxRow+1 := no insert)
114 bool bCombined
= false;
120 Search( nStartRow
, nIndex
);
123 nInsert
= mrSheetLimits
.GetMaxRowCount();
124 if ( mvData
[ni
].bMarked
!= bMarked
)
126 if ( ni
== 0 || (mvData
[ni
-1].nRow
< nStartRow
- 1) )
127 { // may be a split or a simple insert or just a shrink,
128 // row adjustment is done further down
129 if ( mvData
[ni
].nRow
> nEndRow
)
134 else if ( ni
> 0 && mvData
[ni
-1].nRow
== nStartRow
- 1 )
137 if ( ni
> 0 && mvData
[ni
-1].bMarked
== bMarked
)
139 mvData
[ni
-1].nRow
= nEndRow
;
140 nInsert
= mrSheetLimits
.GetMaxRowCount();
150 SCSIZE nj
= ni
; // stop position of range to replace
151 while ( nj
< mvData
.size() && mvData
[nj
].nRow
<= nEndRow
)
155 if ( nj
< mvData
.size() && mvData
[nj
].bMarked
== bMarked
)
159 if ( mvData
[ni
-1].bMarked
== bMarked
)
160 { // adjacent entries
161 mvData
[ni
-1].nRow
= mvData
[nj
].nRow
;
164 else if ( ni
== nInsert
)
165 mvData
[ni
-1].nRow
= nStartRow
- 1; // shrink
167 nInsert
= mrSheetLimits
.GetMaxRowCount();
170 else if ( ni
> 0 && ni
== nInsert
)
171 mvData
[ni
-1].nRow
= nStartRow
- 1; // shrink
174 { // remove middle entries
176 { // replace one entry
177 mvData
[ni
].nRow
= nEndRow
;
178 mvData
[ni
].bMarked
= bMarked
;
180 nInsert
= mrSheetLimits
.GetMaxRowCount();
184 mvData
.erase(mvData
.begin() + ni
, mvData
.begin() + nj
);
188 if ( nInsert
< sal::static_int_cast
<SCSIZE
>(mrSheetLimits
.GetMaxRowCount()) )
189 { // insert or append new entry
190 if ( nInsert
<= mvData
.size() )
193 mvData
.insert(mvData
.begin() + nInsert
, { nEndRow
, bMarked
});
196 mvData
.insert(mvData
.begin() + nInsert
, 2, { nEndRow
, bMarked
});
197 mvData
[nInsert
+1] = mvData
[nInsert
-1];
201 mvData
.push_back(ScMarkEntry
{ nEndRow
, bMarked
});
203 mvData
[nInsert
-1].nRow
= nStartRow
- 1;
209 optimised init-from-range-list. Specifically this is optimised for cases
210 where we have very large data columns with lots and lots of ranges.
212 void ScMarkArray::Set( std::vector
<ScMarkEntry
> && rMarkEntries
)
214 mvData
= std::move(rMarkEntries
);
217 bool ScMarkArray::IsAllMarked( SCROW nStartRow
, SCROW nEndRow
) const
222 if (Search( nStartRow
, nStartIndex
))
223 if (mvData
[nStartIndex
].bMarked
)
224 if (Search( nEndRow
, nEndIndex
))
225 if (nEndIndex
==nStartIndex
)
231 bool ScMarkArray::HasOneMark( SCROW
& rStartRow
, SCROW
& rEndRow
) const
234 if ( mvData
.size() == 1 )
236 if ( mvData
[0].bMarked
)
239 rEndRow
= mrSheetLimits
.mnMaxRow
;
243 else if ( mvData
.size() == 2 )
245 if ( mvData
[0].bMarked
)
248 rEndRow
= mvData
[0].nRow
;
252 rStartRow
= mvData
[0].nRow
+ 1;
253 rEndRow
= mrSheetLimits
.mnMaxRow
;
257 else if ( mvData
.size() == 3 )
259 if ( mvData
[1].bMarked
)
261 rStartRow
= mvData
[0].nRow
+ 1;
262 rEndRow
= mvData
[1].nRow
;
269 bool ScMarkArray::operator==( const ScMarkArray
& rOther
) const
271 return mvData
== rOther
.mvData
;
274 ScMarkArray
& ScMarkArray::operator=( const ScMarkArray
& rOther
)
276 mvData
= rOther
.mvData
;
280 ScMarkArray
& ScMarkArray::operator=(ScMarkArray
&& rOther
) noexcept
282 mvData
= std::move(rOther
.mvData
);
286 SCROW
ScMarkArray::GetNextMarked( SCROW nRow
, bool bUp
) const
289 if (mrSheetLimits
.ValidRow(nRow
))
292 Search(nRow
, nIndex
);
293 if (!mvData
[nIndex
].bMarked
)
298 nRet
= mvData
[nIndex
-1].nRow
;
303 nRet
= mvData
[nIndex
].nRow
+ 1;
309 SCROW
ScMarkArray::GetMarkEnd( SCROW nRow
, bool bUp
) const
313 Search(nRow
, nIndex
);
314 assert( mvData
[nIndex
].bMarked
&& "GetMarkEnd without bMarked" );
318 nRet
= mvData
[nIndex
-1].nRow
+ 1;
323 nRet
= mvData
[nIndex
].nRow
;
328 void ScMarkArray::Shift(SCROW nStartRow
, tools::Long nOffset
)
330 if (nOffset
== 0 || nStartRow
> mrSheetLimits
.mnMaxRow
)
333 for (size_t i
=0; i
< mvData
.size(); ++i
)
335 auto& rEntry
= mvData
[i
];
337 if (rEntry
.nRow
< nStartRow
)
339 rEntry
.nRow
+= nOffset
;
344 else if (rEntry
.nRow
> mrSheetLimits
.mnMaxRow
)
346 rEntry
.nRow
= mrSheetLimits
.mnMaxRow
;
351 // -------------- Iterator ----------------------------------------------
353 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray
* pNewArray
) :
359 void ScMarkArrayIter::reset( const ScMarkArray
* pNewArray
)
365 bool ScMarkArrayIter::Next( SCROW
& rTop
, SCROW
& rBottom
)
369 if ( nPos
>= pArray
->mvData
.size() )
371 while (!pArray
->mvData
[nPos
].bMarked
)
374 if ( nPos
>= pArray
->mvData
.size() )
377 rBottom
= pArray
->mvData
[nPos
].nRow
;
381 rTop
= pArray
->mvData
[nPos
-1].nRow
+ 1;
386 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */