1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #include "oox/xls/richstring.hxx" 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir #include <com/sun/star/text/XText.hpp> 31*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 32*cdf0e10cSrcweir #include "oox/helper/attributelist.hxx" 33*cdf0e10cSrcweir #include "oox/helper/propertyset.hxx" 34*cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx" 35*cdf0e10cSrcweir 36*cdf0e10cSrcweir namespace oox { 37*cdf0e10cSrcweir namespace xls { 38*cdf0e10cSrcweir 39*cdf0e10cSrcweir // ============================================================================ 40*cdf0e10cSrcweir 41*cdf0e10cSrcweir using namespace ::com::sun::star::text; 42*cdf0e10cSrcweir using namespace ::com::sun::star::uno; 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir using ::rtl::OString; 45*cdf0e10cSrcweir using ::rtl::OUString; 46*cdf0e10cSrcweir using ::rtl::OUStringBuffer; 47*cdf0e10cSrcweir 48*cdf0e10cSrcweir // ============================================================================ 49*cdf0e10cSrcweir 50*cdf0e10cSrcweir namespace { 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir const sal_uInt8 BIFF12_STRINGFLAG_FONTS = 0x01; 53*cdf0e10cSrcweir const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS = 0x02; 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir inline bool lclNeedsRichTextFormat( const Font* pFont ) 56*cdf0e10cSrcweir { 57*cdf0e10cSrcweir return pFont && pFont->needsRichTextFormat(); 58*cdf0e10cSrcweir } 59*cdf0e10cSrcweir 60*cdf0e10cSrcweir } // namespace 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir // ============================================================================ 63*cdf0e10cSrcweir 64*cdf0e10cSrcweir RichStringPortion::RichStringPortion( const WorkbookHelper& rHelper ) : 65*cdf0e10cSrcweir WorkbookHelper( rHelper ), 66*cdf0e10cSrcweir mnFontId( -1 ) 67*cdf0e10cSrcweir { 68*cdf0e10cSrcweir } 69*cdf0e10cSrcweir 70*cdf0e10cSrcweir void RichStringPortion::setText( const OUString& rText ) 71*cdf0e10cSrcweir { 72*cdf0e10cSrcweir maText = rText; 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir FontRef RichStringPortion::createFont() 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir mxFont.reset( new Font( *this, false ) ); 78*cdf0e10cSrcweir return mxFont; 79*cdf0e10cSrcweir } 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir void RichStringPortion::setFontId( sal_Int32 nFontId ) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir mnFontId = nFontId; 84*cdf0e10cSrcweir } 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir void RichStringPortion::finalizeImport() 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir if( mxFont.get() ) 89*cdf0e10cSrcweir mxFont->finalizeImport(); 90*cdf0e10cSrcweir else if( mnFontId >= 0 ) 91*cdf0e10cSrcweir mxFont = getStyles().getFont( mnFontId ); 92*cdf0e10cSrcweir } 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir void RichStringPortion::convert( const Reference< XText >& rxText, const Font* pFont, bool bReplace ) 95*cdf0e10cSrcweir { 96*cdf0e10cSrcweir Reference< XTextRange > xRange; 97*cdf0e10cSrcweir if( bReplace ) 98*cdf0e10cSrcweir xRange.set( rxText, UNO_QUERY ); 99*cdf0e10cSrcweir else 100*cdf0e10cSrcweir xRange = rxText->getEnd(); 101*cdf0e10cSrcweir OSL_ENSURE( xRange.is(), "RichStringPortion::convert - cannot get text range interface" ); 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir if( xRange.is() ) 104*cdf0e10cSrcweir { 105*cdf0e10cSrcweir xRange->setString( maText ); 106*cdf0e10cSrcweir if( mxFont.get() ) 107*cdf0e10cSrcweir { 108*cdf0e10cSrcweir PropertySet aPropSet( xRange ); 109*cdf0e10cSrcweir mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); 110*cdf0e10cSrcweir } 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir /* Some font attributes cannot be set to cell formattiing in Calc but 113*cdf0e10cSrcweir require to use rich formatting, e.g. font escapement. */ 114*cdf0e10cSrcweir if( lclNeedsRichTextFormat( pFont ) ) 115*cdf0e10cSrcweir { 116*cdf0e10cSrcweir PropertySet aPropSet( xRange ); 117*cdf0e10cSrcweir pFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT ); 118*cdf0e10cSrcweir } 119*cdf0e10cSrcweir } 120*cdf0e10cSrcweir } 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 123*cdf0e10cSrcweir 124*cdf0e10cSrcweir void FontPortionModel::read( SequenceInputStream& rStrm ) 125*cdf0e10cSrcweir { 126*cdf0e10cSrcweir mnPos = rStrm.readuInt16(); 127*cdf0e10cSrcweir mnFontId = rStrm.readuInt16(); 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir void FontPortionModel::read( BiffInputStream& rStrm, BiffFontPortionMode eMode ) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir switch( eMode ) 133*cdf0e10cSrcweir { 134*cdf0e10cSrcweir case BIFF_FONTPORTION_8BIT: 135*cdf0e10cSrcweir mnPos = rStrm.readuInt8(); 136*cdf0e10cSrcweir mnFontId = rStrm.readuInt8(); 137*cdf0e10cSrcweir break; 138*cdf0e10cSrcweir case BIFF_FONTPORTION_16BIT: 139*cdf0e10cSrcweir mnPos = rStrm.readuInt16(); 140*cdf0e10cSrcweir mnFontId = rStrm.readuInt16(); 141*cdf0e10cSrcweir break; 142*cdf0e10cSrcweir case BIFF_FONTPORTION_OBJ: 143*cdf0e10cSrcweir mnPos = rStrm.readuInt16(); 144*cdf0e10cSrcweir mnFontId = rStrm.readuInt16(); 145*cdf0e10cSrcweir rStrm.skip( 4 ); 146*cdf0e10cSrcweir break; 147*cdf0e10cSrcweir } 148*cdf0e10cSrcweir } 149*cdf0e10cSrcweir 150*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir void FontPortionModelList::appendPortion( const FontPortionModel& rPortion ) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir // #i33341# real life -- same character index may occur several times 155*cdf0e10cSrcweir OSL_ENSURE( empty() || (back().mnPos <= rPortion.mnPos), "FontPortionModelList::appendPortion - wrong char order" ); 156*cdf0e10cSrcweir if( empty() || (back().mnPos < rPortion.mnPos) ) 157*cdf0e10cSrcweir push_back( rPortion ); 158*cdf0e10cSrcweir else 159*cdf0e10cSrcweir back().mnFontId = rPortion.mnFontId; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir 162*cdf0e10cSrcweir void FontPortionModelList::importPortions( SequenceInputStream& rStrm ) 163*cdf0e10cSrcweir { 164*cdf0e10cSrcweir sal_Int32 nCount = rStrm.readInt32(); 165*cdf0e10cSrcweir clear(); 166*cdf0e10cSrcweir if( nCount > 0 ) 167*cdf0e10cSrcweir { 168*cdf0e10cSrcweir reserve( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 4 ) ); 169*cdf0e10cSrcweir /* #i33341# real life -- same character index may occur several times 170*cdf0e10cSrcweir -> use appendPortion() to validate string position. */ 171*cdf0e10cSrcweir FontPortionModel aPortion; 172*cdf0e10cSrcweir for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) 173*cdf0e10cSrcweir { 174*cdf0e10cSrcweir aPortion.read( rStrm ); 175*cdf0e10cSrcweir appendPortion( aPortion ); 176*cdf0e10cSrcweir } 177*cdf0e10cSrcweir } 178*cdf0e10cSrcweir } 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir void FontPortionModelList::importPortions( BiffInputStream& rStrm, sal_uInt16 nCount, BiffFontPortionMode eMode ) 181*cdf0e10cSrcweir { 182*cdf0e10cSrcweir clear(); 183*cdf0e10cSrcweir reserve( nCount ); 184*cdf0e10cSrcweir /* #i33341# real life -- same character index may occur several times 185*cdf0e10cSrcweir -> use appendPortion() to validate string position. */ 186*cdf0e10cSrcweir FontPortionModel aPortion; 187*cdf0e10cSrcweir for( sal_uInt16 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) 188*cdf0e10cSrcweir { 189*cdf0e10cSrcweir aPortion.read( rStrm, eMode ); 190*cdf0e10cSrcweir appendPortion( aPortion ); 191*cdf0e10cSrcweir } 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir void FontPortionModelList::importPortions( BiffInputStream& rStrm, bool b16Bit ) 195*cdf0e10cSrcweir { 196*cdf0e10cSrcweir sal_uInt16 nCount = b16Bit ? rStrm.readuInt16() : rStrm.readuInt8(); 197*cdf0e10cSrcweir importPortions( rStrm, nCount, b16Bit ? BIFF_FONTPORTION_16BIT : BIFF_FONTPORTION_8BIT ); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir // ============================================================================ 201*cdf0e10cSrcweir 202*cdf0e10cSrcweir PhoneticDataModel::PhoneticDataModel() : 203*cdf0e10cSrcweir mnFontId( -1 ), 204*cdf0e10cSrcweir mnType( XML_fullwidthKatakana ), 205*cdf0e10cSrcweir mnAlignment( XML_left ) 206*cdf0e10cSrcweir { 207*cdf0e10cSrcweir } 208*cdf0e10cSrcweir 209*cdf0e10cSrcweir void PhoneticDataModel::setBiffData( sal_Int32 nType, sal_Int32 nAlignment ) 210*cdf0e10cSrcweir { 211*cdf0e10cSrcweir static const sal_Int32 spnTypeIds[] = { XML_halfwidthKatakana, XML_fullwidthKatakana, XML_hiragana, XML_noConversion }; 212*cdf0e10cSrcweir mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_fullwidthKatakana ); 213*cdf0e10cSrcweir 214*cdf0e10cSrcweir static const sal_Int32 spnAlignments[] = { XML_noControl, XML_left, XML_center, XML_distributed }; 215*cdf0e10cSrcweir mnAlignment = STATIC_ARRAY_SELECT( spnAlignments, nAlignment, XML_left ); 216*cdf0e10cSrcweir } 217*cdf0e10cSrcweir 218*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 219*cdf0e10cSrcweir 220*cdf0e10cSrcweir PhoneticSettings::PhoneticSettings( const WorkbookHelper& rHelper ) : 221*cdf0e10cSrcweir WorkbookHelper( rHelper ) 222*cdf0e10cSrcweir { 223*cdf0e10cSrcweir } 224*cdf0e10cSrcweir 225*cdf0e10cSrcweir void PhoneticSettings::importPhoneticPr( const AttributeList& rAttribs ) 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir maModel.mnFontId = rAttribs.getInteger( XML_fontId, -1 ); 228*cdf0e10cSrcweir maModel.mnType = rAttribs.getToken( XML_type, XML_fullwidthKatakana ); 229*cdf0e10cSrcweir maModel.mnAlignment = rAttribs.getToken( XML_alignment, XML_left ); 230*cdf0e10cSrcweir } 231*cdf0e10cSrcweir 232*cdf0e10cSrcweir void PhoneticSettings::importPhoneticPr( SequenceInputStream& rStrm ) 233*cdf0e10cSrcweir { 234*cdf0e10cSrcweir sal_uInt16 nFontId; 235*cdf0e10cSrcweir sal_Int32 nType, nAlignment; 236*cdf0e10cSrcweir rStrm >> nFontId >> nType >> nAlignment; 237*cdf0e10cSrcweir maModel.mnFontId = nFontId; 238*cdf0e10cSrcweir maModel.setBiffData( nType, nAlignment ); 239*cdf0e10cSrcweir } 240*cdf0e10cSrcweir 241*cdf0e10cSrcweir void PhoneticSettings::importPhoneticPr( BiffInputStream& rStrm ) 242*cdf0e10cSrcweir { 243*cdf0e10cSrcweir sal_uInt16 nFontId, nFlags; 244*cdf0e10cSrcweir rStrm >> nFontId >> nFlags; 245*cdf0e10cSrcweir maModel.mnFontId = nFontId; 246*cdf0e10cSrcweir maModel.setBiffData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); 247*cdf0e10cSrcweir // following: range list with cells showing phonetic text 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir 250*cdf0e10cSrcweir void PhoneticSettings::importStringData( SequenceInputStream& rStrm ) 251*cdf0e10cSrcweir { 252*cdf0e10cSrcweir sal_uInt16 nFontId, nFlags; 253*cdf0e10cSrcweir rStrm >> nFontId >> nFlags; 254*cdf0e10cSrcweir maModel.mnFontId = nFontId; 255*cdf0e10cSrcweir maModel.setBiffData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); 256*cdf0e10cSrcweir } 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir void PhoneticSettings::importStringData( BiffInputStream& rStrm ) 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir sal_uInt16 nFontId, nFlags; 261*cdf0e10cSrcweir rStrm >> nFontId >> nFlags; 262*cdf0e10cSrcweir maModel.mnFontId = nFontId; 263*cdf0e10cSrcweir maModel.setBiffData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) ); 264*cdf0e10cSrcweir } 265*cdf0e10cSrcweir 266*cdf0e10cSrcweir // ============================================================================ 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir RichStringPhonetic::RichStringPhonetic( const WorkbookHelper& rHelper ) : 269*cdf0e10cSrcweir WorkbookHelper( rHelper ), 270*cdf0e10cSrcweir mnBasePos( -1 ), 271*cdf0e10cSrcweir mnBaseEnd( -1 ) 272*cdf0e10cSrcweir { 273*cdf0e10cSrcweir } 274*cdf0e10cSrcweir 275*cdf0e10cSrcweir void RichStringPhonetic::setText( const OUString& rText ) 276*cdf0e10cSrcweir { 277*cdf0e10cSrcweir maText = rText; 278*cdf0e10cSrcweir } 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir void RichStringPhonetic::importPhoneticRun( const AttributeList& rAttribs ) 281*cdf0e10cSrcweir { 282*cdf0e10cSrcweir mnBasePos = rAttribs.getInteger( XML_sb, -1 ); 283*cdf0e10cSrcweir mnBaseEnd = rAttribs.getInteger( XML_eb, -1 ); 284*cdf0e10cSrcweir } 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir void RichStringPhonetic::setBaseRange( sal_Int32 nBasePos, sal_Int32 nBaseEnd ) 287*cdf0e10cSrcweir { 288*cdf0e10cSrcweir mnBasePos = nBasePos; 289*cdf0e10cSrcweir mnBaseEnd = nBaseEnd; 290*cdf0e10cSrcweir } 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 293*cdf0e10cSrcweir 294*cdf0e10cSrcweir void PhoneticPortionModel::read( SequenceInputStream& rStrm ) 295*cdf0e10cSrcweir { 296*cdf0e10cSrcweir mnPos = rStrm.readuInt16(); 297*cdf0e10cSrcweir mnBasePos = rStrm.readuInt16(); 298*cdf0e10cSrcweir mnBaseLen = rStrm.readuInt16(); 299*cdf0e10cSrcweir } 300*cdf0e10cSrcweir 301*cdf0e10cSrcweir void PhoneticPortionModel::read( BiffInputStream& rStrm ) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir mnPos = rStrm.readuInt16(); 304*cdf0e10cSrcweir mnBasePos = rStrm.readuInt16(); 305*cdf0e10cSrcweir mnBaseLen = rStrm.readuInt16(); 306*cdf0e10cSrcweir } 307*cdf0e10cSrcweir 308*cdf0e10cSrcweir // ---------------------------------------------------------------------------- 309*cdf0e10cSrcweir 310*cdf0e10cSrcweir void PhoneticPortionModelList::appendPortion( const PhoneticPortionModel& rPortion ) 311*cdf0e10cSrcweir { 312*cdf0e10cSrcweir // same character index may occur several times 313*cdf0e10cSrcweir OSL_ENSURE( empty() || ((back().mnPos <= rPortion.mnPos) && 314*cdf0e10cSrcweir (back().mnBasePos + back().mnBaseLen <= rPortion.mnBasePos)), 315*cdf0e10cSrcweir "PhoneticPortionModelList::appendPortion - wrong char order" ); 316*cdf0e10cSrcweir if( empty() || (back().mnPos < rPortion.mnPos) ) 317*cdf0e10cSrcweir { 318*cdf0e10cSrcweir push_back( rPortion ); 319*cdf0e10cSrcweir } 320*cdf0e10cSrcweir else if( back().mnPos == rPortion.mnPos ) 321*cdf0e10cSrcweir { 322*cdf0e10cSrcweir back().mnBasePos = rPortion.mnBasePos; 323*cdf0e10cSrcweir back().mnBaseLen = rPortion.mnBaseLen; 324*cdf0e10cSrcweir } 325*cdf0e10cSrcweir } 326*cdf0e10cSrcweir 327*cdf0e10cSrcweir void PhoneticPortionModelList::importPortions( SequenceInputStream& rStrm ) 328*cdf0e10cSrcweir { 329*cdf0e10cSrcweir sal_Int32 nCount = rStrm.readInt32(); 330*cdf0e10cSrcweir clear(); 331*cdf0e10cSrcweir if( nCount > 0 ) 332*cdf0e10cSrcweir { 333*cdf0e10cSrcweir reserve( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 6 ) ); 334*cdf0e10cSrcweir PhoneticPortionModel aPortion; 335*cdf0e10cSrcweir for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex ) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir aPortion.read( rStrm ); 338*cdf0e10cSrcweir appendPortion( aPortion ); 339*cdf0e10cSrcweir } 340*cdf0e10cSrcweir } 341*cdf0e10cSrcweir } 342*cdf0e10cSrcweir 343*cdf0e10cSrcweir OUString PhoneticPortionModelList::importPortions( BiffInputStream& rStrm, sal_Int32 nPhoneticSize ) 344*cdf0e10cSrcweir { 345*cdf0e10cSrcweir OUString aPhoneticText; 346*cdf0e10cSrcweir sal_uInt16 nPortionCount, nTextLen1, nTextLen2; 347*cdf0e10cSrcweir rStrm >> nPortionCount >> nTextLen1 >> nTextLen2; 348*cdf0e10cSrcweir OSL_ENSURE( nTextLen1 == nTextLen2, "PhoneticPortionModelList::importPortions - wrong phonetic text length" ); 349*cdf0e10cSrcweir if( (nTextLen1 == nTextLen2) && (nTextLen1 > 0) ) 350*cdf0e10cSrcweir { 351*cdf0e10cSrcweir sal_Int32 nMinSize = 2 * nTextLen1 + 6 * nPortionCount + 14; 352*cdf0e10cSrcweir OSL_ENSURE( nMinSize <= nPhoneticSize, "PhoneticPortionModelList::importPortions - wrong size of phonetic data" ); 353*cdf0e10cSrcweir if( nMinSize <= nPhoneticSize ) 354*cdf0e10cSrcweir { 355*cdf0e10cSrcweir aPhoneticText = rStrm.readUnicodeArray( nTextLen1 ); 356*cdf0e10cSrcweir clear(); 357*cdf0e10cSrcweir reserve( nPortionCount ); 358*cdf0e10cSrcweir PhoneticPortionModel aPortion; 359*cdf0e10cSrcweir for( sal_uInt16 nPortion = 0; nPortion < nPortionCount; ++nPortion ) 360*cdf0e10cSrcweir { 361*cdf0e10cSrcweir aPortion.read( rStrm ); 362*cdf0e10cSrcweir appendPortion( aPortion ); 363*cdf0e10cSrcweir } 364*cdf0e10cSrcweir } 365*cdf0e10cSrcweir } 366*cdf0e10cSrcweir return aPhoneticText; 367*cdf0e10cSrcweir } 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir // ============================================================================ 370*cdf0e10cSrcweir 371*cdf0e10cSrcweir RichString::RichString( const WorkbookHelper& rHelper ) : 372*cdf0e10cSrcweir WorkbookHelper( rHelper ), 373*cdf0e10cSrcweir maPhonSettings( rHelper ) 374*cdf0e10cSrcweir { 375*cdf0e10cSrcweir } 376*cdf0e10cSrcweir 377*cdf0e10cSrcweir RichStringPortionRef RichString::importText( const AttributeList& ) 378*cdf0e10cSrcweir { 379*cdf0e10cSrcweir return createPortion(); 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir RichStringPortionRef RichString::importRun( const AttributeList& ) 383*cdf0e10cSrcweir { 384*cdf0e10cSrcweir return createPortion(); 385*cdf0e10cSrcweir } 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir RichStringPhoneticRef RichString::importPhoneticRun( const AttributeList& rAttribs ) 388*cdf0e10cSrcweir { 389*cdf0e10cSrcweir RichStringPhoneticRef xPhonetic = createPhonetic(); 390*cdf0e10cSrcweir xPhonetic->importPhoneticRun( rAttribs ); 391*cdf0e10cSrcweir return xPhonetic; 392*cdf0e10cSrcweir } 393*cdf0e10cSrcweir 394*cdf0e10cSrcweir void RichString::importPhoneticPr( const AttributeList& rAttribs ) 395*cdf0e10cSrcweir { 396*cdf0e10cSrcweir maPhonSettings.importPhoneticPr( rAttribs ); 397*cdf0e10cSrcweir } 398*cdf0e10cSrcweir 399*cdf0e10cSrcweir void RichString::importString( SequenceInputStream& rStrm, bool bRich ) 400*cdf0e10cSrcweir { 401*cdf0e10cSrcweir sal_uInt8 nFlags = bRich ? rStrm.readuInt8() : 0; 402*cdf0e10cSrcweir OUString aBaseText = BiffHelper::readString( rStrm ); 403*cdf0e10cSrcweir 404*cdf0e10cSrcweir if( !rStrm.isEof() && getFlag( nFlags, BIFF12_STRINGFLAG_FONTS ) ) 405*cdf0e10cSrcweir { 406*cdf0e10cSrcweir FontPortionModelList aPortions; 407*cdf0e10cSrcweir aPortions.importPortions( rStrm ); 408*cdf0e10cSrcweir createTextPortions( aBaseText, aPortions ); 409*cdf0e10cSrcweir } 410*cdf0e10cSrcweir else 411*cdf0e10cSrcweir { 412*cdf0e10cSrcweir createPortion()->setText( aBaseText ); 413*cdf0e10cSrcweir } 414*cdf0e10cSrcweir 415*cdf0e10cSrcweir if( !rStrm.isEof() && getFlag( nFlags, BIFF12_STRINGFLAG_PHONETICS ) ) 416*cdf0e10cSrcweir { 417*cdf0e10cSrcweir OUString aPhoneticText = BiffHelper::readString( rStrm ); 418*cdf0e10cSrcweir PhoneticPortionModelList aPortions; 419*cdf0e10cSrcweir aPortions.importPortions( rStrm ); 420*cdf0e10cSrcweir maPhonSettings.importStringData( rStrm ); 421*cdf0e10cSrcweir createPhoneticPortions( aPhoneticText, aPortions, aBaseText.getLength() ); 422*cdf0e10cSrcweir } 423*cdf0e10cSrcweir } 424*cdf0e10cSrcweir 425*cdf0e10cSrcweir void RichString::importCharArray( BiffInputStream& rStrm, sal_uInt16 nChars, rtl_TextEncoding eTextEnc ) 426*cdf0e10cSrcweir { 427*cdf0e10cSrcweir createPortion()->setText( rStrm.readCharArrayUC( nChars, eTextEnc ) ); 428*cdf0e10cSrcweir } 429*cdf0e10cSrcweir 430*cdf0e10cSrcweir void RichString::importByteString( BiffInputStream& rStrm, rtl_TextEncoding eTextEnc, BiffStringFlags nFlags ) 431*cdf0e10cSrcweir { 432*cdf0e10cSrcweir OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importString - keep fonts not implemented" ); 433*cdf0e10cSrcweir OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_EXTRAFONTS) ) ), "RichString::importByteString - unknown flag" ); 434*cdf0e10cSrcweir bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); 435*cdf0e10cSrcweir 436*cdf0e10cSrcweir OString aBaseText = rStrm.readByteString( !b8BitLength ); 437*cdf0e10cSrcweir 438*cdf0e10cSrcweir if( !rStrm.isEof() && getFlag( nFlags, BIFF_STR_EXTRAFONTS ) ) 439*cdf0e10cSrcweir { 440*cdf0e10cSrcweir FontPortionModelList aPortions; 441*cdf0e10cSrcweir aPortions.importPortions( rStrm, false ); 442*cdf0e10cSrcweir createTextPortions( aBaseText, eTextEnc, aPortions ); 443*cdf0e10cSrcweir } 444*cdf0e10cSrcweir else 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir createPortion()->setText( OStringToOUString( aBaseText, eTextEnc ) ); 447*cdf0e10cSrcweir } 448*cdf0e10cSrcweir } 449*cdf0e10cSrcweir 450*cdf0e10cSrcweir void RichString::importUniString( BiffInputStream& rStrm, BiffStringFlags nFlags ) 451*cdf0e10cSrcweir { 452*cdf0e10cSrcweir OSL_ENSURE( !getFlag( nFlags, BIFF_STR_KEEPFONTS ), "RichString::importUniString - keep fonts not implemented" ); 453*cdf0e10cSrcweir OSL_ENSURE( !getFlag( nFlags, static_cast< BiffStringFlags >( ~(BIFF_STR_8BITLENGTH | BIFF_STR_SMARTFLAGS) ) ), "RichString::importUniString - unknown flag" ); 454*cdf0e10cSrcweir bool b8BitLength = getFlag( nFlags, BIFF_STR_8BITLENGTH ); 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir // --- string header --- 457*cdf0e10cSrcweir sal_uInt16 nChars = b8BitLength ? rStrm.readuInt8() : rStrm.readuInt16(); 458*cdf0e10cSrcweir sal_uInt8 nFlagField = 0; 459*cdf0e10cSrcweir if( (nChars > 0) || !getFlag( nFlags, BIFF_STR_SMARTFLAGS ) ) 460*cdf0e10cSrcweir rStrm >> nFlagField; 461*cdf0e10cSrcweir bool b16Bit = getFlag( nFlagField, BIFF_STRF_16BIT ); 462*cdf0e10cSrcweir bool bFonts = getFlag( nFlagField, BIFF_STRF_RICH ); 463*cdf0e10cSrcweir bool bPhonetic = getFlag( nFlagField, BIFF_STRF_PHONETIC ); 464*cdf0e10cSrcweir sal_uInt16 nFontCount = bFonts ? rStrm.readuInt16() : 0; 465*cdf0e10cSrcweir sal_Int32 nPhoneticSize = bPhonetic ? rStrm.readInt32() : 0; 466*cdf0e10cSrcweir 467*cdf0e10cSrcweir // --- character array --- 468*cdf0e10cSrcweir OUString aBaseText = rStrm.readUniStringChars( nChars, b16Bit ); 469*cdf0e10cSrcweir 470*cdf0e10cSrcweir // --- formatting --- 471*cdf0e10cSrcweir // #122185# bRich flag may be set, but format runs may be missing 472*cdf0e10cSrcweir if( !rStrm.isEof() && (nFontCount > 0) ) 473*cdf0e10cSrcweir { 474*cdf0e10cSrcweir FontPortionModelList aPortions; 475*cdf0e10cSrcweir aPortions.importPortions( rStrm, nFontCount, BIFF_FONTPORTION_16BIT ); 476*cdf0e10cSrcweir createTextPortions( aBaseText, aPortions ); 477*cdf0e10cSrcweir } 478*cdf0e10cSrcweir else 479*cdf0e10cSrcweir { 480*cdf0e10cSrcweir createPortion()->setText( aBaseText ); 481*cdf0e10cSrcweir } 482*cdf0e10cSrcweir 483*cdf0e10cSrcweir // --- Asian phonetic information --- 484*cdf0e10cSrcweir // #122185# bPhonetic flag may be set, but phonetic info may be missing 485*cdf0e10cSrcweir if( !rStrm.isEof() && (nPhoneticSize > 0) ) 486*cdf0e10cSrcweir { 487*cdf0e10cSrcweir sal_Int64 nPhoneticEnd = rStrm.tell() + nPhoneticSize; 488*cdf0e10cSrcweir OSL_ENSURE( nPhoneticSize > 14, "RichString::importUniString - wrong size of phonetic data" ); 489*cdf0e10cSrcweir if( nPhoneticSize > 14 ) 490*cdf0e10cSrcweir { 491*cdf0e10cSrcweir sal_uInt16 nId, nSize; 492*cdf0e10cSrcweir rStrm >> nId >> nSize; 493*cdf0e10cSrcweir OSL_ENSURE( nId == 1, "RichString::importUniString - unknown phonetic data identifier" ); 494*cdf0e10cSrcweir sal_Int32 nMinSize = nSize + 4; 495*cdf0e10cSrcweir OSL_ENSURE( nMinSize <= nPhoneticSize, "RichString::importUniString - wrong size of phonetic data" ); 496*cdf0e10cSrcweir if( (nId == 1) && (nMinSize <= nPhoneticSize) ) 497*cdf0e10cSrcweir { 498*cdf0e10cSrcweir maPhonSettings.importStringData( rStrm ); 499*cdf0e10cSrcweir PhoneticPortionModelList aPortions; 500*cdf0e10cSrcweir OUString aPhoneticText = aPortions.importPortions( rStrm, nPhoneticSize ); 501*cdf0e10cSrcweir createPhoneticPortions( aPhoneticText, aPortions, aBaseText.getLength() ); 502*cdf0e10cSrcweir } 503*cdf0e10cSrcweir } 504*cdf0e10cSrcweir rStrm.seek( nPhoneticEnd ); 505*cdf0e10cSrcweir } 506*cdf0e10cSrcweir } 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir void RichString::finalizeImport() 509*cdf0e10cSrcweir { 510*cdf0e10cSrcweir maTextPortions.forEachMem( &RichStringPortion::finalizeImport ); 511*cdf0e10cSrcweir } 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir bool RichString::extractPlainString( OUString& orString, const Font* pFirstPortionFont ) const 514*cdf0e10cSrcweir { 515*cdf0e10cSrcweir if( !maPhonPortions.empty() ) 516*cdf0e10cSrcweir return false; 517*cdf0e10cSrcweir if( maTextPortions.empty() ) 518*cdf0e10cSrcweir { 519*cdf0e10cSrcweir orString = OUString(); 520*cdf0e10cSrcweir return true; 521*cdf0e10cSrcweir } 522*cdf0e10cSrcweir if( (maTextPortions.size() == 1) && !maTextPortions.front()->hasFont() && !lclNeedsRichTextFormat( pFirstPortionFont ) ) 523*cdf0e10cSrcweir { 524*cdf0e10cSrcweir orString = maTextPortions.front()->getText(); 525*cdf0e10cSrcweir return true; 526*cdf0e10cSrcweir } 527*cdf0e10cSrcweir return false; 528*cdf0e10cSrcweir } 529*cdf0e10cSrcweir 530*cdf0e10cSrcweir void RichString::convert( const Reference< XText >& rxText, const Font* pFirstPortionFont ) const 531*cdf0e10cSrcweir { 532*cdf0e10cSrcweir bool bReplace = true; 533*cdf0e10cSrcweir for( PortionVector::const_iterator aIt = maTextPortions.begin(), aEnd = maTextPortions.end(); aIt != aEnd; ++aIt ) 534*cdf0e10cSrcweir { 535*cdf0e10cSrcweir (*aIt)->convert( rxText, pFirstPortionFont, bReplace ); 536*cdf0e10cSrcweir pFirstPortionFont = 0; // use passed font for first portion only 537*cdf0e10cSrcweir bReplace = false; // do not replace first portion text with following portions 538*cdf0e10cSrcweir } 539*cdf0e10cSrcweir } 540*cdf0e10cSrcweir 541*cdf0e10cSrcweir // private -------------------------------------------------------------------- 542*cdf0e10cSrcweir 543*cdf0e10cSrcweir RichStringPortionRef RichString::createPortion() 544*cdf0e10cSrcweir { 545*cdf0e10cSrcweir RichStringPortionRef xPortion( new RichStringPortion( *this ) ); 546*cdf0e10cSrcweir maTextPortions.push_back( xPortion ); 547*cdf0e10cSrcweir return xPortion; 548*cdf0e10cSrcweir } 549*cdf0e10cSrcweir 550*cdf0e10cSrcweir RichStringPhoneticRef RichString::createPhonetic() 551*cdf0e10cSrcweir { 552*cdf0e10cSrcweir RichStringPhoneticRef xPhonetic( new RichStringPhonetic( *this ) ); 553*cdf0e10cSrcweir maPhonPortions.push_back( xPhonetic ); 554*cdf0e10cSrcweir return xPhonetic; 555*cdf0e10cSrcweir } 556*cdf0e10cSrcweir 557*cdf0e10cSrcweir void RichString::createTextPortions( const OString& rText, rtl_TextEncoding eTextEnc, FontPortionModelList& rPortions ) 558*cdf0e10cSrcweir { 559*cdf0e10cSrcweir maTextPortions.clear(); 560*cdf0e10cSrcweir sal_Int32 nStrLen = rText.getLength(); 561*cdf0e10cSrcweir if( nStrLen > 0 ) 562*cdf0e10cSrcweir { 563*cdf0e10cSrcweir // add leading and trailing string position to ease the following loop 564*cdf0e10cSrcweir if( rPortions.empty() || (rPortions.front().mnPos > 0) ) 565*cdf0e10cSrcweir rPortions.insert( rPortions.begin(), FontPortionModel( 0, -1 ) ); 566*cdf0e10cSrcweir if( rPortions.back().mnPos < nStrLen ) 567*cdf0e10cSrcweir rPortions.push_back( FontPortionModel( nStrLen, -1 ) ); 568*cdf0e10cSrcweir 569*cdf0e10cSrcweir // create all string portions according to the font id vector 570*cdf0e10cSrcweir for( FontPortionModelList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; 573*cdf0e10cSrcweir if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) 574*cdf0e10cSrcweir { 575*cdf0e10cSrcweir // convert byte string to unicode string, using current font encoding 576*cdf0e10cSrcweir FontRef xFont = getStyles().getFont( aIt->mnFontId ); 577*cdf0e10cSrcweir rtl_TextEncoding eFontEnc = xFont.get() ? xFont->getFontEncoding() : eTextEnc; 578*cdf0e10cSrcweir OUString aUniStr = OStringToOUString( rText.copy( aIt->mnPos, nPortionLen ), eFontEnc ); 579*cdf0e10cSrcweir // create string portion 580*cdf0e10cSrcweir RichStringPortionRef xPortion = createPortion(); 581*cdf0e10cSrcweir xPortion->setText( aUniStr ); 582*cdf0e10cSrcweir xPortion->setFontId( aIt->mnFontId ); 583*cdf0e10cSrcweir } 584*cdf0e10cSrcweir } 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir } 587*cdf0e10cSrcweir 588*cdf0e10cSrcweir void RichString::createTextPortions( const OUString& rText, FontPortionModelList& rPortions ) 589*cdf0e10cSrcweir { 590*cdf0e10cSrcweir maTextPortions.clear(); 591*cdf0e10cSrcweir sal_Int32 nStrLen = rText.getLength(); 592*cdf0e10cSrcweir if( nStrLen > 0 ) 593*cdf0e10cSrcweir { 594*cdf0e10cSrcweir // add leading and trailing string position to ease the following loop 595*cdf0e10cSrcweir if( rPortions.empty() || (rPortions.front().mnPos > 0) ) 596*cdf0e10cSrcweir rPortions.insert( rPortions.begin(), FontPortionModel( 0, -1 ) ); 597*cdf0e10cSrcweir if( rPortions.back().mnPos < nStrLen ) 598*cdf0e10cSrcweir rPortions.push_back( FontPortionModel( nStrLen, -1 ) ); 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir // create all string portions according to the font id vector 601*cdf0e10cSrcweir for( FontPortionModelList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) 602*cdf0e10cSrcweir { 603*cdf0e10cSrcweir sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; 604*cdf0e10cSrcweir if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) 605*cdf0e10cSrcweir { 606*cdf0e10cSrcweir RichStringPortionRef xPortion = createPortion(); 607*cdf0e10cSrcweir xPortion->setText( rText.copy( aIt->mnPos, nPortionLen ) ); 608*cdf0e10cSrcweir xPortion->setFontId( aIt->mnFontId ); 609*cdf0e10cSrcweir } 610*cdf0e10cSrcweir } 611*cdf0e10cSrcweir } 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir void RichString::createPhoneticPortions( const ::rtl::OUString& rText, PhoneticPortionModelList& rPortions, sal_Int32 nBaseLen ) 615*cdf0e10cSrcweir { 616*cdf0e10cSrcweir maPhonPortions.clear(); 617*cdf0e10cSrcweir sal_Int32 nStrLen = rText.getLength(); 618*cdf0e10cSrcweir if( nStrLen > 0 ) 619*cdf0e10cSrcweir { 620*cdf0e10cSrcweir // no portions - assign phonetic text to entire base text 621*cdf0e10cSrcweir if( rPortions.empty() ) 622*cdf0e10cSrcweir rPortions.push_back( PhoneticPortionModel( 0, 0, nBaseLen ) ); 623*cdf0e10cSrcweir // add trailing string position to ease the following loop 624*cdf0e10cSrcweir if( rPortions.back().mnPos < nStrLen ) 625*cdf0e10cSrcweir rPortions.push_back( PhoneticPortionModel( nStrLen, nBaseLen, 0 ) ); 626*cdf0e10cSrcweir 627*cdf0e10cSrcweir // create all phonetic portions according to the portions vector 628*cdf0e10cSrcweir for( PhoneticPortionModelList::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt ) 629*cdf0e10cSrcweir { 630*cdf0e10cSrcweir sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos; 631*cdf0e10cSrcweir if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) ) 632*cdf0e10cSrcweir { 633*cdf0e10cSrcweir RichStringPhoneticRef xPhonetic = createPhonetic(); 634*cdf0e10cSrcweir xPhonetic->setText( rText.copy( aIt->mnPos, nPortionLen ) ); 635*cdf0e10cSrcweir xPhonetic->setBaseRange( aIt->mnBasePos, aIt->mnBasePos + aIt->mnBaseLen ); 636*cdf0e10cSrcweir } 637*cdf0e10cSrcweir } 638*cdf0e10cSrcweir } 639*cdf0e10cSrcweir } 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir // ============================================================================ 642*cdf0e10cSrcweir 643*cdf0e10cSrcweir } // namespace xls 644*cdf0e10cSrcweir } // namespace oox 645