LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/ui/unoobj - chart2uno.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1113 1728 64.4 %
Date: 2013-07-09 Functions: 117 162 72.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10