LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - chart2uno.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1200 1807 66.4 %
Date: 2015-06-13 12:38:46 Functions: 122 167 73.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11