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 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 51 ScMarkArray::~ScMarkArray() 52 { 53 delete[] pData; 54 } 55 56 //------------------------------------------------------------------------ 57 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 73 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 110 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 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 255 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 269 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 307 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 322 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 348 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 374 ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) : 375 pArray( pNewArray ), 376 nPos( 0 ) 377 { 378 } 379 380 ScMarkArrayIter::~ScMarkArrayIter() 381 { 382 } 383 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