xref: /trunk/main/sc/source/core/tool/chartpos.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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