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