bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xihelper.cxx
blobc002ae9b5197de0bfc15a046ff19bc57d8b7c73f
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 "rangelst.hxx"
29 #include "editutil.hxx"
30 #include "attrib.hxx"
31 #include "xltracer.hxx"
32 #include "xistream.hxx"
33 #include "xistyle.hxx"
34 #include "excform.hxx"
35 #include "stringutil.hxx"
37 // Excel->Calc cell address/range conversion ==================================
39 namespace {
41 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
42 inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt32 nXclRow, SCTAB nScTab )
44 rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
45 rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
46 rScPos.SetTab( nScTab );
49 } // namespace
51 // ----------------------------------------------------------------------------
53 XclImpAddressConverter::XclImpAddressConverter( const XclImpRoot& rRoot ) :
54 XclAddressConverterBase( rRoot.GetTracer(), rRoot.GetScMaxPos() )
58 // cell address ---------------------------------------------------------------
60 bool XclImpAddressConverter::CheckAddress( const XclAddress& rXclPos, bool bWarn )
62 bool bValidCol = rXclPos.mnCol <= mnMaxCol;
63 bool bValidRow = rXclPos.mnRow <= mnMaxRow;
64 bool bValid = bValidCol && bValidRow;
65 if( !bValid && bWarn )
67 mbColTrunc |= !bValidCol;
68 mbRowTrunc |= !bValidRow;
69 mrTracer.TraceInvalidAddress( ScAddress(
70 static_cast< SCCOL >( rXclPos.mnCol ), static_cast< SCROW >( rXclPos.mnRow ), 0 ), maMaxPos );
72 return bValid;
75 bool XclImpAddressConverter::ConvertAddress( ScAddress& rScPos,
76 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
78 bool bValid = CheckAddress( rXclPos, bWarn );
79 if( bValid )
80 lclFillAddress( rScPos, rXclPos.mnCol, rXclPos.mnRow, nScTab );
81 return bValid;
84 ScAddress XclImpAddressConverter::CreateValidAddress(
85 const XclAddress& rXclPos, SCTAB nScTab, bool bWarn )
87 ScAddress aScPos( ScAddress::UNINITIALIZED );
88 if( !ConvertAddress( aScPos, rXclPos, nScTab, bWarn ) )
90 aScPos.SetCol( static_cast< SCCOL >( ::std::min( rXclPos.mnCol, mnMaxCol ) ) );
91 aScPos.SetRow( static_cast< SCROW >( ::std::min( rXclPos.mnRow, mnMaxRow ) ) );
92 aScPos.SetTab( limit_cast< SCTAB >( nScTab, 0, maMaxPos.Tab() ) );
94 return aScPos;
97 // cell range -----------------------------------------------------------------
99 bool XclImpAddressConverter::ConvertRange( ScRange& rScRange,
100 const XclRange& rXclRange, SCTAB nScTab1, SCTAB nScTab2, bool bWarn )
102 // check start position
103 bool bValidStart = CheckAddress( rXclRange.maFirst, bWarn );
104 if( bValidStart )
106 lclFillAddress( rScRange.aStart, rXclRange.maFirst.mnCol, rXclRange.maFirst.mnRow, nScTab1 );
108 // check & correct end position
109 sal_uInt16 nXclCol2 = rXclRange.maLast.mnCol;
110 sal_uInt32 nXclRow2 = rXclRange.maLast.mnRow;
111 if( !CheckAddress( rXclRange.maLast, bWarn ) )
113 nXclCol2 = ::std::min( nXclCol2, mnMaxCol );
114 nXclRow2 = ::std::min( nXclRow2, mnMaxRow );
116 lclFillAddress( rScRange.aEnd, nXclCol2, nXclRow2, nScTab2 );
118 return bValidStart;
121 // cell range list ------------------------------------------------------------
123 void XclImpAddressConverter::ConvertRangeList( ScRangeList& rScRanges,
124 const XclRangeList& rXclRanges, SCTAB nScTab, bool bWarn )
126 rScRanges.RemoveAll();
127 for( XclRangeList::const_iterator aIt = rXclRanges.begin(), aEnd = rXclRanges.end(); aIt != aEnd; ++aIt )
129 ScRange aScRange( ScAddress::UNINITIALIZED );
130 if( ConvertRange( aScRange, *aIt, nScTab, nScTab, bWarn ) )
131 rScRanges.Append( aScRange );
135 // String->EditEngine conversion ==============================================
137 namespace {
139 EditTextObject* lclCreateTextObject( const XclImpRoot& rRoot,
140 const XclImpString& rString, XclFontItemType eType, sal_uInt16 nXFIndex )
142 EditTextObject* pTextObj = 0;
144 const XclImpXFBuffer& rXFBuffer = rRoot.GetXFBuffer();
145 const XclImpFont* pFirstFont = rXFBuffer.GetFont( nXFIndex );
146 bool bFirstEscaped = pFirstFont && pFirstFont->HasEscapement();
148 if( rString.IsRich() || bFirstEscaped )
150 const XclImpFontBuffer& rFontBuffer = rRoot.GetFontBuffer();
151 const XclFormatRunVec& rFormats = rString.GetFormats();
153 ScEditEngineDefaulter& rEE = (eType == EXC_FONTITEM_NOTE) ?
154 static_cast< ScEditEngineDefaulter& >( rRoot.GetDoc().GetNoteEngine() ) : rRoot.GetEditEngine();
155 rEE.SetText( rString.GetText() );
157 SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
158 if( bFirstEscaped )
159 rFontBuffer.FillToItemSet( aItemSet, eType, rXFBuffer.GetFontIndex( nXFIndex ) );
160 ESelection aSelection;
162 XclFormatRun aNextRun;
163 XclFormatRunVec::const_iterator aIt = rFormats.begin();
164 XclFormatRunVec::const_iterator aEnd = rFormats.end();
166 if( aIt != aEnd )
167 aNextRun = *aIt++;
168 else
169 aNextRun.mnChar = 0xFFFF;
171 xub_StrLen nLen = rString.GetText().Len();
172 for( sal_uInt16 nChar = 0; nChar < nLen; ++nChar )
174 // reached new different formatted text portion
175 if( nChar >= aNextRun.mnChar )
177 // send items to edit engine
178 rEE.QuickSetAttribs( aItemSet, aSelection );
180 // start new item set
181 aItemSet.ClearItem();
182 rFontBuffer.FillToItemSet( aItemSet, eType, aNextRun.mnFontIdx );
184 // read new formatting information
185 if( aIt != aEnd )
186 aNextRun = *aIt++;
187 else
188 aNextRun.mnChar = 0xFFFF;
190 // reset selection start to current position
191 aSelection.nStartPara = aSelection.nEndPara;
192 aSelection.nStartPos = aSelection.nEndPos;
195 // set end of selection to current position
196 if( rString.GetText().GetChar( nChar ) == '\n' )
198 ++aSelection.nEndPara;
199 aSelection.nEndPos = 0;
201 else
202 ++aSelection.nEndPos;
205 // send items of last text portion to edit engine
206 rEE.QuickSetAttribs( aItemSet, aSelection );
208 pTextObj = rEE.CreateTextObject();
211 return pTextObj;
214 } // namespace
216 EditTextObject* XclImpStringHelper::CreateTextObject(
217 const XclImpRoot& rRoot, const XclImpString& rString )
219 return lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, 0 );
222 void XclImpStringHelper::SetToDocument(
223 ScDocument& rDoc, const ScAddress& rPos, const XclImpRoot& rRoot,
224 const XclImpString& rString, sal_uInt16 nXFIndex )
226 if (!rString.GetText().Len())
227 return;
229 ::std::auto_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
231 if (pTextObj.get())
233 rDoc.SetEditText(rPos, pTextObj.release());
235 else
237 OUString aStr = rString.GetText();
238 if (aStr.indexOf('\n') != -1 || aStr.indexOf(CHAR_CR) != -1)
240 // Multiline content.
241 ScFieldEditEngine& rEngine = rDoc.GetEditEngine();
242 rEngine.SetText(aStr);
243 rDoc.SetEditText(rPos, rEngine.CreateTextObject());
245 else
247 // Normal text cell.
248 ScSetStringParam aParam;
249 aParam.setTextInput();
250 rDoc.SetString(rPos, aStr, &aParam);
255 // Header/footer conversion ===================================================
257 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
258 mnHeight( 0 ),
259 mnMaxLineHt( 0 )
261 maSel.nStartPara = maSel.nEndPara = 0;
262 maSel.nStartPos = maSel.nEndPos = 0;
265 // ----------------------------------------------------------------------------
267 XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
268 XclImpRoot( rRoot ),
269 mrEE( rRoot.GetHFEditEngine() ),
270 mxFontData( new XclFontData ),
271 meCurrObj( EXC_HF_CENTER )
275 XclImpHFConverter::~XclImpHFConverter()
279 void XclImpHFConverter::ParseString( const String& rHFString )
281 // edit engine objects
282 mrEE.SetText( EMPTY_STRING );
283 maInfos.clear();
284 maInfos.resize( EXC_HF_PORTION_COUNT );
285 meCurrObj = EXC_HF_CENTER;
287 // parser temporaries
288 maCurrText.Erase();
289 String aReadFont; // current font name
290 String aReadStyle; // current font style
291 sal_uInt16 nReadHeight = 0; // current font height
292 ResetFontData();
294 /** State of the parser. */
295 enum XclHFParserState
297 xlPSText, /// Read text, search for functions.
298 xlPSFunc, /// Read function (token following a '&').
299 xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
300 xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"').
301 xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit).
302 } eState = xlPSText;
304 const sal_Unicode* pChar = rHFString.GetBuffer();
305 const sal_Unicode* pNull = pChar + rHFString.Len(); // pointer to teminating null char
306 while( *pChar )
308 switch( eState )
311 // --- read text character ---
313 case xlPSText:
315 switch( *pChar )
317 case '&': // new command
318 InsertText();
319 eState = xlPSFunc;
320 break;
321 case '\n': // line break
322 InsertText();
323 InsertLineBreak();
324 break;
325 default:
326 maCurrText += *pChar;
329 break;
331 // --- read control sequence ---
333 case xlPSFunc:
335 eState = xlPSText;
336 switch( *pChar )
338 case '&': maCurrText += '&'; break; // the '&' character
340 case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
341 case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
342 case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
344 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
345 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
346 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
347 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
348 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name
350 case 'Z': // file path
351 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name
352 if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') )
354 // &Z&F found - ignore the &F part
355 pChar += 2;
357 break;
358 case 'F': // file name
359 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_STRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
360 break;
362 case 'U': // underline
363 SetAttribs();
364 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
365 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
366 break;
367 case 'E': // double underline
368 SetAttribs();
369 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
370 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
371 break;
372 case 'S': // strikeout
373 SetAttribs();
374 mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
375 break;
376 case 'X': // superscript
377 SetAttribs();
378 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
379 EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
380 break;
381 case 'Y': // subsrcipt
382 SetAttribs();
383 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
384 EXC_FONTESC_NONE : EXC_FONTESC_SUB;
385 break;
387 case '\"': // font name
388 aReadFont.Erase();
389 aReadStyle.Erase();
390 eState = xlPSFont;
391 break;
392 default:
393 if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
395 nReadHeight = *pChar - '0';
396 eState = xlPSHeight;
400 break;
402 // --- read font name ---
404 case xlPSFont:
406 switch( *pChar )
408 case '\"':
409 --pChar;
410 // run through
411 case ',':
412 eState = xlPSFontStyle;
413 break;
414 default:
415 aReadFont += *pChar;
418 break;
420 // --- read font style ---
422 case xlPSFontStyle:
424 switch( *pChar )
426 case '\"':
427 SetAttribs();
428 if( aReadFont.Len() )
429 mxFontData->maName = aReadFont;
430 mxFontData->maStyle = aReadStyle;
431 eState = xlPSText;
432 break;
433 default:
434 aReadStyle += *pChar;
437 break;
439 // --- read font height ---
441 case xlPSHeight:
443 if( ('0' <= *pChar) && (*pChar <= '9') )
445 if( nReadHeight != 0xFFFF )
447 nReadHeight *= 10;
448 nReadHeight += (*pChar - '0');
449 if( nReadHeight > 1600 ) // max 1600pt = 32000twips
450 nReadHeight = 0xFFFF;
453 else
455 if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
457 SetAttribs();
458 mxFontData->mnHeight = nReadHeight * 20;
460 --pChar;
461 eState = xlPSText;
464 break;
466 ++pChar;
469 // finalize
470 CreateCurrObject();
471 maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
472 maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
473 maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
476 void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
478 ScPageHFItem aHFItem( nWhichId );
479 if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
480 aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
481 if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
482 aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
483 if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
484 aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
485 rItemSet.Put( aHFItem );
488 sal_Int32 XclImpHFConverter::GetTotalHeight() const
490 return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
491 ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
494 // private --------------------------------------------------------------------
496 sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
498 sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
499 return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
502 sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
504 return GetMaxLineHeight( meCurrObj );
507 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
509 sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
510 rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
513 void XclImpHFConverter::UpdateCurrMaxLineHeight()
515 UpdateMaxLineHeight( meCurrObj );
518 void XclImpHFConverter::SetAttribs()
520 ESelection& rSel = GetCurrSel();
521 if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
523 SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
524 XclImpFont aFont( GetRoot(), *mxFontData );
525 aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
526 mrEE.QuickSetAttribs( aItemSet, rSel );
527 rSel.nStartPara = rSel.nEndPara;
528 rSel.nStartPos = rSel.nEndPos;
532 void XclImpHFConverter::ResetFontData()
534 if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
535 *mxFontData = pFirstFont->GetFontData();
536 else
538 mxFontData->Clear();
539 mxFontData->mnHeight = 200;
543 void XclImpHFConverter::InsertText()
545 if( maCurrText.Len() )
547 ESelection& rSel = GetCurrSel();
548 mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
549 rSel.nEndPos = rSel.nEndPos + maCurrText.Len();
550 maCurrText.Erase();
551 UpdateCurrMaxLineHeight();
555 void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
557 ESelection& rSel = GetCurrSel();
558 mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
559 ++rSel.nEndPos;
560 UpdateCurrMaxLineHeight();
563 void XclImpHFConverter::InsertLineBreak()
565 ESelection& rSel = GetCurrSel();
566 mrEE.QuickInsertText( OUString('\n'), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
567 ++rSel.nEndPara;
568 rSel.nEndPos = 0;
569 GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
570 GetCurrInfo().mnMaxLineHt = 0;
573 void XclImpHFConverter::CreateCurrObject()
575 InsertText();
576 SetAttribs();
577 GetCurrObj().reset( mrEE.CreateTextObject() );
580 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
582 if( eNew != meCurrObj )
584 CreateCurrObject();
585 meCurrObj = eNew;
586 if( GetCurrObj().get() )
587 mrEE.SetText( *GetCurrObj() );
588 else
589 mrEE.SetText( EMPTY_STRING );
590 ResetFontData();
594 // URL conversion =============================================================
596 namespace {
598 void lclAppendUrlChar( String& rUrl, sal_Unicode cChar )
600 // encode special characters
601 switch( cChar )
603 case '#': rUrl.AppendAscii( "%23" ); break;
604 case '%': rUrl.AppendAscii( "%25" ); break;
605 default: rUrl.Append( cChar );
609 } // namespace
611 void XclImpUrlHelper::DecodeUrl(
612 String& rUrl, String& rTabName, bool& rbSameWb,
613 const XclImpRoot& rRoot, const String& rEncodedUrl )
615 enum
617 xlUrlInit, /// Initial state, read string mode character.
618 xlUrlPath, /// Read URL path.
619 xlUrlFileName, /// Read file name.
620 xlUrlSheetName, /// Read sheet name.
621 xlUrlRaw /// Raw mode. No control characters will occur.
622 } eState = xlUrlInit;
624 bool bEncoded = true;
625 rbSameWb = false;
627 sal_Unicode cCurrDrive = 0;
628 String aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
629 if( (aDosBase.Len() > 2) && aDosBase.EqualsAscii( ":\\", 1, 2 ) )
630 cCurrDrive = aDosBase.GetChar( 0 );
632 const sal_Unicode* pChar = rEncodedUrl.GetBuffer();
633 while( *pChar )
635 switch( eState )
638 // --- first character ---
640 case xlUrlInit:
642 switch( *pChar )
644 case EXC_URLSTART_ENCODED:
645 eState = xlUrlPath;
646 break;
647 case EXC_URLSTART_SELF:
648 case EXC_URLSTART_SELFENCODED:
649 rbSameWb = true;
650 eState = xlUrlSheetName;
651 break;
652 case '[':
653 bEncoded = false;
654 eState = xlUrlFileName;
655 break;
656 default:
657 bEncoded = false;
658 lclAppendUrlChar( rUrl, *pChar );
659 eState = xlUrlPath;
662 break;
664 // --- URL path ---
666 case xlUrlPath:
668 switch( *pChar )
670 case EXC_URL_DOSDRIVE:
672 if( *(pChar + 1) )
674 ++pChar;
675 if( *pChar == '@' )
676 rUrl.AppendAscii( "\\\\" );
677 else
679 lclAppendUrlChar( rUrl, *pChar );
680 rUrl.AppendAscii( ":\\" );
683 else
684 rUrl.AppendAscii( "<NULL-DRIVE!>" );
686 break;
687 case EXC_URL_DRIVEROOT:
688 if( cCurrDrive )
690 lclAppendUrlChar( rUrl, cCurrDrive );
691 rUrl.Append( ':' );
693 // run through
694 case EXC_URL_SUBDIR:
695 if( bEncoded )
696 rUrl.Append( '\\' );
697 else // control character in raw name -> DDE link
699 rUrl.Append( EXC_DDE_DELIM );
700 eState = xlUrlRaw;
702 break;
703 case EXC_URL_PARENTDIR:
704 rUrl.AppendAscii( "..\\" );
705 break;
706 case EXC_URL_RAW:
708 if( *(pChar + 1) )
710 xub_StrLen nLen = *++pChar;
711 for( xub_StrLen nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
712 lclAppendUrlChar( rUrl, *++pChar );
713 // rUrl.Append( ':' );
716 break;
717 case '[':
718 eState = xlUrlFileName;
719 break;
720 default:
721 lclAppendUrlChar( rUrl, *pChar );
724 break;
726 // --- file name ---
728 case xlUrlFileName:
730 switch( *pChar )
732 case ']': eState = xlUrlSheetName; break;
733 default: lclAppendUrlChar( rUrl, *pChar );
736 break;
738 // --- sheet name ---
740 case xlUrlSheetName:
741 rTabName.Append( *pChar );
742 break;
744 // --- raw read mode ---
746 case xlUrlRaw:
747 lclAppendUrlChar( rUrl, *pChar );
748 break;
751 ++pChar;
755 void XclImpUrlHelper::DecodeUrl(
756 String& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const String& rEncodedUrl )
758 String aTabName;
759 DecodeUrl( rUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
760 OSL_ENSURE( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
763 void XclImpUrlHelper::DecodeUrl(
764 OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const OUString& rEncodedUrl )
766 String aTabName;
767 String aUrl;
768 DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
769 rUrl = aUrl;
770 OSL_ENSURE( !aTabName.Len(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
773 bool XclImpUrlHelper::DecodeLink( String& rApplic, String& rTopic, const String rEncUrl )
775 xub_StrLen nPos = rEncUrl.Search( EXC_DDE_DELIM );
776 if( (nPos != STRING_NOTFOUND) && (0 < nPos) && (nPos + 1 < rEncUrl.Len()) )
778 rApplic = rEncUrl.Copy( 0, nPos );
779 rTopic = rEncUrl.Copy( nPos + 1 );
780 return true;
782 return false;
785 // Cached Values ==============================================================
787 XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
788 mfValue( 0.0 ),
789 mnBoolErr( 0 )
791 rStrm >> mnType;
792 switch( mnType )
794 case EXC_CACHEDVAL_EMPTY:
795 rStrm.Ignore( 8 );
796 break;
797 case EXC_CACHEDVAL_DOUBLE:
798 rStrm >> mfValue;
799 break;
800 case EXC_CACHEDVAL_STRING:
801 mxStr.reset( new String( rStrm.ReadUniString() ) );
802 break;
803 case EXC_CACHEDVAL_BOOL:
804 case EXC_CACHEDVAL_ERROR:
806 double fVal;
807 rStrm >> mnBoolErr;
808 rStrm.Ignore( 7 );
810 const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
811 XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
812 if( pScTokArr )
813 mxTokArr.reset( pScTokArr->Clone() );
815 break;
816 default:
817 OSL_FAIL( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
821 XclImpCachedValue::~XclImpCachedValue()
825 sal_uInt16 XclImpCachedValue::GetScError() const
827 return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
830 // Matrix Cached Values ==============================================================
832 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
833 mnScCols( 0 ),
834 mnScRows( 0 )
836 mnScCols = rStrm.ReaduInt8();
837 mnScRows = rStrm.ReaduInt16();
839 if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
841 // in BIFF2-BIFF7: 256 columns represented by 0 columns
842 if( mnScCols == 0 )
843 mnScCols = 256;
845 else
847 // in BIFF8: columns and rows decreaed by 1
848 ++mnScCols;
849 ++mnScRows;
852 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
853 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
854 maValueList.push_back( new XclImpCachedValue( rStrm ) );
857 XclImpCachedMatrix::~XclImpCachedMatrix()
861 ScMatrixRef XclImpCachedMatrix::CreateScMatrix() const
863 ScMatrixRef xScMatrix;
864 OSL_ENSURE( mnScCols * mnScRows == maValueList.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
865 if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.size() )
867 xScMatrix = new ScMatrix(mnScCols, mnScRows, 0.0);
868 XclImpValueList::const_iterator itValue = maValueList.begin();
869 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
871 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
873 switch( itValue->GetType() )
875 case EXC_CACHEDVAL_EMPTY:
876 // Excel shows 0.0 here, not an empty cell
877 xScMatrix->PutEmpty( nScCol, nScRow );
878 break;
879 case EXC_CACHEDVAL_DOUBLE:
880 xScMatrix->PutDouble( itValue->GetValue(), nScCol, nScRow );
881 break;
882 case EXC_CACHEDVAL_STRING:
883 xScMatrix->PutString( itValue->GetString(), nScCol, nScRow );
884 break;
885 case EXC_CACHEDVAL_BOOL:
886 xScMatrix->PutBoolean( itValue->GetBool(), nScCol, nScRow );
887 break;
888 case EXC_CACHEDVAL_ERROR:
889 xScMatrix->PutError( itValue->GetScError(), nScCol, nScRow );
890 break;
891 default:
892 OSL_FAIL( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
893 xScMatrix->PutEmpty( nScCol, nScRow );
895 ++itValue;
899 return xScMatrix;
902 // ============================================================================
904 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */