1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xihelper.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include "xihelper.hxx"
34 #include <svtools/itemset.hxx>
35 #include <svx/editobj.hxx>
36 #include <tools/urlobj.hxx>
37 #include "scitems.hxx"
38 #include <svx/eeitem.hxx>
39 #include <svx/flditem.hxx>
40 #include "document.hxx"
42 #include "rangelst.hxx"
43 #include "editutil.hxx"
45 #include "xltracer.hxx"
46 #include "xistream.hxx"
47 #include "xistyle.hxx"
49 #include "excform.hxx"
51 // Excel->Calc cell address/range conversion ==================================
55 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
56 inline void lclFillAddress( ScAddress
& rScPos
, sal_uInt16 nXclCol
, sal_uInt16 nXclRow
, SCTAB nScTab
)
58 rScPos
.SetCol( static_cast< SCCOL
>( nXclCol
) );
59 rScPos
.SetRow( static_cast< SCROW
>( nXclRow
) );
60 rScPos
.SetTab( nScTab
);
65 // ----------------------------------------------------------------------------
67 XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot
& rRoot
) :
68 XclAddressConverterBase( rRoot
.GetTracer(), rRoot
.GetScMaxPos() )
72 // cell address ---------------------------------------------------------------
74 bool XclImpAddressConverter::CheckAddress( const XclAddress
& rXclPos
, bool bWarn
)
76 bool bValidCol
= rXclPos
.mnCol
<= mnMaxCol
;
77 bool bValidRow
= rXclPos
.mnRow
<= mnMaxRow
;
78 bool bValid
= bValidCol
&& bValidRow
;
79 if( !bValid
&& bWarn
)
81 mbColTrunc
|= !bValidCol
;
82 mbRowTrunc
|= !bValidRow
;
83 mrTracer
.TraceInvalidAddress( ScAddress(
84 static_cast< SCCOL
>( rXclPos
.mnCol
), static_cast< SCROW
>( rXclPos
.mnRow
), 0 ), maMaxPos
);
89 bool XclImpAddressConverter::ConvertAddress( ScAddress
& rScPos
,
90 const XclAddress
& rXclPos
, SCTAB nScTab
, bool bWarn
)
92 bool bValid
= CheckAddress( rXclPos
, bWarn
);
94 lclFillAddress( rScPos
, rXclPos
.mnCol
, rXclPos
.mnRow
, nScTab
);
98 ScAddress
XclImpAddressConverter::CreateValidAddress(
99 const XclAddress
& rXclPos
, SCTAB nScTab
, bool bWarn
)
101 ScAddress
aScPos( ScAddress::UNINITIALIZED
);
102 if( !ConvertAddress( aScPos
, rXclPos
, nScTab
, bWarn
) )
104 aScPos
.SetCol( static_cast< SCCOL
>( ::std::min( rXclPos
.mnCol
, mnMaxCol
) ) );
105 aScPos
.SetRow( static_cast< SCROW
>( ::std::min( rXclPos
.mnRow
, mnMaxRow
) ) );
106 aScPos
.SetTab( limit_cast
< SCTAB
>( nScTab
, 0, maMaxPos
.Tab() ) );
111 // cell range -----------------------------------------------------------------
113 bool XclImpAddressConverter::CheckRange( const XclRange
& rXclRange
, bool bWarn
)
115 return CheckAddress( rXclRange
.maFirst
, bWarn
) && CheckAddress( rXclRange
.maLast
, bWarn
);
118 bool XclImpAddressConverter::ConvertRange( ScRange
& rScRange
,
119 const XclRange
& rXclRange
, SCTAB nScTab1
, SCTAB nScTab2
, bool bWarn
)
121 // check start position
122 bool bValidStart
= CheckAddress( rXclRange
.maFirst
, bWarn
);
125 lclFillAddress( rScRange
.aStart
, rXclRange
.maFirst
.mnCol
, rXclRange
.maFirst
.mnRow
, nScTab1
);
127 // check & correct end position
128 sal_uInt16 nXclCol2
= rXclRange
.maLast
.mnCol
;
129 sal_uInt16 nXclRow2
= rXclRange
.maLast
.mnRow
;
130 if( !CheckAddress( rXclRange
.maLast
, bWarn
) )
132 nXclCol2
= ::std::min( nXclCol2
, mnMaxCol
);
133 nXclRow2
= ::std::min( nXclRow2
, mnMaxRow
);
135 lclFillAddress( rScRange
.aEnd
, nXclCol2
, nXclRow2
, nScTab2
);
140 //UNUSED2009-05 ScRange XclImpAddressConverter::CreateValidRange(
141 //UNUSED2009-05 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
143 //UNUSED2009-05 return ScRange(
144 //UNUSED2009-05 CreateValidAddress( rXclRange.maFirst, nScTab1, bWarn ),
145 //UNUSED2009-05 CreateValidAddress( rXclRange.maLast, nScTab2, bWarn ) );
148 // cell range list ------------------------------------------------------------
150 //UNUSED2009-05 bool XclImpAddressConverter::CheckRangeList( const XclRangeList& rXclRanges, bool bWarn )
152 //UNUSED2009-05 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
153 //UNUSED2009-05 if( !CheckRange( *aIt, bWarn ) )
154 //UNUSED2009-05 return false;
155 //UNUSED2009-05 return true;
158 void XclImpAddressConverter::ConvertRangeList( ScRangeList
& rScRanges
,
159 const XclRangeList
& rXclRanges
, SCTAB nScTab
, bool bWarn
)
161 rScRanges
.RemoveAll();
162 for( XclRangeList::const_iterator aIt
= rXclRanges
.begin(), aEnd
= rXclRanges
.end(); aIt
!= aEnd
; ++aIt
)
164 ScRange
aScRange( ScAddress::UNINITIALIZED
);
165 if( ConvertRange( aScRange
, *aIt
, nScTab
, nScTab
, bWarn
) )
166 rScRanges
.Append( aScRange
);
170 // String->EditEngine conversion ==============================================
174 EditTextObject
* lclCreateTextObject( const XclImpRoot
& rRoot
,
175 const XclImpString
& rString
, XclFontItemType eType
, sal_uInt16 nXFIndex
)
177 EditTextObject
* pTextObj
= 0;
179 const XclImpXFBuffer
& rXFBuffer
= rRoot
.GetXFBuffer();
180 const XclImpFont
* pFirstFont
= rXFBuffer
.GetFont( nXFIndex
);
181 bool bFirstEscaped
= pFirstFont
&& pFirstFont
->HasEscapement();
183 if( rString
.IsRich() || bFirstEscaped
)
185 const XclImpFontBuffer
& rFontBuffer
= rRoot
.GetFontBuffer();
186 const XclFormatRunVec
& rFormats
= rString
.GetFormats();
188 ScEditEngineDefaulter
& rEE
= (eType
== EXC_FONTITEM_NOTE
) ?
189 static_cast< ScEditEngineDefaulter
& >( rRoot
.GetDoc().GetNoteEngine() ) : rRoot
.GetEditEngine();
190 rEE
.SetText( rString
.GetText() );
192 SfxItemSet
aItemSet( rEE
.GetEmptyItemSet() );
194 rFontBuffer
.FillToItemSet( aItemSet
, eType
, rXFBuffer
.GetFontIndex( nXFIndex
) );
195 ESelection aSelection
;
197 XclFormatRun aNextRun
;
198 XclFormatRunVec::const_iterator aIt
= rFormats
.begin();
199 XclFormatRunVec::const_iterator aEnd
= rFormats
.end();
204 aNextRun
.mnChar
= 0xFFFF;
206 xub_StrLen nLen
= rString
.GetText().Len();
207 for( sal_uInt16 nChar
= 0; nChar
< nLen
; ++nChar
)
209 // reached new different formatted text portion
210 if( nChar
>= aNextRun
.mnChar
)
212 // send items to edit engine
213 rEE
.QuickSetAttribs( aItemSet
, aSelection
);
215 // start new item set
216 aItemSet
.ClearItem();
217 rFontBuffer
.FillToItemSet( aItemSet
, eType
, aNextRun
.mnFontIdx
);
219 // read new formatting information
223 aNextRun
.mnChar
= 0xFFFF;
225 // reset selection start to current position
226 aSelection
.nStartPara
= aSelection
.nEndPara
;
227 aSelection
.nStartPos
= aSelection
.nEndPos
;
230 // set end of selection to current position
231 if( rString
.GetText().GetChar( nChar
) == '\n' )
233 ++aSelection
.nEndPara
;
234 aSelection
.nEndPos
= 0;
237 ++aSelection
.nEndPos
;
240 // send items of last text portion to edit engine
241 rEE
.QuickSetAttribs( aItemSet
, aSelection
);
243 pTextObj
= rEE
.CreateTextObject();
251 EditTextObject
* XclImpStringHelper::CreateTextObject(
252 const XclImpRoot
& rRoot
, const XclImpString
& rString
)
254 return lclCreateTextObject( rRoot
, rString
, EXC_FONTITEM_EDITENG
, 0 );
257 //UNUSED2009-05 EditTextObject* XclImpStringHelper::CreateNoteObject(
258 //UNUSED2009-05 const XclImpRoot& rRoot, const XclImpString& rString )
260 //UNUSED2009-05 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_NOTE, 0 );
263 ScBaseCell
* XclImpStringHelper::CreateCell(
264 const XclImpRoot
& rRoot
, const XclImpString
& rString
, sal_uInt16 nXFIndex
)
266 ScBaseCell
* pCell
= 0;
268 if( rString
.GetText().Len() )
270 ::std::auto_ptr
< EditTextObject
> pTextObj( lclCreateTextObject( rRoot
, rString
, EXC_FONTITEM_EDITENG
, nXFIndex
) );
271 ScDocument
& rDoc
= rRoot
.GetDoc();
274 // ScEditCell creates own copy of text object
275 pCell
= new ScEditCell( pTextObj
.get(), &rDoc
, rRoot
.GetEditEngine().GetEditTextObjectPool() );
277 pCell
= ScBaseCell::CreateTextCell( rString
.GetText(), &rDoc
);
283 // Header/footer conversion ===================================================
285 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
289 maSel
.nStartPara
= maSel
.nEndPara
= 0;
290 maSel
.nStartPos
= maSel
.nEndPos
= 0;
293 // ----------------------------------------------------------------------------
295 XclImpHFConverter::XclImpHFConverter( const XclImpRoot
& rRoot
) :
297 mrEE( rRoot
.GetHFEditEngine() ),
298 mxFontData( new XclFontData
),
299 meCurrObj( EXC_HF_CENTER
)
303 XclImpHFConverter::~XclImpHFConverter()
307 void XclImpHFConverter::ParseString( const String
& rHFString
)
309 // edit engine objects
310 mrEE
.SetText( EMPTY_STRING
);
312 maInfos
.resize( EXC_HF_PORTION_COUNT
);
313 meCurrObj
= EXC_HF_CENTER
;
315 // parser temporaries
317 String aReadFont
; // current font name
318 String aReadStyle
; // current font style
319 sal_uInt16 nReadHeight
= 0; // current font height
322 /** State of the parser. */
323 enum XclHFParserState
325 xlPSText
, /// Read text, search for functions.
326 xlPSFunc
, /// Read function (token following a '&').
327 xlPSFont
, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
328 xlPSFontStyle
, /// Read font style name (font part after ',', reads until next '"').
329 xlPSHeight
/// Read font height ('&' is followed by num. digits, reads until non-digit).
332 const sal_Unicode
* pChar
= rHFString
.GetBuffer();
333 const sal_Unicode
* pNull
= pChar
+ rHFString
.Len(); // pointer to teminating null char
339 // --- read text character ---
345 case '&': // new command
349 case '\n': // line break
354 maCurrText
+= *pChar
;
359 // --- read control sequence ---
366 case '&': maCurrText
+= '&'; break; // the '&' character
368 case 'L': SetNewPortion( EXC_HF_LEFT
); break; // Left portion
369 case 'C': SetNewPortion( EXC_HF_CENTER
); break; // Center portion
370 case 'R': SetNewPortion( EXC_HF_RIGHT
); break; // Right portion
372 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD
) ); break; // page
373 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD
) ); break; // page count
374 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD
) ); break; // date
375 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD
) ); break; // time
376 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD
) ); break; // table name
378 case 'Z': // file path
379 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD
) ); // convert to full name
380 if( (pNull
- pChar
>= 2) && (*(pChar
+ 1) == '&') && (*(pChar
+ 2) == 'F') )
382 // &Z&F found - ignore the &F part
386 case 'F': // file name
387 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING
, SVXFILETYPE_VAR
, SVXFILEFORMAT_NAME_EXT
), EE_FEATURE_FIELD
) );
390 case 'U': // underline
392 mxFontData
->mnUnderline
= (mxFontData
->mnUnderline
== EXC_FONTUNDERL_SINGLE
) ?
393 EXC_FONTUNDERL_NONE
: EXC_FONTUNDERL_SINGLE
;
395 case 'E': // double underline
397 mxFontData
->mnUnderline
= (mxFontData
->mnUnderline
== EXC_FONTUNDERL_DOUBLE
) ?
398 EXC_FONTUNDERL_NONE
: EXC_FONTUNDERL_DOUBLE
;
400 case 'S': // strikeout
402 mxFontData
->mbStrikeout
= !mxFontData
->mbStrikeout
;
404 case 'X': // superscript
406 mxFontData
->mnEscapem
= (mxFontData
->mnEscapem
== EXC_FONTESC_SUPER
) ?
407 EXC_FONTESC_NONE
: EXC_FONTESC_SUPER
;
409 case 'Y': // subsrcipt
411 mxFontData
->mnEscapem
= (mxFontData
->mnEscapem
== EXC_FONTESC_SUB
) ?
412 EXC_FONTESC_NONE
: EXC_FONTESC_SUB
;
415 case '\"': // font name
421 if( ('0' <= *pChar
) && (*pChar
<= '9') ) // font size
423 nReadHeight
= *pChar
- '0';
430 // --- read font name ---
440 eState
= xlPSFontStyle
;
448 // --- read font style ---
456 if( aReadFont
.Len() )
457 mxFontData
->maName
= aReadFont
;
458 mxFontData
->maStyle
= aReadStyle
;
462 aReadStyle
+= *pChar
;
467 // --- read font height ---
471 if( ('0' <= *pChar
) && (*pChar
<= '9') )
473 if( nReadHeight
!= 0xFFFF )
476 nReadHeight
+= (*pChar
- '0');
477 if( nReadHeight
> 1600 ) // max 1600pt = 32000twips
478 nReadHeight
= 0xFFFF;
483 if( (nReadHeight
!= 0) && (nReadHeight
!= 0xFFFF) )
486 mxFontData
->mnHeight
= nReadHeight
* 20;
499 maInfos
[ EXC_HF_LEFT
].mnHeight
+= GetMaxLineHeight( EXC_HF_LEFT
);
500 maInfos
[ EXC_HF_CENTER
].mnHeight
+= GetMaxLineHeight( EXC_HF_CENTER
);
501 maInfos
[ EXC_HF_RIGHT
].mnHeight
+= GetMaxLineHeight( EXC_HF_RIGHT
);
504 void XclImpHFConverter::FillToItemSet( SfxItemSet
& rItemSet
, sal_uInt16 nWhichId
) const
506 ScPageHFItem
aHFItem( nWhichId
);
507 if( maInfos
[ EXC_HF_LEFT
].mxObj
.get() )
508 aHFItem
.SetLeftArea( *maInfos
[ EXC_HF_LEFT
].mxObj
);
509 if( maInfos
[ EXC_HF_CENTER
].mxObj
.get() )
510 aHFItem
.SetCenterArea( *maInfos
[ EXC_HF_CENTER
].mxObj
);
511 if( maInfos
[ EXC_HF_RIGHT
].mxObj
.get() )
512 aHFItem
.SetRightArea( *maInfos
[ EXC_HF_RIGHT
].mxObj
);
513 rItemSet
.Put( aHFItem
);
516 sal_Int32
XclImpHFConverter::GetTotalHeight() const
518 return ::std::max( maInfos
[ EXC_HF_LEFT
].mnHeight
,
519 ::std::max( maInfos
[ EXC_HF_CENTER
].mnHeight
, maInfos
[ EXC_HF_RIGHT
].mnHeight
) );
522 // private --------------------------------------------------------------------
524 sal_uInt16
XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion
) const
526 sal_uInt16 nMaxHt
= maInfos
[ ePortion
].mnMaxLineHt
;
527 return (nMaxHt
== 0) ? mxFontData
->mnHeight
: nMaxHt
;
530 sal_uInt16
XclImpHFConverter::GetCurrMaxLineHeight() const
532 return GetMaxLineHeight( meCurrObj
);
535 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion
)
537 sal_uInt16
& rnMaxHt
= maInfos
[ ePortion
].mnMaxLineHt
;
538 rnMaxHt
= ::std::max( rnMaxHt
, mxFontData
->mnHeight
);
541 void XclImpHFConverter::UpdateCurrMaxLineHeight()
543 UpdateMaxLineHeight( meCurrObj
);
546 void XclImpHFConverter::SetAttribs()
548 ESelection
& rSel
= GetCurrSel();
549 if( (rSel
.nStartPara
!= rSel
.nEndPara
) || (rSel
.nStartPos
!= rSel
.nEndPos
) )
551 SfxItemSet
aItemSet( mrEE
.GetEmptyItemSet() );
552 XclImpFont
aFont( GetRoot(), *mxFontData
);
553 aFont
.FillToItemSet( aItemSet
, EXC_FONTITEM_HF
);
554 mrEE
.QuickSetAttribs( aItemSet
, rSel
);
555 rSel
.nStartPara
= rSel
.nEndPara
;
556 rSel
.nStartPos
= rSel
.nEndPos
;
560 void XclImpHFConverter::ResetFontData()
562 if( const XclImpFont
* pFirstFont
= GetFontBuffer().GetFont( EXC_FONT_APP
) )
563 *mxFontData
= pFirstFont
->GetFontData();
567 mxFontData
->mnHeight
= 200;
571 void XclImpHFConverter::InsertText()
573 if( maCurrText
.Len() )
575 ESelection
& rSel
= GetCurrSel();
576 mrEE
.QuickInsertText( maCurrText
, ESelection( rSel
.nEndPara
, rSel
.nEndPos
, rSel
.nEndPara
, rSel
.nEndPos
) );
577 rSel
.nEndPos
= rSel
.nEndPos
+ maCurrText
.Len();
579 UpdateCurrMaxLineHeight();
583 void XclImpHFConverter::InsertField( const SvxFieldItem
& rFieldItem
)
585 ESelection
& rSel
= GetCurrSel();
586 mrEE
.QuickInsertField( rFieldItem
, ESelection( rSel
.nEndPara
, rSel
.nEndPos
, rSel
.nEndPara
, rSel
.nEndPos
) );
588 UpdateCurrMaxLineHeight();
591 void XclImpHFConverter::InsertLineBreak()
593 ESelection
& rSel
= GetCurrSel();
594 mrEE
.QuickInsertText( String( '\n' ), ESelection( rSel
.nEndPara
, rSel
.nEndPos
, rSel
.nEndPara
, rSel
.nEndPos
) );
597 GetCurrInfo().mnHeight
+= GetCurrMaxLineHeight();
598 GetCurrInfo().mnMaxLineHt
= 0;
601 void XclImpHFConverter::CreateCurrObject()
605 GetCurrObj().reset( mrEE
.CreateTextObject() );
608 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew
)
610 if( eNew
!= meCurrObj
)
614 if( GetCurrObj().get() )
615 mrEE
.SetText( *GetCurrObj() );
617 mrEE
.SetText( EMPTY_STRING
);
622 // URL conversion =============================================================
626 void lclAppendUrlChar( String
& rUrl
, sal_Unicode cChar
)
628 // #126855# encode special characters
631 case '#': rUrl
.AppendAscii( "%23" ); break;
632 case '%': rUrl
.AppendAscii( "%25" ); break;
633 default: rUrl
.Append( cChar
);
639 void XclImpUrlHelper::DecodeUrl(
640 String
& rUrl
, String
& rTabName
, bool& rbSameWb
,
641 const XclImpRoot
& rRoot
, const String
& rEncodedUrl
)
645 xlUrlInit
, /// Initial state, read string mode character.
646 xlUrlPath
, /// Read URL path.
647 xlUrlFileName
, /// Read file name.
648 xlUrlSheetName
, /// Read sheet name.
649 xlUrlRaw
/// Raw mode. No control characters will occur.
650 } eState
= xlUrlInit
;
652 bool bEncoded
= true;
655 sal_Unicode cCurrDrive
= 0;
656 String
aDosBase( INetURLObject( rRoot
.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS
) );
657 if( (aDosBase
.Len() > 2) && aDosBase
.EqualsAscii( ":\\", 1, 2 ) )
658 cCurrDrive
= aDosBase
.GetChar( 0 );
660 const sal_Unicode
* pChar
= rEncodedUrl
.GetBuffer();
666 // --- first character ---
672 case EXC_URLSTART_ENCODED
:
675 case EXC_URLSTART_SELF
:
676 case EXC_URLSTART_SELFENCODED
:
678 eState
= xlUrlSheetName
;
682 eState
= xlUrlFileName
;
686 lclAppendUrlChar( rUrl
, *pChar
);
698 case EXC_URL_DOSDRIVE
:
704 rUrl
.AppendAscii( "\\\\" );
707 lclAppendUrlChar( rUrl
, *pChar
);
708 rUrl
.AppendAscii( ":\\" );
712 rUrl
.AppendAscii( "<NULL-DRIVE!>" );
715 case EXC_URL_DRIVEROOT
:
718 lclAppendUrlChar( rUrl
, cCurrDrive
);
725 else // control character in raw name -> DDE link
727 rUrl
.Append( EXC_DDE_DELIM
);
731 case EXC_URL_PARENTDIR
:
732 rUrl
.AppendAscii( "..\\" );
738 xub_StrLen nLen
= *++pChar
;
739 for( xub_StrLen nChar
= 0; (nChar
< nLen
) && *(pChar
+ 1); ++nChar
)
740 lclAppendUrlChar( rUrl
, *++pChar
);
741 // rUrl.Append( ':' );
746 eState
= xlUrlFileName
;
749 lclAppendUrlChar( rUrl
, *pChar
);
760 case ']': eState
= xlUrlSheetName
; break;
761 default: lclAppendUrlChar( rUrl
, *pChar
);
766 // --- sheet name ---
769 rTabName
.Append( *pChar
);
772 // --- raw read mode ---
775 lclAppendUrlChar( rUrl
, *pChar
);
783 void XclImpUrlHelper::DecodeUrl(
784 String
& rUrl
, bool& rbSameWb
, const XclImpRoot
& rRoot
, const String
& rEncodedUrl
)
787 DecodeUrl( rUrl
, aTabName
, rbSameWb
, rRoot
, rEncodedUrl
);
788 DBG_ASSERT( !aTabName
.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
791 bool XclImpUrlHelper::DecodeLink( String
& rApplic
, String
& rTopic
, const String rEncUrl
)
793 xub_StrLen nPos
= rEncUrl
.Search( EXC_DDE_DELIM
);
794 if( (nPos
!= STRING_NOTFOUND
) && (0 < nPos
) && (nPos
+ 1 < rEncUrl
.Len()) )
796 rApplic
= rEncUrl
.Copy( 0, nPos
);
797 rTopic
= rEncUrl
.Copy( nPos
+ 1 );
803 // Cached Values ==============================================================
805 XclImpCachedValue::XclImpCachedValue( XclImpStream
& rStrm
) :
812 case EXC_CACHEDVAL_EMPTY
:
815 case EXC_CACHEDVAL_DOUBLE
:
818 case EXC_CACHEDVAL_STRING
:
819 mxStr
.reset( new String( rStrm
.ReadUniString() ) );
821 case EXC_CACHEDVAL_BOOL
:
822 case EXC_CACHEDVAL_ERROR
:
828 const ScTokenArray
* pScTokArr
= rStrm
.GetRoot().GetOldFmlaConverter().GetBoolErr(
829 XclTools::ErrorToEnum( fVal
, mnType
== EXC_CACHEDVAL_ERROR
, mnBoolErr
) );
831 mxTokArr
.reset( pScTokArr
->Clone() );
835 DBG_ERRORFILE( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
839 XclImpCachedValue::~XclImpCachedValue()
843 USHORT
XclImpCachedValue::GetError() const
845 return (mnType
== EXC_CACHEDVAL_ERROR
) ? XclTools::GetScErrorCode( mnBoolErr
) : 0;
848 // Matrix Cached Values ==============================================================
850 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream
& rStrm
) :
854 mnScCols
= rStrm
.ReaduInt8();
855 mnScRows
= rStrm
.ReaduInt16();
857 if( rStrm
.GetRoot().GetBiff() <= EXC_BIFF5
)
859 // in BIFF2-BIFF7: 256 columns represented by 0 columns
865 // in BIFF8: columns and rows decreaed by 1
870 for( SCSIZE nScRow
= 0; nScRow
< mnScRows
; ++nScRow
)
871 for( SCSIZE nScCol
= 0; nScCol
< mnScCols
; ++nScCol
)
872 maValueList
.Append( new XclImpCachedValue( rStrm
) );
875 XclImpCachedMatrix::~XclImpCachedMatrix()
879 ScMatrixRef
XclImpCachedMatrix::CreateScMatrix() const
881 ScMatrixRef xScMatrix
;
882 DBG_ASSERT( mnScCols
* mnScRows
== maValueList
.Count(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
883 if( mnScCols
&& mnScRows
&& static_cast< ULONG
>( mnScCols
* mnScRows
) <= maValueList
.Count() )
885 xScMatrix
= new ScMatrix( mnScCols
, mnScRows
);
886 const XclImpCachedValue
* pValue
= maValueList
.First();
887 for( SCSIZE nScRow
= 0; nScRow
< mnScRows
; ++nScRow
)
889 for( SCSIZE nScCol
= 0; nScCol
< mnScCols
; ++nScCol
)
891 switch( pValue
->GetType() )
893 case EXC_CACHEDVAL_EMPTY
:
894 // Excel shows 0.0 here, not an empty cell
895 xScMatrix
->PutEmpty( nScCol
, nScRow
);
897 case EXC_CACHEDVAL_DOUBLE
:
898 xScMatrix
->PutDouble( pValue
->GetValue(), nScCol
, nScRow
);
900 case EXC_CACHEDVAL_STRING
:
901 xScMatrix
->PutString( pValue
->GetString(), nScCol
, nScRow
);
903 case EXC_CACHEDVAL_BOOL
:
904 xScMatrix
->PutBoolean( pValue
->GetBool(), nScCol
, nScRow
);
906 case EXC_CACHEDVAL_ERROR
:
907 xScMatrix
->PutError( pValue
->GetError(), nScCol
, nScRow
);
910 DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
911 xScMatrix
->PutEmpty( nScCol
, nScRow
);
913 pValue
= maValueList
.Next();
920 // ============================================================================