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 // INCLUDE --------------------------------------------------------------- 28 29 #include <tools/table.hxx> 30 31 #include "chartpos.hxx" 32 #include "document.hxx" 33 #include "rechead.hxx" 34 35 namespace 36 { 37 bool lcl_hasValueDataButNoDates( ScDocument* pDocument, SCCOL nCol, SCROW nRow, SCTAB nTab ) 38 { 39 bool bReturn = false; 40 if (pDocument->HasValueData( nCol, nRow, nTab )) 41 { 42 //treat dates like text #i25706# 43 sal_uInt32 nNumberFormat = pDocument->GetNumberFormat( ScAddress( nCol, nRow, nTab ) ); 44 short nType = pDocument->GetFormatTable()->GetType(nNumberFormat); 45 bool bIsDate = (nType & NUMBERFORMAT_DATE); 46 bReturn = !bIsDate; 47 } 48 return bReturn; 49 } 50 } 51 52 ScChartPositioner::ScChartPositioner( ScDocument* pDoc, SCTAB nTab, 53 SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP) : 54 pDocument( pDoc ), 55 pPositionMap( NULL ), 56 eGlue( SC_CHARTGLUE_NA ), 57 nStartCol(0), 58 nStartRow(0), 59 bColHeaders( sal_False ), 60 bRowHeaders( sal_False ), 61 bDummyUpperLeft( sal_False ) 62 { 63 SetRangeList( ScRange( nStartColP, nStartRowP, nTab, nEndColP, nEndRowP, nTab ) ); 64 CheckColRowHeaders(); 65 } 66 67 ScChartPositioner::ScChartPositioner( ScDocument* pDoc, const ScRangeListRef& rRangeList ) : 68 aRangeListRef( rRangeList ), 69 pDocument( pDoc ), 70 pPositionMap( NULL ), 71 eGlue( SC_CHARTGLUE_NA ), 72 nStartCol(0), 73 nStartRow(0), 74 bColHeaders( sal_False ), 75 bRowHeaders( sal_False ), 76 bDummyUpperLeft( sal_False ) 77 { 78 if ( aRangeListRef.Is() ) 79 CheckColRowHeaders(); 80 } 81 82 ScChartPositioner::ScChartPositioner( const ScChartPositioner& rPositioner ) : 83 aRangeListRef( rPositioner.aRangeListRef ), 84 pDocument(rPositioner.pDocument), 85 pPositionMap( NULL ), 86 eGlue(rPositioner.eGlue), 87 nStartCol(rPositioner.nStartCol), 88 nStartRow(rPositioner.nStartRow), 89 bColHeaders(rPositioner.bColHeaders), 90 bRowHeaders(rPositioner.bRowHeaders), 91 bDummyUpperLeft( rPositioner.bDummyUpperLeft ) 92 { 93 } 94 95 ScChartPositioner::~ScChartPositioner() 96 { 97 delete pPositionMap; 98 } 99 100 sal_Bool ScChartPositioner::operator==(const ScChartPositioner& rCmp) const 101 { 102 return bColHeaders == rCmp.bColHeaders 103 && bRowHeaders == rCmp.bRowHeaders 104 && *aRangeListRef == *rCmp.aRangeListRef; 105 } 106 107 void ScChartPositioner::SetRangeList( const ScRange& rRange ) 108 { 109 aRangeListRef = new ScRangeList; 110 aRangeListRef->Append( rRange ); 111 InvalidateGlue(); 112 } 113 114 void ScChartPositioner::GlueState() 115 { 116 if ( eGlue != SC_CHARTGLUE_NA ) 117 return; 118 bDummyUpperLeft = sal_False; 119 ScRangePtr pR; 120 if ( aRangeListRef->Count() <= 1 ) 121 { 122 if ( (pR = aRangeListRef->First())!=NULL ) 123 { 124 if ( pR->aStart.Tab() == pR->aEnd.Tab() ) 125 eGlue = SC_CHARTGLUE_NONE; 126 else 127 eGlue = SC_CHARTGLUE_COLS; // mehrere Tabellen spaltenweise 128 nStartCol = pR->aStart.Col(); 129 nStartRow = pR->aStart.Row(); 130 } 131 else 132 { 133 InvalidateGlue(); 134 nStartCol = 0; 135 nStartRow = 0; 136 } 137 return; 138 } 139 // sal_uLong nOldPos = aRangeListRef->GetCurPos(); 140 141 pR = aRangeListRef->First(); 142 nStartCol = pR->aStart.Col(); 143 nStartRow = pR->aStart.Row(); 144 SCCOL nMaxCols, nEndCol; 145 SCROW nMaxRows, nEndRow; 146 nMaxCols = nEndCol = 0; 147 nMaxRows = nEndRow = 0; 148 do 149 { // umspannenden Bereich etc. feststellen 150 SCCOLROW nTmp, n1, n2; 151 if ( (n1 = pR->aStart.Col()) < nStartCol ) 152 nStartCol = static_cast<SCCOL>(n1); 153 if ( (n2 = pR->aEnd.Col()) > nEndCol ) 154 nEndCol = static_cast<SCCOL>(n2); 155 if ( (nTmp = n2 - n1 + 1) > nMaxCols ) 156 nMaxCols = static_cast<SCCOL>(nTmp); 157 if ( (n1 = pR->aStart.Row()) < nStartRow ) 158 nStartRow = static_cast<SCROW>(n1); 159 if ( (n2 = pR->aEnd.Row()) > nEndRow ) 160 nEndRow = static_cast<SCROW>(n2); 161 if ( (nTmp = n2 - n1 + 1) > nMaxRows ) 162 nMaxRows = static_cast<SCROW>(nTmp); 163 } while ( (pR = aRangeListRef->Next())!=NULL ); 164 SCCOL nC = nEndCol - nStartCol + 1; 165 if ( nC == 1 ) 166 { 167 eGlue = SC_CHARTGLUE_ROWS; 168 return; 169 } 170 SCROW nR = nEndRow - nStartRow + 1; 171 if ( nR == 1 ) 172 { 173 eGlue = SC_CHARTGLUE_COLS; 174 return; 175 } 176 sal_uLong nCR = (sal_uLong)nC * nR; 177 //2do: 178 /* 179 Erstmal simpel ohne Bitmaskiererei, maximal koennten so 8MB alloziert 180 werden (256 Cols mal 32000 Rows), das liesse sich mit 2 Bit je Eintrag 181 auf 2MB reduzieren, andererseits ist es so schneller. 182 Weitere Platz-Optimierung waere, in dem Array nur die wirklich benutzten 183 Zeilen/Spalten abzulegen, wuerde aber ein weiteres durchlaufen der 184 RangeList und indirekten Zugriff auf das Array bedeuten. 185 */ 186 const sal_uInt8 nHole = 0; 187 const sal_uInt8 nOccu = 1; 188 const sal_uInt8 nFree = 2; 189 const sal_uInt8 nGlue = 3; 190 sal_uInt8* p; 191 sal_uInt8* pA = new sal_uInt8[ nCR ]; 192 memset( pA, 0, nCR * sizeof(sal_uInt8) ); 193 194 SCCOL nCol, nCol1, nCol2; 195 SCROW nRow, nRow1, nRow2; 196 for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() ) 197 { // Selektionen 2D als belegt markieren 198 nCol1 = pR->aStart.Col() - nStartCol; 199 nCol2 = pR->aEnd.Col() - nStartCol; 200 nRow1 = pR->aStart.Row() - nStartRow; 201 nRow2 = pR->aEnd.Row() - nStartRow; 202 for ( nCol = nCol1; nCol <= nCol2; nCol++ ) 203 { 204 p = pA + (sal_uLong)nCol * nR + nRow1; 205 for ( nRow = nRow1; nRow <= nRow2; nRow++, p++ ) 206 *p = nOccu; 207 } 208 } 209 sal_Bool bGlue = sal_True; 210 211 sal_Bool bGlueCols = sal_False; 212 for ( nCol = 0; bGlue && nCol < nC; nCol++ ) 213 { // Spalten probieren durchzugehen und als frei markieren 214 p = pA + (sal_uLong)nCol * nR; 215 for ( nRow = 0; bGlue && nRow < nR; nRow++, p++ ) 216 { 217 if ( *p == nOccu ) 218 { // Wenn einer mittendrin liegt ist keine Zusammenfassung 219 // moeglich. Am Rand koennte ok sein, wenn in dieser Spalte 220 // in jeder belegten Zeile einer belegt ist. 221 if ( nRow > 0 && nCol > 0 ) 222 bGlue = sal_False; // nCol==0 kann DummyUpperLeft sein 223 else 224 nRow = nR; 225 } 226 else 227 *p = nFree; 228 } 229 if ( bGlue && *(p = (pA + ((((sal_uLong)nCol+1) * nR) - 1))) == nFree ) 230 { // Spalte als komplett frei markieren 231 *p = nGlue; 232 bGlueCols = sal_True; // mindestens eine freie Spalte 233 } 234 } 235 236 sal_Bool bGlueRows = sal_False; 237 for ( nRow = 0; bGlue && nRow < nR; nRow++ ) 238 { // Zeilen probieren durchzugehen und als frei markieren 239 p = pA + nRow; 240 for ( nCol = 0; bGlue && nCol < nC; nCol++, p+=nR ) 241 { 242 if ( *p == nOccu ) 243 { 244 if ( nCol > 0 && nRow > 0 ) 245 bGlue = sal_False; // nRow==0 kann DummyUpperLeft sein 246 else 247 nCol = nC; 248 } 249 else 250 *p = nFree; 251 } 252 if ( bGlue && *(p = (pA + ((((sal_uLong)nC-1) * nR) + nRow))) == nFree ) 253 { // Zeile als komplett frei markieren 254 *p = nGlue; 255 bGlueRows = sal_True; // mindestens eine freie Zeile 256 } 257 } 258 259 // n=1: die linke obere Ecke koennte bei Beschriftung automagisch 260 // hinzugezogen werden 261 p = pA + 1; 262 for ( sal_uLong n = 1; bGlue && n < nCR; n++, p++ ) 263 { // ein unberuehrtes Feld heisst, dass es weder spaltenweise noch 264 // zeilenweise zu erreichen war, also nichts zusamenzufassen 265 if ( *p == nHole ) 266 bGlue = sal_False; 267 } 268 if ( bGlue ) 269 { 270 if ( bGlueCols && bGlueRows ) 271 eGlue = SC_CHARTGLUE_BOTH; 272 else if ( bGlueRows ) 273 eGlue = SC_CHARTGLUE_ROWS; 274 else 275 eGlue = SC_CHARTGLUE_COLS; 276 if ( *pA != nOccu ) 277 bDummyUpperLeft = sal_True; 278 } 279 else 280 { 281 eGlue = SC_CHARTGLUE_NONE; 282 } 283 284 delete [] pA; 285 } 286 287 void ScChartPositioner::CheckColRowHeaders() 288 { 289 SCCOL nCol1, nCol2, iCol; 290 SCROW nRow1, nRow2, iRow; 291 SCTAB nTab1, nTab2; 292 293 sal_Bool bColStrings = sal_True; 294 sal_Bool bRowStrings = sal_True; 295 GlueState(); 296 if ( aRangeListRef->Count() == 1 ) 297 { 298 aRangeListRef->First()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 299 if ( nCol1 > nCol2 || nRow1 > nRow2 ) 300 bColStrings = bRowStrings = sal_False; 301 else 302 { 303 for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++) 304 { 305 if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 )) 306 bColStrings = sal_False; 307 } 308 for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++) 309 { 310 if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 )) 311 bRowStrings = sal_False; 312 } 313 } 314 } 315 else 316 { 317 sal_Bool bVert = (eGlue == SC_CHARTGLUE_NONE || eGlue == SC_CHARTGLUE_ROWS); 318 for ( ScRangePtr pR = aRangeListRef->First(); 319 pR && (bColStrings || bRowStrings); 320 pR = aRangeListRef->Next() ) 321 { 322 pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 323 sal_Bool bTopRow = (nRow1 == nStartRow); 324 if ( bRowStrings && (bVert || nCol1 == nStartCol) ) 325 { // NONE oder ROWS: RowStrings in jeder Selektion moeglich 326 // COLS oder BOTH: nur aus der ersten Spalte 327 if ( nCol1 <= nCol2 ) 328 for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++) 329 { 330 if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 )) 331 bRowStrings = sal_False; 332 } 333 } 334 if ( bColStrings && bTopRow ) 335 { // ColStrings nur aus der ersten Zeile 336 if ( nRow1 <= nRow2 ) 337 for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++) 338 { 339 if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 )) 340 bColStrings = sal_False; 341 } 342 } 343 } 344 } 345 bColHeaders = bColStrings; 346 bRowHeaders = bRowStrings; 347 } 348 349 const ScChartPositionMap* ScChartPositioner::GetPositionMap() 350 { 351 CreatePositionMap(); 352 return pPositionMap; 353 } 354 355 356 void ScChartPositioner::CreatePositionMap() 357 { 358 if ( eGlue == SC_CHARTGLUE_NA && pPositionMap ) 359 { 360 delete pPositionMap; 361 pPositionMap = NULL; 362 } 363 364 if ( pPositionMap ) 365 return ; 366 367 SCSIZE nColAdd = bRowHeaders ? 1 : 0; 368 SCSIZE nRowAdd = bColHeaders ? 1 : 0; 369 370 SCCOL nCol, nCol1, nCol2; 371 SCROW nRow, nRow1, nRow2; 372 SCTAB nTab, nTab1, nTab2; 373 374 // 375 // wirkliche Groesse (ohne versteckte Zeilen/Spalten) 376 // 377 378 SCSIZE nColCount = 0; 379 SCSIZE nRowCount = 0; 380 381 GlueState(); 382 383 sal_Bool bNoGlue = (eGlue == SC_CHARTGLUE_NONE); 384 Table* pCols = new Table; 385 Table* pNewRowTable = new Table; 386 ScAddress* pNewAddress = new ScAddress; 387 ScRangePtr pR; 388 Table* pCol; 389 ScAddress* pPos; 390 SCROW nNoGlueRow = 0; 391 for ( pR = aRangeListRef->First(); pR; pR = aRangeListRef->Next() ) 392 { 393 pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); 394 for ( nTab = nTab1; nTab <= nTab2; nTab++ ) 395 { 396 // nTab im ColKey, um gleiche Col/Row in anderer Table haben zu koennen 397 sal_uLong nInsCol = (static_cast<sal_uLong>(nTab) << 16) | (bNoGlue ? 0 : 398 static_cast<sal_uLong>(nCol1)); 399 for ( nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol ) 400 { 401 if ( bNoGlue || eGlue == SC_CHARTGLUE_ROWS ) 402 { // meistens gleiche Cols 403 if ( (pCol = (Table*) pCols->Get( nInsCol ))==NULL ) 404 { 405 pCols->Insert( nInsCol, pNewRowTable ); 406 pCol = pNewRowTable; 407 pNewRowTable = new Table; 408 } 409 } 410 else 411 { // meistens neue Cols 412 if ( pCols->Insert( nInsCol, pNewRowTable ) ) 413 { 414 pCol = pNewRowTable; 415 pNewRowTable = new Table; 416 } 417 else 418 pCol = (Table*) pCols->Get( nInsCol ); 419 } 420 // bei anderer Tabelle wurde bereits neuer ColKey erzeugt, 421 // die Zeilen muessen fuer's Dummy fuellen gleich sein! 422 sal_uLong nInsRow = (bNoGlue ? nNoGlueRow : nRow1); 423 for ( nRow = nRow1; nRow <= nRow2; nRow++, nInsRow++ ) 424 { 425 if ( pCol->Insert( nInsRow, pNewAddress ) ) 426 { 427 pNewAddress->Set( nCol, nRow, nTab ); 428 pNewAddress = new ScAddress; 429 } 430 } 431 } 432 } 433 // bei NoGlue werden zusammengehoerige Tabellen als ColGlue dargestellt 434 nNoGlueRow += nRow2 - nRow1 + 1; 435 } 436 delete pNewAddress; 437 delete pNewRowTable; 438 439 // Anzahl der Daten 440 nColCount = static_cast< SCSIZE >( pCols->Count()); 441 if ( (pCol = (Table*) pCols->First())!=NULL ) 442 { 443 if ( bDummyUpperLeft ) 444 pCol->Insert( 0, (void*)0 ); // Dummy fuer Beschriftung 445 nRowCount = static_cast< SCSIZE >( pCol->Count()); 446 } 447 else 448 nRowCount = 0; 449 if ( nColCount > 0 ) 450 nColCount -= nColAdd; 451 if ( nRowCount > 0 ) 452 nRowCount -= nRowAdd; 453 454 if ( nColCount==0 || nRowCount==0 ) 455 { // einen Eintrag ohne Daten erzeugen 456 pR = aRangeListRef->First(); 457 if ( pCols->Count() > 0 ) 458 pCol = (Table*) pCols->First(); 459 else 460 { 461 pCol = new Table; 462 pCols->Insert( 0, pCol ); 463 } 464 nColCount = 1; 465 if ( pCol->Count() > 0 ) 466 { // kann ja eigentlich nicht sein, wenn nColCount==0 || nRowCount==0 467 pPos = (ScAddress*) pCol->First(); 468 if ( pPos ) 469 { 470 delete pPos; 471 pCol->Replace( pCol->GetCurKey(), (void*)0 ); 472 } 473 } 474 else 475 pCol->Insert( 0, (void*)0 ); 476 nRowCount = 1; 477 nColAdd = 0; 478 nRowAdd = 0; 479 } 480 else 481 { 482 if ( bNoGlue ) 483 { // Luecken mit Dummies fuellen, erste Spalte ist Master 484 Table* pFirstCol = (Table*) pCols->First(); 485 sal_uLong nCount = pFirstCol->Count(); 486 pFirstCol->First(); 487 for ( sal_uLong n = 0; n < nCount; n++, pFirstCol->Next() ) 488 { 489 sal_uLong nKey = pFirstCol->GetCurKey(); 490 pCols->First(); 491 while ( (pCol = (Table*) pCols->Next())!=NULL ) 492 pCol->Insert( nKey, (void*)0 ); // keine Daten 493 } 494 } 495 } 496 497 pPositionMap = new ScChartPositionMap( static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount), 498 static_cast<SCCOL>(nColAdd), static_cast<SCROW>(nRowAdd), *pCols ); 499 500 // Aufraeumen 501 for ( pCol = (Table*) pCols->First(); pCol; pCol = (Table*) pCols->Next() ) 502 { //! nur Tables loeschen, nicht die ScAddress* 503 delete pCol; 504 } 505 delete pCols; 506 } 507 508 509 ScChartPositionMap::ScChartPositionMap( SCCOL nChartCols, SCROW nChartRows, 510 SCCOL nColAdd, SCROW nRowAdd, Table& rCols ) : 511 ppData( new ScAddress* [ nChartCols * nChartRows ] ), 512 ppColHeader( new ScAddress* [ nChartCols ] ), 513 ppRowHeader( new ScAddress* [ nChartRows ] ), 514 nCount( (sal_uLong) nChartCols * nChartRows ), 515 nColCount( nChartCols ), 516 nRowCount( nChartRows ) 517 { 518 DBG_ASSERT( nColCount && nRowCount, "ScChartPositionMap without dimension" ); 519 520 ScAddress* pPos; 521 SCCOL nCol; 522 SCROW nRow; 523 524 Table* pCol = (Table*) rCols.First(); 525 526 // Zeilen-Header 527 pPos = (ScAddress*) pCol->First(); 528 if ( nRowAdd ) 529 pPos = (ScAddress*) pCol->Next(); 530 if ( nColAdd ) 531 { // eigenstaendig 532 for ( nRow = 0; nRow < nRowCount; nRow++ ) 533 { 534 ppRowHeader[ nRow ] = pPos; 535 pPos = (ScAddress*) pCol->Next(); 536 } 537 } 538 else 539 { // Kopie 540 for ( nRow = 0; nRow < nRowCount; nRow++ ) 541 { 542 ppRowHeader[ nRow ] = ( pPos ? new ScAddress( *pPos ) : NULL ); 543 pPos = (ScAddress*) pCol->Next(); 544 } 545 } 546 if ( nColAdd ) 547 pCol = (Table*) rCols.Next(); 548 549 // Daten spaltenweise und Spalten-Header 550 sal_uLong nIndex = 0; 551 for ( nCol = 0; nCol < nColCount; nCol++ ) 552 { 553 if ( pCol ) 554 { 555 pPos = (ScAddress*) pCol->First(); 556 if ( nRowAdd ) 557 { 558 ppColHeader[ nCol ] = pPos; // eigenstaendig 559 pPos = (ScAddress*) pCol->Next(); 560 } 561 else 562 ppColHeader[ nCol ] = ( pPos ? new ScAddress( *pPos ) : NULL ); 563 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ ) 564 { 565 ppData[ nIndex ] = pPos; 566 pPos = (ScAddress*) pCol->Next(); 567 } 568 } 569 else 570 { 571 ppColHeader[ nCol ] = NULL; 572 for ( nRow = 0; nRow < nRowCount; nRow++, nIndex++ ) 573 { 574 ppData[ nIndex ] = NULL; 575 } 576 } 577 pCol = (Table*) rCols.Next(); 578 } 579 } 580 581 582 ScChartPositionMap::~ScChartPositionMap() 583 { 584 for ( sal_uLong nIndex=0; nIndex < nCount; nIndex++ ) 585 { 586 delete ppData[nIndex]; 587 } 588 delete [] ppData; 589 590 SCCOL j; 591 for ( j=0; j < nColCount; j++ ) 592 { 593 delete ppColHeader[j]; 594 } 595 delete [] ppColHeader; 596 SCROW i; 597 for ( i=0; i < nRowCount; i++ ) 598 { 599 delete ppRowHeader[i]; 600 } 601 delete [] ppRowHeader; 602 } 603 604 605 //UNUSED2009-05 ScRangeListRef ScChartPositionMap::GetColRanges( SCCOL nChartCol ) const 606 //UNUSED2009-05 { 607 //UNUSED2009-05 ScRangeListRef xRangeList = new ScRangeList; 608 //UNUSED2009-05 if ( nChartCol < nColCount ) 609 //UNUSED2009-05 { 610 //UNUSED2009-05 sal_uLong nStop = GetIndex( nChartCol, nRowCount ); 611 //UNUSED2009-05 for ( sal_uLong nIndex = GetIndex( nChartCol, 0 ); nIndex < nStop; nIndex++ ) 612 //UNUSED2009-05 { 613 //UNUSED2009-05 if ( ppData[ nIndex ] ) 614 //UNUSED2009-05 xRangeList->Join( *ppData[ nIndex ] ); 615 //UNUSED2009-05 } 616 //UNUSED2009-05 } 617 //UNUSED2009-05 return xRangeList; 618 //UNUSED2009-05 } 619 620 621 //UNUSED2009-05 ScRangeListRef ScChartPositionMap::GetRowRanges( SCROW nChartRow ) const 622 //UNUSED2009-05 { 623 //UNUSED2009-05 ScRangeListRef xRangeList = new ScRangeList; 624 //UNUSED2009-05 if ( nChartRow < nRowCount ) 625 //UNUSED2009-05 { 626 //UNUSED2009-05 sal_uLong nStop = GetIndex( nColCount, nChartRow ); 627 //UNUSED2009-05 for ( sal_uLong nIndex = GetIndex( 0, nChartRow ); nIndex < nStop; 628 //UNUSED2009-05 nIndex += nRowCount ) 629 //UNUSED2009-05 { 630 //UNUSED2009-05 if ( ppData[ nIndex ] ) 631 //UNUSED2009-05 xRangeList->Join( *ppData[ nIndex ] ); 632 //UNUSED2009-05 } 633 //UNUSED2009-05 } 634 //UNUSED2009-05 return xRangeList; 635 //UNUSED2009-05 } 636