blob: 382709e7dc3c07dde3c54aeed6714f613fa26ec9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
#include "xihelper.hxx"
#include <svl/itemset.hxx>
#include <editeng/editobj.hxx>
#include <tools/urlobj.hxx>
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <editeng/flditem.hxx>
#include "document.hxx"
#include "cell.hxx"
#include "rangelst.hxx"
#include "editutil.hxx"
#include "attrib.hxx"
#include "xltracer.hxx"
#include "xistream.hxx"
#include "xistyle.hxx"
#include "excform.hxx"
// Excel->Calc cell address/range conversion ==================================
namespace {
/** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt16 nXclRow, SCTAB nScTab )
{
rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
rScPos.SetTab( nScTab );
}
} // namespace
// ----------------------------------------------------------------------------
XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) :
XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() )
{
}
// cell address ---------------------------------------------------------------
bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn )
{
bool bValidCol = rXclPos.mnCol <= mnMaxCol;
bool bValidRow = rXclPos.mnRow <= mnMaxRow;
bool bValid = bValidCol && bValidRow;
if( !bValid && bWarn )
{
mbColTrunc |= !bValidCol;
mbRowTrunc |= !bValidRow;
mrTracer.TraceInvalidAddress( ScAddress(
static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos );
}
return bValid;
}
bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
{
bool bValid = CheckAddress( rXclPos, bWarn );
if( bValid )
lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
return bValid;
}
ScAddress XclImpAddressConverter::CreateValidAddress(
const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
{
ScAddress aScPos( ScAddress::UNINITIALIZED );
if( !ConvertAddress( aScPos, rXclPos, nScTab, bWarn ) )
{
aScPos.SetCol( static_cast< SCCOL >( ::std::min( rXclPos.mnCol, mnMaxCol ) ) );
aScPos.SetRow( static_cast< SCROW >( ::std::min( rXclPos.mnRow, mnMaxRow ) ) );
aScPos.SetTab( limit_cast< SCTAB >( nScTab, 0, maMaxPos.Tab() ) );
}
return aScPos;
}
// cell range -----------------------------------------------------------------
bool XclImpAddressConverter::CheckRange( const XclRange& rXclRange, bool bWarn )
{
return CheckAddress( rXclRange.maFirst, bWarn ) && CheckAddress( rXclRange.maLast, bWarn );
}
bool XclImpAddressConverter::ConvertRange( ScRange& rScRange,
const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
{
// check start position
bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn );
if( bValidStart )
{
lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 );
// check & correct end position
sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol;
sal_uInt16 nXclRow2 = rXclRange.maLast.mnRow;
if( !CheckAddress( rXclRange.maLast, bWarn ) )
{
nXclCol2 = ::std::min( nXclCol2, mnMaxCol );
nXclRow2 = ::std::min( nXclRow2, mnMaxRow );
}
lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 );
}
return bValidStart;
}
//UNUSED2009-05 ScRange XclImpAddressConverter::CreateValidRange(
//UNUSED2009-05 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
//UNUSED2009-05 {
//UNUSED2009-05 return ScRange(
//UNUSED2009-05 CreateValidAddress( rXclRange.maFirst, nScTab1, bWarn ),
//UNUSED2009-05 CreateValidAddress( rXclRange.maLast, nScTab2, bWarn ) );
//UNUSED2009-05 }
// cell range list ------------------------------------------------------------
//UNUSED2009-05 bool XclImpAddressConverter::CheckRangeList( const XclRangeList& rXclRanges, bool bWarn )
//UNUSED2009-05 {
//UNUSED2009-05 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
//UNUSED2009-05 if( !CheckRange( *aIt, bWarn ) )
//UNUSED2009-05 return false;
//UNUSED2009-05 return true;
//UNUSED2009-05 }
void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges,
const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn )
{
rScRanges.RemoveAll();
for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
{
ScRange aScRange( ScAddress::UNINITIALIZED );
if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) )
rScRanges.Append( aScRange );
}
}
// String->EditEngine conversion ==============================================
namespace {
EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot,
const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex )
{
EditTextObject* pTextObj = 0;
const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer();
const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex );
bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement();
if( rString.IsRich() || bFirstEscaped )
{
const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
const XclFormatRunVec& rFormats = rString.GetFormats();
ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ?
static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine();
rEE.SetText( rString.GetText() );
SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
if( bFirstEscaped )
rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) );
ESelection aSelection;
XclFormatRun aNextRun;
XclFormatRunVec::const_iterator aIt = rFormats.begin();
XclFormatRunVec::const_iterator aEnd = rFormats.end();
if( aIt != aEnd )
aNextRun = *aIt++;
else
aNextRun.mnChar = 0xFFFF;
xub_StrLen nLen = rString.GetText().Len();
for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar )
{
// reached new different formatted text portion
if( nChar >= aNextRun.mnChar )
{
// send items to edit engine
rEE.QuickSetAttribs( aItemSet, aSelection );
// start new item set
aItemSet.ClearItem();
rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx );
// read new formatting information
if( aIt != aEnd )
aNextRun = *aIt++;
else
aNextRun.mnChar = 0xFFFF;
// reset selection start to current position
aSelection.nStartPara = aSelection.nEndPara;
aSelection.nStartPos = aSelection.nEndPos;
}
// set end of selection to current position
if( rString.GetText().GetChar( nChar ) == '\n' )
{
++aSelection.nEndPara;
aSelection.nEndPos = 0;
}
else
++aSelection.nEndPos;
}
// send items of last text portion to edit engine
rEE.QuickSetAttribs( aItemSet, aSelection );
pTextObj = rEE.CreateTextObject();
}
return pTextObj;
}
} // namespace
EditTextObject* XclImpStringHelper::CreateTextObject(
const XclImpRoot& rRoot, const XclImpString& rString )
{
return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 );
}
//UNUSED2009-05 EditTextObject* XclImpStringHelper::CreateNoteObject(
//UNUSED2009-05 const XclImpRoot& rRoot, const XclImpString& rString )
//UNUSED2009-05 {
//UNUSED2009-05 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_NOTE, 0 );
//UNUSED2009-05 }
ScBaseCell* XclImpStringHelper::CreateCell(
const XclImpRoot& rRoot, const XclImpString& rString, sal_uInt16 nXFIndex )
{
ScBaseCell* pCell = 0;
if( rString.GetText().Len() )
{
::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
ScDocument& rDoc = rRoot.GetDoc();
if( pTextObj.get() )
// ScEditCell creates own copy of text object
pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
else
pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
}
return pCell;
}
// Header/footer conversion ===================================================
XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
mnHeight( 0 ),
mnMaxLineHt( 0 )
{
maSel.nStartPara = maSel.nEndPara = 0;
maSel.nStartPos = maSel.nEndPos = 0;
}
// ----------------------------------------------------------------------------
XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
XclImpRoot( rRoot ),
mrEE( rRoot.GetHFEditEngine() ),
mxFontData( new XclFontData ),
meCurrObj( EXC_HF_CENTER )
{
}
XclImpHFConverter::~XclImpHFConverter()
{
}
void XclImpHFConverter::ParseString( const String& rHFString )
{
// edit engine objects
mrEE.SetText( EMPTY_STRING );
maInfos.clear();
maInfos.resize( EXC_HF_PORTION_COUNT );
meCurrObj = EXC_HF_CENTER;
// parser temporaries
maCurrText.Erase();
String aReadFont; // current font name
String aReadStyle; // current font style
sal_uInt16 nReadHeight = 0; // current font height
ResetFontData();
/** State of the parser. */
enum XclHFParserState
{
xlPSText, /// Read text, search for functions.
xlPSFunc, /// Read function (token following a '&').
xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"').
xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit).
} eState = xlPSText;
const sal_Unicode* pChar = rHFString.GetBuffer();
const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char
while( *pChar )
{
switch( eState )
{
// --- read text character ---
case xlPSText:
{
switch( *pChar )
{
case '&': // new command
InsertText();
eState = xlPSFunc;
break;
case '\n': // line break
InsertText();
InsertLineBreak();
break;
default:
maCurrText += *pChar;
}
}
break;
// --- read control sequence ---
case xlPSFunc:
{
eState = xlPSText;
switch( *pChar )
{
case '&': maCurrText += '&'; break; // the '&' character
case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name
case 'Z': // file path
InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name
if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') )
{
// &Z&F found - ignore the &F part
pChar += 2;
}
break;
case 'F': // file name
InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
break;
case 'U': // underline
SetAttribs();
mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
break;
case 'E': // double underline
SetAttribs();
mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
break;
case 'S': // strikeout
SetAttribs();
mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
break;
case 'X': // superscript
SetAttribs();
mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
break;
case 'Y': // subsrcipt
SetAttribs();
mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
EXC_FONTESC_NONE : EXC_FONTESC_SUB;
break;
case '\"': // font name
aReadFont.Erase();
aReadStyle.Erase();
eState = xlPSFont;
break;
default:
if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
{
nReadHeight = *pChar - '0';
eState = xlPSHeight;
}
}
}
break;
// --- read font name ---
case xlPSFont:
{
switch( *pChar )
{
case '\"':
--pChar;
// run through
case ',':
eState = xlPSFontStyle;
break;
default:
aReadFont += *pChar;
}
}
break;
// --- read font style ---
case xlPSFontStyle:
{
switch( *pChar )
{
case '\"':
SetAttribs();
if( aReadFont.Len() )
mxFontData->maName = aReadFont;
mxFontData->maStyle = aReadStyle;
eState = xlPSText;
break;
default:
aReadStyle += *pChar;
}
}
break;
// --- read font height ---
case xlPSHeight:
{
if( ('0' <= *pChar) && (*pChar <= '9') )
{
if( nReadHeight != 0xFFFF )
{
nReadHeight *= 10;
nReadHeight += (*pChar - '0');
if( nReadHeight > 1600 ) // max 1600pt = 32000twips
nReadHeight = 0xFFFF;
}
}
else
{
if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
{
SetAttribs();
mxFontData->mnHeight = nReadHeight * 20;
}
--pChar;
eState = xlPSText;
}
}
break;
}
++pChar;
}
// finalize
CreateCurrObject();
maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
}
void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
{
ScPageHFItem aHFItem( nWhichId );
if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
rItemSet.Put( aHFItem );
}
sal_Int32 XclImpHFConverter::GetTotalHeight() const
{
return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
}
// private --------------------------------------------------------------------
sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
{
sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
}
sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
{
return GetMaxLineHeight( meCurrObj );
}
void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
{
sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
}
void XclImpHFConverter::UpdateCurrMaxLineHeight()
{
UpdateMaxLineHeight( meCurrObj );
}
void XclImpHFConverter::SetAttribs()
{
ESelection& rSel = GetCurrSel();
if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
{
SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
XclImpFont aFont( GetRoot(), *mxFontData );
aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
mrEE.QuickSetAttribs( aItemSet, rSel );
rSel.nStartPara = rSel.nEndPara;
rSel.nStartPos = rSel.nEndPos;
}
}
void XclImpHFConverter::ResetFontData()
{
if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
*mxFontData = pFirstFont->GetFontData();
else
{
mxFontData->Clear();
mxFontData->mnHeight = 200;
}
}
void XclImpHFConverter::InsertText()
{
if( maCurrText.Len() )
{
ESelection& rSel = GetCurrSel();
mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
rSel.nEndPos = rSel.nEndPos + maCurrText.Len();
maCurrText.Erase();
UpdateCurrMaxLineHeight();
}
}
void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
{
ESelection& rSel = GetCurrSel();
mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
++rSel.nEndPos;
UpdateCurrMaxLineHeight();
}
void XclImpHFConverter::InsertLineBreak()
{
ESelection& rSel = GetCurrSel();
mrEE.QuickInsertText( String( '\n' ), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
++rSel.nEndPara;
rSel.nEndPos = 0;
GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
GetCurrInfo().mnMaxLineHt = 0;
}
void XclImpHFConverter::CreateCurrObject()
{
InsertText();
SetAttribs();
GetCurrObj().reset( mrEE.CreateTextObject() );
}
void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
{
if( eNew != meCurrObj )
{
CreateCurrObject();
meCurrObj = eNew;
if( GetCurrObj().get() )
mrEE.SetText( *GetCurrObj() );
else
mrEE.SetText( EMPTY_STRING );
ResetFontData();
}
}
// URL conversion =============================================================
namespace {
void lclAppendUrlChar( String& rUrl, sal_Unicode cChar )
{
// #126855# encode special characters
switch( cChar )
{
case '#': rUrl.AppendAscii( "%23" ); break;
case '%': rUrl.AppendAscii( "%25" ); break;
default: rUrl.Append( cChar );
}
}
} // namespace
void XclImpUrlHelper::DecodeUrl(
String& rUrl, String& rTabName, bool& rbSameWb,
const XclImpRoot& rRoot, const String& rEncodedUrl )
{
enum
{
xlUrlInit, /// Initial state, read string mode character.
xlUrlPath, /// Read URL path.
xlUrlFileName, /// Read file name.
xlUrlSheetName, /// Read sheet name.
xlUrlRaw /// Raw mode. No control characters will occur.
} eState = xlUrlInit;
bool bEncoded = true;
rbSameWb = false;
sal_Unicode cCurrDrive = 0;
String aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
if( (aDosBase.Len() > 2) && aDosBase.EqualsAscii( ":\\", 1, 2 ) )
cCurrDrive = aDosBase.GetChar( 0 );
const sal_Unicode* pChar = rEncodedUrl.GetBuffer();
while( *pChar )
{
switch( eState )
{
// --- first character ---
case xlUrlInit:
{
switch( *pChar )
{
case EXC_URLSTART_ENCODED:
eState = xlUrlPath;
break;
case EXC_URLSTART_SELF:
case EXC_URLSTART_SELFENCODED:
rbSameWb = true;
eState = xlUrlSheetName;
break;
case '[':
bEncoded = false;
eState = xlUrlFileName;
break;
default:
bEncoded = false;
lclAppendUrlChar( rUrl, *pChar );
eState = xlUrlPath;
}
}
break;
// --- URL path ---
case xlUrlPath:
{
switch( *pChar )
{
case EXC_URL_DOSDRIVE:
{
if( *(pChar + 1) )
{
++pChar;
if( *pChar == '@' )
rUrl.AppendAscii( "\\\\" );
else
{
lclAppendUrlChar( rUrl, *pChar );
rUrl.AppendAscii( ":\\" );
}
}
else
rUrl.AppendAscii( "<NULL-DRIVE!>" );
}
break;
case EXC_URL_DRIVEROOT:
if( cCurrDrive )
{
lclAppendUrlChar( rUrl, cCurrDrive );
rUrl.Append( ':' );
}
// run through
case EXC_URL_SUBDIR:
if( bEncoded )
rUrl.Append( '\\' );
else // control character in raw name -> DDE link
{
rUrl.Append( EXC_DDE_DELIM );
eState = xlUrlRaw;
}
break;
case EXC_URL_PARENTDIR:
rUrl.AppendAscii( "..\\" );
break;
case EXC_URL_RAW:
{
if( *(pChar + 1) )
{
xub_StrLen nLen = *++pChar;
for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
lclAppendUrlChar( rUrl, *++pChar );
// rUrl.Append( ':' );
}
}
break;
case '[':
eState = xlUrlFileName;
break;
default:
lclAppendUrlChar( rUrl, *pChar );
}
}
break;
// --- file name ---
case xlUrlFileName:
{
switch( *pChar )
{
case ']': eState = xlUrlSheetName; break;
default: lclAppendUrlChar( rUrl, *pChar );
}
}
break;
// --- sheet name ---
case xlUrlSheetName:
rTabName.Append( *pChar );
break;
// --- raw read mode ---
case xlUrlRaw:
lclAppendUrlChar( rUrl, *pChar );
break;
}
++pChar;
}
}
void XclImpUrlHelper::DecodeUrl(
String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl )
{
String aTabName;
DecodeUrl( rUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
DBG_ASSERT( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
}
bool XclImpUrlHelper::DecodeLink( String& rApplic, String& rTopic, const String rEncUrl )
{
xub_StrLen nPos = rEncUrl.Search( EXC_DDE_DELIM );
if( (nPos != STRING_NOTFOUND) && (0 < nPos) && (nPos + 1 < rEncUrl.Len()) )
{
rApplic = rEncUrl.Copy( 0, nPos );
rTopic = rEncUrl.Copy( nPos + 1 );
return true;
}
return false;
}
// Cached Values ==============================================================
XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
mfValue( 0.0 ),
mnBoolErr( 0 )
{
rStrm >> mnType;
switch( mnType )
{
case EXC_CACHEDVAL_EMPTY:
rStrm.Ignore( 8 );
break;
case EXC_CACHEDVAL_DOUBLE:
rStrm >> mfValue;
break;
case EXC_CACHEDVAL_STRING:
mxStr.reset( new String( rStrm.ReadUniString() ) );
break;
case EXC_CACHEDVAL_BOOL:
case EXC_CACHEDVAL_ERROR:
{
double fVal;
rStrm >> mnBoolErr;
rStrm.Ignore( 7 );
const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
if( pScTokArr )
mxTokArr.reset( pScTokArr->Clone() );
}
break;
default:
DBG_ERRORFILE( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
}
}
XclImpCachedValue::~XclImpCachedValue()
{
}
sal_uInt16 XclImpCachedValue::GetScError() const
{
return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
}
// Matrix Cached Values ==============================================================
XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
mnScCols( 0 ),
mnScRows( 0 )
{
mnScCols = rStrm.ReaduInt8();
mnScRows = rStrm.ReaduInt16();
if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
{
// in BIFF2-BIFF7: 256 columns represented by 0 columns
if( mnScCols == 0 )
mnScCols = 256;
}
else
{
// in BIFF8: columns and rows decreaed by 1
++mnScCols;
++mnScRows;
}
for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
maValueList.Append( new XclImpCachedValue( rStrm ) );
}
XclImpCachedMatrix::~XclImpCachedMatrix()
{
}
ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
{
ScMatrixRef xScMatrix;
DBG_ASSERT( mnScCols * mnScRows == maValueList.Count(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.Count() )
{
xScMatrix = new ScMatrix( mnScCols, mnScRows );
const XclImpCachedValue* pValue = maValueList.First();
for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
{
for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
{
switch( pValue->GetType() )
{
case EXC_CACHEDVAL_EMPTY:
// Excel shows 0.0 here, not an empty cell
xScMatrix->PutEmpty( nScCol, nScRow );
break;
case EXC_CACHEDVAL_DOUBLE:
xScMatrix->PutDouble( pValue->GetValue(), nScCol, nScRow );
break;
case EXC_CACHEDVAL_STRING:
xScMatrix->PutString( pValue->GetString(), nScCol, nScRow );
break;
case EXC_CACHEDVAL_BOOL:
xScMatrix->PutBoolean( pValue->GetBool(), nScCol, nScRow );
break;
case EXC_CACHEDVAL_ERROR:
xScMatrix->PutError( pValue->GetScError(), nScCol, nScRow );
break;
default:
DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
xScMatrix->PutEmpty( nScCol, nScRow );
}
pValue = maValueList.Next();
}
}
}
return xScMatrix;
}
// ============================================================================