LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/filter/excel - excrecds.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 114 445 25.6 %
Date: 2013-07-09 Functions: 32 84 38.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include "excrecds.hxx"
      21             : 
      22             : #include <map>
      23             : #include <filter/msfilter/countryid.hxx>
      24             : 
      25             : #include "scitems.hxx"
      26             : #include <editeng/eeitem.hxx>
      27             : 
      28             : #include <sfx2/objsh.hxx>
      29             : 
      30             : #include <editeng/editdata.hxx>
      31             : #include <editeng/editeng.hxx>
      32             : #include <editeng/editobj.hxx>
      33             : #include <editeng/editstat.hxx>
      34             : 
      35             : #include <editeng/flditem.hxx>
      36             : #include <editeng/flstitem.hxx>
      37             : 
      38             : #include <svx/algitem.hxx>
      39             : #include <editeng/boxitem.hxx>
      40             : #include <editeng/brushitem.hxx>
      41             : #include <svx/pageitem.hxx>
      42             : #include <editeng/paperinf.hxx>
      43             : #include <editeng/sizeitem.hxx>
      44             : #include <editeng/ulspitem.hxx>
      45             : #include <editeng/fhgtitem.hxx>
      46             : #include <editeng/escapementitem.hxx>
      47             : #include <svl/intitem.hxx>
      48             : #include <svl/zforlist.hxx>
      49             : #include <svl/zformat.hxx>
      50             : #include <svtools/ctrltool.hxx>
      51             : 
      52             : 
      53             : #include <string.h>
      54             : 
      55             : #include "global.hxx"
      56             : #include "globstr.hrc"
      57             : #include "docpool.hxx"
      58             : #include "patattr.hxx"
      59             : #include "formulacell.hxx"
      60             : #include "document.hxx"
      61             : #include "scextopt.hxx"
      62             : #include "attrib.hxx"
      63             : #include "progress.hxx"
      64             : #include "dociter.hxx"
      65             : #include "rangenam.hxx"
      66             : #include "dbdata.hxx"
      67             : #include "stlsheet.hxx"
      68             : #include "stlpool.hxx"
      69             : #include "editutil.hxx"
      70             : #include "formula/errorcodes.hxx"
      71             : #include "queryentry.hxx"
      72             : #include "queryparam.hxx"
      73             : 
      74             : #include "excdoc.hxx"
      75             : #include "xeescher.hxx"
      76             : #include "xeformula.hxx"
      77             : #include "xelink.hxx"
      78             : #include "xename.hxx"
      79             : #include "xecontent.hxx"
      80             : 
      81             : #include "xcl97rec.hxx"
      82             : 
      83             : using namespace ::oox;
      84             : 
      85             : using ::com::sun::star::uno::Sequence;
      86             : 
      87             : //--------------------------------------------------------- class ExcDummy_00 -
      88             : const sal_uInt8     ExcDummy_00::pMyData[] = {
      89             :     0x5c, 0x00, 0x20, 0x00, 0x04, 'C',  'a',  'l',  'c',    // WRITEACCESS
      90             :     0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
      91             :     0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
      92             :     0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
      93             : };
      94             : const sal_Size ExcDummy_00::nMyLen = sizeof( ExcDummy_00::pMyData );
      95             : 
      96             : //-------------------------------------------------------- class ExcDummy_04x -
      97             : const sal_uInt8     ExcDummy_040::pMyData[] = {
      98             :     0x40, 0x00, 0x02, 0x00, 0x00, 0x00,                     // BACKUP
      99             :     0x8d, 0x00, 0x02, 0x00, 0x00, 0x00,                     // HIDEOBJ
     100             : };
     101             : const sal_Size ExcDummy_040::nMyLen = sizeof( ExcDummy_040::pMyData );
     102             : 
     103             : const sal_uInt8     ExcDummy_041::pMyData[] = {
     104             :     0x0e, 0x00, 0x02, 0x00, 0x01, 0x00,                     // PRECISION
     105             :     0xda, 0x00, 0x02, 0x00, 0x00, 0x00                      // BOOKBOOL
     106             : };
     107             : const sal_Size ExcDummy_041::nMyLen = sizeof( ExcDummy_041::pMyData );
     108             : 
     109             : //-------------------------------------------------------- class ExcDummy_02a -
     110             : const sal_uInt8      ExcDummy_02a::pMyData[] = {
     111             :     0x0d, 0x00, 0x02, 0x00, 0x01, 0x00,                     // CALCMODE
     112             :     0x0c, 0x00, 0x02, 0x00, 0x64, 0x00,                     // CALCCOUNT
     113             :     0x0f, 0x00, 0x02, 0x00, 0x01, 0x00,                     // REFMODE
     114             :     0x11, 0x00, 0x02, 0x00, 0x00, 0x00,                     // ITERATION
     115             :     0x10, 0x00, 0x08, 0x00, 0xfc, 0xa9, 0xf1, 0xd2, 0x4d,   // DELTA
     116             :     0x62, 0x50, 0x3f,
     117             :     0x5f, 0x00, 0x02, 0x00, 0x01, 0x00                      // SAVERECALC
     118             : };
     119             : const sal_Size ExcDummy_02a::nMyLen = sizeof( ExcDummy_02a::pMyData );
     120             : 
     121             : //----------------------------------------------------------- class ExcRecord -
     122             : 
     123          42 : void ExcRecord::Save( XclExpStream& rStrm )
     124             : {
     125          42 :     SetRecHeader( GetNum(), GetLen() );
     126          42 :     XclExpRecord::Save( rStrm );
     127          42 : }
     128             : 
     129           8 : void ExcRecord::SaveCont( XclExpStream& /*rStrm*/ )
     130             : {
     131           8 : }
     132             : 
     133          42 : void ExcRecord::WriteBody( XclExpStream& rStrm )
     134             : {
     135          42 :     SaveCont( rStrm );
     136          42 : }
     137             : 
     138          30 : void ExcRecord::SaveXml( XclExpXmlStream& /*rStrm*/ )
     139             : {
     140          30 : }
     141             : 
     142             : 
     143             : //--------------------------------------------------------- class ExcEmptyRec -
     144             : 
     145           0 : void ExcEmptyRec::Save( XclExpStream& /*rStrm*/ )
     146             : {
     147           0 : }
     148             : 
     149             : 
     150           0 : sal_uInt16 ExcEmptyRec::GetNum() const
     151             : {
     152           0 :     return 0;
     153             : }
     154             : 
     155             : 
     156           0 : sal_Size ExcEmptyRec::GetLen() const
     157             : {
     158           0 :     return 0;
     159             : }
     160             : 
     161             : //--------------------------------------------------------- class ExcDummyRec -
     162             : 
     163           0 : void ExcDummyRec::Save( XclExpStream& rStrm )
     164             : {
     165           0 :     rStrm.Write( GetData(), GetLen() );        // raw write mode
     166           0 : }
     167             : 
     168             : 
     169           0 : sal_uInt16 ExcDummyRec::GetNum( void ) const
     170             : {
     171           0 :     return 0x0000;
     172             : }
     173             : 
     174             : //------------------------------------------------------- class ExcBoolRecord -
     175             : 
     176           3 : void ExcBoolRecord::SaveCont( XclExpStream& rStrm )
     177             : {
     178           3 :     rStrm << (sal_uInt16)(bVal ? 0x0001 : 0x0000);
     179           3 : }
     180             : 
     181             : 
     182           3 : sal_Size ExcBoolRecord::GetLen( void ) const
     183             : {
     184           3 :     return 2;
     185             : }
     186             : 
     187             : 
     188             : 
     189             : 
     190             : //--------------------------------------------------------- class ExcBof_Base -
     191             : 
     192          23 : ExcBof_Base::ExcBof_Base() :
     193             :     nRupBuild( 0x096C ),    // copied from Excel
     194          23 :     nRupYear( 0x07C9 )      // copied from Excel
     195             : {
     196          23 : }
     197             : 
     198             : 
     199             : 
     200             : //-------------------------------------------------------------- class ExcBof -
     201             : 
     202           0 : ExcBof::ExcBof( void )
     203             : {
     204           0 :     nDocType = 0x0010;
     205           0 :     nVers = 0x0500;
     206           0 : }
     207             : 
     208             : 
     209           0 : void ExcBof::SaveCont( XclExpStream& rStrm )
     210             : {
     211           0 :     rStrm << nVers << nDocType << nRupBuild << nRupYear;
     212           0 : }
     213             : 
     214             : 
     215           0 : sal_uInt16 ExcBof::GetNum( void ) const
     216             : {
     217           0 :     return 0x0809;
     218             : }
     219             : 
     220             : 
     221           0 : sal_Size ExcBof::GetLen( void ) const
     222             : {
     223           0 :     return 8;
     224             : }
     225             : 
     226             : 
     227             : 
     228             : //------------------------------------------------------------- class ExcBofW -
     229             : 
     230           0 : ExcBofW::ExcBofW( void )
     231             : {
     232           0 :     nDocType = 0x0005;
     233           0 :     nVers = 0x0500;
     234           0 : }
     235             : 
     236             : 
     237           0 : void ExcBofW::SaveCont( XclExpStream& rStrm )
     238             : {
     239           0 :     rStrm << nVers << nDocType << nRupBuild << nRupYear;
     240           0 : }
     241             : 
     242             : 
     243             : 
     244           0 : sal_uInt16 ExcBofW::GetNum( void ) const
     245             : {
     246           0 :     return 0x0809;
     247             : }
     248             : 
     249             : 
     250             : 
     251           0 : sal_Size ExcBofW::GetLen( void ) const
     252             : {
     253           0 :     return 8;
     254             : }
     255             : 
     256             : 
     257             : 
     258             : //-------------------------------------------------------------- class ExcEof -
     259             : 
     260           8 : sal_uInt16 ExcEof::GetNum( void ) const
     261             : {
     262           8 :     return 0x000A;
     263             : }
     264             : 
     265             : 
     266           8 : sal_Size ExcEof::GetLen( void ) const
     267             : {
     268           8 :     return 0;
     269             : }
     270             : 
     271             : 
     272             : 
     273             : //--------------------------------------------------------- class ExcDummy_00 -
     274             : 
     275           0 : sal_Size ExcDummy_00::GetLen( void ) const
     276             : {
     277           0 :     return nMyLen;
     278             : }
     279             : 
     280             : 
     281           0 : const sal_uInt8* ExcDummy_00::GetData( void ) const
     282             : {
     283           0 :     return pMyData;
     284             : }
     285             : 
     286             : 
     287             : 
     288             : //-------------------------------------------------------- class ExcDummy_04x -
     289             : 
     290           0 : sal_Size ExcDummy_040::GetLen( void ) const
     291             : {
     292           0 :     return nMyLen;
     293             : }
     294             : 
     295             : 
     296           0 : const sal_uInt8* ExcDummy_040::GetData( void ) const
     297             : {
     298           0 :     return pMyData;
     299             : }
     300             : 
     301             : 
     302             : 
     303             : 
     304           0 : sal_Size ExcDummy_041::GetLen( void ) const
     305             : {
     306           0 :     return nMyLen;
     307             : }
     308             : 
     309             : 
     310           0 : const sal_uInt8* ExcDummy_041::GetData( void ) const
     311             : {
     312           0 :     return pMyData;
     313             : }
     314             : 
     315             : 
     316             : 
     317             : //------------------------------------------------------------- class Exc1904 -
     318             : 
     319           9 : Exc1904::Exc1904( ScDocument& rDoc )
     320             : {
     321           9 :     Date* pDate = rDoc.GetFormatTable()->GetNullDate();
     322           9 :     bVal = pDate ? (*pDate == Date( 1, 1, 1904 )) : false;
     323           9 :     bDateCompatibility = pDate ? !( *pDate == Date( 30, 12, 1899 )) : false;
     324           9 : }
     325             : 
     326             : 
     327           3 : sal_uInt16 Exc1904::GetNum( void ) const
     328             : {
     329           3 :     return 0x0022;
     330             : }
     331             : 
     332             : 
     333           6 : void Exc1904::SaveXml( XclExpXmlStream& rStrm )
     334             : {
     335           6 :     bool bISOIEC = ( rStrm.getVersion() == oox::core::ISOIEC_29500_2008 );
     336             : 
     337           6 :     if( bISOIEC )
     338             :     {
     339             :         rStrm.WriteAttributes(
     340             :             XML_dateCompatibility, XclXmlUtils::ToPsz( bDateCompatibility ),
     341           2 :             FSEND );
     342             :     }
     343             : 
     344           6 :     if( !bISOIEC || bDateCompatibility )
     345             :     {
     346             :         rStrm.WriteAttributes(
     347             :             XML_date1904, XclXmlUtils::ToPsz( bVal ),
     348           4 :             FSEND );
     349             :     }
     350           6 : }
     351             : 
     352             : 
     353             : 
     354             : //------------------------------------------------------ class ExcBundlesheet -
     355             : 
     356          14 : ExcBundlesheetBase::ExcBundlesheetBase( RootData& rRootData, SCTAB nTabNum ) :
     357             :     nStrPos( STREAM_SEEK_TO_END ),
     358             :     nOwnPos( STREAM_SEEK_TO_END ),
     359          14 :     nGrbit( rRootData.pER->GetTabInfo().IsVisibleTab( nTabNum ) ? 0x0000 : 0x0001 ),
     360          28 :     nTab( nTabNum )
     361             : {
     362          14 : }
     363             : 
     364             : 
     365           0 : ExcBundlesheetBase::ExcBundlesheetBase() :
     366             :     nStrPos( STREAM_SEEK_TO_END ),
     367             :     nOwnPos( STREAM_SEEK_TO_END ),
     368             :     nGrbit( 0x0000 ),
     369           0 :     nTab( SCTAB_GLOBAL )
     370             : {
     371           0 : }
     372             : 
     373             : 
     374           5 : void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm )
     375             : {
     376           5 :     rStrm.SetSvStreamPos( nOwnPos );
     377           5 :     rStrm.DisableEncryption();
     378           5 :     rStrm << static_cast<sal_uInt32>(nStrPos);
     379           5 :     rStrm.EnableEncryption();
     380           5 : }
     381             : 
     382             : 
     383           5 : sal_uInt16 ExcBundlesheetBase::GetNum( void ) const
     384             : {
     385           5 :     return 0x0085;
     386             : }
     387             : 
     388             : 
     389             : 
     390             : 
     391           0 : ExcBundlesheet::ExcBundlesheet( RootData& rRootData, SCTAB _nTab ) :
     392           0 :     ExcBundlesheetBase( rRootData, _nTab )
     393             : {
     394           0 :     OUString sTabName = rRootData.pER->GetTabInfo().GetScTabName( _nTab );
     395             :     OSL_ENSURE( sTabName.getLength() < 256, "ExcBundlesheet::ExcBundlesheet - table name too long" );
     396           0 :     aName = OUStringToOString(sTabName, rRootData.pER->GetTextEncoding());
     397           0 : }
     398             : 
     399             : 
     400           0 : void ExcBundlesheet::SaveCont( XclExpStream& rStrm )
     401             : {
     402           0 :     nOwnPos = rStrm.GetSvStreamPos();
     403           0 :     rStrm   << (sal_uInt32) 0x00000000              // dummy (stream position of the sheet)
     404           0 :             << nGrbit;
     405           0 :     rStrm.WriteByteString(aName);             // 8 bit length, max 255 chars
     406           0 : }
     407             : 
     408             : 
     409           0 : sal_Size ExcBundlesheet::GetLen() const
     410             : {
     411           0 :     return 7 + std::min( aName.getLength(), (sal_Int32) 255 );
     412             : }
     413             : 
     414             : 
     415             : //--------------------------------------------------------- class ExcDummy_02 -
     416             : 
     417           0 : sal_Size ExcDummy_02a::GetLen( void ) const
     418             : {
     419           0 :     return nMyLen;
     420             : }
     421             : 
     422           0 : const sal_uInt8* ExcDummy_02a::GetData( void ) const
     423             : {
     424           0 :     return pMyData;
     425             : }
     426             : //--------------------------------------------------------- class ExcDummy_02 -
     427             : 
     428           9 : XclExpCountry::XclExpCountry( const XclExpRoot& rRoot ) :
     429           9 :     XclExpRecord( EXC_ID_COUNTRY, 4 )
     430             : {
     431             :     /*  #i31530# set document country as UI country too -
     432             :         needed for correct behaviour of number formats. */
     433             :     mnUICountry = mnDocCountry = static_cast< sal_uInt16 >(
     434           9 :         ::msfilter::ConvertLanguageToCountry( rRoot.GetDocLanguage() ) );
     435           9 : }
     436             : 
     437           3 : void XclExpCountry::WriteBody( XclExpStream& rStrm )
     438             : {
     439           3 :     rStrm << mnUICountry << mnDocCountry;
     440           3 : }
     441             : 
     442             : // XclExpWsbool ===============================================================
     443             : 
     444          14 : XclExpWsbool::XclExpWsbool( bool bFitToPages, SCTAB nScTab, XclExpFilterManager* pManager )
     445             :     : XclExpUInt16Record( EXC_ID_WSBOOL, EXC_WSBOOL_DEFAULTFLAGS )
     446             :     , mnScTab( nScTab )
     447          14 :     , mpManager( pManager )
     448             : {
     449          14 :     if( bFitToPages )
     450           0 :         SetValue( GetValue() | EXC_WSBOOL_FITTOPAGE );
     451          14 : }
     452             : 
     453           9 : void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm )
     454             : {
     455           9 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
     456             :     rWorksheet->startElement( XML_sheetPr,
     457             :             // OOXTODO: XML_syncHorizontal,
     458             :             // OOXTODO: XML_syncVertical,
     459             :             // OOXTODO: XML_syncRef,
     460             :             // OOXTODO: XML_transitionEvaluation,
     461             :             // OOXTODO: XML_transitionEntry,
     462             :             // OOXTODO: XML_published,
     463             :             // OOXTODO: XML_codeName,
     464           9 :             XML_filterMode, mpManager ? XclXmlUtils::ToPsz( mpManager->HasFilterMode( mnScTab ) ) : NULL,
     465             :             // OOXTODO: XML_enableFormatConditionsCalculation,
     466          18 :             FSEND );
     467             :     // OOXTODO: elements XML_tabColor, XML_outlinePr
     468             :     rWorksheet->singleElement( XML_pageSetUpPr,
     469             :             // OOXTODO: XML_autoPageBreaks,
     470           9 :             XML_fitToPage,  XclXmlUtils::ToPsz( GetValue() & EXC_WSBOOL_FITTOPAGE ),
     471           9 :             FSEND );
     472           9 :     rWorksheet->endElement( XML_sheetPr );
     473           9 : }
     474             : 
     475             : 
     476             : // XclExpWindowProtection ===============================================================
     477             : 
     478           0 : XclExpWindowProtection::XclExpWindowProtection(bool bValue) :
     479           0 :     XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue)
     480             : {
     481           0 : }
     482             : 
     483           0 : void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm )
     484             : {
     485             :     rStrm.WriteAttributes(
     486           0 :             XML_lockWindows, XclXmlUtils::ToPsz( GetBool() ),
     487           0 :             FSEND );
     488           0 : }
     489             : 
     490             : // XclExpDocProtection ===============================================================
     491             : 
     492           0 : XclExpProtection::XclExpProtection(bool bValue) :
     493           0 :     XclExpBoolRecord(EXC_ID_PROTECT, bValue)
     494             : {
     495           0 : }
     496             : 
     497             : // ============================================================================
     498             : 
     499           0 : XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) :
     500             :     XclExpRecord(EXC_ID_PASSWORD, 2),
     501           0 :     mnHash(0x0000)
     502             : {
     503           0 :     if (aHash.getLength() >= 2)
     504             :     {
     505           0 :         mnHash  = ((aHash[0] << 8) & 0xFFFF);
     506           0 :         mnHash |= (aHash[1] & 0xFF);
     507             :     }
     508           0 : }
     509             : 
     510           0 : XclExpPassHash::~XclExpPassHash()
     511             : {
     512           0 : }
     513             : 
     514           0 : void XclExpPassHash::WriteBody(XclExpStream& rStrm)
     515             : {
     516           0 :     rStrm << mnHash;
     517           0 : }
     518             : 
     519             : // ============================================================================
     520             : 
     521           0 : XclExpFiltermode::XclExpFiltermode() :
     522           0 :     XclExpEmptyRecord( EXC_ID_FILTERMODE )
     523             : {
     524           0 : }
     525             : 
     526             : // ----------------------------------------------------------------------------
     527             : 
     528           0 : XclExpAutofilterinfo::XclExpAutofilterinfo( const ScAddress& rStartPos, SCCOL nScCol ) :
     529             :     XclExpUInt16Record( EXC_ID_AUTOFILTERINFO, static_cast< sal_uInt16 >( nScCol ) ),
     530           0 :     maStartPos( rStartPos )
     531             : {
     532           0 : }
     533             : 
     534             : // ----------------------------------------------------------------------------
     535             : 
     536           0 : ExcFilterCondition::ExcFilterCondition() :
     537             :         nType( EXC_AFTYPE_NOTUSED ),
     538             :         nOper( EXC_AFOPER_EQUAL ),
     539             :         fVal( 0.0 ),
     540           0 :         pText( NULL )
     541             : {
     542           0 : }
     543             : 
     544           0 : ExcFilterCondition::~ExcFilterCondition()
     545             : {
     546           0 :     if( pText )
     547           0 :         delete pText;
     548           0 : }
     549             : 
     550           0 : sal_Size ExcFilterCondition::GetTextBytes() const
     551             : {
     552           0 :     return pText ? (1 + pText->GetBufferSize()) : 0;
     553             : }
     554             : 
     555           0 : void ExcFilterCondition::SetCondition( sal_uInt8 nTp, sal_uInt8 nOp, double fV, OUString* pT )
     556             : {
     557           0 :     nType = nTp;
     558           0 :     nOper = nOp;
     559           0 :     fVal = fV;
     560             : 
     561           0 :     delete pText;
     562           0 :     (pT) ? pText = new XclExpString( *pT, EXC_STR_8BITLENGTH ) : pText =  NULL;
     563           0 : }
     564             : 
     565           0 : void ExcFilterCondition::Save( XclExpStream& rStrm )
     566             : {
     567           0 :     rStrm << nType << nOper;
     568           0 :     switch( nType )
     569             :     {
     570             :         case EXC_AFTYPE_DOUBLE:
     571           0 :             rStrm << fVal;
     572           0 :         break;
     573             :         case EXC_AFTYPE_STRING:
     574             :             OSL_ENSURE( pText, "ExcFilterCondition::Save() -- pText is NULL!" );
     575           0 :             rStrm << (sal_uInt32)0 << (sal_uInt8) pText->Len() << (sal_uInt16)0 << (sal_uInt8)0;
     576           0 :         break;
     577             :         case EXC_AFTYPE_BOOLERR:
     578           0 :             rStrm << (sal_uInt8)0 << (sal_uInt8)((fVal != 0) ? 1 : 0) << (sal_uInt32)0 << (sal_uInt16)0;
     579           0 :         break;
     580             :         default:
     581           0 :             rStrm << (sal_uInt32)0 << (sal_uInt32)0;
     582             :     }
     583           0 : }
     584             : 
     585           0 : static const char* lcl_GetOperator( sal_uInt8 nOper )
     586             : {
     587           0 :     switch( nOper )
     588             :     {
     589           0 :         case EXC_AFOPER_EQUAL:          return "equal";
     590           0 :         case EXC_AFOPER_GREATER:        return "greaterThan";
     591           0 :         case EXC_AFOPER_GREATEREQUAL:   return "greaterThanOrEqual";
     592           0 :         case EXC_AFOPER_LESS:           return "lessThan";
     593           0 :         case EXC_AFOPER_LESSEQUAL:      return "lessThanOrEqual";
     594           0 :         case EXC_AFOPER_NOTEQUAL:       return "notEqual";
     595             :         case EXC_AFOPER_NONE:
     596           0 :         default:                        return "**none**";
     597             :     }
     598             : }
     599             : 
     600           0 : static OString lcl_GetValue( sal_uInt8 nType, double fVal, XclExpString* pStr )
     601             : {
     602           0 :     switch( nType )
     603             :     {
     604           0 :         case EXC_AFTYPE_STRING:     return XclXmlUtils::ToOString( *pStr );
     605           0 :         case EXC_AFTYPE_DOUBLE:     return OString::valueOf( fVal );
     606           0 :         case EXC_AFTYPE_BOOLERR:    return OString::valueOf( (sal_Int32) ( fVal != 0 ? 1 : 0 ) );
     607           0 :         default:                    return OString();
     608             :     }
     609             : }
     610             : 
     611           0 : void ExcFilterCondition::SaveXml( XclExpXmlStream& rStrm )
     612             : {
     613           0 :     if( IsEmpty() )
     614           0 :         return;
     615             : 
     616           0 :     rStrm.GetCurrentStream()->singleElement( XML_customFilter,
     617             :             XML_operator,   lcl_GetOperator( nOper ),
     618             :             XML_val,        lcl_GetValue( nType, fVal, pText ).getStr(),
     619           0 :             FSEND );
     620             : }
     621             : 
     622           0 : void ExcFilterCondition::SaveText( XclExpStream& rStrm )
     623             : {
     624           0 :     if( nType == EXC_AFTYPE_STRING )
     625             :     {
     626             :         OSL_ENSURE( pText, "ExcFilterCondition::SaveText() -- pText is NULL!" );
     627           0 :         pText->WriteFlagField( rStrm );
     628           0 :         pText->WriteBuffer( rStrm );
     629             :     }
     630           0 : }
     631             : 
     632             : // ----------------------------------------------------------------------------
     633             : 
     634           0 : XclExpAutofilter::XclExpAutofilter( const XclExpRoot& rRoot, sal_uInt16 nC ) :
     635             :     XclExpRecord( EXC_ID_AUTOFILTER, 24 ),
     636             :     XclExpRoot( rRoot ),
     637             :     meType(FilterCondition),
     638             :     nCol( nC ),
     639           0 :     nFlags( 0 )
     640             : {
     641           0 : }
     642             : 
     643           0 : bool XclExpAutofilter::AddCondition( ScQueryConnect eConn, sal_uInt8 nType, sal_uInt8 nOp,
     644             :                                      double fVal, OUString* pText, bool bSimple )
     645             : {
     646           0 :     if( !aCond[ 1 ].IsEmpty() )
     647           0 :         return false;
     648             : 
     649           0 :     sal_uInt16 nInd = aCond[ 0 ].IsEmpty() ? 0 : 1;
     650             : 
     651           0 :     if( nInd == 1 )
     652           0 :         nFlags |= (eConn == SC_OR) ? EXC_AFFLAG_OR : EXC_AFFLAG_AND;
     653           0 :     if( bSimple )
     654           0 :         nFlags |= (nInd == 0) ? EXC_AFFLAG_SIMPLE1 : EXC_AFFLAG_SIMPLE2;
     655             : 
     656           0 :     aCond[ nInd ].SetCondition( nType, nOp, fVal, pText );
     657             : 
     658           0 :     AddRecSize( aCond[ nInd ].GetTextBytes() );
     659             : 
     660           0 :     return true;
     661             : }
     662             : 
     663           0 : bool XclExpAutofilter::HasCondition() const
     664             : {
     665           0 :     return !aCond[0].IsEmpty();
     666             : }
     667             : 
     668           0 : bool XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry )
     669             : {
     670           0 :     const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
     671           0 :     if (rItems.empty())
     672           0 :         return true;
     673             : 
     674           0 :     if (GetOutput() != EXC_OUTPUT_BINARY && rItems.size() > 1)
     675           0 :         return AddMultiValueEntry(rEntry);
     676             : 
     677           0 :     bool bConflict = false;
     678           0 :     OUString  sText;
     679           0 :     const ScQueryEntry::Item& rItem = rItems[0];
     680           0 :     const OUString& rQueryStr = rItem.maString;
     681           0 :     if (!rQueryStr.isEmpty())
     682             :     {
     683           0 :         sText = rQueryStr;
     684           0 :         switch( rEntry.eOp )
     685             :         {
     686             :             case SC_CONTAINS:
     687             :             case SC_DOES_NOT_CONTAIN:
     688             :             {
     689           0 :                 sText = "*" + sText + "*";
     690             :             }
     691           0 :             break;
     692             :             case SC_BEGINS_WITH:
     693             :             case SC_DOES_NOT_BEGIN_WITH:
     694           0 :                 sText += "*";
     695           0 :             break;
     696             :             case SC_ENDS_WITH:
     697             :             case SC_DOES_NOT_END_WITH:
     698           0 :                 sText = "*" + sText;
     699           0 :             break;
     700             :             default:
     701             :             {
     702             :                 //nothing
     703             :             }
     704             :         }
     705             :     }
     706             : 
     707           0 :     bool bLen = sText.getLength() > 0;
     708             : 
     709             :     // empty/nonempty fields
     710           0 :     if (rEntry.IsQueryByEmpty())
     711           0 :         bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_EMPTY, EXC_AFOPER_NONE, 0.0, NULL, true );
     712           0 :     else if(rEntry.IsQueryByNonEmpty())
     713           0 :         bConflict = !AddCondition( rEntry.eConnect, EXC_AFTYPE_NOTEMPTY, EXC_AFOPER_NONE, 0.0, NULL, true );
     714             :     // other conditions
     715             :     else
     716             :     {
     717           0 :         double  fVal    = 0.0;
     718           0 :         sal_uInt32  nIndex  = 0;
     719           0 :         bool bIsNum  = bLen ? GetFormatter().IsNumberFormat( sText, nIndex, fVal ) : true;
     720             :         OUString* pText;
     721           0 :         (bIsNum) ? pText = NULL : pText = &sText;
     722             : 
     723             :         // top10 flags
     724           0 :         sal_uInt16 nNewFlags = 0x0000;
     725           0 :         switch( rEntry.eOp )
     726             :         {
     727             :             case SC_TOPVAL:
     728           0 :                 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP);
     729           0 :             break;
     730             :             case SC_BOTVAL:
     731           0 :                 nNewFlags = EXC_AFFLAG_TOP10;
     732           0 :             break;
     733             :             case SC_TOPPERC:
     734           0 :                 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10TOP | EXC_AFFLAG_TOP10PERC);
     735           0 :             break;
     736             :             case SC_BOTPERC:
     737           0 :                 nNewFlags = (EXC_AFFLAG_TOP10 | EXC_AFFLAG_TOP10PERC);
     738           0 :             break;
     739             :             default:;
     740             :         }
     741           0 :         bool bNewTop10 = ::get_flag( nNewFlags, EXC_AFFLAG_TOP10 );
     742             : 
     743           0 :         bConflict = HasTop10() && bNewTop10;
     744           0 :         if( !bConflict )
     745             :         {
     746           0 :             if( bNewTop10 )
     747             :             {
     748           0 :                 if( fVal < 0 )      fVal = 0;
     749           0 :                 if( fVal >= 501 )   fVal = 500;
     750           0 :                 nFlags |= (nNewFlags | (sal_uInt16)(fVal) << 7);
     751             :             }
     752             :             // normal condition
     753             :             else
     754             :             {
     755           0 :                 sal_uInt8 nType = bIsNum ? EXC_AFTYPE_DOUBLE : EXC_AFTYPE_STRING;
     756           0 :                 sal_uInt8 nOper = EXC_AFOPER_NONE;
     757             : 
     758           0 :                 switch( rEntry.eOp )
     759             :                 {
     760           0 :                     case SC_EQUAL:          nOper = EXC_AFOPER_EQUAL;           break;
     761           0 :                     case SC_LESS:           nOper = EXC_AFOPER_LESS;            break;
     762           0 :                     case SC_GREATER:        nOper = EXC_AFOPER_GREATER;         break;
     763           0 :                     case SC_LESS_EQUAL:     nOper = EXC_AFOPER_LESSEQUAL;       break;
     764           0 :                     case SC_GREATER_EQUAL:  nOper = EXC_AFOPER_GREATEREQUAL;    break;
     765           0 :                     case SC_NOT_EQUAL:      nOper = EXC_AFOPER_NOTEQUAL;        break;
     766             :                     case SC_CONTAINS:
     767             :                     case SC_BEGINS_WITH:
     768             :                     case SC_ENDS_WITH:
     769           0 :                                             nOper = EXC_AFOPER_EQUAL;           break;
     770             :                     case SC_DOES_NOT_CONTAIN:
     771             :                     case SC_DOES_NOT_BEGIN_WITH:
     772             :                     case SC_DOES_NOT_END_WITH:
     773           0 :                                             nOper = EXC_AFOPER_NOTEQUAL;        break;
     774             :                     default:;
     775             :                 }
     776           0 :                 bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText );
     777             :             }
     778             :         }
     779             :     }
     780           0 :     return bConflict;
     781             : }
     782             : 
     783           0 : bool XclExpAutofilter::AddMultiValueEntry( const ScQueryEntry& rEntry )
     784             : {
     785           0 :     meType = MultiValue;
     786           0 :     const ScQueryEntry::QueryItemsType& rItems = rEntry.GetQueryItems();
     787           0 :     ScQueryEntry::QueryItemsType::const_iterator itr = rItems.begin(), itrEnd = rItems.end();
     788           0 :     for (; itr != itrEnd; ++itr)
     789           0 :         maMultiValues.push_back(itr->maString);
     790             : 
     791           0 :     return false;
     792             : }
     793             : 
     794           0 : void XclExpAutofilter::WriteBody( XclExpStream& rStrm )
     795             : {
     796           0 :     rStrm << nCol << nFlags;
     797           0 :     aCond[ 0 ].Save( rStrm );
     798           0 :     aCond[ 1 ].Save( rStrm );
     799           0 :     aCond[ 0 ].SaveText( rStrm );
     800           0 :     aCond[ 1 ].SaveText( rStrm );
     801           0 : }
     802             : 
     803           0 : void XclExpAutofilter::SaveXml( XclExpXmlStream& rStrm )
     804             : {
     805           0 :     if (meType == FilterCondition && !HasCondition())
     806           0 :         return;
     807             : 
     808           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
     809             : 
     810             :     rWorksheet->startElement( XML_filterColumn,
     811             :             XML_colId,          OString::valueOf( (sal_Int32) nCol ).getStr(),
     812             :             // OOXTODO: XML_hiddenButton,   AutoFilter12 fHideArrow?
     813             :             // OOXTODO: XML_showButton,
     814           0 :             FSEND );
     815             : 
     816           0 :     switch (meType)
     817             :     {
     818             :         case FilterCondition:
     819             :         {
     820           0 :             if( HasTop10() )
     821             :             {
     822             :                 rWorksheet->singleElement( XML_top10,
     823           0 :                         XML_top,        XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10TOP ) ),
     824           0 :                         XML_percent,    XclXmlUtils::ToPsz( get_flag( nFlags, EXC_AFFLAG_TOP10PERC ) ),
     825           0 :                         XML_val,        OString::valueOf( (sal_Int32) (nFlags >> 7 ) ).getStr(),
     826             :                         // OOXTODO: XML_filterVal,
     827           0 :                         FSEND );
     828             :             }
     829             : 
     830             :             rWorksheet->startElement( XML_customFilters,
     831           0 :                     XML_and,    XclXmlUtils::ToPsz( (nFlags & EXC_AFFLAG_ANDORMASK) == EXC_AFFLAG_AND ),
     832           0 :                     FSEND );
     833           0 :             aCond[ 0 ].SaveXml( rStrm );
     834           0 :             aCond[ 1 ].SaveXml( rStrm );
     835           0 :             rWorksheet->endElement( XML_customFilters );
     836             :             // OOXTODO: XLM_colorFilter, XML_dynamicFilter,
     837             :             // XML_extLst, XML_filters, XML_iconFilter, XML_top10
     838             :         }
     839           0 :         break;
     840             :         case MultiValue:
     841             :         {
     842           0 :             rWorksheet->startElement(XML_filters, FSEND);
     843           0 :             std::vector<OUString>::const_iterator itr = maMultiValues.begin(), itrEnd = maMultiValues.end();
     844           0 :             for (; itr != itrEnd; ++itr)
     845             :             {
     846           0 :                 const char* pz = OUStringToOString(*itr, RTL_TEXTENCODING_UTF8).getStr();
     847           0 :                 rWorksheet->singleElement(XML_filter, XML_val, pz, FSEND);
     848             :             }
     849           0 :             rWorksheet->endElement(XML_filters);
     850             :         }
     851           0 :         break;
     852             :     }
     853           0 :     rWorksheet->endElement( XML_filterColumn );
     854             : }
     855             : 
     856             : // ----------------------------------------------------------------------------
     857             : 
     858          14 : ExcAutoFilterRecs::ExcAutoFilterRecs( const XclExpRoot& rRoot, SCTAB nTab ) :
     859             :     XclExpRoot( rRoot ),
     860             :     pFilterMode( NULL ),
     861             :     pFilterInfo( NULL )
     862          14 :     , mbAutoFilter (false)
     863             : {
     864          14 :     XclExpNameManager& rNameMgr = GetNameManager();
     865             : 
     866          14 :     sal_Bool        bFound  = false;
     867          14 :     sal_Bool        bAdvanced = false;
     868          14 :     ScDBData*   pData   = rRoot.GetDoc().GetAnonymousDBData(nTab);
     869          14 :     ScRange     aAdvRange;
     870          14 :     if (pData)
     871             :     {
     872           0 :         bAdvanced = pData->GetAdvancedQuerySource( aAdvRange );
     873           0 :         bFound = (pData->HasQueryParam() || pData->HasAutoFilter() || bAdvanced);
     874             :     }
     875          14 :     if( bFound )
     876             :     {
     877           0 :         ScQueryParam    aParam;
     878           0 :         pData->GetQueryParam( aParam );
     879             : 
     880             :         ScRange aRange( aParam.nCol1, aParam.nRow1, aParam.nTab,
     881           0 :                         aParam.nCol2, aParam.nRow2, aParam.nTab );
     882           0 :         SCCOL   nColCnt = aParam.nCol2 - aParam.nCol1 + 1;
     883             : 
     884           0 :         maRef = aRange;
     885             : 
     886             :         // #i2394# built-in defined names must be sorted by containing sheet name
     887           0 :         rNameMgr.InsertBuiltInName( EXC_BUILTIN_FILTERDATABASE, aRange );
     888             : 
     889             :         // advanced filter
     890           0 :         if( bAdvanced )
     891             :         {
     892             :             // filter criteria, excel allows only same table
     893           0 :             if( aAdvRange.aStart.Tab() == nTab )
     894           0 :                 rNameMgr.InsertBuiltInName( EXC_BUILTIN_CRITERIA, aAdvRange );
     895             : 
     896             :             // filter destination range, excel allows only same table
     897           0 :             if( !aParam.bInplace )
     898             :             {
     899           0 :                 ScRange aDestRange( aParam.nDestCol, aParam.nDestRow, aParam.nDestTab );
     900           0 :                 aDestRange.aEnd.IncCol( nColCnt - 1 );
     901           0 :                 if( aDestRange.aStart.Tab() == nTab )
     902           0 :                     rNameMgr.InsertBuiltInName( EXC_BUILTIN_EXTRACT, aDestRange );
     903             :             }
     904             : 
     905           0 :             pFilterMode = new XclExpFiltermode;
     906             :         }
     907             :         // AutoFilter
     908             :         else
     909             :         {
     910           0 :             sal_Bool    bConflict   = false;
     911           0 :             sal_Bool    bContLoop   = sal_True;
     912           0 :             sal_Bool    bHasOr      = false;
     913           0 :             SCCOLROW nFirstField = aParam.GetEntry( 0 ).nField;
     914             : 
     915             :             // create AUTOFILTER records for filtered columns
     916           0 :             for( SCSIZE nEntry = 0; !bConflict && bContLoop && (nEntry < aParam.GetEntryCount()); nEntry++ )
     917             :             {
     918           0 :                 const ScQueryEntry& rEntry  = aParam.GetEntry( nEntry );
     919             : 
     920           0 :                 bContLoop = rEntry.bDoQuery;
     921           0 :                 if( bContLoop )
     922             :                 {
     923           0 :                     XclExpAutofilter* pFilter = GetByCol( static_cast<SCCOL>(rEntry.nField) - aRange.aStart.Col() );
     924             : 
     925           0 :                     if( nEntry > 0 )
     926           0 :                         bHasOr |= (rEntry.eConnect == SC_OR);
     927             : 
     928           0 :                     bConflict = (nEntry > 1) && bHasOr;
     929           0 :                     if( !bConflict )
     930           0 :                         bConflict = (nEntry == 1) && (rEntry.eConnect == SC_OR) &&
     931           0 :                                     (nFirstField != rEntry.nField);
     932           0 :                     if( !bConflict )
     933           0 :                         bConflict = pFilter->AddEntry( rEntry );
     934             :                 }
     935             :             }
     936             : 
     937             :             // additional tests for conflicts
     938           0 :             for( size_t nPos = 0, nSize = maFilterList.GetSize(); !bConflict && (nPos < nSize); ++nPos )
     939             :             {
     940           0 :                 XclExpAutofilterRef xFilter = maFilterList.GetRecord( nPos );
     941           0 :                 bConflict = xFilter->HasCondition() && xFilter->HasTop10();
     942           0 :             }
     943             : 
     944           0 :             if( bConflict )
     945           0 :                 maFilterList.RemoveAllRecords();
     946             : 
     947           0 :             if( !maFilterList.IsEmpty() )
     948           0 :                 pFilterMode = new XclExpFiltermode;
     949           0 :             pFilterInfo = new XclExpAutofilterinfo( aRange.aStart, nColCnt );
     950             : 
     951           0 :             if (maFilterList.IsEmpty () && !bConflict)
     952           0 :                 mbAutoFilter = true;
     953           0 :         }
     954             :     }
     955          14 : }
     956             : 
     957          42 : ExcAutoFilterRecs::~ExcAutoFilterRecs()
     958             : {
     959          14 :     delete pFilterMode;
     960          14 :     delete pFilterInfo;
     961          28 : }
     962             : 
     963           0 : XclExpAutofilter* ExcAutoFilterRecs::GetByCol( SCCOL nCol )
     964             : {
     965           0 :     XclExpAutofilterRef xFilter;
     966           0 :     for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
     967             :     {
     968           0 :         xFilter = maFilterList.GetRecord( nPos );
     969           0 :         if( xFilter->GetCol() == static_cast<sal_uInt16>(nCol) )
     970           0 :             return xFilter.get();
     971             :     }
     972           0 :     xFilter.reset( new XclExpAutofilter( GetRoot(), static_cast<sal_uInt16>(nCol) ) );
     973           0 :     maFilterList.AppendRecord( xFilter );
     974           0 :     return xFilter.get();
     975             : }
     976             : 
     977           0 : bool ExcAutoFilterRecs::IsFiltered( SCCOL nCol )
     978             : {
     979           0 :     for( size_t nPos = 0, nSize = maFilterList.GetSize(); nPos < nSize; ++nPos )
     980           0 :         if( maFilterList.GetRecord( nPos )->GetCol() == static_cast<sal_uInt16>(nCol) )
     981           0 :             return true;
     982           0 :     return false;
     983             : }
     984             : 
     985          14 : void ExcAutoFilterRecs::AddObjRecs()
     986             : {
     987          14 :     if( pFilterInfo )
     988             :     {
     989           0 :         ScAddress aAddr( pFilterInfo->GetStartPos() );
     990           0 :         for( SCCOL nObj = 0, nCount = pFilterInfo->GetColCount(); nObj < nCount; nObj++ )
     991             :         {
     992           0 :             XclObj* pObjRec = new XclObjDropDown( GetObjectManager(), aAddr, IsFiltered( nObj ) );
     993           0 :             GetObjectManager().AddObj( pObjRec );
     994           0 :             aAddr.IncCol( 1 );
     995             :         }
     996             :     }
     997          14 : }
     998             : 
     999           5 : void ExcAutoFilterRecs::Save( XclExpStream& rStrm )
    1000             : {
    1001           5 :     if( pFilterMode )
    1002           0 :         pFilterMode->Save( rStrm );
    1003           5 :     if( pFilterInfo )
    1004           0 :         pFilterInfo->Save( rStrm );
    1005           5 :     maFilterList.Save( rStrm );
    1006           5 : }
    1007             : 
    1008           9 : void ExcAutoFilterRecs::SaveXml( XclExpXmlStream& rStrm )
    1009             : {
    1010           9 :     if( maFilterList.IsEmpty() && !mbAutoFilter )
    1011          18 :         return;
    1012             : 
    1013           0 :     sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream();
    1014             :     rWorksheet->startElement( XML_autoFilter,
    1015             :             XML_ref,    XclXmlUtils::ToOString( maRef ).getStr(),
    1016           0 :             FSEND );
    1017             :     // OOXTODO: XML_extLst, XML_sortState
    1018           0 :     if( !maFilterList.IsEmpty() )
    1019           0 :         maFilterList.SaveXml( rStrm );
    1020           0 :     rWorksheet->endElement( XML_autoFilter );
    1021             : }
    1022             : 
    1023           9 : bool ExcAutoFilterRecs::HasFilterMode() const
    1024             : {
    1025           9 :     return pFilterMode != NULL;
    1026             : }
    1027             : 
    1028             : // ----------------------------------------------------------------------------
    1029             : 
    1030           9 : XclExpFilterManager::XclExpFilterManager( const XclExpRoot& rRoot ) :
    1031           9 :     XclExpRoot( rRoot )
    1032             : {
    1033           9 : }
    1034             : 
    1035          14 : void XclExpFilterManager::InitTabFilter( SCTAB nScTab )
    1036             : {
    1037          14 :     maFilterMap[ nScTab ].reset( new ExcAutoFilterRecs( GetRoot(), nScTab ) );
    1038          14 : }
    1039             : 
    1040          14 : XclExpRecordRef XclExpFilterManager::CreateRecord( SCTAB nScTab )
    1041             : {
    1042          14 :     XclExpTabFilterRef xRec;
    1043          14 :     XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
    1044          14 :     if( aIt != maFilterMap.end() )
    1045             :     {
    1046          14 :         xRec = aIt->second;
    1047          14 :         xRec->AddObjRecs();
    1048             :     }
    1049          14 :     return xRec;
    1050             : }
    1051             : 
    1052           9 : bool XclExpFilterManager::HasFilterMode( SCTAB nScTab )
    1053             : {
    1054           9 :     XclExpTabFilterRef xRec;
    1055           9 :     XclExpTabFilterMap::iterator aIt = maFilterMap.find( nScTab );
    1056           9 :     if( aIt != maFilterMap.end() )
    1057             :     {
    1058           9 :         return aIt->second->HasFilterMode();
    1059             :     }
    1060           0 :     return false;
    1061          15 : }
    1062             : 
    1063             : // ============================================================================
    1064             : 
    1065             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10