xref: /AOO41X/main/sc/source/core/tool/chartpos.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 // INCLUDE ---------------------------------------------------------------
28 
29 #include <tools/table.hxx>
30 
31 #include "chartpos.hxx"
32 #include "document.hxx"
33 #include "rechead.hxx"
34 
35 namespace
36 {
lcl_hasValueDataButNoDates(ScDocument * pDocument,SCCOL nCol,SCROW nRow,SCTAB nTab)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 
ScChartPositioner(ScDocument * pDoc,SCTAB nTab,SCCOL nStartColP,SCROW nStartRowP,SCCOL nEndColP,SCROW nEndRowP)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 
ScChartPositioner(ScDocument * pDoc,const ScRangeListRef & rRangeList)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 
ScChartPositioner(const ScChartPositioner & rPositioner)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 
~ScChartPositioner()95 ScChartPositioner::~ScChartPositioner()
96 {
97     delete pPositionMap;
98 }
99 
operator ==(const ScChartPositioner & rCmp) const100 sal_Bool ScChartPositioner::operator==(const ScChartPositioner& rCmp) const
101 {
102     return bColHeaders == rCmp.bColHeaders
103         && bRowHeaders == rCmp.bRowHeaders
104         && *aRangeListRef == *rCmp.aRangeListRef;
105 }
106 
SetRangeList(const ScRange & rRange)107 void ScChartPositioner::SetRangeList( const ScRange& rRange )
108 {
109     aRangeListRef = new ScRangeList;
110     aRangeListRef->Append( rRange );
111     InvalidateGlue();
112 }
113 
GlueState()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 
CheckColRowHeaders()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 
GetPositionMap()349 const ScChartPositionMap* ScChartPositioner::GetPositionMap()
350 {
351     CreatePositionMap();
352     return pPositionMap;
353 }
354 
355 
CreatePositionMap()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 
ScChartPositionMap(SCCOL nChartCols,SCROW nChartRows,SCCOL nColAdd,SCROW nRowAdd,Table & rCols)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 
~ScChartPositionMap()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