blob: 011b8d38062c6f8aaa0aaef63b136bb76979d5c4 [file] [log] [blame]
/**************************************************************
*
* 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.
*
*************************************************************/
#include "precompiled_sc.hxx"
#include "xistring.hxx"
#include "xlstyle.hxx"
#include "xistream.hxx"
#include "xiroot.hxx"
// Byte/Unicode strings =======================================================
/** All allowed flags for import. */
const XclStrFlags nAllowedFlags = EXC_STR_8BITLENGTH | EXC_STR_SMARTFLAGS | EXC_STR_SEPARATEFORMATS;
// ----------------------------------------------------------------------------
XclImpString::XclImpString()
{
}
XclImpString::XclImpString( const String& rString ) :
maString( rString )
{
}
XclImpString::~XclImpString()
{
}
void XclImpString::Read( XclImpStream& rStrm, XclStrFlags nFlags )
{
if( !::get_flag( nFlags, EXC_STR_SEPARATEFORMATS ) )
maFormats.clear();
DBG_ASSERT( (nFlags & ~nAllowedFlags) == 0, "XclImpString::Read - unknown flag" );
bool b16BitLen = !::get_flag( nFlags, EXC_STR_8BITLENGTH );
switch( rStrm.GetRoot().GetBiff() )
{
case EXC_BIFF2:
case EXC_BIFF3:
case EXC_BIFF4:
case EXC_BIFF5:
// no integrated formatting in BIFF2-BIFF7
maString = rStrm.ReadByteString( b16BitLen );
break;
case EXC_BIFF8:
{
// --- string header ---
sal_uInt16 nChars = b16BitLen ? rStrm.ReaduInt16() : rStrm.ReaduInt8();
sal_uInt8 nFlagField = 0;
if( nChars || !::get_flag( nFlags, EXC_STR_SMARTFLAGS ) )
rStrm >> nFlagField;
bool b16Bit, bRich, bFarEast;
sal_uInt16 nRunCount;
sal_uInt32 nExtInf;
rStrm.ReadUniStringExtHeader( b16Bit, bRich, bFarEast, nRunCount, nExtInf, nFlagField );
// #122185# ignore the flags, they may be wrong
// --- character array ---
maString = rStrm.ReadRawUniString( nChars, b16Bit );
// --- formatting ---
if( nRunCount > 0 )
ReadFormats( rStrm, nRunCount );
// --- extended (FarEast) information ---
rStrm.Ignore( nExtInf );
}
break;
default:
DBG_ERROR_BIFF();
}
}
void XclImpString::AppendFormat( XclFormatRunVec& rFormats, sal_uInt16 nChar, sal_uInt16 nFontIdx )
{
// #i33341# real life -- same character index may occur several times
DBG_ASSERT( rFormats.empty() || (rFormats.back().mnChar <= nChar), "XclImpString::AppendFormat - wrong char order" );
if( rFormats.empty() || (rFormats.back().mnChar < nChar) )
rFormats.push_back( XclFormatRun( nChar, nFontIdx ) );
else
rFormats.back().mnFontIdx = nFontIdx;
}
void XclImpString::ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats )
{
bool bBiff8 = rStrm.GetRoot().GetBiff() == EXC_BIFF8;
sal_uInt16 nRunCount = bBiff8 ? rStrm.ReaduInt16() : rStrm.ReaduInt8();
ReadFormats( rStrm, rFormats, nRunCount );
}
void XclImpString::ReadFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nRunCount )
{
rFormats.clear();
rFormats.reserve( nRunCount );
/* #i33341# real life -- same character index may occur several times
-> use AppendFormat() to validate formats */
if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 )
{
for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
{
sal_uInt16 nChar, nFontIdx;
rStrm >> nChar >> nFontIdx;
AppendFormat( rFormats, nChar, nFontIdx );
}
}
else
{
for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
{
sal_uInt8 nChar, nFontIdx;
rStrm >> nChar >> nFontIdx;
AppendFormat( rFormats, nChar, nFontIdx );
}
}
}
void XclImpString::ReadObjFormats( XclImpStream& rStrm, XclFormatRunVec& rFormats, sal_uInt16 nFormatSize )
{
// number of formatting runs, each takes 8 bytes
sal_uInt16 nRunCount = nFormatSize / 8;
rFormats.clear();
rFormats.reserve( nRunCount );
for( sal_uInt16 nIdx = 0; nIdx < nRunCount; ++nIdx )
{
sal_uInt16 nChar, nFontIdx;
rStrm >> nChar >> nFontIdx;
rStrm.Ignore( 4 );
AppendFormat( rFormats, nChar, nFontIdx );
}
}
// String iterator ============================================================
XclImpStringIterator::XclImpStringIterator( const XclImpString& rString ) :
mrText( rString.GetText() ),
mrFormats( rString.GetFormats() ),
mnPortion( 0 ),
mnTextBeg( 0 ),
mnTextEnd( 0 ),
mnFormatsBeg( 0 ),
mnFormatsEnd( 0 )
{
// first portion is formatted, adjust vector index to next portion
if( !mrFormats.empty() && (mrFormats.front().mnChar == 0) )
++mnFormatsEnd;
// find end position of the first portion
mnTextEnd = static_cast< xub_StrLen >( (mnFormatsEnd < mrFormats.size()) ?
mrFormats[ mnFormatsEnd ].mnChar : mrText.Len() );
}
String XclImpStringIterator::GetPortionText() const
{
return String( mrText, mnTextBeg, mnTextEnd - mnTextBeg );
}
sal_uInt16 XclImpStringIterator::GetPortionFont() const
{
return (mnFormatsBeg < mnFormatsEnd) ? mrFormats[ mnFormatsBeg ].mnFontIdx : EXC_FONT_NOTFOUND;
}
XclImpStringIterator& XclImpStringIterator::operator++()
{
if( Is() )
{
++mnPortion;
do
{
// indexes into vector of formatting runs
if( mnFormatsBeg < mnFormatsEnd )
++mnFormatsBeg;
if( mnFormatsEnd < mrFormats.size() )
++mnFormatsEnd;
// character positions of next portion
mnTextBeg = mnTextEnd;
mnTextEnd = static_cast< xub_StrLen >( (mnFormatsEnd < mrFormats.size()) ?
mrFormats[ mnFormatsEnd ].mnChar : mrText.Len() );
}
while( Is() && (mnTextBeg == mnTextEnd) );
}
return *this;
}
// ============================================================================