1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
23 #include "xlstyle.hxx"
24 #include "xestyle.hxx"
25 #include "xestream.hxx"
26 #include "xestring.hxx"
28 using namespace ::oox
;
31 // ============================================================================
37 /** Compares two vectors.
38 @return A negative value, if rLeft<rRight; or a positive value, if rLeft>rRight;
39 or 0, if rLeft==rRight. */
40 template< typename Type
>
41 int lclCompareVectors( const ::std::vector
< Type
>& rLeft
, const ::std::vector
< Type
>& rRight
)
45 // 1st: compare all elements of the vectors
46 typedef typename ::std::vector
< Type
>::const_iterator CIT
;
47 CIT aEndL
= rLeft
.end(), aEndR
= rRight
.end();
48 for( CIT aItL
= rLeft
.begin(), aItR
= rRight
.begin(); !nResult
&& (aItL
!= aEndL
) && (aItR
!= aEndR
); ++aItL
, ++aItR
)
49 nResult
= static_cast< int >( *aItL
) - static_cast< int >( *aItR
);
51 // 2nd: no differences found so far -> compare the vector sizes. Shorter vector is less
53 nResult
= static_cast< int >( rLeft
.size() ) - static_cast< int >( rRight
.size() );
60 /** Base class for value hashers.
61 @descr These function objects are used to hash any value to a sal_uInt32 value. */
62 template< typename Type
>
63 struct XclHasher
: public ::std::unary_function
< Type
, sal_uInt32
> {};
65 template< typename Type
>
66 struct XclDirectHasher
: public XclHasher
< Type
>
68 inline sal_uInt32
operator()( Type nVal
) const { return nVal
; }
71 struct XclFormatRunHasher
: public XclHasher
< const XclFormatRun
& >
73 inline sal_uInt32
operator()( const XclFormatRun
& rRun
) const
74 { return (rRun
.mnChar
<< 8) ^ rRun
.mnFontIdx
; }
77 /** Calculates a hash value from a vector.
78 @descr Uses the passed hasher function object to calculate hash values from
79 all vector elements. */
80 template< typename Type
, typename ValueHasher
>
81 sal_uInt16
lclHashVector( const ::std::vector
< Type
>& rVec
, const ValueHasher
& rHasher
)
83 sal_uInt32 nHash
= rVec
.size();
84 typedef typename ::std::vector
< Type
>::const_iterator CIT
;
85 for( CIT aIt
= rVec
.begin(), aEnd
= rVec
.end(); aIt
!= aEnd
; ++aIt
)
86 (nHash
*= 31) += rHasher( *aIt
);
87 return static_cast< sal_uInt16
>( nHash
^ (nHash
>> 16) );
90 /** Calculates a hash value from a vector. Uses XclDirectHasher to hash the vector elements. */
91 template< typename Type
>
92 inline sal_uInt16
lclHashVector( const ::std::vector
< Type
>& rVec
)
94 return lclHashVector( rVec
, XclDirectHasher
< Type
>() );
99 // constructors ---------------------------------------------------------------
101 XclExpString::XclExpString( XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
103 Init( 0, nFlags
, nMaxLen
, true );
106 XclExpString::XclExpString( const String
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
108 Assign( rString
, nFlags
, nMaxLen
);
111 XclExpString::XclExpString( const OUString
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
113 Assign( rString
, nFlags
, nMaxLen
);
116 // assign ---------------------------------------------------------------------
118 void XclExpString::Assign( const String
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
120 Build( rString
.GetBuffer(), rString
.Len(), nFlags
, nMaxLen
);
123 void XclExpString::Assign( const OUString
& rString
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
125 Build( rString
.getStr(), rString
.getLength(), nFlags
, nMaxLen
);
128 void XclExpString::Assign( sal_Unicode cChar
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
130 Build( &cChar
, 1, nFlags
, nMaxLen
);
133 void XclExpString::AssignByte(
134 const String
& rString
, rtl_TextEncoding eTextEnc
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
136 // length may differ from length of rString
137 OString
aByteStr(OUStringToOString(rString
, eTextEnc
));
138 Build(aByteStr
.getStr(), aByteStr
.getLength(), nFlags
, nMaxLen
);
141 // append ---------------------------------------------------------------------
143 void XclExpString::Append( const String
& rString
)
145 BuildAppend( rString
.GetBuffer(), rString
.Len() );
148 void XclExpString::AppendByte( const String
& rString
, rtl_TextEncoding eTextEnc
)
150 if( rString
.Len() > 0 )
152 // length may differ from length of rString
153 OString
aByteStr(OUStringToOString(rString
, eTextEnc
));
154 BuildAppend(aByteStr
.getStr(), aByteStr
.getLength());
158 void XclExpString::AppendByte( sal_Unicode cChar
, rtl_TextEncoding eTextEnc
)
162 sal_Char cByteChar
= 0;
163 BuildAppend( &cByteChar
, 1 );
167 OString
aByteStr( &cChar
, 1, eTextEnc
); // length may be >1
168 BuildAppend( aByteStr
.getStr(), aByteStr
.getLength() );
172 // formatting runs ------------------------------------------------------------
174 void XclExpString::AppendFormat( sal_uInt16 nChar
, sal_uInt16 nFontIdx
, bool bDropDuplicate
)
176 OSL_ENSURE( maFormats
.empty() || (maFormats
.back().mnChar
< nChar
), "XclExpString::AppendFormat - invalid char index" );
177 size_t nMaxSize
= static_cast< size_t >( mbIsBiff8
? EXC_STR_MAXLEN
: EXC_STR_MAXLEN_8BIT
);
178 if( maFormats
.empty() || ((maFormats
.size() < nMaxSize
) && (!bDropDuplicate
|| (maFormats
.back().mnFontIdx
!= nFontIdx
))) )
179 maFormats
.push_back( XclFormatRun( nChar
, nFontIdx
) );
182 void XclExpString::AppendTrailingFormat( sal_uInt16 nFontIdx
)
184 AppendFormat( mnLen
, nFontIdx
, false );
187 void XclExpString::LimitFormatCount( sal_uInt16 nMaxCount
)
189 if( maFormats
.size() > nMaxCount
)
190 maFormats
.erase( maFormats
.begin() + nMaxCount
, maFormats
.end() );
193 sal_uInt16
XclExpString::RemoveLeadingFont()
195 sal_uInt16 nFontIdx
= EXC_FONT_NOTFOUND
;
196 if( !maFormats
.empty() && (maFormats
.front().mnChar
== 0) )
198 nFontIdx
= maFormats
.front().mnFontIdx
;
199 maFormats
.erase( maFormats
.begin() );
204 bool XclExpString::IsEqual( const XclExpString
& rCmp
) const
207 (mnLen
== rCmp
.mnLen
) &&
208 (mbIsBiff8
== rCmp
.mbIsBiff8
) &&
209 (mbIsUnicode
== rCmp
.mbIsUnicode
) &&
210 (mbWrapped
== rCmp
.mbWrapped
) &&
212 ( mbIsBiff8
&& (maUniBuffer
== rCmp
.maUniBuffer
)) ||
213 (!mbIsBiff8
&& (maCharBuffer
== rCmp
.maCharBuffer
))
215 (maFormats
== rCmp
.maFormats
);
218 bool XclExpString::IsLessThan( const XclExpString
& rCmp
) const
220 int nResult
= mbIsBiff8
?
221 lclCompareVectors( maUniBuffer
, rCmp
.maUniBuffer
) :
222 lclCompareVectors( maCharBuffer
, rCmp
.maCharBuffer
);
223 return (nResult
!= 0) ? (nResult
< 0) : (maFormats
< rCmp
.maFormats
);
226 // get data -------------------------------------------------------------------
228 sal_uInt16
XclExpString::GetFormatsCount() const
230 return static_cast< sal_uInt16
>( maFormats
.size() );
233 sal_uInt8
XclExpString::GetFlagField() const
235 return (mbIsUnicode
? EXC_STRF_16BIT
: 0) | (IsWriteFormats() ? EXC_STRF_RICH
: 0);
238 sal_uInt16
XclExpString::GetHeaderSize() const
241 (mb8BitLen
? 1 : 2) + // length field
242 (IsWriteFlags() ? 1 : 0) + // flag field
243 (IsWriteFormats() ? 2 : 0); // richtext formattting count
246 sal_Size
XclExpString::GetBufferSize() const
248 return mnLen
* (mbIsUnicode
? 2 : 1);
251 sal_Size
XclExpString::GetSize() const
254 GetHeaderSize() + // header
255 GetBufferSize() + // character buffer
256 (IsWriteFormats() ? (4 * GetFormatsCount()) : 0); // richtext formattting
259 sal_uInt16
XclExpString::GetChar( sal_uInt16 nCharIdx
) const
261 OSL_ENSURE( nCharIdx
< Len(), "XclExpString::GetChar - invalid character index" );
262 return static_cast< sal_uInt16
>( mbIsBiff8
? maUniBuffer
[ nCharIdx
] : maCharBuffer
[ nCharIdx
] );
265 sal_uInt16
XclExpString::GetHash() const
268 (mbIsBiff8
? lclHashVector( maUniBuffer
) : lclHashVector( maCharBuffer
)) ^
269 lclHashVector( maFormats
, XclFormatRunHasher() );
272 // streaming ------------------------------------------------------------------
274 void XclExpString::WriteLenField( XclExpStream
& rStrm
) const
277 rStrm
<< static_cast< sal_uInt8
>( mnLen
);
282 void XclExpString::WriteFlagField( XclExpStream
& rStrm
) const
286 PrepareWrite( rStrm
, 1 );
287 rStrm
<< GetFlagField();
288 rStrm
.SetSliceSize( 0 );
292 void XclExpString::WriteHeader( XclExpStream
& rStrm
) const
294 OSL_ENSURE( !mb8BitLen
|| (mnLen
< 256), "XclExpString::WriteHeader - string too long" );
295 PrepareWrite( rStrm
, GetHeaderSize() );
297 WriteLenField( rStrm
);
300 rStrm
<< GetFlagField();
302 if( IsWriteFormats() )
303 rStrm
<< GetFormatsCount();
304 rStrm
.SetSliceSize( 0 );
307 void XclExpString::WriteBuffer( XclExpStream
& rStrm
) const
310 rStrm
.WriteUnicodeBuffer( maUniBuffer
, GetFlagField() );
312 rStrm
.WriteCharBuffer( maCharBuffer
);
315 void XclExpString::WriteFormats( XclExpStream
& rStrm
, bool bWriteSize
) const
319 XclFormatRunVec::const_iterator aIt
= maFormats
.begin(), aEnd
= maFormats
.end();
323 rStrm
<< GetFormatsCount();
324 rStrm
.SetSliceSize( 4 );
325 for( ; aIt
!= aEnd
; ++aIt
)
326 rStrm
<< aIt
->mnChar
<< aIt
->mnFontIdx
;
331 rStrm
<< static_cast< sal_uInt8
>( GetFormatsCount() );
332 rStrm
.SetSliceSize( 2 );
333 for( ; aIt
!= aEnd
; ++aIt
)
334 rStrm
<< static_cast< sal_uInt8
>( aIt
->mnChar
) << static_cast< sal_uInt8
>( aIt
->mnFontIdx
);
336 rStrm
.SetSliceSize( 0 );
340 void XclExpString::Write( XclExpStream
& rStrm
) const
343 WriteHeader( rStrm
);
344 WriteBuffer( rStrm
);
345 if( IsWriteFormats() ) // only in BIFF8 included in string
346 WriteFormats( rStrm
);
349 void XclExpString::WriteHeaderToMem( sal_uInt8
* pnMem
) const
351 OSL_ENSURE( pnMem
, "XclExpString::WriteHeaderToMem - no memory to write to" );
352 OSL_ENSURE( !mb8BitLen
|| (mnLen
< 256), "XclExpString::WriteHeaderToMem - string too long" );
353 OSL_ENSURE( !IsWriteFormats(), "XclExpString::WriteHeaderToMem - formatted strings not supported" );
357 *pnMem
= static_cast< sal_uInt8
>( mnLen
);
362 ShortToSVBT16( mnLen
, pnMem
);
367 *pnMem
= GetFlagField();
370 void XclExpString::WriteBufferToMem( sal_uInt8
* pnMem
) const
372 OSL_ENSURE( pnMem
, "XclExpString::WriteBufferToMem - no memory to write to" );
377 for( ScfUInt16Vec::const_iterator aIt
= maUniBuffer
.begin(), aEnd
= maUniBuffer
.end(); aIt
!= aEnd
; ++aIt
)
379 sal_uInt16 nChar
= *aIt
;
380 *pnMem
= static_cast< sal_uInt8
>( nChar
);
384 *pnMem
= static_cast< sal_uInt8
>( nChar
>> 8 );
390 memcpy( pnMem
, &maCharBuffer
[ 0 ], mnLen
);
394 void XclExpString::WriteToMem( sal_uInt8
* pnMem
) const
396 WriteHeaderToMem( pnMem
);
397 WriteBufferToMem( pnMem
+ GetHeaderSize() );
400 static sal_uInt16
lcl_WriteRun( XclExpXmlStream
& rStrm
, const ScfUInt16Vec
& rBuffer
, sal_uInt16 nStart
, sal_Int32 nLength
, const XclExpFont
* pFont
)
405 sax_fastparser::FSHelperPtr
& rWorksheet
= rStrm
.GetCurrentStream();
407 rWorksheet
->startElement( XML_r
, FSEND
);
410 const XclFontData
& rFontData
= pFont
->GetFontData();
411 rWorksheet
->startElement( XML_rPr
, FSEND
);
412 XclXmlUtils::WriteFontData( rWorksheet
, rFontData
, XML_rFont
);
413 rWorksheet
->endElement( XML_rPr
);
415 rWorksheet
->startElement( XML_t
,
416 FSNS( XML_xml
, XML_space
), "preserve",
418 rWorksheet
->writeEscaped( XclXmlUtils::ToOUString( rBuffer
, nStart
, nLength
) );
419 rWorksheet
->endElement( XML_t
);
420 rWorksheet
->endElement( XML_r
);
421 return nStart
+ nLength
;
424 void XclExpString::WriteXml( XclExpXmlStream
& rStrm
) const
426 sax_fastparser::FSHelperPtr rWorksheet
= rStrm
.GetCurrentStream();
428 if( !IsWriteFormats() )
430 rWorksheet
->startElement( XML_t
, FSEND
);
431 rWorksheet
->writeEscaped( XclXmlUtils::ToOUString( *this ) );
432 rWorksheet
->endElement( XML_t
);
436 XclExpFontBuffer
& rFonts
= rStrm
.GetRoot().GetFontBuffer();
437 XclFormatRunVec::const_iterator aIt
= maFormats
.begin(), aEnd
= maFormats
.end();
439 sal_uInt16 nStart
= 0;
440 const XclExpFont
* pFont
= NULL
;
441 for ( ; aIt
!= aEnd
; ++aIt
)
443 nStart
= lcl_WriteRun( rStrm
, GetUnicodeBuffer(),
444 nStart
, aIt
->mnChar
-nStart
, pFont
);
445 pFont
= rFonts
.GetFont( aIt
->mnFontIdx
);
447 lcl_WriteRun( rStrm
, GetUnicodeBuffer(),
448 nStart
, GetUnicodeBuffer().size() - nStart
, pFont
);
452 // ----------------------------------------------------------------------------
454 bool XclExpString::IsWriteFlags() const
456 return mbIsBiff8
&& (!IsEmpty() || !mbSmartFlags
);
459 bool XclExpString::IsWriteFormats() const
461 return mbIsBiff8
&& !mbSkipFormats
&& IsRich();
464 void XclExpString::SetStrLen( sal_Int32 nNewLen
)
466 sal_uInt16 nAllowedLen
= (mb8BitLen
&& (mnMaxLen
> 255)) ? 255 : mnMaxLen
;
467 mnLen
= limit_cast
< sal_uInt16
>( nNewLen
, 0, nAllowedLen
);
470 void XclExpString::CharsToBuffer( const sal_Unicode
* pcSource
, sal_Int32 nBegin
, sal_Int32 nLen
)
472 OSL_ENSURE( maUniBuffer
.size() >= static_cast< size_t >( nBegin
+ nLen
),
473 "XclExpString::CharsToBuffer - char buffer invalid" );
474 ScfUInt16Vec::iterator aBeg
= maUniBuffer
.begin() + nBegin
;
475 ScfUInt16Vec::iterator aEnd
= aBeg
+ nLen
;
476 const sal_Unicode
* pcSrcChar
= pcSource
;
477 for( ScfUInt16Vec::iterator aIt
= aBeg
; aIt
!= aEnd
; ++aIt
, ++pcSrcChar
)
479 *aIt
= static_cast< sal_uInt16
>( *pcSrcChar
);
484 mbWrapped
= ::std::find( aBeg
, aEnd
, EXC_LF
) != aEnd
;
487 void XclExpString::CharsToBuffer( const sal_Char
* pcSource
, sal_Int32 nBegin
, sal_Int32 nLen
)
489 OSL_ENSURE( maCharBuffer
.size() >= static_cast< size_t >( nBegin
+ nLen
),
490 "XclExpString::CharsToBuffer - char buffer invalid" );
491 ScfUInt8Vec::iterator aBeg
= maCharBuffer
.begin() + nBegin
;
492 ScfUInt8Vec::iterator aEnd
= aBeg
+ nLen
;
493 const sal_Char
* pcSrcChar
= pcSource
;
494 for( ScfUInt8Vec::iterator aIt
= aBeg
; aIt
!= aEnd
; ++aIt
, ++pcSrcChar
)
495 *aIt
= static_cast< sal_uInt8
>( *pcSrcChar
);
498 mbWrapped
= ::std::find( aBeg
, aEnd
, EXC_LF_C
) != aEnd
;
501 void XclExpString::Init( sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
, bool bBiff8
)
504 mbIsUnicode
= bBiff8
&& ::get_flag( nFlags
, EXC_STR_FORCEUNICODE
);
505 mb8BitLen
= ::get_flag( nFlags
, EXC_STR_8BITLENGTH
);
506 mbSmartFlags
= bBiff8
&& ::get_flag( nFlags
, EXC_STR_SMARTFLAGS
);
507 mbSkipFormats
= ::get_flag( nFlags
, EXC_STR_SEPARATEFORMATS
);
509 mbSkipHeader
= ::get_flag( nFlags
, EXC_STR_NOHEADER
);
511 SetStrLen( nCurrLen
);
516 maCharBuffer
.clear();
517 maUniBuffer
.resize( mnLen
);
522 maCharBuffer
.resize( mnLen
);
526 void XclExpString::Build( const sal_Unicode
* pcSource
, sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
528 Init( nCurrLen
, nFlags
, nMaxLen
, true );
529 CharsToBuffer( pcSource
, 0, mnLen
);
532 void XclExpString::Build( const sal_Char
* pcSource
, sal_Int32 nCurrLen
, XclStrFlags nFlags
, sal_uInt16 nMaxLen
)
534 Init( nCurrLen
, nFlags
, nMaxLen
, false );
535 CharsToBuffer( pcSource
, 0, mnLen
);
538 void XclExpString::InitAppend( sal_Int32 nAddLen
)
540 SetStrLen( static_cast< sal_Int32
>( mnLen
) + nAddLen
);
542 maUniBuffer
.resize( mnLen
);
544 maCharBuffer
.resize( mnLen
);
547 void XclExpString::BuildAppend( const sal_Unicode
* pcSource
, sal_Int32 nAddLen
)
549 OSL_ENSURE( mbIsBiff8
, "XclExpString::BuildAppend - must not be called at byte strings" );
552 sal_uInt16 nOldLen
= mnLen
;
553 InitAppend( nAddLen
);
554 CharsToBuffer( pcSource
, nOldLen
, mnLen
- nOldLen
);
558 void XclExpString::BuildAppend( const sal_Char
* pcSource
, sal_Int32 nAddLen
)
560 OSL_ENSURE( !mbIsBiff8
, "XclExpString::BuildAppend - must not be called at unicode strings" );
563 sal_uInt16 nOldLen
= mnLen
;
564 InitAppend( nAddLen
);
565 CharsToBuffer( pcSource
, nOldLen
, mnLen
- nOldLen
);
569 void XclExpString::PrepareWrite( XclExpStream
& rStrm
, sal_uInt16 nBytes
) const
571 rStrm
.SetSliceSize( nBytes
+ (mbIsUnicode
? 2 : 1) );
574 // ============================================================================
576 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */