/************************************************************** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_scfilt.hxx" #include #include #include "xestream.hxx" #include "xlstyle.hxx" #include "xestyle.hxx" #include "xestring.hxx" using namespace ::oox; using ::rtl::OString; using ::rtl::OUString; // ============================================================================ namespace { // compare vectors /** Compares two vectors. @return A negative value, if rLeftrRight; or 0, if rLeft==rRight. */ template< typename Type > int lclCompareVectors( const ::std::vector< Type >& rLeft, const ::std::vector< Type >& rRight ) { int nResult = 0; // 1st: compare all elements of the vectors typedef typename ::std::vector< Type >::const_iterator CIT; CIT aEndL = rLeft.end(), aEndR = rRight.end(); for( CIT aItL = rLeft.begin(), aItR = rRight.begin(); !nResult && (aItL != aEndL) && (aItR != aEndR); ++aItL, ++aItR ) nResult = static_cast< int >( *aItL ) - static_cast< int >( *aItR ); // 2nd: no differences found so far -> compare the vector sizes. Shorter vector is less if( !nResult ) nResult = static_cast< int >( rLeft.size() ) - static_cast< int >( rRight.size() ); return nResult; } // hashing helpers /** Base class for value hashers. @descr These function objects are used to hash any value to a sal_uInt32 value. */ template< typename Type > struct XclHasher : public ::std::unary_function< Type, sal_uInt32 > {}; template< typename Type > struct XclDirectHasher : public XclHasher< Type > { inline sal_uInt32 operator()( Type nVal ) const { return nVal; } }; struct XclFormatRunHasher : public XclHasher< const XclFormatRun& > { inline sal_uInt32 operator()( const XclFormatRun& rRun ) const { return (rRun.mnChar << 8) ^ rRun.mnFontIdx; } }; /** Calculates a hash value from a vector. @descr Uses the passed hasher function object to calculate hash values from all vector elements. */ template< typename Type, typename ValueHasher > sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec, const ValueHasher& rHasher ) { sal_uInt32 nHash = rVec.size(); typedef typename ::std::vector< Type >::const_iterator CIT; for( CIT aIt = rVec.begin(), aEnd = rVec.end(); aIt != aEnd; ++aIt ) (nHash *= 31) += rHasher( *aIt ); return static_cast< sal_uInt16 >( nHash ^ (nHash >> 16) ); } /** Calculates a hash value from a vector. Uses XclDirectHasher to hash the vector elements. */ template< typename Type > inline sal_uInt16 lclHashVector( const ::std::vector< Type >& rVec ) { return lclHashVector( rVec, XclDirectHasher< Type >() ); } } // namespace // constructors --------------------------------------------------------------- XclExpString::XclExpString( XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Init( 0, nFlags, nMaxLen, true ); } XclExpString::XclExpString( const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Assign( rString, nFlags, nMaxLen ); } XclExpString::XclExpString( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Assign( rString, nFlags, nMaxLen ); } //UNUSED2008-05 XclExpString::XclExpString( //UNUSED2008-05 const String& rString, const XclFormatRunVec& rFormats, //UNUSED2008-05 XclStrFlags nFlags, sal_uInt16 nMaxLen ) //UNUSED2008-05 { //UNUSED2008-05 Assign( rString, rFormats, nFlags, nMaxLen ); //UNUSED2008-05 } //UNUSED2008-05 //UNUSED2008-05 XclExpString::XclExpString( //UNUSED2008-05 const OUString& rString, const XclFormatRunVec& rFormats, //UNUSED2008-05 XclStrFlags nFlags, sal_uInt16 nMaxLen ) //UNUSED2008-05 { //UNUSED2008-05 Assign( rString, rFormats, nFlags, nMaxLen ); //UNUSED2008-05 } // assign --------------------------------------------------------------------- void XclExpString::Assign( const String& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Build( rString.GetBuffer(), rString.Len(), nFlags, nMaxLen ); } void XclExpString::Assign( const String& rString, const XclFormatRunVec& rFormats, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Assign( rString, nFlags, nMaxLen ); SetFormats( rFormats ); } void XclExpString::Assign( const OUString& rString, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Build( rString.getStr(), rString.getLength(), nFlags, nMaxLen ); } void XclExpString::Assign( const OUString& rString, const XclFormatRunVec& rFormats, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Assign( rString, nFlags, nMaxLen ); SetFormats( rFormats ); } void XclExpString::Assign( sal_Unicode cChar, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Build( &cChar, 1, nFlags, nMaxLen ); } void XclExpString::AssignByte( const String& rString, rtl_TextEncoding eTextEnc, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { ByteString aByteStr( rString, eTextEnc ); // length may differ from length of rString Build( aByteStr.GetBuffer(), aByteStr.Len(), nFlags, nMaxLen ); } //UNUSED2008-05 void XclExpString::AssignByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc, XclStrFlags nFlags, sal_uInt16 nMaxLen ) //UNUSED2008-05 { //UNUSED2008-05 if( !cChar ) //UNUSED2008-05 { //UNUSED2008-05 sal_Char cByteChar = 0; //UNUSED2008-05 Build( &cByteChar, 1, nFlags, nMaxLen ); //UNUSED2008-05 } //UNUSED2008-05 else //UNUSED2008-05 { //UNUSED2008-05 ByteString aByteStr( &cChar, 1, eTextEnc ); // length may be >1 //UNUSED2008-05 Build( aByteStr.GetBuffer(), aByteStr.Len(), nFlags, nMaxLen ); //UNUSED2008-05 } //UNUSED2008-05 } // append --------------------------------------------------------------------- void XclExpString::Append( const String& rString ) { BuildAppend( rString.GetBuffer(), rString.Len() ); } //UNUSED2008-05 void XclExpString::Append( const ::rtl::OUString& rString ) //UNUSED2008-05 { //UNUSED2008-05 BuildAppend( rString.getStr(), rString.getLength() ); //UNUSED2008-05 } //UNUSED2008-05 //UNUSED2008-05 void XclExpString::Append( sal_Unicode cChar ) //UNUSED2008-05 { //UNUSED2008-05 BuildAppend( &cChar, 1 ); //UNUSED2008-05 } void XclExpString::AppendByte( const String& rString, rtl_TextEncoding eTextEnc ) { if( rString.Len() > 0 ) { ByteString aByteStr( rString, eTextEnc ); // length may differ from length of rString BuildAppend( aByteStr.GetBuffer(), aByteStr.Len() ); } } void XclExpString::AppendByte( sal_Unicode cChar, rtl_TextEncoding eTextEnc ) { if( !cChar ) { sal_Char cByteChar = 0; BuildAppend( &cByteChar, 1 ); } else { ByteString aByteStr( &cChar, 1, eTextEnc ); // length may be >1 BuildAppend( aByteStr.GetBuffer(), aByteStr.Len() ); } } // formatting runs ------------------------------------------------------------ void XclExpString::SetFormats( const XclFormatRunVec& rFormats ) { maFormats = rFormats; #ifdef DBG_UTIL if( IsRich() ) { XclFormatRunVec::const_iterator aCurr = maFormats.begin(); XclFormatRunVec::const_iterator aPrev = aCurr; XclFormatRunVec::const_iterator aEnd = maFormats.end(); for( ++aCurr; aCurr != aEnd; ++aCurr, ++aPrev ) DBG_ASSERT( aPrev->mnChar < aCurr->mnChar, "XclExpString::SetFormats - invalid char order" ); DBG_ASSERT( aPrev->mnChar <= mnLen, "XclExpString::SetFormats - invalid char index" ); } #endif LimitFormatCount( mbIsBiff8 ? EXC_STR_MAXLEN : EXC_STR_MAXLEN_8BIT ); } void XclExpString::AppendFormat( sal_uInt16 nChar, sal_uInt16 nFontIdx, bool bDropDuplicate ) { DBG_ASSERT( maFormats.empty() || (maFormats.back().mnChar < nChar), "XclExpString::AppendFormat - invalid char index" ); size_t nMaxSize = static_cast< size_t >( mbIsBiff8 ? EXC_STR_MAXLEN : EXC_STR_MAXLEN_8BIT ); if( maFormats.empty() || ((maFormats.size() < nMaxSize) && (!bDropDuplicate || (maFormats.back().mnFontIdx != nFontIdx))) ) maFormats.push_back( XclFormatRun( nChar, nFontIdx ) ); } void XclExpString::AppendTrailingFormat( sal_uInt16 nFontIdx ) { AppendFormat( mnLen, nFontIdx, false ); } void XclExpString::LimitFormatCount( sal_uInt16 nMaxCount ) { if( maFormats.size() > nMaxCount ) maFormats.erase( maFormats.begin() + nMaxCount, maFormats.end() ); } sal_uInt16 XclExpString::RemoveLeadingFont() { sal_uInt16 nFontIdx = EXC_FONT_NOTFOUND; if( !maFormats.empty() && (maFormats.front().mnChar == 0) ) { nFontIdx = maFormats.front().mnFontIdx; maFormats.erase( maFormats.begin() ); } return nFontIdx; } bool XclExpString::IsEqual( const XclExpString& rCmp ) const { return (mnLen == rCmp.mnLen) && (mbIsBiff8 == rCmp.mbIsBiff8) && (mbIsUnicode == rCmp.mbIsUnicode) && (mbWrapped == rCmp.mbWrapped) && ( ( mbIsBiff8 && (maUniBuffer == rCmp.maUniBuffer)) || (!mbIsBiff8 && (maCharBuffer == rCmp.maCharBuffer)) ) && (maFormats == rCmp.maFormats); } bool XclExpString::IsLessThan( const XclExpString& rCmp ) const { int nResult = mbIsBiff8 ? lclCompareVectors( maUniBuffer, rCmp.maUniBuffer ) : lclCompareVectors( maCharBuffer, rCmp.maCharBuffer ); return (nResult != 0) ? (nResult < 0) : (maFormats < rCmp.maFormats); } // get data ------------------------------------------------------------------- sal_uInt16 XclExpString::GetFormatsCount() const { return static_cast< sal_uInt16 >( maFormats.size() ); } sal_uInt8 XclExpString::GetFlagField() const { return (mbIsUnicode ? EXC_STRF_16BIT : 0) | (IsWriteFormats() ? EXC_STRF_RICH : 0); } sal_uInt16 XclExpString::GetHeaderSize() const { return (mb8BitLen ? 1 : 2) + // length field (IsWriteFlags() ? 1 : 0) + // flag field (IsWriteFormats() ? 2 : 0); // richtext formattting count } sal_Size XclExpString::GetBufferSize() const { return mnLen * (mbIsUnicode ? 2 : 1); } sal_Size XclExpString::GetSize() const { return GetHeaderSize() + // header GetBufferSize() + // character buffer (IsWriteFormats() ? (4 * GetFormatsCount()) : 0); // richtext formattting } sal_uInt16 XclExpString::GetChar( sal_uInt16 nCharIdx ) const { DBG_ASSERT( nCharIdx < Len(), "XclExpString::GetChar - invalid character index" ); return static_cast< sal_uInt16 >( mbIsBiff8 ? maUniBuffer[ nCharIdx ] : maCharBuffer[ nCharIdx ] ); } sal_uInt16 XclExpString::GetHash() const { return (mbIsBiff8 ? lclHashVector( maUniBuffer ) : lclHashVector( maCharBuffer )) ^ lclHashVector( maFormats, XclFormatRunHasher() ); } // streaming ------------------------------------------------------------------ void XclExpString::WriteLenField( XclExpStream& rStrm ) const { if( mb8BitLen ) rStrm << static_cast< sal_uInt8 >( mnLen ); else rStrm << mnLen; } void XclExpString::WriteFlagField( XclExpStream& rStrm ) const { if( mbIsBiff8 ) { PrepareWrite( rStrm, 1 ); rStrm << GetFlagField(); rStrm.SetSliceSize( 0 ); } } void XclExpString::WriteHeader( XclExpStream& rStrm ) const { DBG_ASSERT( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeader - string too long" ); PrepareWrite( rStrm, GetHeaderSize() ); // length WriteLenField( rStrm ); // flag field if( IsWriteFlags() ) rStrm << GetFlagField(); // format run count if( IsWriteFormats() ) rStrm << GetFormatsCount(); rStrm.SetSliceSize( 0 ); } void XclExpString::WriteBuffer( XclExpStream& rStrm ) const { if( mbIsBiff8 ) rStrm.WriteUnicodeBuffer( maUniBuffer, GetFlagField() ); else rStrm.WriteCharBuffer( maCharBuffer ); } void XclExpString::WriteFormats( XclExpStream& rStrm, bool bWriteSize ) const { if( IsRich() ) { XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end(); if( mbIsBiff8 ) { if( bWriteSize ) rStrm << GetFormatsCount(); rStrm.SetSliceSize( 4 ); for( ; aIt != aEnd; ++aIt ) rStrm << aIt->mnChar << aIt->mnFontIdx; } else { if( bWriteSize ) rStrm << static_cast< sal_uInt8 >( GetFormatsCount() ); rStrm.SetSliceSize( 2 ); for( ; aIt != aEnd; ++aIt ) rStrm << static_cast< sal_uInt8 >( aIt->mnChar ) << static_cast< sal_uInt8 >( aIt->mnFontIdx ); } rStrm.SetSliceSize( 0 ); } } void XclExpString::Write( XclExpStream& rStrm ) const { if (!mbSkipHeader) WriteHeader( rStrm ); WriteBuffer( rStrm ); if( IsWriteFormats() ) // only in BIFF8 included in string WriteFormats( rStrm ); } void XclExpString::WriteHeaderToMem( sal_uInt8* pnMem ) const { DBG_ASSERT( pnMem, "XclExpString::WriteHeaderToMem - no memory to write to" ); DBG_ASSERT( !mb8BitLen || (mnLen < 256), "XclExpString::WriteHeaderToMem - string too long" ); DBG_ASSERT( !IsWriteFormats(), "XclExpString::WriteHeaderToMem - formatted strings not supported" ); // length if( mb8BitLen ) { *pnMem = static_cast< sal_uInt8 >( mnLen ); ++pnMem; } else { ShortToSVBT16( mnLen, pnMem ); pnMem += 2; } // flag field if( IsWriteFlags() ) *pnMem = GetFlagField(); } void XclExpString::WriteBufferToMem( sal_uInt8* pnMem ) const { DBG_ASSERT( pnMem, "XclExpString::WriteBufferToMem - no memory to write to" ); if( !IsEmpty() ) { if( mbIsBiff8 ) { for( ScfUInt16Vec::const_iterator aIt = maUniBuffer.begin(), aEnd = maUniBuffer.end(); aIt != aEnd; ++aIt ) { sal_uInt16 nChar = *aIt; *pnMem = static_cast< sal_uInt8 >( nChar ); ++pnMem; if( mbIsUnicode ) { *pnMem = static_cast< sal_uInt8 >( nChar >> 8 ); ++pnMem; } } } else memcpy( pnMem, &maCharBuffer[ 0 ], mnLen ); } } void XclExpString::WriteToMem( sal_uInt8* pnMem ) const { WriteHeaderToMem( pnMem ); WriteBufferToMem( pnMem + GetHeaderSize() ); } static sal_uInt16 lcl_WriteRun( XclExpXmlStream& rStrm, const ScfUInt16Vec& rBuffer, sal_uInt16 nStart, sal_Int32 nLength, const XclExpFont* pFont ) { if( nLength == 0 ) return nStart; sax_fastparser::FSHelperPtr& rWorksheet = rStrm.GetCurrentStream(); rWorksheet->startElement( XML_r, FSEND ); if( pFont ) { const XclFontData& rFontData = pFont->GetFontData(); rWorksheet->startElement( XML_rPr, FSEND ); rStrm.WriteFontData( rFontData, XML_rFont ); rWorksheet->endElement( XML_rPr ); } rWorksheet->startElement( XML_t, FSNS( XML_xml, XML_space ), "preserve", FSEND ); rWorksheet->writeEscaped( XclXmlUtils::ToOUString( rBuffer, nStart, nLength ) ); rWorksheet->endElement( XML_t ); rWorksheet->endElement( XML_r ); return static_cast(nStart + nLength); } void XclExpString::WriteXml( XclExpXmlStream& rStrm ) const { sax_fastparser::FSHelperPtr rWorksheet = rStrm.GetCurrentStream(); if( !IsWriteFormats() ) { rWorksheet->startElement( XML_t, FSEND ); rWorksheet->writeEscaped( XclXmlUtils::ToOUString( *this ) ); rWorksheet->endElement( XML_t ); } else { XclExpFontBuffer& rFonts = rStrm.GetRoot().GetFontBuffer(); XclFormatRunVec::const_iterator aIt = maFormats.begin(), aEnd = maFormats.end(); sal_uInt16 nStart = 0; const XclExpFont* pFont = NULL; for ( ; aIt != aEnd; ++aIt ) { nStart = lcl_WriteRun( rStrm, GetUnicodeBuffer(), nStart, aIt->mnChar-nStart, pFont ); pFont = rFonts.GetFont( aIt->mnFontIdx ); } lcl_WriteRun( rStrm, GetUnicodeBuffer(), nStart, GetUnicodeBuffer().size() - nStart, pFont ); } } // ---------------------------------------------------------------------------- bool XclExpString::IsWriteFlags() const { return mbIsBiff8 && (!IsEmpty() || !mbSmartFlags); } bool XclExpString::IsWriteFormats() const { return mbIsBiff8 && !mbSkipFormats && IsRich(); } void XclExpString::SetStrLen( sal_Int32 nNewLen ) { sal_uInt16 nAllowedLen = (mb8BitLen && (mnMaxLen > 255)) ? 255 : mnMaxLen; mnLen = limit_cast< sal_uInt16 >( nNewLen, 0, nAllowedLen ); } void XclExpString::CharsToBuffer( const sal_Unicode* pcSource, sal_Int32 nBegin, sal_Int32 nLen ) { DBG_ASSERT( maUniBuffer.size() >= static_cast< size_t >( nBegin + nLen ), "XclExpString::CharsToBuffer - char buffer invalid" ); ScfUInt16Vec::iterator aBeg = maUniBuffer.begin() + nBegin; ScfUInt16Vec::iterator aEnd = aBeg + nLen; const sal_Unicode* pcSrcChar = pcSource; for( ScfUInt16Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar ) { *aIt = static_cast< sal_uInt16 >( *pcSrcChar ); if( *aIt & 0xFF00 ) mbIsUnicode = true; } if( !mbWrapped ) mbWrapped = ::std::find( aBeg, aEnd, EXC_LF ) != aEnd; } void XclExpString::CharsToBuffer( const sal_Char* pcSource, sal_Int32 nBegin, sal_Int32 nLen ) { DBG_ASSERT( maCharBuffer.size() >= static_cast< size_t >( nBegin + nLen ), "XclExpString::CharsToBuffer - char buffer invalid" ); ScfUInt8Vec::iterator aBeg = maCharBuffer.begin() + nBegin; ScfUInt8Vec::iterator aEnd = aBeg + nLen; const sal_Char* pcSrcChar = pcSource; for( ScfUInt8Vec::iterator aIt = aBeg; aIt != aEnd; ++aIt, ++pcSrcChar ) *aIt = static_cast< sal_uInt8 >( *pcSrcChar ); mbIsUnicode = false; if( !mbWrapped ) mbWrapped = ::std::find( aBeg, aEnd, EXC_LF_C ) != aEnd; } void XclExpString::Init( sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen, bool bBiff8 ) { mbIsBiff8 = bBiff8; mbIsUnicode = bBiff8 && ::get_flag( nFlags, EXC_STR_FORCEUNICODE ); mb8BitLen = ::get_flag( nFlags, EXC_STR_8BITLENGTH ); mbSmartFlags = bBiff8 && ::get_flag( nFlags, EXC_STR_SMARTFLAGS ); mbSkipFormats = ::get_flag( nFlags, EXC_STR_SEPARATEFORMATS ); mbWrapped = false; mbSkipHeader = ::get_flag( nFlags, EXC_STR_NOHEADER ); mnMaxLen = nMaxLen; SetStrLen( nCurrLen ); maFormats.clear(); if( mbIsBiff8 ) { maCharBuffer.clear(); maUniBuffer.resize( mnLen ); } else { maUniBuffer.clear(); maCharBuffer.resize( mnLen ); } } void XclExpString::Build( const sal_Unicode* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Init( nCurrLen, nFlags, nMaxLen, true ); CharsToBuffer( pcSource, 0, mnLen ); } void XclExpString::Build( const sal_Char* pcSource, sal_Int32 nCurrLen, XclStrFlags nFlags, sal_uInt16 nMaxLen ) { Init( nCurrLen, nFlags, nMaxLen, false ); CharsToBuffer( pcSource, 0, mnLen ); } void XclExpString::InitAppend( sal_Int32 nAddLen ) { SetStrLen( static_cast< sal_Int32 >( mnLen ) + nAddLen ); if( mbIsBiff8 ) maUniBuffer.resize( mnLen ); else maCharBuffer.resize( mnLen ); } void XclExpString::BuildAppend( const sal_Unicode* pcSource, sal_Int32 nAddLen ) { DBG_ASSERT( mbIsBiff8, "XclExpString::BuildAppend - must not be called at byte strings" ); if( mbIsBiff8 ) { sal_uInt16 nOldLen = mnLen; InitAppend( nAddLen ); CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen ); } } void XclExpString::BuildAppend( const sal_Char* pcSource, sal_Int32 nAddLen ) { DBG_ASSERT( !mbIsBiff8, "XclExpString::BuildAppend - must not be called at unicode strings" ); if( !mbIsBiff8 ) { sal_uInt16 nOldLen = mnLen; InitAppend( nAddLen ); CharsToBuffer( pcSource, nOldLen, mnLen - nOldLen ); } } void XclExpString::PrepareWrite( XclExpStream& rStrm, sal_uInt16 nBytes ) const { rStrm.SetSliceSize( nBytes + (mbIsUnicode ? 2 : 1) ); } // ============================================================================