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