LibreOffice Module sc (master)  1
richstring.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <richstring.hxx>
21 #include <biffhelper.hxx>
22 
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/text/XText.hpp>
25 #include <rtl/ustrbuf.hxx>
26 #include <editeng/editobj.hxx>
27 #include <osl/diagnose.h>
31 #include <oox/token/tokens.hxx>
32 #include <editutil.hxx>
33 
34 #include <vcl/svapp.hxx>
35 
36 namespace oox::xls {
37 
38 using namespace ::com::sun::star::text;
39 using namespace ::com::sun::star::uno;
40 
41 namespace {
42 
43 const sal_uInt8 BIFF12_STRINGFLAG_FONTS = 0x01;
44 const sal_uInt8 BIFF12_STRINGFLAG_PHONETICS = 0x02;
45 
46 bool lclNeedsRichTextFormat( const oox::xls::Font* pFont )
47 {
48  return pFont && pFont->needsRichTextFormat();
49 }
50 
51 } // namespace
52 
54  WorkbookHelper( rHelper ),
55  mnFontId( -1 ),
56  mbConverted( false )
57 {
58 }
59 
60 void RichStringPortion::setText( const OUString& rText )
61 {
62  maText = rText;
63 }
64 
66 {
67  mxFont = std::make_shared<Font>( *this, false );
68  return mxFont;
69 }
70 
71 void RichStringPortion::setFontId( sal_Int32 nFontId )
72 {
73  mnFontId = nFontId;
74 }
75 
77 {
78  if( mxFont )
79  mxFont->finalizeImport();
80  else if( mnFontId >= 0 )
82 }
83 
84 void RichStringPortion::convert( const Reference< XText >& rxText, bool bReplace )
85 {
86  if ( mbConverted )
87  return;
88 
89  Reference< XTextRange > xRange;
90  if( bReplace )
91  xRange = rxText;
92  else
93  xRange = rxText->getEnd();
94  OSL_ENSURE( xRange.is(), "RichStringPortion::convert - cannot get text range interface" );
95 
96  if( xRange.is() )
97  {
98  xRange->setString( maText );
99  if( mxFont )
100  {
101  PropertySet aPropSet( xRange );
102  mxFont->writeToPropertySet( aPropSet );
103  }
104  }
105 
106  mbConverted = true;
107 }
108 
110 {
111  rSelection.nStartPos = rSelection.nEndPos;
112  rSelection.nStartPara = rSelection.nEndPara;
113  SfxItemSet aItemSet( rEE.GetEmptyItemSet() );
114 
115  const Font* pFontToUse = mxFont ? mxFont.get() : lclNeedsRichTextFormat( pFont ) ? pFont : nullptr;
116 
117  if ( pFontToUse )
118  pFontToUse->fillToItemSet( aItemSet, true );
119 
120  // #TODO need to manually adjust nEndPos ( and nEndPara ) to cater for any paragraphs
121  sal_Int32 nLastParaLoc = -1;
122  sal_Int32 nSearchIndex = maText.indexOf( '\n' );
123  sal_Int32 nParaOccurrence = 0;
124  while ( nSearchIndex != -1 )
125  {
126  nLastParaLoc = nSearchIndex;
127  ++nParaOccurrence;
128  rSelection.nEndPos = 0;
129  nSearchIndex = maText.indexOf( '\n', nSearchIndex + 1);
130  }
131 
132  rSelection.nEndPara += nParaOccurrence;
133  if ( nLastParaLoc != -1 )
134  {
135  rSelection.nEndPos = maText.getLength() - 1 - nLastParaLoc;
136  }
137  else
138  {
139  rSelection.nEndPos = rSelection.nStartPos + maText.getLength();
140  }
141  rEE.QuickSetAttribs( aItemSet, rSelection );
142 }
143 
144 void RichStringPortion::writeFontProperties( const Reference<XText>& rxText ) const
145 {
146  PropertySet aPropSet(rxText);
147 
148  if (mxFont)
149  mxFont->writeToPropertySet(aPropSet);
150 }
151 
153 {
154  mnPos = rStrm.readuInt16();
155  mnFontId = rStrm.readuInt16();
156 }
157 
159 {
160  // #i33341# real life -- same character index may occur several times
161  OSL_ENSURE( mvModels.empty() || (mvModels.back().mnPos <= rPortion.mnPos), "FontPortionModelList::appendPortion - wrong char order" );
162  if( mvModels.empty() || (mvModels.back().mnPos < rPortion.mnPos) )
163  mvModels.push_back( rPortion );
164  else
165  mvModels.back().mnFontId = rPortion.mnFontId;
166 }
167 
169 {
170  sal_Int32 nCount = rStrm.readInt32();
171  mvModels.clear();
172  if( nCount > 0 )
173  {
174  mvModels.reserve( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 4 ) );
175  /* #i33341# real life -- same character index may occur several times
176  -> use appendPortion() to validate string position. */
177  FontPortionModel aPortion;
178  for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
179  {
180  aPortion.read( rStrm );
181  appendPortion( aPortion );
182  }
183  }
184 }
185 
187  mnFontId( -1 ),
188  mnType( XML_fullwidthKatakana ),
189  mnAlignment( XML_left )
190 {
191 }
192 
193 void PhoneticDataModel::setBiffData( sal_Int32 nType, sal_Int32 nAlignment )
194 {
195  static const sal_Int32 spnTypeIds[] = { XML_halfwidthKatakana, XML_fullwidthKatakana, XML_hiragana, XML_noConversion };
196  mnType = STATIC_ARRAY_SELECT( spnTypeIds, nType, XML_fullwidthKatakana );
197 
198  static const sal_Int32 spnAlignments[] = { XML_noControl, XML_left, XML_center, XML_distributed };
199  mnAlignment = STATIC_ARRAY_SELECT( spnAlignments, nAlignment, XML_left );
200 }
201 
203  WorkbookHelper( rHelper )
204 {
205 }
206 
208 {
209  maModel.mnFontId = rAttribs.getInteger( XML_fontId, -1 );
210  maModel.mnType = rAttribs.getToken( XML_type, XML_fullwidthKatakana );
211  maModel.mnAlignment = rAttribs.getToken( XML_alignment, XML_left );
212 }
213 
215 {
216  sal_uInt16 nFontId;
217  sal_Int32 nType, nAlignment;
218  nFontId = rStrm.readuInt16();
219  nType = rStrm.readInt32();
220  nAlignment = rStrm.readInt32();
221  maModel.mnFontId = nFontId;
222  maModel.setBiffData( nType, nAlignment );
223 }
224 
226 {
227  sal_uInt16 nFontId, nFlags;
228  nFontId = rStrm.readuInt16();
229  nFlags = rStrm.readuInt16();
230  maModel.mnFontId = nFontId;
231  maModel.setBiffData( extractValue< sal_Int32 >( nFlags, 0, 2 ), extractValue< sal_Int32 >( nFlags, 2, 2 ) );
232 }
233 
235  WorkbookHelper( rHelper ),
236  mnBasePos( -1 ),
237  mnBaseEnd( -1 )
238 {
239 }
240 
241 void RichStringPhonetic::setText( const OUString& rText )
242 {
243  maText = rText;
244 }
245 
247 {
248  mnBasePos = rAttribs.getInteger( XML_sb, -1 );
249  mnBaseEnd = rAttribs.getInteger( XML_eb, -1 );
250 }
251 
252 void RichStringPhonetic::setBaseRange( sal_Int32 nBasePos, sal_Int32 nBaseEnd )
253 {
254  mnBasePos = nBasePos;
255  mnBaseEnd = nBaseEnd;
256 }
257 
259 {
260  mnPos = rStrm.readuInt16();
261  mnBasePos = rStrm.readuInt16();
262  mnBaseLen = rStrm.readuInt16();
263 }
264 
266 {
267  // same character index may occur several times
268  OSL_ENSURE( mvModels.empty() || ((mvModels.back().mnPos <= rPortion.mnPos) &&
269  (mvModels.back().mnBasePos + mvModels.back().mnBaseLen <= rPortion.mnBasePos)),
270  "PhoneticPortionModelList::appendPortion - wrong char order" );
271  if( mvModels.empty() || (mvModels.back().mnPos < rPortion.mnPos) )
272  {
273  mvModels.push_back( rPortion );
274  }
275  else if( mvModels.back().mnPos == rPortion.mnPos )
276  {
277  mvModels.back().mnBasePos = rPortion.mnBasePos;
278  mvModels.back().mnBaseLen = rPortion.mnBaseLen;
279  }
280 }
281 
283 {
284  sal_Int32 nCount = rStrm.readInt32();
285  mvModels.clear();
286  if( nCount > 0 )
287  {
288  mvModels.reserve( getLimitedValue< size_t, sal_Int64 >( nCount, 0, rStrm.getRemaining() / 6 ) );
289  PhoneticPortionModel aPortion;
290  for( sal_Int32 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
291  {
292  aPortion.read( rStrm );
293  appendPortion( aPortion );
294  }
295  }
296 }
297 
299  WorkbookHelper( rHelper ),
300  maPhonSettings( rHelper )
301 {
302 }
303 
305 {
306  return createPortion();
307 }
308 
310 {
311  return createPortion();
312 }
313 
315 {
317  xPhonetic->importPhoneticRun( rAttribs );
318  return xPhonetic;
319 }
320 
322 {
323  maPhonSettings.importPhoneticPr( rAttribs );
324 }
325 
327 {
328  sal_uInt8 nFlags = bRich ? rStrm.readuInt8() : 0;
329  OUString aBaseText = BiffHelper::readString( rStrm );
330 
331  if( !rStrm.isEof() && getFlag( nFlags, BIFF12_STRINGFLAG_FONTS ) )
332  {
333  FontPortionModelList aPortions;
334  aPortions.importPortions( rStrm );
335  createTextPortions( aBaseText, aPortions );
336  }
337  else
338  {
339  createPortion()->setText( aBaseText );
340  }
341 
342  if( !rStrm.isEof() && getFlag( nFlags, BIFF12_STRINGFLAG_PHONETICS ) )
343  {
344  OUString aPhoneticText = BiffHelper::readString( rStrm );
345  PhoneticPortionModelList aPortions;
346  aPortions.importPortions( rStrm );
348  createPhoneticPortions( aPhoneticText, aPortions, aBaseText.getLength() );
349  }
350 }
351 
353 {
355 }
356 
357 bool RichString::extractPlainString( OUString& orString, const oox::xls::Font* pFirstPortionFont ) const
358 {
359  if( !maPhonPortions.empty() )
360  return false;
361  if( maTextPortions.empty() )
362  {
363  orString.clear();
364  return true;
365  }
366  if( (maTextPortions.size() == 1) && !maTextPortions.front()->hasFont() && !lclNeedsRichTextFormat( pFirstPortionFont ) )
367  {
368  orString = maTextPortions.front()->getText();
369  return orString.indexOf( '\x0A' ) < 0;
370  }
371  return false;
372 }
373 
374 void RichString::convert( const Reference< XText >& rxText ) const
375 {
376  if (maTextPortions.size() == 1)
377  {
378  // Set text directly to the cell when the string has only one portion.
379  // It's much faster this way.
380  RichStringPortion& rPtn = *maTextPortions.front();
381  rxText->setString(rPtn.getText());
382  rPtn.writeFontProperties(rxText);
383  return;
384  }
385 
386  bool bReplaceOld = true;
387  for( const auto& rxTextPortion : maTextPortions )
388  {
389  rxTextPortion->convert( rxText, bReplaceOld );
390  bReplaceOld = false; // do not replace first portion text with following portions
391  }
392 }
393 
394 std::unique_ptr<EditTextObject> RichString::convert( ScEditEngineDefaulter& rEE, const oox::xls::Font* pFirstPortionFont ) const
395 {
396  ESelection aSelection;
397 
398  OUStringBuffer sString;
399  for( const auto& rxTextPortion : maTextPortions )
400  sString.append(rxTextPortion->getText());
401 
402  // fdo#84370 - diving into editeng is not thread safe.
403  SolarMutexGuard aGuard;
404 
405  rEE.SetTextCurrentDefaults( sString.makeStringAndClear() );
406 
407  for( const auto& rxTextPortion : maTextPortions )
408  {
409  rxTextPortion->convert( rEE, aSelection, pFirstPortionFont );
410  pFirstPortionFont = nullptr;
411  }
412 
413  return rEE.CreateTextObject();
414 }
415 
416 // private --------------------------------------------------------------------
417 
419 {
420  RichStringPortionRef xPortion = std::make_shared<RichStringPortion>( *this );
421  maTextPortions.push_back( xPortion );
422  return xPortion;
423 }
424 
426 {
427  RichStringPhoneticRef xPhonetic = std::make_shared<RichStringPhonetic>( *this );
428  maPhonPortions.push_back( xPhonetic );
429  return xPhonetic;
430 }
431 
432 void RichString::createTextPortions( const OUString& rText, FontPortionModelList& rPortions )
433 {
434  maTextPortions.clear();
435  if( !rText.isEmpty() )
436  {
437  sal_Int32 nStrLen = rText.getLength();
438  // add leading and trailing string position to ease the following loop
439  if( rPortions.empty() || (rPortions.front().mnPos > 0) )
440  rPortions.insert( rPortions.begin(), FontPortionModel( 0 ) );
441  if( rPortions.back().mnPos < nStrLen )
442  rPortions.push_back( FontPortionModel( nStrLen ) );
443 
444  // create all string portions according to the font id vector
445  for( ::std::vector< FontPortionModel >::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt )
446  {
447  sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos;
448  if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) )
449  {
450  RichStringPortionRef xPortion = createPortion();
451  xPortion->setText( rText.copy( aIt->mnPos, nPortionLen ) );
452  xPortion->setFontId( aIt->mnFontId );
453  }
454  }
455  }
456 }
457 
458 void RichString::createPhoneticPortions( const OUString& rText, PhoneticPortionModelList& rPortions, sal_Int32 nBaseLen )
459 {
460  maPhonPortions.clear();
461  if( !rText.isEmpty())
462  {
463  sal_Int32 nStrLen = rText.getLength();
464  // no portions - assign phonetic text to entire base text
465  if( rPortions.empty() )
466  rPortions.push_back( PhoneticPortionModel( 0, 0, nBaseLen ) );
467  // add trailing string position to ease the following loop
468  if( rPortions.back().mnPos < nStrLen )
469  rPortions.push_back( PhoneticPortionModel( nStrLen, nBaseLen, 0 ) );
470 
471  // create all phonetic portions according to the portions vector
472  for( ::std::vector< PhoneticPortionModel >::const_iterator aIt = rPortions.begin(); aIt->mnPos < nStrLen; ++aIt )
473  {
474  sal_Int32 nPortionLen = (aIt + 1)->mnPos - aIt->mnPos;
475  if( (0 < nPortionLen) && (aIt->mnPos + nPortionLen <= nStrLen) )
476  {
478  xPhonetic->setText( rText.copy( aIt->mnPos, nPortionLen ) );
479  xPhonetic->setBaseRange( aIt->mnBasePos, aIt->mnBasePos + aIt->mnBaseLen );
480  }
481  }
482  }
483 }
484 
485 } // namespace oox::xls
486 
487 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Helper class to provide access to global workbook data.
void importPhoneticPr(const AttributeList &rAttribs)
Imports phonetic settings from the rPhoneticPr element.
Definition: richstring.cxx:321
void setText(const OUString &rText)
Sets text data for this portion.
Definition: richstring.cxx:60
Represents a position in a rich-string containing current font identifier.
Definition: richstring.hxx:83
sal_Int32 nStartPara
sal_Int32 mnAlignment
Phonetic text type.
Definition: richstring.hxx:124
sal_Int32 nIndex
Contains text data and font attributes for a part of a rich formatted string.
Definition: richstring.hxx:39
void push_back(const PhoneticPortionModel &rModel)
Definition: richstring.hxx:195
void importPortions(SequenceInputStream &rStrm)
Reads all phonetic portions from the passed stream.
Definition: richstring.cxx:282
void setBaseRange(sal_Int32 nBasePos, sal_Int32 nBaseEnd)
Sets the associated range in base text for this phonetic portion.
Definition: richstring.cxx:252
RichStringPortion(const WorkbookHelper &rHelper)
Definition: richstring.cxx:53
const SfxItemSet & GetEmptyItemSet() const
std::shared_ptr< RichStringPortion > RichStringPortionRef
Definition: richstring.hxx:75
OptValue< sal_Int32 > getInteger(sal_Int32 nAttrToken) const
::std::vector< FontPortionModel >::iterator begin()
Definition: richstring.hxx:112
RichStringPortionRef importRun()
Appends and returns a portion object for a new formatting run (r element).
Definition: richstring.cxx:309
PhoneticVector maPhonPortions
Phonetic settings for this string.
Definition: richstring.hxx:258
sal_Int32 mnBaseEnd
Start position in base text.
Definition: richstring.hxx:165
void convert(const css::uno::Reference< css::text::XText > &rxText, bool bReplace)
Converts the portion and replaces or appends to the passed XText.
void insert(::std::vector< FontPortionModel >::iterator it, const FontPortionModel &rModel)
Definition: richstring.hxx:108
const FontPortionModel & front() const
Definition: richstring.hxx:104
#define STATIC_ARRAY_SELECT(array, index, def)
void importPortions(SequenceInputStream &rStrm)
Reads count and font identifiers from the passed stream.
Definition: richstring.cxx:168
StylesBuffer & getStyles() const
Returns all cell formatting objects read from the styles substream.
void read(SequenceInputStream &rStrm)
Definition: richstring.cxx:258
void setFontId(sal_Int32 nFontId)
Links this portion to a font object from the global font list.
Definition: richstring.cxx:71
void importPhoneticPr(const AttributeList &rAttribs)
Imports phonetic settings from the phoneticPr element.
Definition: richstring.cxx:207
void createPhoneticPortions(const OUString &rText, PhoneticPortionModelList &rPortions, sal_Int32 nBaseLen)
Create phonetic text portions from the passed string and portion data.
Definition: richstring.cxx:458
void finalizeImport()
Final processing after import of all strings.
Definition: richstring.cxx:352
void forEachMem(FuncType pFunc) const
FontRef mxFont
Portion text.
Definition: richstring.hxx:70
sal_Int32 mnBaseLen
First character in base text.
Definition: richstring.hxx:176
sal_uInt16 readuInt16()
::std::vector< FontPortionModel > mvModels
Definition: richstring.hxx:96
void importString(SequenceInputStream &rStrm, bool bRich)
Imports a Unicode rich-string from the passed record stream.
Definition: richstring.cxx:326
PhoneticSettings(const WorkbookHelper &rHelper)
Definition: richstring.cxx:202
PhoneticDataModel maModel
Definition: richstring.hxx:146
int nCount
void appendPortion(const PhoneticPortionModel &rPortion)
Appends a rich-string phonetic portion.
Definition: richstring.cxx:265
A vector with all font portions in a rich-string.
Definition: richstring.hxx:95
RichStringPhonetic(const WorkbookHelper &rHelper)
Definition: richstring.cxx:234
const OUString & getText() const
Returns the text data of this portion.
Definition: richstring.hxx:55
void push_back(const FontPortionModel &rModel)
Definition: richstring.hxx:106
void writeFontProperties(const css::uno::Reference< css::text::XText > &rxText) const
Definition: richstring.cxx:144
sal_Int32 nEndPos
void setText(const OUString &rText)
Sets text data for this phonetic portion.
Definition: richstring.cxx:241
bool getFlag(Type nBitField, Type nMask)
void importStringData(SequenceInputStream &rStrm)
Imports phonetic settings from a rich string.
Definition: richstring.cxx:225
RichStringPhoneticRef importPhoneticRun(const AttributeList &rAttribs)
Appends and returns a phonetic text object for a new phonetic run (rPh element).
Definition: richstring.cxx:314
void read(SequenceInputStream &rStrm)
Definition: richstring.cxx:152
sal_Int32 nEndPara
sal_Int32 mnBasePos
Portion text.
Definition: richstring.hxx:164
void SetTextCurrentDefaults(const EditTextObject &rTextObject)
SetText and apply defaults already set.
Definition: editutil.cxx:559
bool needsRichTextFormat() const
Returns true, if the font requires rich text formatting in Calc.
PhoneticSettings maPhonSettings
String portions with font data.
Definition: richstring.hxx:257
sal_Int32 mnType
FontRef getFont(sal_Int32 nFontId) const
Returns the specified font object.
static OUString readString(SequenceInputStream &rStrm, bool b32BitLen=true)
Reads a BIFF12 string with leading 16-bit or 32-bit length field.
Definition: biffhelper.cxx:78
std::unique_ptr< EditTextObject > CreateTextObject()
void importPhoneticRun(const AttributeList &rAttribs)
Imports attributes of a phonetic run (rPh element).
Definition: richstring.cxx:246
void convert(const css::uno::Reference< css::text::XText > &rxText) const
Converts the string and writes it into the passed XText, replace old contents of the text object...
bool mbConverted
Link to global font list.
Definition: richstring.hxx:72
const PhoneticPortionModel & back() const
Definition: richstring.hxx:193
PortionVector maTextPortions
Definition: richstring.hxx:256
::std::vector< PhoneticPortionModel > mvModels
Definition: richstring.hxx:205
RichStringPortionRef createPortion()
Creates, appends, and returns a new empty string portion.
Definition: richstring.cxx:418
std::shared_ptr< Font > FontRef
void createTextPortions(const OUString &rText, FontPortionModelList &rPortions)
Create base text portions from the passed string and character formatting.
Definition: richstring.cxx:432
Represents a phonetic text portion in a rich-string with phonetic text.
Definition: richstring.hxx:172
RichStringPortionRef importText()
Appends and returns a portion object for a plain string (t element).
Definition: richstring.cxx:304
void fillToItemSet(SfxItemSet &rItemSet, bool bEditEngineText, bool bSkipPoolDefs=false) const
sal_Int64 getRemaining() const
void appendPortion(const FontPortionModel &rPortion)
Appends a rich-string font identifier.
Definition: richstring.cxx:158
unsigned char sal_uInt8
void setBiffData(sal_Int32 nType, sal_Int32 nAlignment)
Sets the passed data from binary import.
Definition: richstring.cxx:193
sal_Int32 mnBasePos
First character in phonetic text.
Definition: richstring.hxx:175
A vector with all phonetic portions in a rich-string.
Definition: richstring.hxx:186
void QuickSetAttribs(const SfxItemSet &rSet, const ESelection &rSel)
QPRO_FUNC_TYPE nType
Definition: qproform.cxx:401
void finalizeImport()
Final processing after import of all strings.
Definition: richstring.cxx:76
sal_Int32 mnFontId
First character in the string.
Definition: richstring.hxx:86
sal_Int32 mnType
Font identifier for text formatting.
Definition: richstring.hxx:123
FontRef const & createFont()
Creates and returns a new font formatting object.
Definition: richstring.cxx:65
bool isEof() const
sal_Int32 mnFontId
Embedded portion font, may be empty.
Definition: richstring.hxx:71
::std::vector< PhoneticPortionModel >::const_iterator begin() const
Definition: richstring.hxx:197
RichString(const WorkbookHelper &rHelper)
Definition: richstring.cxx:298
std::shared_ptr< RichStringPhonetic > RichStringPhoneticRef
Definition: richstring.hxx:168
bool extractPlainString(OUString &orString, const oox::xls::Font *pFirstPortionFont) const
Tries to extract a plain string from this object.
Definition: richstring.cxx:357
RichStringPhoneticRef createPhonetic()
Creates, appends, and returns a new empty phonetic text portion.
Definition: richstring.cxx:425
PhoneticDataModel()
Phonetic portion alignment.
Definition: richstring.cxx:186
OptValue< sal_Int32 > getToken(sal_Int32 nAttrToken) const
const FontPortionModel & back() const
Definition: richstring.hxx:103
sal_Int32 nStartPos