Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "chartpos.hxx"
21 : #include "document.hxx"
22 : #include "rechead.hxx"
23 : #include <osl/diagnose.h>
24 :
25 : #include <boost/scoped_array.hpp>
26 :
27 : namespace
28 : {
29 276 : bool lcl_hasValueDataButNoDates( ScDocument* pDocument, SCCOL nCol, SCROW nRow, SCTAB nTab )
30 : {
31 276 : bool bReturn = false;
32 276 : if (pDocument->HasValueData( nCol, nRow, nTab ))
33 : {
34 : //treat dates like text #i25706#
35 13 : sal_uInt32 nNumberFormat = pDocument->GetNumberFormat( ScAddress( nCol, nRow, nTab ) );
36 13 : short nType = pDocument->GetFormatTable()->GetType(nNumberFormat);
37 13 : bool bIsDate = (nType & css::util::NumberFormat::DATE);
38 13 : bReturn = !bIsDate;
39 : }
40 276 : return bReturn;
41 : }
42 : }
43 :
44 0 : ScChartPositioner::ScChartPositioner( ScDocument* pDoc, SCTAB nTab,
45 : SCCOL nStartColP, SCROW nStartRowP, SCCOL nEndColP, SCROW nEndRowP) :
46 : pDocument( pDoc ),
47 : pPositionMap( NULL ),
48 : eGlue( SC_CHARTGLUE_NA ),
49 : nStartCol(0),
50 : nStartRow(0),
51 : bColHeaders( false ),
52 : bRowHeaders( false ),
53 0 : bDummyUpperLeft( false )
54 : {
55 0 : SetRangeList( ScRange( nStartColP, nStartRowP, nTab, nEndColP, nEndRowP, nTab ) );
56 0 : CheckColRowHeaders();
57 0 : }
58 :
59 26 : ScChartPositioner::ScChartPositioner( ScDocument* pDoc, const ScRangeListRef& rRangeList ) :
60 : aRangeListRef( rRangeList ),
61 : pDocument( pDoc ),
62 : pPositionMap( NULL ),
63 : eGlue( SC_CHARTGLUE_NA ),
64 : nStartCol(0),
65 : nStartRow(0),
66 : bColHeaders( false ),
67 : bRowHeaders( false ),
68 26 : bDummyUpperLeft( false )
69 : {
70 26 : if ( aRangeListRef.Is() )
71 26 : CheckColRowHeaders();
72 26 : }
73 :
74 0 : ScChartPositioner::ScChartPositioner( const ScChartPositioner& rPositioner ) :
75 : aRangeListRef( rPositioner.aRangeListRef ),
76 : pDocument(rPositioner.pDocument),
77 : pPositionMap( NULL ),
78 : eGlue(rPositioner.eGlue),
79 : nStartCol(rPositioner.nStartCol),
80 : nStartRow(rPositioner.nStartRow),
81 : bColHeaders(rPositioner.bColHeaders),
82 : bRowHeaders(rPositioner.bRowHeaders),
83 0 : bDummyUpperLeft( rPositioner.bDummyUpperLeft )
84 : {
85 0 : }
86 :
87 52 : ScChartPositioner::~ScChartPositioner()
88 : {
89 26 : delete pPositionMap;
90 26 : }
91 :
92 0 : bool ScChartPositioner::operator==(const ScChartPositioner& rCmp) const
93 : {
94 0 : return bColHeaders == rCmp.bColHeaders
95 0 : && bRowHeaders == rCmp.bRowHeaders
96 0 : && *aRangeListRef == *rCmp.aRangeListRef;
97 : }
98 :
99 0 : void ScChartPositioner::SetRangeList( const ScRange& rRange )
100 : {
101 0 : aRangeListRef = new ScRangeList;
102 0 : aRangeListRef->Append( rRange );
103 0 : InvalidateGlue();
104 0 : }
105 :
106 44 : void ScChartPositioner::GlueState()
107 : {
108 44 : if ( eGlue != SC_CHARTGLUE_NA )
109 47 : return;
110 26 : bDummyUpperLeft = false;
111 : ScRange* pR;
112 26 : if ( aRangeListRef->size() <= 1 )
113 : {
114 11 : if ( !aRangeListRef->empty() )
115 : {
116 11 : pR = aRangeListRef->front();
117 11 : if ( pR->aStart.Tab() == pR->aEnd.Tab() )
118 11 : eGlue = SC_CHARTGLUE_NONE;
119 : else
120 0 : eGlue = SC_CHARTGLUE_COLS; // several tables column by column
121 11 : nStartCol = pR->aStart.Col();
122 11 : nStartRow = pR->aStart.Row();
123 : }
124 : else
125 : {
126 0 : InvalidateGlue();
127 0 : nStartCol = 0;
128 0 : nStartRow = 0;
129 : }
130 11 : return;
131 : }
132 :
133 15 : pR = aRangeListRef->front();
134 15 : nStartCol = pR->aStart.Col();
135 15 : nStartRow = pR->aStart.Row();
136 : SCCOL nMaxCols, nEndCol;
137 : SCROW nMaxRows, nEndRow;
138 15 : nMaxCols = nEndCol = 0;
139 15 : nMaxRows = nEndRow = 0;
140 :
141 : // <= so 1 extra pass after last item
142 75 : for ( size_t i = 1, nRanges = aRangeListRef->size(); i <= nRanges; ++i )
143 : { // detect spanning/surrounding area etc.
144 : SCCOLROW nTmp, n1, n2;
145 60 : if ( (n1 = pR->aStart.Col()) < nStartCol ) nStartCol = static_cast<SCCOL>(n1 );
146 60 : if ( (n2 = pR->aEnd.Col() ) > nEndCol ) nEndCol = static_cast<SCCOL>(n2 );
147 60 : if ( (nTmp = n2 - n1 + 1 ) > nMaxCols ) nMaxCols = static_cast<SCCOL>(nTmp);
148 60 : if ( (n1 = pR->aStart.Row()) < nStartRow ) nStartRow = static_cast<SCROW>(n1 );
149 60 : if ( (n2 = pR->aEnd.Row() ) > nEndRow ) nEndRow = static_cast<SCROW>(n2 );
150 60 : if ( (nTmp = n2 - n1 + 1 ) > nMaxRows ) nMaxRows = static_cast<SCROW>(nTmp);
151 :
152 : // in last pass; i = nRanges so don't use at()
153 60 : if ( i < nRanges )
154 45 : pR = (*aRangeListRef)[i];
155 : }
156 15 : SCCOL nC = nEndCol - nStartCol + 1;
157 15 : if ( nC == 1 )
158 : {
159 0 : eGlue = SC_CHARTGLUE_ROWS;
160 0 : return;
161 : }
162 15 : SCROW nR = nEndRow - nStartRow + 1;
163 15 : if ( nR == 1 )
164 : {
165 0 : eGlue = SC_CHARTGLUE_COLS;
166 0 : return;
167 : }
168 15 : sal_uLong nCR = (sal_uLong)nC * nR;
169 :
170 : /*
171 : TODO:
172 : First do it simple without bit masking. A maximum of 8MB could be allocated
173 : this way (256 Cols x 32000 Rows). That could be reduced to 2MB by
174 : using 2 Bits per entry, but it is faster this way.
175 : Another optimization would be to store only used rows/columns in the array, but
176 : would mean another iteration of the RangeList indirect access to the array. */
177 :
178 15 : const sal_uInt8 nHole = 0;
179 15 : const sal_uInt8 nOccu = 1;
180 15 : const sal_uInt8 nFree = 2;
181 15 : const sal_uInt8 nGlue = 3;
182 : sal_uInt8* p;
183 15 : boost::scoped_array<sal_uInt8> pA(new sal_uInt8[ nCR ]);
184 15 : memset( pA.get(), 0, nCR * sizeof(sal_uInt8) );
185 :
186 : SCCOL nCol, nCol1, nCol2;
187 : SCROW nRow, nRow1, nRow2;
188 75 : for ( size_t i = 0, nRanges = aRangeListRef->size(); i < nRanges; ++i )
189 : { // mark selections as used in 2D
190 60 : pR = (*aRangeListRef)[i];
191 60 : nCol1 = pR->aStart.Col() - nStartCol;
192 60 : nCol2 = pR->aEnd.Col() - nStartCol;
193 60 : nRow1 = pR->aStart.Row() - nStartRow;
194 60 : nRow2 = pR->aEnd.Row() - nStartRow;
195 180 : for ( nCol = nCol1; nCol <= nCol2; nCol++ )
196 : {
197 120 : p = pA.get() + (sal_uLong)nCol * nR + nRow1;
198 480 : for ( nRow = nRow1; nRow <= nRow2; nRow++, p++ )
199 360 : *p = nOccu;
200 : }
201 : }
202 15 : bool bGlue = true;
203 :
204 15 : bool bGlueCols = false;
205 60 : for ( nCol = 0; bGlue && nCol < nC; nCol++ )
206 : { // iterate columns and try to mark as unused
207 45 : p = pA.get() + (sal_uLong)nCol * nR;
208 105 : for ( nRow = 0; bGlue && nRow < nR; nRow++, p++ )
209 : {
210 60 : if ( *p == nOccu )
211 : { // If there's one right in the middle, we can't combine.
212 : // If it were at the edge, we could combine, if in this Column
213 : // in every set line, one is set.
214 45 : if ( nRow > 0 && nCol > 0 )
215 15 : bGlue = false; // nCol==0 can be DummyUpperLeft
216 : else
217 30 : nRow = nR;
218 : }
219 : else
220 15 : *p = nFree;
221 : }
222 45 : if ( bGlue && *(p = (pA.get() + ((((sal_uLong)nCol+1) * nR) - 1))) == nFree )
223 : { // mark column as totally unused
224 0 : *p = nGlue;
225 0 : bGlueCols = true; // one unused column at least
226 : }
227 : }
228 :
229 15 : bool bGlueRows = false;
230 15 : for ( nRow = 0; bGlue && nRow < nR; nRow++ )
231 : { // iterate rows and try to mark as unused
232 0 : p = pA.get() + nRow;
233 0 : for ( nCol = 0; bGlue && nCol < nC; nCol++, p+=nR )
234 : {
235 0 : if ( *p == nOccu )
236 : {
237 0 : if ( nCol > 0 && nRow > 0 )
238 0 : bGlue = false; // nRow==0 can be DummyUpperLeft
239 : else
240 0 : nCol = nC;
241 : }
242 : else
243 0 : *p = nFree;
244 : }
245 0 : if ( bGlue && *(p = (pA.get() + ((((sal_uLong)nC-1) * nR) + nRow))) == nFree )
246 : { // mark row as totally unused
247 0 : *p = nGlue;
248 0 : bGlueRows = true; // one unused row at least
249 : }
250 : }
251 :
252 : // If n=1: The upper left corner could be automagically pulled in for labeling
253 15 : p = pA.get() + 1;
254 15 : for ( sal_uLong n = 1; bGlue && n < nCR; n++, p++ )
255 : { // An untouched field means we could neither reach it through rows nor columns,
256 : // thus we can't combine anything
257 0 : if ( *p == nHole )
258 0 : bGlue = false;
259 : }
260 15 : if ( bGlue )
261 : {
262 0 : if ( bGlueCols && bGlueRows )
263 0 : eGlue = SC_CHARTGLUE_BOTH;
264 0 : else if ( bGlueRows )
265 0 : eGlue = SC_CHARTGLUE_ROWS;
266 : else
267 0 : eGlue = SC_CHARTGLUE_COLS;
268 0 : if ( pA[0] != nOccu )
269 0 : bDummyUpperLeft = true;
270 : }
271 : else
272 : {
273 15 : eGlue = SC_CHARTGLUE_NONE;
274 15 : }
275 : }
276 :
277 26 : void ScChartPositioner::CheckColRowHeaders()
278 : {
279 : SCCOL nCol1, nCol2, iCol;
280 : SCROW nRow1, nRow2, iRow;
281 : SCTAB nTab1, nTab2;
282 :
283 26 : bool bColStrings = true;
284 26 : bool bRowStrings = true;
285 26 : GlueState();
286 26 : if ( aRangeListRef->size() == 1 )
287 : {
288 11 : aRangeListRef->front()->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
289 11 : if ( nCol1 > nCol2 || nRow1 > nRow2 )
290 0 : bColStrings = bRowStrings = false;
291 : else
292 : {
293 55 : for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++)
294 : {
295 44 : if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 ))
296 0 : bColStrings = false;
297 : }
298 66 : for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++)
299 : {
300 55 : if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 ))
301 0 : bRowStrings = false;
302 : }
303 : }
304 : }
305 : else
306 : {
307 15 : bool bVert = (eGlue == SC_CHARTGLUE_NONE || eGlue == SC_CHARTGLUE_ROWS);
308 69 : for ( size_t i = 0, nRanges = aRangeListRef->size();
309 56 : (i < nRanges) && (bColStrings || bRowStrings);
310 : ++i
311 : )
312 : {
313 54 : ScRange* pR = (*aRangeListRef)[i];
314 54 : pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
315 54 : bool bTopRow = (nRow1 == nStartRow);
316 54 : if ( bRowStrings && (bVert || nCol1 == nStartCol) )
317 : { // NONE or ROWS: RowStrings in every selection possible
318 : // COLS or BOTH: only from first column
319 54 : if ( nCol1 <= nCol2 )
320 203 : for (iRow=nRow1; iRow<=nRow2 && bRowStrings; iRow++)
321 : {
322 149 : if (lcl_hasValueDataButNoDates( pDocument, nCol1, iRow, nTab1 ))
323 11 : bRowStrings = false;
324 : }
325 : }
326 54 : if ( bColStrings && bTopRow )
327 : { // ColStrings only from first row
328 15 : if ( nRow1 <= nRow2 )
329 43 : for (iCol=nCol1; iCol<=nCol2 && bColStrings; iCol++)
330 : {
331 28 : if (lcl_hasValueDataButNoDates( pDocument, iCol, nRow1, nTab1 ))
332 2 : bColStrings = false;
333 : }
334 : }
335 : }
336 : }
337 26 : bColHeaders = bColStrings;
338 26 : bRowHeaders = bRowStrings;
339 26 : }
340 :
341 288 : const ScChartPositionMap* ScChartPositioner::GetPositionMap()
342 : {
343 288 : CreatePositionMap();
344 288 : return pPositionMap;
345 : }
346 :
347 288 : void ScChartPositioner::CreatePositionMap()
348 : {
349 288 : if ( eGlue == SC_CHARTGLUE_NA && pPositionMap )
350 : {
351 0 : delete pPositionMap;
352 0 : pPositionMap = NULL;
353 : }
354 :
355 288 : if ( pPositionMap )
356 558 : return ;
357 :
358 18 : SCSIZE nColAdd = bRowHeaders ? 1 : 0;
359 18 : SCSIZE nRowAdd = bColHeaders ? 1 : 0;
360 :
361 : SCCOL nCol, nCol1, nCol2;
362 : SCROW nRow, nRow1, nRow2;
363 : SCTAB nTab, nTab1, nTab2;
364 :
365 : // real size (without hidden rows/columns)
366 :
367 18 : SCSIZE nColCount = 0;
368 18 : SCSIZE nRowCount = 0;
369 :
370 18 : GlueState();
371 :
372 18 : const bool bNoGlue = (eGlue == SC_CHARTGLUE_NONE);
373 18 : ColumnMap* pCols = new ColumnMap;
374 18 : SCROW nNoGlueRow = 0;
375 81 : for ( size_t i = 0, nRanges = aRangeListRef->size(); i < nRanges; ++i )
376 : {
377 63 : ScRange* pR = (*aRangeListRef)[i];
378 63 : pR->GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
379 126 : for ( nTab = nTab1; nTab <= nTab2; nTab++ )
380 : {
381 : // nTab in ColKey to allow to have the same col/row in another tabe
382 63 : sal_uLong nInsCol = (static_cast<sal_uLong>(nTab) << 16) | (bNoGlue ? 0 :
383 63 : static_cast<sal_uLong>(nCol1));
384 195 : for ( nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol )
385 : {
386 132 : RowMap* pCol = NULL;
387 132 : ColumnMap::const_iterator it = pCols->find( nInsCol );
388 132 : if ( it == pCols->end() )
389 : {
390 42 : pCol = new RowMap;
391 42 : pCols->insert( ColumnMap::value_type( nInsCol, pCol ) );
392 : }
393 : else
394 90 : pCol = it->second;
395 :
396 : // in other table a new ColKey already was created,
397 : // the rows must be equal to be filled with Dummy
398 132 : sal_uLong nInsRow = (bNoGlue ? nNoGlueRow : nRow1);
399 552 : for ( nRow = nRow1; nRow <= nRow2; nRow++, nInsRow++ )
400 : {
401 420 : if ( pCol->find( nInsRow ) == pCol->end() )
402 : {
403 420 : pCol->insert( RowMap::value_type( nInsRow, new ScAddress( nCol, nRow, nTab ) ) );
404 : }
405 : }
406 : }
407 : }
408 : // For NoGlue: associated tables will be rendered as ColGlue
409 63 : nNoGlueRow += nRow2 - nRow1 + 1;
410 : }
411 :
412 : // count of data
413 18 : nColCount = static_cast< SCSIZE >( pCols->size());
414 18 : if ( !pCols->empty() )
415 : {
416 18 : RowMap* pCol = pCols->begin()->second;
417 18 : if ( bDummyUpperLeft )
418 0 : (*pCol)[ 0 ] = NULL; // Dummy for labeling
419 18 : nRowCount = static_cast< SCSIZE >( pCol->size());
420 : }
421 : else
422 0 : nRowCount = 0;
423 18 : if ( nColCount > 0 )
424 18 : nColCount -= nColAdd;
425 18 : if ( nRowCount > 0 )
426 18 : nRowCount -= nRowAdd;
427 :
428 18 : if ( nColCount==0 || nRowCount==0 )
429 : { // create an entry without data
430 : RowMap* pCol;
431 0 : if ( !pCols->empty() )
432 0 : pCol = pCols->begin()->second;
433 : else
434 : {
435 0 : pCol = new RowMap;
436 0 : (*pCols)[ 0 ] = pCol;
437 : }
438 0 : nColCount = 1;
439 0 : if ( !pCol->empty() )
440 : { // cannot be if nColCount==0 || nRowCount==0
441 0 : ScAddress* pPos = pCol->begin()->second;
442 0 : if ( pPos )
443 : {
444 0 : sal_uLong nCurrentKey = pCol->begin()->first;
445 0 : delete pPos;
446 0 : (*pCol)[ nCurrentKey ] = NULL;
447 : }
448 : }
449 : else
450 0 : (*pCol)[ 0 ] = NULL;
451 0 : nRowCount = 1;
452 0 : nColAdd = 0;
453 0 : nRowAdd = 0;
454 : }
455 : else
456 : {
457 18 : if ( bNoGlue )
458 : { // fill gaps with Dummies, first column is master
459 18 : RowMap* pFirstCol = pCols->begin()->second;
460 18 : sal_uLong nCount = pFirstCol->size();
461 18 : RowMap::const_iterator it1 = pFirstCol->begin();
462 213 : for ( sal_uLong n = 0; n < nCount; n++, ++it1 )
463 : {
464 195 : sal_uLong nKey = it1->first;
465 420 : for (ColumnMap::const_iterator it2 = ++pCols->begin(); it2 != pCols->end(); ++it2 )
466 225 : it2->second->insert( RowMap::value_type( nKey, nullptr )); // no data
467 : }
468 : }
469 : }
470 :
471 : pPositionMap = new ScChartPositionMap( static_cast<SCCOL>(nColCount), static_cast<SCROW>(nRowCount),
472 18 : static_cast<SCCOL>(nColAdd), static_cast<SCROW>(nRowAdd), *pCols );
473 :
474 : // cleanup
475 60 : for (ColumnMap::const_iterator it = pCols->begin(); it != pCols->end(); ++it )
476 : { // Only delete tables, not the ScAddress*!
477 42 : delete it->second;
478 : }
479 18 : delete pCols;
480 : }
481 :
482 18 : ScChartPositionMap::ScChartPositionMap( SCCOL nChartCols, SCROW nChartRows,
483 : SCCOL nColAdd, SCROW nRowAdd, ColumnMap& rCols ) :
484 18 : ppData( new ScAddress* [ nChartCols * nChartRows ] ),
485 18 : ppColHeader( new ScAddress* [ nChartCols ] ),
486 18 : ppRowHeader( new ScAddress* [ nChartRows ] ),
487 18 : nCount( (sal_uLong) nChartCols * nChartRows ),
488 : nColCount( nChartCols ),
489 72 : nRowCount( nChartRows )
490 : {
491 : OSL_ENSURE( nColCount && nRowCount, "ScChartPositionMap without dimension" );
492 :
493 18 : ColumnMap::const_iterator pColIter = rCols.begin();
494 18 : RowMap* pCol1 = pColIter->second;
495 18 : RowMap::const_iterator pPos1Iter;
496 :
497 : // row header
498 18 : pPos1Iter = pCol1->begin();
499 18 : if ( nRowAdd )
500 14 : ++pPos1Iter;
501 18 : if ( nColAdd )
502 : { // independent
503 14 : SCROW nRow = 0;
504 147 : for ( ; nRow < nRowCount && pPos1Iter != pCol1->end(); nRow++ )
505 : {
506 133 : ppRowHeader[ nRow ] = pPos1Iter->second;
507 133 : ++pPos1Iter;
508 : }
509 14 : for ( ; nRow < nRowCount; nRow++ )
510 0 : ppRowHeader[ nRow ] = NULL;
511 : }
512 : else
513 : { // copy
514 4 : SCROW nRow = 0;
515 52 : for ( ; nRow < nRowCount && pPos1Iter != pCol1->end(); nRow++ )
516 : {
517 48 : ppRowHeader[ nRow ] = pPos1Iter->second ?
518 48 : new ScAddress( *pPos1Iter->second ) : NULL;
519 48 : ++pPos1Iter;
520 : }
521 4 : for ( ; nRow < nRowCount; nRow++ )
522 0 : ppRowHeader[ nRow ] = NULL;
523 : }
524 18 : if ( nColAdd )
525 : {
526 14 : ++pColIter;
527 : }
528 :
529 : // data column by column and column-header
530 18 : sal_uLong nIndex = 0;
531 46 : for ( SCCOL nCol = 0; nCol < nColCount; nCol++ )
532 : {
533 28 : if ( pColIter != rCols.end() )
534 : {
535 28 : RowMap* pCol2 = pColIter->second;
536 28 : RowMap::const_iterator pPosIter = pCol2->begin();
537 28 : if ( pPosIter != pCol2->end() )
538 : {
539 28 : if ( nRowAdd )
540 : {
541 20 : ppColHeader[ nCol ] = pPosIter->second; // independent
542 20 : ++pPosIter;
543 : }
544 : else
545 8 : ppColHeader[ nCol ] = pPosIter->second ?
546 8 : new ScAddress( *pPosIter->second ) : NULL;
547 : }
548 :
549 28 : SCROW nRow = 0;
550 281 : for ( ; nRow < nRowCount && pPosIter != pCol2->end(); nRow++, nIndex++ )
551 : {
552 253 : ppData[ nIndex ] = pPosIter->second;
553 253 : ++pPosIter;
554 : }
555 28 : for ( ; nRow < nRowCount; nRow++, nIndex++ )
556 0 : ppData[ nIndex ] = NULL;
557 :
558 28 : ++pColIter;
559 : }
560 : else
561 : {
562 0 : ppColHeader[ nCol ] = NULL;
563 0 : for ( SCROW nRow = 0; nRow < nRowCount; nRow++, nIndex++ )
564 : {
565 0 : ppData[ nIndex ] = NULL;
566 : }
567 : }
568 : }
569 18 : }
570 :
571 18 : ScChartPositionMap::~ScChartPositionMap()
572 : {
573 271 : for ( sal_uLong nIndex=0; nIndex < nCount; nIndex++ )
574 : {
575 253 : delete ppData[nIndex];
576 : }
577 18 : delete [] ppData;
578 :
579 : SCCOL j;
580 46 : for ( j=0; j < nColCount; j++ )
581 : {
582 28 : delete ppColHeader[j];
583 : }
584 18 : delete [] ppColHeader;
585 : SCROW i;
586 199 : for ( i=0; i < nRowCount; i++ )
587 : {
588 181 : delete ppRowHeader[i];
589 : }
590 18 : delete [] ppRowHeader;
591 174 : }
592 :
593 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|