1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xestream.cxx,v $
10 * $Revision: 1.11.30.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include <rtl/ustring.hxx>
38 #include <sax/fshelper.hxx>
39 #include <unotools/streamwrap.hxx>
41 #include "precompiled_sc.hxx"
43 #include "xestream.hxx"
44 #include "xladdress.hxx"
45 #include "xlstring.hxx"
47 #include "xestyle.hxx"
48 #include "rangelst.hxx"
49 #include "compiler.hxx"
51 #include <oox/core/tokens.hxx>
52 #include <formula/grammar.hxx>
54 #define DEBUG_XL_ENCRYPTION 0
56 using ::com::sun::star::beans::PropertyValue
;
57 using ::com::sun::star::io::XOutputStream
;
58 using ::com::sun::star::io::XStream
;
59 using ::com::sun::star::lang::XComponent
;
60 using ::com::sun::star::lang::XMultiServiceFactory
;
61 using ::com::sun::star::lang::XServiceInfo
;
62 using ::com::sun::star::uno::Reference
;
63 using ::com::sun::star::uno::Sequence
;
64 using ::com::sun::star::uno::UNO_QUERY
;
66 using ::rtl::OUString
;
67 using ::utl::OStreamWrapper
;
70 using namespace formula
;
72 // ============================================================================
74 XclExpStream::XclExpStream( SvStream
& rOutStrm
, const XclExpRoot
& rRoot
, sal_uInt16 nMaxRecSize
) :
77 mnMaxRecSize( nMaxRecSize
),
87 if( mnMaxRecSize
== 0 )
88 mnMaxRecSize
= (mrRoot
.GetBiff() <= EXC_BIFF5
) ? EXC_MAXRECSIZE_BIFF5
: EXC_MAXRECSIZE_BIFF8
;
89 mnMaxContSize
= mnMaxRecSize
;
92 XclExpStream::~XclExpStream()
97 void XclExpStream::StartRecord( sal_uInt16 nRecId
, sal_Size nRecSize
)
99 DBG_ASSERT( !mbInRec
, "XclExpStream::StartRecord - another record still open" );
101 mnMaxContSize
= mnCurrMaxSize
= mnMaxRecSize
;
102 mnPredictSize
= nRecSize
;
104 InitRecord( nRecId
);
109 void XclExpStream::EndRecord()
111 DBG_ASSERT( mbInRec
, "XclExpStream::EndRecord - no record open" );
114 mrStrm
.Seek( STREAM_SEEK_TO_END
);
118 void XclExpStream::SetSliceSize( sal_uInt16 nSize
)
120 mnMaxSliceSize
= nSize
;
124 XclExpStream
& XclExpStream::operator<<( sal_Int8 nValue
)
127 if (mbUseEncrypter
&& HasValidEncrypter())
128 mxEncrypter
->Encrypt(mrStrm
, nValue
);
134 XclExpStream
& XclExpStream::operator<<( sal_uInt8 nValue
)
137 if (mbUseEncrypter
&& HasValidEncrypter())
138 mxEncrypter
->Encrypt(mrStrm
, nValue
);
144 XclExpStream
& XclExpStream::operator<<( sal_Int16 nValue
)
147 if (mbUseEncrypter
&& HasValidEncrypter())
148 mxEncrypter
->Encrypt(mrStrm
, nValue
);
154 XclExpStream
& XclExpStream::operator<<( sal_uInt16 nValue
)
157 if (mbUseEncrypter
&& HasValidEncrypter())
158 mxEncrypter
->Encrypt(mrStrm
, nValue
);
164 XclExpStream
& XclExpStream::operator<<( sal_Int32 nValue
)
167 if (mbUseEncrypter
&& HasValidEncrypter())
168 mxEncrypter
->Encrypt(mrStrm
, nValue
);
174 XclExpStream
& XclExpStream::operator<<( sal_uInt32 nValue
)
177 if (mbUseEncrypter
&& HasValidEncrypter())
178 mxEncrypter
->Encrypt(mrStrm
, nValue
);
184 XclExpStream
& XclExpStream::operator<<( float fValue
)
187 if (mbUseEncrypter
&& HasValidEncrypter())
188 mxEncrypter
->Encrypt(mrStrm
, fValue
);
194 XclExpStream
& XclExpStream::operator<<( double fValue
)
197 if (mbUseEncrypter
&& HasValidEncrypter())
198 mxEncrypter
->Encrypt(mrStrm
, fValue
);
204 sal_Size
XclExpStream::Write( const void* pData
, sal_Size nBytes
)
207 if( pData
&& (nBytes
> 0) )
211 const sal_uInt8
* pBuffer
= reinterpret_cast< const sal_uInt8
* >( pData
);
212 sal_Size nBytesLeft
= nBytes
;
215 while( bValid
&& (nBytesLeft
> 0) )
217 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
218 sal_Size nWriteRet
= nWriteLen
;
219 if (mbUseEncrypter
&& HasValidEncrypter())
221 DBG_ASSERT(nWriteLen
> 0, "XclExpStream::Write: write length is 0!");
222 vector
<sal_uInt8
> aBytes(nWriteLen
);
223 memcpy(&aBytes
[0], pBuffer
, nWriteLen
);
224 mxEncrypter
->EncryptBytes(mrStrm
, aBytes
);
225 // TODO: How do I check if all the bytes have been successfully written ?
229 nWriteRet
= mrStrm
.Write( pBuffer
, nWriteLen
);
230 bValid
= (nWriteLen
== nWriteRet
);
231 DBG_ASSERT( bValid
, "XclExpStream::Write - stream write error" );
233 pBuffer
+= nWriteRet
;
235 nBytesLeft
-= nWriteRet
;
236 UpdateSizeVars( nWriteRet
);
240 nRet
= mrStrm
.Write( pData
, nBytes
);
245 void XclExpStream::WriteZeroBytes( sal_Size nBytes
)
249 sal_Size nBytesLeft
= nBytes
;
250 while( nBytesLeft
> 0 )
252 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
253 WriteRawZeroBytes( nWriteLen
);
254 nBytesLeft
-= nWriteLen
;
255 UpdateSizeVars( nWriteLen
);
259 WriteRawZeroBytes( nBytes
);
262 sal_Size
XclExpStream::CopyFromStream( SvStream
& rInStrm
, sal_Size nBytes
)
264 sal_Size nStrmPos
= rInStrm
.Tell();
265 rInStrm
.Seek( STREAM_SEEK_TO_END
);
266 sal_Size nStrmSize
= rInStrm
.Tell();
267 rInStrm
.Seek( nStrmPos
);
269 sal_Size nBytesLeft
= ::std::min( nBytes
, nStrmSize
- nStrmPos
);
273 const sal_Size nMaxBuffer
= 4096;
274 sal_uInt8
* pBuffer
= new sal_uInt8
[ ::std::min( nBytesLeft
, nMaxBuffer
) ];
277 while( bValid
&& (nBytesLeft
> 0) )
279 sal_Size nWriteLen
= ::std::min( nBytesLeft
, nMaxBuffer
);
280 rInStrm
.Read( pBuffer
, nWriteLen
);
281 sal_Size nWriteRet
= Write( pBuffer
, nWriteLen
);
282 bValid
= (nWriteLen
== nWriteRet
);
284 nBytesLeft
-= nWriteRet
;
291 //UNUSED2008-05 void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_Size nChars, sal_uInt8 nFlags )
293 //UNUSED2008-05 SetSliceSize( 0 );
294 //UNUSED2008-05 if( pBuffer && (nChars > 0) )
296 //UNUSED2008-05 sal_uInt16 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
297 //UNUSED2008-05 for( sal_Size nIndex = 0; nIndex < nChars; ++nIndex )
299 //UNUSED2008-05 if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
301 //UNUSED2008-05 StartContinue();
302 //UNUSED2008-05 // repeat only 16bit flag
303 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
305 //UNUSED2008-05 if( nCharLen == 2 )
306 //UNUSED2008-05 operator<<( pBuffer[ nIndex ] );
308 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
313 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec
& rBuffer
, sal_uInt8 nFlags
)
316 nFlags
&= EXC_STRF_16BIT
; // repeat only 16bit flag
317 sal_uInt16 nCharLen
= nFlags
? 2 : 1;
319 ScfUInt16Vec::const_iterator aEnd
= rBuffer
.end();
320 for( ScfUInt16Vec::const_iterator aIter
= rBuffer
.begin(); aIter
!= aEnd
; ++aIter
)
322 if( mbInRec
&& (mnCurrSize
+ nCharLen
> mnCurrMaxSize
) )
325 operator<<( nFlags
);
328 operator<<( *aIter
);
330 operator<<( static_cast< sal_uInt8
>( *aIter
) );
334 //UNUSED2008-05 void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
336 //UNUSED2008-05 SetSliceSize( 0 );
337 //UNUSED2008-05 Write( rString.GetBuffer(), ::std::min< sal_Size >( rString.Len(), nMaxLen ) );
340 // ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
341 // and crashes if it encounters the string header at the very end of a record.
342 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
343 void XclExpStream::WriteByteString( const ByteString
& rString
, sal_uInt16 nMaxLen
, bool b16BitCount
)
346 sal_Size nLen
= ::std::min
< sal_Size
>( rString
.Len(), nMaxLen
);
348 nLen
= ::std::min
< sal_Size
>( nLen
, 0xFF );
350 sal_uInt16 nLeft
= PrepareWrite();
351 sal_uInt16 nLenFieldSize
= b16BitCount
? 2 : 1;
352 if( mbInRec
&& (nLeft
<= nLenFieldSize
) )
356 operator<<( static_cast< sal_uInt16
>( nLen
) );
358 operator<<( static_cast< sal_uInt8
>( nLen
) );
359 Write( rString
.GetBuffer(), nLen
);
362 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec
& rBuffer
)
365 Write( &rBuffer
[ 0 ], rBuffer
.size() );
368 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter
)
370 mxEncrypter
= xEncrypter
;
373 bool XclExpStream::HasValidEncrypter() const
375 return mxEncrypter
.is() && mxEncrypter
->IsValid();
378 void XclExpStream::EnableEncryption( bool bEnable
)
380 mbUseEncrypter
= bEnable
&& HasValidEncrypter();
383 void XclExpStream::DisableEncryption()
385 EnableEncryption(false);
388 sal_Size
XclExpStream::SetSvStreamPos( sal_Size nPos
)
390 DBG_ASSERT( !mbInRec
, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
391 return mbInRec
? 0 : mrStrm
.Seek( nPos
);
394 // private --------------------------------------------------------------------
396 void XclExpStream::InitRecord( sal_uInt16 nRecId
)
398 mrStrm
.Seek( STREAM_SEEK_TO_END
);
401 mnLastSizePos
= mrStrm
.Tell();
402 mnHeaderSize
= static_cast< sal_uInt16
>( ::std::min
< sal_Size
>( mnPredictSize
, mnCurrMaxSize
) );
403 mrStrm
<< mnHeaderSize
;
404 mnCurrSize
= mnSliceSize
= 0;
407 void XclExpStream::UpdateRecSize()
409 if( mnCurrSize
!= mnHeaderSize
)
411 mrStrm
.Seek( mnLastSizePos
);
412 mrStrm
<< mnCurrSize
;
416 void XclExpStream::UpdateSizeVars( sal_Size nSize
)
418 DBG_ASSERT( mnCurrSize
+ nSize
<= mnCurrMaxSize
, "XclExpStream::UpdateSizeVars - record overwritten" );
419 mnCurrSize
= mnCurrSize
+ static_cast< sal_uInt16
>( nSize
);
421 if( mnMaxSliceSize
> 0 )
423 DBG_ASSERT( mnSliceSize
+ nSize
<= mnMaxSliceSize
, "XclExpStream::UpdateSizeVars - slice overwritten" );
424 mnSliceSize
= mnSliceSize
+ static_cast< sal_uInt16
>( nSize
);
425 if( mnSliceSize
>= mnMaxSliceSize
)
430 void XclExpStream::StartContinue()
433 mnCurrMaxSize
= mnMaxContSize
;
434 mnPredictSize
-= mnCurrSize
;
435 InitRecord( EXC_ID_CONT
);
438 void XclExpStream::PrepareWrite( sal_uInt16 nSize
)
442 if( (mnCurrSize
+ nSize
> mnCurrMaxSize
) ||
443 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
445 UpdateSizeVars( nSize
);
449 sal_uInt16
XclExpStream::PrepareWrite()
454 if( (mnCurrSize
>= mnCurrMaxSize
) ||
455 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
459 nRet
= (mnMaxSliceSize
> 0) ? (mnMaxSliceSize
- mnSliceSize
) : (mnCurrMaxSize
- mnCurrSize
);
464 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes
)
466 const sal_uInt32 nData
= 0;
467 sal_Size nBytesLeft
= nBytes
;
468 while( nBytesLeft
>= sizeof( nData
) )
471 nBytesLeft
-= sizeof( nData
);
474 mrStrm
.Write( &nData
, nBytesLeft
);
477 // ============================================================================
479 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot
& rRoot
, const sal_uInt8 nDocId
[16],
480 const sal_uInt8 nSalt
[16] ) :
482 mnOldPos(STREAM_SEEK_TO_END
),
485 String aPass
= rRoot
.GetPassword();
486 if (aPass
.Len() == 0)
487 // Empty password. Get the default biff8 password.
488 aPass
= rRoot
.GetDefaultPassword();
489 Init(aPass
, nDocId
, nSalt
);
492 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
496 bool XclExpBiff8Encrypter::IsValid() const
501 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 nSaltDigest
[16] ) const
503 memcpy(nSaltDigest
, mnSaltDigest
, 16);
506 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt8 nData
)
508 vector
<sal_uInt8
> aByte(1);
510 EncryptBytes(rStrm
, aByte
);
513 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt16 nData
)
515 ::std::vector
<sal_uInt8
> pnBytes(2);
516 pnBytes
[0] = nData
& 0xFF;
517 pnBytes
[1] = (nData
>> 8) & 0xFF;
518 EncryptBytes(rStrm
, pnBytes
);
521 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt32 nData
)
523 ::std::vector
<sal_uInt8
> pnBytes(4);
524 pnBytes
[0] = nData
& 0xFF;
525 pnBytes
[1] = (nData
>> 8) & 0xFF;
526 pnBytes
[2] = (nData
>> 16) & 0xFF;
527 pnBytes
[3] = (nData
>> 24) & 0xFF;
528 EncryptBytes(rStrm
, pnBytes
);
531 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, float fValue
)
533 ::std::vector
<sal_uInt8
> pnBytes(4);
534 memcpy(&pnBytes
[0], &fValue
, 4);
535 EncryptBytes(rStrm
, pnBytes
);
538 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, double fValue
)
540 ::std::vector
<sal_uInt8
> pnBytes(8);
541 memcpy(&pnBytes
[0], &fValue
, 8);
542 EncryptBytes(rStrm
, pnBytes
);
545 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int8 nData
)
547 Encrypt(rStrm
, static_cast<sal_uInt8
>(nData
));
550 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int16 nData
)
552 Encrypt(rStrm
, static_cast<sal_uInt16
>(nData
));
555 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int32 nData
)
557 Encrypt(rStrm
, static_cast<sal_uInt32
>(nData
));
560 void XclExpBiff8Encrypter::Init( const String
& aPass
, const sal_uInt8 nDocId
[16],
561 const sal_uInt8 nSalt
[16] )
563 memset(mnSaltDigest
, 0, sizeof(mnSaltDigest
));
565 xub_StrLen nLen
= aPass
.Len();
566 bool bValid
= (0 < nLen
) && (nLen
< 16);
569 // transform String to sal_uInt16 array
570 memset(mnPassw
, 0, sizeof(mnPassw
));
571 for (xub_StrLen nChar
= 0; nChar
< nLen
; ++nChar
)
572 mnPassw
[nChar
] = static_cast<sal_uInt16
>(aPass
.GetChar(nChar
));
575 memcpy(mnDocId
, nDocId
, sizeof(mnDocId
));
578 maCodec
.InitKey(mnPassw
, mnDocId
);
580 // generate salt hash.
581 ::svx::MSCodec_Std97 aCodec
;
582 aCodec
.InitKey(mnPassw
, mnDocId
);
583 aCodec
.CreateSaltDigest(nSalt
, mnSaltDigest
);
585 // verify to make sure it's in good shape.
586 bValid
= maCodec
.VerifyKey(nSalt
, mnSaltDigest
);
592 sal_uInt32
XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos
) const
594 return static_cast<sal_uInt32
>(nStrmPos
/ EXC_ENCR_BLOCKSIZE
);
597 sal_uInt16
XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos
) const
599 return static_cast<sal_uInt16
>(nStrmPos
% EXC_ENCR_BLOCKSIZE
);
602 void XclExpBiff8Encrypter::EncryptBytes( SvStream
& rStrm
, vector
<sal_uInt8
>& aBytes
)
604 sal_Size nStrmPos
= rStrm
.Tell();
605 sal_uInt16 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
606 sal_uInt32 nBlockPos
= GetBlockPos(nStrmPos
);
608 #if DEBUG_XL_ENCRYPTION
609 fprintf(stdout
, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
610 nStrmPos
, nBlockOffset
, nBlockPos
);
613 sal_uInt16 nSize
= static_cast< sal_uInt16
>( aBytes
.size() );
617 #if DEBUG_XL_ENCRYPTION
618 fprintf(stdout
, "RAW: ");
619 for (sal_uInt16 i
= 0; i
< nSize
; ++i
)
620 fprintf(stdout
, "%2.2X ", aBytes
[i
]);
621 fprintf(stdout
, "\n");
624 if (mnOldPos
!= nStrmPos
)
626 sal_uInt16 nOldOffset
= GetOffsetInBlock(mnOldPos
);
627 sal_uInt32 nOldBlockPos
= GetBlockPos(mnOldPos
);
629 if ( (nBlockPos
!= nOldBlockPos
) || (nBlockOffset
< nOldOffset
) )
631 maCodec
.InitCipher(nBlockPos
);
635 if (nBlockOffset
> nOldOffset
)
636 maCodec
.Skip(nBlockOffset
- nOldOffset
);
639 sal_uInt16 nBytesLeft
= nSize
;
641 while (nBytesLeft
> 0)
643 sal_uInt16 nBlockLeft
= EXC_ENCR_BLOCKSIZE
- nBlockOffset
;
644 sal_uInt16 nEncBytes
= ::std::min(nBlockLeft
, nBytesLeft
);
646 bool bRet
= maCodec
.Encode(&aBytes
[nPos
], nEncBytes
, &aBytes
[nPos
], nEncBytes
);
647 DBG_ASSERT(bRet
, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
648 bRet
= bRet
; // to remove a silly compiler warning.
650 sal_Size nRet
= rStrm
.Write(&aBytes
[nPos
], nEncBytes
);
651 DBG_ASSERT(nRet
== nEncBytes
, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
652 nRet
= nRet
; // to remove a silly compiler warning.
654 nStrmPos
= rStrm
.Tell();
655 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
656 nBlockPos
= GetBlockPos(nStrmPos
);
657 if (nBlockOffset
== 0)
658 maCodec
.InitCipher(nBlockPos
);
660 nBytesLeft
-= nEncBytes
;
666 rtl::OUString
XclXmlUtils::GetStreamName( const char* sStreamDir
, const char* sStream
, sal_Int32 nId
)
668 rtl::OUStringBuffer sBuf
;
670 sBuf
.appendAscii( sStreamDir
);
671 sBuf
.appendAscii( sStream
);
674 sBuf
.appendAscii( ".xml" );
675 return sBuf
.makeStringAndClear();
678 rtl::OString
XclXmlUtils::ToOString( const Color
& rColor
)
681 sprintf( buf
, "%.2X%.2X%.2X%.2X", rColor
.GetTransparency(), rColor
.GetRed(), rColor
.GetGreen(), rColor
.GetBlue() );
683 return OString( buf
);
686 rtl::OString
XclXmlUtils::ToOString( const ::rtl::OUString
& s
)
688 return OUStringToOString( s
, RTL_TEXTENCODING_UTF8
);
691 rtl::OString
XclXmlUtils::ToOString( const String
& s
)
693 return rtl::OString( s
.GetBuffer(), s
.Len(), RTL_TEXTENCODING_UTF8
);
696 rtl::OString
XclXmlUtils::ToOString( const ScAddress
& rAddress
)
699 rAddress
.Format( sAddress
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
700 return ToOString( sAddress
);
703 rtl::OString
XclXmlUtils::ToOString( const ScfUInt16Vec
& rBuffer
)
705 const sal_uInt16
* pBuffer
= &rBuffer
[0];
706 return ::rtl::OString( pBuffer
, rBuffer
.size(), RTL_TEXTENCODING_UTF8
);
709 rtl::OString
XclXmlUtils::ToOString( const ScRange
& rRange
)
712 rRange
.Format( sRange
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
713 return ToOString( sRange
);
716 rtl::OString
XclXmlUtils::ToOString( const ScRangeList
& rRangeList
)
719 rRangeList
.Format( s
, SCA_VALID
, NULL
, FormulaGrammar::CONV_XL_A1
, ' ' );
720 return ToOString( s
);
723 static ScAddress
lcl_ToAddress( const XclAddress
& rAddress
)
727 // For some reason, ScRange::Format() returns omits row numbers if
728 // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
729 // like "A:IV" (i.e. no row numbers). Prevent this.
730 aAddress
.SetRow( std::min
<sal_Int32
>( rAddress
.mnRow
, MAXROW
-1 ) );
731 aAddress
.SetCol( static_cast<sal_Int16
>(std::min
<sal_Int32
>( rAddress
.mnCol
, MAXCOL
-1 )) );
736 rtl::OString
XclXmlUtils::ToOString( const XclAddress
& rAddress
)
738 return ToOString( lcl_ToAddress( rAddress
) );
741 rtl::OString
XclXmlUtils::ToOString( const XclExpString
& s
)
743 DBG_ASSERT( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
744 return ToOString( s
.GetUnicodeBuffer() );
747 static ScRange
lcl_ToRange( const XclRange
& rRange
)
751 aRange
.aStart
= lcl_ToAddress( rRange
.maFirst
);
752 aRange
.aEnd
= lcl_ToAddress( rRange
.maLast
);
757 rtl::OString
XclXmlUtils::ToOString( const XclRangeList
& rRanges
)
760 for( XclRangeList::const_iterator i
= rRanges
.begin(), end
= rRanges
.end();
763 aRanges
.Append( lcl_ToRange( *i
) );
765 return ToOString( aRanges
);
768 OUString
XclXmlUtils::ToOUString( const char* s
)
770 return OUString( s
, (sal_Int32
) strlen( s
), RTL_TEXTENCODING_ASCII_US
);
773 OUString
XclXmlUtils::ToOUString( const ScfUInt16Vec
& rBuf
, sal_Int32 nStart
, sal_Int32 nLength
)
776 nLength
= rBuf
.size();
778 return OUString( &rBuf
[nStart
], nLength
);
781 OUString
XclXmlUtils::ToOUString( const String
& s
)
783 return OUString( s
.GetBuffer(), s
.Len() );
786 rtl::OUString
XclXmlUtils::ToOUString( ScDocument
& rDocument
, const ScAddress
& rAddress
, ScTokenArray
* pTokenArray
)
788 ScCompiler
aCompiler( &rDocument
, rAddress
, *pTokenArray
);
789 aCompiler
.SetGrammar(FormulaGrammar::GRAM_NATIVE_XL_A1
);
791 aCompiler
.CreateStringFromTokenArray( s
);
792 return ToOUString( s
);
795 OUString
XclXmlUtils::ToOUString( const XclExpString
& s
)
797 DBG_ASSERT( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
798 return ToOUString( s
.GetUnicodeBuffer() );
801 const char* XclXmlUtils::ToPsz( bool b
)
803 return b
? "true" : "false";
806 // ============================================================================
808 XclExpXmlStream::XclExpXmlStream( const Reference
< XMultiServiceFactory
>& rSMgr
, SvStream
& rStrm
, const XclExpRoot
& rRoot
)
809 : XmlFilterBase( rSMgr
)
812 Sequence
< PropertyValue
> aArgs( 1 );
813 const OUString
sStream( RTL_CONSTASCII_USTRINGPARAM( "StreamForOutput" ) );
814 aArgs
[0].Name
= sStream
;
815 aArgs
[0].Value
<<= Reference
< XStream
> ( new OStreamWrapper( rStrm
) );
817 XServiceInfo
* pInfo
= rRoot
.GetDocModelObj();
818 Reference
< XComponent
> aComponent( pInfo
, UNO_QUERY
);
819 setSourceDocument( aComponent
);
822 PushStream( CreateOutputStream(
823 OUString::createFromAscii( "xl/workbook.xml" ),
824 OUString::createFromAscii( "xl/workbook.xml" ),
825 Reference
< XOutputStream
>(),
826 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
827 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
830 XclExpXmlStream::~XclExpXmlStream()
834 sax_fastparser::FSHelperPtr
& XclExpXmlStream::GetCurrentStream()
836 DBG_ASSERT( !maStreams
.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
837 return maStreams
.top();
840 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream
)
842 maStreams
.push( aStream
);
845 void XclExpXmlStream::PopStream()
847 DBG_ASSERT( !maStreams
.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
851 OUString
XclExpXmlStream::GetIdForPath( const OUString
& sPath
)
853 if( maOpenedStreamMap
.find( sPath
) == maOpenedStreamMap
.end() )
855 return maOpenedStreamMap
[ sPath
].first
;
858 sax_fastparser::FSHelperPtr
XclExpXmlStream::GetStreamForPath( const OUString
& sPath
)
860 if( maOpenedStreamMap
.find( sPath
) == maOpenedStreamMap
.end() )
861 return sax_fastparser::FSHelperPtr();
862 return maOpenedStreamMap
[ sPath
].second
;
865 sax_fastparser::FSHelperPtr
& XclExpXmlStream::WriteAttributes( sal_Int32 nAttribute
, ... )
867 sax_fastparser::FSHelperPtr
& rStream
= GetCurrentStream();
870 va_start( args
, nAttribute
);
872 const char* pValue
= va_arg( args
, const char* );
875 rStream
->write( " " )
876 ->writeId( nAttribute
)
878 ->writeEscaped( pValue
)
882 nAttribute
= va_arg( args
, sal_Int32
);
883 if( nAttribute
== FSEND
)
891 static void lcl_WriteValue( sax_fastparser::FSHelperPtr
& rStream
, sal_Int32 nElement
, const char* pValue
)
895 rStream
->singleElement( nElement
,
900 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline
, bool& bHaveUnderline
)
902 bHaveUnderline
= true;
905 // OOXTODO: doubleAccounting, singleAccounting
906 // OOXTODO: what should be done with the other FontUnderline values?
907 case UNDERLINE_SINGLE
: return "single";
908 case UNDERLINE_DOUBLE
: return "double";
910 default: bHaveUnderline
= false; return "none";
914 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement
, bool& bHaveAlignment
)
916 bHaveAlignment
= true;
917 switch( eEscapement
)
919 case SVX_ESCAPEMENT_SUPERSCRIPT
: return "superscript";
920 case SVX_ESCAPEMENT_SUBSCRIPT
: return "subscript";
921 case SVX_ESCAPEMENT_OFF
:
922 default: bHaveAlignment
= false; return "baseline";
926 sax_fastparser::FSHelperPtr
& XclExpXmlStream::WriteFontData( const XclFontData
& rFontData
, sal_Int32 nFontId
)
928 bool bHaveUnderline
, bHaveVertAlign
;
929 const char* pUnderline
= lcl_GetUnderlineStyle( rFontData
.GetScUnderline(), bHaveUnderline
);
930 const char* pVertAlign
= lcl_ToVerticalAlignmentRun( rFontData
.GetScEscapement(), bHaveVertAlign
);
932 sax_fastparser::FSHelperPtr
& rStream
= GetCurrentStream();
934 lcl_WriteValue( rStream
, nFontId
, XclXmlUtils::ToOString( rFontData
.maName
).getStr() );
935 lcl_WriteValue( rStream
, XML_charset
, rFontData
.mnCharSet
!= 0 ? OString::valueOf( (sal_Int32
) rFontData
.mnCharSet
).getStr() : NULL
);
936 lcl_WriteValue( rStream
, XML_family
, OString::valueOf( (sal_Int32
) rFontData
.mnFamily
).getStr() );
937 lcl_WriteValue( rStream
, XML_b
, rFontData
.mnWeight
> 400 ? XclXmlUtils::ToPsz( rFontData
.mnWeight
> 400 ) : NULL
);
938 lcl_WriteValue( rStream
, XML_i
, rFontData
.mbItalic
? XclXmlUtils::ToPsz( rFontData
.mbItalic
) : NULL
);
939 lcl_WriteValue( rStream
, XML_strike
, rFontData
.mbStrikeout
? XclXmlUtils::ToPsz( rFontData
.mbStrikeout
) : NULL
);
940 lcl_WriteValue( rStream
, XML_outline
, rFontData
.mbOutline
? XclXmlUtils::ToPsz( rFontData
.mbOutline
) : NULL
);
941 lcl_WriteValue( rStream
, XML_shadow
, rFontData
.mbShadow
? XclXmlUtils::ToPsz( rFontData
.mbShadow
) : NULL
);
942 // OOXTODO: lcl_WriteValue( rStream, XML_condense, ); // mac compatibility setting
943 // OOXTODO: lcl_WriteValue( rStream, XML_extend, ); // compatibility setting
944 if( rFontData
.maColor
!= Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
945 rStream
->singleElement( XML_color
,
946 // OOXTODO: XML_auto, bool
947 // OOXTODO: XML_indexed, uint
948 XML_rgb
, XclXmlUtils::ToOString( rFontData
.maColor
).getStr(),
949 // OOXTODO: XML_theme, index into <clrScheme/>
950 // OOXTODO: XML_tint, double
952 lcl_WriteValue( rStream
, XML_sz
, OString::valueOf( (double) (rFontData
.mnHeight
/ 20.0) ) ); // Twips->Pt
953 lcl_WriteValue( rStream
, XML_u
, bHaveUnderline
? pUnderline
: NULL
);
954 lcl_WriteValue( rStream
, XML_vertAlign
, bHaveVertAlign
? pVertAlign
: NULL
);
959 sax_fastparser::FSHelperPtr
XclExpXmlStream::CreateOutputStream (
960 const OUString
& sFullStream
,
961 const OUString
& sRelativeStream
,
962 const Reference
< XOutputStream
>& xParentRelation
,
963 const char* sContentType
,
964 const char* sRelationshipType
,
965 ::rtl::OUString
* pRelationshipId
)
967 OUString sRelationshipId
;
968 if (xParentRelation
.is())
969 sRelationshipId
= addRelation( xParentRelation
, OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
971 sRelationshipId
= addRelation( OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
973 if( pRelationshipId
)
974 *pRelationshipId
= sRelationshipId
;
976 sax_fastparser::FSHelperPtr p
= openFragmentStreamWithSerializer( sFullStream
, OUString::createFromAscii( sContentType
) );
978 maOpenedStreamMap
[ sFullStream
] = std::make_pair( sRelationshipId
, p
);
983 bool XclExpXmlStream::importDocument() throw()
988 sal_Int32
XclExpXmlStream::getSchemeClr( sal_Int32
/*nColorSchemeToken*/ ) const
993 oox::vml::Drawing
* XclExpXmlStream::getVmlDrawing()
998 const oox::drawingml::Theme
* XclExpXmlStream::getCurrentTheme() const
1003 const oox::drawingml::table::TableStyleListPtr
XclExpXmlStream::getTableStyles()
1005 return oox::drawingml::table::TableStyleListPtr();
1008 oox::drawingml::chart::ChartConverter
& XclExpXmlStream::getChartConverter()
1011 return * (oox::drawingml::chart::ChartConverter
*) NULL
;
1014 bool XclExpXmlStream::exportDocument() throw()
1019 ::rtl::OUString
XclExpXmlStream::implGetImplementationName() const
1021 return CREATE_OUSTRING( "TODO" );
1024 void XclExpXmlStream::Trace( const char* format
, ...)
1027 va_start( ap
, format
);
1028 vfprintf( stderr
, format
, ap
);