merge the formfield patch from ooo-build
[ooovba.git] / sc / source / filter / excel / xihelper.cxx
blobf39bb1e1866fc780371254f46c124e26b4b88a96
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xihelper.cxx,v $
10 * $Revision: 1.29 $
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"
41 #include "cell.hxx"
42 #include "rangelst.hxx"
43 #include "editutil.hxx"
44 #include "attrib.hxx"
45 #include "xltracer.hxx"
46 #include "xistream.hxx"
47 #include "xistyle.hxx"
49 #include "excform.hxx"
51 // Excel->Calc cell address/range conversion ==================================
53 namespace {
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 );
63 } // namespace
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 );
86 return bValid;
89 bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
90 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
92 bool bValid = CheckAddress( rXclPos, bWarn );
93 if( bValid )
94 lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
95 return bValid;
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() ) );
108 return aScPos;
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 );
123 if( bValidStart )
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 );
137 return bValidStart;
140 //UNUSED2009-05 ScRange XclImpAddressConverter::CreateValidRange(
141 //UNUSED2009-05 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
142 //UNUSED2009-05 {
143 //UNUSED2009-05 return ScRange(
144 //UNUSED2009-05 CreateValidAddress( rXclRange.maFirst, nScTab1, bWarn ),
145 //UNUSED2009-05 CreateValidAddress( rXclRange.maLast, nScTab2, bWarn ) );
146 //UNUSED2009-05 }
148 // cell range list ------------------------------------------------------------
150 //UNUSED2009-05 bool XclImpAddressConverter::CheckRangeList( const XclRangeList& rXclRanges, bool bWarn )
151 //UNUSED2009-05 {
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;
156 //UNUSED2009-05 }
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 ==============================================
172 namespace {
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() );
193 if( bFirstEscaped )
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();
201 if( aIt != aEnd )
202 aNextRun = *aIt++;
203 else
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
220 if( aIt != aEnd )
221 aNextRun = *aIt++;
222 else
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;
236 else
237 ++aSelection.nEndPos;
240 // send items of last text portion to edit engine
241 rEE.QuickSetAttribs( aItemSet, aSelection );
243 pTextObj = rEE.CreateTextObject();
246 return pTextObj;
249 } // namespace
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 )
259 //UNUSED2009-05 {
260 //UNUSED2009-05 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_NOTE, 0 );
261 //UNUSED2009-05 }
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();
273 if( pTextObj.get() )
274 // ScEditCell creates own copy of text object
275 pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
276 else
277 pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
280 return pCell;
283 // Header/footer conversion ===================================================
285 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
286 mnHeight( 0 ),
287 mnMaxLineHt( 0 )
289 maSel.nStartPara = maSel.nEndPara = 0;
290 maSel.nStartPos = maSel.nEndPos = 0;
293 // ----------------------------------------------------------------------------
295 XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
296 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 );
311 maInfos.clear();
312 maInfos.resize( EXC_HF_PORTION_COUNT );
313 meCurrObj = EXC_HF_CENTER;
315 // parser temporaries
316 maCurrText.Erase();
317 String aReadFont; // current font name
318 String aReadStyle; // current font style
319 sal_uInt16 nReadHeight = 0; // current font height
320 ResetFontData();
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).
330 } eState = xlPSText;
332 const sal_Unicode* pChar = rHFString.GetBuffer();
333 const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char
334 while( *pChar )
336 switch( eState )
339 // --- read text character ---
341 case xlPSText:
343 switch( *pChar )
345 case '&': // new command
346 InsertText();
347 eState = xlPSFunc;
348 break;
349 case '\n': // line break
350 InsertText();
351 InsertLineBreak();
352 break;
353 default:
354 maCurrText += *pChar;
357 break;
359 // --- read control sequence ---
361 case xlPSFunc:
363 eState = xlPSText;
364 switch( *pChar )
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
383 pChar += 2;
385 break;
386 case 'F': // file name
387 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
388 break;
390 case 'U': // underline
391 SetAttribs();
392 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
393 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
394 break;
395 case 'E': // double underline
396 SetAttribs();
397 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
398 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
399 break;
400 case 'S': // strikeout
401 SetAttribs();
402 mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
403 break;
404 case 'X': // superscript
405 SetAttribs();
406 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
407 EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
408 break;
409 case 'Y': // subsrcipt
410 SetAttribs();
411 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
412 EXC_FONTESC_NONE : EXC_FONTESC_SUB;
413 break;
415 case '\"': // font name
416 aReadFont.Erase();
417 aReadStyle.Erase();
418 eState = xlPSFont;
419 break;
420 default:
421 if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
423 nReadHeight = *pChar - '0';
424 eState = xlPSHeight;
428 break;
430 // --- read font name ---
432 case xlPSFont:
434 switch( *pChar )
436 case '\"':
437 --pChar;
438 // run through
439 case ',':
440 eState = xlPSFontStyle;
441 break;
442 default:
443 aReadFont += *pChar;
446 break;
448 // --- read font style ---
450 case xlPSFontStyle:
452 switch( *pChar )
454 case '\"':
455 SetAttribs();
456 if( aReadFont.Len() )
457 mxFontData->maName = aReadFont;
458 mxFontData->maStyle = aReadStyle;
459 eState = xlPSText;
460 break;
461 default:
462 aReadStyle += *pChar;
465 break;
467 // --- read font height ---
469 case xlPSHeight:
471 if( ('0' <= *pChar) && (*pChar <= '9') )
473 if( nReadHeight != 0xFFFF )
475 nReadHeight *= 10;
476 nReadHeight += (*pChar - '0');
477 if( nReadHeight > 1600 ) // max 1600pt = 32000twips
478 nReadHeight = 0xFFFF;
481 else
483 if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
485 SetAttribs();
486 mxFontData->mnHeight = nReadHeight * 20;
488 --pChar;
489 eState = xlPSText;
492 break;
494 ++pChar;
497 // finalize
498 CreateCurrObject();
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();
564 else
566 mxFontData->Clear();
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();
578 maCurrText.Erase();
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 ) );
587 ++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 ) );
595 ++rSel.nEndPara;
596 rSel.nEndPos = 0;
597 GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
598 GetCurrInfo().mnMaxLineHt = 0;
601 void XclImpHFConverter::CreateCurrObject()
603 InsertText();
604 SetAttribs();
605 GetCurrObj().reset( mrEE.CreateTextObject() );
608 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
610 if( eNew != meCurrObj )
612 CreateCurrObject();
613 meCurrObj = eNew;
614 if( GetCurrObj().get() )
615 mrEE.SetText( *GetCurrObj() );
616 else
617 mrEE.SetText( EMPTY_STRING );
618 ResetFontData();
622 // URL conversion =============================================================
624 namespace {
626 void lclAppendUrlChar( String& rUrl, sal_Unicode cChar )
628 // #126855# encode special characters
629 switch( cChar )
631 case '#': rUrl.AppendAscii( "%23" ); break;
632 case '%': rUrl.AppendAscii( "%25" ); break;
633 default: rUrl.Append( cChar );
637 } // namespace
639 void XclImpUrlHelper::DecodeUrl(
640 String& rUrl, String& rTabName, bool& rbSameWb,
641 const XclImpRoot& rRoot, const String& rEncodedUrl )
643 enum
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;
653 rbSameWb = false;
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();
661 while( *pChar )
663 switch( eState )
666 // --- first character ---
668 case xlUrlInit:
670 switch( *pChar )
672 case EXC_URLSTART_ENCODED:
673 eState = xlUrlPath;
674 break;
675 case EXC_URLSTART_SELF:
676 case EXC_URLSTART_SELFENCODED:
677 rbSameWb = true;
678 eState = xlUrlSheetName;
679 break;
680 case '[':
681 bEncoded = false;
682 eState = xlUrlFileName;
683 break;
684 default:
685 bEncoded = false;
686 lclAppendUrlChar( rUrl, *pChar );
687 eState = xlUrlPath;
690 break;
692 // --- URL path ---
694 case xlUrlPath:
696 switch( *pChar )
698 case EXC_URL_DOSDRIVE:
700 if( *(pChar + 1) )
702 ++pChar;
703 if( *pChar == '@' )
704 rUrl.AppendAscii( "\\\\" );
705 else
707 lclAppendUrlChar( rUrl, *pChar );
708 rUrl.AppendAscii( ":\\" );
711 else
712 rUrl.AppendAscii( "<NULL-DRIVE!>" );
714 break;
715 case EXC_URL_DRIVEROOT:
716 if( cCurrDrive )
718 lclAppendUrlChar( rUrl, cCurrDrive );
719 rUrl.Append( ':' );
721 // run through
722 case EXC_URL_SUBDIR:
723 if( bEncoded )
724 rUrl.Append( '\\' );
725 else // control character in raw name -> DDE link
727 rUrl.Append( EXC_DDE_DELIM );
728 eState = xlUrlRaw;
730 break;
731 case EXC_URL_PARENTDIR:
732 rUrl.AppendAscii( "..\\" );
733 break;
734 case EXC_URL_RAW:
736 if( *(pChar + 1) )
738 xub_StrLen nLen = *++pChar;
739 for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
740 lclAppendUrlChar( rUrl, *++pChar );
741 // rUrl.Append( ':' );
744 break;
745 case '[':
746 eState = xlUrlFileName;
747 break;
748 default:
749 lclAppendUrlChar( rUrl, *pChar );
752 break;
754 // --- file name ---
756 case xlUrlFileName:
758 switch( *pChar )
760 case ']': eState = xlUrlSheetName; break;
761 default: lclAppendUrlChar( rUrl, *pChar );
764 break;
766 // --- sheet name ---
768 case xlUrlSheetName:
769 rTabName.Append( *pChar );
770 break;
772 // --- raw read mode ---
774 case xlUrlRaw:
775 lclAppendUrlChar( rUrl, *pChar );
776 break;
779 ++pChar;
783 void XclImpUrlHelper::DecodeUrl(
784 String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl )
786 String aTabName;
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 );
798 return true;
800 return false;
803 // Cached Values ==============================================================
805 XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
806 mfValue( 0.0 ),
807 mnBoolErr( 0 )
809 rStrm >> mnType;
810 switch( mnType )
812 case EXC_CACHEDVAL_EMPTY:
813 rStrm.Ignore( 8 );
814 break;
815 case EXC_CACHEDVAL_DOUBLE:
816 rStrm >> mfValue;
817 break;
818 case EXC_CACHEDVAL_STRING:
819 mxStr.reset( new String( rStrm.ReadUniString() ) );
820 break;
821 case EXC_CACHEDVAL_BOOL:
822 case EXC_CACHEDVAL_ERROR:
824 double fVal;
825 rStrm >> mnBoolErr;
826 rStrm.Ignore( 7 );
828 const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
829 XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
830 if( pScTokArr )
831 mxTokArr.reset( pScTokArr->Clone() );
833 break;
834 default:
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 ) :
851 mnScCols( 0 ),
852 mnScRows( 0 )
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
860 if( mnScCols == 0 )
861 mnScCols = 256;
863 else
865 // in BIFF8: columns and rows decreaed by 1
866 ++mnScCols;
867 ++mnScRows;
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 );
896 break;
897 case EXC_CACHEDVAL_DOUBLE:
898 xScMatrix->PutDouble( pValue->GetValue(), nScCol, nScRow );
899 break;
900 case EXC_CACHEDVAL_STRING:
901 xScMatrix->PutString( pValue->GetString(), nScCol, nScRow );
902 break;
903 case EXC_CACHEDVAL_BOOL:
904 xScMatrix->PutBoolean( pValue->GetBool(), nScCol, nScRow );
905 break;
906 case EXC_CACHEDVAL_ERROR:
907 xScMatrix->PutError( pValue->GetError(), nScCol, nScRow );
908 break;
909 default:
910 DBG_ERRORFILE( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
911 xScMatrix->PutEmpty( nScCol, nScRow );
913 pValue = maValueList.Next();
917 return xScMatrix;
920 // ============================================================================