LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xecontent.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 449 1035 43.4 %
Date: 2015-06-13 12:38:46 Functions: 66 100 66.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "xecontent.hxx"
      21             : 
      22             : #include <list>
      23             : #include <algorithm>
      24             : #include <com/sun/star/container/XIndexAccess.hpp>
      25             : #include <com/sun/star/frame/XModel.hpp>
      26             : #include <com/sun/star/sheet/XAreaLinks.hpp>
      27             : #include <com/sun/star/sheet/XAreaLink.hpp>
      28             : #include <comphelper/string.hxx>
      29             : #include <sfx2/objsh.hxx>
      30             : #include <tools/urlobj.hxx>
      31             : #include <svl/itemset.hxx>
      32             : #include <formula/grammar.hxx>
      33             : #include "scitems.hxx"
      34             : #include <editeng/eeitem.hxx>
      35             : #include <editeng/flditem.hxx>
      36             : #include "document.hxx"
      37             : #include "validat.hxx"
      38             : #include "unonames.hxx"
      39             : #include "convuno.hxx"
      40             : #include "rangenam.hxx"
      41             : #include "tokenarray.hxx"
      42             : #include "stlpool.hxx"
      43             : #include "patattr.hxx"
      44             : #include "fapihelper.hxx"
      45             : #include "xehelper.hxx"
      46             : #include "xestyle.hxx"
      47             : #include "xename.hxx"
      48             : #include <rtl/uuid.h>
      49             : 
      50             : using namespace ::oox;
      51             : 
      52             : using ::com::sun::star::uno::Reference;
      53             : using ::com::sun::star::uno::Any;
      54             : using ::com::sun::star::uno::UNO_QUERY;
      55             : using ::com::sun::star::beans::XPropertySet;
      56             : using ::com::sun::star::container::XIndexAccess;
      57             : using ::com::sun::star::frame::XModel;
      58             : using ::com::sun::star::table::CellRangeAddress;
      59             : using ::com::sun::star::sheet::XAreaLinks;
      60             : using ::com::sun::star::sheet::XAreaLink;
      61             : 
      62             : // Shared string table ========================================================
      63             : 
      64             : /** A single string entry in the hash table. */
      65             : struct XclExpHashEntry
      66             : {
      67             :     const XclExpString* mpString;       /// Pointer to the string (no ownership).
      68             :     sal_uInt32          mnSstIndex;     /// The SST index of this string.
      69         449 :     inline explicit     XclExpHashEntry( const XclExpString* pString = 0, sal_uInt32 nSstIndex = 0 ) :
      70         449 :                             mpString( pString ), mnSstIndex( nSstIndex ) {}
      71             : };
      72             : 
      73             : /** Function object for strict weak ordering. */
      74             : struct XclExpHashEntrySWO
      75             : {
      76          83 :     inline bool         operator()( const XclExpHashEntry& rLeft, const XclExpHashEntry& rRight ) const
      77          83 :                             { return *rLeft.mpString < *rRight.mpString; }
      78             : };
      79             : 
      80             : /** Implementation of the SST export.
      81             :     @descr  Stores all passed strings in a hash table and prevents repeated
      82             :     insertion of equal strings. */
      83          72 : class XclExpSstImpl
      84             : {
      85             : public:
      86             :     explicit            XclExpSstImpl();
      87             : 
      88             :     /** Inserts the passed string, if not already inserted, and returns the unique SST index. */
      89             :     sal_uInt32          Insert( XclExpStringRef xString );
      90             : 
      91             :     /** Writes the complete SST and EXTSST records. */
      92             :     void                Save( XclExpStream& rStrm );
      93             :     void                SaveXml( XclExpXmlStream& rStrm );
      94             : 
      95             : private:
      96             :     typedef ::std::list< XclExpStringRef >      XclExpStringList;
      97             :     typedef ::std::vector< XclExpHashEntry >    XclExpHashVec;
      98             :     typedef ::std::vector< XclExpHashVec >      XclExpHashTab;
      99             : 
     100             :     XclExpStringList    maStringList;   /// List of unique strings (in SST ID order).
     101             :     XclExpHashTab       maHashTab;      /// Hashed table that manages string pointers.
     102             :     sal_uInt32          mnTotal;        /// Total count of strings (including doubles).
     103             :     sal_uInt32          mnSize;         /// Size of the SST (count of unique strings).
     104             : };
     105             : 
     106             : const sal_uInt32 EXC_SST_HASHTABLE_SIZE = 2048;
     107             : 
     108          72 : XclExpSstImpl::XclExpSstImpl() :
     109             :     maHashTab( EXC_SST_HASHTABLE_SIZE ),
     110             :     mnTotal( 0 ),
     111          72 :     mnSize( 0 )
     112             : {
     113          72 : }
     114             : 
     115         449 : sal_uInt32 XclExpSstImpl::Insert( XclExpStringRef xString )
     116             : {
     117             :     OSL_ENSURE( xString.get(), "XclExpSstImpl::Insert - empty pointer not allowed" );
     118         449 :     if( !xString.get() )
     119           0 :         xString.reset( new XclExpString );
     120             : 
     121         449 :     ++mnTotal;
     122         449 :     sal_uInt32 nSstIndex = 0;
     123             : 
     124             :     // calculate hash value in range [0,EXC_SST_HASHTABLE_SIZE)
     125         449 :     sal_uInt16 nHash = xString->GetHash();
     126         449 :     (nHash ^= (nHash / EXC_SST_HASHTABLE_SIZE)) %= EXC_SST_HASHTABLE_SIZE;
     127             : 
     128         449 :     XclExpHashVec& rVec = maHashTab[ nHash ];
     129         449 :     XclExpHashEntry aEntry( xString.get(), mnSize );
     130         449 :     XclExpHashVec::iterator aIt = ::std::lower_bound( rVec.begin(), rVec.end(), aEntry, XclExpHashEntrySWO() );
     131         449 :     if( (aIt == rVec.end()) || (*aIt->mpString != *xString) )
     132             :     {
     133         372 :         nSstIndex = mnSize;
     134         372 :         maStringList.push_back( xString );
     135         372 :         rVec.insert( aIt, aEntry );
     136         372 :         ++mnSize;
     137             :     }
     138             :     else
     139             :     {
     140          77 :         nSstIndex = aIt->mnSstIndex;
     141             :     }
     142             : 
     143         449 :     return nSstIndex;
     144             : }
     145             : 
     146          17 : void XclExpSstImpl::Save( XclExpStream& rStrm )
     147             : {
     148          17 :     if( maStringList.empty() )
     149          27 :         return;
     150             : 
     151           7 :     SvMemoryStream aExtSst( 8192 );
     152             : 
     153           7 :     sal_uInt32 nBucket = mnSize;
     154          14 :     while( nBucket > 0x0100 )
     155           0 :         nBucket /= 2;
     156             : 
     157           7 :     sal_uInt16 nPerBucket = llimit_cast< sal_uInt16 >( nBucket, 8 );
     158           7 :     sal_uInt16 nBucketIndex = 0;
     159             : 
     160             :     // *** write the SST record ***
     161             : 
     162           7 :     rStrm.StartRecord( EXC_ID_SST, 8 );
     163             : 
     164           7 :     rStrm << mnTotal << mnSize;
     165         143 :     for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
     166             :     {
     167         136 :         if( !nBucketIndex )
     168             :         {
     169             :             // write bucket info before string to get correct record position
     170           7 :             sal_uInt32 nStrmPos = static_cast< sal_uInt32 >( rStrm.GetSvStreamPos() );
     171           7 :             sal_uInt16 nRecPos = rStrm.GetRawRecPos() + 4;
     172           7 :             aExtSst.WriteUInt32( nStrmPos )             // stream position
     173          14 :                    .WriteUInt16( nRecPos )              // position from start of SST or CONTINUE
     174           7 :                    .WriteUInt16( 0 );     // reserved
     175             :         }
     176             : 
     177         136 :         rStrm << **aIt;
     178             : 
     179         136 :         if( ++nBucketIndex == nPerBucket )
     180           3 :             nBucketIndex = 0;
     181             :     }
     182             : 
     183           7 :     rStrm.EndRecord();
     184             : 
     185             :     // *** write the EXTSST record ***
     186             : 
     187           7 :     rStrm.StartRecord( EXC_ID_EXTSST, 0 );
     188             : 
     189           7 :     rStrm << nPerBucket;
     190           7 :     rStrm.SetSliceSize( 8 );    // size of one bucket info
     191           7 :     aExtSst.Seek( STREAM_SEEK_TO_BEGIN );
     192           7 :     rStrm.CopyFromStream( aExtSst );
     193             : 
     194           7 :     rStrm.EndRecord();
     195             : }
     196             : 
     197          55 : void XclExpSstImpl::SaveXml( XclExpXmlStream& rStrm )
     198             : {
     199          55 :     if( maStringList.empty() )
     200          77 :         return;
     201             : 
     202             :     sax_fastparser::FSHelperPtr pSst = rStrm.CreateOutputStream(
     203             :             OUString( "xl/sharedStrings.xml"),
     204             :             OUString( "sharedStrings.xml" ),
     205          33 :             rStrm.GetCurrentStream()->getOutputStream(),
     206             :             "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml",
     207          33 :             "http://schemas.openxmlformats.org/officeDocument/2006/relationships/sharedStrings" );
     208          33 :     rStrm.PushStream( pSst );
     209             : 
     210             :     pSst->startElement( XML_sst,
     211             :             XML_xmlns, "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
     212             :             XML_count, OString::number(  mnTotal ).getStr(),
     213             :             XML_uniqueCount, OString::number(  mnSize ).getStr(),
     214          33 :             FSEND );
     215             : 
     216         269 :     for( XclExpStringList::const_iterator aIt = maStringList.begin(), aEnd = maStringList.end(); aIt != aEnd; ++aIt )
     217             :     {
     218         236 :         pSst->startElement( XML_si, FSEND );
     219         236 :         (*aIt)->WriteXml( rStrm );
     220         236 :         pSst->endElement( XML_si );
     221             :     }
     222             : 
     223          33 :     pSst->endElement( XML_sst );
     224             : 
     225          33 :     rStrm.PopStream();
     226             : }
     227             : 
     228          72 : XclExpSst::XclExpSst() :
     229          72 :     mxImpl( new XclExpSstImpl )
     230             : {
     231          72 : }
     232             : 
     233         144 : XclExpSst::~XclExpSst()
     234             : {
     235         144 : }
     236             : 
     237         449 : sal_uInt32 XclExpSst::Insert( XclExpStringRef xString )
     238             : {
     239         449 :     return mxImpl->Insert( xString );
     240             : }
     241             : 
     242          17 : void XclExpSst::Save( XclExpStream& rStrm )
     243             : {
     244          17 :     mxImpl->Save( rStrm );
     245          17 : }
     246             : 
     247          55 : void XclExpSst::SaveXml( XclExpXmlStream& rStrm )
     248             : {
     249          55 :     mxImpl->SaveXml( rStrm );
     250          55 : }
     251             : 
     252             : // Merged cells ===============================================================
     253             : 
     254         129 : XclExpMergedcells::XclExpMergedcells( const XclExpRoot& rRoot ) :
     255         129 :     XclExpRoot( rRoot )
     256             : {
     257         129 : }
     258             : 
     259           6 : void XclExpMergedcells::AppendRange( const ScRange& rRange, sal_uInt32 nBaseXFId )
     260             : {
     261           6 :     if( GetBiff() == EXC_BIFF8 )
     262             :     {
     263           6 :         maMergedRanges.Append( rRange );
     264           6 :         maBaseXFIds.push_back( nBaseXFId );
     265             :     }
     266           6 : }
     267             : 
     268          34 : sal_uInt32 XclExpMergedcells::GetBaseXFId( const ScAddress& rPos ) const
     269             : {
     270             :     OSL_ENSURE( maBaseXFIds.size() == maMergedRanges.size(), "XclExpMergedcells::GetBaseXFId - invalid lists" );
     271          34 :     ScfUInt32Vec::const_iterator aIt = maBaseXFIds.begin();
     272          34 :     ScRangeList& rNCRanges = const_cast< ScRangeList& >( maMergedRanges );
     273          50 :     for ( size_t i = 0, nRanges = rNCRanges.size(); i < nRanges; ++i, ++aIt )
     274             :     {
     275          50 :         const ScRange* pScRange = rNCRanges[ i ];
     276          50 :         if( pScRange->In( rPos ) )
     277          34 :             return *aIt;
     278             :     }
     279           0 :     return EXC_XFID_NOTFOUND;
     280             : }
     281             : 
     282          29 : void XclExpMergedcells::Save( XclExpStream& rStrm )
     283             : {
     284          29 :     if( GetBiff() == EXC_BIFF8 )
     285             :     {
     286          29 :         XclRangeList aXclRanges;
     287          29 :         GetAddressConverter().ConvertRangeList( aXclRanges, maMergedRanges, true );
     288          29 :         size_t nFirstRange = 0;
     289          29 :         size_t nRemainingRanges = aXclRanges.size();
     290          60 :         while( nRemainingRanges > 0 )
     291             :         {
     292           2 :             size_t nRangeCount = ::std::min< size_t >( nRemainingRanges, EXC_MERGEDCELLS_MAXCOUNT );
     293           2 :             rStrm.StartRecord( EXC_ID_MERGEDCELLS, 2 + 8 * nRangeCount );
     294           2 :             aXclRanges.WriteSubList( rStrm, nFirstRange, nRangeCount );
     295           2 :             rStrm.EndRecord();
     296           2 :             nFirstRange += nRangeCount;
     297           2 :             nRemainingRanges -= nRangeCount;
     298          29 :         }
     299             :     }
     300          29 : }
     301             : 
     302         100 : void XclExpMergedcells::SaveXml( XclExpXmlStream& rStrm )
     303             : {
     304         100 :     size_t nCount = maMergedRanges.size();
     305         100 :     if( !nCount )
     306         198 :         return;
     307           2 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
     308             :     rWorksheet->startElement( XML_mergeCells,
     309             :             XML_count,  OString::number(  nCount ).getStr(),
     310           2 :             FSEND );
     311           5 :     for( size_t i = 0; i < nCount; ++i )
     312             :     {
     313           3 :         if( const ScRange* pRange = maMergedRanges[ i ] )
     314             :         {
     315             :             rWorksheet->singleElement( XML_mergeCell,
     316             :                     XML_ref,    XclXmlUtils::ToOString( *pRange ).getStr(),
     317           3 :                     FSEND );
     318             :         }
     319             :     }
     320           2 :     rWorksheet->endElement( XML_mergeCells );
     321             : }
     322             : 
     323             : // Hyperlinks =================================================================
     324             : 
     325           3 : XclExpHyperlink::XclExpHyperlink( const XclExpRoot& rRoot, const SvxURLField& rUrlField, const ScAddress& rScPos ) :
     326             :     XclExpRecord( EXC_ID_HLINK ),
     327             :     maScPos( rScPos ),
     328           3 :     mxVarData( new SvMemoryStream ),
     329             :     mnFlags( 0 ),
     330           6 :     mbSetDisplay( true )
     331             : {
     332           3 :     const OUString& rUrl = rUrlField.GetURL();
     333           3 :     const OUString& rRepr = rUrlField.GetRepresentation();
     334           3 :     INetURLObject aUrlObj( rUrl );
     335           3 :     const INetProtocol eProtocol = aUrlObj.GetProtocol();
     336           3 :     bool bWithRepr = !rRepr.isEmpty();
     337           6 :     XclExpStream aXclStrm( *mxVarData, rRoot );         // using in raw write mode.
     338             : 
     339             :     // description
     340           3 :     if( bWithRepr )
     341             :     {
     342           0 :         XclExpString aDescr( rRepr, EXC_STR_FORCEUNICODE, 255 );
     343           0 :         aXclStrm << sal_uInt32( aDescr.Len() + 1 );     // string length + 1 trailing zero word
     344           0 :         aDescr.WriteBuffer( aXclStrm );                 // NO flags
     345           0 :         aXclStrm << sal_uInt16( 0 );
     346             : 
     347           0 :         mnFlags |= EXC_HLINK_DESCR;
     348           0 :         m_Repr = rRepr;
     349             :     }
     350             : 
     351             :     // file link or URL
     352           3 :     if( eProtocol == INetProtocol::File || eProtocol == INetProtocol::Smb )
     353             :     {
     354             :         sal_uInt16 nLevel;
     355             :         bool bRel;
     356             :         /* TODO: should we differentiate between BIFF and OOXML and write IURI
     357             :          * encoded for OOXML? */
     358           0 :         OUString aFileName( BuildFileName( nLevel, bRel, rUrl, rRoot, false ) );
     359             : 
     360           0 :         if( eProtocol == INetProtocol::Smb )
     361             :         {
     362             :             // #n382718# (and #n261623#) Convert smb notation to '\\'
     363           0 :             aFileName = aUrlObj.GetMainURL( INetURLObject::NO_DECODE );
     364           0 :             aFileName = aFileName.copy(4); // skip the 'smb:' part
     365           0 :             aFileName = aFileName.replace('/', '\\');
     366             :         }
     367             : 
     368           0 :         if( !bRel )
     369           0 :             mnFlags |= EXC_HLINK_ABS;
     370           0 :         mnFlags |= EXC_HLINK_BODY;
     371             : 
     372             :         OString aAsciiLink(OUStringToOString(aFileName,
     373           0 :             rRoot.GetTextEncoding()));
     374           0 :         XclExpString aLink( aFileName, EXC_STR_FORCEUNICODE, 255 );
     375           0 :         aXclStrm    << XclTools::maGuidFileMoniker
     376           0 :                     << nLevel
     377           0 :                     << sal_uInt32( aAsciiLink.getLength() + 1 );      // string length + 1 trailing zero byte
     378           0 :         aXclStrm.Write( aAsciiLink.getStr(), aAsciiLink.getLength() );
     379           0 :         aXclStrm    << sal_uInt8( 0 )
     380           0 :                     << sal_uInt32( 0xDEADFFFF );
     381           0 :         aXclStrm.WriteZeroBytes( 20 );
     382           0 :         aXclStrm    << sal_uInt32( aLink.GetBufferSize() + 6 )
     383           0 :                     << sal_uInt32( aLink.GetBufferSize() )      // byte count, not string length
     384           0 :                     << sal_uInt16( 0x0003 );
     385           0 :         aLink.WriteBuffer( aXclStrm );                          // NO flags
     386             : 
     387           0 :         if (m_Repr.isEmpty())
     388           0 :             m_Repr = aFileName;
     389             : 
     390           0 :         msTarget = XclXmlUtils::ToOUString( aLink );
     391             :         // ooxml expects the file:/// part appended ( or at least
     392             :         // ms2007 does, ms2010 is more tolerant )
     393           0 :         msTarget = "file:///" + msTarget;
     394             :     }
     395           3 :     else if( eProtocol != INetProtocol::NotValid )
     396             :     {
     397           2 :         XclExpString aUrl( aUrlObj.GetURLNoMark(), EXC_STR_FORCEUNICODE, 255 );
     398           2 :         aXclStrm    << XclTools::maGuidUrlMoniker
     399           4 :                     << sal_uInt32( aUrl.GetBufferSize() + 2 );  // byte count + 1 trailing zero word
     400           2 :         aUrl.WriteBuffer( aXclStrm );                           // NO flags
     401           2 :         aXclStrm    << sal_uInt16( 0 );
     402             : 
     403           2 :         mnFlags |= EXC_HLINK_BODY | EXC_HLINK_ABS;
     404           2 :         if (m_Repr.isEmpty())
     405           2 :             m_Repr = rUrl;
     406             : 
     407           2 :         msTarget = XclXmlUtils::ToOUString( aUrl );
     408             :     }
     409           1 :     else if( !rUrl.isEmpty() && rUrl[0] == '#' )     // hack for #89066#
     410             :     {
     411           1 :         OUString aTextMark( rUrl.copy( 1 ) );
     412             : 
     413           1 :         sal_Int32 nSepPos = aTextMark.indexOf( '.' );
     414           1 :         if(nSepPos != -1)
     415             :         {
     416           1 :             aTextMark = aTextMark.replaceAt( nSepPos, 1, "!" );
     417           1 :             OUString aSheetName( aTextMark.copy(0, nSepPos));
     418             : 
     419           1 :             if ( aSheetName.indexOf(' ') != -1 && aSheetName[0] != '\'')
     420             :             {
     421           0 :                 aTextMark = "'" + aTextMark.replaceAt(nSepPos, 0, "'");
     422           1 :             }
     423             :         }
     424             : 
     425           1 :         mxTextMark.reset( new XclExpString( aTextMark, EXC_STR_FORCEUNICODE, 255 ) );
     426             :     }
     427             : 
     428             :     // text mark
     429           3 :     if( !mxTextMark.get() && aUrlObj.HasMark() )
     430           0 :         mxTextMark.reset( new XclExpString( aUrlObj.GetMark(), EXC_STR_FORCEUNICODE, 255 ) );
     431             : 
     432           3 :     if( mxTextMark.get() )
     433             :     {
     434           1 :         aXclStrm    << sal_uInt32( mxTextMark->Len() + 1 );  // string length + 1 trailing zero word
     435           1 :         mxTextMark->WriteBuffer( aXclStrm );                 // NO flags
     436           1 :         aXclStrm    << sal_uInt16( 0 );
     437             : 
     438           1 :         mnFlags |= EXC_HLINK_MARK;
     439             :     }
     440             : 
     441           6 :     SetRecSize( 32 + mxVarData->Tell() );
     442           3 : }
     443             : 
     444           3 : XclExpHyperlink::~XclExpHyperlink()
     445             : {
     446           3 : }
     447             : 
     448           0 : OUString XclExpHyperlink::BuildFileName(
     449             :         sal_uInt16& rnLevel, bool& rbRel, const OUString& rUrl, const XclExpRoot& rRoot, bool bEncoded )
     450             : {
     451           0 :     INetURLObject aURLObject( rUrl );
     452           0 :     OUString aDosName( bEncoded ? aURLObject.GetURLPath() : aURLObject.getFSysPath( INetURLObject::FSYS_DOS ) );
     453           0 :     rnLevel = 0;
     454           0 :     rbRel = rRoot.IsRelUrl();
     455             : 
     456           0 :     if( rbRel )
     457             :     {
     458             :         // try to convert to relative file name
     459           0 :         OUString aTmpName( aDosName );
     460           0 :         aDosName = INetURLObject::GetRelURL( rRoot.GetBasePath(), rUrl,
     461             :             INetURLObject::WAS_ENCODED,
     462           0 :             (bEncoded ? INetURLObject::DECODE_TO_IURI : INetURLObject::DECODE_WITH_CHARSET));
     463             : 
     464           0 :         if (aDosName.startsWith(INET_FILE_SCHEME))
     465             :         {
     466             :             // not converted to rel -> back to old, return absolute flag
     467           0 :             aDosName = aTmpName;
     468           0 :             rbRel = false;
     469             :         }
     470           0 :         else if (aDosName.startsWith("./"))
     471             :         {
     472           0 :             aDosName = aDosName.copy(2);
     473             :         }
     474             :         else
     475             :         {
     476           0 :             while (aDosName.startsWith("../"))
     477             :             {
     478           0 :                 aDosName = aDosName.copy(3);
     479           0 :                 ++rnLevel;
     480             :             }
     481           0 :         }
     482             :     }
     483           0 :     return aDosName;
     484             : }
     485             : 
     486           0 : void XclExpHyperlink::WriteBody( XclExpStream& rStrm )
     487             : {
     488           0 :     sal_uInt16 nXclCol = static_cast< sal_uInt16 >( maScPos.Col() );
     489           0 :     sal_uInt16 nXclRow = static_cast< sal_uInt16 >( maScPos.Row() );
     490           0 :     rStrm   << nXclRow << nXclRow << nXclCol << nXclCol;
     491           0 :     WriteEmbeddedData( rStrm );
     492           0 : }
     493             : 
     494           3 : void XclExpHyperlink::WriteEmbeddedData( XclExpStream& rStrm )
     495             : {
     496           3 :     rStrm << XclTools::maGuidStdLink
     497           3 :             << sal_uInt32( 2 )
     498           6 :             << mnFlags;
     499             : 
     500           3 :     mxVarData->Seek( STREAM_SEEK_TO_BEGIN );
     501           3 :     rStrm.CopyFromStream( *mxVarData );
     502           3 : }
     503             : 
     504           0 : void XclExpHyperlink::SaveXml( XclExpXmlStream& rStrm )
     505             : {
     506           0 :     OUString sId = !msTarget.isEmpty() ? rStrm.addRelation( rStrm.GetCurrentStream()->getOutputStream(),
     507             :             XclXmlUtils::ToOUString( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
     508           0 :             msTarget, true ) : OUString();
     509           0 :     rStrm.GetCurrentStream()->singleElement( XML_hyperlink,
     510             :             XML_ref,                XclXmlUtils::ToOString( maScPos ).getStr(),
     511           0 :             FSNS( XML_r, XML_id ),  !sId.isEmpty()
     512           0 :                                        ? XclXmlUtils::ToOString( sId ).getStr()
     513             :                                        : NULL,
     514           0 :             XML_location,           mxTextMark.get() != NULL
     515           0 :                                         ? XclXmlUtils::ToOString( *mxTextMark ).getStr()
     516             :                                         : NULL,
     517             :             // OOXTODO: XML_tooltip,    from record HLinkTooltip 800h wzTooltip
     518             :             XML_display,            mbSetDisplay
     519           0 :                                        ? XclXmlUtils::ToOString(m_Repr).getStr()
     520             :                                        : NULL,
     521           0 :             FSEND );
     522           0 : }
     523             : 
     524             : // Label ranges ===============================================================
     525             : 
     526          29 : XclExpLabelranges::XclExpLabelranges( const XclExpRoot& rRoot ) :
     527          29 :     XclExpRoot( rRoot )
     528             : {
     529          29 :     SCTAB nScTab = GetCurrScTab();
     530             :     // row label ranges
     531          29 :     FillRangeList( maRowRanges, rRoot.GetDoc().GetRowNameRangesRef(), nScTab );
     532             :     // row labels only over 1 column (restriction of Excel97/2000/XP)
     533          29 :     for ( size_t i = 0, nRanges = maRowRanges.size(); i < nRanges; ++i )
     534             :     {
     535           0 :         ScRange* pScRange = maRowRanges[ i ];
     536           0 :         if( pScRange->aStart.Col() != pScRange->aEnd.Col() )
     537           0 :             pScRange->aEnd.SetCol( pScRange->aStart.Col() );
     538             :     }
     539             :     // col label ranges
     540          29 :     FillRangeList( maColRanges, rRoot.GetDoc().GetColNameRangesRef(), nScTab );
     541          29 : }
     542             : 
     543          58 : void XclExpLabelranges::FillRangeList( ScRangeList& rScRanges,
     544             :         ScRangePairListRef xLabelRangesRef, SCTAB nScTab )
     545             : {
     546          58 :     for ( size_t i = 0, nPairs = xLabelRangesRef->size(); i < nPairs; ++i )
     547             :     {
     548           0 :         ScRangePair* pRangePair = (*xLabelRangesRef)[i];
     549           0 :         const ScRange& rScRange = pRangePair->GetRange( 0 );
     550           0 :         if( rScRange.aStart.Tab() == nScTab )
     551           0 :             rScRanges.Append( rScRange );
     552             :     }
     553          58 : }
     554             : 
     555          29 : void XclExpLabelranges::Save( XclExpStream& rStrm )
     556             : {
     557          29 :     XclExpAddressConverter& rAddrConv = GetAddressConverter();
     558          58 :     XclRangeList aRowXclRanges, aColXclRanges;
     559          29 :     rAddrConv.ConvertRangeList( aRowXclRanges, maRowRanges, false );
     560          29 :     rAddrConv.ConvertRangeList( aColXclRanges, maColRanges, false );
     561          29 :     if( !aRowXclRanges.empty() || !aColXclRanges.empty() )
     562             :     {
     563           0 :         rStrm.StartRecord( EXC_ID_LABELRANGES, 4 + 8 * (aRowXclRanges.size() + aColXclRanges.size()) );
     564           0 :         rStrm << aRowXclRanges << aColXclRanges;
     565           0 :         rStrm.EndRecord();
     566          29 :     }
     567          29 : }
     568             : 
     569             : // Conditional formatting  ====================================================
     570             : 
     571             : /** Represents a CF record that contains one condition of a conditional format. */
     572          20 : class XclExpCFImpl : protected XclExpRoot
     573             : {
     574             : public:
     575             :     explicit            XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority = 0 );
     576             : 
     577             :     /** Writes the body of the CF record. */
     578             :     void                WriteBody( XclExpStream& rStrm );
     579             :     void                SaveXml( XclExpXmlStream& rStrm );
     580             : 
     581             : private:
     582             :     const ScCondFormatEntry& mrFormatEntry; /// Calc conditional format entry.
     583             :     XclFontData         maFontData;         /// Font formatting attributes.
     584             :     XclExpCellBorder    maBorder;           /// Border formatting attributes.
     585             :     XclExpCellArea      maArea;             /// Pattern formatting attributes.
     586             :     XclTokenArrayRef    mxTokArr1;          /// Formula for first condition.
     587             :     XclTokenArrayRef    mxTokArr2;          /// Formula for second condition.
     588             :     sal_uInt32          mnFontColorId;      /// Font color ID.
     589             :     sal_uInt8           mnType;             /// Type of the condition (cell/formula).
     590             :     sal_uInt8           mnOperator;         /// Comparison operator for cell type.
     591             :     sal_Int32           mnPriority;         /// Priority of this entry; needed for oox export
     592             :     bool                mbFontUsed;         /// true = Any font attribute used.
     593             :     bool                mbHeightUsed;       /// true = Font height used.
     594             :     bool                mbWeightUsed;       /// true = Font weight used.
     595             :     bool                mbColorUsed;        /// true = Font color used.
     596             :     bool                mbUnderlUsed;       /// true = Font underline type used.
     597             :     bool                mbItalicUsed;       /// true = Font posture used.
     598             :     bool                mbStrikeUsed;       /// true = Font strikeout used.
     599             :     bool                mbBorderUsed;       /// true = Border attribute used.
     600             :     bool                mbPattUsed;         /// true = Pattern attribute used.
     601             : };
     602             : 
     603          10 : XclExpCFImpl::XclExpCFImpl( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority ) :
     604             :     XclExpRoot( rRoot ),
     605             :     mrFormatEntry( rFormatEntry ),
     606             :     mnFontColorId( 0 ),
     607             :     mnType( EXC_CF_TYPE_CELL ),
     608             :     mnOperator( EXC_CF_CMP_NONE ),
     609             :     mnPriority( nPriority ),
     610             :     mbFontUsed( false ),
     611             :     mbHeightUsed( false ),
     612             :     mbWeightUsed( false ),
     613             :     mbColorUsed( false ),
     614             :     mbUnderlUsed( false ),
     615             :     mbItalicUsed( false ),
     616             :     mbStrikeUsed( false ),
     617             :     mbBorderUsed( false ),
     618          10 :     mbPattUsed( false )
     619             : {
     620             :     /*  Get formatting attributes here, and not in WriteBody(). This is needed to
     621             :         correctly insert all colors into the palette. */
     622             : 
     623          10 :     if( SfxStyleSheetBase* pStyleSheet = GetDoc().GetStyleSheetPool()->Find( mrFormatEntry.GetStyle(), SFX_STYLE_FAMILY_PARA ) )
     624             :     {
     625          10 :         const SfxItemSet& rItemSet = pStyleSheet->GetItemSet();
     626             : 
     627             :         // font
     628          10 :         mbHeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_HEIGHT,     true );
     629          10 :         mbWeightUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_WEIGHT,     true );
     630          10 :         mbColorUsed  = ScfTools::CheckItem( rItemSet, ATTR_FONT_COLOR,      true );
     631          10 :         mbUnderlUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_UNDERLINE,  true );
     632          10 :         mbItalicUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_POSTURE,    true );
     633          10 :         mbStrikeUsed = ScfTools::CheckItem( rItemSet, ATTR_FONT_CROSSEDOUT, true );
     634          10 :         mbFontUsed = mbHeightUsed || mbWeightUsed || mbColorUsed || mbUnderlUsed || mbItalicUsed || mbStrikeUsed;
     635          10 :         if( mbFontUsed )
     636             :         {
     637           0 :             vcl::Font aFont;
     638           0 :             ScPatternAttr::GetFont( aFont, rItemSet, SC_AUTOCOL_RAW );
     639           0 :             maFontData.FillFromVclFont( aFont );
     640           0 :             mnFontColorId = GetPalette().InsertColor( maFontData.maColor, EXC_COLOR_CELLTEXT );
     641             :         }
     642             : 
     643             :         // border
     644          10 :         mbBorderUsed = ScfTools::CheckItem( rItemSet, ATTR_BORDER, true );
     645          10 :         if( mbBorderUsed )
     646           0 :             maBorder.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
     647             : 
     648             :         // pattern
     649          10 :         mbPattUsed = ScfTools::CheckItem( rItemSet, ATTR_BACKGROUND, true );
     650          10 :         if( mbPattUsed )
     651           0 :             maArea.FillFromItemSet( rItemSet, GetPalette(), GetBiff() );
     652             :     }
     653             : 
     654             :     // *** mode and comparison operator ***
     655             : 
     656          10 :     bool bFmla2 = false;
     657          10 :     switch( rFormatEntry.GetOperation() )
     658             :     {
     659           0 :         case SC_COND_NONE:          mnType = EXC_CF_TYPE_NONE;                              break;
     660           0 :         case SC_COND_BETWEEN:       mnOperator = EXC_CF_CMP_BETWEEN;        bFmla2 = true;  break;
     661           0 :         case SC_COND_NOTBETWEEN:    mnOperator = EXC_CF_CMP_NOT_BETWEEN;    bFmla2 = true;  break;
     662           0 :         case SC_COND_EQUAL:         mnOperator = EXC_CF_CMP_EQUAL;                          break;
     663           0 :         case SC_COND_NOTEQUAL:      mnOperator = EXC_CF_CMP_NOT_EQUAL;                      break;
     664           0 :         case SC_COND_GREATER:       mnOperator = EXC_CF_CMP_GREATER;                        break;
     665           0 :         case SC_COND_LESS:          mnOperator = EXC_CF_CMP_LESS;                           break;
     666           0 :         case SC_COND_EQGREATER:     mnOperator = EXC_CF_CMP_GREATER_EQUAL;                  break;
     667           0 :         case SC_COND_EQLESS:        mnOperator = EXC_CF_CMP_LESS_EQUAL;                     break;
     668           2 :         case SC_COND_DIRECT:        mnType = EXC_CF_TYPE_FMLA;                              break;
     669           8 :         default:                    mnType = EXC_CF_TYPE_NONE;
     670             :             OSL_FAIL( "XclExpCF::WriteBody - unknown condition type" );
     671             :     }
     672             : 
     673             :     // *** formulas ***
     674             : 
     675          10 :     XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
     676             : 
     677          10 :     boost::scoped_ptr< ScTokenArray > xScTokArr( mrFormatEntry.CreateTokenArry( 0 ) );
     678          10 :     mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
     679             : 
     680          10 :     if( bFmla2 )
     681             :     {
     682           0 :         xScTokArr.reset( mrFormatEntry.CreateTokenArry( 1 ) );
     683           0 :         mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_CONDFMT, *xScTokArr );
     684          10 :     }
     685          10 : }
     686             : 
     687           0 : void XclExpCFImpl::WriteBody( XclExpStream& rStrm )
     688             : {
     689             :     // *** mode and comparison operator ***
     690             : 
     691           0 :     rStrm << mnType << mnOperator;
     692             : 
     693             :     // *** formula sizes ***
     694             : 
     695           0 :     sal_uInt16 nFmlaSize1 = mxTokArr1.get() ? mxTokArr1->GetSize() : 0;
     696           0 :     sal_uInt16 nFmlaSize2 = mxTokArr2.get() ? mxTokArr2->GetSize() : 0;
     697           0 :     rStrm << nFmlaSize1 << nFmlaSize2;
     698             : 
     699             :     // *** formatting blocks ***
     700             : 
     701           0 :     if( mbFontUsed || mbBorderUsed || mbPattUsed )
     702             :     {
     703           0 :         sal_uInt32 nFlags = EXC_CF_ALLDEFAULT;
     704             : 
     705           0 :         ::set_flag( nFlags, EXC_CF_BLOCK_FONT,   mbFontUsed );
     706           0 :         ::set_flag( nFlags, EXC_CF_BLOCK_BORDER, mbBorderUsed );
     707           0 :         ::set_flag( nFlags, EXC_CF_BLOCK_AREA,   mbPattUsed );
     708             : 
     709             :         // attributes used -> set flags to 0.
     710           0 :         ::set_flag( nFlags, EXC_CF_BORDER_ALL, !mbBorderUsed );
     711           0 :         ::set_flag( nFlags, EXC_CF_AREA_ALL,   !mbPattUsed );
     712             : 
     713           0 :         rStrm << nFlags << sal_uInt16( 0 );
     714             : 
     715           0 :         if( mbFontUsed )
     716             :         {
     717             :             // font height, 0xFFFFFFFF indicates unused
     718           0 :             sal_uInt32 nHeight = mbHeightUsed ? maFontData.mnHeight : 0xFFFFFFFF;
     719             :             // font style: italic and strikeout
     720           0 :             sal_uInt32 nStyle = 0;
     721           0 :             ::set_flag( nStyle, EXC_CF_FONT_STYLE,     maFontData.mbItalic );
     722           0 :             ::set_flag( nStyle, EXC_CF_FONT_STRIKEOUT, maFontData.mbStrikeout );
     723             :             // font color, 0xFFFFFFFF indicates unused
     724           0 :             sal_uInt32 nColor = mbColorUsed ? GetPalette().GetColorIndex( mnFontColorId ) : 0xFFFFFFFF;
     725             :             // font used flags for italic, weight, and strikeout -> 0 = used, 1 = default
     726           0 :             sal_uInt32 nFontFlags1 = EXC_CF_FONT_ALLDEFAULT;
     727           0 :             ::set_flag( nFontFlags1, EXC_CF_FONT_STYLE, !(mbItalicUsed || mbWeightUsed) );
     728           0 :             ::set_flag( nFontFlags1, EXC_CF_FONT_STRIKEOUT, !mbStrikeUsed );
     729             :             // font used flag for underline -> 0 = used, 1 = default
     730           0 :             sal_uInt32 nFontFlags3 = mbUnderlUsed ? 0 : EXC_CF_FONT_UNDERL;
     731             : 
     732           0 :             rStrm.WriteZeroBytesToRecord( 64 );
     733           0 :             rStrm   << nHeight
     734           0 :                     << nStyle
     735           0 :                     << maFontData.mnWeight
     736           0 :                     << EXC_FONTESC_NONE
     737           0 :                     << maFontData.mnUnderline;
     738           0 :             rStrm.WriteZeroBytesToRecord( 3 );
     739           0 :             rStrm   << nColor
     740           0 :                     << sal_uInt32( 0 )
     741           0 :                     << nFontFlags1
     742           0 :                     << EXC_CF_FONT_ESCAPEM      // escapement never used -> set the flag
     743           0 :                     << nFontFlags3;
     744           0 :             rStrm.WriteZeroBytesToRecord( 16 );
     745           0 :             rStrm   << sal_uInt16( 1 );         // must be 1
     746             :         }
     747             : 
     748           0 :         if( mbBorderUsed )
     749             :         {
     750           0 :             sal_uInt16 nLineStyle = 0;
     751           0 :             sal_uInt32 nLineColor = 0;
     752           0 :             maBorder.SetFinalColors( GetPalette() );
     753           0 :             maBorder.FillToCF8( nLineStyle, nLineColor );
     754           0 :             rStrm << nLineStyle << nLineColor << sal_uInt16( 0 );
     755             :         }
     756             : 
     757           0 :         if( mbPattUsed )
     758             :         {
     759           0 :             sal_uInt16 nPattern = 0, nColor = 0;
     760           0 :             maArea.SetFinalColors( GetPalette() );
     761           0 :             maArea.FillToCF8( nPattern, nColor );
     762           0 :             rStrm << nPattern << nColor;
     763           0 :         }
     764             :     }
     765             :     else
     766             :     {
     767             :         // no data blocks at all
     768           0 :         rStrm << sal_uInt32( 0 ) << sal_uInt16( 0 );
     769             :     }
     770             : 
     771             :     // *** formulas ***
     772             : 
     773           0 :     if( mxTokArr1.get() )
     774           0 :         mxTokArr1->WriteArray( rStrm );
     775           0 :     if( mxTokArr2.get() )
     776           0 :         mxTokArr2->WriteArray( rStrm );
     777           0 : }
     778             : 
     779             : namespace {
     780             : 
     781          10 : const char* GetOperatorString(ScConditionMode eMode, bool& bFrmla2)
     782             : {
     783          10 :     const char *pRet = NULL;
     784          10 :     switch(eMode)
     785             :     {
     786             :         case SC_COND_EQUAL:
     787           0 :             pRet = "equal";
     788           0 :             break;
     789             :         case SC_COND_LESS:
     790           0 :             pRet = "lessThan";
     791           0 :             break;
     792             :         case SC_COND_GREATER:
     793           0 :             pRet = "greaterThan";
     794           0 :             break;
     795             :         case SC_COND_EQLESS:
     796           0 :             pRet = "lessThanOrEqual";
     797           0 :             break;
     798             :         case SC_COND_EQGREATER:
     799           0 :             pRet = "greaterThanOrEqual";
     800           0 :             break;
     801             :         case SC_COND_NOTEQUAL:
     802           0 :             pRet = "notEqual";
     803           0 :             break;
     804             :         case SC_COND_BETWEEN:
     805           0 :             bFrmla2 = true;
     806           0 :             pRet = "between";
     807           0 :             break;
     808             :         case SC_COND_NOTBETWEEN:
     809           0 :             bFrmla2 = true;
     810           0 :             pRet = "notBetween";
     811           0 :             break;
     812             :         case SC_COND_DUPLICATE:
     813           0 :             pRet = NULL;
     814           0 :             break;
     815             :         case SC_COND_NOTDUPLICATE:
     816           0 :             pRet = NULL;
     817           0 :             break;
     818             :         case SC_COND_DIRECT:
     819           2 :             break;
     820             :         case SC_COND_NONE:
     821             :         default:
     822           8 :             break;
     823             :     }
     824          10 :     return pRet;
     825             : }
     826             : 
     827          10 : const char* GetTypeString(ScConditionMode eMode)
     828             : {
     829          10 :     switch(eMode)
     830             :     {
     831             :         case SC_COND_DIRECT:
     832           2 :             return "expression";
     833             :         case SC_COND_TOP10:
     834             :         case SC_COND_TOP_PERCENT:
     835             :         case SC_COND_BOTTOM10:
     836             :         case SC_COND_BOTTOM_PERCENT:
     837           4 :             return "top10";
     838             :         case SC_COND_ABOVE_AVERAGE:
     839             :         case SC_COND_BELOW_AVERAGE:
     840             :         case SC_COND_ABOVE_EQUAL_AVERAGE:
     841             :         case SC_COND_BELOW_EQUAL_AVERAGE:
     842           4 :             return "aboveAverage";
     843             :         case SC_COND_NOTDUPLICATE:
     844           0 :             return "uniqueValues";
     845             :         case SC_COND_DUPLICATE:
     846           0 :             return "duplicateValues";
     847             :         case SC_COND_ERROR:
     848           0 :             return "containsErrors";
     849             :         case SC_COND_NOERROR:
     850           0 :             return "notContainsErrors";
     851             :         case SC_COND_BEGINS_WITH:
     852           0 :             return "beginsWith";
     853             :         case SC_COND_ENDS_WITH:
     854           0 :             return "endsWith";
     855             :         case SC_COND_CONTAINS_TEXT:
     856           0 :             return "containsText";
     857             :         case SC_COND_NOT_CONTAINS_TEXT:
     858           0 :             return "notContainsText";
     859             :         default:
     860           0 :             return "cellIs";
     861             :     }
     862             : }
     863             : 
     864          20 : bool IsTopBottomRule(ScConditionMode eMode)
     865             : {
     866          20 :     switch(eMode)
     867             :     {
     868             :         case SC_COND_TOP10:
     869             :         case SC_COND_BOTTOM10:
     870             :         case SC_COND_TOP_PERCENT:
     871             :         case SC_COND_BOTTOM_PERCENT:
     872           8 :             return true;
     873             :         default:
     874          12 :             break;
     875             :     }
     876             : 
     877          12 :     return false;
     878             : }
     879             : 
     880          20 : bool IsTextRule(ScConditionMode eMode)
     881             : {
     882          20 :     switch(eMode)
     883             :     {
     884             :         case SC_COND_BEGINS_WITH:
     885             :         case SC_COND_ENDS_WITH:
     886             :         case SC_COND_CONTAINS_TEXT:
     887             :         case SC_COND_NOT_CONTAINS_TEXT:
     888           0 :             return true;
     889             :         default:
     890          20 :             break;
     891             :     }
     892             : 
     893          20 :     return false;
     894             : }
     895             : 
     896             : }
     897             : 
     898          10 : void XclExpCFImpl::SaveXml( XclExpXmlStream& rStrm )
     899             : {
     900          10 :     bool bFmla2 = false;
     901          10 :     ScConditionMode eOperation = mrFormatEntry.GetOperation();
     902          10 :     bool nAboveAverage = eOperation == SC_COND_ABOVE_AVERAGE ||
     903          10 :                                 eOperation == SC_COND_ABOVE_EQUAL_AVERAGE;
     904          10 :     bool nEqualAverage = eOperation == SC_COND_ABOVE_EQUAL_AVERAGE ||
     905          10 :                                 eOperation == SC_COND_BELOW_EQUAL_AVERAGE;
     906             :     bool nBottom = eOperation == SC_COND_BOTTOM10
     907          10 :         || eOperation == SC_COND_BOTTOM_PERCENT;
     908          10 :     bool nPercent = eOperation == SC_COND_TOP_PERCENT ||
     909          10 :         eOperation == SC_COND_BOTTOM_PERCENT;
     910          10 :     OString aRank("0");
     911          10 :     if(IsTopBottomRule(eOperation))
     912             :     {
     913             :         // position and formula grammar are not important
     914             :         // we only store a number there
     915           4 :         aRank = XclXmlUtils::ToOString(mrFormatEntry.GetExpression(ScAddress(0,0,0), 0));
     916             :     }
     917          20 :     OString aText;
     918          10 :     if(IsTextRule(eOperation))
     919             :     {
     920             :         // we need to write the text without quotes
     921             :         // we have to actually get the string from
     922             :         // the token array for that
     923           0 :         boost::scoped_ptr<ScTokenArray> pTokenArray(mrFormatEntry.CreateTokenArry(0));
     924           0 :         if(pTokenArray->GetLen())
     925           0 :             aText = XclXmlUtils::ToOString(pTokenArray->First()->GetString().getString());
     926             :     }
     927             : 
     928          10 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
     929             :     rWorksheet->startElement( XML_cfRule,
     930             :             XML_type, GetTypeString( mrFormatEntry.GetOperation() ),
     931             :             XML_priority, OString::number( mnPriority + 1 ).getStr(),
     932             :             XML_operator, GetOperatorString( mrFormatEntry.GetOperation(), bFmla2 ),
     933             :             XML_aboveAverage, OString::number( int(nAboveAverage) ).getStr(),
     934             :             XML_equalAverage, OString::number( int(nEqualAverage) ).getStr(),
     935             :             XML_bottom, OString::number( int(nBottom) ).getStr(),
     936             :             XML_percent, OString::number( int(nPercent) ).getStr(),
     937             :             XML_rank, aRank.getStr(),
     938             :             XML_text, aText.getStr(),
     939          10 :             XML_dxfId, OString::number( GetDxfs().GetDxfId( mrFormatEntry.GetStyle() ) ).getStr(),
     940          10 :             FSEND );
     941          10 :     if(!IsTextRule(eOperation) && !IsTopBottomRule(eOperation))
     942             :     {
     943           6 :         rWorksheet->startElement( XML_formula, FSEND );
     944           6 :         rWorksheet->writeEscaped(XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormatEntry.GetValidSrcPos(),
     945          12 :                     mrFormatEntry.CreateTokenArry(0)));
     946           6 :         rWorksheet->endElement( XML_formula );
     947           6 :         if (bFmla2)
     948             :         {
     949           0 :             rWorksheet->startElement( XML_formula, FSEND );
     950           0 :             rWorksheet->writeEscaped(XclXmlUtils::ToOUString( GetCompileFormulaContext(), mrFormatEntry.GetValidSrcPos(),
     951           0 :                         mrFormatEntry.CreateTokenArry(1)));
     952           0 :             rWorksheet->endElement( XML_formula );
     953             :         }
     954             :     }
     955             :     // OOXTODO: XML_extLst
     956          20 :     rWorksheet->endElement( XML_cfRule );
     957          10 : }
     958             : 
     959          10 : XclExpCF::XclExpCF( const XclExpRoot& rRoot, const ScCondFormatEntry& rFormatEntry, sal_Int32 nPriority = 0 ) :
     960             :     XclExpRecord( EXC_ID_CF ),
     961             :     XclExpRoot( rRoot ),
     962          10 :     mxImpl( new XclExpCFImpl( rRoot, rFormatEntry, nPriority ) )
     963             : {
     964          10 : }
     965             : 
     966          20 : XclExpCF::~XclExpCF()
     967             : {
     968          20 : }
     969             : 
     970           0 : void XclExpCF::WriteBody( XclExpStream& rStrm )
     971             : {
     972           0 :     mxImpl->WriteBody( rStrm );
     973           0 : }
     974             : 
     975          10 : void XclExpCF::SaveXml( XclExpXmlStream& rStrm )
     976             : {
     977          10 :     mxImpl->SaveXml( rStrm );
     978          10 : }
     979             : 
     980           0 : XclExpDateFormat::XclExpDateFormat( const XclExpRoot& rRoot, const ScCondDateFormatEntry& rFormatEntry, sal_Int32 nPriority ):
     981             :     XclExpRecord( EXC_ID_CF ),
     982             :     XclExpRoot( rRoot ),
     983             :     mrFormatEntry(rFormatEntry),
     984           0 :     mnPriority(nPriority)
     985             : {
     986           0 : }
     987             : 
     988           0 : XclExpDateFormat::~XclExpDateFormat()
     989             : {
     990           0 : }
     991             : 
     992             : namespace {
     993             : 
     994           0 : const char* getTimePeriodString( condformat::ScCondFormatDateType eType )
     995             : {
     996           0 :     switch(eType)
     997             :     {
     998             :         case condformat::TODAY:
     999           0 :             return "today";
    1000             :         case condformat::YESTERDAY:
    1001           0 :             return "yesterday";
    1002             :         case condformat::TOMORROW:
    1003           0 :             return "yesterday";
    1004             :         case condformat::THISWEEK:
    1005           0 :             return "thisWeek";
    1006             :         case condformat::LASTWEEK:
    1007           0 :             return "lastWeek";
    1008             :         case condformat::NEXTWEEK:
    1009           0 :             return "nextWeek";
    1010             :         case condformat::THISMONTH:
    1011           0 :             return "thisMonth";
    1012             :         case condformat::LASTMONTH:
    1013           0 :             return "lastMonth";
    1014             :         case condformat::NEXTMONTH:
    1015           0 :             return "nextMonth";
    1016             :         case condformat::LAST7DAYS:
    1017           0 :             return "last7Days";
    1018             :         default:
    1019           0 :             break;
    1020             :     }
    1021           0 :     return NULL;
    1022             : }
    1023             : 
    1024             : }
    1025             : 
    1026           0 : void XclExpDateFormat::SaveXml( XclExpXmlStream& rStrm )
    1027             : {
    1028             :     // only write the supported entries into OOXML
    1029           0 :     const char* sTimePeriod = getTimePeriodString(mrFormatEntry.GetDateType());
    1030           0 :     if(!sTimePeriod)
    1031           0 :         return;
    1032             : 
    1033           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1034             :     rWorksheet->startElement( XML_cfRule,
    1035             :             XML_type, "timePeriod",
    1036             :             XML_priority, OString::number( mnPriority + 1 ).getStr(),
    1037             :             XML_timePeriod, sTimePeriod,
    1038           0 :             XML_dxfId, OString::number( GetDxfs().GetDxfId( mrFormatEntry.GetStyleName() ) ).getStr(),
    1039           0 :             FSEND );
    1040           0 :     rWorksheet->endElement( XML_cfRule);
    1041             : }
    1042             : 
    1043          25 : XclExpCfvo::XclExpCfvo(const XclExpRoot& rRoot, const ScColorScaleEntry& rEntry, const ScAddress& rAddr, bool bFirst):
    1044             :     XclExpRecord(),
    1045             :     XclExpRoot( rRoot ),
    1046             :     mrEntry(rEntry),
    1047             :     maSrcPos(rAddr),
    1048          25 :     mbFirst(bFirst)
    1049             : {
    1050          25 : }
    1051             : 
    1052             : namespace {
    1053             : 
    1054          25 : OString getColorScaleType( const ScColorScaleEntry& rEntry, bool bFirst )
    1055             : {
    1056          25 :     switch(rEntry.GetType())
    1057             :     {
    1058             :         case COLORSCALE_MIN:
    1059           3 :             return "min";
    1060             :         case COLORSCALE_MAX:
    1061           3 :             return "max";
    1062             :         case COLORSCALE_PERCENT:
    1063           3 :             return "percent";
    1064             :         case COLORSCALE_FORMULA:
    1065           3 :             return "formula";
    1066             :         case COLORSCALE_AUTO:
    1067           4 :             if(bFirst)
    1068           2 :                 return "min";
    1069             :             else
    1070           2 :                 return "max";
    1071             :         case COLORSCALE_PERCENTILE:
    1072           4 :             return "percentile";
    1073             :         default:
    1074           5 :             break;
    1075             :     }
    1076             : 
    1077           5 :     return "num";
    1078             : }
    1079             : 
    1080             : }
    1081             : 
    1082          25 : void XclExpCfvo::SaveXml( XclExpXmlStream& rStrm )
    1083             : {
    1084          25 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1085             : 
    1086          25 :     OString aValue;
    1087          25 :     if(mrEntry.GetType() == COLORSCALE_FORMULA)
    1088             :     {
    1089           3 :         OUString aFormula = XclXmlUtils::ToOUString( GetCompileFormulaContext(), maSrcPos,
    1090           6 :                 mrEntry.GetFormula()->Clone());
    1091           3 :         aValue = OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8 );
    1092             :     }
    1093             :     else
    1094             :     {
    1095          22 :         aValue = OString::number( mrEntry.GetValue() );
    1096             :     }
    1097             : 
    1098             :     rWorksheet->startElement( XML_cfvo,
    1099             :             XML_type, getColorScaleType(mrEntry, mbFirst).getStr(),
    1100             :             XML_val, aValue.getStr(),
    1101          25 :             FSEND );
    1102             : 
    1103          25 :     rWorksheet->endElement( XML_cfvo );
    1104          25 : }
    1105             : 
    1106          20 : XclExpColScaleCol::XclExpColScaleCol( const XclExpRoot& rRoot, const Color& rColor ):
    1107             :     XclExpRecord(),
    1108             :     XclExpRoot( rRoot ),
    1109          20 :     mrColor( rColor )
    1110             : {
    1111          20 : }
    1112             : 
    1113          40 : XclExpColScaleCol::~XclExpColScaleCol()
    1114             : {
    1115          40 : }
    1116             : 
    1117          20 : void XclExpColScaleCol::SaveXml( XclExpXmlStream& rStrm )
    1118             : {
    1119          20 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1120             : 
    1121             :     rWorksheet->startElement( XML_color,
    1122             :             XML_rgb, XclXmlUtils::ToOString( mrColor ).getStr(),
    1123          20 :             FSEND );
    1124             : 
    1125          20 :     rWorksheet->endElement( XML_color );
    1126          20 : }
    1127             : 
    1128             : namespace {
    1129             : 
    1130          80 : OString createHexStringFromDigit(sal_uInt8 nDigit)
    1131             : {
    1132          80 :     OString aString = OString::number( nDigit, 16 );
    1133          80 :     if(aString.getLength() == 1)
    1134           4 :         aString = aString + OString::number(0);
    1135          80 :     return aString;
    1136             : }
    1137             : 
    1138           5 : OString createGuidStringFromInt(sal_uInt8 nGuid[16])
    1139             : {
    1140           5 :     OStringBuffer aBuffer;
    1141           5 :     aBuffer.append('{');
    1142          85 :     for(size_t i = 0; i < 16; ++i)
    1143             :     {
    1144          80 :         aBuffer.append(createHexStringFromDigit(nGuid[i]));
    1145          80 :         if(i == 3|| i == 5 || i == 7 || i == 9 )
    1146          20 :             aBuffer.append('-');
    1147             :     }
    1148           5 :     aBuffer.append('}');
    1149          10 :     OString aString = aBuffer.makeStringAndClear();
    1150          10 :     return aString.toAsciiUpperCase();
    1151             : }
    1152             : 
    1153           5 : OString generateGUIDString()
    1154             : {
    1155             :     sal_uInt8 nGuid[16];
    1156           5 :     rtl_createUuid(nGuid, NULL, true);
    1157           5 :     return createGuidStringFromInt(nGuid);
    1158             : }
    1159             : 
    1160             : }
    1161             : 
    1162          21 : XclExpCondfmt::XclExpCondfmt( const XclExpRoot& rRoot, const ScConditionalFormat& rCondFormat, XclExtLstRef xExtLst, sal_Int32& rIndex ) :
    1163             :     XclExpRecord( EXC_ID_CONDFMT ),
    1164          21 :     XclExpRoot( rRoot )
    1165             : {
    1166          21 :     const ScRangeList& aScRanges = rCondFormat.GetRange();
    1167          21 :     GetAddressConverter().ConvertRangeList( maXclRanges, aScRanges, true );
    1168          21 :     if( !maXclRanges.empty() )
    1169             :     {
    1170          21 :         std::vector<XclExpExtCondFormatData> aExtEntries;
    1171          42 :         for( size_t nIndex = 0, nCount = rCondFormat.size(); nIndex < nCount; ++nIndex )
    1172          21 :             if( const ScFormatEntry* pFormatEntry = rCondFormat.GetEntry( nIndex ) )
    1173             :             {
    1174          21 :                 if(pFormatEntry->GetType() == condformat::CONDITION)
    1175          10 :                     maCFList.AppendNewRecord( new XclExpCF( GetRoot(), static_cast<const ScCondFormatEntry&>(*pFormatEntry), ++rIndex ) );
    1176          11 :                 else if(pFormatEntry->GetType() == condformat::COLORSCALE)
    1177           6 :                     maCFList.AppendNewRecord( new XclExpColorScale( GetRoot(), static_cast<const ScColorScaleFormat&>(*pFormatEntry), ++rIndex ) );
    1178           5 :                 else if(pFormatEntry->GetType() == condformat::DATABAR)
    1179             :                 {
    1180           5 :                     const ScDataBarFormat& rFormat = static_cast<const ScDataBarFormat&>(*pFormatEntry);
    1181           5 :                     XclExpExtCondFormatData aExtEntry;
    1182           5 :                     aExtEntry.nPriority = -1;
    1183           5 :                     aExtEntry.aGUID = generateGUIDString();
    1184           5 :                     aExtEntry.pEntry = &rFormat;
    1185           5 :                     aExtEntries.push_back(aExtEntry);
    1186             : 
    1187           5 :                     maCFList.AppendNewRecord( new XclExpDataBar( GetRoot(), rFormat, ++rIndex, aExtEntry.aGUID));
    1188             :                 }
    1189           0 :                 else if(pFormatEntry->GetType() == condformat::ICONSET)
    1190             :                 {
    1191             :                     // don't export iconSet entries that are not in OOXML
    1192           0 :                     const ScIconSetFormat& rIconSet = static_cast<const ScIconSetFormat&>(*pFormatEntry);
    1193           0 :                     bool bNeedsExt = false;
    1194           0 :                     switch (rIconSet.GetIconSetData()->eIconSetType)
    1195             :                     {
    1196             :                         case IconSet_3Smilies:
    1197             :                         case IconSet_3ColorSmilies:
    1198             :                         case IconSet_3Stars:
    1199             :                         case IconSet_3Triangles:
    1200             :                         case IconSet_5Boxes:
    1201             :                         {
    1202           0 :                             bNeedsExt = true;
    1203             :                         }
    1204           0 :                         break;
    1205             :                         default:
    1206           0 :                             break;
    1207             :                     }
    1208             : 
    1209           0 :                     bNeedsExt |= rIconSet.GetIconSetData()->mbCustom;
    1210             : 
    1211           0 :                     if (bNeedsExt)
    1212             :                     {
    1213           0 :                         XclExpExtCondFormatData aExtEntry;
    1214           0 :                         aExtEntry.nPriority = ++rIndex;
    1215           0 :                         aExtEntry.aGUID = generateGUIDString();
    1216           0 :                         aExtEntry.pEntry = &rIconSet;
    1217           0 :                         aExtEntries.push_back(aExtEntry);
    1218             :                     }
    1219             :                     else
    1220           0 :                         maCFList.AppendNewRecord( new XclExpIconSet( GetRoot(), rIconSet, ++rIndex ) );
    1221             :                 }
    1222           0 :                 else if(pFormatEntry->GetType() == condformat::DATE)
    1223           0 :                     maCFList.AppendNewRecord( new XclExpDateFormat( GetRoot(), static_cast<const ScCondDateFormatEntry&>(*pFormatEntry), ++rIndex ) );
    1224             :             }
    1225          21 :         aScRanges.Format( msSeqRef, SCA_VALID, NULL, formula::FormulaGrammar::CONV_XL_A1 );
    1226             : 
    1227          21 :         if(!aExtEntries.empty() && xExtLst.get())
    1228             :         {
    1229           5 :             XclExpExtRef pParent = xExtLst->GetItem( XclExpExtDataBarType );
    1230           5 :             if( !pParent.get() )
    1231             :             {
    1232           1 :                 xExtLst->AddRecord( XclExpExtRef(new XclExpExtCondFormat( *xExtLst.get() )) );
    1233           1 :                 pParent = xExtLst->GetItem( XclExpExtDataBarType );
    1234             :             }
    1235          10 :             static_cast<XclExpExtCondFormat*>(xExtLst->GetItem( XclExpExtDataBarType ).get())->AddRecord(
    1236          15 :                     XclExpExtConditionalFormattingRef(new XclExpExtConditionalFormatting( *pParent, aExtEntries, aScRanges)));
    1237          21 :         }
    1238             :     }
    1239          21 : }
    1240             : 
    1241          42 : XclExpCondfmt::~XclExpCondfmt()
    1242             : {
    1243          42 : }
    1244             : 
    1245          42 : bool XclExpCondfmt::IsValid() const
    1246             : {
    1247          42 :     return !maCFList.IsEmpty() && !maXclRanges.empty();
    1248             : }
    1249             : 
    1250           0 : void XclExpCondfmt::Save( XclExpStream& rStrm )
    1251             : {
    1252           0 :     if( IsValid() )
    1253             :     {
    1254           0 :         XclExpRecord::Save( rStrm );
    1255           0 :         maCFList.Save( rStrm );
    1256             :     }
    1257           0 : }
    1258             : 
    1259           0 : void XclExpCondfmt::WriteBody( XclExpStream& rStrm )
    1260             : {
    1261             :     OSL_ENSURE( !maCFList.IsEmpty(), "XclExpCondfmt::WriteBody - no CF records to write" );
    1262             :     OSL_ENSURE( !maXclRanges.empty(), "XclExpCondfmt::WriteBody - no cell ranges found" );
    1263             : 
    1264           0 :     rStrm   << static_cast< sal_uInt16 >( maCFList.GetSize() )
    1265           0 :             << sal_uInt16( 1 )
    1266           0 :             << maXclRanges.GetEnclosingRange()
    1267           0 :             << maXclRanges;
    1268           0 : }
    1269             : 
    1270          21 : void XclExpCondfmt::SaveXml( XclExpXmlStream& rStrm )
    1271             : {
    1272          21 :     if( !IsValid() )
    1273          21 :         return;
    1274             : 
    1275          21 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1276             :     rWorksheet->startElement( XML_conditionalFormatting,
    1277             :             XML_sqref, XclXmlUtils::ToOString( msSeqRef ).getStr(),
    1278             :             // OOXTODO: XML_pivot,
    1279          21 :             FSEND );
    1280             : 
    1281          21 :     maCFList.SaveXml( rStrm );
    1282             : 
    1283          21 :     rWorksheet->endElement( XML_conditionalFormatting );
    1284             : }
    1285             : 
    1286           6 : XclExpColorScale::XclExpColorScale( const XclExpRoot& rRoot, const ScColorScaleFormat& rFormat, sal_Int32 nPriority ):
    1287             :     XclExpRecord(),
    1288             :     XclExpRoot( rRoot ),
    1289           6 :     mnPriority( nPriority )
    1290             : {
    1291           6 :     const ScRange* pRange = rFormat.GetRange().front();
    1292           6 :     ScAddress aAddr = pRange->aStart;
    1293          63 :     for(ScColorScaleFormat::const_iterator itr = rFormat.begin();
    1294          42 :             itr != rFormat.end(); ++itr)
    1295             :     {
    1296             :         // exact position is not important, we allow only absolute refs
    1297             : 
    1298          15 :         XclExpCfvoList::RecordRefType xCfvo( new XclExpCfvo( GetRoot(), *itr, aAddr ) );
    1299          15 :         maCfvoList.AppendRecord( xCfvo );
    1300          30 :         XclExpColScaleColList::RecordRefType xClo( new XclExpColScaleCol( GetRoot(), itr->GetColor() ) );
    1301          15 :         maColList.AppendRecord( xClo );
    1302          15 :     }
    1303           6 : }
    1304             : 
    1305           6 : void XclExpColorScale::SaveXml( XclExpXmlStream& rStrm )
    1306             : {
    1307           6 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1308             : 
    1309             :     rWorksheet->startElement( XML_cfRule,
    1310             :             XML_type, "colorScale",
    1311             :             XML_priority, OString::number( mnPriority + 1 ).getStr(),
    1312           6 :             FSEND );
    1313             : 
    1314           6 :     rWorksheet->startElement( XML_colorScale, FSEND );
    1315             : 
    1316           6 :     maCfvoList.SaveXml(rStrm);
    1317           6 :     maColList.SaveXml(rStrm);
    1318             : 
    1319           6 :     rWorksheet->endElement( XML_colorScale );
    1320             : 
    1321           6 :     rWorksheet->endElement( XML_cfRule );
    1322           6 : }
    1323             : 
    1324           5 : XclExpDataBar::XclExpDataBar( const XclExpRoot& rRoot, const ScDataBarFormat& rFormat, sal_Int32 nPriority, const OString& rGUID):
    1325             :     XclExpRecord(),
    1326             :     XclExpRoot( rRoot ),
    1327             :     mrFormat( rFormat ),
    1328             :     mnPriority( nPriority ),
    1329           5 :     maGUID(rGUID)
    1330             : {
    1331           5 :     const ScRange* pRange = rFormat.GetRange().front();
    1332           5 :     ScAddress aAddr = pRange->aStart;
    1333             :     // exact position is not important, we allow only absolute refs
    1334           5 :     mpCfvoLowerLimit.reset( new XclExpCfvo( GetRoot(), *mrFormat.GetDataBarData()->mpLowerLimit.get(), aAddr, true ) );
    1335           5 :     mpCfvoUpperLimit.reset( new XclExpCfvo( GetRoot(), *mrFormat.GetDataBarData()->mpUpperLimit.get(), aAddr, false ) );
    1336             : 
    1337           5 :     mpCol.reset( new XclExpColScaleCol( GetRoot(), mrFormat.GetDataBarData()->maPositiveColor ) );
    1338           5 : }
    1339             : 
    1340           5 : void XclExpDataBar::SaveXml( XclExpXmlStream& rStrm )
    1341             : {
    1342           5 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1343             : 
    1344             :     rWorksheet->startElement( XML_cfRule,
    1345             :             XML_type, "dataBar",
    1346             :             XML_priority, OString::number( mnPriority + 1 ).getStr(),
    1347           5 :             FSEND );
    1348             : 
    1349             :     rWorksheet->startElement( XML_dataBar,
    1350           5 :                                 XML_showValue, OString::number(int(!mrFormat.GetDataBarData()->mbOnlyBar)),
    1351           5 :                                 XML_minLength, OString::number(sal_uInt32(mrFormat.GetDataBarData()->mnMinLength)),
    1352           5 :                                 XML_maxLength, OString::number(sal_uInt32(mrFormat.GetDataBarData()->mnMaxLength)),
    1353          15 :             FSEND );
    1354             : 
    1355           5 :     mpCfvoLowerLimit->SaveXml(rStrm);
    1356           5 :     mpCfvoUpperLimit->SaveXml(rStrm);
    1357           5 :     mpCol->SaveXml(rStrm);
    1358             : 
    1359           5 :     rWorksheet->endElement( XML_dataBar );
    1360             : 
    1361             :     // extLst entries for Excel 2010 and 2013
    1362           5 :     rWorksheet->startElement( XML_extLst, FSEND );
    1363             :     rWorksheet->startElement( XML_ext,
    1364             :                                 FSNS( XML_xmlns, XML_x14 ), "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main",
    1365             :                                 XML_uri, "{B025F937-C7B1-47D3-B67F-A62EFF666E3E}",
    1366           5 :                                 FSEND );
    1367             : 
    1368           5 :     rWorksheet->startElementNS( XML_x14, XML_id, FSEND );
    1369           5 :     rWorksheet->write( maGUID.getStr() );
    1370           5 :     rWorksheet->endElementNS( XML_x14, XML_id );
    1371             : 
    1372           5 :     rWorksheet->endElement( XML_ext );
    1373           5 :     rWorksheet->endElement( XML_extLst );
    1374             : 
    1375           5 :     rWorksheet->endElement( XML_cfRule );
    1376           5 : }
    1377             : 
    1378           0 : XclExpIconSet::XclExpIconSet( const XclExpRoot& rRoot, const ScIconSetFormat& rFormat, sal_Int32 nPriority ):
    1379             :     XclExpRecord(),
    1380             :     XclExpRoot( rRoot ),
    1381             :     mrFormat( rFormat ),
    1382           0 :     mnPriority( nPriority )
    1383             : {
    1384           0 :     const ScRange* pRange = rFormat.GetRange().front();
    1385           0 :     ScAddress aAddr = pRange->aStart;
    1386           0 :     for(ScIconSetFormat::const_iterator itr = rFormat.begin();
    1387           0 :             itr != rFormat.end(); ++itr)
    1388             :     {
    1389             :         // exact position is not important, we allow only absolute refs
    1390             : 
    1391           0 :         XclExpCfvoList::RecordRefType xCfvo( new XclExpCfvo( GetRoot(), *itr, aAddr ) );
    1392           0 :         maCfvoList.AppendRecord( xCfvo );
    1393           0 :     }
    1394           0 : }
    1395             : 
    1396             : namespace {
    1397             : 
    1398           0 : const char* getIconSetName( ScIconSetType eType )
    1399             : {
    1400           0 :     ScIconSetMap* pMap = ScIconSetFormat::getIconSetMap();
    1401           0 :     for(; pMap->pName; ++pMap)
    1402             :     {
    1403           0 :         if(pMap->eType == eType)
    1404           0 :             return pMap->pName;
    1405             :     }
    1406             : 
    1407           0 :     return "";
    1408             : }
    1409             : 
    1410             : }
    1411             : 
    1412           0 : void XclExpIconSet::SaveXml( XclExpXmlStream& rStrm )
    1413             : {
    1414           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1415             : 
    1416             :     rWorksheet->startElement( XML_cfRule,
    1417             :             XML_type, "iconSet",
    1418             :             XML_priority, OString::number( mnPriority + 1 ).getStr(),
    1419           0 :             FSEND );
    1420             : 
    1421           0 :     const char* pIconSetName = getIconSetName(mrFormat.GetIconSetData()->eIconSetType);
    1422             :     rWorksheet->startElement( XML_iconSet,
    1423             :             XML_iconSet, pIconSetName,
    1424           0 :             XML_showValue, mrFormat.GetIconSetData()->mbShowValue ? NULL : "0",
    1425           0 :             XML_reverse, mrFormat.GetIconSetData()->mbReverse ? "1" : NULL,
    1426           0 :             FSEND );
    1427             : 
    1428           0 :     maCfvoList.SaveXml( rStrm );
    1429             : 
    1430           0 :     rWorksheet->endElement( XML_iconSet );
    1431           0 :     rWorksheet->endElement( XML_cfRule );
    1432           0 : }
    1433             : 
    1434         129 : XclExpCondFormatBuffer::XclExpCondFormatBuffer( const XclExpRoot& rRoot, XclExtLstRef xExtLst ) :
    1435         129 :     XclExpRoot( rRoot )
    1436             : {
    1437         129 :     if( const ScConditionalFormatList* pCondFmtList = GetDoc().GetCondFormList(GetCurrScTab()) )
    1438             :     {
    1439         129 :         sal_Int32 nIndex = 0;
    1440         450 :         for( ScConditionalFormatList::const_iterator itr = pCondFmtList->begin();
    1441         300 :                         itr != pCondFmtList->end(); ++itr)
    1442             :         {
    1443          21 :             XclExpCondfmtList::RecordRefType xCondfmtRec( new XclExpCondfmt( GetRoot(), *itr, xExtLst, nIndex ));
    1444          21 :             if( xCondfmtRec->IsValid() )
    1445          21 :                 maCondfmtList.AppendRecord( xCondfmtRec );
    1446          21 :         }
    1447             :     }
    1448         129 : }
    1449             : 
    1450          29 : void XclExpCondFormatBuffer::Save( XclExpStream& rStrm )
    1451             : {
    1452          29 :     maCondfmtList.Save( rStrm );
    1453          29 : }
    1454             : 
    1455         100 : void XclExpCondFormatBuffer::SaveXml( XclExpXmlStream& rStrm )
    1456             : {
    1457         100 :     maCondfmtList.SaveXml( rStrm );
    1458         100 : }
    1459             : 
    1460             : // Validation =================================================================
    1461             : 
    1462             : namespace {
    1463             : 
    1464             : /** Writes a formula for the DV record. */
    1465           0 : void lclWriteDvFormula( XclExpStream& rStrm, const XclTokenArray* pXclTokArr )
    1466             : {
    1467           0 :     sal_uInt16 nFmlaSize = pXclTokArr ? pXclTokArr->GetSize() : 0;
    1468           0 :     rStrm << nFmlaSize << sal_uInt16( 0 );
    1469           0 :     if( pXclTokArr )
    1470           0 :         pXclTokArr->WriteArray( rStrm );
    1471           0 : }
    1472             : 
    1473             : /** Writes a formula for the DV record, based on a single string. */
    1474           0 : void lclWriteDvFormula( XclExpStream& rStrm, const XclExpString& rString )
    1475             : {
    1476             :     // fake a formula with a single tStr token
    1477           0 :     rStrm   << static_cast< sal_uInt16 >( rString.GetSize() + 1 )
    1478           0 :             << sal_uInt16( 0 )
    1479           0 :             << EXC_TOKID_STR
    1480           0 :             << rString;
    1481           0 : }
    1482             : 
    1483           0 : const char* lcl_GetValidationType( sal_uInt32 nFlags )
    1484             : {
    1485           0 :     switch( nFlags & EXC_DV_MODE_MASK )
    1486             :     {
    1487           0 :         case EXC_DV_MODE_ANY:       return "none";
    1488           0 :         case EXC_DV_MODE_WHOLE:     return "whole";
    1489           0 :         case EXC_DV_MODE_DECIMAL:   return "decimal";
    1490           0 :         case EXC_DV_MODE_LIST:      return "list";
    1491           0 :         case EXC_DV_MODE_DATE:      return "date";
    1492           0 :         case EXC_DV_MODE_TIME:      return "time";
    1493           0 :         case EXC_DV_MODE_TEXTLEN:   return "textLength";
    1494           0 :         case EXC_DV_MODE_CUSTOM:    return "custom";
    1495             :     }
    1496           0 :     return NULL;
    1497             : }
    1498             : 
    1499           0 : const char* lcl_GetOperatorType( sal_uInt32 nFlags )
    1500             : {
    1501           0 :     switch( nFlags & EXC_DV_COND_MASK )
    1502             :     {
    1503           0 :         case EXC_DV_COND_BETWEEN:       return "between";
    1504           0 :         case EXC_DV_COND_NOTBETWEEN:    return "notBetween";
    1505           0 :         case EXC_DV_COND_EQUAL:         return "equal";
    1506           0 :         case EXC_DV_COND_NOTEQUAL:      return "notEqual";
    1507           0 :         case EXC_DV_COND_GREATER:       return "greaterThan";
    1508           0 :         case EXC_DV_COND_LESS:          return "lessThan";
    1509           0 :         case EXC_DV_COND_EQGREATER:     return "greaterThanOrEqual";
    1510           0 :         case EXC_DV_COND_EQLESS:        return "lessThanOrEqual";
    1511             :     }
    1512           0 :     return NULL;
    1513             : }
    1514             : 
    1515             : } // namespace
    1516             : 
    1517           0 : XclExpDV::XclExpDV( const XclExpRoot& rRoot, sal_uLong nScHandle ) :
    1518             :     XclExpRecord( EXC_ID_DV ),
    1519             :     XclExpRoot( rRoot ),
    1520             :     mnFlags( 0 ),
    1521           0 :     mnScHandle( nScHandle )
    1522             : {
    1523           0 :     if( const ScValidationData* pValData = GetDoc().GetValidationEntry( mnScHandle ) )
    1524             :     {
    1525             :         // prompt box - empty string represented by single NUL character
    1526           0 :         OUString aTitle, aText;
    1527           0 :         bool bShowPrompt = pValData->GetInput( aTitle, aText );
    1528           0 :         if( !aTitle.isEmpty() )
    1529           0 :             maPromptTitle.Assign( aTitle );
    1530             :         else
    1531           0 :             maPromptTitle.Assign( '\0' );
    1532           0 :         if( !aText.isEmpty() )
    1533           0 :             maPromptText.Assign( aText );
    1534             :         else
    1535           0 :             maPromptText.Assign( '\0' );
    1536             : 
    1537             :         // error box - empty string represented by single NUL character
    1538             :         ScValidErrorStyle eScErrorStyle;
    1539           0 :         bool bShowError = pValData->GetErrMsg( aTitle, aText, eScErrorStyle );
    1540           0 :         if( !aTitle.isEmpty() )
    1541           0 :             maErrorTitle.Assign( aTitle );
    1542             :         else
    1543           0 :             maErrorTitle.Assign( '\0' );
    1544           0 :         if( !aText.isEmpty() )
    1545           0 :             maErrorText.Assign( aText );
    1546             :         else
    1547           0 :             maErrorText.Assign( '\0' );
    1548             : 
    1549             :         // flags
    1550           0 :         switch( pValData->GetDataMode() )
    1551             :         {
    1552           0 :             case SC_VALID_ANY:      mnFlags |= EXC_DV_MODE_ANY;         break;
    1553           0 :             case SC_VALID_WHOLE:    mnFlags |= EXC_DV_MODE_WHOLE;       break;
    1554           0 :             case SC_VALID_DECIMAL:  mnFlags |= EXC_DV_MODE_DECIMAL;     break;
    1555           0 :             case SC_VALID_LIST:     mnFlags |= EXC_DV_MODE_LIST;        break;
    1556           0 :             case SC_VALID_DATE:     mnFlags |= EXC_DV_MODE_DATE;        break;
    1557           0 :             case SC_VALID_TIME:     mnFlags |= EXC_DV_MODE_TIME;        break;
    1558           0 :             case SC_VALID_TEXTLEN:  mnFlags |= EXC_DV_MODE_TEXTLEN;     break;
    1559           0 :             case SC_VALID_CUSTOM:   mnFlags |= EXC_DV_MODE_CUSTOM;      break;
    1560             :             default:                OSL_FAIL( "XclExpDV::XclExpDV - unknown mode" );
    1561             :         }
    1562             : 
    1563           0 :         switch( pValData->GetOperation() )
    1564             :         {
    1565             :             case SC_COND_NONE:
    1566           0 :             case SC_COND_EQUAL:         mnFlags |= EXC_DV_COND_EQUAL;       break;
    1567           0 :             case SC_COND_LESS:          mnFlags |= EXC_DV_COND_LESS;        break;
    1568           0 :             case SC_COND_GREATER:       mnFlags |= EXC_DV_COND_GREATER;     break;
    1569           0 :             case SC_COND_EQLESS:        mnFlags |= EXC_DV_COND_EQLESS;      break;
    1570           0 :             case SC_COND_EQGREATER:     mnFlags |= EXC_DV_COND_EQGREATER;   break;
    1571           0 :             case SC_COND_NOTEQUAL:      mnFlags |= EXC_DV_COND_NOTEQUAL;    break;
    1572           0 :             case SC_COND_BETWEEN:       mnFlags |= EXC_DV_COND_BETWEEN;     break;
    1573           0 :             case SC_COND_NOTBETWEEN:    mnFlags |= EXC_DV_COND_NOTBETWEEN;  break;
    1574             :             default:                    OSL_FAIL( "XclExpDV::XclExpDV - unknown condition" );
    1575             :         }
    1576           0 :         switch( eScErrorStyle )
    1577             :         {
    1578           0 :             case SC_VALERR_STOP:        mnFlags |= EXC_DV_ERROR_STOP;       break;
    1579           0 :             case SC_VALERR_WARNING:     mnFlags |= EXC_DV_ERROR_WARNING;    break;
    1580           0 :             case SC_VALERR_INFO:        mnFlags |= EXC_DV_ERROR_INFO;       break;
    1581             :             case SC_VALERR_MACRO:
    1582             :                 // set INFO for validity with macro call, delete title
    1583           0 :                 mnFlags |= EXC_DV_ERROR_INFO;
    1584           0 :                 maErrorTitle.Assign( '\0' );    // contains macro name
    1585           0 :             break;
    1586             :             default:                    OSL_FAIL( "XclExpDV::XclExpDV - unknown error style" );
    1587             :         }
    1588           0 :         ::set_flag( mnFlags, EXC_DV_IGNOREBLANK, pValData->IsIgnoreBlank() );
    1589           0 :         ::set_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN, pValData->GetListType() == css::sheet::TableValidationVisibility::INVISIBLE );
    1590           0 :         ::set_flag( mnFlags, EXC_DV_SHOWPROMPT, bShowPrompt );
    1591           0 :         ::set_flag( mnFlags, EXC_DV_SHOWERROR, bShowError );
    1592             : 
    1593             :         // formulas
    1594           0 :         XclExpFormulaCompiler& rFmlaComp = GetFormulaCompiler();
    1595           0 :         boost::scoped_ptr< ScTokenArray > xScTokArr;
    1596             : 
    1597             :         // first formula
    1598           0 :         xScTokArr.reset( pValData->CreateTokenArry( 0 ) );
    1599           0 :         if( xScTokArr.get() )
    1600             :         {
    1601           0 :             if( pValData->GetDataMode() == SC_VALID_LIST )
    1602             :             {
    1603           0 :                 OUString aString;
    1604           0 :                 if( XclTokenArrayHelper::GetStringList( aString, *xScTokArr, '\n' ) )
    1605             :                 {
    1606           0 :                     OUStringBuffer sFormulaBuf;
    1607           0 :                     sFormulaBuf.append( '"' );
    1608             :                     /*  Formula is a list of string tokens -> build the Excel string.
    1609             :                         Data validity is BIFF8 only (important for the XclExpString object).
    1610             :                         Excel uses the NUL character as string list separator. */
    1611           0 :                     mxString1.reset( new XclExpString( EXC_STR_8BITLENGTH ) );
    1612           0 :                     sal_Int32 nTokenCnt = comphelper::string::getTokenCount(aString, '\n');
    1613           0 :                     sal_Int32 nStringIx = 0;
    1614           0 :                     for( sal_Int32 nToken = 0; nToken < nTokenCnt; ++nToken )
    1615             :                     {
    1616           0 :                         OUString aToken( aString.getToken( 0, '\n', nStringIx ) );
    1617           0 :                         if( nToken > 0 )
    1618             :                         {
    1619           0 :                             mxString1->Append(OUString(static_cast<sal_Unicode>('\0')));
    1620           0 :                             sFormulaBuf.append( ',' );
    1621             :                         }
    1622           0 :                         mxString1->Append( aToken );
    1623           0 :                         sFormulaBuf.append( aToken );
    1624           0 :                     }
    1625           0 :                     ::set_flag( mnFlags, EXC_DV_STRINGLIST );
    1626             : 
    1627           0 :                     sFormulaBuf.append( '"' );
    1628           0 :                     msFormula1 = sFormulaBuf.makeStringAndClear();
    1629             :                 }
    1630             :                 else
    1631             :                 {
    1632             :                     /*  All other formulas in validation are stored like conditional
    1633             :                         formatting formulas (with tRefN/tAreaN tokens as value or
    1634             :                         array class). But NOT the cell references and defined names
    1635             :                         in list validation - they are stored as reference class
    1636             :                         tokens... Example:
    1637             :                         1) Cell must be equal to A1 -> formula is =A1 -> writes tRefNV token
    1638             :                         2) List is taken from A1    -> formula is =A1 -> writes tRefNR token
    1639             :                         Formula compiler supports this by offering two different functions
    1640             :                         CreateDataValFormula() and CreateListValFormula(). */
    1641           0 :                     if(GetOutput() == EXC_OUTPUT_BINARY)
    1642           0 :                         mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_LISTVAL, *xScTokArr );
    1643             :                     else
    1644           0 :                         msFormula1 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
    1645           0 :                             xScTokArr.get());
    1646           0 :                 }
    1647             :             }
    1648             :             else
    1649             :             {
    1650             :                 // no list validation -> convert the formula
    1651           0 :                 if(GetOutput() == EXC_OUTPUT_BINARY)
    1652           0 :                     mxTokArr1 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
    1653             :                 else
    1654           0 :                     msFormula1 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
    1655           0 :                             xScTokArr.get());
    1656             :             }
    1657             :         }
    1658             : 
    1659             :         // second formula
    1660           0 :         xScTokArr.reset( pValData->CreateTokenArry( 1 ) );
    1661           0 :         if( xScTokArr.get() )
    1662             :         {
    1663           0 :             if(GetOutput() == EXC_OUTPUT_BINARY)
    1664           0 :                 mxTokArr2 = rFmlaComp.CreateFormula( EXC_FMLATYPE_DATAVAL, *xScTokArr );
    1665             :             else
    1666           0 :                 msFormula2 = XclXmlUtils::ToOUString( GetCompileFormulaContext(), pValData->GetSrcPos(),
    1667           0 :                         xScTokArr.get());
    1668           0 :         }
    1669             :     }
    1670             :     else
    1671             :     {
    1672             :         OSL_FAIL( "XclExpDV::XclExpDV - missing core data" );
    1673           0 :         mnScHandle = ULONG_MAX;
    1674             :     }
    1675           0 : }
    1676             : 
    1677           0 : XclExpDV::~XclExpDV()
    1678             : {
    1679           0 : }
    1680             : 
    1681           0 : void XclExpDV::InsertCellRange( const ScRange& rRange )
    1682             : {
    1683           0 :     maScRanges.Join( rRange );
    1684           0 : }
    1685             : 
    1686           0 : bool XclExpDV::Finalize()
    1687             : {
    1688           0 :     GetAddressConverter().ConvertRangeList( maXclRanges, maScRanges, true );
    1689           0 :     return (mnScHandle != ULONG_MAX) && !maXclRanges.empty();
    1690             : }
    1691             : 
    1692           0 : void XclExpDV::WriteBody( XclExpStream& rStrm )
    1693             : {
    1694             :     // flags and strings
    1695           0 :     rStrm << mnFlags << maPromptTitle << maErrorTitle << maPromptText << maErrorText;
    1696             :     // condition formulas
    1697           0 :     if( mxString1.get() )
    1698           0 :         lclWriteDvFormula( rStrm, *mxString1 );
    1699             :     else
    1700           0 :         lclWriteDvFormula( rStrm, mxTokArr1.get() );
    1701           0 :     lclWriteDvFormula( rStrm, mxTokArr2.get() );
    1702             :     // cell ranges
    1703           0 :     rStrm << maXclRanges;
    1704           0 : }
    1705             : 
    1706           0 : void XclExpDV::SaveXml( XclExpXmlStream& rStrm )
    1707             : {
    1708           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1709             :     rWorksheet->startElement( XML_dataValidation,
    1710           0 :             XML_allowBlank,         XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_IGNOREBLANK ) ),
    1711           0 :             XML_error,              XESTRING_TO_PSZ( maErrorText ),
    1712             :             // OOXTODO: XML_errorStyle,
    1713           0 :             XML_errorTitle,         XESTRING_TO_PSZ( maErrorTitle ),
    1714             :             // OOXTODO: XML_imeMode,
    1715             :             XML_operator,           lcl_GetOperatorType( mnFlags ),
    1716           0 :             XML_prompt,             XESTRING_TO_PSZ( maPromptText ),
    1717           0 :             XML_promptTitle,        XESTRING_TO_PSZ( maPromptTitle ),
    1718             :             // showDropDown should have been showNoDropDown - check oox/xlsx import for details
    1719           0 :             XML_showDropDown,       XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SUPPRESSDROPDOWN ) ),
    1720           0 :             XML_showErrorMessage,   XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWERROR ) ),
    1721           0 :             XML_showInputMessage,   XclXmlUtils::ToPsz( ::get_flag( mnFlags, EXC_DV_SHOWPROMPT ) ),
    1722             :             XML_sqref,              XclXmlUtils::ToOString( maScRanges ).getStr(),
    1723             :             XML_type,               lcl_GetValidationType( mnFlags ),
    1724           0 :             FSEND );
    1725           0 :     if( !msFormula1.isEmpty() )
    1726             :     {
    1727           0 :         rWorksheet->startElement( XML_formula1, FSEND );
    1728           0 :         rWorksheet->writeEscaped( msFormula1 );
    1729           0 :         rWorksheet->endElement( XML_formula1 );
    1730             :     }
    1731           0 :     if( !msFormula2.isEmpty() )
    1732             :     {
    1733           0 :         rWorksheet->startElement( XML_formula2, FSEND );
    1734           0 :         rWorksheet->writeEscaped( msFormula2 );
    1735           0 :         rWorksheet->endElement( XML_formula2 );
    1736             :     }
    1737           0 :     rWorksheet->endElement( XML_dataValidation );
    1738           0 : }
    1739             : 
    1740         129 : XclExpDval::XclExpDval( const XclExpRoot& rRoot ) :
    1741             :     XclExpRecord( EXC_ID_DVAL, 18 ),
    1742         129 :     XclExpRoot( rRoot )
    1743             : {
    1744         129 : }
    1745             : 
    1746         258 : XclExpDval::~XclExpDval()
    1747             : {
    1748         258 : }
    1749             : 
    1750           0 : void XclExpDval::InsertCellRange( const ScRange& rRange, sal_uLong nScHandle )
    1751             : {
    1752           0 :     if( GetBiff() == EXC_BIFF8 )
    1753             :     {
    1754           0 :         XclExpDV& rDVRec = SearchOrCreateDv( nScHandle );
    1755           0 :         rDVRec.InsertCellRange( rRange );
    1756             :     }
    1757           0 : }
    1758             : 
    1759          29 : void XclExpDval::Save( XclExpStream& rStrm )
    1760             : {
    1761             :     // check all records
    1762          29 :     size_t nPos = maDVList.GetSize();
    1763          58 :     while( nPos )
    1764             :     {
    1765           0 :         --nPos;     // backwards to keep nPos valid
    1766           0 :         XclExpDVRef xDVRec = maDVList.GetRecord( nPos );
    1767           0 :         if( !xDVRec->Finalize() )
    1768           0 :             maDVList.RemoveRecord( nPos );
    1769           0 :     }
    1770             : 
    1771             :     // write the DVAL and the DV's
    1772          29 :     if( !maDVList.IsEmpty() )
    1773             :     {
    1774           0 :         XclExpRecord::Save( rStrm );
    1775           0 :         maDVList.Save( rStrm );
    1776             :     }
    1777          29 : }
    1778             : 
    1779         100 : void XclExpDval::SaveXml( XclExpXmlStream& rStrm )
    1780             : {
    1781         100 :     if( maDVList.IsEmpty() )
    1782         200 :         return;
    1783             : 
    1784           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1785             :     rWorksheet->startElement( XML_dataValidations,
    1786             :             XML_count, OString::number(  maDVList.GetSize() ).getStr(),
    1787             :             // OOXTODO: XML_disablePrompts,
    1788             :             // OOXTODO: XML_xWindow,
    1789             :             // OOXTODO: XML_yWindow,
    1790           0 :             FSEND );
    1791           0 :     maDVList.SaveXml( rStrm );
    1792           0 :     rWorksheet->endElement( XML_dataValidations );
    1793             : }
    1794             : 
    1795           0 : XclExpDV& XclExpDval::SearchOrCreateDv( sal_uLong nScHandle )
    1796             : {
    1797             :     // test last found record
    1798           0 :     if( mxLastFoundDV.get() && (mxLastFoundDV->GetScHandle() == nScHandle) )
    1799           0 :         return *mxLastFoundDV;
    1800             : 
    1801             :     // binary search
    1802           0 :     size_t nCurrPos = 0;
    1803           0 :     if( !maDVList.IsEmpty() )
    1804             :     {
    1805           0 :         size_t nFirstPos = 0;
    1806           0 :         size_t nLastPos = maDVList.GetSize() - 1;
    1807           0 :         bool bLoop = true;
    1808           0 :         sal_uLong nCurrScHandle = ::std::numeric_limits< sal_uLong >::max();
    1809           0 :         while( (nFirstPos <= nLastPos) && bLoop )
    1810             :         {
    1811           0 :             nCurrPos = (nFirstPos + nLastPos) / 2;
    1812           0 :             mxLastFoundDV = maDVList.GetRecord( nCurrPos );
    1813           0 :             nCurrScHandle = mxLastFoundDV->GetScHandle();
    1814           0 :             if( nCurrScHandle == nScHandle )
    1815           0 :                 bLoop = false;
    1816           0 :             else if( nCurrScHandle < nScHandle )
    1817           0 :                 nFirstPos = nCurrPos + 1;
    1818           0 :             else if( nCurrPos )
    1819           0 :                 nLastPos = nCurrPos - 1;
    1820             :             else    // special case for nLastPos = -1
    1821           0 :                 bLoop = false;
    1822             :         }
    1823           0 :         if( nCurrScHandle == nScHandle )
    1824           0 :             return *mxLastFoundDV;
    1825           0 :         else if( nCurrScHandle < nScHandle )
    1826           0 :             ++nCurrPos;
    1827             :     }
    1828             : 
    1829             :     // create new DV record
    1830           0 :     mxLastFoundDV.reset( new XclExpDV( *this, nScHandle ) );
    1831           0 :     maDVList.InsertRecord( mxLastFoundDV, nCurrPos );
    1832           0 :     return *mxLastFoundDV;
    1833             : }
    1834             : 
    1835           0 : void XclExpDval::WriteBody( XclExpStream& rStrm )
    1836             : {
    1837           0 :     rStrm.WriteZeroBytes( 10 );
    1838           0 :     rStrm << EXC_DVAL_NOOBJ << static_cast< sal_uInt32 >( maDVList.GetSize() );
    1839           0 : }
    1840             : 
    1841             : // Web Queries ================================================================
    1842             : 
    1843           0 : XclExpWebQuery::XclExpWebQuery(
    1844             :         const OUString& rRangeName,
    1845             :         const OUString& rUrl,
    1846             :         const OUString& rSource,
    1847             :         sal_Int32 nRefrSecs ) :
    1848             :     maDestRange( rRangeName ),
    1849             :     maUrl( rUrl ),
    1850             :     // refresh delay time: seconds -> minutes
    1851           0 :     mnRefresh( ulimit_cast< sal_Int16 >( (nRefrSecs + 59L) / 60L ) ),
    1852           0 :     mbEntireDoc( false )
    1853             : {
    1854             :     // comma separated list of HTML table names or indexes
    1855           0 :     sal_Int32 nTokenCnt = comphelper::string::getTokenCount(rSource, ';');
    1856           0 :     OUString aNewTables;
    1857           0 :     OUString aAppendTable;
    1858           0 :     sal_Int32 nStringIx = 0;
    1859           0 :     bool bExitLoop = false;
    1860           0 :     for( sal_Int32 nToken = 0; (nToken < nTokenCnt) && !bExitLoop; ++nToken )
    1861             :     {
    1862           0 :         OUString aToken( rSource.getToken( 0, ';', nStringIx ) );
    1863           0 :         mbEntireDoc = ScfTools::IsHTMLDocName( aToken );
    1864           0 :         bExitLoop = mbEntireDoc || ScfTools::IsHTMLTablesName( aToken );
    1865           0 :         if( !bExitLoop && ScfTools::GetHTMLNameFromName( aToken, aAppendTable ) )
    1866           0 :             aNewTables = ScGlobal::addToken( aNewTables, aAppendTable, ',' );
    1867           0 :     }
    1868             : 
    1869           0 :     if( !bExitLoop )    // neither HTML_all nor HTML_tables found
    1870             :     {
    1871           0 :         if( !aNewTables.isEmpty() )
    1872           0 :             mxQryTables.reset( new XclExpString( aNewTables ) );
    1873             :         else
    1874           0 :             mbEntireDoc = true;
    1875           0 :     }
    1876           0 : }
    1877             : 
    1878           0 : XclExpWebQuery::~XclExpWebQuery()
    1879             : {
    1880           0 : }
    1881             : 
    1882           0 : void XclExpWebQuery::Save( XclExpStream& rStrm )
    1883             : {
    1884             :     OSL_ENSURE( !mbEntireDoc || !mxQryTables.get(), "XclExpWebQuery::Save - illegal mode" );
    1885             :     sal_uInt16 nFlags;
    1886             : 
    1887             :     // QSI record
    1888           0 :     rStrm.StartRecord( EXC_ID_QSI, 10 + maDestRange.GetSize() );
    1889           0 :     rStrm   << EXC_QSI_DEFAULTFLAGS
    1890           0 :             << sal_uInt16( 0x0010 )
    1891           0 :             << sal_uInt16( 0x0012 )
    1892           0 :             << sal_uInt32( 0x00000000 )
    1893           0 :             << maDestRange;
    1894           0 :     rStrm.EndRecord();
    1895             : 
    1896             :     // PARAMQRY record
    1897           0 :     nFlags = 0;
    1898           0 :     ::insert_value( nFlags, EXC_PQRYTYPE_WEBQUERY, 0, 3 );
    1899           0 :     ::set_flag( nFlags, EXC_PQRY_WEBQUERY );
    1900           0 :     ::set_flag( nFlags, EXC_PQRY_TABLES, !mbEntireDoc );
    1901           0 :     rStrm.StartRecord( EXC_ID_PQRY, 12 );
    1902           0 :     rStrm   << nFlags
    1903           0 :             << sal_uInt16( 0x0000 )
    1904           0 :             << sal_uInt16( 0x0001 );
    1905           0 :     rStrm.WriteZeroBytes( 6 );
    1906           0 :     rStrm.EndRecord();
    1907             : 
    1908             :     // WQSTRING record
    1909           0 :     rStrm.StartRecord( EXC_ID_WQSTRING, maUrl.GetSize() );
    1910           0 :     rStrm << maUrl;
    1911           0 :     rStrm.EndRecord();
    1912             : 
    1913             :     // unknown record 0x0802
    1914           0 :     rStrm.StartRecord( EXC_ID_0802, 16 + maDestRange.GetSize() );
    1915           0 :     rStrm   << EXC_ID_0802;             // repeated record id ?!?
    1916           0 :     rStrm.WriteZeroBytes( 6 );
    1917           0 :     rStrm   << sal_uInt16( 0x0003 )
    1918           0 :             << sal_uInt32( 0x00000000 )
    1919           0 :             << sal_uInt16( 0x0010 )
    1920           0 :             << maDestRange;
    1921           0 :     rStrm.EndRecord();
    1922             : 
    1923             :     // WEBQRYSETTINGS record
    1924           0 :     nFlags = mxQryTables.get() ? EXC_WQSETT_SPECTABLES : EXC_WQSETT_ALL;
    1925           0 :     rStrm.StartRecord( EXC_ID_WQSETT, 28 );
    1926           0 :     rStrm   << EXC_ID_WQSETT            // repeated record id ?!?
    1927           0 :             << sal_uInt16( 0x0000 )
    1928           0 :             << sal_uInt16( 0x0004 )
    1929           0 :             << sal_uInt16( 0x0000 )
    1930           0 :             << EXC_WQSETT_DEFAULTFLAGS
    1931           0 :             << nFlags;
    1932           0 :     rStrm.WriteZeroBytes( 10 );
    1933           0 :     rStrm   << mnRefresh                // refresh delay in minutes
    1934           0 :             << EXC_WQSETT_FORMATFULL
    1935           0 :             << sal_uInt16( 0x0000 );
    1936           0 :     rStrm.EndRecord();
    1937             : 
    1938             :     // WEBQRYTABLES record
    1939           0 :     if( mxQryTables.get() )
    1940             :     {
    1941           0 :         rStrm.StartRecord( EXC_ID_WQTABLES, 4 + mxQryTables->GetSize() );
    1942           0 :         rStrm   << EXC_ID_WQTABLES          // repeated record id ?!?
    1943           0 :                 << sal_uInt16( 0x0000 )
    1944           0 :                 << *mxQryTables;            // comma separated list of source tables
    1945           0 :         rStrm.EndRecord();
    1946             :     }
    1947           0 : }
    1948             : 
    1949          29 : XclExpWebQueryBuffer::XclExpWebQueryBuffer( const XclExpRoot& rRoot )
    1950             : {
    1951          29 :     SCTAB nScTab = rRoot.GetCurrScTab();
    1952          29 :     SfxObjectShell* pShell = rRoot.GetDocShell();
    1953          29 :     if( !pShell ) return;
    1954          29 :     ScfPropertySet aModelProp( pShell->GetModel() );
    1955          29 :     if( !aModelProp.Is() ) return;
    1956             : 
    1957          58 :     Reference< XAreaLinks > xAreaLinks;
    1958          29 :     aModelProp.GetProperty( xAreaLinks, SC_UNO_AREALINKS );
    1959          29 :     if( !xAreaLinks.is() ) return;
    1960             : 
    1961          29 :     for( sal_Int32 nIndex = 0, nCount = xAreaLinks->getCount(); nIndex < nCount; ++nIndex )
    1962             :     {
    1963           0 :         Reference< XAreaLink > xAreaLink( xAreaLinks->getByIndex( nIndex ), UNO_QUERY );
    1964           0 :         if( xAreaLink.is() )
    1965             :         {
    1966           0 :             CellRangeAddress aDestRange( xAreaLink->getDestArea() );
    1967           0 :             if( static_cast< SCTAB >( aDestRange.Sheet ) == nScTab )
    1968             :             {
    1969           0 :                 ScfPropertySet aLinkProp( xAreaLink );
    1970           0 :                 OUString aFilter;
    1971           0 :                 if( aLinkProp.GetProperty( aFilter, SC_UNONAME_FILTER ) &&
    1972           0 :                     (aFilter == EXC_WEBQRY_FILTER) )
    1973             :                 {
    1974             :                     // get properties
    1975           0 :                     OUString /*aFilterOpt,*/ aUrl;
    1976           0 :                     sal_Int32 nRefresh = 0;
    1977             : 
    1978             : //                  aLinkProp.GetProperty( aFilterOpt, SC_UNONAME_FILTOPT );
    1979           0 :                     aLinkProp.GetProperty( aUrl, SC_UNONAME_LINKURL );
    1980           0 :                     aLinkProp.GetProperty( nRefresh, SC_UNONAME_REFDELAY );
    1981             : 
    1982           0 :                     OUString aAbsDoc( ScGlobal::GetAbsDocName( aUrl, pShell ) );
    1983           0 :                     INetURLObject aUrlObj( aAbsDoc );
    1984           0 :                     OUString aWebQueryUrl( aUrlObj.getFSysPath( INetURLObject::FSYS_DOS ) );
    1985           0 :                     if( aWebQueryUrl.isEmpty() )
    1986           0 :                         aWebQueryUrl = aAbsDoc;
    1987             : 
    1988             :                     // find range or create a new range
    1989           0 :                     OUString aRangeName;
    1990           0 :                     ScRange aScDestRange;
    1991           0 :                     ScUnoConversion::FillScRange( aScDestRange, aDestRange );
    1992           0 :                     if( const ScRangeData* pRangeData = rRoot.GetNamedRanges().findByRange( aScDestRange ) )
    1993             :                     {
    1994           0 :                         aRangeName = pRangeData->GetName();
    1995             :                     }
    1996             :                     else
    1997             :                     {
    1998           0 :                         XclExpFormulaCompiler& rFmlaComp = rRoot.GetFormulaCompiler();
    1999           0 :                         XclExpNameManager& rNameMgr = rRoot.GetNameManager();
    2000             : 
    2001             :                         // create a new unique defined name containing the range
    2002           0 :                         XclTokenArrayRef xTokArr = rFmlaComp.CreateFormula( EXC_FMLATYPE_WQUERY, aScDestRange );
    2003           0 :                         sal_uInt16 nNameIdx = rNameMgr.InsertUniqueName( aUrlObj.getBase(), xTokArr, nScTab );
    2004           0 :                         aRangeName = rNameMgr.GetOrigName( nNameIdx );
    2005             :                     }
    2006             : 
    2007             :                     // create and store the web query record
    2008           0 :                     if( !aRangeName.isEmpty() )
    2009             :                         AppendNewRecord( new XclExpWebQuery(
    2010           0 :                             aRangeName, aWebQueryUrl, xAreaLink->getSourceArea(), nRefresh ) );
    2011           0 :                 }
    2012             :             }
    2013             :         }
    2014          29 :     }
    2015          30 : }
    2016             : 
    2017             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11