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
58 using ::com::sun::star::beans::PropertyValue
;
59 using ::com::sun::star::io::XOutputStream
;
60 using ::com::sun::star::io::XStream
;
61 using ::com::sun::star::lang::XComponent
;
62 using ::com::sun::star::lang::XMultiServiceFactory
;
63 using ::com::sun::star::lang::XServiceInfo
;
64 using ::com::sun::star::uno::Reference
;
65 using ::com::sun::star::uno::Sequence
;
66 using ::com::sun::star::uno::UNO_QUERY
;
68 using ::rtl::OUString
;
69 using ::utl::OStreamWrapper
;
70 using namespace formula
;
71 // ============================================================================
73 XclExpStream::XclExpStream( SvStream
& rOutStrm
, const XclExpRoot
& rRoot
, sal_uInt16 nMaxRecSize
) :
76 mnMaxRecSize( nMaxRecSize
),
86 if( mnMaxRecSize
== 0 )
87 mnMaxRecSize
= (mrRoot
.GetBiff() <= EXC_BIFF5
) ? EXC_MAXRECSIZE_BIFF5
: EXC_MAXRECSIZE_BIFF8
;
88 mnMaxContSize
= mnMaxRecSize
;
91 XclExpStream::~XclExpStream()
96 void XclExpStream::StartRecord( sal_uInt16 nRecId
, sal_Size nRecSize
)
98 DBG_ASSERT( !mbInRec
, "XclExpStream::StartRecord - another record still open" );
100 mnMaxContSize
= mnCurrMaxSize
= mnMaxRecSize
;
101 mnPredictSize
= nRecSize
;
103 InitRecord( nRecId
);
108 void XclExpStream::EndRecord()
110 DBG_ASSERT( mbInRec
, "XclExpStream::EndRecord - no record open" );
113 mrStrm
.Seek( STREAM_SEEK_TO_END
);
117 void XclExpStream::SetSliceSize( sal_uInt16 nSize
)
119 mnMaxSliceSize
= nSize
;
123 XclExpStream
& XclExpStream::operator<<( sal_Int8 nValue
)
126 if (mbUseEncrypter
&& HasValidEncrypter())
127 mxEncrypter
->Encrypt(mrStrm
, nValue
);
133 XclExpStream
& XclExpStream::operator<<( sal_uInt8 nValue
)
136 if (mbUseEncrypter
&& HasValidEncrypter())
137 mxEncrypter
->Encrypt(mrStrm
, nValue
);
143 XclExpStream
& XclExpStream::operator<<( sal_Int16 nValue
)
146 if (mbUseEncrypter
&& HasValidEncrypter())
147 mxEncrypter
->Encrypt(mrStrm
, nValue
);
153 XclExpStream
& XclExpStream::operator<<( sal_uInt16 nValue
)
156 if (mbUseEncrypter
&& HasValidEncrypter())
157 mxEncrypter
->Encrypt(mrStrm
, nValue
);
163 XclExpStream
& XclExpStream::operator<<( sal_Int32 nValue
)
166 if (mbUseEncrypter
&& HasValidEncrypter())
167 mxEncrypter
->Encrypt(mrStrm
, nValue
);
173 XclExpStream
& XclExpStream::operator<<( sal_uInt32 nValue
)
176 if (mbUseEncrypter
&& HasValidEncrypter())
177 mxEncrypter
->Encrypt(mrStrm
, nValue
);
183 XclExpStream
& XclExpStream::operator<<( float fValue
)
186 if (mbUseEncrypter
&& HasValidEncrypter())
187 mxEncrypter
->Encrypt(mrStrm
, fValue
);
193 XclExpStream
& XclExpStream::operator<<( double fValue
)
196 if (mbUseEncrypter
&& HasValidEncrypter())
197 mxEncrypter
->Encrypt(mrStrm
, fValue
);
203 sal_Size
XclExpStream::Write( const void* pData
, sal_Size nBytes
)
206 if( pData
&& (nBytes
> 0) )
210 const sal_uInt8
* pBuffer
= reinterpret_cast< const sal_uInt8
* >( pData
);
211 sal_Size nBytesLeft
= nBytes
;
214 while( bValid
&& (nBytesLeft
> 0) )
216 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
217 sal_Size nWriteRet
= nWriteLen
;
218 if (mbUseEncrypter
&& HasValidEncrypter())
220 DBG_ASSERT(nWriteLen
> 0, "XclExpStream::Write: write length is 0!");
221 vector
<sal_uInt8
> aBytes(nWriteLen
);
222 memcpy(&aBytes
[0], pBuffer
, nWriteLen
);
223 mxEncrypter
->EncryptBytes(mrStrm
, aBytes
);
224 // TODO: How do I check if all the bytes have been successfully written ?
228 nWriteRet
= mrStrm
.Write( pBuffer
, nWriteLen
);
229 bValid
= (nWriteLen
== nWriteRet
);
230 DBG_ASSERT( bValid
, "XclExpStream::Write - stream write error" );
232 pBuffer
+= nWriteRet
;
234 nBytesLeft
-= nWriteRet
;
235 UpdateSizeVars( nWriteRet
);
239 nRet
= mrStrm
.Write( pData
, nBytes
);
244 void XclExpStream::WriteZeroBytes( sal_Size nBytes
)
248 sal_Size nBytesLeft
= nBytes
;
249 while( nBytesLeft
> 0 )
251 sal_Size nWriteLen
= ::std::min
< sal_Size
>( PrepareWrite(), nBytesLeft
);
252 WriteRawZeroBytes( nWriteLen
);
253 nBytesLeft
-= nWriteLen
;
254 UpdateSizeVars( nWriteLen
);
258 WriteRawZeroBytes( nBytes
);
261 sal_Size
XclExpStream::CopyFromStream( SvStream
& rInStrm
, sal_Size nBytes
)
263 sal_Size nStrmPos
= rInStrm
.Tell();
264 rInStrm
.Seek( STREAM_SEEK_TO_END
);
265 sal_Size nStrmSize
= rInStrm
.Tell();
266 rInStrm
.Seek( nStrmPos
);
268 sal_Size nBytesLeft
= ::std::min( nBytes
, nStrmSize
- nStrmPos
);
272 const sal_Size nMaxBuffer
= 4096;
273 sal_uInt8
* pBuffer
= new sal_uInt8
[ ::std::min( nBytesLeft
, nMaxBuffer
) ];
276 while( bValid
&& (nBytesLeft
> 0) )
278 sal_Size nWriteLen
= ::std::min( nBytesLeft
, nMaxBuffer
);
279 rInStrm
.Read( pBuffer
, nWriteLen
);
280 sal_Size nWriteRet
= Write( pBuffer
, nWriteLen
);
281 bValid
= (nWriteLen
== nWriteRet
);
283 nBytesLeft
-= nWriteRet
;
290 //UNUSED2008-05 void XclExpStream::WriteUnicodeBuffer( const sal_uInt16* pBuffer, sal_Size nChars, sal_uInt8 nFlags )
292 //UNUSED2008-05 SetSliceSize( 0 );
293 //UNUSED2008-05 if( pBuffer && (nChars > 0) )
295 //UNUSED2008-05 sal_uInt16 nCharLen = (nFlags & EXC_STRF_16BIT) ? 2 : 1;
296 //UNUSED2008-05 for( sal_Size nIndex = 0; nIndex < nChars; ++nIndex )
298 //UNUSED2008-05 if( mbInRec && (mnCurrSize + nCharLen > mnCurrMaxSize) )
300 //UNUSED2008-05 StartContinue();
301 //UNUSED2008-05 // repeat only 16bit flag
302 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( nFlags & EXC_STRF_16BIT ) );
304 //UNUSED2008-05 if( nCharLen == 2 )
305 //UNUSED2008-05 operator<<( pBuffer[ nIndex ] );
307 //UNUSED2008-05 operator<<( static_cast< sal_uInt8 >( pBuffer[ nIndex ] ) );
312 void XclExpStream::WriteUnicodeBuffer( const ScfUInt16Vec
& rBuffer
, sal_uInt8 nFlags
)
315 nFlags
&= EXC_STRF_16BIT
; // repeat only 16bit flag
316 sal_uInt16 nCharLen
= nFlags
? 2 : 1;
318 ScfUInt16Vec::const_iterator aEnd
= rBuffer
.end();
319 for( ScfUInt16Vec::const_iterator aIter
= rBuffer
.begin(); aIter
!= aEnd
; ++aIter
)
321 if( mbInRec
&& (mnCurrSize
+ nCharLen
> mnCurrMaxSize
) )
324 operator<<( nFlags
);
327 operator<<( *aIter
);
329 operator<<( static_cast< sal_uInt8
>( *aIter
) );
333 //UNUSED2008-05 void XclExpStream::WriteByteStringBuffer( const ByteString& rString, sal_uInt16 nMaxLen )
335 //UNUSED2008-05 SetSliceSize( 0 );
336 //UNUSED2008-05 Write( rString.GetBuffer(), ::std::min< sal_Size >( rString.Len(), nMaxLen ) );
339 // ER: #71367# Xcl has an obscure sense of whether starting a new record or not,
340 // and crashes if it encounters the string header at the very end of a record.
341 // Thus we add 1 to give some room, seems like they do it that way but with another count (10?)
342 void XclExpStream::WriteByteString( const ByteString
& rString
, sal_uInt16 nMaxLen
, bool b16BitCount
)
345 sal_Size nLen
= ::std::min
< sal_Size
>( rString
.Len(), nMaxLen
);
347 nLen
= ::std::min
< sal_Size
>( nLen
, 0xFF );
349 sal_uInt16 nLeft
= PrepareWrite();
350 sal_uInt16 nLenFieldSize
= b16BitCount
? 2 : 1;
351 if( mbInRec
&& (nLeft
<= nLenFieldSize
) )
355 operator<<( static_cast< sal_uInt16
>( nLen
) );
357 operator<<( static_cast< sal_uInt8
>( nLen
) );
358 Write( rString
.GetBuffer(), nLen
);
361 void XclExpStream::WriteCharBuffer( const ScfUInt8Vec
& rBuffer
)
364 Write( &rBuffer
[ 0 ], rBuffer
.size() );
367 void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter
)
369 mxEncrypter
= xEncrypter
;
372 bool XclExpStream::HasValidEncrypter() const
374 return mxEncrypter
.is() && mxEncrypter
->IsValid();
377 void XclExpStream::EnableEncryption( bool bEnable
)
379 mbUseEncrypter
= bEnable
&& HasValidEncrypter();
382 void XclExpStream::DisableEncryption()
384 EnableEncryption(false);
387 sal_Size
XclExpStream::SetSvStreamPos( sal_Size nPos
)
389 DBG_ASSERT( !mbInRec
, "XclExpStream::SetSvStreamPos - not allowed inside of a record" );
390 return mbInRec
? 0 : mrStrm
.Seek( nPos
);
393 // private --------------------------------------------------------------------
395 void XclExpStream::InitRecord( sal_uInt16 nRecId
)
397 mrStrm
.Seek( STREAM_SEEK_TO_END
);
400 mnLastSizePos
= mrStrm
.Tell();
401 mnHeaderSize
= static_cast< sal_uInt16
>( ::std::min
< sal_Size
>( mnPredictSize
, mnCurrMaxSize
) );
402 mrStrm
<< mnHeaderSize
;
403 mnCurrSize
= mnSliceSize
= 0;
406 void XclExpStream::UpdateRecSize()
408 if( mnCurrSize
!= mnHeaderSize
)
410 mrStrm
.Seek( mnLastSizePos
);
411 mrStrm
<< mnCurrSize
;
415 void XclExpStream::UpdateSizeVars( sal_Size nSize
)
417 DBG_ASSERT( mnCurrSize
+ nSize
<= mnCurrMaxSize
, "XclExpStream::UpdateSizeVars - record overwritten" );
418 mnCurrSize
= mnCurrSize
+ static_cast< sal_uInt16
>( nSize
);
420 if( mnMaxSliceSize
> 0 )
422 DBG_ASSERT( mnSliceSize
+ nSize
<= mnMaxSliceSize
, "XclExpStream::UpdateSizeVars - slice overwritten" );
423 mnSliceSize
= mnSliceSize
+ static_cast< sal_uInt16
>( nSize
);
424 if( mnSliceSize
>= mnMaxSliceSize
)
429 void XclExpStream::StartContinue()
432 mnCurrMaxSize
= mnMaxContSize
;
433 mnPredictSize
-= mnCurrSize
;
434 InitRecord( EXC_ID_CONT
);
437 void XclExpStream::PrepareWrite( sal_uInt16 nSize
)
441 if( (mnCurrSize
+ nSize
> mnCurrMaxSize
) ||
442 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
444 UpdateSizeVars( nSize
);
448 sal_uInt16
XclExpStream::PrepareWrite()
453 if( (mnCurrSize
>= mnCurrMaxSize
) ||
454 ((mnMaxSliceSize
> 0) && (mnSliceSize
== 0) && (mnCurrSize
+ mnMaxSliceSize
> mnCurrMaxSize
)) )
458 nRet
= (mnMaxSliceSize
> 0) ? (mnMaxSliceSize
- mnSliceSize
) : (mnCurrMaxSize
- mnCurrSize
);
463 void XclExpStream::WriteRawZeroBytes( sal_Size nBytes
)
465 const sal_uInt32 nData
= 0;
466 sal_Size nBytesLeft
= nBytes
;
467 while( nBytesLeft
>= sizeof( nData
) )
470 nBytesLeft
-= sizeof( nData
);
473 mrStrm
.Write( &nData
, nBytesLeft
);
476 // ============================================================================
478 XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot
& rRoot
, const sal_uInt8 nDocId
[16],
479 const sal_uInt8 nSalt
[16] ) :
481 mnOldPos(STREAM_SEEK_TO_END
),
484 String aPass
= rRoot
.GetPassword();
485 if (aPass
.Len() == 0)
486 // Empty password. Get the default biff8 password.
487 aPass
= XclCryptoHelper::GetBiff8WbProtPassword();
488 Init(aPass
, nDocId
, nSalt
);
491 XclExpBiff8Encrypter::~XclExpBiff8Encrypter()
495 bool XclExpBiff8Encrypter::IsValid() const
500 void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 nSaltDigest
[16] ) const
502 memcpy(nSaltDigest
, mnSaltDigest
, 16);
505 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt8 nData
)
507 vector
<sal_uInt8
> aByte(1);
509 EncryptBytes(rStrm
, aByte
);
512 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt16 nData
)
514 ::std::vector
<sal_uInt8
> pnBytes(2);
515 pnBytes
[0] = nData
& 0xFF;
516 pnBytes
[1] = (nData
>> 8) & 0xFF;
517 EncryptBytes(rStrm
, pnBytes
);
520 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_uInt32 nData
)
522 ::std::vector
<sal_uInt8
> pnBytes(4);
523 pnBytes
[0] = nData
& 0xFF;
524 pnBytes
[1] = (nData
>> 8) & 0xFF;
525 pnBytes
[2] = (nData
>> 16) & 0xFF;
526 pnBytes
[3] = (nData
>> 24) & 0xFF;
527 EncryptBytes(rStrm
, pnBytes
);
530 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, float fValue
)
532 ::std::vector
<sal_uInt8
> pnBytes(4);
533 memcpy(&pnBytes
[0], &fValue
, 4);
534 EncryptBytes(rStrm
, pnBytes
);
537 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, double fValue
)
539 ::std::vector
<sal_uInt8
> pnBytes(8);
540 memcpy(&pnBytes
[0], &fValue
, 8);
541 EncryptBytes(rStrm
, pnBytes
);
544 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int8 nData
)
546 Encrypt(rStrm
, static_cast<sal_uInt8
>(nData
));
549 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int16 nData
)
551 Encrypt(rStrm
, static_cast<sal_uInt16
>(nData
));
554 void XclExpBiff8Encrypter::Encrypt( SvStream
& rStrm
, sal_Int32 nData
)
556 Encrypt(rStrm
, static_cast<sal_uInt32
>(nData
));
559 void XclExpBiff8Encrypter::Init( const String
& aPass
, const sal_uInt8 nDocId
[16],
560 const sal_uInt8 nSalt
[16] )
562 memset(mnSaltDigest
, 0, sizeof(mnSaltDigest
));
564 xub_StrLen nLen
= aPass
.Len();
565 bool bValid
= (0 < nLen
) && (nLen
< 16);
568 // transform String to sal_uInt16 array
569 memset(mnPassw
, 0, sizeof(mnPassw
));
570 for (xub_StrLen nChar
= 0; nChar
< nLen
; ++nChar
)
571 mnPassw
[nChar
] = static_cast<sal_uInt16
>(aPass
.GetChar(nChar
));
574 memcpy(mnDocId
, nDocId
, sizeof(mnDocId
));
577 maCodec
.InitKey(mnPassw
, mnDocId
);
579 // generate salt hash.
580 ::svx::MSCodec_Std97 aCodec
;
581 aCodec
.InitKey(mnPassw
, mnDocId
);
582 aCodec
.CreateSaltDigest(nSalt
, mnSaltDigest
);
584 // verify to make sure it's in good shape.
585 bValid
= maCodec
.VerifyKey(nSalt
, mnSaltDigest
);
591 sal_uInt32
XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos
) const
593 return static_cast<sal_uInt32
>(nStrmPos
/ EXC_ENCR_BLOCKSIZE
);
596 sal_uInt16
XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos
) const
598 return static_cast<sal_uInt16
>(nStrmPos
% EXC_ENCR_BLOCKSIZE
);
601 void XclExpBiff8Encrypter::EncryptBytes( SvStream
& rStrm
, vector
<sal_uInt8
>& aBytes
)
603 sal_Size nStrmPos
= rStrm
.Tell();
604 sal_uInt16 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
605 sal_uInt16 nBlockPos
= GetBlockPos(nStrmPos
);
607 #if DEBUG_XL_ENCRYPTION
608 fprintf(stdout
, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n",
609 nStrmPos
, nBlockOffset
, nBlockPos
);
612 sal_uInt16 nSize
= aBytes
.size();
616 #if DEBUG_XL_ENCRYPTION
617 fprintf(stdout
, "RAW: ");
618 for (sal_uInt16 i
= 0; i
< nSize
; ++i
)
619 fprintf(stdout
, "%2.2X ", aBytes
[i
]);
620 fprintf(stdout
, "\n");
623 if (mnOldPos
!= nStrmPos
)
625 sal_uInt16 nOldOffset
= GetOffsetInBlock(mnOldPos
);
626 sal_uInt16 nOldBlockPos
= GetBlockPos(mnOldPos
);
628 if ( (nBlockPos
!= nOldBlockPos
) || (nBlockOffset
< nOldOffset
) )
630 maCodec
.InitCipher(nBlockPos
);
634 if (nBlockOffset
> nOldOffset
)
635 maCodec
.Skip(nBlockOffset
- nOldOffset
);
638 sal_uInt16 nBytesLeft
= nSize
;
640 while (nBytesLeft
> 0)
642 sal_uInt16 nBlockLeft
= EXC_ENCR_BLOCKSIZE
- nBlockOffset
;
643 sal_uInt16 nEncBytes
= ::std::min(nBlockLeft
, nBytesLeft
);
645 bool bRet
= maCodec
.Encode(&aBytes
[nPos
], nEncBytes
, &aBytes
[nPos
], nEncBytes
);
646 DBG_ASSERT(bRet
, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!");
648 sal_Size nRet
= rStrm
.Write(&aBytes
[nPos
], nEncBytes
);
649 DBG_ASSERT(nRet
== nEncBytes
, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!");
651 nStrmPos
= rStrm
.Tell();
652 nBlockOffset
= GetOffsetInBlock(nStrmPos
);
653 nBlockPos
= GetBlockPos(nStrmPos
);
654 if (nBlockOffset
== 0)
655 maCodec
.InitCipher(nBlockPos
);
657 nBytesLeft
-= nEncBytes
;
662 rtl::OUString
XclXmlUtils::GetStreamName( const char* sStreamDir
, const char* sStream
, sal_Int32 nId
)
664 rtl::OUStringBuffer sBuf
;
666 sBuf
.appendAscii( sStreamDir
);
667 sBuf
.appendAscii( sStream
);
670 sBuf
.appendAscii( ".xml" );
671 return sBuf
.makeStringAndClear();
674 rtl::OString
XclXmlUtils::ToOString( const Color
& rColor
)
677 sprintf( buf
, "%.2X%.2X%.2X%.2X", rColor
.GetTransparency(), rColor
.GetRed(), rColor
.GetGreen(), rColor
.GetBlue() );
679 return OString( buf
);
682 rtl::OString
XclXmlUtils::ToOString( const ::rtl::OUString
& s
)
684 return OUStringToOString( s
, RTL_TEXTENCODING_UTF8
);
687 rtl::OString
XclXmlUtils::ToOString( const String
& s
)
689 return rtl::OString( s
.GetBuffer(), s
.Len(), RTL_TEXTENCODING_UTF8
);
692 rtl::OString
XclXmlUtils::ToOString( const ScAddress
& rAddress
)
695 rAddress
.Format( sAddress
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
696 return ToOString( sAddress
);
699 rtl::OString
XclXmlUtils::ToOString( const ScfUInt16Vec
& rBuffer
)
701 const sal_uInt16
* pBuffer
= &rBuffer
[0];
702 return ::rtl::OString( pBuffer
, rBuffer
.size(), RTL_TEXTENCODING_UTF8
);
705 rtl::OString
XclXmlUtils::ToOString( const ScRange
& rRange
)
708 rRange
.Format( sRange
, SCA_VALID
, NULL
, ScAddress::Details( FormulaGrammar::CONV_XL_A1
) );
709 return ToOString( sRange
);
712 rtl::OString
XclXmlUtils::ToOString( const ScRangeList
& rRangeList
)
715 rRangeList
.Format( s
, SCA_VALID
, NULL
, FormulaGrammar::CONV_XL_A1
, ' ' );
716 return ToOString( s
);
719 static ScAddress
lcl_ToAddress( const XclAddress
& rAddress
)
723 // For some reason, ScRange::Format() returns omits row numbers if
724 // the row is >= MAXROW or the column is >= MAXCOL, and Excel doesn't
725 // like "A:IV" (i.e. no row numbers). Prevent this.
726 aAddress
.SetRow( std::min
<sal_Int32
>( rAddress
.mnRow
, MAXROW
-1 ) );
727 aAddress
.SetCol( static_cast<sal_Int16
>(std::min
<sal_Int32
>( rAddress
.mnCol
, MAXCOL
-1 )) );
732 rtl::OString
XclXmlUtils::ToOString( const XclAddress
& rAddress
)
734 return ToOString( lcl_ToAddress( rAddress
) );
737 rtl::OString
XclXmlUtils::ToOString( const XclExpString
& s
)
739 DBG_ASSERT( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
740 return ToOString( s
.GetUnicodeBuffer() );
743 static ScRange
lcl_ToRange( const XclRange
& rRange
)
747 aRange
.aStart
= lcl_ToAddress( rRange
.maFirst
);
748 aRange
.aEnd
= lcl_ToAddress( rRange
.maLast
);
753 rtl::OString
XclXmlUtils::ToOString( const XclRangeList
& rRanges
)
756 for( XclRangeList::const_iterator i
= rRanges
.begin(), end
= rRanges
.end();
759 aRanges
.Append( lcl_ToRange( *i
) );
761 return ToOString( aRanges
);
764 OUString
XclXmlUtils::ToOUString( const char* s
)
766 return OUString( s
, (sal_Int32
) strlen( s
), RTL_TEXTENCODING_ASCII_US
);
769 OUString
XclXmlUtils::ToOUString( const ScfUInt16Vec
& rBuf
, sal_Int32 nStart
, sal_Int32 nLength
)
772 nLength
= rBuf
.size();
774 return OUString( &rBuf
[nStart
], nLength
);
777 OUString
XclXmlUtils::ToOUString( const String
& s
)
779 return OUString( s
.GetBuffer(), s
.Len() );
782 rtl::OUString
XclXmlUtils::ToOUString( ScDocument
& rDocument
, const ScAddress
& rAddress
, ScTokenArray
* pTokenArray
)
784 ScCompiler
aCompiler( &rDocument
, rAddress
, *pTokenArray
);
785 aCompiler
.SetGrammar(FormulaGrammar::GRAM_NATIVE_XL_A1
);
787 aCompiler
.CreateStringFromTokenArray( s
);
788 return ToOUString( s
);
791 OUString
XclXmlUtils::ToOUString( const XclExpString
& s
)
793 DBG_ASSERT( !s
.IsRich(), "XclXmlUtils::ToOString(XclExpString): rich text string found!" );
794 return ToOUString( s
.GetUnicodeBuffer() );
797 const char* XclXmlUtils::ToPsz( bool b
)
799 return b
? "true" : "false";
802 // ============================================================================
804 XclExpXmlStream::XclExpXmlStream( const Reference
< XMultiServiceFactory
>& rSMgr
, SvStream
& rStrm
, const XclExpRoot
& rRoot
)
805 : XmlFilterBase( rSMgr
)
808 Sequence
< PropertyValue
> aArgs( 1 );
809 const OUString
sStream( RTL_CONSTASCII_USTRINGPARAM( "StreamForOutput" ) );
810 aArgs
[0].Name
= sStream
;
811 aArgs
[0].Value
<<= Reference
< XStream
> ( new OStreamWrapper( rStrm
) );
813 XServiceInfo
* pInfo
= rRoot
.GetDocModelObj();
814 Reference
< XComponent
> aComponent( pInfo
, UNO_QUERY
);
815 setSourceDocument( aComponent
);
818 PushStream( CreateOutputStream(
819 OUString::createFromAscii( "xl/workbook.xml" ),
820 OUString::createFromAscii( "xl/workbook.xml" ),
821 Reference
< XOutputStream
>(),
822 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
823 "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ) );
826 XclExpXmlStream::~XclExpXmlStream()
830 sax_fastparser::FSHelperPtr
& XclExpXmlStream::GetCurrentStream()
832 DBG_ASSERT( !maStreams
.empty(), "XclExpXmlStream::GetCurrentStream - no current stream" );
833 return maStreams
.top();
836 void XclExpXmlStream::PushStream( sax_fastparser::FSHelperPtr aStream
)
838 maStreams
.push( aStream
);
841 void XclExpXmlStream::PopStream()
843 DBG_ASSERT( !maStreams
.empty(), "XclExpXmlStream::PopStream - stack is empty!" );
847 OUString
XclExpXmlStream::GetIdForPath( const OUString
& sPath
)
849 if( maOpenedStreamMap
.find( sPath
) == maOpenedStreamMap
.end() )
851 return maOpenedStreamMap
[ sPath
].first
;
854 sax_fastparser::FSHelperPtr
XclExpXmlStream::GetStreamForPath( const OUString
& sPath
)
856 if( maOpenedStreamMap
.find( sPath
) == maOpenedStreamMap
.end() )
857 return sax_fastparser::FSHelperPtr();
858 return maOpenedStreamMap
[ sPath
].second
;
861 sax_fastparser::FSHelperPtr
& XclExpXmlStream::WriteAttributes( sal_Int32 nAttribute
, ... )
863 sax_fastparser::FSHelperPtr
& rStream
= GetCurrentStream();
866 va_start( args
, nAttribute
);
868 const char* pValue
= va_arg( args
, const char* );
871 rStream
->write( " " )
872 ->writeId( nAttribute
)
874 ->writeEscaped( pValue
)
878 nAttribute
= va_arg( args
, sal_Int32
);
879 if( nAttribute
== FSEND
)
887 static void lcl_WriteValue( sax_fastparser::FSHelperPtr
& rStream
, sal_Int32 nElement
, const char* pValue
)
891 rStream
->singleElement( nElement
,
896 static const char* lcl_GetUnderlineStyle( FontUnderline eUnderline
, bool& bHaveUnderline
)
898 bHaveUnderline
= true;
901 // OOXTODO: doubleAccounting, singleAccounting
902 // OOXTODO: what should be done with the other FontUnderline values?
903 case UNDERLINE_SINGLE
: return "single";
904 case UNDERLINE_DOUBLE
: return "double";
906 default: bHaveUnderline
= false; return "none";
910 static const char* lcl_ToVerticalAlignmentRun( SvxEscapement eEscapement
, bool& bHaveAlignment
)
912 bHaveAlignment
= true;
913 switch( eEscapement
)
915 case SVX_ESCAPEMENT_SUPERSCRIPT
: return "superscript";
916 case SVX_ESCAPEMENT_SUBSCRIPT
: return "subscript";
917 case SVX_ESCAPEMENT_OFF
:
918 default: bHaveAlignment
= false; return "baseline";
922 sax_fastparser::FSHelperPtr
& XclExpXmlStream::WriteFontData( const XclFontData
& rFontData
, sal_Int32 nFontId
)
924 bool bHaveUnderline
, bHaveVertAlign
;
925 const char* pUnderline
= lcl_GetUnderlineStyle( rFontData
.GetScUnderline(), bHaveUnderline
);
926 const char* pVertAlign
= lcl_ToVerticalAlignmentRun( rFontData
.GetScEscapement(), bHaveVertAlign
);
928 sax_fastparser::FSHelperPtr
& rStream
= GetCurrentStream();
930 lcl_WriteValue( rStream
, nFontId
, XclXmlUtils::ToOString( rFontData
.maName
).getStr() );
931 lcl_WriteValue( rStream
, XML_charset
, rFontData
.mnCharSet
!= 0 ? OString::valueOf( (sal_Int32
) rFontData
.mnCharSet
).getStr() : NULL
);
932 lcl_WriteValue( rStream
, XML_family
, OString::valueOf( (sal_Int32
) rFontData
.mnFamily
).getStr() );
933 lcl_WriteValue( rStream
, XML_b
, rFontData
.mnWeight
> 400 ? XclXmlUtils::ToPsz( rFontData
.mnWeight
> 400 ) : NULL
);
934 lcl_WriteValue( rStream
, XML_i
, rFontData
.mbItalic
? XclXmlUtils::ToPsz( rFontData
.mbItalic
) : NULL
);
935 lcl_WriteValue( rStream
, XML_strike
, rFontData
.mbStrikeout
? XclXmlUtils::ToPsz( rFontData
.mbStrikeout
) : NULL
);
936 lcl_WriteValue( rStream
, XML_outline
, rFontData
.mbOutline
? XclXmlUtils::ToPsz( rFontData
.mbOutline
) : NULL
);
937 lcl_WriteValue( rStream
, XML_shadow
, rFontData
.mbShadow
? XclXmlUtils::ToPsz( rFontData
.mbShadow
) : NULL
);
938 // OOXTODO: lcl_WriteValue( rStream, XML_condense, ); // mac compatibility setting
939 // OOXTODO: lcl_WriteValue( rStream, XML_extend, ); // compatibility setting
940 if( rFontData
.maColor
!= Color( 0xFF, 0xFF, 0xFF, 0xFF ) )
941 rStream
->singleElement( XML_color
,
942 // OOXTODO: XML_auto, bool
943 // OOXTODO: XML_indexed, uint
944 XML_rgb
, XclXmlUtils::ToOString( rFontData
.maColor
).getStr(),
945 // OOXTODO: XML_theme, index into <clrScheme/>
946 // OOXTODO: XML_tint, double
948 lcl_WriteValue( rStream
, XML_sz
, OString::valueOf( (double) (rFontData
.mnHeight
/ 20.0) ) ); // Twips->Pt
949 lcl_WriteValue( rStream
, XML_u
, bHaveUnderline
? pUnderline
: NULL
);
950 lcl_WriteValue( rStream
, XML_vertAlign
, bHaveVertAlign
? pVertAlign
: NULL
);
955 sax_fastparser::FSHelperPtr
XclExpXmlStream::CreateOutputStream (
956 const OUString
& sFullStream
,
957 const OUString
& sRelativeStream
,
958 const Reference
< XOutputStream
>& xParentRelation
,
959 const char* sContentType
,
960 const char* sRelationshipType
,
961 ::rtl::OUString
* pRelationshipId
)
963 OUString sRelationshipId
;
964 if (xParentRelation
.is())
965 sRelationshipId
= addRelation( xParentRelation
, OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
967 sRelationshipId
= addRelation( OUString::createFromAscii( sRelationshipType
), sRelativeStream
);
969 if( pRelationshipId
)
970 *pRelationshipId
= sRelationshipId
;
972 sax_fastparser::FSHelperPtr p
= openOutputStreamWithSerializer( sFullStream
, OUString::createFromAscii( sContentType
) );
974 maOpenedStreamMap
[ sFullStream
] = std::make_pair( sRelationshipId
, p
);
979 bool XclExpXmlStream::importDocument() throw()
984 sal_Int32
XclExpXmlStream::getSchemeClr( sal_Int32
/*nColorSchemeToken*/ ) const
989 const oox::vml::DrawingPtr
XclExpXmlStream::getDrawings()
991 return oox::vml::DrawingPtr();
994 const oox::drawingml::Theme
* XclExpXmlStream::getCurrentTheme() const
999 const oox::drawingml::table::TableStyleListPtr
XclExpXmlStream::getTableStyles()
1001 return oox::drawingml::table::TableStyleListPtr();
1004 oox::drawingml::chart::ChartConverter
* XclExpXmlStream::getChartConverter()
1009 bool XclExpXmlStream::exportDocument() throw()
1014 ::rtl::OUString
XclExpXmlStream::implGetImplementationName() const
1016 return CREATE_OUSTRING( "TODO" );
1019 void XclExpXmlStream::Trace( const char* format
, ...)
1022 va_start( ap
, format
);
1023 vfprintf( stderr
, format
, ap
);