LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xehelper.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1 485 0.2 %
Date: 2012-08-25 Functions: 2 49 4.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 2 957 0.2 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <com/sun/star/i18n/XBreakIterator.hpp>
      30                 :            : #include <com/sun/star/i18n/ScriptType.hpp>
      31                 :            : #include <sfx2/objsh.hxx>
      32                 :            : #include <vcl/font.hxx>
      33                 :            : #include <tools/urlobj.hxx>
      34                 :            : #include <svl/itemset.hxx>
      35                 :            : #include <svtools/ctrltool.hxx>
      36                 :            : #include <svx/svdotext.hxx>
      37                 :            : #include <editeng/outlobj.hxx>
      38                 :            : #include "scitems.hxx"
      39                 :            : #include <editeng/fhgtitem.hxx>
      40                 :            : #include <editeng/flstitem.hxx>
      41                 :            : #include <editeng/colritem.hxx>
      42                 :            : #include <editeng/eeitem.hxx>
      43                 :            : #include <editeng/flditem.hxx>
      44                 :            : #include <editeng/escpitem.hxx>
      45                 :            : #include <editeng/svxfont.hxx>
      46                 :            : 
      47                 :            : #include "document.hxx"
      48                 :            : #include "docpool.hxx"
      49                 :            : #include "cell.hxx"
      50                 :            : #include "editutil.hxx"
      51                 :            : #include "patattr.hxx"
      52                 :            : #include "xestyle.hxx"
      53                 :            : #include "fprogressbar.hxx"
      54                 :            : #include "xltracer.hxx"
      55                 :            : #include "xecontent.hxx"
      56                 :            : #include "xelink.hxx"
      57                 :            : #include "xehelper.hxx"
      58                 :            : 
      59                 :            : using ::rtl::OUString;
      60                 :            : using ::com::sun::star::uno::Reference;
      61                 :            : using ::com::sun::star::i18n::XBreakIterator;
      62                 :            : 
      63                 :            : // Export progress bar ========================================================
      64                 :            : 
      65                 :          0 : XclExpProgressBar::XclExpProgressBar( const XclExpRoot& rRoot ) :
      66                 :            :     XclExpRoot( rRoot ),
      67         [ #  # ]:          0 :     mxProgress( new ScfProgressBar( rRoot.GetDocShell(), STR_SAVE_DOC ) ),
      68                 :            :     mpSubProgress( 0 ),
      69                 :            :     mpSubRowCreate( 0 ),
      70                 :            :     mpSubRowFinal( 0 ),
      71                 :            :     mnSegRowFinal( SCF_INV_SEGMENT ),
      72 [ #  # ][ #  # ]:          0 :     mnRowCount( 0 )
                 [ #  # ]
      73                 :            : {
      74                 :          0 : }
      75                 :            : 
      76         [ #  # ]:          0 : XclExpProgressBar::~XclExpProgressBar()
      77                 :            : {
      78         [ #  # ]:          0 : }
      79                 :            : 
      80                 :          0 : void XclExpProgressBar::Initialize()
      81                 :            : {
      82                 :          0 :     const ScDocument& rDoc = GetDoc();
      83                 :          0 :     const XclExpTabInfo& rTabInfo = GetTabInfo();
      84                 :          0 :     SCTAB nScTabCount = rTabInfo.GetScTabCount();
      85                 :            : 
      86                 :            :     // *** segment: creation of ROW records *** -------------------------------
      87                 :            : 
      88                 :          0 :     sal_Int32 nSegRowCreate = mxProgress->AddSegment( 2000 );
      89                 :          0 :     mpSubRowCreate = &mxProgress->GetSegmentProgressBar( nSegRowCreate );
      90                 :          0 :     maSubSegRowCreate.resize( nScTabCount, SCF_INV_SEGMENT );
      91                 :            : 
      92         [ #  # ]:          0 :     for( SCTAB nScTab = 0; nScTab < nScTabCount; ++nScTab )
      93                 :            :     {
      94         [ #  # ]:          0 :         if( rTabInfo.IsExportTab( nScTab ) )
      95                 :            :         {
      96                 :            :             SCCOL nLastUsedScCol;
      97                 :            :             SCROW nLastUsedScRow;
      98         [ #  # ]:          0 :             rDoc.GetTableArea( nScTab, nLastUsedScCol, nLastUsedScRow );
      99                 :          0 :             sal_Size nSegSize = static_cast< sal_Size >( nLastUsedScRow + 1 );
     100 [ #  # ][ #  # ]:          0 :             maSubSegRowCreate[ nScTab ] = mpSubRowCreate->AddSegment( nSegSize );
     101                 :            :         }
     102                 :            :     }
     103                 :            : 
     104                 :            :     // *** segment: writing all ROW records *** -------------------------------
     105                 :            : 
     106                 :          0 :     mnSegRowFinal = mxProgress->AddSegment( 1000 );
     107                 :            :     // sub progress bar and segment are created later in ActivateFinalRowsSegment()
     108                 :          0 : }
     109                 :            : 
     110                 :          0 : void XclExpProgressBar::IncRowRecordCount()
     111                 :            : {
     112                 :          0 :     ++mnRowCount;
     113                 :          0 : }
     114                 :            : 
     115                 :          0 : void XclExpProgressBar::ActivateCreateRowsSegment()
     116                 :            : {
     117                 :            :     OSL_ENSURE( (0 <= GetCurrScTab()) && (GetCurrScTab() < GetTabInfo().GetScTabCount()),
     118                 :            :         "XclExpProgressBar::ActivateCreateRowsSegment - invalid sheet" );
     119                 :          0 :     sal_Int32 nSeg = maSubSegRowCreate[ GetCurrScTab() ];
     120                 :            :     OSL_ENSURE( nSeg != SCF_INV_SEGMENT, "XclExpProgressBar::ActivateCreateRowsSegment - invalid segment" );
     121         [ #  # ]:          0 :     if( nSeg != SCF_INV_SEGMENT )
     122                 :            :     {
     123                 :          0 :         mpSubProgress = mpSubRowCreate;
     124                 :          0 :         mpSubProgress->ActivateSegment( nSeg );
     125                 :            :     }
     126                 :            :     else
     127                 :          0 :         mpSubProgress = 0;
     128                 :          0 : }
     129                 :            : 
     130                 :          0 : void XclExpProgressBar::ActivateFinalRowsSegment()
     131                 :            : {
     132 [ #  # ][ #  # ]:          0 :     if( !mpSubRowFinal && (mnRowCount > 0) )
     133                 :            :     {
     134                 :          0 :         mpSubRowFinal = &mxProgress->GetSegmentProgressBar( mnSegRowFinal );
     135                 :          0 :         mpSubRowFinal->AddSegment( mnRowCount );
     136                 :            :     }
     137                 :          0 :     mpSubProgress = mpSubRowFinal;
     138         [ #  # ]:          0 :     if( mpSubProgress )
     139                 :          0 :         mpSubProgress->Activate();
     140                 :          0 : }
     141                 :            : 
     142                 :          0 : void XclExpProgressBar::Progress()
     143                 :            : {
     144 [ #  # ][ #  # ]:          0 :     if( mpSubProgress && !mpSubProgress->IsFull() )
                 [ #  # ]
     145                 :          0 :         mpSubProgress->Progress();
     146                 :          0 : }
     147                 :            : 
     148                 :            : // Calc->Excel cell address/range conversion ==================================
     149                 :            : 
     150                 :            : namespace {
     151                 :            : 
     152                 :            : /** Fills the passed Excel address with the passed Calc cell coordinates without checking any limits. */
     153                 :          0 : inline void lclFillAddress( XclAddress& rXclPos, SCCOL nScCol, SCROW nScRow )
     154                 :            : {
     155                 :          0 :     rXclPos.mnCol = static_cast< sal_uInt16 >( nScCol );
     156                 :          0 :     rXclPos.mnRow = static_cast< sal_uInt32 >( nScRow );
     157                 :          0 : }
     158                 :            : 
     159                 :            : } // namespace
     160                 :            : 
     161                 :            : // ----------------------------------------------------------------------------
     162                 :            : 
     163                 :          0 : XclExpAddressConverter::XclExpAddressConverter( const XclExpRoot& rRoot ) :
     164                 :          0 :     XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetXclMaxPos() )
     165                 :            : {
     166                 :          0 : }
     167                 :            : 
     168                 :            : // cell address ---------------------------------------------------------------
     169                 :            : 
     170                 :          0 : bool XclExpAddressConverter::CheckAddress( const ScAddress& rScPos, bool bWarn )
     171                 :            : {
     172                 :            :     // ScAddress::operator<=() doesn't do what we want here
     173 [ #  # ][ #  # ]:          0 :     bool bValidCol = (0 <= rScPos.Col()) && (rScPos.Col() <= maMaxPos.Col());
     174 [ #  # ][ #  # ]:          0 :     bool bValidRow = (0 <= rScPos.Row()) && (rScPos.Row() <= maMaxPos.Row());
     175 [ #  # ][ #  # ]:          0 :     bool bValidTab = (0 <= rScPos.Tab()) && (rScPos.Tab() <= maMaxPos.Tab());
     176                 :            : 
     177 [ #  # ][ #  # ]:          0 :     bool bValid = bValidCol && bValidRow && bValidTab;
                 [ #  # ]
     178 [ #  # ][ #  # ]:          0 :     if( !bValid && bWarn )
     179                 :            :     {
     180                 :          0 :         mbColTrunc |= !bValidCol;
     181                 :          0 :         mbRowTrunc |= !bValidRow;
     182                 :          0 :         mbTabTrunc |= (rScPos.Tab() > maMaxPos.Tab());  // do not warn for deleted refs
     183                 :          0 :         mrTracer.TraceInvalidAddress( rScPos, maMaxPos );
     184                 :            :     }
     185                 :          0 :     return bValid;
     186                 :            : }
     187                 :            : 
     188                 :          0 : bool XclExpAddressConverter::ConvertAddress( XclAddress& rXclPos,
     189                 :            :         const ScAddress& rScPos, bool bWarn )
     190                 :            : {
     191                 :          0 :     bool bValid = CheckAddress( rScPos, bWarn );
     192         [ #  # ]:          0 :     if( bValid )
     193                 :          0 :         lclFillAddress( rXclPos, rScPos.Col(), rScPos.Row() );
     194                 :          0 :     return bValid;
     195                 :            : }
     196                 :            : 
     197                 :          0 : XclAddress XclExpAddressConverter::CreateValidAddress( const ScAddress& rScPos, bool bWarn )
     198                 :            : {
     199                 :          0 :     XclAddress aXclPos( ScAddress::UNINITIALIZED );
     200         [ #  # ]:          0 :     if( !ConvertAddress( aXclPos, rScPos, bWarn ) )
     201 [ #  # ][ #  # ]:          0 :         lclFillAddress( aXclPos, ::std::min( rScPos.Col(), maMaxPos.Col() ), ::std::min( rScPos.Row(), maMaxPos.Row() ) );
     202                 :          0 :     return aXclPos;
     203                 :            : }
     204                 :            : 
     205                 :            : // cell range -----------------------------------------------------------------
     206                 :            : 
     207                 :          0 : bool XclExpAddressConverter::CheckRange( const ScRange& rScRange, bool bWarn )
     208                 :            : {
     209 [ #  # ][ #  # ]:          0 :     return CheckAddress( rScRange.aStart, bWarn ) && CheckAddress( rScRange.aEnd, bWarn );
     210                 :            : }
     211                 :            : 
     212                 :          0 : bool XclExpAddressConverter::ValidateRange( ScRange& rScRange, bool bWarn )
     213                 :            : {
     214                 :          0 :     rScRange.Justify();
     215                 :            : 
     216                 :            :     // check start position
     217                 :          0 :     bool bValidStart = CheckAddress( rScRange.aStart, bWarn );
     218         [ #  # ]:          0 :     if( bValidStart )
     219                 :            :     {
     220                 :            :         // check & correct end position
     221                 :          0 :         ScAddress& rScEnd = rScRange.aEnd;
     222         [ #  # ]:          0 :         if( !CheckAddress( rScEnd, bWarn ) )
     223                 :            :         {
     224         [ #  # ]:          0 :             rScEnd.SetCol( ::std::min( rScEnd.Col(), maMaxPos.Col() ) );
     225         [ #  # ]:          0 :             rScEnd.SetRow( ::std::min( rScEnd.Row(), maMaxPos.Row() ) );
     226         [ #  # ]:          0 :             rScEnd.SetTab( ::std::min( rScEnd.Tab(), maMaxPos.Tab() ) );
     227                 :            :         }
     228                 :            :     }
     229                 :            : 
     230                 :          0 :     return bValidStart;
     231                 :            : }
     232                 :            : 
     233                 :          0 : bool XclExpAddressConverter::ConvertRange( XclRange& rXclRange,
     234                 :            :         const ScRange& rScRange, bool bWarn )
     235                 :            : {
     236                 :            :     // check start position
     237                 :          0 :     bool bValidStart = CheckAddress( rScRange.aStart, bWarn );
     238         [ #  # ]:          0 :     if( bValidStart )
     239                 :            :     {
     240                 :          0 :         lclFillAddress( rXclRange.maFirst, rScRange.aStart.Col(), rScRange.aStart.Row() );
     241                 :            : 
     242                 :            :         // check & correct end position
     243                 :          0 :         SCCOL nScCol2 = rScRange.aEnd.Col();
     244                 :          0 :         SCROW nScRow2 = rScRange.aEnd.Row();
     245 [ #  # ][ #  # ]:          0 :         if( !CheckAddress( rScRange.aEnd, bWarn ) )
     246                 :            :         {
     247         [ #  # ]:          0 :             nScCol2 = ::std::min( nScCol2, maMaxPos.Col() );
     248         [ #  # ]:          0 :             nScRow2 = ::std::min( nScRow2, maMaxPos.Row() );
     249                 :            :         }
     250                 :          0 :         lclFillAddress( rXclRange.maLast, nScCol2, nScRow2 );
     251                 :            :     }
     252                 :          0 :     return bValidStart;
     253                 :            : }
     254                 :            : 
     255                 :            : // cell range list ------------------------------------------------------------
     256                 :            : 
     257                 :          0 : void XclExpAddressConverter::ValidateRangeList( ScRangeList& rScRanges, bool bWarn )
     258                 :            : {
     259         [ #  # ]:          0 :     for ( size_t nRange = rScRanges.size(); nRange > 0; )
     260                 :            :     {
     261                 :          0 :         ScRange* pScRange = rScRanges[ --nRange ];
     262         [ #  # ]:          0 :         if( !CheckRange( *pScRange, bWarn ) )
     263                 :          0 :             delete rScRanges.Remove(nRange);
     264                 :            :     }
     265                 :          0 : }
     266                 :            : 
     267                 :          0 : void XclExpAddressConverter::ConvertRangeList( XclRangeList& rXclRanges,
     268                 :            :         const ScRangeList& rScRanges, bool bWarn )
     269                 :            : {
     270                 :          0 :     rXclRanges.clear();
     271         [ #  # ]:          0 :     for( size_t nPos = 0, nCount = rScRanges.size(); nPos < nCount; ++nPos )
     272                 :            :     {
     273         [ #  # ]:          0 :         if( const ScRange* pScRange = rScRanges[ nPos ] )
     274                 :            :         {
     275                 :          0 :             XclRange aXclRange( ScAddress::UNINITIALIZED );
     276 [ #  # ][ #  # ]:          0 :             if( ConvertRange( aXclRange, *pScRange, bWarn ) )
     277         [ #  # ]:          0 :                 rXclRanges.push_back( aXclRange );
     278                 :            :         }
     279                 :            :     }
     280                 :          0 : }
     281                 :            : 
     282                 :            : // EditEngine->String conversion ==============================================
     283                 :            : 
     284                 :            : namespace {
     285                 :            : 
     286                 :          0 : rtl::OUString lclGetUrlRepresentation( const SvxURLField& rUrlField )
     287                 :            : {
     288                 :          0 :     const rtl::OUString& aRepr = rUrlField.GetRepresentation();
     289                 :            :     // no representation -> use URL
     290         [ #  # ]:          0 :     return aRepr.isEmpty() ? rUrlField.GetURL() : aRepr;
     291                 :            : }
     292                 :            : 
     293                 :            : } // namespace
     294                 :            : 
     295                 :            : // ----------------------------------------------------------------------------
     296                 :            : 
     297                 :          0 : XclExpHyperlinkHelper::XclExpHyperlinkHelper( const XclExpRoot& rRoot, const ScAddress& rScPos ) :
     298                 :            :     XclExpRoot( rRoot ),
     299                 :            :     maScPos( rScPos ),
     300 [ #  # ][ #  # ]:          0 :     mbMultipleUrls( false )
     301                 :            : {
     302                 :          0 : }
     303                 :            : 
     304 [ #  # ][ #  # ]:          0 : XclExpHyperlinkHelper::~XclExpHyperlinkHelper()
     305                 :            : {
     306         [ #  # ]:          0 : }
     307                 :            : 
     308                 :          0 : rtl::OUString XclExpHyperlinkHelper::ProcessUrlField( const SvxURLField& rUrlField )
     309                 :            : {
     310                 :          0 :     rtl::OUString aUrlRepr;
     311                 :            : 
     312         [ #  # ]:          0 :     if( GetBiff() == EXC_BIFF8 )    // no HLINK records in BIFF2-BIFF7
     313                 :            :     {
     314                 :            :         // there was/is already a HLINK record
     315                 :          0 :         mbMultipleUrls = mxLinkRec;
     316                 :            : 
     317 [ #  # ][ #  # ]:          0 :         mxLinkRec.reset( new XclExpHyperlink( GetRoot(), rUrlField, maScPos ) );
                 [ #  # ]
     318                 :            : 
     319 [ #  # ][ #  # ]:          0 :         if( const String* pRepr = mxLinkRec->GetRepr() )
     320         [ #  # ]:          0 :             aUrlRepr = *pRepr;
     321                 :            : 
     322                 :            :         // add URL to note text
     323 [ #  # ][ #  # ]:          0 :         ScGlobal::AddToken( maUrlList, rUrlField.GetURL(), '\n' );
                 [ #  # ]
     324                 :            :     }
     325                 :            : 
     326                 :            :     // no hyperlink representation from Excel HLINK record -> use it from text field
     327         [ #  # ]:          0 :     return aUrlRepr.isEmpty() ? lclGetUrlRepresentation(rUrlField) : aUrlRepr;
     328                 :            : }
     329                 :            : 
     330                 :          0 : bool XclExpHyperlinkHelper::HasLinkRecord() const
     331                 :            : {
     332 [ #  # ][ #  # ]:          0 :     return !mbMultipleUrls && mxLinkRec;
     333                 :            : }
     334                 :            : 
     335                 :          0 : XclExpHyperlinkHelper::XclExpHyperlinkRef XclExpHyperlinkHelper::GetLinkRecord()
     336                 :            : {
     337         [ #  # ]:          0 :     if( HasLinkRecord() )
     338                 :          0 :         return mxLinkRec;
     339                 :          0 :     return XclExpHyperlinkRef();
     340                 :            : }
     341                 :            : 
     342                 :            : // ----------------------------------------------------------------------------
     343                 :            : 
     344                 :            : namespace {
     345                 :            : 
     346                 :            : /** Creates a new formatted string from the passed unformatted string.
     347                 :            : 
     348                 :            :     Creates a Unicode string or a byte string, depending on the current BIFF
     349                 :            :     version contained in the passed XclExpRoot object. May create a formatted
     350                 :            :     string object, if the text contains different script types.
     351                 :            : 
     352                 :            :     @param pCellAttr
     353                 :            :         Cell attributes used for font formatting.
     354                 :            :     @param nFlags
     355                 :            :         Modifiers for string export.
     356                 :            :     @param nMaxLen
     357                 :            :         The maximum number of characters to store in this string.
     358                 :            :     @return
     359                 :            :         The new string object.
     360                 :            :  */
     361                 :          0 : XclExpStringRef lclCreateFormattedString(
     362                 :            :         const XclExpRoot& rRoot, const String& rText, const ScPatternAttr* pCellAttr,
     363                 :            :         XclStrFlags nFlags, sal_uInt16 nMaxLen )
     364                 :            : {
     365                 :            :     /*  Create an empty Excel string object with correctly initialized BIFF mode,
     366                 :            :         because this function only uses Append() functions that require this. */
     367 [ #  # ][ #  # ]:          0 :     XclExpStringRef xString = XclExpStringHelper::CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
     368                 :            : 
     369                 :            :     // script type handling
     370         [ #  # ]:          0 :     Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
     371                 :            :     namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
     372                 :            :     // #i63255# get script type for leading weak characters
     373         [ #  # ]:          0 :     sal_Int16 nLastScript = XclExpStringHelper::GetLeadingScriptType( rRoot, rText );
     374                 :            : 
     375                 :            :     // font buffer and cell item set
     376         [ #  # ]:          0 :     XclExpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
     377 [ #  # ][ #  # ]:          0 :     const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
     378                 :            : 
     379                 :            :     // process all script portions
     380         [ #  # ]:          0 :     OUString aOUText( rText );
     381                 :          0 :     sal_Int32 nPortionPos = 0;
     382                 :          0 :     sal_Int32 nTextLen = aOUText.getLength();
     383         [ #  # ]:          0 :     while( nPortionPos < nTextLen )
     384                 :            :     {
     385                 :            :         // get script type and end position of next script portion
     386 [ #  # ][ #  # ]:          0 :         sal_Int16 nScript = xBreakIt->getScriptType( aOUText, nPortionPos );
     387 [ #  # ][ #  # ]:          0 :         sal_Int32 nPortionEnd = xBreakIt->endOfScript( aOUText, nPortionPos, nScript );
     388                 :            : 
     389                 :            :         // reuse previous script for following weak portions
     390         [ #  # ]:          0 :         if( nScript == ApiScriptType::WEAK )
     391                 :          0 :             nScript = nLastScript;
     392                 :            : 
     393                 :            :         // construct font from current text portion
     394 [ #  # ][ #  # ]:          0 :         SvxFont aFont( XclExpFontHelper::GetFontFromItemSet( rRoot, rItemSet, nScript ) );
                 [ #  # ]
     395                 :            : 
     396                 :            :         // Excel start position of this portion
     397                 :          0 :         sal_uInt16 nXclPortionStart = xString->Len();
     398                 :            :         // add portion text to Excel string
     399 [ #  # ][ #  # ]:          0 :         XclExpStringHelper::AppendString( *xString, rRoot, aOUText.copy( nPortionPos, nPortionEnd - nPortionPos ) );
                 [ #  # ]
     400         [ #  # ]:          0 :         if( nXclPortionStart < xString->Len() )
     401                 :            :         {
     402                 :            :             // insert font into buffer
     403         [ #  # ]:          0 :             sal_uInt16 nFontIdx = rFontBuffer.Insert( aFont, EXC_COLOR_CELLTEXT );
     404                 :            :             // insert font index into format run vector
     405         [ #  # ]:          0 :             xString->AppendFormat( nXclPortionStart, nFontIdx );
     406                 :            :         }
     407                 :            : 
     408                 :            :         // go to next script portion
     409                 :          0 :         nLastScript = nScript;
     410                 :          0 :         nPortionPos = nPortionEnd;
     411         [ #  # ]:          0 :     }
     412                 :            : 
     413                 :          0 :     return xString;
     414                 :            : }
     415                 :            : 
     416                 :            : /** Creates a new formatted string from an edit engine text object.
     417                 :            : 
     418                 :            :     Creates a Unicode string or a byte string, depending on the current BIFF
     419                 :            :     version contained in the passed XclExpRoot object.
     420                 :            : 
     421                 :            :     @param rEE
     422                 :            :         The edit engine in use. The text object must already be set.
     423                 :            :     @param nFlags
     424                 :            :         Modifiers for string export.
     425                 :            :     @param nMaxLen
     426                 :            :         The maximum number of characters to store in this string.
     427                 :            :     @return
     428                 :            :         The new string object.
     429                 :            :  */
     430                 :          0 : XclExpStringRef lclCreateFormattedString(
     431                 :            :         const XclExpRoot& rRoot, EditEngine& rEE, XclExpHyperlinkHelper* pLinkHelper,
     432                 :            :         XclStrFlags nFlags, sal_uInt16 nMaxLen )
     433                 :            : {
     434                 :            :     /*  Create an empty Excel string object with correctly initialized BIFF mode,
     435                 :            :         because this function only uses Append() functions that require this. */
     436 [ #  # ][ #  # ]:          0 :     XclExpStringRef xString = XclExpStringHelper::CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
     437                 :            : 
     438                 :            :     // font buffer and helper item set for edit engine -> Calc item conversion
     439         [ #  # ]:          0 :     XclExpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
     440 [ #  # ][ #  # ]:          0 :     SfxItemSet aItemSet( *rRoot.GetDoc().GetPool(), ATTR_PATTERN_START, ATTR_PATTERN_END );
     441                 :            : 
     442                 :            :     // script type handling
     443         [ #  # ]:          0 :     Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
     444                 :            :     namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
     445                 :            :     // #i63255# get script type for leading weak characters
     446 [ #  # ][ #  # ]:          0 :     sal_Int16 nLastScript = XclExpStringHelper::GetLeadingScriptType( rRoot, rEE.GetText() );
                 [ #  # ]
     447                 :            : 
     448                 :            :     // process all paragraphs
     449         [ #  # ]:          0 :     sal_uInt16 nParaCount = rEE.GetParagraphCount();
     450         [ #  # ]:          0 :     for( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara )
     451                 :            :     {
     452                 :          0 :         ESelection aSel( nPara, 0 );
     453         [ #  # ]:          0 :         String aParaText( rEE.GetText( nPara ) );
     454                 :            : 
     455         [ #  # ]:          0 :         std::vector<sal_uInt16> aPosList;
     456         [ #  # ]:          0 :         rEE.GetPortions( nPara, aPosList );
     457                 :            : 
     458                 :            :         // process all portions in the paragraph
     459 [ #  # ][ #  # ]:          0 :         for( std::vector<sal_uInt16>::const_iterator it(aPosList.begin()); it != aPosList.end(); ++it )
         [ #  # ][ #  # ]
     460                 :            :         {
     461         [ #  # ]:          0 :             aSel.nEndPos = static_cast< xub_StrLen >( *it );
     462         [ #  # ]:          0 :             String aXclPortionText( aParaText, aSel.nStartPos, aSel.nEndPos - aSel.nStartPos );
     463                 :            : 
     464         [ #  # ]:          0 :             aItemSet.ClearItem();
     465         [ #  # ]:          0 :             SfxItemSet aEditSet( rEE.GetAttribs( aSel ) );
     466         [ #  # ]:          0 :             ScPatternAttr::GetFromEditItemSet( aItemSet, aEditSet );
     467                 :            : 
     468                 :            :             // get escapement value
     469         [ #  # ]:          0 :             short nEsc = GETITEM( aEditSet, SvxEscapementItem, EE_CHAR_ESCAPEMENT ).GetEsc();
     470                 :            : 
     471                 :            :             // process text fields
     472                 :          0 :             bool bIsHyperlink = false;
     473         [ #  # ]:          0 :             if( aSel.nStartPos + 1 == aSel.nEndPos )
     474                 :            :             {
     475                 :            :                 // test if the character is a text field
     476                 :            :                 const SfxPoolItem* pItem;
     477 [ #  # ][ #  # ]:          0 :                 if( aEditSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SFX_ITEM_SET )
     478                 :            :                 {
     479                 :          0 :                     const SvxFieldData* pField = static_cast< const SvxFieldItem* >( pItem )->GetField();
     480 [ #  # ][ #  # ]:          0 :                     if( const SvxURLField* pUrlField = PTR_CAST( SvxURLField, pField ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     481                 :            :                     {
     482                 :            :                         // convert URL field to string representation
     483                 :            :                         aXclPortionText = pLinkHelper ?
     484                 :            :                             pLinkHelper->ProcessUrlField( *pUrlField ) :
     485 [ #  # ][ #  # ]:          0 :                             lclGetUrlRepresentation( *pUrlField );
                 [ #  # ]
     486                 :          0 :                         bIsHyperlink = true;
     487                 :            :                     }
     488                 :            :                     else
     489                 :            :                     {
     490                 :            :                         OSL_FAIL( "lclCreateFormattedString - unknown text field" );
     491         [ #  # ]:          0 :                         aXclPortionText.Erase();
     492                 :            :                     }
     493                 :            :                 }
     494                 :            :             }
     495                 :            : 
     496                 :            :             // Excel start position of this portion
     497                 :          0 :             sal_uInt16 nXclPortionStart = xString->Len();
     498                 :            :             // add portion text to Excel string
     499         [ #  # ]:          0 :             XclExpStringHelper::AppendString( *xString, rRoot, aXclPortionText );
     500 [ #  # ][ #  # ]:          0 :             if( (nXclPortionStart < xString->Len()) || (aParaText.Len() == 0) )
                 [ #  # ]
     501                 :            :             {
     502                 :            :                 /*  Construct font from current edit engine text portion. Edit engine
     503                 :            :                     creates different portions for different script types, no need to loop. */
     504 [ #  # ][ #  # ]:          0 :                 sal_Int16 nScript = xBreakIt->getScriptType( aXclPortionText, 0 );
                 [ #  # ]
     505         [ #  # ]:          0 :                 if( nScript == ApiScriptType::WEAK )
     506                 :          0 :                     nScript = nLastScript;
     507 [ #  # ][ #  # ]:          0 :                 SvxFont aFont( XclExpFontHelper::GetFontFromItemSet( rRoot, aItemSet, nScript ) );
                 [ #  # ]
     508                 :          0 :                 nLastScript = nScript;
     509                 :            : 
     510                 :            :                 // add escapement
     511                 :          0 :                 aFont.SetEscapement( nEsc );
     512                 :            :                 // modify automatic font color for hyperlinks
     513 [ #  # ][ #  # ]:          0 :                 if( bIsHyperlink && (GETITEM( aItemSet, SvxColorItem, ATTR_FONT_COLOR ).GetValue().GetColor() == COL_AUTO) )
         [ #  # ][ #  # ]
     514         [ #  # ]:          0 :                     aFont.SetColor( Color( COL_LIGHTBLUE ) );
     515                 :            : 
     516                 :            :                 // insert font into buffer
     517         [ #  # ]:          0 :                 sal_uInt16 nFontIdx = rFontBuffer.Insert( aFont, EXC_COLOR_CELLTEXT );
     518                 :            :                 // insert font index into format run vector
     519 [ #  # ][ #  # ]:          0 :                 xString->AppendFormat( nXclPortionStart, nFontIdx );
     520                 :            :             }
     521                 :            : 
     522                 :          0 :             aSel.nStartPos = aSel.nEndPos;
     523 [ #  # ][ #  # ]:          0 :         }
     524                 :            : 
     525                 :            :         // add trailing newline (important for correct character index calculation)
     526         [ #  # ]:          0 :         if( nPara + 1 < nParaCount )
     527         [ #  # ]:          0 :             XclExpStringHelper::AppendChar( *xString, rRoot, '\n' );
     528         [ #  # ]:          0 :     }
     529                 :            : 
     530         [ #  # ]:          0 :     return xString;
     531                 :            : }
     532                 :            : 
     533                 :            : } // namespace
     534                 :            : 
     535                 :            : // ----------------------------------------------------------------------------
     536                 :            : 
     537                 :          0 : XclExpStringRef XclExpStringHelper::CreateString(
     538                 :            :         const XclExpRoot& rRoot, const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen )
     539                 :            : {
     540 [ #  # ][ #  # ]:          0 :     XclExpStringRef xString( new XclExpString );
     541         [ #  # ]:          0 :     if( rRoot.GetBiff() == EXC_BIFF8 )
     542         [ #  # ]:          0 :         xString->Assign( rString, nFlags, nMaxLen );
     543                 :            :     else
     544         [ #  # ]:          0 :         xString->AssignByte( rString, rRoot.GetTextEncoding(), nFlags, nMaxLen );
     545                 :          0 :     return xString;
     546                 :            : }
     547                 :            : 
     548                 :          0 : XclExpStringRef XclExpStringHelper::CreateString(
     549                 :            :         const XclExpRoot& rRoot, sal_Unicode cChar, XclStrFlags nFlags, sal_uInt16 nMaxLen )
     550                 :            : {
     551                 :          0 :     XclExpStringRef xString = CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
     552         [ #  # ]:          0 :     AppendChar( *xString, rRoot, cChar );
     553                 :          0 :     return xString;
     554                 :            : }
     555                 :            : 
     556                 :          0 : void XclExpStringHelper::AppendString( XclExpString& rXclString, const XclExpRoot& rRoot, const String& rString )
     557                 :            : {
     558         [ #  # ]:          0 :     if( rRoot.GetBiff() == EXC_BIFF8 )
     559                 :          0 :         rXclString.Append( rString );
     560                 :            :     else
     561                 :          0 :         rXclString.AppendByte( rString, rRoot.GetTextEncoding() );
     562                 :          0 : }
     563                 :            : 
     564                 :          0 : void XclExpStringHelper::AppendChar( XclExpString& rXclString, const XclExpRoot& rRoot, sal_Unicode cChar )
     565                 :            : {
     566         [ #  # ]:          0 :     if( rRoot.GetBiff() == EXC_BIFF8 )
     567 [ #  # ][ #  # ]:          0 :         rXclString.Append( rtl::OUString(cChar) );
                 [ #  # ]
     568                 :            :     else
     569                 :          0 :         rXclString.AppendByte( cChar, rRoot.GetTextEncoding() );
     570                 :          0 : }
     571                 :            : 
     572                 :          0 : XclExpStringRef XclExpStringHelper::CreateCellString(
     573                 :            :         const XclExpRoot& rRoot, const ScStringCell& rStringCell, const ScPatternAttr* pCellAttr,
     574                 :            :         XclStrFlags nFlags, sal_uInt16 nMaxLen )
     575                 :            : {
     576                 :          0 :     rtl::OUString aCellText = rStringCell.GetString();
     577 [ #  # ][ #  # ]:          0 :     return lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
                 [ #  # ]
     578                 :            : }
     579                 :            : 
     580                 :          0 : XclExpStringRef XclExpStringHelper::CreateCellString(
     581                 :            :         const XclExpRoot& rRoot, const ScEditCell& rEditCell, const ScPatternAttr* pCellAttr,
     582                 :            :         XclExpHyperlinkHelper& rLinkHelper, XclStrFlags nFlags, sal_uInt16 nMaxLen )
     583                 :            : {
     584                 :          0 :     XclExpStringRef xString;
     585         [ #  # ]:          0 :     if( const EditTextObject* pEditObj = rEditCell.GetData() )
     586                 :            :     {
     587                 :            :         // formatted cell
     588         [ #  # ]:          0 :         ScEditEngineDefaulter& rEE = rRoot.GetEditEngine();
     589         [ #  # ]:          0 :         sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
     590         [ #  # ]:          0 :         rEE.SetUpdateMode( sal_True );
     591                 :            :         // default items
     592 [ #  # ][ #  # ]:          0 :         const SfxItemSet& rItemSet = pCellAttr ? pCellAttr->GetItemSet() : rRoot.GetDoc().GetDefPattern()->GetItemSet();
     593 [ #  # ][ #  # ]:          0 :         SfxItemSet* pEEItemSet = new SfxItemSet( rEE.GetEmptyItemSet() );
                 [ #  # ]
     594         [ #  # ]:          0 :         ScPatternAttr::FillToEditItemSet( *pEEItemSet, rItemSet );
     595         [ #  # ]:          0 :         rEE.SetDefaults( pEEItemSet );      // edit engine takes ownership
     596                 :            :         // create the string
     597         [ #  # ]:          0 :         rEE.SetText( *pEditObj );
     598 [ #  # ][ #  # ]:          0 :         xString = lclCreateFormattedString( rRoot, rEE, &rLinkHelper, nFlags, nMaxLen );
                 [ #  # ]
     599         [ #  # ]:          0 :         rEE.SetUpdateMode( bOldUpdateMode );
     600                 :            :     }
     601                 :            :     else
     602                 :            :     {
     603                 :            :         // unformatted cell
     604 [ #  # ][ #  # ]:          0 :         String aCellText = rEditCell.GetString();
     605 [ #  # ][ #  # ]:          0 :         xString = lclCreateFormattedString( rRoot, aCellText, pCellAttr, nFlags, nMaxLen );
         [ #  # ][ #  # ]
     606                 :            :     }
     607                 :          0 :     return xString;
     608                 :            : }
     609                 :            : 
     610                 :          0 : XclExpStringRef XclExpStringHelper::CreateString(
     611                 :            :         const XclExpRoot& rRoot, const SdrTextObj& rTextObj,
     612                 :            :         XclStrFlags nFlags, sal_uInt16 nMaxLen )
     613                 :            : {
     614                 :          0 :     XclExpStringRef xString;
     615 [ #  # ][ #  # ]:          0 :     if( const OutlinerParaObject* pParaObj = rTextObj.GetOutlinerParaObject() )
     616                 :            :     {
     617         [ #  # ]:          0 :         EditEngine& rEE = rRoot.GetDrawEditEngine();
     618         [ #  # ]:          0 :         sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
     619         [ #  # ]:          0 :         rEE.SetUpdateMode( sal_True );
     620                 :            :         // create the string
     621 [ #  # ][ #  # ]:          0 :         rEE.SetText( pParaObj->GetTextObject() );
     622 [ #  # ][ #  # ]:          0 :         xString = lclCreateFormattedString( rRoot, rEE, 0, nFlags, nMaxLen );
                 [ #  # ]
     623         [ #  # ]:          0 :         rEE.SetUpdateMode( bOldUpdateMode );
     624                 :            :         // limit formats - TODO: BIFF dependent
     625         [ #  # ]:          0 :         if( !xString->IsEmpty() )
     626                 :            :         {
     627         [ #  # ]:          0 :             xString->LimitFormatCount( EXC_MAXRECSIZE_BIFF8 / 8 - 1 );
     628         [ #  # ]:          0 :             xString->AppendTrailingFormat( EXC_FONT_APP );
     629                 :            :         }
     630                 :            :     }
     631                 :            :     else
     632                 :            :     {
     633                 :            :         OSL_FAIL( "XclExpStringHelper::CreateString - textbox without para object" );
     634                 :            :         // create BIFF dependent empty Excel string
     635 [ #  # ][ #  # ]:          0 :         xString = CreateString( rRoot, EMPTY_STRING, nFlags, nMaxLen );
         [ #  # ][ #  # ]
     636                 :            :     }
     637                 :          0 :     return xString;
     638                 :            : }
     639                 :            : 
     640                 :          0 : XclExpStringRef XclExpStringHelper::CreateString(
     641                 :            :         const XclExpRoot& rRoot, const EditTextObject& rEditObj,
     642                 :            :         XclStrFlags nFlags, sal_uInt16 nMaxLen )
     643                 :            : {
     644                 :          0 :     XclExpStringRef xString;
     645         [ #  # ]:          0 :     EditEngine& rEE = rRoot.GetDrawEditEngine();
     646         [ #  # ]:          0 :     sal_Bool bOldUpdateMode = rEE.GetUpdateMode();
     647         [ #  # ]:          0 :     rEE.SetUpdateMode( sal_True );
     648         [ #  # ]:          0 :     rEE.SetText( rEditObj );
     649 [ #  # ][ #  # ]:          0 :     xString = lclCreateFormattedString( rRoot, rEE, 0, nFlags, nMaxLen );
                 [ #  # ]
     650         [ #  # ]:          0 :     rEE.SetUpdateMode( bOldUpdateMode );
     651                 :            :     // limit formats - TODO: BIFF dependent
     652         [ #  # ]:          0 :     if( !xString->IsEmpty() )
     653                 :            :     {
     654         [ #  # ]:          0 :         xString->LimitFormatCount( EXC_MAXRECSIZE_BIFF8 / 8 - 1 );
     655         [ #  # ]:          0 :         xString->AppendTrailingFormat( EXC_FONT_APP );
     656                 :            :     }
     657                 :          0 :     return xString;
     658                 :            : }
     659                 :            : 
     660                 :          0 : sal_Int16 XclExpStringHelper::GetLeadingScriptType( const XclExpRoot& rRoot, const String& rString )
     661                 :            : {
     662                 :            :     namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
     663         [ #  # ]:          0 :     Reference< XBreakIterator > xBreakIt = rRoot.GetDoc().GetBreakIterator();
     664         [ #  # ]:          0 :     OUString aOUString( rString );
     665                 :          0 :     sal_Int32 nStrPos = 0;
     666                 :          0 :     sal_Int32 nStrLen = aOUString.getLength();
     667                 :          0 :     sal_Int16 nScript = ApiScriptType::WEAK;
     668 [ #  # ][ #  # ]:          0 :     while( (nStrPos < nStrLen) && (nScript == ApiScriptType::WEAK) )
                 [ #  # ]
     669                 :            :     {
     670 [ #  # ][ #  # ]:          0 :         nScript = xBreakIt->getScriptType( aOUString, nStrPos );
     671 [ #  # ][ #  # ]:          0 :         nStrPos = xBreakIt->endOfScript( aOUString, nStrPos, nScript );
     672                 :            :     }
     673         [ #  # ]:          0 :     return (nScript == ApiScriptType::WEAK) ? rRoot.GetDefApiScript() : nScript;
     674                 :            : }
     675                 :            : 
     676                 :            : // Header/footer conversion ===================================================
     677                 :            : 
     678                 :          0 : XclExpHFConverter::XclExpHFConverter( const XclExpRoot& rRoot ) :
     679                 :            :     XclExpRoot( rRoot ),
     680         [ #  # ]:          0 :     mrEE( rRoot.GetHFEditEngine() ),
     681         [ #  # ]:          0 :     mnTotalHeight( 0 )
     682                 :            : {
     683                 :          0 : }
     684                 :            : 
     685                 :          0 : void XclExpHFConverter::GenerateString(
     686                 :            :         const EditTextObject* pLeftObj,
     687                 :            :         const EditTextObject* pCenterObj,
     688                 :            :         const EditTextObject* pRightObj )
     689                 :            : {
     690                 :          0 :     maHFString.Erase();
     691                 :          0 :     mnTotalHeight = 0;
     692                 :          0 :     AppendPortion( pLeftObj, 'L' );
     693                 :          0 :     AppendPortion( pCenterObj, 'C' );
     694                 :          0 :     AppendPortion( pRightObj, 'R' );
     695                 :          0 : }
     696                 :            : 
     697                 :          0 : void XclExpHFConverter::AppendPortion( const EditTextObject* pTextObj, sal_Unicode cPortionCode )
     698                 :            : {
     699         [ #  # ]:          0 :     if( !pTextObj ) return;
     700                 :            : 
     701         [ #  # ]:          0 :     String aText;
     702                 :          0 :     sal_Int32 nHeight = 0;
     703 [ #  # ][ #  # ]:          0 :     SfxItemSet aItemSet( *GetDoc().GetPool(), ATTR_PATTERN_START, ATTR_PATTERN_END );
     704                 :            : 
     705                 :            :     // edit engine
     706         [ #  # ]:          0 :     sal_Bool bOldUpdateMode = mrEE.GetUpdateMode();
     707         [ #  # ]:          0 :     mrEE.SetUpdateMode( sal_True );
     708         [ #  # ]:          0 :     mrEE.SetText( *pTextObj );
     709                 :            : 
     710                 :            :     // font information
     711 [ #  # ][ #  # ]:          0 :     XclFontData aFontData, aNewData;
     712 [ #  # ][ #  # ]:          0 :     if( const XclExpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
                 [ #  # ]
     713                 :            :     {
     714         [ #  # ]:          0 :         aFontData = pFirstFont->GetFontData();
     715                 :          0 :         (aFontData.mnHeight += 10) /= 20;   // using pt here, not twips
     716                 :            :     }
     717                 :            :     else
     718                 :          0 :         aFontData.mnHeight = 10;
     719                 :            : 
     720                 :          0 :     const FontList* pFontList = 0;
     721 [ #  # ][ #  # ]:          0 :     if( SfxObjectShell* pDocShell = GetDocShell() )
     722                 :            :     {
     723         [ #  # ]:          0 :         if( const SvxFontListItem* pInfoItem = static_cast< const SvxFontListItem* >(
     724         [ #  # ]:          0 :                 pDocShell->GetItem( SID_ATTR_CHAR_FONTLIST ) ) )
     725                 :          0 :             pFontList = pInfoItem->GetFontList();
     726                 :            :     }
     727                 :            : 
     728         [ #  # ]:          0 :     sal_uInt16 nParaCount = mrEE.GetParagraphCount();
     729         [ #  # ]:          0 :     for( sal_uInt16 nPara = 0; nPara < nParaCount; ++nPara )
     730                 :            :     {
     731                 :          0 :         ESelection aSel( nPara, 0 );
     732         [ #  # ]:          0 :         String aParaText;
     733                 :          0 :         sal_Int32 nParaHeight = 0;
     734         [ #  # ]:          0 :         std::vector<sal_uInt16> aPosList;
     735         [ #  # ]:          0 :         mrEE.GetPortions( nPara, aPosList );
     736                 :            : 
     737 [ #  # ][ #  # ]:          0 :         for( std::vector<sal_uInt16>::const_iterator it( aPosList.begin() ); it != aPosList.end(); ++it )
         [ #  # ][ #  # ]
     738                 :            :         {
     739         [ #  # ]:          0 :             aSel.nEndPos = static_cast< xub_StrLen >( *it );
     740         [ #  # ]:          0 :             if( aSel.nStartPos < aSel.nEndPos )
     741                 :            :             {
     742                 :            : 
     743                 :            : // --- font attributes ---
     744                 :            : 
     745         [ #  # ]:          0 :                 Font aFont;
     746         [ #  # ]:          0 :                 aItemSet.ClearItem();
     747         [ #  # ]:          0 :                 SfxItemSet aEditSet( mrEE.GetAttribs( aSel ) );
     748         [ #  # ]:          0 :                 ScPatternAttr::GetFromEditItemSet( aItemSet, aEditSet );
     749         [ #  # ]:          0 :                 ScPatternAttr::GetFont( aFont, aItemSet, SC_AUTOCOL_RAW );
     750                 :            : 
     751                 :            :                 // font name and style
     752 [ #  # ][ #  # ]:          0 :                 aNewData.maName = XclTools::GetXclFontName( aFont.GetName() );
         [ #  # ][ #  # ]
     753 [ #  # ][ #  # ]:          0 :                 aNewData.mnWeight = (aFont.GetWeight() > WEIGHT_NORMAL) ? EXC_FONTWGHT_BOLD : EXC_FONTWGHT_NORMAL;
     754         [ #  # ]:          0 :                 aNewData.mbItalic = (aFont.GetItalic() != ITALIC_NONE);
     755         [ #  # ]:          0 :                 bool bNewFont = !(aFontData.maName == aNewData.maName);
     756                 :            :                 bool bNewStyle = (aFontData.mnWeight != aNewData.mnWeight) ||
     757 [ #  # ][ #  # ]:          0 :                                  (aFontData.mbItalic != aNewData.mbItalic);
     758 [ #  # ][ #  # ]:          0 :                 if( bNewFont || (bNewStyle && pFontList) )
                 [ #  # ]
     759                 :            :                 {
     760 [ #  # ][ #  # ]:          0 :                     aParaText.AppendAscii( "&\"" ).Append( aNewData.maName );
     761         [ #  # ]:          0 :                     if( pFontList )
     762                 :            :                     {
     763                 :            :                         FontInfo aFontInfo( pFontList->Get(
     764                 :            :                             aNewData.maName,
     765                 :            :                             (aNewData.mnWeight > EXC_FONTWGHT_NORMAL) ? WEIGHT_BOLD : WEIGHT_NORMAL,
     766 [ #  # ][ #  # ]:          0 :                             aNewData.mbItalic ? ITALIC_NORMAL : ITALIC_NONE ) );
                 [ #  # ]
     767 [ #  # ][ #  # ]:          0 :                         aNewData.maStyle = pFontList->GetStyleName( aFontInfo );
                 [ #  # ]
     768         [ #  # ]:          0 :                         if( aNewData.maStyle.Len() )
     769 [ #  # ][ #  # ]:          0 :                             aParaText.Append( ',' ).Append( aNewData.maStyle );
                 [ #  # ]
     770                 :            :                     }
     771         [ #  # ]:          0 :                     aParaText.Append( '"' );
     772                 :            :                 }
     773                 :            : 
     774                 :            :                 // height
     775                 :            :                 // is calculated wrong in ScPatternAttr::GetFromEditItemSet, because already in twips and not 100thmm
     776                 :            :                 // -> get it directly from edit engine item set
     777 [ #  # ][ #  # ]:          0 :                 aNewData.mnHeight = ulimit_cast< sal_uInt16 >( GETITEM( aEditSet, SvxFontHeightItem, EE_CHAR_FONTHEIGHT ).GetHeight() );
     778                 :          0 :                 (aNewData.mnHeight += 10) /= 20;
     779                 :          0 :                 bool bFontHtChanged = (aFontData.mnHeight != aNewData.mnHeight);
     780         [ #  # ]:          0 :                 if( bFontHtChanged )
     781 [ #  # ][ #  # ]:          0 :                     aParaText.Append( '&' ).Append( String::CreateFromInt32( aNewData.mnHeight ) );
         [ #  # ][ #  # ]
     782                 :            :                 // update maximum paragraph height, convert to twips
     783         [ #  # ]:          0 :                 nParaHeight = ::std::max< sal_Int32 >( nParaHeight, aNewData.mnHeight * 20 );
     784                 :            : 
     785                 :            :                 // underline
     786                 :          0 :                 aNewData.mnUnderline = EXC_FONTUNDERL_NONE;
     787         [ #  # ]:          0 :                 switch( aFont.GetUnderline() )
           [ #  #  #  # ]
     788                 :            :                 {
     789                 :          0 :                     case UNDERLINE_NONE:    aNewData.mnUnderline = EXC_FONTUNDERL_NONE;    break;
     790                 :          0 :                     case UNDERLINE_SINGLE:  aNewData.mnUnderline = EXC_FONTUNDERL_SINGLE;  break;
     791                 :          0 :                     case UNDERLINE_DOUBLE:  aNewData.mnUnderline = EXC_FONTUNDERL_DOUBLE;  break;
     792                 :          0 :                     default:                aNewData.mnUnderline = EXC_FONTUNDERL_SINGLE;
     793                 :            :                 }
     794         [ #  # ]:          0 :                 if( aFontData.mnUnderline != aNewData.mnUnderline )
     795                 :            :                 {
     796                 :            :                     sal_uInt8 nTmpUnderl = (aNewData.mnUnderline == EXC_FONTUNDERL_NONE) ?
     797         [ #  # ]:          0 :                         aFontData.mnUnderline : aNewData.mnUnderline;
     798 [ #  # ][ #  # ]:          0 :                     aParaText.AppendAscii( (nTmpUnderl == EXC_FONTUNDERL_SINGLE) ? "&U" : "&E" );
     799                 :            :                 }
     800                 :            : 
     801                 :            :                 // strikeout
     802         [ #  # ]:          0 :                 aNewData.mbStrikeout = (aFont.GetStrikeout() != STRIKEOUT_NONE);
     803         [ #  # ]:          0 :                 if( aFontData.mbStrikeout != aNewData.mbStrikeout )
     804         [ #  # ]:          0 :                     aParaText.AppendAscii( "&S" );
     805                 :            : 
     806                 :            :                 // super/sub script
     807         [ #  # ]:          0 :                 const SvxEscapementItem& rEscapeItem = GETITEM( aEditSet, SvxEscapementItem, EE_CHAR_ESCAPEMENT );
     808         [ #  # ]:          0 :                 aNewData.SetScEscapement( rEscapeItem.GetEsc() );
     809         [ #  # ]:          0 :                 if( aFontData.mnEscapem != aNewData.mnEscapem )
     810                 :            :                 {
     811   [ #  #  #  # ]:          0 :                     switch(aNewData.mnEscapem)
     812                 :            :                     {
     813                 :            :                         // close the previous super/sub script.
     814 [ #  # ][ #  # ]:          0 :                         case EXC_FONTESC_NONE:  aParaText.AppendAscii( (aFontData.mnEscapem == EXC_FONTESC_SUPER) ? "&X" : "&Y" ); break;
     815         [ #  # ]:          0 :                         case EXC_FONTESC_SUPER: aParaText.AppendAscii( "&X" );  break;
     816         [ #  # ]:          0 :                         case EXC_FONTESC_SUB:   aParaText.AppendAscii( "&Y" );  break;
     817                 :          0 :                         default: break;
     818                 :            :                     }
     819                 :            :                 }
     820                 :            : 
     821         [ #  # ]:          0 :                 aFontData = aNewData;
     822                 :            : 
     823                 :            : // --- text content or text fields ---
     824                 :            : 
     825                 :            :                 const SfxPoolItem* pItem;
     826 [ #  # ][ #  # ]:          0 :                 if( (aSel.nStartPos + 1 == aSel.nEndPos) &&     // fields are single characters
                 [ #  # ]
     827         [ #  # ]:          0 :                     (aEditSet.GetItemState( EE_FEATURE_FIELD, false, &pItem ) == SFX_ITEM_SET) )
     828                 :            :                 {
     829         [ #  # ]:          0 :                     if( const SvxFieldData* pFieldData = static_cast< const SvxFieldItem* >( pItem )->GetField() )
     830                 :            :                     {
     831 [ #  # ][ #  # ]:          0 :                         if( pFieldData->ISA( SvxPageField ) )
                 [ #  # ]
     832         [ #  # ]:          0 :                             aParaText.AppendAscii( "&P" );
     833 [ #  # ][ #  # ]:          0 :                         else if( pFieldData->ISA( SvxPagesField ) )
                 [ #  # ]
     834         [ #  # ]:          0 :                             aParaText.AppendAscii( "&N" );
     835 [ #  # ][ #  # ]:          0 :                         else if( pFieldData->ISA( SvxDateField ) )
                 [ #  # ]
     836         [ #  # ]:          0 :                             aParaText.AppendAscii( "&D" );
     837 [ #  # ][ #  # ]:          0 :                         else if( pFieldData->ISA( SvxTimeField ) || pFieldData->ISA( SvxExtTimeField ) )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     838         [ #  # ]:          0 :                             aParaText.AppendAscii( "&T" );
     839 [ #  # ][ #  # ]:          0 :                         else if( pFieldData->ISA( SvxTableField ) )
                 [ #  # ]
     840         [ #  # ]:          0 :                             aParaText.AppendAscii( "&A" );
     841 [ #  # ][ #  # ]:          0 :                         else if( pFieldData->ISA( SvxFileField ) )  // title -> file name
                 [ #  # ]
     842         [ #  # ]:          0 :                             aParaText.AppendAscii( "&F" );
     843 [ #  # ][ #  # ]:          0 :                         else if( const SvxExtFileField* pFileField = PTR_CAST( SvxExtFileField, pFieldData ) )
         [ #  # ][ #  # ]
                 [ #  # ]
     844                 :            :                         {
     845   [ #  #  #  # ]:          0 :                             switch( pFileField->GetFormat() )
     846                 :            :                             {
     847                 :            :                                 case SVXFILEFORMAT_NAME_EXT:
     848                 :            :                                 case SVXFILEFORMAT_NAME:
     849         [ #  # ]:          0 :                                     aParaText.AppendAscii( "&F" );
     850                 :          0 :                                 break;
     851                 :            :                                 case SVXFILEFORMAT_PATH:
     852         [ #  # ]:          0 :                                     aParaText.AppendAscii( "&Z" );
     853                 :          0 :                                 break;
     854                 :            :                                 case SVXFILEFORMAT_FULLPATH:
     855         [ #  # ]:          0 :                                     aParaText.AppendAscii( "&Z&F" );
     856                 :          0 :                                 break;
     857                 :            :                                 default:
     858                 :            :                                     OSL_FAIL( "XclExpHFConverter::AppendPortion - unknown file field" );
     859                 :            :                             }
     860                 :            :                         }
     861                 :            :                     }
     862                 :            :                 }
     863                 :            :                 else
     864                 :            :                 {
     865         [ #  # ]:          0 :                     String aPortionText( mrEE.GetText( aSel ) );
     866 [ #  # ][ #  # ]:          0 :                     aPortionText.SearchAndReplaceAll( rtl::OUString('&'), rtl::OUString("&&") );
         [ #  # ][ #  # ]
                 [ #  # ]
     867                 :            :                     // #i17440# space between font height and numbers in text
     868 [ #  # ][ #  # ]:          0 :                     if( bFontHtChanged && aParaText.Len() && aPortionText.Len() )
         [ #  # ][ #  # ]
     869                 :            :                     {
     870                 :          0 :                         sal_Unicode cLast = aParaText.GetChar( aParaText.Len() - 1 );
     871                 :          0 :                         sal_Unicode cFirst = aPortionText.GetChar( 0 );
     872 [ #  # ][ #  # ]:          0 :                         if( ('0' <= cLast) && (cLast <= '9') && ('0' <= cFirst) && (cFirst <= '9') )
         [ #  # ][ #  # ]
     873         [ #  # ]:          0 :                             aParaText.Append( ' ' );
     874                 :            :                     }
     875 [ #  # ][ #  # ]:          0 :                     aParaText.Append( aPortionText );
     876 [ #  # ][ #  # ]:          0 :                 }
     877                 :            :             }
     878                 :            : 
     879                 :          0 :             aSel.nStartPos = aSel.nEndPos;
     880                 :            :         }
     881                 :            : 
     882         [ #  # ]:          0 :         ScGlobal::AddToken( aText, aParaText, '\n' );
     883         [ #  # ]:          0 :         if( nParaHeight == 0 )
     884                 :          0 :             nParaHeight = aFontData.mnHeight * 20;  // points -> twips
     885                 :          0 :         nHeight += nParaHeight;
     886         [ #  # ]:          0 :     }
     887                 :            : 
     888         [ #  # ]:          0 :     mrEE.SetUpdateMode( bOldUpdateMode );
     889                 :            : 
     890         [ #  # ]:          0 :     if( aText.Len() )
     891                 :            :     {
     892 [ #  # ][ #  # ]:          0 :         maHFString.Append( '&' ).Append( cPortionCode ).Append( aText );
                 [ #  # ]
     893         [ #  # ]:          0 :         mnTotalHeight = ::std::max( mnTotalHeight, nHeight );
     894 [ #  # ][ #  # ]:          0 :     }
         [ #  # ][ #  # ]
     895                 :            : }
     896                 :            : 
     897                 :            : // URL conversion =============================================================
     898                 :            : 
     899                 :            : namespace {
     900                 :            : 
     901                 :            : /** Encodes special parts of the URL, i.e. directory separators and volume names.
     902                 :            :     @param pTableName  Pointer to a table name to be encoded in this URL, or 0. */
     903                 :          0 : rtl::OUString lclEncodeDosUrl(
     904                 :            :     XclBiff eBiff, const rtl::OUString& rUrl, const rtl::OUString& rBase, const rtl::OUString* pTableName)
     905                 :            : {
     906                 :          0 :     rtl::OUStringBuffer aBuf;
     907                 :            : 
     908         [ #  # ]:          0 :     if (!rUrl.isEmpty())
     909                 :            :     {
     910                 :          0 :         rtl::OUString aOldUrl = rUrl;
     911         [ #  # ]:          0 :         aBuf.append(EXC_URLSTART_ENCODED);
     912                 :            : 
     913 [ #  # ][ #  # ]:          0 :         if ( aOldUrl.getLength() > 2 && aOldUrl.copy(0,2) == "\\\\" )
         [ #  # ][ #  # ]
     914                 :            :         {
     915                 :            :             // UNC
     916 [ #  # ][ #  # ]:          0 :             aBuf.append(EXC_URL_DOSDRIVE).append(sal_Unicode('@'));
     917                 :          0 :             aOldUrl = aOldUrl.copy(2);
     918                 :            :         }
     919 [ #  # ][ #  # ]:          0 :         else if ( aOldUrl.getLength() > 2 && aOldUrl.copy(1,2) == ":\\" )
         [ #  # ][ #  # ]
     920                 :            :         {
     921                 :            :             // drive letter
     922         [ #  # ]:          0 :             sal_Unicode cThisDrive = rBase.isEmpty() ? ' ' : rBase.getStr()[0];
     923                 :          0 :             sal_Unicode cDrive = aOldUrl.getStr()[0];
     924         [ #  # ]:          0 :             if (cThisDrive == cDrive)
     925                 :            :                 // This document and the referenced document are under the same drive.
     926         [ #  # ]:          0 :                 aBuf.append(EXC_URL_DRIVEROOT);
     927                 :            :             else
     928 [ #  # ][ #  # ]:          0 :                 aBuf.append(EXC_URL_DOSDRIVE).append(cDrive);
     929                 :          0 :             aOldUrl = aOldUrl.copy(3);
     930                 :            :         }
     931                 :            : 
     932                 :            :         // directories
     933                 :          0 :         sal_Int32 nPos = -1;
     934         [ #  # ]:          0 :         while((nPos = aOldUrl.indexOf('\\')) != -1)
     935                 :            :         {
     936         [ #  # ]:          0 :             if ( aOldUrl.copy(0,2) == ".." )
     937                 :            :                 // parent dir (NOTE: the MS-XLS spec doesn't mention this, and
     938                 :            :                 // Excel seems confused by this token).
     939         [ #  # ]:          0 :                 aBuf.append(EXC_URL_PARENTDIR);
     940                 :            :             else
     941 [ #  # ][ #  # ]:          0 :                 aBuf.append(aOldUrl.copy(0,nPos)).append(EXC_URL_SUBDIR);
     942                 :            : 
     943                 :          0 :             aOldUrl = aOldUrl.copy(nPos + 1);
     944                 :            :         }
     945                 :            : 
     946                 :            :         // file name
     947         [ #  # ]:          0 :         if (pTableName)    // enclose file name in brackets if table name follows
     948 [ #  # ][ #  # ]:          0 :             aBuf.append(sal_Unicode('[')).append(aOldUrl).append(sal_Unicode(']'));
                 [ #  # ]
     949                 :            :         else
     950         [ #  # ]:          0 :             aBuf.append(aOldUrl);
     951                 :            :     }
     952                 :            :     else    // empty URL -> self reference
     953                 :            :     {
     954      [ #  #  # ]:          0 :         switch( eBiff )
     955                 :            :         {
     956                 :            :             case EXC_BIFF5:
     957 [ #  # ][ #  # ]:          0 :                 aBuf.append(pTableName ? EXC_URLSTART_SELFENCODED : EXC_URLSTART_SELF);
     958                 :          0 :             break;
     959                 :            :             case EXC_BIFF8:
     960                 :            :                 DBG_ASSERT( pTableName, "lclEncodeDosUrl - sheet name required for BIFF8" );
     961         [ #  # ]:          0 :                 aBuf.append(EXC_URLSTART_SELF);
     962                 :          0 :             break;
     963                 :            :             default:
     964                 :            :                 DBG_ERROR_BIFF();
     965                 :            :         }
     966                 :            :     }
     967                 :            : 
     968                 :            :     // table name
     969         [ #  # ]:          0 :     if (pTableName)
     970         [ #  # ]:          0 :         aBuf.append(*pTableName);
     971                 :            : 
     972         [ #  # ]:          0 :     return aBuf.makeStringAndClear();
     973                 :            : }
     974                 :            : 
     975                 :            : } // namespace
     976                 :            : 
     977                 :            : // ----------------------------------------------------------------------------
     978                 :            : 
     979                 :          0 : rtl::OUString XclExpUrlHelper::EncodeUrl( const XclExpRoot& rRoot, const rtl::OUString& rAbsUrl, const rtl::OUString* pTableName )
     980                 :            : {
     981 [ #  # ][ #  # ]:          0 :     rtl::OUString aDosUrl = INetURLObject(rAbsUrl).getFSysPath(INetURLObject::FSYS_DOS);
                 [ #  # ]
     982 [ #  # ][ #  # ]:          0 :     rtl::OUString aDosBase = INetURLObject(rRoot.GetBasePath()).getFSysPath(INetURLObject::FSYS_DOS);
         [ #  # ][ #  # ]
     983         [ #  # ]:          0 :     return lclEncodeDosUrl(rRoot.GetBiff(), aDosUrl, aDosBase, pTableName);
     984                 :            : }
     985                 :            : 
     986                 :          0 : rtl::OUString XclExpUrlHelper::EncodeDde( const rtl::OUString& rApplic, const rtl::OUString& rTopic )
     987                 :            : {
     988                 :          0 :     rtl::OUStringBuffer aBuf;
     989 [ #  # ][ #  # ]:          0 :     aBuf.append(rApplic).append(EXC_DDE_DELIM).append(rTopic);
                 [ #  # ]
     990         [ #  # ]:          0 :     return aBuf.makeStringAndClear();
     991                 :            : }
     992                 :            : 
     993                 :            : // Cached Value Lists =========================================================
     994                 :            : 
     995                 :          0 : XclExpCachedMatrix::XclExpCachedMatrix( const ScMatrix& rMatrix )
     996                 :          0 :     : mrMatrix( rMatrix )
     997                 :            : {
     998                 :          0 :     mrMatrix.IncRef();
     999                 :          0 : }
    1000                 :          0 : XclExpCachedMatrix::~XclExpCachedMatrix()
    1001                 :            : {
    1002                 :          0 :     mrMatrix.DecRef();
    1003                 :          0 : }
    1004                 :            : 
    1005                 :          0 : void XclExpCachedMatrix::GetDimensions( SCSIZE & nCols, SCSIZE & nRows ) const
    1006                 :            : {
    1007                 :          0 :     mrMatrix.GetDimensions( nCols, nRows );
    1008                 :            : 
    1009                 :            :     OSL_ENSURE( nCols && nRows, "XclExpCachedMatrix::GetDimensions - empty matrix" );
    1010                 :            :     OSL_ENSURE( nCols <= 256, "XclExpCachedMatrix::GetDimensions - too many columns" );
    1011                 :          0 : }
    1012                 :            : 
    1013                 :          0 : sal_Size XclExpCachedMatrix::GetSize() const
    1014                 :            : {
    1015                 :            :     SCSIZE nCols, nRows;
    1016                 :            : 
    1017         [ #  # ]:          0 :     GetDimensions( nCols, nRows );
    1018                 :            : 
    1019                 :            :     /*  The returned size may be wrong if the matrix contains strings. The only
    1020                 :            :         effect is that the export stream has to update a wrong record size which is
    1021                 :            :         faster than to iterate through all cached values and calculate their sizes. */
    1022                 :          0 :     return 3 + 9 * (nCols * nRows);
    1023                 :            : }
    1024                 :            : 
    1025                 :          0 : void XclExpCachedMatrix::Save( XclExpStream& rStrm ) const
    1026                 :            : {
    1027                 :            :     SCSIZE nCols, nRows;
    1028                 :            : 
    1029         [ #  # ]:          0 :     GetDimensions( nCols, nRows );
    1030                 :            : 
    1031         [ #  # ]:          0 :     if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
    1032                 :            :         // in BIFF2-BIFF7: 256 columns represented by 0 columns
    1033 [ #  # ][ #  # ]:          0 :         rStrm << static_cast< sal_uInt8 >( nCols ) << static_cast< sal_uInt16 >( nRows );
    1034                 :            :     else
    1035                 :            :         // in BIFF8: columns and rows decreaed by 1
    1036 [ #  # ][ #  # ]:          0 :         rStrm << static_cast< sal_uInt8 >( nCols - 1 ) << static_cast< sal_uInt16 >( nRows - 1 );
    1037                 :            : 
    1038         [ #  # ]:          0 :     for( SCSIZE nRow = 0; nRow < nRows; ++nRow )
    1039                 :            :     {
    1040         [ #  # ]:          0 :         for( SCSIZE nCol = 0; nCol < nCols; ++nCol )
    1041                 :            :         {
    1042         [ #  # ]:          0 :             ScMatrixValue nMatVal = mrMatrix.Get( nCol, nRow );
    1043                 :            : 
    1044         [ #  # ]:          0 :             if( SC_MATVAL_EMPTY == nMatVal.nType )
    1045                 :            :             {
    1046         [ #  # ]:          0 :                 rStrm.SetSliceSize( 9 );
    1047         [ #  # ]:          0 :                 rStrm << EXC_CACHEDVAL_EMPTY;
    1048         [ #  # ]:          0 :                 rStrm.WriteZeroBytes( 8 );
    1049                 :            :             }
    1050         [ #  # ]:          0 :             else if( ScMatrix::IsNonValueType( nMatVal.nType ) )
    1051                 :            :             {
    1052         [ #  # ]:          0 :                 XclExpString aStr( nMatVal.GetString(), EXC_STR_DEFAULT );
    1053         [ #  # ]:          0 :                 rStrm.SetSliceSize( 6 );
    1054 [ #  # ][ #  # ]:          0 :                 rStrm << EXC_CACHEDVAL_STRING << aStr;
    1055                 :            :             }
    1056         [ #  # ]:          0 :             else if( SC_MATVAL_BOOLEAN == nMatVal.nType )
    1057                 :            :             {
    1058                 :          0 :                 sal_Int8 nBool = nMatVal.GetBoolean();
    1059         [ #  # ]:          0 :                 rStrm.SetSliceSize( 9 );
    1060 [ #  # ][ #  # ]:          0 :                 rStrm << EXC_CACHEDVAL_BOOL << nBool;
    1061         [ #  # ]:          0 :                 rStrm.WriteZeroBytes( 7 );
    1062                 :            :             }
    1063         [ #  # ]:          0 :             else if( sal_uInt16 nScError = nMatVal.GetError() )
    1064                 :            :             {
    1065         [ #  # ]:          0 :                 sal_Int8 nError ( XclTools::GetXclErrorCode( nScError ) );
    1066         [ #  # ]:          0 :                 rStrm.SetSliceSize( 9 );
    1067 [ #  # ][ #  # ]:          0 :                 rStrm << EXC_CACHEDVAL_ERROR << nError;
    1068         [ #  # ]:          0 :                 rStrm.WriteZeroBytes( 7 );
    1069                 :            :             }
    1070                 :            :             else
    1071                 :            :             {
    1072         [ #  # ]:          0 :                 rStrm.SetSliceSize( 9 );
    1073 [ #  # ][ #  # ]:          0 :                 rStrm << EXC_CACHEDVAL_DOUBLE << nMatVal.fVal;
    1074                 :            :             }
    1075                 :          0 :         }
    1076                 :            :     }
    1077 [ +  - ][ +  - ]:         24 : }
    1078                 :            : 
    1079                 :            : // ============================================================================
    1080                 :            : 
    1081                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10