LCOV - code coverage report
Current view: top level - libreoffice/sc/source/ui/unoobj - chart2uno.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 214 1713 12.5 %
Date: 2012-12-27 Functions: 29 160 18.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10