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

Generated by: LCOV version 1.10