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