xref: /aoo42x/main/oox/source/xls/richstring.cxx (revision c0670b14)
1ca5ec200SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3ca5ec200SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4ca5ec200SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5ca5ec200SAndrew Rist  * distributed with this work for additional information
6ca5ec200SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7ca5ec200SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8ca5ec200SAndrew Rist  * "License"); you may not use this file except in compliance
9ca5ec200SAndrew Rist  * with the License.  You may obtain a copy of the License at
10ca5ec200SAndrew Rist  *
11ca5ec200SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12ca5ec200SAndrew Rist  *
13ca5ec200SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14ca5ec200SAndrew Rist  * software distributed under the License is distributed on an
15ca5ec200SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16ca5ec200SAndrew Rist  * KIND, either express or implied.  See the License for the
17ca5ec200SAndrew Rist  * specific language governing permissions and limitations
18ca5ec200SAndrew Rist  * under the License.
19ca5ec200SAndrew Rist  *
20ca5ec200SAndrew Rist  *************************************************************/
21ca5ec200SAndrew Rist 
22cdf0e10cSrcweir #include "oox/xls/richstring.hxx"
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #include <com/sun/star/text/XText.hpp>
25cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
26cdf0e10cSrcweir #include "oox/helper/attributelist.hxx"
27cdf0e10cSrcweir #include "oox/helper/propertyset.hxx"
28cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx"
29cdf0e10cSrcweir 
30cdf0e10cSrcweir namespace oox {
31cdf0e10cSrcweir namespace xls {
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // ============================================================================
34cdf0e10cSrcweir 
35cdf0e10cSrcweir using namespace ::com::sun::star::text;
36cdf0e10cSrcweir using namespace ::com::sun::star::uno;
37cdf0e10cSrcweir 
38cdf0e10cSrcweir using ::rtl::OString;
39cdf0e10cSrcweir using ::rtl::OUString;
40cdf0e10cSrcweir using ::rtl::OUStringBuffer;
41cdf0e10cSrcweir 
42cdf0e10cSrcweir // ============================================================================
43cdf0e10cSrcweir 
44cdf0e10cSrcweir namespace {
45cdf0e10cSrcweir 
46cdf0e10cSrcweir const sal_uInt8 BIFF12_STRINGFLAG_FONTS         = 0x01;
47cdf0e10cSrcweir const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS     = 0x02;
48cdf0e10cSrcweir 
lclNeedsRichTextFormat(const Font * pFont)49cdf0e10cSrcweir inline bool lclNeedsRichTextFormat( const Font* pFont )
50cdf0e10cSrcweir {
51cdf0e10cSrcweir     return pFont && pFont->needsRichTextFormat();
52cdf0e10cSrcweir }
53cdf0e10cSrcweir 
54cdf0e10cSrcweir } // namespace
55cdf0e10cSrcweir 
56cdf0e10cSrcweir // ============================================================================
57cdf0e10cSrcweir 
RichStringPortion(const WorkbookHelper & rHelper)58cdf0e10cSrcweir RichStringPortion::RichStringPortion( const WorkbookHelper& rHelper ) :
59cdf0e10cSrcweir     WorkbookHelper( rHelper ),
60*c0670b14SClarence Guo     mnFontId( -1 ),
61*c0670b14SClarence Guo     mbConverted( false )
62cdf0e10cSrcweir {
63cdf0e10cSrcweir }
64cdf0e10cSrcweir 
setText(const OUString & rText)65cdf0e10cSrcweir void RichStringPortion::setText( const OUString& rText )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir     maText = rText;
68cdf0e10cSrcweir }
69cdf0e10cSrcweir 
createFont()70cdf0e10cSrcweir FontRef RichStringPortion::createFont()
71cdf0e10cSrcweir {
72cdf0e10cSrcweir     mxFont.reset( new Font( *this, false ) );
73cdf0e10cSrcweir     return mxFont;
74cdf0e10cSrcweir }
75cdf0e10cSrcweir 
setFontId(sal_Int32 nFontId)76cdf0e10cSrcweir void RichStringPortion::setFontId( sal_Int32 nFontId )
77cdf0e10cSrcweir {
78cdf0e10cSrcweir     mnFontId = nFontId;
79cdf0e10cSrcweir }
80cdf0e10cSrcweir 
finalizeImport()81cdf0e10cSrcweir void RichStringPortion::finalizeImport()
82cdf0e10cSrcweir {
83cdf0e10cSrcweir     if( mxFont.get() )
84cdf0e10cSrcweir         mxFont->finalizeImport();
85cdf0e10cSrcweir     else if( mnFontId >= 0 )
86cdf0e10cSrcweir         mxFont = getStyles().getFont( mnFontId );
87cdf0e10cSrcweir }
88cdf0e10cSrcweir 
convert(const Reference<XText> & rxText,const Font * pFont,bool bReplace)89cdf0e10cSrcweir void RichStringPortion::convert( const Reference< XText >& rxText, const Font* pFont, bool bReplace )
90cdf0e10cSrcweir {
91*c0670b14SClarence Guo     if ( mbConverted )
92*c0670b14SClarence Guo         return;
93*c0670b14SClarence Guo 
94cdf0e10cSrcweir     Reference< XTextRange > xRange;
95cdf0e10cSrcweir     if( bReplace )
96cdf0e10cSrcweir         xRange.set( rxText, UNO_QUERY );
97cdf0e10cSrcweir     else
98cdf0e10cSrcweir         xRange = rxText->getEnd();
99cdf0e10cSrcweir     OSL_ENSURE( xRange.is(), "RichStringPortion::convert - cannot get text range interface" );
100cdf0e10cSrcweir 
101cdf0e10cSrcweir     if( xRange.is() )
102cdf0e10cSrcweir     {
103cdf0e10cSrcweir         xRange->setString( maText );
104cdf0e10cSrcweir         if( mxFont.get() )
105cdf0e10cSrcweir         {
106cdf0e10cSrcweir             PropertySet aPropSet( xRange );
107cdf0e10cSrcweir             mxFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
108cdf0e10cSrcweir         }
1090dac23a0SMichael Stahl         /*  Some font attributes cannot be set to cell formatting in Calc but
1100dac23a0SMichael Stahl             require to use rich formatting, e.g. font escapement. But do not
1110dac23a0SMichael Stahl             use the passed font if this portion has its own font. */
1120dac23a0SMichael Stahl         else if( lclNeedsRichTextFormat( pFont ) )
113cdf0e10cSrcweir         {
114cdf0e10cSrcweir             PropertySet aPropSet( xRange );
115cdf0e10cSrcweir             pFont->writeToPropertySet( aPropSet, FONT_PROPTYPE_TEXT );
116cdf0e10cSrcweir         }
117cdf0e10cSrcweir     }
118*c0670b14SClarence Guo 
119*c0670b14SClarence Guo     mbConverted = true;
120cdf0e10cSrcweir }
121cdf0e10cSrcweir 
122cdf0e10cSrcweir // ----------------------------------------------------------------------------
123cdf0e10cSrcweir 
read(SequenceInputStream & rStrm)124cdf0e10cSrcweir void FontPortionModel::read( SequenceInputStream& rStrm )
125cdf0e10cSrcweir {
126cdf0e10cSrcweir     mnPos = rStrm.readuInt16();
127cdf0e10cSrcweir     mnFontId = rStrm.readuInt16();
128cdf0e10cSrcweir }
129cdf0e10cSrcweir 
read(BiffInputStream & rStrm,BiffFontPortionMode eMode)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 
appendPortion(const FontPortionModel & rPortion)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 
importPortions(SequenceInputStream & rStrm)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 
importPortions(BiffInputStream & rStrm,sal_uInt16 nCount,BiffFontPortionMode eMode)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 
importPortions(BiffInputStream & rStrm,bool b16Bit)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 
PhoneticDataModel()202cdf0e10cSrcweir PhoneticDataModel::PhoneticDataModel() :
203cdf0e10cSrcweir     mnFontId( -1 ),
204cdf0e10cSrcweir     mnType( XML_fullwidthKatakana ),
205cdf0e10cSrcweir     mnAlignment( XML_left )
206cdf0e10cSrcweir {
207cdf0e10cSrcweir }
208cdf0e10cSrcweir 
setBiffData(sal_Int32 nType,sal_Int32 nAlignment)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 
PhoneticSettings(const WorkbookHelper & rHelper)220cdf0e10cSrcweir PhoneticSettings::PhoneticSettings( const WorkbookHelper& rHelper ) :
221cdf0e10cSrcweir     WorkbookHelper( rHelper )
222cdf0e10cSrcweir {
223cdf0e10cSrcweir }
224cdf0e10cSrcweir 
importPhoneticPr(const AttributeList & rAttribs)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 
importPhoneticPr(SequenceInputStream & rStrm)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 
importPhoneticPr(BiffInputStream & rStrm)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 
importStringData(SequenceInputStream & rStrm)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 
importStringData(BiffInputStream & rStrm)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 
RichStringPhonetic(const WorkbookHelper & rHelper)268cdf0e10cSrcweir RichStringPhonetic::RichStringPhonetic( const WorkbookHelper& rHelper ) :
269cdf0e10cSrcweir     WorkbookHelper( rHelper ),
270cdf0e10cSrcweir     mnBasePos( -1 ),
271cdf0e10cSrcweir     mnBaseEnd( -1 )
272cdf0e10cSrcweir {
273cdf0e10cSrcweir }
274cdf0e10cSrcweir 
setText(const OUString & rText)275cdf0e10cSrcweir void RichStringPhonetic::setText( const OUString& rText )
276cdf0e10cSrcweir {
277cdf0e10cSrcweir     maText = rText;
278cdf0e10cSrcweir }
279cdf0e10cSrcweir 
importPhoneticRun(const AttributeList & rAttribs)280cdf0e10cSrcweir void RichStringPhonetic::importPhoneticRun( const AttributeList& rAttribs )
281cdf0e10cSrcweir {
282cdf0e10cSrcweir     mnBasePos = rAttribs.getInteger( XML_sb, -1 );
283cdf0e10cSrcweir     mnBaseEnd = rAttribs.getInteger( XML_eb, -1 );
284cdf0e10cSrcweir }
285cdf0e10cSrcweir 
setBaseRange(sal_Int32 nBasePos,sal_Int32 nBaseEnd)286cdf0e10cSrcweir void RichStringPhonetic::setBaseRange( sal_Int32 nBasePos, sal_Int32 nBaseEnd )
287cdf0e10cSrcweir {
288cdf0e10cSrcweir     mnBasePos = nBasePos;
289cdf0e10cSrcweir     mnBaseEnd = nBaseEnd;
290cdf0e10cSrcweir }
291cdf0e10cSrcweir 
292cdf0e10cSrcweir // ----------------------------------------------------------------------------
293cdf0e10cSrcweir 
read(SequenceInputStream & rStrm)294cdf0e10cSrcweir void PhoneticPortionModel::read( SequenceInputStream& rStrm )
295cdf0e10cSrcweir {
296cdf0e10cSrcweir     mnPos = rStrm.readuInt16();
297cdf0e10cSrcweir     mnBasePos = rStrm.readuInt16();
298cdf0e10cSrcweir     mnBaseLen = rStrm.readuInt16();
299cdf0e10cSrcweir }
300cdf0e10cSrcweir 
read(BiffInputStream & rStrm)301cdf0e10cSrcweir void PhoneticPortionModel::read( BiffInputStream& rStrm )
302cdf0e10cSrcweir {
303cdf0e10cSrcweir     mnPos = rStrm.readuInt16();
304cdf0e10cSrcweir     mnBasePos = rStrm.readuInt16();
305cdf0e10cSrcweir     mnBaseLen = rStrm.readuInt16();
306cdf0e10cSrcweir }
307cdf0e10cSrcweir 
308cdf0e10cSrcweir // ----------------------------------------------------------------------------
309cdf0e10cSrcweir 
appendPortion(const PhoneticPortionModel & rPortion)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 
importPortions(SequenceInputStream & rStrm)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 
importPortions(BiffInputStream & rStrm,sal_Int32 nPhoneticSize)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 
RichString(const WorkbookHelper & rHelper)371cdf0e10cSrcweir RichString::RichString( const WorkbookHelper& rHelper ) :
372cdf0e10cSrcweir     WorkbookHelper( rHelper ),
373cdf0e10cSrcweir     maPhonSettings( rHelper )
374cdf0e10cSrcweir {
375cdf0e10cSrcweir }
376cdf0e10cSrcweir 
importText(const AttributeList &)377cdf0e10cSrcweir RichStringPortionRef RichString::importText( const AttributeList& )
378cdf0e10cSrcweir {
379cdf0e10cSrcweir     return createPortion();
380cdf0e10cSrcweir }
381cdf0e10cSrcweir 
importRun(const AttributeList &)382cdf0e10cSrcweir RichStringPortionRef RichString::importRun( const AttributeList& )
383cdf0e10cSrcweir {
384cdf0e10cSrcweir     return createPortion();
385cdf0e10cSrcweir }
386cdf0e10cSrcweir 
importPhoneticRun(const AttributeList & rAttribs)387cdf0e10cSrcweir RichStringPhoneticRef RichString::importPhoneticRun( const AttributeList& rAttribs )
388cdf0e10cSrcweir {
389cdf0e10cSrcweir     RichStringPhoneticRef xPhonetic = createPhonetic();
390cdf0e10cSrcweir     xPhonetic->importPhoneticRun( rAttribs );
391cdf0e10cSrcweir     return xPhonetic;
392cdf0e10cSrcweir }
393cdf0e10cSrcweir 
importPhoneticPr(const AttributeList & rAttribs)394cdf0e10cSrcweir void RichString::importPhoneticPr( const AttributeList& rAttribs )
395cdf0e10cSrcweir {
396cdf0e10cSrcweir     maPhonSettings.importPhoneticPr( rAttribs );
397cdf0e10cSrcweir }
398cdf0e10cSrcweir 
importString(SequenceInputStream & rStrm,bool bRich)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 
importCharArray(BiffInputStream & rStrm,sal_uInt16 nChars,rtl_TextEncoding eTextEnc)425cdf0e10cSrcweir void RichString::importCharArray( BiffInputStream& rStrm, sal_uInt16 nChars, rtl_TextEncoding eTextEnc )
426cdf0e10cSrcweir {
427cdf0e10cSrcweir     createPortion()->setText( rStrm.readCharArrayUC( nChars, eTextEnc ) );
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
importByteString(BiffInputStream & rStrm,rtl_TextEncoding eTextEnc,BiffStringFlags nFlags)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 
importUniString(BiffInputStream & rStrm,BiffStringFlags nFlags)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 
finalizeImport()508cdf0e10cSrcweir void RichString::finalizeImport()
509cdf0e10cSrcweir {
510cdf0e10cSrcweir     maTextPortions.forEachMem( &RichStringPortion::finalizeImport );
511cdf0e10cSrcweir }
512cdf0e10cSrcweir 
extractPlainString(OUString & orString,const Font * pFirstPortionFont) const513cdf0e10cSrcweir 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();
5250dac23a0SMichael Stahl         return orString.indexOf( '\x0A' ) < 0;
526cdf0e10cSrcweir     }
527cdf0e10cSrcweir     return false;
528cdf0e10cSrcweir }
529cdf0e10cSrcweir 
convert(const Reference<XText> & rxText,bool bReplaceOld,const Font * pFirstPortionFont) const5300dac23a0SMichael 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     {
5340dac23a0SMichael Stahl         (*aIt)->convert( rxText, pFirstPortionFont, bReplaceOld );
535cdf0e10cSrcweir         pFirstPortionFont = 0;  // use passed font for first portion only
5360dac23a0SMichael Stahl         bReplaceOld = false;    // do not replace first portion text with following portions
537cdf0e10cSrcweir     }
538cdf0e10cSrcweir }
539cdf0e10cSrcweir 
540cdf0e10cSrcweir // private --------------------------------------------------------------------
541cdf0e10cSrcweir 
createPortion()542cdf0e10cSrcweir RichStringPortionRef RichString::createPortion()
543cdf0e10cSrcweir {
544cdf0e10cSrcweir     RichStringPortionRef xPortion( new RichStringPortion( *this ) );
545cdf0e10cSrcweir     maTextPortions.push_back( xPortion );
546cdf0e10cSrcweir     return xPortion;
547cdf0e10cSrcweir }
548cdf0e10cSrcweir 
createPhonetic()549cdf0e10cSrcweir RichStringPhoneticRef RichString::createPhonetic()
550cdf0e10cSrcweir {
551cdf0e10cSrcweir     RichStringPhoneticRef xPhonetic( new RichStringPhonetic( *this ) );
552cdf0e10cSrcweir     maPhonPortions.push_back( xPhonetic );
553cdf0e10cSrcweir     return xPhonetic;
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
createTextPortions(const OString & rText,rtl_TextEncoding eTextEnc,FontPortionModelList & rPortions)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 
createTextPortions(const OUString & rText,FontPortionModelList & rPortions)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 
createPhoneticPortions(const::rtl::OUString & rText,PhoneticPortionModelList & rPortions,sal_Int32 nBaseLen)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