fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / filter / excel / xestream.cxx
blob42ceb6c20fc2b332a1b7d8e490d94b1b63eb6f18
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 <stdarg.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <utility>
25 #include <rtl/ustring.hxx>
26 #include <rtl/ustrbuf.hxx>
27 #include <rtl/random.h>
28 #include <sax/fshelper.hxx>
29 #include <unotools/streamwrap.hxx>
31 #include "docuno.hxx"
32 #include "xestream.hxx"
33 #include "xladdress.hxx"
34 #include "xlstring.hxx"
35 #include "xeroot.hxx"
36 #include "xestyle.hxx"
37 #include "xcl97rec.hxx"
38 #include "rangelst.hxx"
39 #include "compiler.hxx"
40 #include "formulacell.hxx"
41 #include "tokenarray.hxx"
42 #include "tokenstringcontext.hxx"
43 #include "refreshtimerprotector.hxx"
44 #include "globstr.hrc"
46 #include <../../ui/inc/docsh.hxx>
47 #include <../../ui/inc/viewdata.hxx>
48 #include <excdoc.hxx>
50 #include <oox/token/tokens.hxx>
51 #include <formula/grammar.hxx>
52 #include <oox/export/drawingml.hxx>
53 #include <excelvbaproject.hxx>
55 #include <sfx2/docfile.hxx>
56 #include <sfx2/objsh.hxx>
57 #include <sfx2/app.hxx>
59 #include <com/sun/star/task/XStatusIndicator.hpp>
60 #include <boost/scoped_array.hpp>
62 #define DEBUG_XL_ENCRYPTION 0
64 using ::com::sun::star::embed::XStorage;
65 using ::com::sun::star::lang::XSingleServiceFactory;
66 using ::com::sun::star::registry::InvalidRegistryException;
67 using ::com::sun::star::registry::XRegistryKey;
68 using ::com::sun::star::uno::Exception;
69 using ::com::sun::star::uno::XInterface;
70 using ::utl::OStreamWrapper;
71 using ::std::vector;
73 using namespace com::sun::star;
74 using namespace ::com::sun::star::beans;
75 using namespace ::com::sun::star::io;
76 using namespace ::com::sun::star::lang;
77 using namespace ::com::sun::star::sheet;
78 using namespace ::com::sun::star::uno;
79 using namespace ::formula;
80 using namespace ::oox;
82 XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) :
83 mrStrm( rOutStrm ),
84 mrRoot( rRoot ),
85 mbUseEncrypter( false ),
86 mnMaxRecSize( nMaxRecSize ),
87 mnCurrMaxSize( 0 ),
88 mnMaxSliceSize( 0 ),
89 mnHeaderSize( 0 ),
90 mnCurrSize( 0 ),
91 mnSliceSize( 0 ),
92 mnPredictSize( 0 ),
93 mnLastSizePos( 0 ),
94 mbInRec( false )
96 if( mnMaxRecSize == 0 )
97 mnMaxRecSize = (mrRoot.GetBiff() <= EXC_BIFF5) ? EXC_MAXRECSIZE_BIFF5 : EXC_MAXRECSIZE_BIFF8;
98 mnMaxContSize = mnMaxRecSize;
101 XclExpStream::~XclExpStream()
103 mrStrm.Flush();
106 void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize )
108 OSL_ENSURE( !mbInRec, "XclExpStream::StartRecord - another record still open" );
109 DisableEncryption();
110 mnMaxContSize = mnCurrMaxSize = mnMaxRecSize;
111 mnPredictSize = nRecSize;
112 mbInRec = true;
113 InitRecord( nRecId );
114 SetSliceSize( 0 );
115 EnableEncryption();
118 void XclExpStream::EndRecord()
120 OSL_ENSURE( mbInRec, "XclExpStream::EndRecord - no record open" );
121 DisableEncryption();
122 UpdateRecSize();
123 mrStrm.Seek( STREAM_SEEK_TO_END );
124 mbInRec = false;
127 void XclExpStream::SetSliceSize( sal_uInt16 nSize )
129 mnMaxSliceSize = nSize;
130 mnSliceSize = 0;
133 XclExpStream& XclExpStream::operator<<( sal_Int8 nValue )
135 PrepareWrite( 1 );
136 if (mbUseEncrypter && HasValidEncrypter())
137 mxEncrypter->Encrypt(mrStrm, nValue);
138 else
139 mrStrm.WriteSChar( nValue );
140 return *this;
143 XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue )
145 PrepareWrite( 1 );
146 if (mbUseEncrypter && HasValidEncrypter())
147 mxEncrypter->Encrypt(mrStrm, nValue);
148 else
149 mrStrm.WriteUChar( nValue );
150 return *this;
153 XclExpStream& XclExpStream::operator<<( sal_Int16 nValue )
155 PrepareWrite( 2 );
156 if (mbUseEncrypter && HasValidEncrypter())
157 mxEncrypter->Encrypt(mrStrm, nValue);
158 else
159 mrStrm.WriteInt16( nValue );
160 return *this;
163 XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue )
165 PrepareWrite( 2 );
166 if (mbUseEncrypter && HasValidEncrypter())
167 mxEncrypter->Encrypt(mrStrm, nValue);
168 else
169 mrStrm.WriteUInt16( nValue );
170 return *this;
173 XclExpStream& XclExpStream::operator<<( sal_Int32 nValue )
175 PrepareWrite( 4 );
176 if (mbUseEncrypter && HasValidEncrypter())
177 mxEncrypter->Encrypt(mrStrm, nValue);
178 else
179 mrStrm.WriteInt32( nValue );
180 return *this;
183 XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue )
185 PrepareWrite( 4 );
186 if (mbUseEncrypter && HasValidEncrypter())
187 mxEncrypter->Encrypt(mrStrm, nValue);
188 else
189 mrStrm.WriteUInt32( nValue );
190 return *this;
193 XclExpStream& XclExpStream::operator<<( float fValue )
195 PrepareWrite( 4 );
196 if (mbUseEncrypter && HasValidEncrypter())
197 mxEncrypter->Encrypt(mrStrm, fValue);
198 else
199 mrStrm.WriteFloat( fValue );
200 return *this;
203 XclExpStream& XclExpStream::operator<<( double fValue )
205 PrepareWrite( 8 );
206 if (mbUseEncrypter && HasValidEncrypter())
207 mxEncrypter->Encrypt(mrStrm, fValue);
208 else
209 mrStrm.WriteDouble( fValue );
210 return *this;
213 sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes )
215 sal_Size nRet = 0;
216 if( pData && (nBytes > 0) )
218 if( mbInRec )
220 const sal_uInt8* pBuffer = static_cast< const sal_uInt8* >( pData );
221 sal_Size nBytesLeft = nBytes;
222 bool bValid = true;
224 while( bValid && (nBytesLeft > 0) )
226 sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
227 sal_Size nWriteRet = nWriteLen;
228 if (mbUseEncrypter && HasValidEncrypter())
230 OSL_ENSURE(nWriteLen > 0, "XclExpStream::Write: write length is 0!");
231 vector<sal_uInt8> aBytes(nWriteLen);
232 memcpy(&aBytes[0], pBuffer, nWriteLen);
233 mxEncrypter->EncryptBytes(mrStrm, aBytes);
234 // TODO: How do I check if all the bytes have been successfully written ?
236 else
238 nWriteRet = mrStrm.Write( pBuffer, nWriteLen );
239 bValid = (nWriteLen == nWriteRet);
240 OSL_ENSURE( bValid, "XclExpStream::Write - stream write error" );
242 pBuffer += nWriteRet;
243 nRet += nWriteRet;
244 nBytesLeft -= nWriteRet;
245 UpdateSizeVars( nWriteRet );
248 else
249 nRet = mrStrm.Write( pData, nBytes );
251 return nRet;
254 void XclExpStream::WriteZeroBytes( sal_Size nBytes )
256 if( mbInRec )
258 sal_Size nBytesLeft = nBytes;
259 while( nBytesLeft > 0 )
261 sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft );
262 WriteRawZeroBytes( nWriteLen );
263 nBytesLeft -= nWriteLen;
264 UpdateSizeVars( nWriteLen );
267 else
268 WriteRawZeroBytes( nBytes );
271 void XclExpStream::WriteZeroBytesToRecord( sal_Size nBytes )
273 if (!mbInRec)
274 // not in record.
275 return;
277 sal_uInt8 nZero = 0;
278 for (sal_Size i = 0; i < nBytes; ++i)
279 *this << nZero;
282 void XclExpStream::CopyFromStream(SvStream& rInStrm, sal_uInt64 const nBytes)
284 sal_uInt64 const nRemaining(rInStrm.remainingSize());
285 sal_uInt64 nBytesLeft = ::std::min(nBytes, nRemaining);
286 if( nBytesLeft > 0 )
288 const sal_Size nMaxBuffer = 4096;
289 boost::scoped_array<sal_uInt8> pBuffer(
290 new sal_uInt8[ ::std::min<sal_Size>(nBytesLeft, nMaxBuffer) ]);
291 bool bValid = true;
293 while( bValid && (nBytesLeft > 0) )
295 sal_Size nWriteLen = ::std::min<sal_Size>(nBytesLeft, nMaxBuffer);
296 rInStrm.Read( pBuffer.get(), nWriteLen );
297 sal_Size nWriteRet = Write( pBuffer.get(), nWriteLen );
298 bValid = (nWriteLen == nWriteRet);
299 nBytesLeft -= nWriteRet;
304 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec& rBuffer, sal_uInt8 nFlags )
306 SetSliceSize( 0 );
307 nFlags &= EXC_STRF_16BIT; // repeat only 16bit flag
308 sal_uInt16 nCharLen = nFlags ? 2 : 1;
310 ScfUInt16Vec::const_iterator aEnd = rBuffer.end();
311 for( ScfUInt16Vec::const_iterator aIter = rBuffer.begin(); aIter != aEnd; ++aIter )
313 if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
315 StartContinue();
316 operator<<( nFlags );
318 if( nCharLen == 2 )
319 operator<<( *aIter );
320 else
321 operator<<( static_cast< sal_uInt8 >( *aIter ) );
325 // Xcl has an obscure sense of whether starting a new record or not,
326 // and crashes if it encounters the string header at the very end of a record.
327 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
328 void XclExpStream::WriteByteString( const OString& rString, sal_uInt16 nMaxLen, bool b16BitCount )
330 SetSliceSize( 0 );
331 sal_Size nLen = ::std::min< sal_Size >( rString.getLength(), nMaxLen );
332 if( !b16BitCount )
333 nLen = ::std::min< sal_Size >( nLen, 0xFF );
335 sal_uInt16 nLeft = PrepareWrite();
336 sal_uInt16 nLenFieldSize = b16BitCount ? 2 : 1;
337 if( mbInRec && (nLeft <= nLenFieldSize) )
338 StartContinue();
340 if( b16BitCount )
341 operator<<( static_cast< sal_uInt16 >( nLen ) );
342 else
343 operator<<( static_cast< sal_uInt8 >( nLen ) );
344 Write( rString.getStr(), nLen );
347 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer )
349 SetSliceSize( 0 );
350 Write( &rBuffer[ 0 ], rBuffer.size() );
353 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter )
355 mxEncrypter = xEncrypter;
358 bool XclExpStream::HasValidEncrypter() const
360 return mxEncrypter && mxEncrypter->IsValid();
363 void XclExpStream::EnableEncryption( bool bEnable )
365 mbUseEncrypter = bEnable && HasValidEncrypter();
368 void XclExpStream::DisableEncryption()
370 EnableEncryption(false);
373 sal_uInt64 XclExpStream::SetSvStreamPos(sal_uInt64 const nPos)
375 OSL_ENSURE( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
376 return mbInRec ? 0 : mrStrm.Seek( nPos );
379 // private --------------------------------------------------------------------
381 void XclExpStream::InitRecord( sal_uInt16 nRecId )
383 mrStrm.Seek( STREAM_SEEK_TO_END );
384 mrStrm.WriteUInt16( nRecId );
386 mnLastSizePos = mrStrm.Tell();
387 mnHeaderSize = static_cast< sal_uInt16 >( ::std::min< sal_Size >( mnPredictSize, mnCurrMaxSize ) );
388 mrStrm.WriteUInt16( mnHeaderSize );
389 mnCurrSize = mnSliceSize = 0;
392 void XclExpStream::UpdateRecSize()
394 if( mnCurrSize != mnHeaderSize )
396 mrStrm.Seek( mnLastSizePos );
397 mrStrm.WriteUInt16( mnCurrSize );
401 void XclExpStream::UpdateSizeVars( sal_Size nSize )
403 OSL_ENSURE( mnCurrSize + nSize <= mnCurrMaxSize, "XclExpStream::UpdateSizeVars - record overwritten" );
404 mnCurrSize = mnCurrSize + static_cast< sal_uInt16 >( nSize );
406 if( mnMaxSliceSize > 0 )
408 OSL_ENSURE( mnSliceSize + nSize <= mnMaxSliceSize, "XclExpStream::UpdateSizeVars - slice overwritten" );
409 mnSliceSize = mnSliceSize + static_cast< sal_uInt16 >( nSize );
410 if( mnSliceSize >= mnMaxSliceSize )
411 mnSliceSize = 0;
415 void XclExpStream::StartContinue()
417 UpdateRecSize();
418 mnCurrMaxSize = mnMaxContSize;
419 mnPredictSize -= mnCurrSize;
420 InitRecord( EXC_ID_CONT );
423 void XclExpStream::PrepareWrite( sal_uInt16 nSize )
425 if( mbInRec )
427 if( (mnCurrSize + nSize > mnCurrMaxSize) ||
428 ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
429 StartContinue();
430 UpdateSizeVars( nSize );
434 sal_uInt16 XclExpStream::PrepareWrite()
436 sal_uInt16 nRet = 0;
437 if( mbInRec )
439 if( (mnCurrSize >= mnCurrMaxSize) ||
440 ((mnMaxSliceSize > 0) && (mnSliceSize == 0) && (mnCurrSize + mnMaxSliceSize > mnCurrMaxSize)) )
441 StartContinue();
442 UpdateSizeVars( 0 );
444 nRet = (mnMaxSliceSize > 0) ? (mnMaxSliceSize - mnSliceSize) : (mnCurrMaxSize - mnCurrSize);
446 return nRet;
449 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes )
451 const sal_uInt32 nData = 0;
452 sal_Size nBytesLeft = nBytes;
453 while( nBytesLeft >= sizeof( nData ) )
455 mrStrm.WriteUInt32( nData );
456 nBytesLeft -= sizeof( nData );
458 if( nBytesLeft )
459 mrStrm.Write( &nData, nBytesLeft );
462 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot ) :
463 mnOldPos(STREAM_SEEK_TO_END),
464 mbValid(false)
466 Sequence< NamedValue > aEncryptionData = rRoot.GetEncryptionData();
467 if( !aEncryptionData.hasElements() )
468 // Empty password. Get the default biff8 password.
469 aEncryptionData = rRoot.GenerateDefaultEncryptionData();
470 Init( aEncryptionData );
473 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
477 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 pnSaltDigest[16] ) const
479 if ( sizeof( mpnSaltDigest ) == 16 )
480 memcpy( pnSaltDigest, mpnSaltDigest, 16 );
483 void XclExpBiff8Encrypter::GetSalt( sal_uInt8 pnSalt[16] ) const
485 if ( sizeof( mpnSalt ) == 16 )
486 memcpy( pnSalt, mpnSalt, 16 );
489 void XclExpBiff8Encrypter::GetDocId( sal_uInt8 pnDocId[16] ) const
491 if ( sizeof( mpnDocId ) == 16 )
492 memcpy( pnDocId, mpnDocId, 16 );
495 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData )
497 vector<sal_uInt8> aByte(1);
498 aByte[0] = nData;
499 EncryptBytes(rStrm, aByte);
502 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData )
504 ::std::vector<sal_uInt8> pnBytes(2);
505 pnBytes[0] = nData & 0xFF;
506 pnBytes[1] = (nData >> 8) & 0xFF;
507 EncryptBytes(rStrm, pnBytes);
510 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData )
512 ::std::vector<sal_uInt8> pnBytes(4);
513 pnBytes[0] = nData & 0xFF;
514 pnBytes[1] = (nData >> 8) & 0xFF;
515 pnBytes[2] = (nData >> 16) & 0xFF;
516 pnBytes[3] = (nData >> 24) & 0xFF;
517 EncryptBytes(rStrm, pnBytes);
520 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue )
522 ::std::vector<sal_uInt8> pnBytes(4);
523 memcpy(&pnBytes[0], &fValue, 4);
524 EncryptBytes(rStrm, pnBytes);
527 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue )
529 ::std::vector<sal_uInt8> pnBytes(8);
530 memcpy(&pnBytes[0], &fValue, 8);
531 EncryptBytes(rStrm, pnBytes);
534 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData )
536 Encrypt(rStrm, static_cast<sal_uInt8>(nData));
539 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData )
541 Encrypt(rStrm, static_cast<sal_uInt16>(nData));
544 void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData )
546 Encrypt(rStrm, static_cast<sal_uInt32>(nData));
549 void XclExpBiff8Encrypter::Init( const Sequence< NamedValue >& rEncryptionData )
551 mbValid = false;
553 if( maCodec.InitCodec( rEncryptionData ) )
555 maCodec.GetDocId( mpnDocId );
557 // generate the salt here
558 TimeValue aTime;
559 osl_getSystemTime( &aTime );
560 rtlRandomPool aRandomPool = rtl_random_createPool ();
561 rtl_random_addBytes( aRandomPool, &aTime, 8 );
562 rtl_random_getBytes( aRandomPool, mpnSalt, 16 );
563 rtl_random_destroyPool( aRandomPool );
565 memset( mpnSaltDigest, 0, sizeof( mpnSaltDigest ) );
567 // generate salt hash.
568 ::msfilter::MSCodec_Std97 aCodec;
569 aCodec.InitCodec( rEncryptionData );
570 aCodec.CreateSaltDigest( mpnSalt, mpnSaltDigest );
572 // verify to make sure it's in good shape.
573 mbValid = maCodec.VerifyKey( mpnSalt, mpnSaltDigest );
577 sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos )
579 return static_cast< sal_uInt32 >( nStrmPos / EXC_ENCR_BLOCKSIZE );
582 sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos )
584 return static_cast< sal_uInt16 >( nStrmPos % EXC_ENCR_BLOCKSIZE );
587 void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes )
589 sal_uInt64 nStrmPos = rStrm.Tell();
590 sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos);
591 sal_uInt32 nBlockPos = GetBlockPos(nStrmPos);
593 #if DEBUG_XL_ENCRYPTION
594 fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
595 nStrmPos, nBlockOffset, nBlockPos);
596 #endif
598 sal_uInt16 nSize = static_cast< sal_uInt16 >( aBytes.size() );
599 if (nSize == 0)
600 return;
602 #if DEBUG_XL_ENCRYPTION
603 fprintf(stdout, "RAW: ");
604 for (sal_uInt16 i = 0; i < nSize; ++i)
605 fprintf(stdout, "%2.2X ", aBytes[i]);
606 fprintf(stdout, "\n");
607 #endif
609 if (mnOldPos != nStrmPos)
611 sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos);
612 sal_uInt32 nOldBlockPos = GetBlockPos(mnOldPos);
614 if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) )
616 maCodec.InitCipher(nBlockPos);
617 nOldOffset = 0;
620 if (nBlockOffset > nOldOffset)
621 maCodec.Skip(nBlockOffset - nOldOffset);
624 sal_uInt16 nBytesLeft = nSize;
625 sal_uInt16 nPos = 0;
626 while (nBytesLeft > 0)
628 sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset;
629 sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft);
631 bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes);
632 OSL_ENSURE(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
633 (void) bRet; // to remove a silly compiler warning.
635 sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes);
636 OSL_ENSURE(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
637 (void) nRet; // to remove a silly compiler warning.
639 nStrmPos = rStrm.Tell();
640 nBlockOffset = GetOffsetInBlock(nStrmPos);
641 nBlockPos = GetBlockPos(nStrmPos);
642 if (nBlockOffset == 0)
643 maCodec.InitCipher(nBlockPos);
645 nBytesLeft -= nEncBytes;
646 nPos += nEncBytes;
648 mnOldPos = nStrmPos;
651 static const char* lcl_GetErrorString( sal_uInt16 nScErrCode )
653 sal_uInt8 nXclErrCode = XclTools::GetXclErrorCode( nScErrCode );
654 switch( nXclErrCode )
656 case EXC_ERR_NULL: return "#NULL!";
657 case EXC_ERR_DIV0: return "#DIV/0!";
658 case EXC_ERR_VALUE: return "#VALUE!";
659 case EXC_ERR_REF: return "#REF!";
660 case EXC_ERR_NAME: return "#NAME?";
661 case EXC_ERR_NUM: return "#NUM!";
662 case EXC_ERR_NA:
663 default: return "#N/A";
667 void XclXmlUtils::GetFormulaTypeAndValue( ScFormulaCell& rCell, const char*& rsType, OUString& rsValue )
669 sc::FormulaResultValue aResValue = rCell.GetResult();
671 switch (aResValue.meType)
673 case sc::FormulaResultValue::Error:
674 rsType = "e";
675 rsValue = ToOUString(lcl_GetErrorString(aResValue.mnError));
676 break;
677 case sc::FormulaResultValue::Value:
678 rsType = "n";
679 rsValue = OUString::number(aResValue.mfValue);
680 break;
681 case sc::FormulaResultValue::String:
682 rsType = "str";
683 rsValue = rCell.GetString().getString();
684 break;
685 case sc::FormulaResultValue::Invalid:
686 default:
687 // TODO : double-check this to see if this is correct.
688 rsType = "inlineStr";
689 rsValue = rCell.GetString().getString();
693 OUString XclXmlUtils::GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId )
695 OUStringBuffer sBuf;
696 if( sStreamDir )
697 sBuf.appendAscii( sStreamDir );
698 sBuf.appendAscii( sStream );
699 if( nId )
700 sBuf.append( nId );
701 if( strstr(sStream, "vml") )
702 sBuf.appendAscii( ".vml" );
703 else
704 sBuf.appendAscii( ".xml" );
705 return sBuf.makeStringAndClear();
708 OString XclXmlUtils::ToOString( const Color& rColor )
710 char buf[9];
711 sprintf( buf, "%.2X%.2X%.2X%.2X", 0xFF-rColor.GetTransparency(), rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue() );
712 buf[8] = '\0';
713 return OString( buf );
716 OString XclXmlUtils::ToOString( const OUString& s )
718 return OUStringToOString( s, RTL_TEXTENCODING_UTF8 );
721 OStringBuffer& XclXmlUtils::ToOString( OStringBuffer& s, const ScAddress& rAddress )
723 rAddress.Format(s, SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1));
724 return s;
727 OString XclXmlUtils::ToOString( const ScfUInt16Vec& rBuffer )
729 if(rBuffer.empty())
730 return OString();
732 const sal_uInt16* pBuffer = &rBuffer [0];
733 return OString( pBuffer, rBuffer.size(), RTL_TEXTENCODING_UTF8 );
736 OString XclXmlUtils::ToOString( const ScRange& rRange )
738 OUString sRange(rRange.Format(SCA_VALID, NULL, ScAddress::Details( FormulaGrammar::CONV_XL_A1)));
739 return ToOString( sRange );
742 OString XclXmlUtils::ToOString( const ScRangeList& rRangeList )
744 OUString s;
745 rRangeList.Format(s, SCA_VALID, NULL, FormulaGrammar::CONV_XL_A1, ' ');
746 return ToOString( s );
749 static ScAddress lcl_ToAddress( const XclAddress& rAddress )
751 ScAddress aAddress;
753 // For some reason, ScRange::Format() returns omits row numbers if
754 // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
755 // like "A:IV" (i.e. no row numbers). Prevent this.
756 // KOHEI: Find out if the above comment is still true.
757 aAddress.SetRow( std::min<sal_Int32>( rAddress.mnRow, MAXROW ) );
758 aAddress.SetCol( static_cast<sal_Int16>(std::min<sal_Int32>( rAddress.mnCol, MAXCOL )) );
760 return aAddress;
763 OStringBuffer& XclXmlUtils::ToOString( OStringBuffer& s, const XclAddress& rAddress )
765 return ToOString( s, lcl_ToAddress( rAddress ));
768 OString XclXmlUtils::ToOString( const XclExpString& s )
770 OSL_ENSURE( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
771 return ToOString( s.GetUnicodeBuffer() );
774 static ScRange lcl_ToRange( const XclRange& rRange )
776 ScRange aRange;
778 aRange.aStart = lcl_ToAddress( rRange.maFirst );
779 aRange.aEnd = lcl_ToAddress( rRange.maLast );
781 return aRange;
784 OString XclXmlUtils::ToOString( const XclRange& rRange )
786 return ToOString( lcl_ToRange( rRange ) );
789 OString XclXmlUtils::ToOString( const XclRangeList& rRanges )
791 ScRangeList aRanges;
792 for( XclRangeVector::const_iterator i = rRanges.begin(), end = rRanges.end();
793 i != end; ++i )
795 aRanges.Append( lcl_ToRange( *i ) );
797 return ToOString( aRanges );
800 OUString XclXmlUtils::ToOUString( const char* s )
802 return OUString( s, (sal_Int32) strlen( s ), RTL_TEXTENCODING_ASCII_US );
805 OUString XclXmlUtils::ToOUString( const ScfUInt16Vec& rBuf, sal_Int32 nStart, sal_Int32 nLength )
807 if( nLength == -1 || ( nLength > ((sal_Int32)rBuf.size() - nStart) ) )
808 nLength = (rBuf.size() - nStart);
810 return (nLength > 0) ? OUString( &rBuf[nStart], nLength ) : OUString();
813 OUString XclXmlUtils::ToOUString(
814 sc::CompileFormulaContext& rCtx, const ScAddress& rAddress, const ScTokenArray* pTokenArray )
816 ScCompiler aCompiler( rCtx, rAddress, const_cast<ScTokenArray&>(*pTokenArray));
818 aCompiler.SetGrammar(FormulaGrammar::GRAM_OOXML);
820 OUStringBuffer aBuffer( pTokenArray->GetLen() * 5 );
821 aCompiler.CreateStringFromTokenArray( aBuffer );
822 return aBuffer.makeStringAndClear();
825 OUString XclXmlUtils::ToOUString( const XclExpString& s )
827 OSL_ENSURE( !s.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
828 return ToOUString( s.GetUnicodeBuffer() );
831 const char* XclXmlUtils::ToPsz( bool b )
833 return b ? "true" : "false";
836 const char* XclXmlUtils::ToPsz10( bool b )
838 // xlsx seems to use "1" or "0" for boolean values. I wonder it ever uses
839 // the "true" "false" variant.
840 return b ? "1" : "0";
843 sax_fastparser::FSHelperPtr XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int32 nValue )
845 pStream->startElement( nElement, FSEND );
846 pStream->write( nValue );
847 pStream->endElement( nElement );
849 return pStream;
852 sax_fastparser::FSHelperPtr XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, sal_Int64 nValue )
854 pStream->startElement( nElement, FSEND );
855 pStream->write( nValue );
856 pStream->endElement( nElement );
858 return pStream;
861 sax_fastparser::FSHelperPtr XclXmlUtils::WriteElement( sax_fastparser::FSHelperPtr pStream, sal_Int32 nElement, const char* sValue )
863 pStream->startElement( nElement, FSEND );
864 pStream->write( sValue );
865 pStream->endElement( nElement );
867 return pStream;
870 static void lcl_WriteValue( sax_fastparser::FSHelperPtr& rStream, sal_Int32 nElement, const char* pValue )
872 if( !pValue )
873 return;
874 rStream->singleElement( nElement,
875 XML_val, pValue,
876 FSEND );
879 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline, bool& bHaveUnderline )
881 bHaveUnderline = true;
882 switch( eUnderline )
884 // OOXTODO: doubleAccounting, singleAccounting
885 // OOXTODO: what should be done with the other FontUnderline values?
886 case UNDERLINE_SINGLE: return "single";
887 case UNDERLINE_DOUBLE: return "double";
888 case UNDERLINE_NONE:
889 default: bHaveUnderline = false; return "none";
893 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement, bool& bHaveAlignment )
895 bHaveAlignment = true;
896 switch( eEscapement )
898 case SVX_ESCAPEMENT_SUPERSCRIPT: return "superscript";
899 case SVX_ESCAPEMENT_SUBSCRIPT: return "subscript";
900 case SVX_ESCAPEMENT_OFF:
901 default: bHaveAlignment = false; return "baseline";
905 sax_fastparser::FSHelperPtr XclXmlUtils::WriteFontData( sax_fastparser::FSHelperPtr pStream, const XclFontData& rFontData, sal_Int32 nFontId )
907 bool bHaveUnderline, bHaveVertAlign;
908 const char* pUnderline = lcl_GetUnderlineStyle( rFontData.GetScUnderline(), bHaveUnderline );
909 const char* pVertAlign = lcl_ToVerticalAlignmentRun( rFontData.GetScEscapement(), bHaveVertAlign );
911 lcl_WriteValue( pStream, XML_b, rFontData.mnWeight > 400 ? XclXmlUtils::ToPsz( rFontData.mnWeight > 400 ) : NULL );
912 lcl_WriteValue( pStream, XML_i, rFontData.mbItalic ? XclXmlUtils::ToPsz( rFontData.mbItalic ) : NULL );
913 lcl_WriteValue( pStream, XML_strike, rFontData.mbStrikeout ? XclXmlUtils::ToPsz( rFontData.mbStrikeout ) : NULL );
914 // OOXTODO: lcl_WriteValue( rStream, XML_condense, ); // mac compatibility setting
915 // OOXTODO: lcl_WriteValue( rStream, XML_extend, ); // compatibility setting
916 lcl_WriteValue( pStream, XML_outline, rFontData.mbOutline ? XclXmlUtils::ToPsz( rFontData.mbOutline ) : NULL );
917 lcl_WriteValue( pStream, XML_shadow, rFontData.mbShadow ? XclXmlUtils::ToPsz( rFontData.mbShadow ) : NULL );
918 lcl_WriteValue( pStream, XML_u, bHaveUnderline ? pUnderline : NULL );
919 lcl_WriteValue( pStream, XML_vertAlign, bHaveVertAlign ? pVertAlign : NULL );
920 lcl_WriteValue( pStream, XML_sz, OString::number( (double) (rFontData.mnHeight / 20.0) ).getStr() ); // Twips->Pt
921 if( rFontData.maColor != Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
922 pStream->singleElement( XML_color,
923 // OOXTODO: XML_auto, bool
924 // OOXTODO: XML_indexed, uint
925 XML_rgb, XclXmlUtils::ToOString( rFontData.maColor ).getStr(),
926 // OOXTODO: XML_theme, index into <clrScheme/>
927 // OOXTODO: XML_tint, double
928 FSEND );
929 lcl_WriteValue( pStream, nFontId, XclXmlUtils::ToOString( rFontData.maName ).getStr() );
930 lcl_WriteValue( pStream, XML_family, OString::number( rFontData.mnFamily ).getStr() );
931 lcl_WriteValue( pStream, XML_charset, rFontData.mnCharSet != 0 ? OString::number( rFontData.mnCharSet ).getStr() : NULL );
933 return pStream;
936 XclExpXmlStream::XclExpXmlStream( const Reference< XComponentContext >& rCC )
937 : XmlFilterBase( rCC ),
938 mpRoot( NULL )
942 XclExpXmlStream::~XclExpXmlStream()
944 assert(maStreams.empty() && "Forgotten PopStream()?");
947 sax_fastparser::FSHelperPtr& XclExpXmlStream::GetCurrentStream()
949 OSL_ENSURE( !maStreams.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
950 return maStreams.top();
953 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream )
955 maStreams.push( aStream );
958 void XclExpXmlStream::PopStream()
960 OSL_ENSURE( !maStreams.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
961 maStreams.pop();
964 sax_fastparser::FSHelperPtr XclExpXmlStream::GetStreamForPath( const OUString& sPath )
966 if( maOpenedStreamMap.find( sPath ) == maOpenedStreamMap.end() )
967 return sax_fastparser::FSHelperPtr();
968 return maOpenedStreamMap[ sPath ].second;
971 sax_fastparser::FSHelperPtr& XclExpXmlStream::WriteAttributesInternal( sal_Int32 nAttribute, ... )
973 sax_fastparser::FSHelperPtr& rStream = GetCurrentStream();
975 va_list args;
976 va_start( args, nAttribute );
977 do {
978 const char* pValue = va_arg( args, const char* );
979 if( pValue )
981 rStream->write( " " )
982 ->writeId( nAttribute )
983 ->write( "=\"" )
984 ->writeEscaped( OUString(pValue, strlen(pValue), RTL_TEXTENCODING_UTF8) )
985 ->write( "\"" );
988 nAttribute = va_arg( args, sal_Int32 );
989 if( nAttribute == FSEND_internal )
990 break;
991 } while( true );
992 va_end( args );
994 return rStream;
996 sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream (
997 const OUString& sFullStream,
998 const OUString& sRelativeStream,
999 const Reference< XOutputStream >& xParentRelation,
1000 const char* sContentType,
1001 const char* sRelationshipType,
1002 OUString* pRelationshipId )
1004 OUString sRelationshipId;
1005 if (xParentRelation.is())
1006 sRelationshipId = addRelation( xParentRelation, OUString::createFromAscii( sRelationshipType), sRelativeStream );
1007 else
1008 sRelationshipId = addRelation( OUString::createFromAscii( sRelationshipType ), sRelativeStream );
1010 if( pRelationshipId )
1011 *pRelationshipId = sRelationshipId;
1013 sax_fastparser::FSHelperPtr p = openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) );
1015 maOpenedStreamMap[ sFullStream ] = std::make_pair( sRelationshipId, p );
1017 return p;
1020 bool XclExpXmlStream::importDocument() throw()
1022 return false;
1025 oox::vml::Drawing* XclExpXmlStream::getVmlDrawing()
1027 return 0;
1030 const oox::drawingml::Theme* XclExpXmlStream::getCurrentTheme() const
1032 return 0;
1035 const oox::drawingml::table::TableStyleListPtr XclExpXmlStream::getTableStyles()
1037 return oox::drawingml::table::TableStyleListPtr();
1040 oox::drawingml::chart::ChartConverter* XclExpXmlStream::getChartConverter()
1042 // DO NOT CALL
1043 return NULL;
1046 ScDocShell* XclExpXmlStream::getDocShell()
1048 Reference< XInterface > xModel( getModel(), UNO_QUERY );
1050 ScModelObj *pObj = dynamic_cast < ScModelObj* >( xModel.get() );
1052 if ( pObj )
1053 return static_cast < ScDocShell* >( pObj->GetEmbeddedObject() );
1055 return 0;
1058 bool XclExpXmlStream::exportDocument()
1059 throw (css::uno::RuntimeException, std::exception)
1061 ScDocShell* pShell = getDocShell();
1062 ScDocument& rDoc = pShell->GetDocument();
1063 ScRefreshTimerProtector aProt(rDoc.GetRefreshTimerControlAddress());
1065 uno::Reference<task::XStatusIndicator> xStatusIndicator = getStatusIndicator();
1067 if (xStatusIndicator.is())
1068 xStatusIndicator->start(ScGlobal::GetRscString(STR_SAVE_DOC), 100);
1070 // NOTE: Don't use SotStorage or SvStream any more, and never call
1071 // SfxMedium::GetOutStream() anywhere in the xlsx export filter code!
1072 // Instead, write via XOutputStream instance.
1073 tools::SvRef<SotStorage> rStorage = static_cast<SotStorage*>(NULL);
1074 XclExpObjList::ResetCounters();
1076 XclExpRootData aData( EXC_BIFF8, *pShell->GetMedium (), rStorage, rDoc, RTL_TEXTENCODING_DONTKNOW );
1077 aData.meOutput = EXC_OUTPUT_XML_2007;
1078 aData.maXclMaxPos.Set( EXC_MAXCOL_XML_2007, EXC_MAXROW_XML_2007, EXC_MAXTAB_XML_2007 );
1079 aData.maMaxPos.SetCol( ::std::min( aData.maScMaxPos.Col(), aData.maXclMaxPos.Col() ) );
1080 aData.maMaxPos.SetRow( ::std::min( aData.maScMaxPos.Row(), aData.maXclMaxPos.Row() ) );
1081 aData.maMaxPos.SetTab( ::std::min( aData.maScMaxPos.Tab(), aData.maXclMaxPos.Tab() ) );
1082 aData.mpCompileFormulaCxt.reset( new sc::CompileFormulaContext(&rDoc) );
1084 XclExpRoot aRoot( aData );
1086 mpRoot = &aRoot;
1087 aRoot.GetOldRoot().pER = &aRoot;
1088 aRoot.GetOldRoot().eDateiTyp = Biff8;
1089 // Get the viewsettings before processing
1090 if( ScDocShell::GetViewData() )
1091 ScDocShell::GetViewData()->WriteExtOptions( mpRoot->GetExtDocOptions() );
1093 OUString const workbook = "xl/workbook.xml";
1094 PushStream( CreateOutputStream( workbook, workbook,
1095 Reference <XOutputStream>(),
1096 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
1097 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
1099 // destruct at the end of the block
1101 ExcDocument aDocRoot( aRoot );
1102 if (xStatusIndicator.is())
1103 xStatusIndicator->setValue(10);
1104 aDocRoot.ReadDoc();
1105 if (xStatusIndicator.is())
1106 xStatusIndicator->setValue(40);
1107 aDocRoot.WriteXml( *this );
1110 PopStream();
1111 // Free all FSHelperPtr, to flush data before committing storage
1112 maOpenedStreamMap.clear();
1114 commitStorage();
1116 if (xStatusIndicator.is())
1117 xStatusIndicator->end();
1118 mpRoot = NULL;
1119 return true;
1122 ::oox::ole::VbaProject* XclExpXmlStream::implCreateVbaProject() const
1124 return new ::oox::xls::ExcelVbaProject( getComponentContext(), Reference< XSpreadsheetDocument >( getModel(), UNO_QUERY ) );
1127 OUString XclExpXmlStream::getImplementationName() throw (css::uno::RuntimeException, std::exception)
1129 return OUString( "TODO" );
1132 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */