LCOV - code coverage report
Current view: top level - sc/source/filter/excel - xehelper.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 486 0.0 %
Date: 2014-04-14 Functions: 0 49 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10