LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - chart2uno.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1142 1807 63.2 %
Date: 2014-11-03 Functions: 119 167 71.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10