xref: /AOO41X/main/sc/source/core/data/markarr.cxx (revision b3f79822e811ac3493b185030a72c3c5a51f32d8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 // INCLUDE ---------------------------------------------------------------
30 
31 #include <tools/debug.hxx>
32 
33 #include "markarr.hxx"
34 #include "global.hxx"
35 #include "address.hxx"
36 
37 // STATIC DATA -----------------------------------------------------------
38 
39 //------------------------------------------------------------------------
40 
ScMarkArray()41 ScMarkArray::ScMarkArray() :
42     nCount( 0 ),
43     nLimit( 0 ),
44     pData( NULL )
45 {
46     // special case "no marks" with pData = NULL
47 }
48 
49 //------------------------------------------------------------------------
50 
~ScMarkArray()51 ScMarkArray::~ScMarkArray()
52 {
53     delete[] pData;
54 }
55 
56 //------------------------------------------------------------------------
57 
Reset(sal_Bool bMarked)58 void ScMarkArray::Reset( sal_Bool bMarked )
59 {
60     // always create pData here
61     // (or have separate method to ensure pData)
62 
63     delete[] pData;
64 
65     nCount = nLimit = 1;
66     pData = new ScMarkEntry[1];
67     pData[0].nRow = MAXROW;
68     pData[0].bMarked = bMarked;
69 }
70 
71 //------------------------------------------------------------------------
72 
Search(SCROW nRow,SCSIZE & nIndex) const73 sal_Bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
74 {
75     long    nLo         = 0;
76     long    nHi         = static_cast<long>(nCount) - 1;
77     long    nStartRow   = 0;
78     long    nEndRow     = 0;
79     long    i           = 0;
80     sal_Bool    bFound      = (nCount == 1);
81     if (pData)
82     {
83         while ( !bFound && nLo <= nHi )
84         {
85             i = (nLo + nHi) / 2;
86             if (i > 0)
87                 nStartRow = (long) pData[i - 1].nRow;
88             else
89                 nStartRow = -1;
90             nEndRow = (long) pData[i].nRow;
91             if (nEndRow < (long) nRow)
92                 nLo = ++i;
93             else
94                 if (nStartRow >= (long) nRow)
95                     nHi = --i;
96                 else
97                     bFound = sal_True;
98         }
99     }
100     else
101         bFound = sal_False;
102 
103     if (bFound)
104         nIndex=(SCSIZE)i;
105     else
106         nIndex=0;
107     return bFound;
108 }
109 
GetMark(SCROW nRow) const110 sal_Bool ScMarkArray::GetMark( SCROW nRow ) const
111 {
112     SCSIZE i;
113     if (Search( nRow, i ))
114         return pData[i].bMarked;
115     else
116         return sal_False;
117 
118 }
119 
120 //------------------------------------------------------------------------
121 
SetMarkArea(SCROW nStartRow,SCROW nEndRow,sal_Bool bMarked)122 void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, sal_Bool bMarked )
123 {
124     if (ValidRow(nStartRow) && ValidRow(nEndRow))
125     {
126         if ((nStartRow == 0) && (nEndRow == MAXROW))
127         {
128             Reset(bMarked);
129         }
130         else
131         {
132             if (!pData)
133                 Reset(sal_False);   // create pData for further processing - could use special case handling!
134 
135             SCSIZE nNeeded = nCount + 2;
136             if ( nLimit < nNeeded )
137             {
138                 nLimit += SC_MARKARRAY_DELTA;
139                 if ( nLimit < nNeeded )
140                     nLimit = nNeeded;
141                 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
142                 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
143                 delete[] pData;
144                 pData = pNewData;
145             }
146 
147             SCSIZE ni;          // number of entries in beginning
148             SCSIZE nInsert;     // insert position (MAXROW+1 := no insert)
149             sal_Bool bCombined = sal_False;
150             sal_Bool bSplit = sal_False;
151             if ( nStartRow > 0 )
152             {
153                 // skip beginning
154                 SCSIZE nIndex;
155                 Search( nStartRow, nIndex );
156                 ni = nIndex;
157 
158                 nInsert = MAXROWCOUNT;
159                 if ( pData[ni].bMarked != bMarked )
160                 {
161                     if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
162                     {   // may be a split or a simple insert or just a shrink,
163                         // row adjustment is done further down
164                         if ( pData[ni].nRow > nEndRow )
165                             bSplit = sal_True;
166                         ni++;
167                         nInsert = ni;
168                     }
169                     else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
170                         nInsert = ni;
171                 }
172                 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
173                 {   // combine
174                     pData[ni-1].nRow = nEndRow;
175                     nInsert = MAXROWCOUNT;
176                     bCombined = sal_True;
177                 }
178             }
179             else
180         {
181                 nInsert = 0;
182                 ni = 0;
183         }
184 
185             SCSIZE nj = ni;     // stop position of range to replace
186             while ( nj < nCount && pData[nj].nRow <= nEndRow )
187                 nj++;
188             if ( !bSplit )
189             {
190                 if ( nj < nCount && pData[nj].bMarked == bMarked )
191                 {   // combine
192                     if ( ni > 0 )
193                     {
194                         if ( pData[ni-1].bMarked == bMarked )
195                         {   // adjacent entries
196                             pData[ni-1].nRow = pData[nj].nRow;
197                             nj++;
198                         }
199                         else if ( ni == nInsert )
200                             pData[ni-1].nRow = nStartRow - 1;   // shrink
201                     }
202                     nInsert = MAXROWCOUNT;
203                     bCombined = sal_True;
204                 }
205                 else if ( ni > 0 && ni == nInsert )
206                     pData[ni-1].nRow = nStartRow - 1;   // shrink
207             }
208             if ( ni < nj )
209             {   // remove middle entries
210                 if ( !bCombined )
211                 {   // replace one entry
212                     pData[ni].nRow = nEndRow;
213                     pData[ni].bMarked = bMarked;
214                     ni++;
215                     nInsert = MAXROWCOUNT;
216                 }
217                 if ( ni < nj )
218                 {   // remove entries
219                     memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
220                     nCount -= nj - ni;
221                 }
222             }
223 
224             if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
225             {   // insert or append new entry
226                 if ( nInsert <= nCount )
227                 {
228                     if ( !bSplit )
229                         memmove( pData + nInsert + 1, pData + nInsert,
230                             (nCount - nInsert) * sizeof(ScMarkEntry) );
231                     else
232                     {
233                         memmove( pData + nInsert + 2, pData + nInsert,
234                             (nCount - nInsert) * sizeof(ScMarkEntry) );
235                         pData[nInsert+1] = pData[nInsert-1];
236                         nCount++;
237                     }
238                 }
239                 if ( nInsert )
240                     pData[nInsert-1].nRow = nStartRow - 1;
241                 pData[nInsert].nRow = nEndRow;
242                 pData[nInsert].bMarked = bMarked;
243                 nCount++;
244             }
245         }
246     }
247 //  InfoBox(0, String(nCount) + String(" Eintraege") ).Execute();
248 }
249 
250 //UNUSED2009-05 void ScMarkArray::DeleteArea(SCROW nStartRow, SCROW nEndRow)
251 //UNUSED2009-05 {
252 //UNUSED2009-05     SetMarkArea(nStartRow, nEndRow, sal_False);
253 //UNUSED2009-05 }
254 
IsAllMarked(SCROW nStartRow,SCROW nEndRow) const255 sal_Bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
256 {
257     SCSIZE nStartIndex;
258     SCSIZE nEndIndex;
259 
260     if (Search( nStartRow, nStartIndex ))
261         if (pData[nStartIndex].bMarked)
262             if (Search( nEndRow, nEndIndex ))
263                 if (nEndIndex==nStartIndex)
264                     return sal_True;
265 
266     return sal_False;
267 }
268 
HasOneMark(SCROW & rStartRow,SCROW & rEndRow) const269 sal_Bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
270 {
271     sal_Bool bRet = sal_False;
272     if ( nCount == 1 )
273     {
274         if ( pData[0].bMarked )
275         {
276             rStartRow = 0;
277             rEndRow = MAXROW;
278             bRet = sal_True;
279         }
280     }
281     else if ( nCount == 2 )
282     {
283         if ( pData[0].bMarked )
284         {
285             rStartRow = 0;
286             rEndRow = pData[0].nRow;
287         }
288         else
289         {
290             rStartRow = pData[0].nRow + 1;
291             rEndRow = MAXROW;
292         }
293         bRet = sal_True;
294     }
295     else if ( nCount == 3 )
296     {
297         if ( pData[1].bMarked )
298         {
299             rStartRow = pData[0].nRow + 1;
300             rEndRow = pData[1].nRow;
301             bRet = sal_True;
302         }
303     }
304     return bRet;
305 }
306 
CopyMarksTo(ScMarkArray & rDestMarkArray) const307 void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
308 {
309     delete[] rDestMarkArray.pData;
310 
311     if (pData)
312     {
313         rDestMarkArray.pData = new ScMarkEntry[nCount];
314         memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
315     }
316     else
317         rDestMarkArray.pData = NULL;
318 
319     rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
320 }
321 
GetNextMarked(SCsROW nRow,sal_Bool bUp) const322 SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, sal_Bool bUp ) const
323 {
324     if (!pData)
325         const_cast<ScMarkArray*>(this)->Reset(sal_False);   // create pData for further processing
326 
327     SCsROW nRet = nRow;
328     if (VALIDROW(nRow))
329     {
330         SCSIZE nIndex;
331         Search(nRow, nIndex);
332         if (!pData[nIndex].bMarked)
333         {
334             if (bUp)
335             {
336                 if (nIndex>0)
337                     nRet = pData[nIndex-1].nRow;
338                 else
339                     nRet = -1;
340             }
341             else
342                 nRet = pData[nIndex].nRow + 1;
343         }
344     }
345     return nRet;
346 }
347 
GetMarkEnd(SCROW nRow,sal_Bool bUp) const348 SCROW ScMarkArray::GetMarkEnd( SCROW nRow, sal_Bool bUp ) const
349 {
350     if (!pData)
351         const_cast<ScMarkArray*>(this)->Reset(sal_False);   // create pData for further processing
352 
353     SCROW nRet;
354     SCSIZE nIndex;
355     Search(nRow, nIndex);
356     DBG_ASSERT( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
357     if (bUp)
358     {
359         if (nIndex>0)
360             nRet = pData[nIndex-1].nRow + 1;
361         else
362             nRet = 0;
363     }
364     else
365         nRet = pData[nIndex].nRow;
366 
367     return nRet;
368 }
369 
370 //
371 //  -------------- Iterator ----------------------------------------------
372 //
373 
ScMarkArrayIter(const ScMarkArray * pNewArray)374 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
375     pArray( pNewArray ),
376     nPos( 0 )
377 {
378 }
379 
~ScMarkArrayIter()380 ScMarkArrayIter::~ScMarkArrayIter()
381 {
382 }
383 
Next(SCROW & rTop,SCROW & rBottom)384 sal_Bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
385 {
386     if ( nPos >= pArray->nCount )
387         return sal_False;
388     while (!pArray->pData[nPos].bMarked)
389     {
390         ++nPos;
391         if ( nPos >= pArray->nCount )
392             return sal_False;
393     }
394     rBottom = pArray->pData[nPos].nRow;
395     if (nPos==0)
396         rTop = 0;
397     else
398         rTop = pArray->pData[nPos-1].nRow + 1;
399     ++nPos;
400     return sal_True;
401 }
402 
403 
404 
405 
406 
407