xref: /aoo42x/main/sc/source/ui/unoobj/chart2uno.cxx (revision b3f79822)
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 "chart2uno.hxx"
28 #include "miscuno.hxx"
29 #include "document.hxx"
30 #include "unoguard.hxx"
31 #include "cell.hxx"
32 #include "chartpos.hxx"
33 #include "unonames.hxx"
34 #include "globstr.hrc"
35 #include "convuno.hxx"
36 #include "rangeutl.hxx"
37 #include "hints.hxx"
38 #include "unoreflist.hxx"
39 #include "compiler.hxx"
40 #include "reftokenhelper.hxx"
41 #include "chartlis.hxx"
42 
43 #include <sfx2/objsh.hxx>
44 #include <tools/table.hxx>
45 
46 #include <com/sun/star/beans/UnknownPropertyException.hpp>
47 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
48 #include <com/sun/star/table/XCellRange.hpp>
49 #include <com/sun/star/table/CellAddress.hpp>
50 #include <com/sun/star/text/XText.hpp>
51 #include <comphelper/extract.hxx>
52 #include <comphelper/processfactory.hxx>
53 
54 #include <vector>
55 #include <list>
56 #include <rtl/math.hxx>
57 
58 SC_SIMPLE_SERVICE_INFO( ScChart2DataProvider, "ScChart2DataProvider",
59         "com.sun.star.chart2.data.DataProvider")
60 SC_SIMPLE_SERVICE_INFO( ScChart2DataSource, "ScChart2DataSource",
61         "com.sun.star.chart2.data.DataSource")
62 SC_SIMPLE_SERVICE_INFO( ScChart2DataSequence, "ScChart2DataSequence",
63         "com.sun.star.chart2.data.DataSequence")
64 #if USE_CHART2_EMPTYDATASEQUENCE
65 SC_SIMPLE_SERVICE_INFO( ScChart2EmptyDataSequence, "ScChart2EmptyDataSequence",
66         "com.sun.star.chart2.data.DataSequence")
67 #endif
68 
69 using namespace ::com::sun::star;
70 using namespace ::formula;
71 using ::rtl::OUString;
72 using ::rtl::OUStringBuffer;
73 using ::com::sun::star::uno::Sequence;
74 using ::com::sun::star::uno::Reference;
75 using ::std::auto_ptr;
76 using ::std::vector;
77 using ::std::list;
78 using ::std::distance;
79 using ::std::unary_function;
80 using ::std::hash_set;
81 using ::boost::shared_ptr;
82 
83 namespace
84 {
85 const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap()
86 {
87     static SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] =
88     {
89         {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0,		&getBooleanCppuType(),					0, 0 },
90         {0,0,0,0,0,0}
91     };
92     return aDataProviderPropertyMap_Impl;
93 }
94 
95 const SfxItemPropertyMapEntry* lcl_GetDataSequencePropertyMap()
96 {
97     static SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl[] =
98 	{
99 		{MAP_CHAR_LEN(SC_UNONAME_HIDDENVALUES), 0, &getCppuType((uno::Sequence<sal_Int32>*)0 ),					0, 0 },
100 		{MAP_CHAR_LEN(SC_UNONAME_ROLE), 0, &getCppuType((::com::sun::star::chart2::data::DataSequenceRole*)0),					0, 0 },
101         {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0,		&getBooleanCppuType(),					0, 0 },
102 		{0,0,0,0,0,0}
103 	};
104 	return aDataSequencePropertyMap_Impl;
105 }
106 
107 template< typename T >
108 ::com::sun::star::uno::Sequence< T > lcl_VectorToSequence(
109     const ::std::vector< T > & rCont )
110 {
111     ::com::sun::star::uno::Sequence< T > aResult( rCont.size());
112     ::std::copy( rCont.begin(), rCont.end(), aResult.getArray());
113     return aResult;
114 }
115 
116 struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void >
117 {
118     lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) :
119             m_rBuffer( rBuffer )
120     {}
121     void operator() ( SCTAB nTab )
122     {
123         // there is no append with SCTAB or sal_Int16
124         m_rBuffer.append( static_cast< sal_Int32 >( nTab ));
125         m_rBuffer.append( sal_Unicode( ' ' ));
126     }
127 private:
128     ::rtl::OUStringBuffer & m_rBuffer;
129 };
130 
131 ::rtl::OUString lcl_createTableNumberList( const ::std::list< SCTAB > & rTableList )
132 {
133     ::rtl::OUStringBuffer aBuffer;
134     ::std::for_each( rTableList.begin(), rTableList.end(), lcl_appendTableNumber( aBuffer ));
135     // remove last trailing ' '
136     if( aBuffer.getLength() > 0 )
137         aBuffer.setLength( aBuffer.getLength() - 1 );
138     return aBuffer.makeStringAndClear();
139 }
140 
141 uno::Reference< frame::XModel > lcl_GetXModel( ScDocument * pDoc )
142 {
143     uno::Reference< frame::XModel > xModel;
144     SfxObjectShell * pObjSh( pDoc ? pDoc->GetDocumentShell() : 0 );
145     if( pObjSh )
146         xModel.set( pObjSh->GetModel());
147 	return xModel;
148 }
149 
150 uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocument * pDoc )
151 {
152     return uno::Reference< sheet::XSpreadsheetDocument >( lcl_GetXModel( pDoc ), uno::UNO_QUERY );
153 }
154 
155 // ============================================================================
156 
157 namespace {
158 
159 struct DeleteInstance : public unary_function<FormulaToken*, void>
160 {
161     void operator() (FormulaToken* p) const
162     {
163         delete p;
164     }
165 };
166 
167 }
168 
169 struct TokenTable
170 {
171     SCROW mnRowCount;
172     SCCOL mnColCount;
173     vector<FormulaToken*> maTokens;
174 
175     void init( SCCOL nColCount, SCROW nRowCount )
176     {
177         mnColCount = nColCount;
178         mnRowCount = nRowCount;
179         maTokens.reserve(mnColCount*mnRowCount);
180     }
181     void clear()
182     {
183         for_each(maTokens.begin(), maTokens.end(), DeleteInstance());
184     }
185 
186     void push_back( FormulaToken* pToken )
187     {
188         maTokens.push_back( pToken );
189         DBG_ASSERT( maTokens.size()<= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too much tokens" );
190     }
191 
192     sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const
193     {
194         DBG_ASSERT( nCol<mnColCount, "wrong column index" );
195         DBG_ASSERT( nRow<mnRowCount, "wrong row index" );
196         sal_uInt32 nRet = static_cast<sal_uInt32>(nCol*mnRowCount + nRow);
197         DBG_ASSERT( maTokens.size()>= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too few tokens" );
198         return nRet;
199     }
200 
201     vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const;
202     vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const;
203     vector<ScSharedTokenRef>* getAllRanges() const;
204 };
205 
206 vector<ScSharedTokenRef>* TokenTable::getColRanges(SCCOL nCol) const
207 {
208     if (nCol >= mnColCount)
209         return NULL;
210     if( mnRowCount<=0 )
211         return NULL;
212 
213     auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
214     sal_uInt32 nLast = getIndex(nCol, mnRowCount-1);
215     for (sal_uInt32 i = getIndex(nCol, 0); i <= nLast; ++i)
216     {
217         FormulaToken* p = maTokens[i];
218         if (!p)
219             continue;
220 
221         ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone()));
222         ScRefTokenHelper::join(*pTokens, pCopy);
223     }
224     return pTokens.release();
225 }
226 
227 vector<ScSharedTokenRef>* TokenTable::getRowRanges(SCROW nRow) const
228 {
229     if (nRow >= mnRowCount)
230         return NULL;
231     if( mnColCount<=0 )
232         return NULL;
233 
234     auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
235     sal_uInt32 nLast = getIndex(mnColCount-1, nRow);
236     for (sal_uInt32 i = getIndex(0, nRow); i <= nLast; i += mnRowCount)
237     {
238         FormulaToken* p = maTokens[i];
239         if (!p)
240             continue;
241 
242         ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
243         ScRefTokenHelper::join(*pTokens, p2);
244     }
245     return pTokens.release();
246 }
247 
248 vector<ScSharedTokenRef>* TokenTable::getAllRanges() const
249 {
250     auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>);
251     sal_uInt32 nStop = mnColCount*mnRowCount;
252     for (sal_uInt32 i = 0; i < nStop; i++)
253     {
254         FormulaToken* p = maTokens[i];
255         if (!p)
256             continue;
257 
258         ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone()));
259         ScRefTokenHelper::join(*pTokens, p2);
260     }
261     return pTokens.release();
262 }
263 
264 // ============================================================================
265 
266 class Chart2PositionMap
267 {
268 public:
269     Chart2PositionMap(SCCOL nColCount, SCROW nRowCount,
270                       bool bFillRowHeader, bool bFillColumnHeader, Table& rCols,
271                       ScDocument* pDoc );
272     ~Chart2PositionMap();
273 
274     SCCOL getDataColCount() const { return mnDataColCount; }
275     SCROW getDataRowCount() const { return mnDataRowCount; }
276 
277     vector<ScSharedTokenRef>* getLeftUpperCornerRanges() const;
278     vector<ScSharedTokenRef>* getAllColHeaderRanges() const;
279     vector<ScSharedTokenRef>* getAllRowHeaderRanges() const;
280 
281     vector<ScSharedTokenRef>* getColHeaderRanges(SCCOL nChartCol) const;
282     vector<ScSharedTokenRef>* getRowHeaderRanges(SCROW nChartRow) const;
283 
284     vector<ScSharedTokenRef>* getDataColRanges(SCCOL nCol) const;
285     vector<ScSharedTokenRef>* getDataRowRanges(SCROW nRow) const;
286 
287 private:
288     SCCOL mnDataColCount;
289     SCROW mnDataRowCount;
290 
291     TokenTable maLeftUpperCorner; //nHeaderColCount*nHeaderRowCount
292     TokenTable maColHeaders; //mnDataColCount*nHeaderRowCount
293     TokenTable maRowHeaders; //nHeaderColCount*mnDataRowCount
294     TokenTable maData;//mnDataColCount*mnDataRowCount
295 };
296 
297 Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount,  SCROW nAllRowCount,
298                                      bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, ScDocument* pDoc)
299 {
300     // if bFillRowHeader is true, at least the first column serves as a row header.
301     //  If more than one column is pure text all the first pure text columns are used as header.
302     // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header.
303     //  If more than one row is pure text all the first pure text rows are used as header.
304 
305     SCROW nHeaderRowCount = (bFillColumnHeader && nAllColCount && nAllRowCount) ? 1 : 0;
306     SCCOL nHeaderColCount = (bFillRowHeader && nAllColCount && nAllRowCount) ? 1 : 0;
307 
308     if( nHeaderColCount || nHeaderRowCount )
309     {
310         const SCCOL nInitialHeaderColCount = nHeaderColCount;
311         //check whether there is more than one text column or row that should be added to the headers
312         SCROW nSmallestValueRowIndex = nAllRowCount;
313         bool bFoundValues = false;
314         bool bFoundAnything = false;
315         Table* pCol = static_cast<Table*>(rCols.First());
316         for (SCCOL nCol = 0; !bFoundValues && nCol < nAllColCount; ++nCol)
317         {
318             if (pCol && nCol>=nHeaderColCount)
319             {
320                 ScToken* pToken = static_cast<ScToken*>(pCol->First());
321                 for (SCROW nRow = 0; !bFoundValues && nRow < nSmallestValueRowIndex; ++nRow)
322                 {
323                     if (pToken && nRow>=nHeaderRowCount)
324                     {
325                         ScRange aRange;
326                         bool bExternal = false;
327                         StackVar eType = pToken->GetType();
328                         if( eType==svExternal || eType==svExternalSingleRef || eType==svExternalDoubleRef || eType==svExternalName )
329                             bExternal = true;//lllll todo correct?
330                         ScSharedTokenRef pSharedToken(static_cast<ScToken*>(pToken->Clone()));
331                         ScRefTokenHelper::getRangeFromToken(aRange, pSharedToken, bExternal );
332                         SCCOL nCol1=0, nCol2=0;
333                         SCROW nRow1=0, nRow2=0;
334                         SCTAB nTab1=0, nTab2=0;
335                         aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
336                         if (pDoc && pDoc->HasValueData( nCol1, nRow1, nTab1 ))
337                         {
338                             bFoundValues = bFoundAnything = true;
339                             nSmallestValueRowIndex = std::min( nSmallestValueRowIndex, nRow );
340                         }
341                         if( !bFoundAnything )
342                         {
343                             if (pDoc && pDoc->HasData( nCol1, nRow1, nTab1 ) )
344                                 bFoundAnything = true;
345                         }
346                     }
347                     pToken = static_cast<ScToken*>(pCol->Next());
348                 }
349                 if(!bFoundValues && nHeaderColCount>0)
350                     nHeaderColCount++;
351             }
352             pCol = static_cast<Table*>(rCols.Next());
353         }
354         if( bFoundAnything )
355         {
356             if(nHeaderRowCount>0)
357             {
358                 if( bFoundValues )
359                     nHeaderRowCount = nSmallestValueRowIndex;
360                 else if( nAllRowCount>1 )
361                     nHeaderRowCount = nAllRowCount-1;
362             }
363         }
364         else //if the cells are completely empty, just use single header rows and columns
365             nHeaderColCount = nInitialHeaderColCount;
366     }
367 
368     mnDataColCount = nAllColCount - nHeaderColCount;
369     mnDataRowCount = nAllRowCount - nHeaderRowCount;
370 
371     maLeftUpperCorner.init(nHeaderColCount,nHeaderRowCount);
372     maColHeaders.init(mnDataColCount,nHeaderRowCount);
373     maRowHeaders.init(nHeaderColCount,mnDataRowCount);
374     maData.init(mnDataColCount,mnDataRowCount);
375 
376     Table* pCol = static_cast<Table*>(rCols.First());
377     FormulaToken* pToken = static_cast<FormulaToken*>(pCol->First());
378     for (SCCOL nCol = 0; nCol < nAllColCount; ++nCol)
379     {
380         if (pCol)
381         {
382             pToken = static_cast<FormulaToken*>(pCol->First());
383             for (SCROW nRow = 0; nRow < nAllRowCount; ++nRow)
384             {
385                 if( nCol < nHeaderColCount )
386                 {
387                     if( nRow < nHeaderRowCount )
388                         maLeftUpperCorner.push_back(pToken);
389                     else
390                         maRowHeaders.push_back(pToken);
391                 }
392                 else if( nRow < nHeaderRowCount )
393                     maColHeaders.push_back(pToken);
394                 else
395                     maData.push_back(pToken);
396 
397                 pToken = static_cast<FormulaToken*>(pCol->Next());
398             }
399         }
400         pCol = static_cast<Table*>(rCols.Next());
401     }
402 }
403 
404 Chart2PositionMap::~Chart2PositionMap()
405 {
406     maLeftUpperCorner.clear();
407     maColHeaders.clear();
408     maRowHeaders.clear();
409     maData.clear();
410 }
411 
412 vector<ScSharedTokenRef>* Chart2PositionMap::getLeftUpperCornerRanges() const
413 {
414     return maLeftUpperCorner.getAllRanges();
415 }
416 vector<ScSharedTokenRef>* Chart2PositionMap::getAllColHeaderRanges() const
417 {
418     return maColHeaders.getAllRanges();
419 }
420 vector<ScSharedTokenRef>* Chart2PositionMap::getAllRowHeaderRanges() const
421 {
422     return maRowHeaders.getAllRanges();
423 }
424 vector<ScSharedTokenRef>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol) const
425 {
426     return maColHeaders.getColRanges( nCol);
427 }
428 vector<ScSharedTokenRef>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow) const
429 {
430     return maRowHeaders.getRowRanges( nRow);
431 }
432 
433 vector<ScSharedTokenRef>* Chart2PositionMap::getDataColRanges(SCCOL nCol) const
434 {
435     return maData.getColRanges( nCol);
436 }
437 
438 vector<ScSharedTokenRef>* Chart2PositionMap::getDataRowRanges(SCROW nRow) const
439 {
440     return maData.getRowRanges( nRow);
441 }
442 
443 // ----------------------------------------------------------------------------
444 
445 /**
446  * Designed to be a drop-in replacement for ScChartPositioner, in order to
447  * handle external references.
448  */
449 class Chart2Positioner
450 {
451     enum GlueType
452     {
453         GLUETYPE_NA,
454         GLUETYPE_NONE,
455         GLUETYPE_COLS,
456         GLUETYPE_ROWS,
457         GLUETYPE_BOTH
458     };
459 
460 public:
461     Chart2Positioner(ScDocument* pDoc, const vector<ScSharedTokenRef>& rRefTokens) :
462         mpRefTokens(new vector<ScSharedTokenRef>(rRefTokens)),
463         mpPositionMap(NULL),
464         meGlue(GLUETYPE_NA),
465         mpDoc(pDoc),
466         mbColHeaders(false),
467         mbRowHeaders(false),
468         mbDummyUpperLeft(false)
469     {
470     }
471 
472     ~Chart2Positioner()
473     {
474     }
475 
476     void setHeaders(bool bColHeaders, bool bRowHeaders)
477     {
478         mbColHeaders = bColHeaders;
479         mbRowHeaders = bRowHeaders;
480     }
481 
482     bool hasColHeaders() const { return mbColHeaders; }
483     bool hasRowHeaders() const { return mbRowHeaders; }
484 
485     Chart2PositionMap* getPositionMap()
486     {
487         createPositionMap();
488         return mpPositionMap.get();
489     }
490 
491 private:
492     Chart2Positioner(); // disabled
493 
494     void invalidateGlue();
495     void glueState();
496     void createPositionMap();
497 
498 private:
499     shared_ptr< vector<ScSharedTokenRef> >  mpRefTokens;
500     auto_ptr<Chart2PositionMap>             mpPositionMap;
501     GlueType    meGlue;
502     SCCOL       mnStartCol;
503     SCROW       mnStartRow;
504     ScDocument* mpDoc;
505     bool mbColHeaders:1;
506     bool mbRowHeaders:1;
507     bool mbDummyUpperLeft:1;
508 };
509 
510 void Chart2Positioner::invalidateGlue()
511 {
512     meGlue = GLUETYPE_NA;
513     mpPositionMap.reset(NULL);
514 }
515 
516 void Chart2Positioner::glueState()
517 {
518     if (meGlue != GLUETYPE_NA)
519         return;
520 
521     mbDummyUpperLeft = false;
522     if (mpRefTokens->size() <= 1)
523     {
524         const ScSharedTokenRef& p = mpRefTokens->front();
525         ScComplexRefData aData;
526         if (ScRefTokenHelper::getDoubleRefDataFromToken(aData, p))
527         {
528             if (aData.Ref1.nTab == aData.Ref2.nTab)
529                 meGlue = GLUETYPE_NONE;
530             else
531                 meGlue = GLUETYPE_COLS;
532             mnStartCol = aData.Ref1.nCol;
533             mnStartRow = aData.Ref1.nRow;
534         }
535         else
536         {
537             invalidateGlue();
538             mnStartCol = 0;
539             mnStartRow = 0;
540         }
541         return;
542     }
543 
544     ScComplexRefData aData;
545     ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front());
546     mnStartCol = aData.Ref1.nCol;
547     mnStartRow = aData.Ref1.nRow;
548 
549     SCCOL nMaxCols = 0, nEndCol = 0;
550     SCROW nMaxRows = 0, nEndRow = 0;
551     for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end()
552          ; itr != itrEnd; ++itr)
553     {
554         ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
555         SCCOLROW n1 = aData.Ref1.nCol;
556         SCCOLROW n2 = aData.Ref2.nCol;
557         if (n1 > MAXCOL)
558             n1 = MAXCOL;
559         if (n2 > MAXCOL)
560             n2 = MAXCOL;
561         SCCOLROW nTmp = n2 - n1 + 1;
562         if (n1 < mnStartCol)
563             mnStartCol = static_cast<SCCOL>(n1);
564         if (n2 > nEndCol)
565             nEndCol = static_cast<SCCOL>(n2);
566         if (nTmp > nMaxCols)
567             nMaxCols = static_cast<SCCOL>(nTmp);
568 
569         n1 = aData.Ref1.nRow;
570         n2 = aData.Ref2.nRow;
571         if (n1 > MAXROW)
572             n1 = MAXROW;
573         if (n2 > MAXROW)
574             n2 = MAXROW;
575         nTmp = n2 - n1 + 1;
576 
577         if (n1 < mnStartRow)
578             mnStartRow = static_cast<SCROW>(n1);
579         if (n2 > nEndRow)
580             nEndRow = static_cast<SCROW>(n2);
581         if (nTmp > nMaxRows)
582             nMaxRows = static_cast<SCROW>(nTmp);
583     }
584 
585     // total column size ?
586     SCCOL nC = nEndCol - mnStartCol + 1;
587     if (nC == 1)
588     {
589         meGlue = GLUETYPE_ROWS;
590         return;
591     }
592     // total row size ?
593     SCROW nR = nEndRow - mnStartRow + 1;
594     if (nR == 1)
595     {
596         meGlue = GLUETYPE_COLS;
597         return;
598     }
599     // #i103540# prevent invalid vector size
600     if ((nC <= 0) || (nR <= 0))
601     {
602         invalidateGlue();
603         mnStartCol = 0;
604         mnStartRow = 0;
605         return;
606     }
607     sal_uInt32 nCR = static_cast<sal_uInt32>(nC*nR);
608 
609     const sal_uInt8 nHole = 0;
610     const sal_uInt8 nOccu = 1;
611     const sal_uInt8 nFree = 2;
612     const sal_uInt8 nGlue = 3;
613 
614     vector<sal_uInt8> aCellStates(nCR);
615     for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
616           itr != itrEnd; ++itr)
617     {
618         ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
619         SCCOL nCol1 = static_cast<SCCOL>(aData.Ref1.nCol) - mnStartCol;
620         SCCOL nCol2 = static_cast<SCCOL>(aData.Ref2.nCol) - mnStartCol;
621         SCROW nRow1 = static_cast<SCROW>(aData.Ref1.nRow) - mnStartRow;
622         SCROW nRow2 = static_cast<SCROW>(aData.Ref2.nRow) - mnStartRow;
623         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
624             for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
625             {
626                 size_t i = nCol*nR + nRow;
627                 aCellStates[i] = nOccu;
628             }
629     }
630     bool bGlue = true;
631 
632     size_t i = 0;
633     bool bGlueCols = false;
634     for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol)
635     {
636         for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
637         {
638             i = nCol*nR + nRow;
639             if (aCellStates[i] == nOccu)
640             {
641                 if (nRow > 0 && nRow > 0)
642                     bGlue = false;
643                 else
644                     nRow = nR;
645             }
646             else
647                 aCellStates[i] = nFree;
648         }
649         i = (nCol+1)*nR - 1; // index for the last cell in the column.
650         if (bGlue && (aCellStates[i] == nFree))
651         {
652             aCellStates[i] = nGlue;
653             bGlueCols = true;
654         }
655     }
656 
657     bool bGlueRows = false;
658     for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow)
659     {
660         i = nRow;
661         for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol, i += nR)
662         {
663             if (aCellStates[i] == nOccu)
664             {
665                 if (nCol > 0 && nRow > 0)
666                     bGlue = false;
667                 else
668                     nCol = nC;
669             }
670             else
671                 aCellStates[i] = nFree;
672         }
673         i = (nC-1)*nR + nRow; // index for the row position in the last column.
674         if (bGlue && aCellStates[i] == nFree)
675         {
676             aCellStates[i] = nGlue;
677             bGlueRows = true;
678         }
679     }
680 
681     i = 1;
682     for (sal_uInt32 n = 1; bGlue && n < nCR; ++n, ++i)
683         if (aCellStates[i] == nHole)
684             bGlue = false;
685 
686     if (bGlue)
687     {
688         if (bGlueCols && bGlueRows)
689             meGlue = GLUETYPE_BOTH;
690         else if (bGlueRows)
691             meGlue = GLUETYPE_ROWS;
692         else
693             meGlue = GLUETYPE_COLS;
694         if (aCellStates.front() != nOccu)
695             mbDummyUpperLeft = true;
696     }
697     else
698         meGlue = GLUETYPE_NONE;
699 }
700 
701 void Chart2Positioner::createPositionMap()
702 {
703     if (meGlue == GLUETYPE_NA && mpPositionMap.get())
704         mpPositionMap.reset(NULL);
705 
706     if (mpPositionMap.get())
707         return;
708 
709     glueState();
710 
711     bool bNoGlue = (meGlue == GLUETYPE_NONE);
712     auto_ptr<Table> pCols(new Table);
713     auto_ptr<FormulaToken> pNewAddress;
714     auto_ptr<Table> pNewRowTable(new Table);
715     Table* pCol = NULL;
716     SCROW nNoGlueRow = 0;
717     for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end();
718           itr != itrEnd; ++itr)
719     {
720         const ScSharedTokenRef& pToken = *itr;
721 
722         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
723         sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
724         String aTabName = bExternal ? pToken->GetString() : String();
725 
726         ScComplexRefData aData;
727         ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
728         const ScSingleRefData& s = aData.Ref1;
729         const ScSingleRefData& e = aData.Ref2;
730         SCCOL nCol1 = s.nCol, nCol2 = e.nCol;
731         SCROW nRow1 = s.nRow, nRow2 = e.nRow;
732         SCTAB nTab1 = s.nTab, nTab2 = e.nTab;
733 
734         for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab)
735         {
736             // What's this for ???
737             sal_uInt32 nInsCol = (static_cast<sal_uInt32>(nTab) << 16) |
738                 (bNoGlue ? 0 : static_cast<sal_uInt32>(nCol1));
739             for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol)
740             {
741                 if (bNoGlue || meGlue == GLUETYPE_ROWS)
742                 {
743                     pCol = static_cast<Table*>(pCols->Get(nInsCol));
744                     if (!pCol)
745                     {
746                         pCol = pNewRowTable.get();
747                         pCols->Insert(nInsCol, pNewRowTable.release());
748                         pNewRowTable.reset(new Table);
749                     }
750                 }
751                 else
752                 {
753                     if (pCols->Insert(nInsCol, pNewRowTable.get()))
754                     {
755                         pCol = pNewRowTable.release();
756                         pNewRowTable.reset(new Table);
757                     }
758                     else
759                         pCol = static_cast<Table*>(pCols->Get(nInsCol));
760                 }
761 
762                 sal_uInt32 nInsRow = static_cast<sal_uInt32>(bNoGlue ? nNoGlueRow : nRow1);
763                 for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow, ++nInsRow)
764                 {
765                     ScSingleRefData aCellData;
766                     aCellData.InitFlags();
767                     aCellData.SetFlag3D(true);
768                     aCellData.SetColRel(false);
769                     aCellData.SetRowRel(false);
770                     aCellData.SetTabRel(false);
771                     aCellData.nCol = nCol;
772                     aCellData.nRow = nRow;
773                     aCellData.nTab = nTab;
774 
775                     if (bExternal)
776                         pNewAddress.reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData));
777                     else
778                         pNewAddress.reset(new ScSingleRefToken(aCellData));
779 
780                     if (pCol->Insert(nInsRow, pNewAddress.get()))
781                         pNewAddress.release(); // To prevent the instance from being destroyed.
782                 }
783             }
784         }
785         nNoGlueRow += nRow2 - nRow1 + 1;
786     }
787     pNewAddress.reset(NULL);
788     pNewRowTable.reset(NULL);
789 
790     bool bFillRowHeader = mbRowHeaders;
791     bool bFillColumnHeader = mbColHeaders;
792 
793     SCSIZE nAllColCount = static_cast<SCSIZE>(pCols->Count());
794     SCSIZE nAllRowCount = 0;
795     pCol = static_cast<Table*>(pCols->First());
796     if (pCol)
797     {
798         if (mbDummyUpperLeft)
799             pCol->Insert(0, NULL);        // Dummy fuer Beschriftung
800         nAllRowCount = static_cast<SCSIZE>(pCol->Count());
801     }
802 
803     if( nAllColCount!=0 && nAllRowCount!=0 )
804     {
805         if (bNoGlue)
806         {
807             Table* pFirstCol = static_cast<Table*>(pCols->First());
808             sal_uInt32 nCount = pFirstCol->Count();
809             pFirstCol->First();
810             for (sal_uInt32 n = 0; n < nCount; ++n, pFirstCol->Next())
811             {
812                 sal_uInt32 nKey = pFirstCol->GetCurKey();
813                 pCols->First();
814                 for (pCol = static_cast<Table*>(pCols->Next()); pCol; pCol = static_cast<Table*>(pCols->Next()))
815                     pCol->Insert(nKey, NULL);
816             }
817         }
818     }
819     mpPositionMap.reset(
820         new Chart2PositionMap(
821             static_cast<SCCOL>(nAllColCount), static_cast<SCROW>(nAllRowCount),
822             bFillRowHeader, bFillColumnHeader, *pCols, mpDoc));
823 
824     // Destroy all column instances.
825     for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next()))
826         delete pCol;
827 }
828 
829 // ============================================================================
830 
831 /**
832  * Function object to create a range string from a token list.
833  */
834 class Tokens2RangeString : public unary_function<ScSharedTokenRef, void>
835 {
836 public:
837     Tokens2RangeString(ScDocument* pDoc, FormulaGrammar::Grammar eGram, sal_Unicode cRangeSep) :
838         mpRangeStr(new OUStringBuffer),
839         mpDoc(pDoc),
840         meGrammar(eGram),
841         mcRangeSep(cRangeSep),
842         mbFirst(true)
843     {
844     }
845 
846     Tokens2RangeString(const Tokens2RangeString& r) :
847         mpRangeStr(r.mpRangeStr),
848         mpDoc(r.mpDoc),
849         meGrammar(r.meGrammar),
850         mcRangeSep(r.mcRangeSep),
851         mbFirst(r.mbFirst)
852     {
853     }
854 
855     void operator() (const ScSharedTokenRef& rToken)
856     {
857         ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
858         aCompiler.SetGrammar(meGrammar);
859         String aStr;
860         aCompiler.CreateStringFromToken(aStr, rToken.get());
861         if (mbFirst)
862             mbFirst = false;
863         else
864             mpRangeStr->append(mcRangeSep);
865         mpRangeStr->append(aStr);
866     }
867 
868     void getString(OUString& rStr)
869     {
870         rStr = mpRangeStr->makeStringAndClear();
871     }
872 
873 private:
874     Tokens2RangeString(); // disabled
875 
876 private:
877     shared_ptr<OUStringBuffer>  mpRangeStr;
878     ScDocument*         mpDoc;
879     FormulaGrammar::Grammar  meGrammar;
880     sal_Unicode         mcRangeSep;
881     bool                mbFirst;
882 };
883 
884 /**
885  * Function object to convert a list of tokens into a string form suitable
886  * for ODF export.  In ODF, a range is expressed as
887  *
888  *   (start cell address):(end cell address)
889  *
890  * and each address doesn't include any '$' symbols.
891  */
892 class Tokens2RangeStringXML : public unary_function<ScSharedTokenRef, void>
893 {
894 public:
895     Tokens2RangeStringXML(ScDocument* pDoc) :
896         mpRangeStr(new OUStringBuffer),
897         mpDoc(pDoc),
898         mcRangeSep(' '),
899         mcAddrSep(':'),
900         mbFirst(true)
901     {
902     }
903 
904     Tokens2RangeStringXML(const Tokens2RangeStringXML& r) :
905         mpRangeStr(r.mpRangeStr),
906         mpDoc(r.mpDoc),
907         mcRangeSep(r.mcRangeSep),
908         mcAddrSep(r.mcAddrSep),
909         mbFirst(r.mbFirst)
910     {
911     }
912 
913     void operator() (const ScSharedTokenRef& rToken)
914     {
915         if (mbFirst)
916             mbFirst = false;
917         else
918             mpRangeStr->append(mcRangeSep);
919 
920         ScSharedTokenRef aStart, aEnd;
921         splitRangeToken(rToken, aStart, aEnd);
922         ScCompiler aCompiler(mpDoc, ScAddress(0,0,0));
923         aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH);
924         {
925             String aStr;
926             aCompiler.CreateStringFromToken(aStr, aStart.get());
927             mpRangeStr->append(aStr);
928         }
929         mpRangeStr->append(mcAddrSep);
930         {
931             String aStr;
932             aCompiler.CreateStringFromToken(aStr, aEnd.get());
933             mpRangeStr->append(aStr);
934         }
935     }
936 
937     void getString(OUString& rStr)
938     {
939         rStr = mpRangeStr->makeStringAndClear();
940     }
941 
942 private:
943     Tokens2RangeStringXML(); // disabled
944 
945     void splitRangeToken(const ScSharedTokenRef& pToken, ScSharedTokenRef& rStart, ScSharedTokenRef& rEnd) const
946     {
947         ScComplexRefData aData;
948         ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken);
949         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
950         sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0;
951         String aTabName = bExternal ? pToken->GetString() : String();
952 
953         // In saving to XML, we don't prepend address with '$'.
954         setRelative(aData.Ref1);
955         setRelative(aData.Ref2);
956 
957         // In XML, the end range must explicitly specify sheet name.
958         aData.Ref2.SetFlag3D(true);
959 
960         if (bExternal)
961             rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1));
962         else
963             rStart.reset(new ScSingleRefToken(aData.Ref1));
964 
965         if (bExternal)
966             rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2));
967         else
968             rEnd.reset(new ScSingleRefToken(aData.Ref2));
969     }
970 
971     void setRelative(ScSingleRefData& rData) const
972     {
973         rData.SetColRel(true);
974         rData.SetRowRel(true);
975         rData.SetTabRel(true);
976     }
977 
978 private:
979     shared_ptr<OUStringBuffer>  mpRangeStr;
980     ScDocument*         mpDoc;
981     sal_Unicode         mcRangeSep;
982     sal_Unicode         mcAddrSep;
983     bool                mbFirst;
984 };
985 
986 void lcl_convertTokensToString(OUString& rStr, const vector<ScSharedTokenRef>& rTokens, ScDocument* pDoc)
987 {
988     const sal_Unicode cRangeSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
989     FormulaGrammar::Grammar eGrammar = pDoc->GetGrammar();
990     Tokens2RangeString func(pDoc, eGrammar, cRangeSep);
991     func = for_each(rTokens.begin(), rTokens.end(), func);
992     func.getString(rStr);
993 }
994 
995 } // anonymous namespace
996 
997 // DataProvider ==============================================================
998 
999 ScChart2DataProvider::ScChart2DataProvider( ScDocument* pDoc )
1000     : m_pDocument( pDoc)
1001     , m_aPropSet(lcl_GetDataProviderPropertyMap())
1002     , m_bIncludeHiddenCells( sal_True)
1003 {
1004     if ( m_pDocument )
1005         m_pDocument->AddUnoObject( *this);
1006 }
1007 
1008 ScChart2DataProvider::~ScChart2DataProvider()
1009 {
1010     if ( m_pDocument )
1011         m_pDocument->RemoveUnoObject( *this);
1012 }
1013 
1014 
1015 void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
1016 {
1017     if ( rHint.ISA( SfxSimpleHint ) &&
1018             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
1019     {
1020         m_pDocument = NULL;
1021     }
1022 }
1023 
1024 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSourcePossible( const uno::Sequence< beans::PropertyValue >& aArguments )
1025     throw (uno::RuntimeException)
1026 {
1027     ScUnoGuard aGuard;
1028     if( ! m_pDocument )
1029         return false;
1030 
1031     rtl::OUString aRangeRepresentation;
1032     for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1033     {
1034         rtl::OUString sName(aArguments[i].Name);
1035         if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1036         {
1037             aArguments[i].Value >>= aRangeRepresentation;
1038         }
1039     }
1040 
1041     vector<ScSharedTokenRef> aTokens;
1042     ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1043     return !aTokens.empty();
1044 }
1045 
1046 namespace
1047 {
1048 
1049 Reference< chart2::data::XLabeledDataSequence > lcl_createLabeledDataSequenceFromTokens(
1050     auto_ptr< vector< ScSharedTokenRef > > pValueTokens, auto_ptr< vector< ScSharedTokenRef > > pLabelTokens,
1051     ScDocument* pDoc, const Reference< chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells )
1052 {
1053     Reference< chart2::data::XLabeledDataSequence >  xResult;
1054     bool bHasValues = pValueTokens.get() && !pValueTokens->empty();
1055     bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty();
1056     if( bHasValues || bHasLabel )
1057     {
1058         try
1059         {
1060             Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1061             if ( xContext.is() )
1062             {
1063                 xResult.set( xContext->getServiceManager()->createInstanceWithContext(
1064                     ::rtl::OUString::createFromAscii( "com.sun.star.chart2.data.LabeledDataSequence" ),
1065                         xContext ), uno::UNO_QUERY_THROW );
1066             }
1067             if ( bHasValues )
1068             {
1069                 Reference< chart2::data::XDataSequence > xSeq( new ScChart2DataSequence( pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells ) );
1070                 xResult->setValues( xSeq );
1071             }
1072             if ( bHasLabel )
1073             {
1074                 Reference< chart2::data::XDataSequence > xLabelSeq( new ScChart2DataSequence( pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells ) );
1075                 xResult->setLabel( xLabelSeq );
1076             }
1077         }
1078         catch( const uno::Exception& )
1079         {
1080         }
1081     }
1082     return xResult;
1083 }
1084 
1085 //----------------------------------------------------
1086 /**
1087  * Check the current list of reference tokens, and add the upper left
1088  * corner of the minimum range that encloses all ranges if certain
1089  * conditions are met.
1090  *
1091  * @param rRefTokens list of reference tokens
1092  *
1093  * @return true if the corner was added, false otherwise.
1094  */
1095 bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens,
1096             SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1)
1097 {
1098     using ::std::max;
1099     using ::std::min;
1100 
1101     if (rRefTokens.empty())
1102         return false;
1103 
1104     SCCOL nMinCol = MAXCOLCOUNT;
1105     SCROW nMinRow = MAXROWCOUNT;
1106     SCCOL nMaxCol = 0;
1107     SCROW nMaxRow = 0;
1108     SCTAB nTab    = 0;
1109 
1110     sal_uInt16 nFileId = 0;
1111     String aExtTabName;
1112     bool bExternal = false;
1113 
1114     vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end();
1115 
1116     // Get the first ref token.
1117     ScSharedTokenRef pToken = *itr;
1118     switch (pToken->GetType())
1119     {
1120         case svSingleRef:
1121         {
1122             const ScSingleRefData& rData = pToken->GetSingleRef();
1123             nMinCol = rData.nCol;
1124             nMinRow = rData.nRow;
1125             nMaxCol = rData.nCol;
1126             nMaxRow = rData.nRow;
1127             nTab = rData.nTab;
1128         }
1129         break;
1130         case svDoubleRef:
1131         {
1132             const ScComplexRefData& rData = pToken->GetDoubleRef();
1133             nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1134             nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1135             nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1136             nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1137             nTab = rData.Ref1.nTab;
1138         }
1139         break;
1140         case svExternalSingleRef:
1141         {
1142             const ScSingleRefData& rData = pToken->GetSingleRef();
1143             nMinCol = rData.nCol;
1144             nMinRow = rData.nRow;
1145             nMaxCol = rData.nCol;
1146             nMaxRow = rData.nRow;
1147             nTab = rData.nTab;
1148             nFileId = pToken->GetIndex();
1149             aExtTabName = pToken->GetString();
1150             bExternal = true;
1151         }
1152         break;
1153         case svExternalDoubleRef:
1154         {
1155             const ScComplexRefData& rData = pToken->GetDoubleRef();
1156             nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol);
1157             nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow);
1158             nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol);
1159             nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow);
1160             nTab = rData.Ref1.nTab;
1161             nFileId = pToken->GetIndex();
1162             aExtTabName = pToken->GetString();
1163             bExternal = true;
1164         }
1165         break;
1166         default:
1167             ;
1168     }
1169 
1170     // Determine the minimum range enclosing all data ranges.  Also make sure
1171     // that they are all on the same table.
1172 
1173     for (++itr; itr != itrEnd; ++itr)
1174     {
1175         pToken = *itr;
1176         switch (pToken->GetType())
1177         {
1178             case svSingleRef:
1179             {
1180                 const ScSingleRefData& rData = pToken->GetSingleRef();
1181 
1182                 nMinCol = min(nMinCol, rData.nCol);
1183                 nMinRow = min(nMinRow, rData.nRow);
1184                 nMaxCol = max(nMaxCol, rData.nCol);
1185                 nMaxRow = max(nMaxRow, rData.nRow);
1186                 if (nTab != rData.nTab || bExternal)
1187                     return false;
1188             }
1189             break;
1190             case svDoubleRef:
1191             {
1192                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1193 
1194                 nMinCol = min(nMinCol, rData.Ref1.nCol);
1195                 nMinCol = min(nMinCol, rData.Ref2.nCol);
1196                 nMinRow = min(nMinRow, rData.Ref1.nRow);
1197                 nMinRow = min(nMinRow, rData.Ref2.nRow);
1198 
1199                 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1200                 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1201                 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1202                 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1203 
1204                 if (nTab != rData.Ref1.nTab || bExternal)
1205                     return false;
1206             }
1207             break;
1208             case svExternalSingleRef:
1209             {
1210                 if (!bExternal)
1211                     return false;
1212 
1213                 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1214                     return false;
1215 
1216                 const ScSingleRefData& rData = pToken->GetSingleRef();
1217 
1218                 nMinCol = min(nMinCol, rData.nCol);
1219                 nMinRow = min(nMinRow, rData.nRow);
1220                 nMaxCol = max(nMaxCol, rData.nCol);
1221                 nMaxRow = max(nMaxRow, rData.nRow);
1222             }
1223             break;
1224             case svExternalDoubleRef:
1225             {
1226                 if (!bExternal)
1227                     return false;
1228 
1229                 if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString())
1230                     return false;
1231 
1232                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1233 
1234                 nMinCol = min(nMinCol, rData.Ref1.nCol);
1235                 nMinCol = min(nMinCol, rData.Ref2.nCol);
1236                 nMinRow = min(nMinRow, rData.Ref1.nRow);
1237                 nMinRow = min(nMinRow, rData.Ref2.nRow);
1238 
1239                 nMaxCol = max(nMaxCol, rData.Ref1.nCol);
1240                 nMaxCol = max(nMaxCol, rData.Ref2.nCol);
1241                 nMaxRow = max(nMaxRow, rData.Ref1.nRow);
1242                 nMaxRow = max(nMaxRow, rData.Ref2.nRow);
1243             }
1244             break;
1245             default:
1246                 ;
1247         }
1248     }
1249 
1250     if (nMinRow >= nMaxRow || nMinCol >= nMaxCol ||
1251         nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT ||
1252         nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT)
1253     {
1254         // Invalid range.  Bail out.
1255         return false;
1256     }
1257 
1258     // Check if the following conditions are met:
1259     //
1260     // 1) The upper-left corner cell is not included.
1261     // 2) The three adjacent cells of that corner cell are included.
1262 
1263     bool bRight = false, bBottom = false, bDiagonal = false;
1264     for (itr = rRefTokens.begin(); itr != itrEnd; ++itr)
1265     {
1266         pToken = *itr;
1267         switch (pToken->GetType())
1268         {
1269             case svSingleRef:
1270             case svExternalSingleRef:
1271             {
1272                 const ScSingleRefData& rData = pToken->GetSingleRef();
1273                 if (rData.nCol == nMinCol && rData.nRow == nMinRow)
1274                     // The corner cell is contained.
1275                     return false;
1276 
1277                 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow)
1278                     bRight = true;
1279 
1280                 if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount)
1281                     bBottom = true;
1282 
1283                 if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount)
1284                     bDiagonal = true;
1285             }
1286             break;
1287             case svDoubleRef:
1288             case svExternalDoubleRef:
1289             {
1290                 const ScComplexRefData& rData = pToken->GetDoubleRef();
1291                 const ScSingleRefData& r1 = rData.Ref1;
1292                 const ScSingleRefData& r2 = rData.Ref2;
1293                 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1294                     r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1295                     // The corner cell is contained.
1296                     return false;
1297 
1298                 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
1299                     r1.nRow <= nMinRow && nMinRow <= r2.nRow)
1300                     bRight = true;
1301 
1302                 if (r1.nCol <= nMinCol && nMinCol <= r2.nCol &&
1303                     r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
1304                     bBottom = true;
1305 
1306                 if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol &&
1307                     r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow)
1308                     bDiagonal = true;
1309             }
1310             break;
1311             default:
1312                 ;
1313         }
1314     }
1315 
1316     if (!bRight || !bBottom || !bDiagonal)
1317         // Not all the adjacent cells are included.  Bail out.
1318         return false;
1319 
1320 #if 0 // Do we really need to do this ???
1321     if (rRefTokens.size() == 2)
1322     {
1323         // Make a simple rectangular range if possible.
1324         ScRange aRightPart(ScAddress(nMinCol+1, nMinRow,   nTab),  ScAddress(nMaxCol, nMaxRow, nTab));
1325         ScRange aBottomPart(ScAddress(nMinCol,  nMinRow+1, nTab),  ScAddress(nMaxCol, nMaxRow, nTab));
1326         vector<ScRange> aRanges;
1327         aRanges.reserve(2);
1328         aRanges.push_back(aRightPart);
1329         aRanges.push_back(aBottomPart);
1330         if (lcl_isRangeContained(rRefTokens, aRanges))
1331         {
1332             // Consolidate them into a single rectangle.
1333             ScComplexRefData aData;
1334             aData.InitFlags();
1335             aData.Ref1.SetFlag3D(true);
1336             aData.Ref1.SetColRel(false);
1337             aData.Ref1.SetRowRel(false);
1338             aData.Ref1.SetTabRel(false);
1339             aData.Ref2.SetColRel(false);
1340             aData.Ref2.SetRowRel(false);
1341             aData.Ref2.SetTabRel(false);
1342             aData.Ref1.nCol = nMinCol;
1343             aData.Ref1.nRow = nMinRow;
1344             aData.Ref1.nTab = nTab;
1345             aData.Ref2.nCol = nMaxCol;
1346             aData.Ref2.nRow = nMaxRow;
1347             aData.Ref2.nTab = nTab;
1348             vector<ScSharedTokenRef> aNewTokens;
1349             aNewTokens.reserve(1);
1350             if (bExternal)
1351             {
1352                 ScSharedTokenRef p(
1353                     new ScExternalDoubleRefToken(nFileId, aExtTabName, aData));
1354                 aNewTokens.push_back(p);
1355             }
1356             else
1357             {
1358                 ScSharedTokenRef p(new ScDoubleRefToken(aData));
1359                 aNewTokens.push_back(p);
1360             }
1361             rRefTokens.swap(aNewTokens);
1362             return true;
1363         }
1364     }
1365 #endif
1366 
1367     ScSingleRefData aData;
1368     aData.InitFlags();
1369     aData.SetFlag3D(true);
1370     aData.SetColRel(false);
1371     aData.SetRowRel(false);
1372     aData.SetTabRel(false);
1373     aData.nCol = nMinCol;
1374     aData.nRow = nMinRow;
1375     aData.nTab = nTab;
1376 
1377     if( nCornerRowCount==1 && nCornerColumnCount==1 )
1378     {
1379         if (bExternal)
1380         {
1381             ScSharedTokenRef pCorner(
1382                 new ScExternalSingleRefToken(nFileId, aExtTabName, aData));
1383             ScRefTokenHelper::join(rRefTokens, pCorner);
1384         }
1385         else
1386         {
1387             ScSharedTokenRef pCorner(new ScSingleRefToken(aData));
1388             ScRefTokenHelper::join(rRefTokens, pCorner);
1389         }
1390     }
1391     else
1392     {
1393         ScSingleRefData aDataEnd(aData);
1394         aDataEnd.nCol += (nCornerColumnCount-1);
1395         aDataEnd.nRow += (nCornerRowCount-1);
1396         ScComplexRefData r;
1397         r.Ref1=aData;
1398         r.Ref2=aDataEnd;
1399         if (bExternal)
1400         {
1401             ScSharedTokenRef pCorner(
1402                 new ScExternalDoubleRefToken(nFileId, aExtTabName, r));
1403             ScRefTokenHelper::join(rRefTokens, pCorner);
1404         }
1405         else
1406         {
1407             ScSharedTokenRef pCorner(new ScDoubleRefToken(r));
1408             ScRefTokenHelper::join(rRefTokens, pCorner);
1409         }
1410     }
1411 
1412     return true;
1413 }
1414 
1415 }
1416 
1417 uno::Reference< chart2::data::XDataSource> SAL_CALL
1418 ScChart2DataProvider::createDataSource(
1419     const uno::Sequence< beans::PropertyValue >& aArguments )
1420     throw( lang::IllegalArgumentException, uno::RuntimeException)
1421 {
1422     ScUnoGuard aGuard;
1423     if ( ! m_pDocument )
1424         throw uno::RuntimeException();
1425 
1426     uno::Reference< chart2::data::XDataSource> xResult;
1427     bool bLabel = true;
1428     bool bCategories = false;
1429     bool bOrientCol = true;
1430     ::rtl::OUString aRangeRepresentation;
1431     uno::Sequence< sal_Int32 > aSequenceMapping;
1432     for(sal_Int32 i = 0; i < aArguments.getLength(); ++i)
1433     {
1434         rtl::OUString sName(aArguments[i].Name);
1435         if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource")))
1436         {
1437             chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS;
1438             if( ! (aArguments[i].Value >>= eSource))
1439             {
1440                 sal_Int32 nSource(0);
1441                 if( aArguments[i].Value >>= nSource )
1442                     eSource = (static_cast< chart::ChartDataRowSource >( nSource ));
1443             }
1444             bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS);
1445         }
1446         else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel")))
1447         {
1448             bLabel = ::cppu::any2bool(aArguments[i].Value);
1449         }
1450         else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories")))
1451         {
1452             bCategories = ::cppu::any2bool(aArguments[i].Value);
1453         }
1454         else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation")))
1455         {
1456             aArguments[i].Value >>= aRangeRepresentation;
1457         }
1458         else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping")))
1459         {
1460             aArguments[i].Value >>= aSequenceMapping;
1461         }
1462     }
1463 
1464     vector<ScSharedTokenRef> aRefTokens;
1465     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
1466     if (aRefTokens.empty())
1467         // Invalid range representation.  Bail out.
1468         throw lang::IllegalArgumentException();
1469 
1470     if (bLabel)
1471         lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669#
1472 
1473     bool bColHeaders = (bOrientCol ? bLabel : bCategories );
1474     bool bRowHeaders = (bOrientCol ? bCategories : bLabel );
1475 
1476     Chart2Positioner aChPositioner(m_pDocument, aRefTokens);
1477     aChPositioner.setHeaders(bColHeaders, bRowHeaders);
1478 
1479     const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap();
1480     if (!pChartMap)
1481         // No chart position map instance.  Bail out.
1482         return xResult;
1483 
1484     ScChart2DataSource* pDS = NULL;
1485     ::std::list< Reference< chart2::data::XLabeledDataSequence > > aSeqs;
1486 
1487     // Fill Categories
1488     if( bCategories )
1489     {
1490         auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
1491         if (bOrientCol)
1492             pValueTokens.reset(pChartMap->getAllRowHeaderRanges());
1493         else
1494             pValueTokens.reset(pChartMap->getAllColHeaderRanges());
1495 
1496         auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
1497             pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges());
1498 
1499         Reference< chart2::data::XLabeledDataSequence > xCategories = lcl_createLabeledDataSequenceFromTokens(
1500             pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered!
1501         if ( xCategories.is() )
1502         {
1503             aSeqs.push_back( xCategories );
1504         }
1505     }
1506 
1507     // Fill Serieses (values and label)
1508     sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount();
1509     for (sal_Int32 i = 0; i < nCount; ++i)
1510     {
1511         auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL);
1512         auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL);
1513         if (bOrientCol)
1514         {
1515             pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i)));
1516             pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i)));
1517         }
1518         else
1519         {
1520             pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i)));
1521             pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i)));
1522         }
1523         Reference< chart2::data::XLabeledDataSequence > xChartSeries = lcl_createLabeledDataSequenceFromTokens(
1524             pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered!
1525         if ( xChartSeries.is() )
1526         {
1527             aSeqs.push_back( xChartSeries );
1528         }
1529     }
1530 
1531     pDS = new ScChart2DataSource(m_pDocument);
1532     ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aItr( aSeqs.begin() );
1533     ::std::list< Reference< chart2::data::XLabeledDataSequence > >::iterator aEndItr( aSeqs.end() );
1534 
1535     //reorder labeled sequences according to aSequenceMapping
1536     ::std::vector< Reference< chart2::data::XLabeledDataSequence > > aSeqVector;
1537     while(aItr != aEndItr)
1538     {
1539         aSeqVector.push_back(*aItr);
1540         ++aItr;
1541     }
1542 
1543     ::std::map< sal_Int32, Reference< chart2::data::XLabeledDataSequence > > aSequenceMap;
1544     for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ )
1545     {
1546         // note: assuming that the values in the sequence mapping are always non-negative
1547         ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] ) );
1548         if( nOldIndex < aSeqVector.size() )
1549         {
1550             pDS->AddLabeledSequence( aSeqVector[nOldIndex] );
1551             aSeqVector[nOldIndex] = 0;
1552         }
1553     }
1554 
1555     ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorItr( aSeqVector.begin() );
1556     ::std::vector< Reference< chart2::data::XLabeledDataSequence > >::iterator aVectorEndItr( aSeqVector.end() );
1557     while(aVectorItr != aVectorEndItr)
1558     {
1559         Reference< chart2::data::XLabeledDataSequence > xSeq( *aVectorItr );
1560         if ( xSeq.is() )
1561         {
1562             pDS->AddLabeledSequence( xSeq );
1563         }
1564         ++aVectorItr;
1565     }
1566 
1567     xResult.set( pDS );
1568     return xResult;
1569 }
1570 
1571 namespace
1572 {
1573 
1574 /**
1575  * Function object to create a list of table numbers from a token list.
1576  */
1577 class InsertTabNumber : public unary_function<ScSharedTokenRef, void>
1578 {
1579 public:
1580     InsertTabNumber() :
1581         mpTabNumList(new list<SCTAB>())
1582     {
1583     }
1584 
1585     InsertTabNumber(const InsertTabNumber& r) :
1586         mpTabNumList(r.mpTabNumList)
1587     {
1588     }
1589 
1590     void operator() (const ScSharedTokenRef& pToken) const
1591     {
1592         if (!ScRefTokenHelper::isRef(pToken))
1593             return;
1594 
1595         const ScSingleRefData& r = pToken->GetSingleRef();
1596         mpTabNumList->push_back(r.nTab);
1597     }
1598 
1599     void getList(list<SCTAB>& rList)
1600     {
1601         mpTabNumList->swap(rList);
1602     }
1603 private:
1604     shared_ptr< list<SCTAB> > mpTabNumList;
1605 };
1606 
1607 class RangeAnalyzer
1608 {
1609 public:
1610     RangeAnalyzer();
1611     void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens );
1612     void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols,
1613             bool& rbRowSourceAmbiguous ) const;
1614     bool inSameSingleRow( RangeAnalyzer& rOther );
1615     bool inSameSingleColumn( RangeAnalyzer& rOther );
1616     SCROW getRowCount() { return mnRowCount; }
1617     SCCOL getColumnCount() { return mnColumnCount; }
1618 
1619 private:
1620     bool mbEmpty;
1621     bool mbAmbiguous;
1622     SCROW mnRowCount;
1623     SCCOL mnColumnCount;
1624 
1625     SCCOL mnStartColumn;
1626     SCROW mnStartRow;
1627 };
1628 
1629 RangeAnalyzer::RangeAnalyzer()
1630     : mbEmpty(true)
1631     , mbAmbiguous(false)
1632     , mnRowCount(0)
1633     , mnColumnCount(0)
1634     , mnStartColumn(-1)
1635     , mnStartRow(-1)
1636 {
1637 }
1638 
1639 void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens )
1640 {
1641     mnRowCount=0;
1642     mnColumnCount=0;
1643     mnStartColumn = -1;
1644     mnStartRow = -1;
1645     mbAmbiguous=false;
1646     if( rTokens.empty() )
1647     {
1648         mbEmpty=true;
1649         return;
1650     }
1651     mbEmpty=false;
1652 
1653     vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end();
1654     for (; itr != itrEnd ; ++itr)
1655     {
1656         ScSharedTokenRef aRefToken = *itr;
1657         StackVar eVar = aRefToken->GetType();
1658         if (eVar == svDoubleRef || eVar == svExternalDoubleRef)
1659         {
1660             const ScComplexRefData& r = aRefToken->GetDoubleRef();
1661             if (r.Ref1.nTab == r.Ref2.nTab)
1662             {
1663                 mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) );
1664                 mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) );
1665                 if( mnStartColumn == -1 )
1666                 {
1667                     mnStartColumn = r.Ref1.nCol;
1668                     mnStartRow = r.Ref1.nRow;
1669                 }
1670                 else
1671                 {
1672                     if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow )
1673                         mbAmbiguous=true;
1674                 }
1675             }
1676             else
1677                 mbAmbiguous=true;
1678         }
1679         else if (eVar == svSingleRef || eVar == svExternalSingleRef)
1680         {
1681             const ScSingleRefData& r = aRefToken->GetSingleRef();
1682             mnColumnCount = std::max<SCCOL>( mnColumnCount, 1);
1683             mnRowCount = std::max<SCROW>( mnRowCount, 1);
1684             if( mnStartColumn == -1 )
1685             {
1686                 mnStartColumn = r.nCol;
1687                 mnStartRow = r.nRow;
1688             }
1689             else
1690             {
1691                 if( mnStartColumn != r.nCol && mnStartRow != r.nRow )
1692                     mbAmbiguous=true;
1693             }
1694         }
1695         else
1696             mbAmbiguous=true;
1697     }
1698 }
1699 
1700 void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows,
1701                                      sal_Int32& rnDataInCols,
1702                                      bool& rbRowSourceAmbiguous ) const
1703 {
1704     if(!mbEmpty && !mbAmbiguous)
1705     {
1706         if( mnRowCount==1 && mnColumnCount>1 )
1707             ++rnDataInRows;
1708         else if( mnColumnCount==1 && mnRowCount>1 )
1709             ++rnDataInCols;
1710         else if( mnRowCount>1 && mnColumnCount>1 )
1711             rbRowSourceAmbiguous = true;
1712     }
1713     else if( !mbEmpty )
1714         rbRowSourceAmbiguous = true;
1715 }
1716 
1717 bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther )
1718 {
1719     if( mnStartRow==rOther.mnStartRow &&
1720         mnRowCount==1 && rOther.mnRowCount==1 )
1721         return true;
1722     return false;
1723 }
1724 
1725 bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther )
1726 {
1727     if( mnStartColumn==rOther.mnStartColumn &&
1728         mnColumnCount==1 && rOther.mnColumnCount==1 )
1729         return true;
1730     return false;
1731 }
1732 
1733 } //end anonymous namespace
1734 
1735 uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments(
1736     const uno::Reference< chart2::data::XDataSource >& xDataSource )
1737     throw (uno::RuntimeException)
1738 {
1739     ::std::vector< beans::PropertyValue > aResult;
1740     bool bRowSourceDetected = false;
1741     bool bFirstCellAsLabel = false;
1742     bool bHasCategories = false;
1743     ::rtl::OUString sRangeRep;
1744 
1745     bool bHasCategoriesLabels = false;
1746     vector<ScSharedTokenRef> aAllCategoriesValuesTokens;
1747     vector<ScSharedTokenRef> aAllSeriesLabelTokens;
1748 
1749     chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS;
1750 
1751     vector<ScSharedTokenRef> aAllTokens;
1752 
1753     // parse given data source and collect infos
1754     {
1755         ScUnoGuard aGuard;
1756         DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" );
1757         if(!m_pDocument ||!xDataSource.is())
1758             return lcl_VectorToSequence( aResult );
1759 
1760         sal_Int32 nDataInRows = 0;
1761         sal_Int32 nDataInCols = 0;
1762         bool bRowSourceAmbiguous = false;
1763 
1764         Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences());
1765         const sal_Int32 nCount( aSequences.getLength());
1766         RangeAnalyzer aPrevLabel,aPrevValues;
1767         for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx )
1768         {
1769             Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]);
1770             if( xLS.is() )
1771             {
1772                 bool bThisIsCategories = false;
1773                 if(!bHasCategories)
1774                 {
1775                     Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY );
1776                     ::rtl::OUString aRole;
1777                     if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) &&
1778                         aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) )
1779                         bThisIsCategories = bHasCategories = true;
1780                 }
1781 
1782                 RangeAnalyzer aLabel,aValues;
1783                 // label
1784                 Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel());
1785                 if( xLabel.is())
1786                 {
1787                     bFirstCellAsLabel = true;
1788                     vector<ScSharedTokenRef> aTokens;
1789                     ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
1790                     aLabel.initRangeAnalyzer(aTokens);
1791                     vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
1792                     for (; itr != itrEnd; ++itr)
1793                     {
1794                         ScRefTokenHelper::join(aAllTokens, *itr);
1795                         if(!bThisIsCategories)
1796                             ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr);
1797                     }
1798                     if(bThisIsCategories)
1799                         bHasCategoriesLabels=true;
1800                 }
1801                 // values
1802                 Reference< chart2::data::XDataSequence > xValues( xLS->getValues());
1803                 if( xValues.is())
1804                 {
1805                     vector<ScSharedTokenRef> aTokens;
1806                     ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() );
1807                     aValues.initRangeAnalyzer(aTokens);
1808                     vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end();
1809                     for (; itr != itrEnd; ++itr)
1810                     {
1811                         ScRefTokenHelper::join(aAllTokens, *itr);
1812                         if(bThisIsCategories)
1813                             ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr);
1814                     }
1815                 }
1816                 //detect row source
1817                 if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available
1818                 {
1819                     if (!bRowSourceAmbiguous)
1820                     {
1821                         aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
1822                         aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous);
1823                         if (nDataInRows > 1 && nDataInCols > 1)
1824                             bRowSourceAmbiguous = true;
1825                         else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols )
1826                         {
1827                             if( aValues.inSameSingleColumn( aLabel ) )
1828                                 nDataInCols++;
1829                             else if( aValues.inSameSingleRow( aLabel ) )
1830                                 nDataInRows++;
1831                             else
1832                             {
1833                                 //#i86188# also detect a single column split into rows correctly
1834                                 if( aValues.inSameSingleColumn( aPrevValues ) )
1835                                     nDataInRows++;
1836                                 else if( aValues.inSameSingleRow( aPrevValues ) )
1837                                     nDataInCols++;
1838                                 else if( aLabel.inSameSingleColumn( aPrevLabel ) )
1839                                     nDataInRows++;
1840                                 else if( aLabel.inSameSingleRow( aPrevLabel ) )
1841                                     nDataInCols++;
1842                             }
1843                         }
1844                     }
1845                 }
1846                 aPrevValues=aValues;
1847                 aPrevLabel=aLabel;
1848             }
1849         }
1850 
1851         if (!bRowSourceAmbiguous)
1852         {
1853             bRowSourceDetected = true;
1854             eRowSource = ( nDataInRows > 0
1855                            ? chart::ChartDataRowSource_ROWS
1856                            : chart::ChartDataRowSource_COLUMNS );
1857         }
1858         else
1859         {
1860             // set DataRowSource to the better of the two ambiguities
1861             eRowSource = ( nDataInRows > nDataInCols
1862                            ? chart::ChartDataRowSource_ROWS
1863                            : chart::ChartDataRowSource_COLUMNS );
1864         }
1865 
1866     }
1867 
1868     // TableNumberList
1869     {
1870         list<SCTAB> aTableNumList;
1871         InsertTabNumber func;
1872         func = for_each(aAllTokens.begin(), aAllTokens.end(), func);
1873         func.getList(aTableNumList);
1874         aResult.push_back(
1875             beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1,
1876                                   uno::makeAny( lcl_createTableNumberList( aTableNumList ) ),
1877                                   beans::PropertyState_DIRECT_VALUE ));
1878     }
1879 
1880     // DataRowSource (calculated before)
1881     if( bRowSourceDetected )
1882     {
1883         aResult.push_back(
1884             beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1,
1885                                   uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE ));
1886     }
1887 
1888     // HasCategories
1889     if( bRowSourceDetected )
1890     {
1891         aResult.push_back(
1892             beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1,
1893                                   uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE ));
1894     }
1895 
1896     // FirstCellAsLabel
1897     if( bRowSourceDetected )
1898     {
1899         aResult.push_back(
1900             beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1,
1901                                   uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE ));
1902     }
1903 
1904     // Add the left upper corner to the range if it is missing.
1905     if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels )
1906     {
1907         RangeAnalyzer aTop,aLeft;
1908         if( eRowSource==chart::ChartDataRowSource_COLUMNS )
1909         {
1910             aTop.initRangeAnalyzer(aAllSeriesLabelTokens);
1911             aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens);
1912         }
1913         else
1914         {
1915             aTop.initRangeAnalyzer(aAllCategoriesValuesTokens);
1916             aLeft.initRangeAnalyzer(aAllSeriesLabelTokens);
1917         }
1918         lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212#
1919     }
1920 
1921     // Get range string.
1922     lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument);
1923 
1924     // add cell range property
1925     aResult.push_back(
1926         beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1,
1927                               uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE ));
1928 
1929     //Sequence Mapping
1930     bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ...
1931     if( bSequencesReordered && bRowSourceDetected )
1932     {
1933         bool bDifferentIndexes = false;
1934 
1935         std::vector< sal_Int32 > aSequenceMappingVector;
1936 
1937         uno::Reference< chart2::data::XDataSource > xCompareDataSource;
1938         try
1939         {
1940             xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) );
1941         }
1942         catch( const lang::IllegalArgumentException & )
1943         {
1944             // creation of data source to compare didn't work, so we cannot
1945             // create a sequence mapping
1946         }
1947 
1948         if( xDataSource.is() && xCompareDataSource.is() )
1949         {
1950             uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences(
1951                 xCompareDataSource->getDataSequences() );
1952             uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences(
1953                 xDataSource->getDataSequences());
1954 
1955             rtl::OUString aOldLabel;
1956             rtl::OUString aNewLabel;
1957             rtl::OUString aOldValues;
1958             rtl::OUString aNewValues;
1959             rtl::OUString aEmpty;
1960 
1961             for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ )
1962             {
1963                 uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] );
1964                 for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ )
1965                 {
1966                     uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] );
1967 
1968                     if( xOld.is() && xNew.is() )
1969                     {
1970                         aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty;
1971                         if( xOld.is() && xOld->getLabel().is() )
1972                             aOldLabel = xOld->getLabel()->getSourceRangeRepresentation();
1973                         if( xNew.is() && xNew->getLabel().is() )
1974                             aNewLabel = xNew->getLabel()->getSourceRangeRepresentation();
1975                         if( xOld.is() && xOld->getValues().is() )
1976                             aOldValues = xOld->getValues()->getSourceRangeRepresentation();
1977                         if( xNew.is() && xNew->getValues().is() )
1978                             aNewValues = xNew->getValues()->getSourceRangeRepresentation();
1979 
1980                         if( aOldLabel.equals(aNewLabel)
1981                             && ( aOldValues.equals(aNewValues) ) )
1982                         {
1983                             if( nOldIndex!=nNewIndex )
1984                                 bDifferentIndexes = true;
1985                             aSequenceMappingVector.push_back(nOldIndex);
1986                             break;
1987                         }
1988                     }
1989                 }
1990             }
1991         }
1992 
1993         if( bDifferentIndexes && aSequenceMappingVector.size() )
1994         {
1995             aResult.push_back(
1996                 beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1,
1997                     uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) )
1998                     , beans::PropertyState_DIRECT_VALUE ));
1999         }
2000     }
2001 
2002     return lcl_VectorToSequence( aResult );
2003 }
2004 
2005 ::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation )
2006     throw (uno::RuntimeException)
2007 {
2008     ScUnoGuard aGuard;
2009     if( ! m_pDocument )
2010         return false;
2011 
2012     vector<ScSharedTokenRef> aTokens;
2013     ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2014     return !aTokens.empty();
2015 }
2016 
2017 uno::Reference< chart2::data::XDataSequence > SAL_CALL
2018     ScChart2DataProvider::createDataSequenceByRangeRepresentation(
2019     const ::rtl::OUString& aRangeRepresentation )
2020     throw (lang::IllegalArgumentException,
2021            uno::RuntimeException)
2022 {
2023     ScUnoGuard aGuard;
2024     uno::Reference< chart2::data::XDataSequence > xResult;
2025 
2026     DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" );
2027     if(!m_pDocument || (aRangeRepresentation.getLength() == 0))
2028         return xResult;
2029 
2030     // Note: the range representation must be in Calc A1 format.  The import
2031     // filters use this method to pass data ranges, and they have no idea what
2032     // the current formula syntax is.  In the future we should add another
2033     // method to allow the client code to directly pass tokens representing
2034     // ranges.
2035 
2036     vector<ScSharedTokenRef> aRefTokens;
2037     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument);
2038     if (aRefTokens.empty())
2039         return xResult;
2040 
2041     // ScChart2DataSequence manages the life cycle of pRefTokens.
2042     vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>();
2043     pRefTokens->swap(aRefTokens);
2044     xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells));
2045 
2046     return xResult;
2047 }
2048 
2049 uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection()
2050     throw (uno::RuntimeException)
2051 {
2052     uno::Reference< sheet::XRangeSelection > xResult;
2053 
2054     uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument ));
2055     if( xModel.is())
2056         xResult.set( xModel->getCurrentController(), uno::UNO_QUERY );
2057 
2058     return xResult;
2059 }
2060 
2061 /*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier()
2062     throw (uno::RuntimeException)
2063 {
2064     return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY );
2065 }*/
2066 
2067 // XRangeXMLConversion ---------------------------------------------------
2068 
2069 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation )
2070     throw ( uno::RuntimeException, lang::IllegalArgumentException )
2071 {
2072     OUString aRet;
2073     if (!m_pDocument)
2074         return aRet;
2075 
2076     if (!sRangeRepresentation.getLength())
2077         // Empty data range is allowed.
2078         return aRet;
2079 
2080     vector<ScSharedTokenRef> aRefTokens;
2081     ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar());
2082     if (aRefTokens.empty())
2083         throw lang::IllegalArgumentException();
2084 
2085     Tokens2RangeStringXML converter(m_pDocument);
2086     converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter);
2087     converter.getString(aRet);
2088 
2089     return aRet;
2090 }
2091 
2092 rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange )
2093     throw ( uno::RuntimeException, lang::IllegalArgumentException )
2094 {
2095     const sal_Unicode cSep = ' ';
2096     const sal_Unicode cQuote = '\'';
2097 
2098     if (!m_pDocument)
2099     {
2100         // #i74062# When loading flat XML, this is called before the referenced sheets are in the document,
2101         // so the conversion has to take place directly with the strings, without looking up the sheets.
2102 
2103         rtl::OUStringBuffer sRet;
2104         sal_Int32 nOffset = 0;
2105         while( nOffset >= 0 )
2106         {
2107             rtl::OUString sToken;
2108             ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote );
2109             if( nOffset >= 0 )
2110             {
2111                 // convert one address (remove dots)
2112 
2113                 String aUIString(sToken);
2114 
2115                 sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote );
2116                 if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 &&
2117                         aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' )
2118                     aUIString.Erase( (xub_StrLen)nIndex + 1, 1 );
2119 
2120                 if ( aUIString.GetChar(0) == (sal_Unicode) '.' )
2121                     aUIString.Erase( 0, 1 );
2122 
2123                 if( sRet.getLength() )
2124                     sRet.append( (sal_Unicode) ';' );
2125                 sRet.append( aUIString );
2126             }
2127         }
2128 
2129         return sRet.makeStringAndClear();
2130     }
2131 
2132     OUString aRet;
2133     ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument);
2134     return aRet;
2135 }
2136 
2137 // DataProvider XPropertySet -------------------------------------------------
2138 
2139 uno::Reference< beans::XPropertySetInfo> SAL_CALL
2140 ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException)
2141 {
2142 	ScUnoGuard aGuard;
2143 	static uno::Reference<beans::XPropertySetInfo> aRef =
2144 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
2145 	return aRef;
2146 }
2147 
2148 
2149 void SAL_CALL ScChart2DataProvider::setPropertyValue(
2150         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
2151             throw( beans::UnknownPropertyException,
2152                     beans::PropertyVetoException,
2153                     lang::IllegalArgumentException,
2154                     lang::WrappedTargetException, uno::RuntimeException)
2155 {
2156     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2157     {
2158         if ( !(rValue >>= m_bIncludeHiddenCells))
2159             throw lang::IllegalArgumentException();
2160     }
2161     else
2162         throw beans::UnknownPropertyException();
2163 }
2164 
2165 
2166 uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue(
2167         const ::rtl::OUString& rPropertyName)
2168             throw( beans::UnknownPropertyException,
2169                     lang::WrappedTargetException, uno::RuntimeException)
2170 {
2171     uno::Any aRet;
2172     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
2173         aRet <<= m_bIncludeHiddenCells;
2174     else
2175         throw beans::UnknownPropertyException();
2176     return aRet;
2177 }
2178 
2179 
2180 void SAL_CALL ScChart2DataProvider::addPropertyChangeListener(
2181         const ::rtl::OUString& /*rPropertyName*/,
2182         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
2183             throw( beans::UnknownPropertyException,
2184                     lang::WrappedTargetException, uno::RuntimeException)
2185 {
2186     OSL_ENSURE( false, "Not yet implemented" );
2187 }
2188 
2189 
2190 void SAL_CALL ScChart2DataProvider::removePropertyChangeListener(
2191         const ::rtl::OUString& /*rPropertyName*/,
2192         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
2193             throw( beans::UnknownPropertyException,
2194                     lang::WrappedTargetException, uno::RuntimeException)
2195 {
2196     OSL_ENSURE( false, "Not yet implemented" );
2197 }
2198 
2199 
2200 void SAL_CALL ScChart2DataProvider::addVetoableChangeListener(
2201         const ::rtl::OUString& /*rPropertyName*/,
2202         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
2203             throw( beans::UnknownPropertyException,
2204                     lang::WrappedTargetException, uno::RuntimeException)
2205 {
2206     OSL_ENSURE( false, "Not yet implemented" );
2207 }
2208 
2209 
2210 void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener(
2211         const ::rtl::OUString& /*rPropertyName*/,
2212         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
2213             throw( beans::UnknownPropertyException,
2214                     lang::WrappedTargetException, uno::RuntimeException)
2215 {
2216     OSL_ENSURE( false, "Not yet implemented" );
2217 }
2218 
2219 // DataSource ================================================================
2220 
2221 ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc)
2222     : m_pDocument( pDoc)
2223 {
2224     if ( m_pDocument )
2225         m_pDocument->AddUnoObject( *this);
2226 }
2227 
2228 
2229 ScChart2DataSource::~ScChart2DataSource()
2230 {
2231     if ( m_pDocument )
2232         m_pDocument->RemoveUnoObject( *this);
2233 }
2234 
2235 
2236 void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2237 {
2238     if ( rHint.ISA( SfxSimpleHint ) &&
2239             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
2240     {
2241         m_pDocument = NULL;
2242     }
2243 }
2244 
2245 
2246 uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL
2247 ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException)
2248 {
2249     ScUnoGuard aGuard;
2250 
2251     LabeledList::const_iterator aItr(m_aLabeledSequences.begin());
2252     LabeledList::const_iterator aEndItr(m_aLabeledSequences.end());
2253 
2254     uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size());
2255 
2256     sal_Int32 i = 0;
2257     while (aItr != aEndItr)
2258     {
2259         aRet[i] = *aItr;
2260         ++i;
2261         ++aItr;
2262     }
2263 
2264     return aRet;
2265 
2266 /*    typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec;
2267     tVec aVec;
2268     bool bSeries = false;
2269     // split into columns - FIXME: different if GlueState() is used
2270     for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next())
2271     {
2272         for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
2273         {
2274             uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq(
2275                 new ScChart2LabeledDataSequence( m_pDocument));
2276             if( xLabeledSeq.is())
2277             {
2278                 aVec.push_back( xLabeledSeq );
2279                 if( bSeries )
2280                 {
2281                     ScRangeListRef aColRanges = new ScRangeList;
2282                     // one single sheet selected assumed for now
2283                     aColRanges->Append( ScRange( nCol, p->aStart.Row(),
2284                                                  p->aStart.Tab(), nCol, p->aStart.Row(),
2285                                                  p->aStart.Tab()));
2286                     // TEST: add range two times, once as label, once as data
2287                     // TODO: create pure Numerical and Text sequences if possible
2288                     uno::Reference< chart2::data::XDataSequence > xLabel(
2289                         new ScChart2DataSequence( m_pDocument, aColRanges));
2290 
2291                     // set role
2292                     uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY );
2293                     if( xProp.is())
2294                         xProp->setPropertyValue(
2295                             ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2296                             ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" ))));
2297 
2298                     xLabeledSeq->setLabel( xLabel );
2299                 }
2300 
2301                 ScRangeListRef aColRanges = new ScRangeList;
2302 
2303                 // one single sheet selected assumed for now
2304                 aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1,
2305                                              p->aStart.Tab(), nCol, p->aEnd.Row(),
2306                                              p->aStart.Tab()));
2307                 uno::Reference< chart2::data::XDataSequence > xData(
2308                     new ScChart2DataSequence( m_pDocument, aColRanges));
2309 
2310                 // set role
2311                 uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY );
2312                 if( xProp.is())
2313                     xProp->setPropertyValue(
2314                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )),
2315                         ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" ))));
2316 
2317                 xLabeledSeq->setValues( xData );
2318 
2319                 bSeries = true;
2320             }
2321         }
2322     }
2323     uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences(
2324             aVec.size());
2325     uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray();
2326     sal_Int32 j = 0;
2327     for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end();
2328             ++iSeq, ++j)
2329     {
2330         pArr[j] = *iSeq;
2331     }
2332     return aSequences;*/
2333 }
2334 
2335 void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew)
2336 {
2337     m_aLabeledSequences.push_back(xNew);
2338 }
2339 
2340 
2341 // DataSequence ==============================================================
2342 
2343 ScChart2DataSequence::Item::Item() :
2344     mfValue(0.0), mbIsValue(false)
2345 {
2346     ::rtl::math::setNan(&mfValue);
2347 }
2348 
2349 ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) :
2350     mrParent(rParent)
2351 {
2352 }
2353 
2354 ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener()
2355 {
2356 }
2357 
2358 void ScChart2DataSequence::HiddenRangeListener::notify()
2359 {
2360     mrParent.setDataChangedHint(true);
2361 }
2362 
2363 ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc,
2364         const uno::Reference < chart2::data::XDataProvider >& xDP,
2365         vector<ScSharedTokenRef>* pTokens,
2366         bool bIncludeHiddenCells )
2367     : m_bIncludeHiddenCells( bIncludeHiddenCells)
2368     , m_nObjectId( 0 )
2369     , m_pDocument( pDoc)
2370     , m_pTokens(pTokens)
2371     , m_pRangeIndices(NULL)
2372     , m_pExtRefListener(NULL)
2373     , m_xDataProvider( xDP)
2374     , m_aPropSet(lcl_GetDataSequencePropertyMap())
2375     , m_pHiddenListener(NULL)
2376     , m_pValueListener( NULL )
2377     , m_bGotDataChangedHint(false)
2378     , m_bExtDataRebuildQueued(false)
2379 {
2380     DBG_ASSERT(pTokens, "reference token list is null");
2381 
2382     if ( m_pDocument )
2383     {
2384         m_pDocument->AddUnoObject( *this);
2385         m_nObjectId = m_pDocument->GetNewUnoId();
2386     }
2387     // FIXME: real implementation of identifier and it's mapping to ranges.
2388     // Reuse ScChartListener?
2389 
2390     // BM: don't use names of named ranges but the UI range strings
2391 //	String	aStr;
2392 //	rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
2393 //    m_aIdentifier = ::rtl::OUString( aStr );
2394 
2395 //      m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
2396 //      static sal_Int32 nID = 0;
2397 //      m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
2398 }
2399 
2400 ScChart2DataSequence::~ScChart2DataSequence()
2401 {
2402     if ( m_pDocument )
2403     {
2404         m_pDocument->RemoveUnoObject( *this);
2405         if (m_pHiddenListener.get())
2406         {
2407             ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
2408             if (pCLC)
2409                 pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2410         }
2411         StopListeningToAllExternalRefs();
2412     }
2413 
2414     delete m_pValueListener;
2415 }
2416 
2417 void ScChart2DataSequence::RefChanged()
2418 {
2419     if( m_pValueListener && m_aValueListeners.Count() != 0 )
2420     {
2421         m_pValueListener->EndListeningAll();
2422 
2423         if( m_pDocument )
2424         {
2425             ScChartListenerCollection* pCLC = NULL;
2426             if (m_pHiddenListener.get())
2427             {
2428                 pCLC = m_pDocument->GetChartListenerCollection();
2429                 if (pCLC)
2430                     pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
2431             }
2432 
2433             vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2434             for (; itr != itrEnd; ++itr)
2435             {
2436                 ScRange aRange;
2437                 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2438                     continue;
2439 
2440                 m_pDocument->StartListeningArea(aRange, m_pValueListener);
2441                 if (pCLC)
2442                     pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
2443             }
2444         }
2445     }
2446 }
2447 
2448 void ScChart2DataSequence::BuildDataCache()
2449 {
2450     m_bExtDataRebuildQueued = false;
2451 
2452     if (!m_aDataArray.empty())
2453         return;
2454 
2455     if (!m_pTokens.get())
2456     {
2457         DBG_ERROR("m_pTokens == NULL!  Something is wrong.");
2458         return;
2459     }
2460 
2461     StopListeningToAllExternalRefs();
2462 
2463     ::std::list<sal_Int32> aHiddenValues;
2464     sal_Int32 nDataCount = 0;
2465     sal_Int32 nHiddenValueCount = 0;
2466 
2467     for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
2468           itr != itrEnd; ++itr)
2469     {
2470         if (ScRefTokenHelper::isExternalRef(*itr))
2471         {
2472             nDataCount += FillCacheFromExternalRef(*itr);
2473         }
2474         else
2475         {
2476             ScRange aRange;
2477             if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
2478                 continue;
2479 
2480             SCCOL nLastCol = -1;
2481             SCROW nLastRow = -1;
2482             for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab)
2483             {
2484                 for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
2485                 {
2486                     for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
2487                     {
2488                         bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol);
2489                         bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow);
2490 
2491                         if (bColHidden || bRowHidden)
2492                         {
2493                             // hidden cell
2494                             ++nHiddenValueCount;
2495                             aHiddenValues.push_back(nDataCount-1);
2496 
2497                             if( !m_bIncludeHiddenCells )
2498                                 continue;
2499                         }
2500 
2501                         m_aDataArray.push_back(Item());
2502                         Item& rItem = m_aDataArray.back();
2503                         ++nDataCount;
2504 
2505                         ScAddress aAdr(nCol, nRow, nTab);
2506                         ScBaseCell* pCell = m_pDocument->GetCell(aAdr);
2507                         if (!pCell)
2508                             continue;
2509 
2510                         if (pCell->HasStringData())
2511                             rItem.maString = pCell->GetStringData();
2512                         else
2513                         {
2514                             String aStr;
2515                             m_pDocument->GetString(nCol, nRow, nTab, aStr);
2516                             rItem.maString = aStr;
2517                         }
2518 
2519                         switch (pCell->GetCellType())
2520                         {
2521                             case CELLTYPE_VALUE:
2522                                 rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue();
2523                                 rItem.mbIsValue = true;
2524                             break;
2525                             case CELLTYPE_FORMULA:
2526                             {
2527                                 ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
2528                                 sal_uInt16 nErr = pFCell->GetErrCode();
2529                                 if (nErr)
2530                                     break;
2531 
2532                                 if (pFCell->HasValueData())
2533                                 {
2534                                     rItem.mfValue = pFCell->GetValue();
2535                                     rItem.mbIsValue = true;
2536                                 }
2537                             }
2538                             break;
2539 #if DBG_UTIL
2540                             case CELLTYPE_DESTROYED:
2541 #endif
2542                             case CELLTYPE_EDIT:
2543                             case CELLTYPE_NONE:
2544                             case CELLTYPE_NOTE:
2545                             case CELLTYPE_STRING:
2546                             case CELLTYPE_SYMBOLS:
2547                             default:
2548                                 ; // do nothing
2549                         }
2550                     }
2551                 }
2552             }
2553         }
2554     }
2555 
2556     // convert the hidden cell list to sequence.
2557     m_aHiddenValues.realloc(nHiddenValueCount);
2558     sal_Int32* pArr = m_aHiddenValues.getArray();
2559     ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end();
2560     for (;itr != itrEnd; ++itr, ++pArr)
2561         *pArr = *itr;
2562 
2563     // Clear the data series cache when the array is re-built.
2564     m_aMixedDataCache.realloc(0);
2565 }
2566 
2567 void ScChart2DataSequence::RebuildDataCache()
2568 {
2569     if (!m_bExtDataRebuildQueued)
2570     {
2571         m_aDataArray.clear();
2572         m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL));
2573         m_bExtDataRebuildQueued = true;
2574         m_bGotDataChangedHint = true;
2575     }
2576 }
2577 
2578 sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken)
2579 {
2580     ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2581     ScRange aRange;
2582     if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true))
2583         return 0;
2584 
2585     sal_uInt16 nFileId = pToken->GetIndex();
2586     const String& rTabName = pToken->GetString();
2587     ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL);
2588     if (!pArray)
2589         // no external data exists for this range.
2590         return 0;
2591 
2592     // Start listening for this external document.
2593     ExternalRefListener* pExtRefListener = GetExtRefListener();
2594     pRefMgr->addLinkListener(nFileId, pExtRefListener);
2595     pExtRefListener->addFileId(nFileId);
2596 
2597     ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL);
2598     sal_Int32 nDataCount = 0;
2599     for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
2600     {
2601         // Cached external range is always represented as a single
2602         // matrix token, although that might change in the future when
2603         // we introduce a new token type to store multi-table range
2604         // data.
2605 
2606         if (p->GetType() != svMatrix)
2607         {
2608             DBG_ERROR("Cached array is not a matrix token.");
2609             continue;
2610         }
2611 
2612         const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
2613         SCSIZE nCSize, nRSize;
2614         pMat->GetDimensions(nCSize, nRSize);
2615         for (SCSIZE nC = 0; nC < nCSize; ++nC)
2616         {
2617             for (SCSIZE nR = 0; nR < nRSize; ++nR)
2618             {
2619                 if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR))
2620                 {
2621                     m_aDataArray.push_back(Item());
2622                     Item& rItem = m_aDataArray.back();
2623                     ++nDataCount;
2624 
2625                     rItem.mbIsValue = true;
2626                     rItem.mfValue = pMat->GetDouble(nC, nR);
2627 
2628                     SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable();
2629                     if (pFormatter)
2630                     {
2631                         String aStr;
2632                         const double fVal = rItem.mfValue;
2633                         Color* pColor = NULL;
2634                         sal_uInt32 nFmt = 0;
2635                         if (pTable)
2636                         {
2637                             // Get the correct format index from the cache.
2638                             SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC);
2639                             SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR);
2640                             pTable->getCell(nCol, nRow, &nFmt);
2641                         }
2642                         pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor);
2643                         rItem.maString = aStr;
2644                     }
2645                 }
2646                 else if (pMat->IsString(nC, nR))
2647                 {
2648                     m_aDataArray.push_back(Item());
2649                     Item& rItem = m_aDataArray.back();
2650                     ++nDataCount;
2651 
2652                     rItem.mbIsValue = false;
2653                     rItem.maString = pMat->GetString(nC, nR);
2654                 }
2655             }
2656         }
2657     }
2658     return nDataCount;
2659 }
2660 
2661 void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges)
2662 {
2663     if (!m_pRangeIndices.get())
2664         return;
2665 
2666     sal_uInt32 nCount = rRanges.Count();
2667     for (sal_uInt32 i = 0; i < nCount; ++i)
2668     {
2669         ScSharedTokenRef pToken;
2670         ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i));
2671         DBG_ASSERT(pRange, "range object is NULL.");
2672 
2673         ScRefTokenHelper::getTokenFromRange(pToken, *pRange);
2674         sal_uInt32 nOrigPos = (*m_pRangeIndices)[i];
2675         (*m_pTokens)[nOrigPos] = pToken;
2676     }
2677 
2678     RefChanged();
2679 
2680     // any change of the range address is broadcast to value (modify) listeners
2681     if ( m_aValueListeners.Count() )
2682         m_bGotDataChangedHint = true;
2683 }
2684 
2685 ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener()
2686 {
2687     if (!m_pExtRefListener.get())
2688         m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
2689 
2690     return m_pExtRefListener.get();
2691 }
2692 
2693 void ScChart2DataSequence::StopListeningToAllExternalRefs()
2694 {
2695     if (!m_pExtRefListener.get())
2696         return;
2697 
2698     const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds();
2699     hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
2700     ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2701     for (; itr != itrEnd; ++itr)
2702         pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get());
2703 
2704     m_pExtRefListener.reset(NULL);
2705 }
2706 
2707 void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r)
2708 {
2709     if (!m_pDocument)
2710     {
2711         DBG_ERROR("document instance is NULL!?");
2712         return;
2713     }
2714 
2715     list<Item> aDataArray(r.m_aDataArray);
2716     m_aDataArray.swap(aDataArray);
2717 
2718     m_aHiddenValues = r.m_aHiddenValues;
2719     m_aRole = r.m_aRole;
2720 
2721     if (r.m_pRangeIndices.get())
2722         m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices));
2723 
2724     if (r.m_pExtRefListener.get())
2725     {
2726         // Re-register all external files that the old instance was
2727         // listening to.
2728 
2729         ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager();
2730         m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument));
2731         const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds();
2732         hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end();
2733         for (; itr != itrEnd; ++itr)
2734         {
2735             pRefMgr->addLinkListener(*itr, m_pExtRefListener.get());
2736             m_pExtRefListener->addFileId(*itr);
2737         }
2738     }
2739 }
2740 
2741 void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
2742 {
2743     if ( rHint.ISA( SfxSimpleHint ) )
2744     {
2745         sal_uLong nId = static_cast<const SfxSimpleHint&>(rHint).GetId();
2746         if ( nId ==SFX_HINT_DYING )
2747         {
2748             m_pDocument = NULL;
2749         }
2750         else if ( nId == SFX_HINT_DATACHANGED )
2751         {
2752             // delayed broadcast as in ScCellRangesBase
2753 
2754             if ( m_bGotDataChangedHint && m_pDocument )
2755             {
2756                 m_aDataArray.clear();
2757                 lang::EventObject aEvent;
2758                 aEvent.Source.set((cppu::OWeakObject*)this);
2759 
2760                 if( m_pDocument )
2761                 {
2762                     for ( sal_uInt16 n=0; n<m_aValueListeners.Count(); n++ )
2763                         m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent );
2764                 }
2765 
2766                 m_bGotDataChangedHint = false;
2767             }
2768         }
2769         else if ( nId == SC_HINT_CALCALL )
2770         {
2771             // broadcast from DoHardRecalc - set m_bGotDataChangedHint
2772             // (SFX_HINT_DATACHANGED follows separately)
2773 
2774             if ( m_aValueListeners.Count() )
2775                 m_bGotDataChangedHint = true;
2776         }
2777     }
2778     else if ( rHint.ISA( ScUpdateRefHint ) )
2779     {
2780         // Create a range list from the token list, have the range list
2781         // updated, and bring the change back to the token list.
2782 
2783         ScRangeList aRanges;
2784         m_pRangeIndices.reset(new vector<sal_uInt32>());
2785         vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end();
2786         for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr)
2787         {
2788             if (!ScRefTokenHelper::isExternalRef(*itr))
2789             {
2790                 ScRange aRange;
2791                 ScRefTokenHelper::getRangeFromToken(aRange, *itr);
2792                 aRanges.Append(aRange);
2793                 sal_uInt32 nPos = distance(itrBeg, itr);
2794                 m_pRangeIndices->push_back(nPos);
2795             }
2796         }
2797 
2798         DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
2799                    "range list and range index list have different sizes.");
2800 
2801         auto_ptr<ScRangeList> pUndoRanges;
2802         if ( m_pDocument->HasUnoRefUndo() )
2803             pUndoRanges.reset(new ScRangeList(aRanges));
2804 
2805         const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
2806         bool bChanged = aRanges.UpdateReference(
2807             rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz());
2808 
2809         if (bChanged)
2810         {
2811             DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()),
2812                        "range list and range index list have different sizes after the reference update.");
2813 
2814             // Bring the change back from the range list to the token list.
2815             UpdateTokensFromRanges(aRanges);
2816 
2817             if (pUndoRanges.get())
2818                 m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges);
2819         }
2820     }
2821     else if ( rHint.ISA( ScUnoRefUndoHint ) )
2822     {
2823         const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint);
2824 
2825         do
2826         {
2827             if (rUndoHint.GetObjectId() != m_nObjectId)
2828                 break;
2829 
2830             // The hint object provides the old ranges.  Restore the old state
2831             // from these ranges.
2832 
2833             if (!m_pRangeIndices.get() || m_pRangeIndices->empty())
2834             {
2835                 DBG_ERROR(" faulty range indices");
2836                 break;
2837             }
2838 
2839             const ScRangeList& rRanges = rUndoHint.GetRanges();
2840 
2841             sal_uInt32 nCount = rRanges.Count();
2842             if (nCount != m_pRangeIndices->size())
2843             {
2844                 DBG_ERROR("range count and range index count differ.");
2845                 break;
2846             }
2847 
2848             UpdateTokensFromRanges(rRanges);
2849         }
2850         while (false);
2851     }
2852 }
2853 
2854 
2855 IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint )
2856 {
2857     if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) &&
2858             ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) )
2859     {
2860         //  This may be called several times for a single change, if several formulas
2861         //  in the range are notified. So only a flag is set that is checked when
2862         //  SFX_HINT_DATACHANGED is received.
2863 
2864         setDataChangedHint(true);
2865     }
2866     return 0;
2867 }
2868 
2869 // ----------------------------------------------------------------------------
2870 
2871 ScChart2DataSequence::ExternalRefListener::ExternalRefListener(
2872     ScChart2DataSequence& rParent, ScDocument* pDoc) :
2873     ScExternalRefManager::LinkListener(),
2874     mrParent(rParent),
2875     mpDoc(pDoc)
2876 {
2877 }
2878 
2879 ScChart2DataSequence::ExternalRefListener::~ExternalRefListener()
2880 {
2881     if (!mpDoc || mpDoc->IsInDtorClear())
2882         // The document is being destroyed.  Do nothing.
2883         return;
2884 
2885     // Make sure to remove all pointers to this object.
2886     mpDoc->GetExternalRefManager()->removeLinkListener(this);
2887 }
2888 
2889 void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType)
2890 {
2891     switch (eType)
2892     {
2893         case ScExternalRefManager::LINK_MODIFIED:
2894         {
2895             if (maFileIds.count(nFileId))
2896                 // We are listening to this external document.
2897                 mrParent.RebuildDataCache();
2898         }
2899         break;
2900         case ScExternalRefManager::LINK_BROKEN:
2901             removeFileId(nFileId);
2902         break;
2903     }
2904 }
2905 
2906 void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId)
2907 {
2908     maFileIds.insert(nFileId);
2909 }
2910 
2911 void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId)
2912 {
2913     maFileIds.erase(nFileId);
2914 }
2915 
2916 const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds()
2917 {
2918     return maFileIds;
2919 }
2920 
2921 // ----------------------------------------------------------------------------
2922 
2923 uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData()
2924             throw ( uno::RuntimeException)
2925 {
2926     ScUnoGuard aGuard;
2927     if ( !m_pDocument)
2928         throw uno::RuntimeException();
2929 
2930     BuildDataCache();
2931 
2932     if (!m_aMixedDataCache.getLength())
2933     {
2934         // Build a cache for the 1st time...
2935 
2936         sal_Int32 nCount = m_aDataArray.size();
2937         m_aMixedDataCache.realloc(nCount);
2938         uno::Any* pArr = m_aMixedDataCache.getArray();
2939         ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
2940         for (; itr != itrEnd; ++itr, ++pArr)
2941         {
2942             if (itr->mbIsValue)
2943                 *pArr <<= itr->mfValue;
2944             else
2945                 *pArr <<= itr->maString;
2946         }
2947     }
2948     return m_aMixedDataCache;
2949 }
2950 
2951 // XNumericalDataSequence --------------------------------------------------
2952 
2953 uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData()
2954             throw ( uno::RuntimeException)
2955 {
2956     ScUnoGuard aGuard;
2957     if ( !m_pDocument)
2958         throw uno::RuntimeException();
2959 
2960     BuildDataCache();
2961 
2962     double fNAN;
2963     ::rtl::math::setNan(&fNAN);
2964 
2965     sal_Int32 nCount = m_aDataArray.size();
2966     uno::Sequence<double> aSeq(nCount);
2967     double* pArr = aSeq.getArray();
2968     ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
2969     for (; itr != itrEnd; ++itr, ++pArr)
2970         *pArr = itr->mbIsValue ? itr->mfValue : fNAN;
2971 
2972     return aSeq;
2973 }
2974 
2975 // XTextualDataSequence --------------------------------------------------
2976 
2977 uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData(  ) throw (uno::RuntimeException)
2978 {
2979     ScUnoGuard aGuard;
2980     if ( !m_pDocument)
2981         throw uno::RuntimeException();
2982 
2983     BuildDataCache();
2984 
2985     sal_Int32 nCount = m_aDataArray.size();
2986     uno::Sequence<rtl::OUString> aSeq(nCount);
2987     rtl::OUString* pArr = aSeq.getArray();
2988     ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end();
2989     for (; itr != itrEnd; ++itr, ++pArr)
2990         *pArr = itr->maString;
2991 
2992     return aSeq;
2993 }
2994 
2995 ::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation()
2996             throw ( uno::RuntimeException)
2997 {
2998     ScUnoGuard aGuard;
2999     OUString aStr;
3000     DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3001     if (m_pDocument && m_pTokens.get())
3002         lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument);
3003 
3004     return aStr;
3005 }
3006 
3007 namespace {
3008 
3009 /**
3010  * This function object is used to accumulatively count the numbers of
3011  * columns and rows in all reference tokens.
3012  */
3013 class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void>
3014 {
3015 public:
3016     AccumulateRangeSize() :
3017         mnCols(0), mnRows(0) {}
3018 
3019     AccumulateRangeSize(const AccumulateRangeSize& r) :
3020         mnCols(r.mnCols), mnRows(r.mnRows) {}
3021 
3022     void operator() (const ScSharedTokenRef& pToken)
3023     {
3024         ScRange r;
3025         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3026         ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal);
3027         r.Justify();
3028         mnCols += r.aEnd.Col() - r.aStart.Col() + 1;
3029         mnRows += r.aEnd.Row() - r.aStart.Row() + 1;
3030     }
3031 
3032     SCCOL getCols() const { return mnCols; }
3033     SCROW getRows() const { return mnRows; }
3034 private:
3035     SCCOL mnCols;
3036     SCROW mnRows;
3037 };
3038 
3039 /**
3040  * This function object is used to generate label strings from a list of
3041  * reference tokens.
3042  */
3043 class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void>
3044 {
3045 public:
3046     GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) :
3047         mpLabels(new Sequence<OUString>(nSize)),
3048         meOrigin(eOrigin),
3049         mnCount(0),
3050         mbColumn(bColumn) {}
3051 
3052     GenerateLabelStrings(const GenerateLabelStrings& r) :
3053         mpLabels(r.mpLabels),
3054         meOrigin(r.meOrigin),
3055         mnCount(r.mnCount),
3056         mbColumn(r.mbColumn) {}
3057 
3058     void operator() (const ScSharedTokenRef& pToken)
3059     {
3060         bool bExternal = ScRefTokenHelper::isExternalRef(pToken);
3061         ScRange aRange;
3062         ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal);
3063         OUString* pArr = mpLabels->getArray();
3064         if (mbColumn)
3065         {
3066             for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
3067             {
3068                 if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3069                 {
3070                     String aString = ScGlobal::GetRscString(STR_COLUMN);
3071                     aString += ' ';
3072                     ScAddress aPos( nCol, 0, 0 );
3073                     String aColStr;
3074                     aPos.Format( aColStr, SCA_VALID_COL, NULL );
3075                     aString += aColStr;
3076                     pArr[mnCount] = aString;
3077                 }
3078                 else //only indices for categories
3079                     pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3080                 ++mnCount;
3081             }
3082         }
3083         else
3084         {
3085             for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow)
3086             {
3087                 if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE)
3088                 {
3089                     String aString = ScGlobal::GetRscString(STR_ROW);
3090                     aString += ' ';
3091                     aString += String::CreateFromInt32( nRow+1 );
3092                     pArr[mnCount] = aString;
3093                 }
3094                 else //only indices for categories
3095                     pArr[mnCount] = String::CreateFromInt32( mnCount+1 );
3096                 ++mnCount;
3097             }
3098         }
3099     }
3100 
3101     Sequence<OUString> getLabels() const { return *mpLabels; }
3102 
3103 private:
3104     GenerateLabelStrings(); // disabled
3105 
3106     shared_ptr< Sequence<OUString> >    mpLabels;
3107     chart2::data::LabelOrigin           meOrigin;
3108     sal_Int32                           mnCount;
3109     bool                                mbColumn;
3110 };
3111 
3112 }
3113 
3114 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin)
3115         throw (uno::RuntimeException)
3116 {
3117     ScUnoGuard aGuard;
3118     if ( !m_pDocument)
3119         throw uno::RuntimeException();
3120 
3121     if (!m_pTokens.get())
3122         return Sequence<OUString>();
3123 
3124     // Determine the total size of all ranges.
3125     AccumulateRangeSize func;
3126     func = for_each(m_pTokens->begin(), m_pTokens->end(), func);
3127     SCCOL nCols = func.getCols();
3128     SCROW nRows = func.getRows();
3129 
3130     // Detemine whether this is column-major or row-major.
3131     bool bColumn = true;
3132     if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) ||
3133         (eOrigin == chart2::data::LabelOrigin_LONG_SIDE))
3134     {
3135         if (nRows > nCols)
3136         {
3137             if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3138                 bColumn = true;
3139             else
3140                 bColumn = false;
3141         }
3142         else if (nCols > nRows)
3143         {
3144             if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE)
3145                 bColumn = false;
3146             else
3147                 bColumn = true;
3148         }
3149         else
3150             return Sequence<OUString>();
3151     }
3152 
3153     // Generate label strings based on the info so far.
3154     sal_Int32 nCount = bColumn ? nCols : nRows;
3155     GenerateLabelStrings genLabels(nCount, eOrigin, bColumn);
3156     genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels);
3157     Sequence<OUString> aSeq = genLabels.getLabels();
3158 
3159     return aSeq;
3160 }
3161 
3162 ::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex )
3163     throw (lang::IndexOutOfBoundsException,
3164            uno::RuntimeException)
3165 {
3166     // index -1 means a heuristic value for the entire sequence
3167     bool bGetSeriesFormat = (nIndex == -1);
3168     sal_Int32 nResult = 0;
3169 
3170     ScUnoGuard aGuard;
3171     if ( !m_pDocument || !m_pTokens.get())
3172         return nResult;
3173 
3174     sal_Int32 nCount = 0;
3175     bool bFound = false;
3176     ScRangePtr p;
3177 
3178     uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument ));
3179     if (!xSpreadDoc.is())
3180         return nResult;
3181 
3182     uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY );
3183     if (!xIndex.is())
3184         return nResult;
3185 
3186     ScRangeList aRanges;
3187     ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3188     uno::Reference< table::XCellRange > xSheet;
3189     for ( p = aRanges.First(); p && !bFound; p = aRanges.Next())
3190     {
3191         // TODO: use DocIter?
3192         table::CellAddress aStart, aEnd;
3193         ScUnoConversion::FillApiAddress( aStart, p->aStart );
3194         ScUnoConversion::FillApiAddress( aEnd, p->aEnd );
3195         for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet)
3196         {
3197             xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY);
3198             for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol)
3199             {
3200                 for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow)
3201                 {
3202                     if( bGetSeriesFormat )
3203                     {
3204                         // TODO: use nicer heuristic
3205                         // return format of first non-empty cell
3206                         uno::Reference< text::XText > xText(
3207                             xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3208                         if (xText.is() && xText->getString().getLength())
3209                         {
3210                             uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY);
3211                             if( xProp.is())
3212                                 xProp->getPropertyValue(
3213                                     ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3214                             bFound = true;
3215                             break;
3216                         }
3217                     }
3218                     else if( nCount == nIndex )
3219                     {
3220                         uno::Reference< beans::XPropertySet > xProp(
3221                             xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
3222                         if( xProp.is())
3223                             xProp->getPropertyValue(
3224                                 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult;
3225                         bFound = true;
3226                         break;
3227                     }
3228                     ++nCount;
3229                 }
3230             }
3231         }
3232     }
3233 
3234     return nResult;
3235 }
3236 
3237 // XCloneable ================================================================
3238 
3239 uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone()
3240     throw (uno::RuntimeException)
3241 {
3242     ScUnoGuard aGuard;
3243 
3244     auto_ptr< vector<ScSharedTokenRef> > pTokensNew;
3245     if (m_pTokens.get())
3246     {
3247         // Clone tokens.
3248         pTokensNew.reset(new vector<ScSharedTokenRef>);
3249         pTokensNew->reserve(m_pTokens->size());
3250         vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3251         for (; itr != itrEnd; ++itr)
3252         {
3253             ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone()));
3254             pTokensNew->push_back(p);
3255         }
3256     }
3257 
3258     auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells));
3259     p->CopyData(*this);
3260     Reference< util::XCloneable > xClone(p.release());
3261 
3262     return xClone;
3263 }
3264 
3265 // XModifyBroadcaster ========================================================
3266 
3267 void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3268     throw (uno::RuntimeException)
3269 {
3270     // like ScCellRangesBase::addModifyListener
3271 	ScUnoGuard aGuard;
3272     if (!m_pTokens.get() || m_pTokens->empty())
3273         return;
3274 
3275     ScRangeList aRanges;
3276     ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens);
3277 	uno::Reference<util::XModifyListener> *pObj =
3278 			new uno::Reference<util::XModifyListener>( aListener );
3279 	m_aValueListeners.Insert( pObj, m_aValueListeners.Count() );
3280 
3281 	if ( m_aValueListeners.Count() == 1 )
3282 	{
3283 		if (!m_pValueListener)
3284 			m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) );
3285 
3286         if (!m_pHiddenListener.get())
3287             m_pHiddenListener.reset(new HiddenRangeListener(*this));
3288 
3289         if( m_pDocument )
3290         {
3291             ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3292             vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end();
3293             for (; itr != itrEnd; ++itr)
3294             {
3295                 ScRange aRange;
3296                 if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr))
3297                     continue;
3298 
3299                 m_pDocument->StartListeningArea( aRange, m_pValueListener );
3300                 if (pCLC)
3301                     pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get());
3302             }
3303         }
3304 
3305 		acquire();	// don't lose this object (one ref for all listeners)
3306 	}
3307 }
3308 
3309 void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener )
3310     throw (uno::RuntimeException)
3311 {
3312     // like ScCellRangesBase::removeModifyListener
3313 
3314 	ScUnoGuard aGuard;
3315     if (!m_pTokens.get() || m_pTokens->empty())
3316         return;
3317 
3318 	acquire();		// in case the listeners have the last ref - released below
3319 
3320 	sal_uInt16 nCount = m_aValueListeners.Count();
3321 	for ( sal_uInt16 n=nCount; n--; )
3322 	{
3323 		uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n];
3324 		if ( *pObj == aListener )
3325 		{
3326 			m_aValueListeners.DeleteAndDestroy( n );
3327 
3328 			if ( m_aValueListeners.Count() == 0 )
3329 			{
3330 				if (m_pValueListener)
3331 					m_pValueListener->EndListeningAll();
3332 
3333                 if (m_pHiddenListener.get() && m_pDocument)
3334                 {
3335                     ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection();
3336                     if (pCLC)
3337                         pCLC->EndListeningHiddenRange(m_pHiddenListener.get());
3338                 }
3339 
3340 				release();		// release the ref for the listeners
3341 			}
3342 
3343 			break;
3344 		}
3345 	}
3346 
3347 	release();		// might delete this object
3348 }
3349 
3350 // DataSequence XPropertySet -------------------------------------------------
3351 
3352 uno::Reference< beans::XPropertySetInfo> SAL_CALL
3353 ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3354 {
3355 	ScUnoGuard aGuard;
3356 	static uno::Reference<beans::XPropertySetInfo> aRef =
3357 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3358 	return aRef;
3359 }
3360 
3361 
3362 void SAL_CALL ScChart2DataSequence::setPropertyValue(
3363         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3364             throw( beans::UnknownPropertyException,
3365                     beans::PropertyVetoException,
3366                     lang::IllegalArgumentException,
3367                     lang::WrappedTargetException, uno::RuntimeException)
3368 {
3369     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3370     {
3371         if ( !(rValue >>= m_aRole))
3372             throw lang::IllegalArgumentException();
3373     }
3374     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3375     {
3376         sal_Bool bOldValue = m_bIncludeHiddenCells;
3377         if ( !(rValue >>= m_bIncludeHiddenCells))
3378             throw lang::IllegalArgumentException();
3379         if( bOldValue != m_bIncludeHiddenCells )
3380             m_aDataArray.clear();//data array is dirty now
3381     }
3382     else
3383         throw beans::UnknownPropertyException();
3384     // TODO: support optional properties
3385 }
3386 
3387 
3388 uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue(
3389         const ::rtl::OUString& rPropertyName)
3390             throw( beans::UnknownPropertyException,
3391                     lang::WrappedTargetException, uno::RuntimeException)
3392 {
3393     uno::Any aRet;
3394     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3395         aRet <<= m_aRole;
3396     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3397         aRet <<= m_bIncludeHiddenCells;
3398     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES)))
3399     {
3400         // This property is read-only thus cannot be set externally via
3401         // setPropertyValue(...).
3402         BuildDataCache();
3403         aRet <<= m_aHiddenValues;
3404     }
3405     else
3406         throw beans::UnknownPropertyException();
3407     // TODO: support optional properties
3408     return aRet;
3409 }
3410 
3411 
3412 void SAL_CALL ScChart2DataSequence::addPropertyChangeListener(
3413         const ::rtl::OUString& /*rPropertyName*/,
3414         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3415             throw( beans::UnknownPropertyException,
3416                     lang::WrappedTargetException, uno::RuntimeException)
3417 {
3418     // FIXME: real implementation
3419 //     throw uno::RuntimeException();
3420     OSL_ENSURE( false, "Not yet implemented" );
3421 }
3422 
3423 
3424 void SAL_CALL ScChart2DataSequence::removePropertyChangeListener(
3425         const ::rtl::OUString& /*rPropertyName*/,
3426         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3427             throw( beans::UnknownPropertyException,
3428                     lang::WrappedTargetException, uno::RuntimeException)
3429 {
3430     // FIXME: real implementation
3431 //     throw uno::RuntimeException();
3432     OSL_ENSURE( false, "Not yet implemented" );
3433 }
3434 
3435 
3436 void SAL_CALL ScChart2DataSequence::addVetoableChangeListener(
3437         const ::rtl::OUString& /*rPropertyName*/,
3438         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3439             throw( beans::UnknownPropertyException,
3440                     lang::WrappedTargetException, uno::RuntimeException)
3441 {
3442     // FIXME: real implementation
3443 //     throw uno::RuntimeException();
3444     OSL_ENSURE( false, "Not yet implemented" );
3445 }
3446 
3447 
3448 void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener(
3449         const ::rtl::OUString& /*rPropertyName*/,
3450         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3451             throw( beans::UnknownPropertyException,
3452                     lang::WrappedTargetException, uno::RuntimeException)
3453 {
3454     // FIXME: real implementation
3455 //     throw uno::RuntimeException();
3456     OSL_ENSURE( false, "Not yet implemented" );
3457 }
3458 
3459 void ScChart2DataSequence::setDataChangedHint(bool b)
3460 {
3461     m_bGotDataChangedHint = b;
3462 }
3463 
3464 // XUnoTunnel
3465 
3466 // sal_Int64 SAL_CALL ScChart2DataSequence::getSomething(
3467 // 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3468 // {
3469 // 	if ( rId.getLength() == 16 &&
3470 //           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3471 // 									rId.getConstArray(), 16 ) )
3472 // 	{
3473 // 		return (sal_Int64)this;
3474 // 	}
3475 // 	return 0;
3476 // }
3477 
3478 // // static
3479 // const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId()
3480 // {
3481 // 	static uno::Sequence<sal_Int8> * pSeq = 0;
3482 // 	if( !pSeq )
3483 // 	{
3484 // 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3485 // 		if( !pSeq )
3486 // 		{
3487 // 			static uno::Sequence< sal_Int8 > aSeq( 16 );
3488 // 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3489 // 			pSeq = &aSeq;
3490 // 		}
3491 // 	}
3492 // 	return *pSeq;
3493 // }
3494 
3495 // // static
3496 // ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3497 // {
3498 // 	ScChart2DataSequence* pRet = NULL;
3499 // 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3500 // 	if (xUT.is())
3501 // 		pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() );
3502 // 	return pRet;
3503 // }
3504 
3505 #if USE_CHART2_EMPTYDATASEQUENCE
3506 // DataSequence ==============================================================
3507 
3508 ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc,
3509         const uno::Reference < chart2::data::XDataProvider >& xDP,
3510         const ScRangeListRef& rRangeList,
3511         sal_Bool bColumn)
3512     : m_bIncludeHiddenCells( sal_True)
3513     , m_xRanges( rRangeList)
3514     , m_pDocument( pDoc)
3515     , m_xDataProvider( xDP)
3516 	, m_aPropSet(lcl_GetDataSequencePropertyMap())
3517     , m_bColumn(bColumn)
3518 {
3519     if ( m_pDocument )
3520         m_pDocument->AddUnoObject( *this);
3521     // FIXME: real implementation of identifier and it's mapping to ranges.
3522     // Reuse ScChartListener?
3523 
3524     // BM: don't use names of named ranges but the UI range strings
3525 //	String	aStr;
3526 //	rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument );
3527 //    m_aIdentifier = ::rtl::OUString( aStr );
3528 
3529 //      m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_");
3530 //      static sal_Int32 nID = 0;
3531 //      m_aIdentifier += ::rtl::OUString::valueOf( ++nID);
3532 }
3533 
3534 
3535 ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence()
3536 {
3537     if ( m_pDocument )
3538         m_pDocument->RemoveUnoObject( *this);
3539 }
3540 
3541 
3542 void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint)
3543 {
3544     if ( rHint.ISA( SfxSimpleHint ) &&
3545             ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
3546     {
3547         m_pDocument = NULL;
3548     }
3549 }
3550 
3551 
3552 uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData()
3553             throw ( uno::RuntimeException)
3554 {
3555     ScUnoGuard aGuard;
3556     if ( !m_pDocument)
3557         throw uno::RuntimeException();
3558     return uno::Sequence< uno::Any>();
3559 }
3560 
3561 // XTextualDataSequence --------------------------------------------------
3562 
3563 uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData(  ) throw (uno::RuntimeException)
3564 {
3565     ScUnoGuard aGuard;
3566     if ( !m_pDocument)
3567         throw uno::RuntimeException();
3568 
3569     sal_Int32 nCount = 0;
3570     ScRangePtr p;
3571 
3572     DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges");
3573 
3574     for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3575     {
3576         p->Justify();
3577         // TODO: handle overlaping ranges?
3578         nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1;
3579     }
3580     uno::Sequence< rtl::OUString > aSeq( nCount);
3581     rtl::OUString* pArr = aSeq.getArray();
3582     nCount = 0;
3583     for ( p = m_xRanges->First(); p; p = m_xRanges->Next())
3584     {
3585         if (m_bColumn)
3586         {
3587             for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol)
3588             {
3589 			    String aString = ScGlobal::GetRscString(STR_COLUMN);
3590 			    aString += ' ';
3591                 ScAddress aPos( nCol, 0, 0 );
3592                 String aColStr;
3593                 aPos.Format( aColStr, SCA_VALID_COL, NULL );
3594                 aString += aColStr;
3595                 pArr[nCount] = aString;
3596                 ++nCount;
3597             }
3598         }
3599         else
3600         {
3601             for (sal_Int32 nRow = p->aStart.Row(); nRow <= p->aEnd.Row(); ++nRow)
3602             {
3603 			    String aString = ScGlobal::GetRscString(STR_ROW);
3604 			    aString += ' ';
3605 			    aString += String::CreateFromInt32( nRow+1 );
3606                 pArr[nCount] = aString;
3607                 ++nCount;
3608             }
3609         }
3610     }
3611     return aSeq;
3612 }
3613 
3614 ::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation()
3615             throw ( uno::RuntimeException)
3616 {
3617     ScUnoGuard aGuard;
3618 	String	aStr;
3619     DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" );
3620     if( m_pDocument )
3621 	    m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() );
3622 	return aStr;
3623 }
3624 
3625 uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/)
3626         throw (uno::RuntimeException)
3627 {
3628     ScUnoGuard aGuard;
3629     uno::Sequence< ::rtl::OUString > aRet;
3630     return aRet;
3631 }
3632 
3633 ::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ )
3634     throw (lang::IndexOutOfBoundsException,
3635            uno::RuntimeException)
3636 {
3637     sal_Int32 nResult = 0;
3638 
3639     ScUnoGuard aGuard;
3640     if ( !m_pDocument)
3641         return nResult;
3642 
3643     return nResult;
3644 }
3645 
3646 // XCloneable ================================================================
3647 
3648 uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone()
3649     throw (uno::RuntimeException)
3650 {
3651     ScUnoGuard aGuard;
3652     if (m_xDataProvider.is())
3653     {
3654         // copy properties
3655         uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn));
3656         uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY );
3657         if( xProp.is())
3658         {
3659             xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )),
3660                                      uno::makeAny( m_aRole ));
3661             xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )),
3662                                      uno::makeAny( m_bIncludeHiddenCells ));
3663         }
3664         return xClone;
3665     }
3666     return uno::Reference< util::XCloneable >();
3667 }
3668 
3669 // XModifyBroadcaster ========================================================
3670 
3671 void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
3672     throw (uno::RuntimeException)
3673 {
3674     // TODO: Implement
3675 }
3676 
3677 void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ )
3678     throw (uno::RuntimeException)
3679 {
3680     // TODO: Implement
3681 }
3682 
3683 // DataSequence XPropertySet -------------------------------------------------
3684 
3685 uno::Reference< beans::XPropertySetInfo> SAL_CALL
3686 ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException)
3687 {
3688 	ScUnoGuard aGuard;
3689 	static uno::Reference<beans::XPropertySetInfo> aRef =
3690 		new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() );
3691 	return aRef;
3692 }
3693 
3694 
3695 void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue(
3696         const ::rtl::OUString& rPropertyName, const uno::Any& rValue)
3697             throw( beans::UnknownPropertyException,
3698                     beans::PropertyVetoException,
3699                     lang::IllegalArgumentException,
3700                     lang::WrappedTargetException, uno::RuntimeException)
3701 {
3702     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3703     {
3704         if ( !(rValue >>= m_aRole))
3705             throw lang::IllegalArgumentException();
3706     }
3707     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3708     {
3709         if ( !(rValue >>= m_bIncludeHiddenCells))
3710             throw lang::IllegalArgumentException();
3711     }
3712     else
3713         throw beans::UnknownPropertyException();
3714     // TODO: support optional properties
3715 }
3716 
3717 
3718 uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue(
3719         const ::rtl::OUString& rPropertyName)
3720             throw( beans::UnknownPropertyException,
3721                     lang::WrappedTargetException, uno::RuntimeException)
3722 {
3723     uno::Any aRet;
3724     if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE)))
3725         aRet <<= m_aRole;
3726     else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS)))
3727         aRet <<= m_bIncludeHiddenCells;
3728     else
3729         throw beans::UnknownPropertyException();
3730     // TODO: support optional properties
3731     return aRet;
3732 }
3733 
3734 
3735 void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener(
3736         const ::rtl::OUString& /*rPropertyName*/,
3737         const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/)
3738             throw( beans::UnknownPropertyException,
3739                     lang::WrappedTargetException, uno::RuntimeException)
3740 {
3741     // FIXME: real implementation
3742 //     throw uno::RuntimeException();
3743     OSL_ENSURE( false, "Not yet implemented" );
3744 }
3745 
3746 
3747 void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener(
3748         const ::rtl::OUString& /*rPropertyName*/,
3749         const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/)
3750             throw( beans::UnknownPropertyException,
3751                     lang::WrappedTargetException, uno::RuntimeException)
3752 {
3753     // FIXME: real implementation
3754 //     throw uno::RuntimeException();
3755     OSL_ENSURE( false, "Not yet implemented" );
3756 }
3757 
3758 
3759 void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener(
3760         const ::rtl::OUString& /*rPropertyName*/,
3761         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/)
3762             throw( beans::UnknownPropertyException,
3763                     lang::WrappedTargetException, uno::RuntimeException)
3764 {
3765     // FIXME: real implementation
3766 //     throw uno::RuntimeException();
3767     OSL_ENSURE( false, "Not yet implemented" );
3768 }
3769 
3770 
3771 void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener(
3772         const ::rtl::OUString& /*rPropertyName*/,
3773         const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ )
3774             throw( beans::UnknownPropertyException,
3775                     lang::WrappedTargetException, uno::RuntimeException)
3776 {
3777     // FIXME: real implementation
3778 //     throw uno::RuntimeException();
3779     OSL_ENSURE( false, "Not yet implemented" );
3780 }
3781 
3782 // XUnoTunnel
3783 
3784 // sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething(
3785 // 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
3786 // {
3787 // 	if ( rId.getLength() == 16 &&
3788 //           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
3789 // 									rId.getConstArray(), 16 ) )
3790 // 	{
3791 // 		return (sal_Int64)this;
3792 // 	}
3793 // 	return 0;
3794 // }
3795 
3796 // // static
3797 // const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId()
3798 // {
3799 // 	static uno::Sequence<sal_Int8> * pSeq = 0;
3800 // 	if( !pSeq )
3801 // 	{
3802 // 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
3803 // 		if( !pSeq )
3804 // 		{
3805 // 			static uno::Sequence< sal_Int8 > aSeq( 16 );
3806 // 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
3807 // 			pSeq = &aSeq;
3808 // 		}
3809 // 	}
3810 // 	return *pSeq;
3811 // }
3812 
3813 // // static
3814 // ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj )
3815 // {
3816 // 	ScChart2DataSequence* pRet = NULL;
3817 // 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
3818 // 	if (xUT.is())
3819 // 		pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() );
3820 // 	return pRet;
3821 // }
3822 #endif
3823