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: xestring.cxx,v $
10 * $Revision: 1.13.32.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
32 #include "precompiled_sc.hxx"
36 #include "xestream.hxx"
37 #include "xlstyle.hxx"
38 #include "xestyle.hxx"
39 #include "xestring.hxx"
41 #include <oox/core/tokens.hxx>
44 using ::rtl::OUString
;
46 // ============================================================================
52 /** Compares two vectors.
53 @return A negative value, if rLeft<rRight; or a positive value, if rLeft>rRight;
54 or 0, if rLeft==rRight. */
55 template< typename Type
>
56 int lclCompareVectors( const ::std::vector
< Type
>& rLeft
, const ::std::vector
< Type
>& rRight
)
60 // 1st: compare all elements of the vectors
61 typedef typename ::std::vector
< Type
>::const_iterator CIT
;
62 CIT aEndL
= rLeft
.end(), aEndR
= rRight
.end();
63 for( CIT aItL
= rLeft
.begin(), aItR
= rRight
.begin(); !nResult
&& (aItL
!= aEndL
) && (aItR
!= aEndR
); ++aItL
, ++aItR
)
64 nResult
= static_cast< int >( *aItL
) - static_cast< int >( *aItR
);
66 // 2nd: no differences found so far -> compare the vector sizes. Shorter vector is less
68 nResult
= static_cast< int >( rLeft
.size() ) - static_cast< int >( rRight
.size() );
75 /** Base class for value hashers.
76 @descr These function objects are used to hash any value to a sal_uInt32 value. */
77 template< typename Type
>
78 struct XclHasher
: public ::std::unary_function
< Type
, sal_uInt32
> {};
80 template< typename Type
>
81 struct XclDirectHasher
: public XclHasher
< Type
>
83 inline sal_uInt32
operator()( Type nVal
) const { return nVal
; }
86 struct XclFormatRunHasher
: public XclHasher
< const XclFormatRun
& >
88 inline sal_uInt32
operator()( const XclFormatRun
& rRun
) const
89 { return (rRun
.mnChar
<< 8) ^ rRun
.mnFontIdx
; }
92 /** Calculates a hash value from a vector.
93 @descr Uses the passed hasher function object to calculate hash values from
94 all vector elements. */
95 template< typename Type
, typename ValueHasher
>
96 sal_uInt16
lclHashVector( const ::std::vector
< Type
>& rVec
, const ValueHasher
& rHasher
)
98 sal_uInt32 nHash
= rVec
.size();
99 typedef typename ::std::vector
< Type
>::const_iterator CIT
;
100 for( CIT aIt
= rVec
.begin(), aEnd
= rVec
.end(); aIt
!= aEnd
; ++aIt
)
101 (nHash
*= 31) += rHasher( *aIt
);
102 return static_cast< sal_uInt16
>( nHash
^ (nHash
>> 16) );
105 /** Calculates a hash value from a vector. Uses XclDirectHasher to hash the vector elements. */
106 template< typename Type
>
107 inline sal_uInt16
lclHashVector( const ::std::vector
< Type
>& rVec
)
109 return lclHashVector( rVec
, XclDirectHasher
< Type
>() );
114 // constructors ---------------------------------------------------------------
116 XclExpString::XclExpString( XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
118 Init( 0, nFlags
, nMaxLen
, true );
121 XclExpString::XclExpString( const String
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
123 Assign( rString
, nFlags
, nMaxLen
);
126 XclExpString::XclExpString( const OUString
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
128 Assign( rString
, nFlags
, nMaxLen
);
131 //UNUSED2008-05 XclExpString::XclExpString(
132 //UNUSED2008-05 const String& rString, const XclFormatRunVec& rFormats,
133 //UNUSED2008-05 XclStrFlags nFlags, sal_uInt16 nMaxLen )
135 //UNUSED2008-05 Assign( rString, rFormats, nFlags, nMaxLen );
138 //UNUSED2008-05 XclExpString::XclExpString(
139 //UNUSED2008-05 const OUString& rString, const XclFormatRunVec& rFormats,
140 //UNUSED2008-05 XclStrFlags nFlags, sal_uInt16 nMaxLen )
142 //UNUSED2008-05 Assign( rString, rFormats, nFlags, nMaxLen );
145 // assign ---------------------------------------------------------------------
147 void XclExpString::Assign( const String
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
149 Build( rString
.GetBuffer(), rString
.Len(), nFlags
, nMaxLen
);
152 void XclExpString::Assign(
153 const String
& rString
, const XclFormatRunVec
& rFormats
,
154 XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
156 Assign( rString
, nFlags
, nMaxLen
);
157 SetFormats( rFormats
);
160 void XclExpString::Assign( const OUString
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
162 Build( rString
.getStr(), rString
.getLength(), nFlags
, nMaxLen
);
165 void XclExpString::Assign(
166 const OUString
& rString
, const XclFormatRunVec
& rFormats
,
167 XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
169 Assign( rString
, nFlags
, nMaxLen
);
170 SetFormats( rFormats
);
173 void XclExpString::Assign( sal_Unicode cChar
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
175 Build( &cChar
, 1, nFlags
, nMaxLen
);
178 void XclExpString::AssignByte(
179 const String
& rString
, rtl_TextEncoding eTextEnc
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
181 ByteString
aByteStr( rString
, eTextEnc
); // length may differ from length of rString
182 Build( aByteStr
.GetBuffer(), aByteStr
.Len(), nFlags
, nMaxLen
);
185 //UNUSED2008-05 void XclExpString::AssignByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc, XclStrFlags nFlags, sal_uInt16 nMaxLen )
187 //UNUSED2008-05 if( !cChar )
189 //UNUSED2008-05 sal_Char cByteChar = 0;
190 //UNUSED2008-05 Build( &cByteChar, 1, nFlags, nMaxLen );
194 //UNUSED2008-05 ByteString aByteStr( &cChar, 1, eTextEnc ); // length may be >1
195 //UNUSED2008-05 Build( aByteStr.GetBuffer(), aByteStr.Len(), nFlags, nMaxLen );
199 // append ---------------------------------------------------------------------
201 void XclExpString::Append( const String
& rString
)
203 BuildAppend( rString
.GetBuffer(), rString
.Len() );
206 //UNUSED2008-05 void XclExpString::Append( const ::rtl::OUString& rString )
208 //UNUSED2008-05 BuildAppend( rString.getStr(), rString.getLength() );
211 //UNUSED2008-05 void XclExpString::Append( sal_Unicode cChar )
213 //UNUSED2008-05 BuildAppend( &cChar, 1 );
216 void XclExpString::AppendByte( const String
& rString
, rtl_TextEncoding eTextEnc
)
218 if( rString
.Len() > 0 )
220 ByteString
aByteStr( rString
, eTextEnc
); // length may differ from length of rString
221 BuildAppend( aByteStr
.GetBuffer(), aByteStr
.Len() );
225 void XclExpString::AppendByte( sal_Unicode cChar
, rtl_TextEncoding eTextEnc
)
229 sal_Char cByteChar
= 0;
230 BuildAppend( &cByteChar
, 1 );
234 ByteString
aByteStr( &cChar
, 1, eTextEnc
); // length may be >1
235 BuildAppend( aByteStr
.GetBuffer(), aByteStr
.Len() );
239 // formatting runs ------------------------------------------------------------
241 void XclExpString::SetFormats( const XclFormatRunVec
& rFormats
)
243 maFormats
= rFormats
;
247 XclFormatRunVec::const_iterator aCurr
= maFormats
.begin();
248 XclFormatRunVec::const_iterator aPrev
= aCurr
;
249 XclFormatRunVec::const_iterator aEnd
= maFormats
.end();
250 for( ++aCurr
; aCurr
!= aEnd
; ++aCurr
, ++aPrev
)
251 DBG_ASSERT( aPrev
->mnChar
< aCurr
->mnChar
, "XclExpString::SetFormats - invalid char order" );
252 DBG_ASSERT( aPrev
->mnChar
<= mnLen
, "XclExpString::SetFormats - invalid char index" );
255 LimitFormatCount( mbIsBiff8
? EXC_STR_MAXLEN
: EXC_STR_MAXLEN_8BIT
);
258 void XclExpString::AppendFormat( sal_uInt16 nChar
, sal_uInt16 nFontIdx
, bool bDropDuplicate
)
260 DBG_ASSERT( maFormats
.empty() || (maFormats
.back().mnChar
< nChar
), "XclExpString::AppendFormat - invalid char index" );
261 size_t nMaxSize
= static_cast< size_t >( mbIsBiff8
? EXC_STR_MAXLEN
: EXC_STR_MAXLEN_8BIT
);
262 if( maFormats
.empty() || ((maFormats
.size() < nMaxSize
) && (!bDropDuplicate
|| (maFormats
.back().mnFontIdx
!= nFontIdx
))) )
263 maFormats
.push_back( XclFormatRun( nChar
, nFontIdx
) );
266 void XclExpString::AppendTrailingFormat( sal_uInt16 nFontIdx
)
268 AppendFormat( mnLen
, nFontIdx
, false );
271 void XclExpString::LimitFormatCount( sal_uInt16 nMaxCount
)
273 if( maFormats
.size() > nMaxCount
)
274 maFormats
.erase( maFormats
.begin() + nMaxCount
, maFormats
.end() );
277 sal_uInt16
XclExpString::RemoveLeadingFont()
279 sal_uInt16 nFontIdx
= EXC_FONT_NOTFOUND
;
280 if( !maFormats
.empty() && (maFormats
.front().mnChar
== 0) )
282 nFontIdx
= maFormats
.front().mnFontIdx
;
283 maFormats
.erase( maFormats
.begin() );
288 bool XclExpString::IsEqual( const XclExpString
& rCmp
) const
291 (mnLen
== rCmp
.mnLen
) &&
292 (mbIsBiff8
== rCmp
.mbIsBiff8
) &&
293 (mbIsUnicode
== rCmp
.mbIsUnicode
) &&
294 (mbWrapped
== rCmp
.mbWrapped
) &&
296 ( mbIsBiff8
&& (maUniBuffer
== rCmp
.maUniBuffer
)) ||
297 (!mbIsBiff8
&& (maCharBuffer
== rCmp
.maCharBuffer
))
299 (maFormats
== rCmp
.maFormats
);
302 bool XclExpString::IsLessThan( const XclExpString
& rCmp
) const
304 int nResult
= mbIsBiff8
?
305 lclCompareVectors( maUniBuffer
, rCmp
.maUniBuffer
) :
306 lclCompareVectors( maCharBuffer
, rCmp
.maCharBuffer
);
307 return (nResult
!= 0) ? (nResult
< 0) : (maFormats
< rCmp
.maFormats
);
310 // get data -------------------------------------------------------------------
312 sal_uInt16
XclExpString::GetFormatsCount() const
314 return static_cast< sal_uInt16
>( maFormats
.size() );
317 sal_uInt8
XclExpString::GetFlagField() const
319 return (mbIsUnicode
? EXC_STRF_16BIT
: 0) | (IsWriteFormats() ? EXC_STRF_RICH
: 0);
322 sal_uInt16
XclExpString::GetHeaderSize() const
325 (mb8BitLen
? 1 : 2) + // length field
326 (IsWriteFlags() ? 1 : 0) + // flag field
327 (IsWriteFormats() ? 2 : 0); // richtext formattting count
330 sal_Size
XclExpString::GetBufferSize() const
332 return mnLen
* (mbIsUnicode
? 2 : 1);
335 sal_Size
XclExpString::GetSize() const
338 GetHeaderSize() + // header
339 GetBufferSize() + // character buffer
340 (IsWriteFormats() ? (4 * GetFormatsCount()) : 0); // richtext formattting
343 sal_uInt16
XclExpString::GetChar( sal_uInt16 nCharIdx
) const
345 DBG_ASSERT( nCharIdx
< Len(), "XclExpString::GetChar - invalid character index" );
346 return static_cast< sal_uInt16
>( mbIsBiff8
? maUniBuffer
[ nCharIdx
] : maCharBuffer
[ nCharIdx
] );
349 sal_uInt16
XclExpString::GetHash() const
352 (mbIsBiff8
? lclHashVector( maUniBuffer
) : lclHashVector( maCharBuffer
)) ^
353 lclHashVector( maFormats
, XclFormatRunHasher() );
356 // streaming ------------------------------------------------------------------
358 void XclExpString::WriteLenField( XclExpStream
& rStrm
) const
361 rStrm
<< static_cast< sal_uInt8
>( mnLen
);
366 void XclExpString::WriteFlagField( XclExpStream
& rStrm
) const
370 PrepareWrite( rStrm
, 1 );
371 rStrm
<< GetFlagField();
372 rStrm
.SetSliceSize( 0 );
376 void XclExpString::WriteHeader( XclExpStream
& rStrm
) const
378 DBG_ASSERT( !mb8BitLen
|| (mnLen
< 256), "XclExpString::WriteHeader - string too long" );
379 PrepareWrite( rStrm
, GetHeaderSize() );
381 WriteLenField( rStrm
);
384 rStrm
<< GetFlagField();
386 if( IsWriteFormats() )
387 rStrm
<< GetFormatsCount();
388 rStrm
.SetSliceSize( 0 );
391 void XclExpString::WriteBuffer( XclExpStream
& rStrm
) const
394 rStrm
.WriteUnicodeBuffer( maUniBuffer
, GetFlagField() );
396 rStrm
.WriteCharBuffer( maCharBuffer
);
399 void XclExpString::WriteFormats( XclExpStream
& rStrm
, bool bWriteSize
) const
403 XclFormatRunVec::const_iterator aIt
= maFormats
.begin(), aEnd
= maFormats
.end();
407 rStrm
<< GetFormatsCount();
408 rStrm
.SetSliceSize( 4 );
409 for( ; aIt
!= aEnd
; ++aIt
)
410 rStrm
<< aIt
->mnChar
<< aIt
->mnFontIdx
;
415 rStrm
<< static_cast< sal_uInt8
>( GetFormatsCount() );
416 rStrm
.SetSliceSize( 2 );
417 for( ; aIt
!= aEnd
; ++aIt
)
418 rStrm
<< static_cast< sal_uInt8
>( aIt
->mnChar
) << static_cast< sal_uInt8
>( aIt
->mnFontIdx
);
420 rStrm
.SetSliceSize( 0 );
424 void XclExpString::Write( XclExpStream
& rStrm
) const
427 WriteHeader( rStrm
);
428 WriteBuffer( rStrm
);
429 if( IsWriteFormats() ) // only in BIFF8 included in string
430 WriteFormats( rStrm
);
433 void XclExpString::WriteHeaderToMem( sal_uInt8
* pnMem
) const
435 DBG_ASSERT( pnMem
, "XclExpString::WriteHeaderToMem - no memory to write to" );
436 DBG_ASSERT( !mb8BitLen
|| (mnLen
< 256), "XclExpString::WriteHeaderToMem - string too long" );
437 DBG_ASSERT( !IsWriteFormats(), "XclExpString::WriteHeaderToMem - formatted strings not supported" );
441 *pnMem
= static_cast< sal_uInt8
>( mnLen
);
446 ShortToSVBT16( mnLen
, pnMem
);
451 *pnMem
= GetFlagField();
454 void XclExpString::WriteBufferToMem( sal_uInt8
* pnMem
) const
456 DBG_ASSERT( pnMem
, "XclExpString::WriteBufferToMem - no memory to write to" );
461 for( ScfUInt16Vec::const_iterator aIt
= maUniBuffer
.begin(), aEnd
= maUniBuffer
.end(); aIt
!= aEnd
; ++aIt
)
463 sal_uInt16 nChar
= *aIt
;
464 *pnMem
= static_cast< sal_uInt8
>( nChar
);
468 *pnMem
= static_cast< sal_uInt8
>( nChar
>> 8 );
474 memcpy( pnMem
, &maCharBuffer
[ 0 ], mnLen
);
478 void XclExpString::WriteToMem( sal_uInt8
* pnMem
) const
480 WriteHeaderToMem( pnMem
);
481 WriteBufferToMem( pnMem
+ GetHeaderSize() );
484 static sal_uInt16
lcl_WriteRun( XclExpXmlStream
& rStrm
, const ScfUInt16Vec
& rBuffer
, sal_uInt16 nStart
, sal_Int32 nLength
, const XclExpFont
* pFont
)
489 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
491 rWorksheet
->startElement( XML_r
, FSEND
);
494 const XclFontData
& rFontData
= pFont
->GetFontData();
495 rWorksheet
->startElement( XML_rPr
, FSEND
);
496 rStrm
.WriteFontData( rFontData
, XML_rFont
);
497 rWorksheet
->endElement( XML_rPr
);
499 rWorksheet
->startElement( XML_t
,
500 FSNS( XML_xml
, XML_space
), "preserve",
502 rWorksheet
->writeEscaped( XclXmlUtils::ToOUString( rBuffer
, nStart
, nLength
) );
503 rWorksheet
->endElement( XML_t
);
504 rWorksheet
->endElement( XML_r
);
505 return static_cast<sal_uInt16
>(nStart
+ nLength
);
508 void XclExpString::WriteXml( XclExpXmlStream
& rStrm
) const
510 sax_fastparser::FSHelperPtr rWorksheet
= rStrm
.GetCurrentStream();
512 if( !IsWriteFormats() )
514 rWorksheet
->startElement( XML_t
, FSEND
);
515 rWorksheet
->writeEscaped( XclXmlUtils::ToOUString( *this ) );
516 rWorksheet
->endElement( XML_t
);
520 XclExpFontBuffer
& rFonts
= rStrm
.GetRoot().GetFontBuffer();
521 XclFormatRunVec::const_iterator aIt
= maFormats
.begin(), aEnd
= maFormats
.end();
523 sal_uInt16 nStart
= 0;
524 const XclExpFont
* pFont
= NULL
;
525 for ( ; aIt
!= aEnd
; ++aIt
)
527 nStart
= lcl_WriteRun( rStrm
, GetUnicodeBuffer(),
528 nStart
, aIt
->mnChar
-nStart
, pFont
);
529 pFont
= rFonts
.GetFont( aIt
->mnFontIdx
);
531 lcl_WriteRun( rStrm
, GetUnicodeBuffer(),
532 nStart
, GetUnicodeBuffer().size() - nStart
, pFont
);
536 // ----------------------------------------------------------------------------
538 bool XclExpString::IsWriteFlags() const
540 return mbIsBiff8
&& (!IsEmpty() || !mbSmartFlags
);
543 bool XclExpString::IsWriteFormats() const
545 return mbIsBiff8
&& !mbSkipFormats
&& IsRich();
548 void XclExpString::SetStrLen( sal_Int32 nNewLen
)
550 sal_uInt16 nAllowedLen
= (mb8BitLen
&& (mnMaxLen
> 255)) ? 255 : mnMaxLen
;
551 mnLen
= limit_cast
< sal_uInt16
>( nNewLen
, 0, nAllowedLen
);
554 void XclExpString::CharsToBuffer( const sal_Unicode
* pcSource
, sal_Int32 nBegin
, sal_Int32 nLen
)
556 DBG_ASSERT( maUniBuffer
.size() >= static_cast< size_t >( nBegin
+ nLen
),
557 "XclExpString::CharsToBuffer - char buffer invalid" );
558 ScfUInt16Vec::iterator aBeg
= maUniBuffer
.begin() + nBegin
;
559 ScfUInt16Vec::iterator aEnd
= aBeg
+ nLen
;
560 const sal_Unicode
* pcSrcChar
= pcSource
;
561 for( ScfUInt16Vec::iterator aIt
= aBeg
; aIt
!= aEnd
; ++aIt
, ++pcSrcChar
)
563 *aIt
= static_cast< sal_uInt16
>( *pcSrcChar
);
568 mbWrapped
= ::std::find( aBeg
, aEnd
, EXC_LF
) != aEnd
;
571 void XclExpString::CharsToBuffer( const sal_Char
* pcSource
, sal_Int32 nBegin
, sal_Int32 nLen
)
573 DBG_ASSERT( maCharBuffer
.size() >= static_cast< size_t >( nBegin
+ nLen
),
574 "XclExpString::CharsToBuffer - char buffer invalid" );
575 ScfUInt8Vec::iterator aBeg
= maCharBuffer
.begin() + nBegin
;
576 ScfUInt8Vec::iterator aEnd
= aBeg
+ nLen
;
577 const sal_Char
* pcSrcChar
= pcSource
;
578 for( ScfUInt8Vec::iterator aIt
= aBeg
; aIt
!= aEnd
; ++aIt
, ++pcSrcChar
)
579 *aIt
= static_cast< sal_uInt8
>( *pcSrcChar
);
582 mbWrapped
= ::std::find( aBeg
, aEnd
, EXC_LF_C
) != aEnd
;
585 void XclExpString::Init( sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
, bool bBiff8
)
588 mbIsUnicode
= bBiff8
&& ::get_flag( nFlags
, EXC_STR_FORCEUNICODE
);
589 mb8BitLen
= ::get_flag( nFlags
, EXC_STR_8BITLENGTH
);
590 mbSmartFlags
= bBiff8
&& ::get_flag( nFlags
, EXC_STR_SMARTFLAGS
);
591 mbSkipFormats
= ::get_flag( nFlags
, EXC_STR_SEPARATEFORMATS
);
593 mbSkipHeader
= ::get_flag( nFlags
, EXC_STR_NOHEADER
);
595 SetStrLen( nCurrLen
);
600 maCharBuffer
.clear();
601 maUniBuffer
.resize( mnLen
);
606 maCharBuffer
.resize( mnLen
);
610 void XclExpString::Build( const sal_Unicode
* pcSource
, sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
612 Init( nCurrLen
, nFlags
, nMaxLen
, true );
613 CharsToBuffer( pcSource
, 0, mnLen
);
616 void XclExpString::Build( const sal_Char
* pcSource
, sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
618 Init( nCurrLen
, nFlags
, nMaxLen
, false );
619 CharsToBuffer( pcSource
, 0, mnLen
);
622 void XclExpString::InitAppend( sal_Int32 nAddLen
)
624 SetStrLen( static_cast< sal_Int32
>( mnLen
) + nAddLen
);
626 maUniBuffer
.resize( mnLen
);
628 maCharBuffer
.resize( mnLen
);
631 void XclExpString::BuildAppend( const sal_Unicode
* pcSource
, sal_Int32 nAddLen
)
633 DBG_ASSERT( mbIsBiff8
, "XclExpString::BuildAppend - must not be called at byte strings" );
636 sal_uInt16 nOldLen
= mnLen
;
637 InitAppend( nAddLen
);
638 CharsToBuffer( pcSource
, nOldLen
, mnLen
- nOldLen
);
642 void XclExpString::BuildAppend( const sal_Char
* pcSource
, sal_Int32 nAddLen
)
644 DBG_ASSERT( !mbIsBiff8
, "XclExpString::BuildAppend - must not be called at unicode strings" );
647 sal_uInt16 nOldLen
= mnLen
;
648 InitAppend( nAddLen
);
649 CharsToBuffer( pcSource
, nOldLen
, mnLen
- nOldLen
);
653 void XclExpString::PrepareWrite( XclExpStream
& rStrm
, sal_uInt16 nBytes
) const
655 rStrm
.SetSliceSize( nBytes
+ (mbIsUnicode
? 2 : 1) );
658 // ============================================================================