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

Generated by: LCOV version 1.10