fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xihelper.cxx
blobcdf1c17bb1953a355ce34ff066287954b59ea619
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 <svl/sharedstringpool.hxx>
23 #include <editeng/editobj.hxx>
24 #include <tools/urlobj.hxx>
25 #include "scitems.hxx"
26 #include <editeng/eeitem.hxx>
27 #include <editeng/flditem.hxx>
28 #include "document.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"
35 #include "excform.hxx"
36 #include "stringutil.hxx"
37 #include "scmatrix.hxx"
38 #include "documentimport.hxx"
40 // Excel->Calc cell address/range conversion ==================================
42 namespace {
44 /** Fills the passed Calc address with the passed Excel cell coordinates without checking any limits. */
45 inline void lclFillAddress( ScAddress& rScPos, sal_uInt16 nXclCol, sal_uInt32 nXclRow, SCTAB nScTab )
47 rScPos.SetCol( static_cast< SCCOL >( nXclCol ) );
48 rScPos.SetRow( static_cast< SCROW >( nXclRow ) );
49 rScPos.SetTab( nScTab );
52 } // namespace
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( XclRangeVector::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 sal_Int32 nLen = rString.GetText().getLength();
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()[ 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 void XclImpStringHelper::SetToDocument(
224 ScDocumentImport& rDoc, const ScAddress& rPos, const XclImpRoot& rRoot,
225 const XclImpString& rString, sal_uInt16 nXFIndex )
227 if (rString.GetText().isEmpty())
228 return;
230 ::std::unique_ptr< EditTextObject > pTextObj( lclCreateTextObject( rRoot, rString, EXC_FONTITEM_EDITENG, nXFIndex ) );
232 if (pTextObj.get())
234 rDoc.setEditCell(rPos, pTextObj.release());
236 else
238 OUString aStr = rString.GetText();
239 if (aStr.indexOf('\n') != -1 || aStr.indexOf(CHAR_CR) != -1)
241 // Multiline content.
242 ScFieldEditEngine& rEngine = rDoc.getDoc().GetEditEngine();
243 rEngine.SetText(aStr);
244 rDoc.setEditCell(rPos, rEngine.CreateTextObject());
246 else
248 // Normal text cell.
249 rDoc.setStringCell(rPos, aStr);
254 // Header/footer conversion ===================================================
256 XclImpHFConverter::XclImpHFPortionInfo::XclImpHFPortionInfo() :
257 mnHeight( 0 ),
258 mnMaxLineHt( 0 )
260 maSel.nStartPara = maSel.nEndPara = 0;
261 maSel.nStartPos = maSel.nEndPos = 0;
264 XclImpHFConverter::XclImpHFConverter( const XclImpRoot& rRoot ) :
265 XclImpRoot( rRoot ),
266 mrEE( rRoot.GetHFEditEngine() ),
267 mxFontData( new XclFontData ),
268 meCurrObj( EXC_HF_CENTER )
272 XclImpHFConverter::~XclImpHFConverter()
276 void XclImpHFConverter::ParseString( const OUString& rHFString )
278 // edit engine objects
279 mrEE.SetText( EMPTY_OUSTRING );
280 maInfos.clear();
281 maInfos.resize( EXC_HF_PORTION_COUNT );
282 meCurrObj = EXC_HF_CENTER;
284 // parser temporaries
285 maCurrText.clear();
286 OUString aReadFont; // current font name
287 OUString aReadStyle; // current font style
288 sal_uInt16 nReadHeight = 0; // current font height
289 ResetFontData();
291 /** State of the parser. */
292 enum XclHFParserState
294 xlPSText, /// Read text, search for functions.
295 xlPSFunc, /// Read function (token following a '&').
296 xlPSFont, /// Read font name ('&' is followed by '"', reads until next '"' or ',').
297 xlPSFontStyle, /// Read font style name (font part after ',', reads until next '"').
298 xlPSHeight /// Read font height ('&' is followed by num. digits, reads until non-digit).
299 } eState = xlPSText;
301 const sal_Unicode* pChar = rHFString.getStr();
302 const sal_Unicode* pNull = pChar + rHFString.getLength(); // pointer to teminating null char
303 while( *pChar )
305 switch( eState )
308 // --- read text character ---
310 case xlPSText:
312 switch( *pChar )
314 case '&': // new command
315 InsertText();
316 eState = xlPSFunc;
317 break;
318 case '\n': // line break
319 InsertText();
320 InsertLineBreak();
321 break;
322 default:
323 maCurrText += OUString(*pChar);
326 break;
328 // --- read control sequence ---
330 case xlPSFunc:
332 eState = xlPSText;
333 switch( *pChar )
335 case '&': maCurrText += "&"; break; // the '&' character
337 case 'L': SetNewPortion( EXC_HF_LEFT ); break; // Left portion
338 case 'C': SetNewPortion( EXC_HF_CENTER ); break; // Center portion
339 case 'R': SetNewPortion( EXC_HF_RIGHT ); break; // Right portion
341 case 'P': InsertField( SvxFieldItem( SvxPageField(), EE_FEATURE_FIELD ) ); break; // page
342 case 'N': InsertField( SvxFieldItem( SvxPagesField(), EE_FEATURE_FIELD ) ); break; // page count
343 case 'D': InsertField( SvxFieldItem( SvxDateField(), EE_FEATURE_FIELD ) ); break; // date
344 case 'T': InsertField( SvxFieldItem( SvxTimeField(), EE_FEATURE_FIELD ) ); break; // time
345 case 'A': InsertField( SvxFieldItem( SvxTableField(), EE_FEATURE_FIELD ) ); break; // table name
347 case 'Z': // file path
348 InsertField( SvxFieldItem( SvxExtFileField(), EE_FEATURE_FIELD ) ); // convert to full name
349 if( (pNull - pChar >= 2) && (*(pChar + 1) == '&') && (*(pChar + 2) == 'F') )
351 // &Z&F found - ignore the &F part
352 pChar += 2;
354 break;
355 case 'F': // file name
356 InsertField( SvxFieldItem( SvxExtFileField( EMPTY_OUSTRING, SVXFILETYPE_VAR, SVXFILEFORMAT_NAME_EXT ), EE_FEATURE_FIELD ) );
357 break;
359 case 'U': // underline
360 SetAttribs();
361 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_SINGLE) ?
362 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_SINGLE;
363 break;
364 case 'E': // double underline
365 SetAttribs();
366 mxFontData->mnUnderline = (mxFontData->mnUnderline == EXC_FONTUNDERL_DOUBLE) ?
367 EXC_FONTUNDERL_NONE : EXC_FONTUNDERL_DOUBLE;
368 break;
369 case 'S': // strikeout
370 SetAttribs();
371 mxFontData->mbStrikeout = !mxFontData->mbStrikeout;
372 break;
373 case 'X': // superscript
374 SetAttribs();
375 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUPER) ?
376 EXC_FONTESC_NONE : EXC_FONTESC_SUPER;
377 break;
378 case 'Y': // subsrcipt
379 SetAttribs();
380 mxFontData->mnEscapem = (mxFontData->mnEscapem == EXC_FONTESC_SUB) ?
381 EXC_FONTESC_NONE : EXC_FONTESC_SUB;
382 break;
384 case '\"': // font name
385 aReadFont.clear();
386 aReadStyle.clear();
387 eState = xlPSFont;
388 break;
389 default:
390 if( ('0' <= *pChar) && (*pChar <= '9') ) // font size
392 nReadHeight = *pChar - '0';
393 eState = xlPSHeight;
397 break;
399 // --- read font name ---
401 case xlPSFont:
403 switch( *pChar )
405 case '\"':
406 --pChar;
407 // run through
408 case ',':
409 eState = xlPSFontStyle;
410 break;
411 default:
412 aReadFont += OUString(*pChar);
415 break;
417 // --- read font style ---
419 case xlPSFontStyle:
421 switch( *pChar )
423 case '\"':
424 SetAttribs();
425 if( !aReadFont.isEmpty() )
426 mxFontData->maName = aReadFont;
427 mxFontData->maStyle = aReadStyle;
428 eState = xlPSText;
429 break;
430 default:
431 aReadStyle += OUString(*pChar);
434 break;
436 // --- read font height ---
438 case xlPSHeight:
440 if( ('0' <= *pChar) && (*pChar <= '9') )
442 if( nReadHeight != 0xFFFF )
444 nReadHeight *= 10;
445 nReadHeight += (*pChar - '0');
446 if( nReadHeight > 1600 ) // max 1600pt = 32000twips
447 nReadHeight = 0xFFFF;
450 else
452 if( (nReadHeight != 0) && (nReadHeight != 0xFFFF) )
454 SetAttribs();
455 mxFontData->mnHeight = nReadHeight * 20;
457 --pChar;
458 eState = xlPSText;
461 break;
463 ++pChar;
466 // finalize
467 CreateCurrObject();
468 maInfos[ EXC_HF_LEFT ].mnHeight += GetMaxLineHeight( EXC_HF_LEFT );
469 maInfos[ EXC_HF_CENTER ].mnHeight += GetMaxLineHeight( EXC_HF_CENTER );
470 maInfos[ EXC_HF_RIGHT ].mnHeight += GetMaxLineHeight( EXC_HF_RIGHT );
473 void XclImpHFConverter::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nWhichId ) const
475 ScPageHFItem aHFItem( nWhichId );
476 if( maInfos[ EXC_HF_LEFT ].mxObj.get() )
477 aHFItem.SetLeftArea( *maInfos[ EXC_HF_LEFT ].mxObj );
478 if( maInfos[ EXC_HF_CENTER ].mxObj.get() )
479 aHFItem.SetCenterArea( *maInfos[ EXC_HF_CENTER ].mxObj );
480 if( maInfos[ EXC_HF_RIGHT ].mxObj.get() )
481 aHFItem.SetRightArea( *maInfos[ EXC_HF_RIGHT ].mxObj );
482 rItemSet.Put( aHFItem );
485 sal_Int32 XclImpHFConverter::GetTotalHeight() const
487 return ::std::max( maInfos[ EXC_HF_LEFT ].mnHeight,
488 ::std::max( maInfos[ EXC_HF_CENTER ].mnHeight, maInfos[ EXC_HF_RIGHT ].mnHeight ) );
491 // private --------------------------------------------------------------------
493 sal_uInt16 XclImpHFConverter::GetMaxLineHeight( XclImpHFPortion ePortion ) const
495 sal_uInt16 nMaxHt = maInfos[ ePortion ].mnMaxLineHt;
496 return (nMaxHt == 0) ? mxFontData->mnHeight : nMaxHt;
499 sal_uInt16 XclImpHFConverter::GetCurrMaxLineHeight() const
501 return GetMaxLineHeight( meCurrObj );
504 void XclImpHFConverter::UpdateMaxLineHeight( XclImpHFPortion ePortion )
506 sal_uInt16& rnMaxHt = maInfos[ ePortion ].mnMaxLineHt;
507 rnMaxHt = ::std::max( rnMaxHt, mxFontData->mnHeight );
510 void XclImpHFConverter::UpdateCurrMaxLineHeight()
512 UpdateMaxLineHeight( meCurrObj );
515 void XclImpHFConverter::SetAttribs()
517 ESelection& rSel = GetCurrSel();
518 if( (rSel.nStartPara != rSel.nEndPara) || (rSel.nStartPos != rSel.nEndPos) )
520 SfxItemSet aItemSet( mrEE.GetEmptyItemSet() );
521 XclImpFont aFont( GetRoot(), *mxFontData );
522 aFont.FillToItemSet( aItemSet, EXC_FONTITEM_HF );
523 mrEE.QuickSetAttribs( aItemSet, rSel );
524 rSel.nStartPara = rSel.nEndPara;
525 rSel.nStartPos = rSel.nEndPos;
529 void XclImpHFConverter::ResetFontData()
531 if( const XclImpFont* pFirstFont = GetFontBuffer().GetFont( EXC_FONT_APP ) )
532 *mxFontData = pFirstFont->GetFontData();
533 else
535 mxFontData->Clear();
536 mxFontData->mnHeight = 200;
540 void XclImpHFConverter::InsertText()
542 if( !maCurrText.isEmpty() )
544 ESelection& rSel = GetCurrSel();
545 mrEE.QuickInsertText( maCurrText, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
546 rSel.nEndPos = rSel.nEndPos + maCurrText.getLength();
547 maCurrText.clear();
548 UpdateCurrMaxLineHeight();
552 void XclImpHFConverter::InsertField( const SvxFieldItem& rFieldItem )
554 ESelection& rSel = GetCurrSel();
555 mrEE.QuickInsertField( rFieldItem, ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
556 ++rSel.nEndPos;
557 UpdateCurrMaxLineHeight();
560 void XclImpHFConverter::InsertLineBreak()
562 ESelection& rSel = GetCurrSel();
563 mrEE.QuickInsertText( OUString('\n'), ESelection( rSel.nEndPara, rSel.nEndPos, rSel.nEndPara, rSel.nEndPos ) );
564 ++rSel.nEndPara;
565 rSel.nEndPos = 0;
566 GetCurrInfo().mnHeight += GetCurrMaxLineHeight();
567 GetCurrInfo().mnMaxLineHt = 0;
570 void XclImpHFConverter::CreateCurrObject()
572 InsertText();
573 SetAttribs();
574 GetCurrObj().reset( mrEE.CreateTextObject() );
577 void XclImpHFConverter::SetNewPortion( XclImpHFPortion eNew )
579 if( eNew != meCurrObj )
581 CreateCurrObject();
582 meCurrObj = eNew;
583 if( GetCurrObj().get() )
584 mrEE.SetText( *GetCurrObj() );
585 else
586 mrEE.SetText( EMPTY_OUSTRING );
587 ResetFontData();
591 // URL conversion =============================================================
593 namespace {
595 void lclAppendUrlChar( OUString& rUrl, sal_Unicode cChar )
597 // encode special characters
598 switch( cChar )
600 case '#': rUrl += "%23"; break;
601 case '%': rUrl += "%25"; break;
602 default: rUrl += OUString( cChar );
606 } // namespace
608 void XclImpUrlHelper::DecodeUrl(
609 OUString& rUrl, OUString& rTabName, bool& rbSameWb,
610 const XclImpRoot& rRoot, const OUString& rEncodedUrl )
612 enum
614 xlUrlInit, /// Initial state, read string mode character.
615 xlUrlPath, /// Read URL path.
616 xlUrlFileName, /// Read file name.
617 xlUrlSheetName, /// Read sheet name.
618 xlUrlRaw /// Raw mode. No control characters will occur.
619 } eState = xlUrlInit;
621 bool bEncoded = true;
622 rbSameWb = false;
624 sal_Unicode cCurrDrive = 0;
625 OUString aDosBase( INetURLObject( rRoot.GetBasePath() ).getFSysPath( INetURLObject::FSYS_DOS ) );
626 if (!aDosBase.isEmpty() && aDosBase.match(":\\", 1))
627 cCurrDrive = aDosBase[0];
629 const sal_Unicode* pChar = rEncodedUrl.getStr();
630 while( *pChar )
632 switch( eState )
635 // --- first character ---
637 case xlUrlInit:
639 switch( *pChar )
641 case EXC_URLSTART_ENCODED:
642 eState = xlUrlPath;
643 break;
644 case EXC_URLSTART_SELF:
645 case EXC_URLSTART_SELFENCODED:
646 rbSameWb = true;
647 eState = xlUrlSheetName;
648 break;
649 case '[':
650 bEncoded = false;
651 eState = xlUrlFileName;
652 break;
653 default:
654 bEncoded = false;
655 lclAppendUrlChar( rUrl, *pChar );
656 eState = xlUrlPath;
659 break;
661 // --- URL path ---
663 case xlUrlPath:
665 switch( *pChar )
667 case EXC_URL_DOSDRIVE:
669 if( *(pChar + 1) )
671 ++pChar;
672 if( *pChar == '@' )
673 rUrl += "\\\\";
674 else
676 lclAppendUrlChar( rUrl, *pChar );
677 rUrl += ":\\";
680 else
681 rUrl += "<NULL-DRIVE!>";
683 break;
684 case EXC_URL_DRIVEROOT:
685 if( cCurrDrive )
687 lclAppendUrlChar( rUrl, cCurrDrive );
688 rUrl += ":";
690 // run through
691 case EXC_URL_SUBDIR:
692 if( bEncoded )
693 rUrl += "\\";
694 else // control character in raw name -> DDE link
696 rUrl += OUString( EXC_DDE_DELIM );
697 eState = xlUrlRaw;
699 break;
700 case EXC_URL_PARENTDIR:
701 rUrl += "..\\";
702 break;
703 case EXC_URL_RAW:
705 if( *(pChar + 1) )
707 sal_Int32 nLen = *++pChar;
708 for( sal_Int32 nChar = 0; (nChar < nLen) && *(pChar + 1); ++nChar )
709 lclAppendUrlChar( rUrl, *++pChar );
710 // rUrl.Append( ':' );
713 break;
714 case '[':
715 eState = xlUrlFileName;
716 break;
717 default:
718 lclAppendUrlChar( rUrl, *pChar );
721 break;
723 // --- file name ---
725 case xlUrlFileName:
727 switch( *pChar )
729 case ']': eState = xlUrlSheetName; break;
730 default: lclAppendUrlChar( rUrl, *pChar );
733 break;
735 // --- sheet name ---
737 case xlUrlSheetName:
738 rTabName += OUString( *pChar );
739 break;
741 // --- raw read mode ---
743 case xlUrlRaw:
744 lclAppendUrlChar( rUrl, *pChar );
745 break;
748 ++pChar;
752 void XclImpUrlHelper::DecodeUrl(
753 OUString& rUrl, bool& rbSameWb, const XclImpRoot& rRoot, const OUString& rEncodedUrl )
755 OUString aTabName;
756 OUString aUrl;
757 DecodeUrl( aUrl, aTabName, rbSameWb, rRoot, rEncodedUrl );
758 rUrl = aUrl;
759 OSL_ENSURE( aTabName.isEmpty(), "XclImpUrlHelper::DecodeUrl - sheet name ignored" );
762 bool XclImpUrlHelper::DecodeLink( OUString& rApplic, OUString& rTopic, const OUString& rEncUrl )
764 sal_Int32 nPos = rEncUrl.indexOf( EXC_DDE_DELIM );
765 if( (nPos > 0) && (nPos + 1 < rEncUrl.getLength()) )
767 rApplic = rEncUrl.copy( 0, nPos );
768 rTopic = rEncUrl.copy( nPos + 1 );
769 return true;
771 return false;
774 // Cached Values ==============================================================
776 XclImpCachedValue::XclImpCachedValue( XclImpStream& rStrm ) :
777 mfValue( 0.0 ),
778 mnBoolErr( 0 )
780 mnType = rStrm.ReaduInt8();
781 switch( mnType )
783 case EXC_CACHEDVAL_EMPTY:
784 rStrm.Ignore( 8 );
785 break;
786 case EXC_CACHEDVAL_DOUBLE:
787 mfValue = rStrm.ReadDouble();
788 break;
789 case EXC_CACHEDVAL_STRING:
790 maStr = rStrm.ReadUniString();
791 break;
792 case EXC_CACHEDVAL_BOOL:
793 case EXC_CACHEDVAL_ERROR:
795 double fVal;
796 mnBoolErr = rStrm.ReaduInt8();
797 rStrm.Ignore( 7 );
799 const ScTokenArray* pScTokArr = rStrm.GetRoot().GetOldFmlaConverter().GetBoolErr(
800 XclTools::ErrorToEnum( fVal, mnType == EXC_CACHEDVAL_ERROR, mnBoolErr ) );
801 if( pScTokArr )
802 mxTokArr.reset( pScTokArr->Clone() );
804 break;
805 default:
806 OSL_FAIL( "XclImpCachedValue::XclImpCachedValue - unknown data type" );
810 XclImpCachedValue::~XclImpCachedValue()
814 sal_uInt16 XclImpCachedValue::GetScError() const
816 return (mnType == EXC_CACHEDVAL_ERROR) ? XclTools::GetScErrorCode( mnBoolErr ) : 0;
819 // Matrix Cached Values ==============================================================
821 XclImpCachedMatrix::XclImpCachedMatrix( XclImpStream& rStrm ) :
822 mnScCols( 0 ),
823 mnScRows( 0 )
825 mnScCols = rStrm.ReaduInt8();
826 mnScRows = rStrm.ReaduInt16();
828 if( rStrm.GetRoot().GetBiff() <= EXC_BIFF5 )
830 // in BIFF2-BIFF7: 256 columns represented by 0 columns
831 if( mnScCols == 0 )
832 mnScCols = 256;
834 else
836 // in BIFF8: columns and rows decreaed by 1
837 ++mnScCols;
838 ++mnScRows;
841 //assuming worse case scenario of unknown types
842 const size_t nMinRecordSize = 1;
843 const size_t nMaxRows = rStrm.GetRecLeft() / (nMinRecordSize * mnScCols);
844 if (mnScRows > nMaxRows)
846 SAL_WARN("sc", "Parsing error: " << nMaxRows <<
847 " max possible rows, but " << mnScRows << " claimed, truncating");
848 mnScRows = nMaxRows;
851 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
852 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
853 maValueList.push_back( new XclImpCachedValue( rStrm ) );
856 XclImpCachedMatrix::~XclImpCachedMatrix()
860 ScMatrixRef XclImpCachedMatrix::CreateScMatrix( svl::SharedStringPool& rPool ) const
862 ScMatrixRef xScMatrix;
863 OSL_ENSURE( mnScCols * mnScRows == maValueList.size(), "XclImpCachedMatrix::CreateScMatrix - element count mismatch" );
864 if( mnScCols && mnScRows && static_cast< sal_uLong >( mnScCols * mnScRows ) <= maValueList.size() )
866 xScMatrix = new ScMatrix(mnScCols, mnScRows, 0.0);
867 XclImpValueList::const_iterator itValue = maValueList.begin();
868 for( SCSIZE nScRow = 0; nScRow < mnScRows; ++nScRow )
870 for( SCSIZE nScCol = 0; nScCol < mnScCols; ++nScCol )
872 switch( itValue->GetType() )
874 case EXC_CACHEDVAL_EMPTY:
875 // Excel shows 0.0 here, not an empty cell
876 xScMatrix->PutEmpty( nScCol, nScRow );
877 break;
878 case EXC_CACHEDVAL_DOUBLE:
879 xScMatrix->PutDouble( itValue->GetValue(), nScCol, nScRow );
880 break;
881 case EXC_CACHEDVAL_STRING:
882 xScMatrix->PutString(rPool.intern(itValue->GetString()), nScCol, nScRow);
883 break;
884 case EXC_CACHEDVAL_BOOL:
885 xScMatrix->PutBoolean( itValue->GetBool(), nScCol, nScRow );
886 break;
887 case EXC_CACHEDVAL_ERROR:
888 xScMatrix->PutError( itValue->GetScError(), nScCol, nScRow );
889 break;
890 default:
891 OSL_FAIL( "XclImpCachedMatrix::CreateScMatrix - unknown value type" );
892 xScMatrix->PutEmpty( nScCol, nScRow );
894 ++itValue;
898 return xScMatrix;
901 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */