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