Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / sc / source / filter / excel / xihelper.cxx
blobad5d1f8c1f124c12294222254393b15f758ade6f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "xihelper.hxx"
21 #include <svl/itemset.hxx>
22 #include <editeng/editobj.hxx>
23 #include <tools/urlobj.hxx>
24 #include "scitems.hxx"
25 #include <editeng/eeitem.hxx>
26 #include <editeng/flditem.hxx>
27 #include "document.hxx"
28 #include "cell.hxx"
29 #include "rangelst.hxx"
30 #include "editutil.hxx"
31 #include "attrib.hxx"
32 #include "xltracer.hxx"
33 #include "xistream.hxx"
34 #include "xistyle.hxx"
36 #include "excform.hxx"
38 // Excel->Calc cell address/range conversion ==================================
40 namespace {
42 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
43 inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt32 nXclRow, SCTAB nScTab )
45 rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
46 rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
47 rScPos.SetTab( nScTab );
50 } // namespace
52 // ----------------------------------------------------------------------------
54 XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) :
55 XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() )
59 // cell address ---------------------------------------------------------------
61 bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn )
63 bool bValidCol = rXclPos.mnCol <= mnMaxCol;
64 bool bValidRow = rXclPos.mnRow <= mnMaxRow;
65 bool bValid = bValidCol && bValidRow;
66 if( !bValid && bWarn )
68 mbColTrunc |= !bValidCol;
69 mbRowTrunc |= !bValidRow;
70 mrTracer.TraceInvalidAddress( ScAddress(
71 static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos );
73 return bValid;
76 bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
77 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
79 bool bValid = CheckAddress( rXclPos, bWarn );
80 if( bValid )
81 lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
82 return bValid;
85 ScAddress XclImpAddressConverter::CreateValidAddress(
86 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
88 ScAddress aScPos( ScAddress::UNINITIALIZED );
89 if( !ConvertAddress( aScPos, rXclPos, nScTab, bWarn ) )
91 aScPos.SetCol( static_cast< SCCOL >( ::std::min( rXclPos.mnCol, mnMaxCol ) ) );
92 aScPos.SetRow( static_cast< SCROW >( ::std::min( rXclPos.mnRow, mnMaxRow ) ) );
93 aScPos.SetTab( limit_cast< SCTAB >( nScTab, 0, maMaxPos.Tab() ) );
95 return aScPos;
98 // cell range -----------------------------------------------------------------
100 bool XclImpAddressConverter::ConvertRange( ScRange& rScRange,
101 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
103 // check start position
104 bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn );
105 if( bValidStart )
107 lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 );
109 // check & correct end position
110 sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol;
111 sal_uInt32 nXclRow2 = rXclRange.maLast.mnRow;
112 if( !CheckAddress( rXclRange.maLast, bWarn ) )
114 nXclCol2 = ::std::min( nXclCol2, mnMaxCol );
115 nXclRow2 = ::std::min( nXclRow2, mnMaxRow );
117 lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 );
119 return bValidStart;
122 // cell range list ------------------------------------------------------------
124 void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges,
125 const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn )
127 rScRanges.RemoveAll();
128 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
130 ScRange aScRange( ScAddress::UNINITIALIZED );
131 if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) )
132 rScRanges.Append( aScRange );
136 // String->EditEngine conversion ==============================================
138 namespace {
140 EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot,
141 const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex )
143 EditTextObject* pTextObj = 0;
145 const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer();
146 const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex );
147 bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement();
149 if( rString.IsRich() || bFirstEscaped )
151 const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
152 const XclFormatRunVec& rFormats = rString.GetFormats();
154 ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ?
155 static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine();
156 rEE.SetText( rString.GetText() );
158 SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
159 if( bFirstEscaped )
160 rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) );
161 ESelection aSelection;
163 XclFormatRun aNextRun;
164 XclFormatRunVec::const_iterator aIt = rFormats.begin();
165 XclFormatRunVec::const_iterator aEnd = rFormats.end();
167 if( aIt != aEnd )
168 aNextRun = *aIt++;
169 else
170 aNextRun.mnChar = 0xFFFF;
172 xub_StrLen nLen = rString.GetText().Len();
173 for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar )
175 // reached new different formatted text portion
176 if( nChar >= aNextRun.mnChar )
178 // send items to edit engine
179 rEE.QuickSetAttribs( aItemSet, aSelection );
181 // start new item set
182 aItemSet.ClearItem();
183 rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx );
185 // read new formatting information
186 if( aIt != aEnd )
187 aNextRun = *aIt++;
188 else
189 aNextRun.mnChar = 0xFFFF;
191 // reset selection start to current position
192 aSelection.nStartPara = aSelection.nEndPara;
193 aSelection.nStartPos = aSelection.nEndPos;
196 // set end of selection to current position
197 if( rString.GetText().GetChar( nChar ) == '\n' )
199 ++aSelection.nEndPara;
200 aSelection.nEndPos = 0;
202 else
203 ++aSelection.nEndPos;
206 // send items of last text portion to edit engine
207 rEE.QuickSetAttribs( aItemSet, aSelection );
209 pTextObj = rEE.CreateTextObject();
212 return pTextObj;
215 } // namespace
217 EditTextObject* XclImpStringHelper::CreateTextObject(
218 const XclImpRoot& rRoot, const XclImpString& rString )
220 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 );
223 ScBaseCell* XclImpStringHelper::CreateCell(
224 const XclImpRoot& rRoot, const XclImpString& rString, sal_uInt16 nXFIndex )
226 ScBaseCell* pCell = 0;
228 if( rString.GetText().Len() )
230 ::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
231 ScDocument& rDoc = rRoot.GetDoc();
233 if( pTextObj.get() )
234 // ScEditCell creates own copy of text object
235 pCell = new ScEditCell( pTextObj.get(), &rDoc, rRoot.GetEditEngine().GetEditTextObjectPool() );
236 else
237 pCell = ScBaseCell::CreateTextCell( rString.GetText(), &rDoc );
240 return pCell;
243 // Header/footer conversion ===================================================
245 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
246 mnHeight( 0 ),
247 mnMaxLineHt( 0 )
249 maSel.nStartPara = maSel.nEndPara = 0;
250 maSel.nStartPos = maSel.nEndPos = 0;
253 // ----------------------------------------------------------------------------
255 XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
256 XclImpRoot( rRoot ),
257 mrEE( rRoot.GetHFEditEngine() ),
258 mxFontData( new XclFontData ),
259 meCurrObj( EXC_HF_CENTER )
263 XclImpHFConverter::~XclImpHFConverter()
267 void XclImpHFConverter::ParseString( const String& rHFString )
269 // edit engine objects
270 mrEE.SetText( EMPTY_STRING );
271 maInfos.clear();
272 maInfos.resize( EXC_HF_PORTION_COUNT );
273 meCurrObj = EXC_HF_CENTER;
275 // parser temporaries
276 maCurrText.Erase();
277 String aReadFont; // current font name
278 String aReadStyle; // current font style
279 sal_uInt16 nReadHeight = 0; // current font height
280 ResetFontData();
282 /** State of the parser. */
283 enum XclHFParserState
285 xlPSText, /// Read text, search for functions.
286 xlPSFunc, /// Read function (token following a '&').
287 xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
288 xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"').
289 xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit).
290 } eState = xlPSText;
292 const sal_Unicode* pChar = rHFString.GetBuffer();
293 const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char
294 while( *pChar )
296 switch( eState )
299 // --- read text character ---
301 case xlPSText:
303 switch( *pChar )
305 case '&': // new command
306 InsertText();
307 eState = xlPSFunc;
308 break;
309 case '\n': // line break
310 InsertText();
311 InsertLineBreak();
312 break;
313 default:
314 maCurrText += *pChar;
317 break;
319 // --- read control sequence ---
321 case xlPSFunc:
323 eState = xlPSText;
324 switch( *pChar )
326 case '&': maCurrText += '&'; break; // the '&' character
328 case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
329 case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
330 case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
332 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
333 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
334 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
335 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
336 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name
338 case 'Z': // file path
339 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name
340 if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') )
342 // &Z&F found - ignore the &F part
343 pChar += 2;
345 break;
346 case 'F': // file name
347 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
348 break;
350 case 'U': // underline
351 SetAttribs();
352 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
353 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
354 break;
355 case 'E': // double underline
356 SetAttribs();
357 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
358 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
359 break;
360 case 'S': // strikeout
361 SetAttribs();
362 mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
363 break;
364 case 'X': // superscript
365 SetAttribs();
366 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
367 EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
368 break;
369 case 'Y': // subsrcipt
370 SetAttribs();
371 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
372 EXC_FONTESC_NONE : EXC_FONTESC_SUB;
373 break;
375 case '\"': // font name
376 aReadFont.Erase();
377 aReadStyle.Erase();
378 eState = xlPSFont;
379 break;
380 default:
381 if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
383 nReadHeight = *pChar - '0';
384 eState = xlPSHeight;
388 break;
390 // --- read font name ---
392 case xlPSFont:
394 switch( *pChar )
396 case '\"':
397 --pChar;
398 // run through
399 case ',':
400 eState = xlPSFontStyle;
401 break;
402 default:
403 aReadFont += *pChar;
406 break;
408 // --- read font style ---
410 case xlPSFontStyle:
412 switch( *pChar )
414 case '\"':
415 SetAttribs();
416 if( aReadFont.Len() )
417 mxFontData->maName = aReadFont;
418 mxFontData->maStyle = aReadStyle;
419 eState = xlPSText;
420 break;
421 default:
422 aReadStyle += *pChar;
425 break;
427 // --- read font height ---
429 case xlPSHeight:
431 if( ('0' <= *pChar) && (*pChar <= '9') )
433 if( nReadHeight != 0xFFFF )
435 nReadHeight *= 10;
436 nReadHeight += (*pChar - '0');
437 if( nReadHeight > 1600 ) // max 1600pt = 32000twips
438 nReadHeight = 0xFFFF;
441 else
443 if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
445 SetAttribs();
446 mxFontData->mnHeight = nReadHeight * 20;
448 --pChar;
449 eState = xlPSText;
452 break;
454 ++pChar;
457 // finalize
458 CreateCurrObject();
459 maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
460 maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
461 maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
464 void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
466 ScPageHFItem aHFItem( nWhichId );
467 if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
468 aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
469 if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
470 aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
471 if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
472 aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
473 rItemSet.Put( aHFItem );
476 sal_Int32 XclImpHFConverter::GetTotalHeight() const
478 return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
479 ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
482 // private --------------------------------------------------------------------
484 sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
486 sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
487 return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
490 sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
492 return GetMaxLineHeight( meCurrObj );
495 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
497 sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
498 rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
501 void XclImpHFConverter::UpdateCurrMaxLineHeight()
503 UpdateMaxLineHeight( meCurrObj );
506 void XclImpHFConverter::SetAttribs()
508 ESelection& rSel = GetCurrSel();
509 if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
511 SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
512 XclImpFont aFont( GetRoot(), *mxFontData );
513 aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
514 mrEE.QuickSetAttribs( aItemSet, rSel );
515 rSel.nStartPara = rSel.nEndPara;
516 rSel.nStartPos = rSel.nEndPos;
520 void XclImpHFConverter::ResetFontData()
522 if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
523 *mxFontData = pFirstFont->GetFontData();
524 else
526 mxFontData->Clear();
527 mxFontData->mnHeight = 200;
531 void XclImpHFConverter::InsertText()
533 if( maCurrText.Len() )
535 ESelection& rSel = GetCurrSel();
536 mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
537 rSel.nEndPos = rSel.nEndPos + maCurrText.Len();
538 maCurrText.Erase();
539 UpdateCurrMaxLineHeight();
543 void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
545 ESelection& rSel = GetCurrSel();
546 mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
547 ++rSel.nEndPos;
548 UpdateCurrMaxLineHeight();
551 void XclImpHFConverter::InsertLineBreak()
553 ESelection& rSel = GetCurrSel();
554 mrEE.QuickInsertText( rtl::OUString('\n'), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
555 ++rSel.nEndPara;
556 rSel.nEndPos = 0;
557 GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
558 GetCurrInfo().mnMaxLineHt = 0;
561 void XclImpHFConverter::CreateCurrObject()
563 InsertText();
564 SetAttribs();
565 GetCurrObj().reset( mrEE.CreateTextObject() );
568 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
570 if( eNew != meCurrObj )
572 CreateCurrObject();
573 meCurrObj = eNew;
574 if( GetCurrObj().get() )
575 mrEE.SetText( *GetCurrObj() );
576 else
577 mrEE.SetText( EMPTY_STRING );
578 ResetFontData();
582 // URL conversion =============================================================
584 namespace {
586 void lclAppendUrlChar( String& rUrl, sal_Unicode cChar )
588 // encode special characters
589 switch( cChar )
591 case '#': rUrl.AppendAscii( "%23" ); break;
592 case '%': rUrl.AppendAscii( "%25" ); break;
593 default: rUrl.Append( cChar );
597 } // namespace
599 void XclImpUrlHelper::DecodeUrl(
600 String& rUrl, String& rTabName, bool& rbSameWb,
601 const XclImpRoot& rRoot, const String& rEncodedUrl )
603 enum
605 xlUrlInit, /// Initial state, read string mode character.
606 xlUrlPath, /// Read URL path.
607 xlUrlFileName, /// Read file name.
608 xlUrlSheetName, /// Read sheet name.
609 xlUrlRaw /// Raw mode. No control characters will occur.
610 } eState = xlUrlInit;
612 bool bEncoded = true;
613 rbSameWb = false;
615 sal_Unicode cCurrDrive = 0;
616 String aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
617 if( (aDosBase.Len() > 2) && aDosBase.EqualsAscii( ":\\", 1, 2 ) )
618 cCurrDrive = aDosBase.GetChar( 0 );
620 const sal_Unicode* pChar = rEncodedUrl.GetBuffer();
621 while( *pChar )
623 switch( eState )
626 // --- first character ---
628 case xlUrlInit:
630 switch( *pChar )
632 case EXC_URLSTART_ENCODED:
633 eState = xlUrlPath;
634 break;
635 case EXC_URLSTART_SELF:
636 case EXC_URLSTART_SELFENCODED:
637 rbSameWb = true;
638 eState = xlUrlSheetName;
639 break;
640 case '[':
641 bEncoded = false;
642 eState = xlUrlFileName;
643 break;
644 default:
645 bEncoded = false;
646 lclAppendUrlChar( rUrl, *pChar );
647 eState = xlUrlPath;
650 break;
652 // --- URL path ---
654 case xlUrlPath:
656 switch( *pChar )
658 case EXC_URL_DOSDRIVE:
660 if( *(pChar + 1) )
662 ++pChar;
663 if( *pChar == '@' )
664 rUrl.AppendAscii( "\\\\" );
665 else
667 lclAppendUrlChar( rUrl, *pChar );
668 rUrl.AppendAscii( ":\\" );
671 else
672 rUrl.AppendAscii( "<NULL-DRIVE!>" );
674 break;
675 case EXC_URL_DRIVEROOT:
676 if( cCurrDrive )
678 lclAppendUrlChar( rUrl, cCurrDrive );
679 rUrl.Append( ':' );
681 // run through
682 case EXC_URL_SUBDIR:
683 if( bEncoded )
684 rUrl.Append( '\\' );
685 else // control character in raw name -> DDE link
687 rUrl.Append( EXC_DDE_DELIM );
688 eState = xlUrlRaw;
690 break;
691 case EXC_URL_PARENTDIR:
692 rUrl.AppendAscii( "..\\" );
693 break;
694 case EXC_URL_RAW:
696 if( *(pChar + 1) )
698 xub_StrLen nLen = *++pChar;
699 for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
700 lclAppendUrlChar( rUrl, *++pChar );
701 // rUrl.Append( ':' );
704 break;
705 case '[':
706 eState = xlUrlFileName;
707 break;
708 default:
709 lclAppendUrlChar( rUrl, *pChar );
712 break;
714 // --- file name ---
716 case xlUrlFileName:
718 switch( *pChar )
720 case ']': eState = xlUrlSheetName; break;
721 default: lclAppendUrlChar( rUrl, *pChar );
724 break;
726 // --- sheet name ---
728 case xlUrlSheetName:
729 rTabName.Append( *pChar );
730 break;
732 // --- raw read mode ---
734 case xlUrlRaw:
735 lclAppendUrlChar( rUrl, *pChar );
736 break;
739 ++pChar;
743 void XclImpUrlHelper::DecodeUrl(
744 String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl )
746 String aTabName;
747 DecodeUrl( rUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
748 OSL_ENSURE( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
751 void XclImpUrlHelper::DecodeUrl(
752 ::rtl::OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const ::rtl::OUString& rEncodedUrl )
754 String aTabName;
755 String aUrl;
756 DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
757 rUrl = aUrl;
758 OSL_ENSURE( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
761 bool XclImpUrlHelper::DecodeLink( String& rApplic, String& rTopic, const String rEncUrl )
763 xub_StrLen nPos = rEncUrl.Search( EXC_DDE_DELIM );
764 if( (nPos != STRING_NOTFOUND) && (0 < nPos) && (nPos + 1 < rEncUrl.Len()) )
766 rApplic = rEncUrl.Copy( 0, nPos );
767 rTopic = rEncUrl.Copy( nPos + 1 );
768 return true;
770 return false;
773 // Cached Values ==============================================================
775 XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
776 mfValue( 0.0 ),
777 mnBoolErr( 0 )
779 rStrm >> mnType;
780 switch( mnType )
782 case EXC_CACHEDVAL_EMPTY:
783 rStrm.Ignore( 8 );
784 break;
785 case EXC_CACHEDVAL_DOUBLE:
786 rStrm >> mfValue;
787 break;
788 case EXC_CACHEDVAL_STRING:
789 mxStr.reset( new String( rStrm.ReadUniString() ) );
790 break;
791 case EXC_CACHEDVAL_BOOL:
792 case EXC_CACHEDVAL_ERROR:
794 double fVal;
795 rStrm >> mnBoolErr;
796 rStrm.Ignore( 7 );
798 const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
799 XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
800 if( pScTokArr )
801 mxTokArr.reset( pScTokArr->Clone() );
803 break;
804 default:
805 OSL_FAIL( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
809 XclImpCachedValue::~XclImpCachedValue()
813 sal_uInt16 XclImpCachedValue::GetScError() const
815 return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
818 // Matrix Cached Values ==============================================================
820 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
821 mnScCols( 0 ),
822 mnScRows( 0 )
824 mnScCols = rStrm.ReaduInt8();
825 mnScRows = rStrm.ReaduInt16();
827 if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
829 // in BIFF2-BIFF7: 256 columns represented by 0 columns
830 if( mnScCols == 0 )
831 mnScCols = 256;
833 else
835 // in BIFF8: columns and rows decreaed by 1
836 ++mnScCols;
837 ++mnScRows;
840 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
841 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
842 maValueList.push_back( new XclImpCachedValue( rStrm ) );
845 XclImpCachedMatrix::~XclImpCachedMatrix()
849 ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
851 ScMatrixRef xScMatrix;
852 OSL_ENSURE( mnScCols * mnScRows == maValueList.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
853 if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.size() )
855 xScMatrix = new ScMatrix(mnScCols, mnScRows, 0.0);
856 XclImpValueList::const_iterator itValue = maValueList.begin();
857 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
859 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
861 switch( itValue->GetType() )
863 case EXC_CACHEDVAL_EMPTY:
864 // Excel shows 0.0 here, not an empty cell
865 xScMatrix->PutEmpty( nScCol, nScRow );
866 break;
867 case EXC_CACHEDVAL_DOUBLE:
868 xScMatrix->PutDouble( itValue->GetValue(), nScCol, nScRow );
869 break;
870 case EXC_CACHEDVAL_STRING:
871 xScMatrix->PutString( itValue->GetString(), nScCol, nScRow );
872 break;
873 case EXC_CACHEDVAL_BOOL:
874 xScMatrix->PutBoolean( itValue->GetBool(), nScCol, nScRow );
875 break;
876 case EXC_CACHEDVAL_ERROR:
877 xScMatrix->PutError( itValue->GetScError(), nScCol, nScRow );
878 break;
879 default:
880 OSL_FAIL( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
881 xScMatrix->PutEmpty( nScCol, nScRow );
883 ++itValue;
887 return xScMatrix;
890 // ============================================================================
892 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */