LibreOffice Module sw (master)  1
writerwordglue.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 <msfilter.hxx>
21 #include "writerwordglue.hxx"
22 #include <doc.hxx>
23 #include "writerhelper.hxx"
25 
26 #include <algorithm>
27 
28 #include <rtl/tencinfo.h>
29 #include <sal/log.hxx>
30 
31 #include <unicode/ubidi.h>
32 #include <tools/tenccvt.hxx>
33 #include <com/sun/star/i18n/ScriptType.hpp>
34 #include <com/sun/star/i18n/XBreakIterator.hpp>
35 
36 #include <editeng/lrspitem.hxx>
37 #include <editeng/ulspitem.hxx>
38 #include <editeng/boxitem.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <o3tl/sorted_vector.hxx>
41 #include <frmfmt.hxx>
42 #include <fmtclds.hxx>
43 #include <hfspacingitem.hxx>
44 #include <fmtfsize.hxx>
45 #include <poolfmt.hxx>
46 #include <swrect.hxx>
47 #include <fmthdft.hxx>
48 #include <frmatr.hxx>
49 #include <ndtxt.hxx>
50 #include <breakit.hxx>
51 
52 using namespace css;
53 
54 namespace myImplHelpers
55 {
56  static SwTwips CalcHdFtDist(const SwFrameFormat& rFormat, sal_uInt16 nSpacing)
57  {
58  /*
59  The normal case for reexporting word docs is to have dynamic spacing,
60  as this is word's only setting, and the reason for the existence of the
61  dynamic spacing features. If we have dynamic spacing active then we can
62  add its spacing to the value height of the h/f and get the wanted total
63  size for word.
64 
65  Otherwise we have to get the real layout rendered
66  height, which is totally nonoptimum, but the best we can do.
67  */
68  long nDist=0;
69  const SwFormatFrameSize& rSz = rFormat.GetFrameSize();
70 
71  const SwHeaderAndFooterEatSpacingItem &rSpacingCtrl =
72  sw::util::ItemGet<SwHeaderAndFooterEatSpacingItem>
74  if (rSpacingCtrl.GetValue())
75  nDist += rSz.GetHeight();
76  else
77  {
78  SwRect aRect(rFormat.FindLayoutRect());
79  if (aRect.Height())
80  nDist += aRect.Height();
81  else
82  {
83  const SwFormatFrameSize& rSize = rFormat.GetFrameSize();
85  nDist += rSize.GetHeight();
86  else
87  {
88  nDist += 274; // default for 12pt text
89  nDist += nSpacing;
90  }
91  }
92  }
93  return nDist;
94  }
95 
96  static SwTwips CalcHdDist(const SwFrameFormat& rFormat)
97  {
98  return CalcHdFtDist(rFormat, rFormat.GetULSpace().GetUpper());
99  }
100 
101  static SwTwips CalcFtDist(const SwFrameFormat& rFormat)
102  {
103  return CalcHdFtDist(rFormat, rFormat.GetULSpace().GetLower());
104  }
105 
106  /*
107  SwTextFormatColl and SwCharFormat are quite distinct types and how they are
108  gotten is also distinct, but the algorithm to match word's equivalents into
109  them is the same, so we put the different stuff into two separate helper
110  implementations and a core template that uses the helpers that uses the
111  same algorithm to do the work. We'll make the helpers specializations of a
112  non existing template so I can let the compiler figure out the right one
113  to use from a simple argument to the algorithm class
114  */
115  template <class C> class MapperImpl;
116  template<> class MapperImpl<SwTextFormatColl>
117  {
118  private:
120  public:
121  MapperImpl(SwDoc &rDoc) : mrDoc(rDoc) {}
122  SwTextFormatColl* GetBuiltInStyle(ww::sti eSti);
123  SwTextFormatColl* GetStyle(const OUString &rName);
124  SwTextFormatColl* MakeStyle(const OUString &rName);
125  };
126 
128  {
130  static const RES_POOL_COLLFMT_TYPE aArr[]=
131  {
138  RES_POOLCOLL_TOX_IDX3, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
139  RES_NONE, RES_NONE, RES_POOLCOLL_TOX_CNTNT1,
145  RES_POOLCOLL_FOOTER, RES_POOLCOLL_TOX_IDXH, RES_NONE, RES_NONE,
147  RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_POOLCOLL_ENDNOTE,
148  RES_NONE, RES_NONE, RES_NONE, RES_POOLCOLL_LISTS_BEGIN,
149  RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
150  RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
151  RES_NONE, RES_NONE, RES_POOLCOLL_HEADLINE_BASE, RES_NONE,
153  RES_POOLCOLL_TEXT_MOVE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
154  RES_NONE, RES_NONE, RES_POOLCOLL_DOC_SUBTITLE
155  };
156 
157  OSL_ENSURE(SAL_N_ELEMENTS(aArr) == 75, "Style Array has false size");
158 
159  SwTextFormatColl* pRet = nullptr;
160  //If this is a built-in word style that has a built-in writer
161  //equivalent, then map it to one of our built in styles regardless
162  //of its name
163  if (sal::static_int_cast< size_t >(eSti) < SAL_N_ELEMENTS(aArr) && aArr[eSti] != RES_NONE)
164  pRet = mrDoc.getIDocumentStylePoolAccess().GetTextCollFromPool( static_cast< sal_uInt16 >(aArr[eSti]), false);
165  return pRet;
166  }
167 
169  {
170  return sw::util::GetParaStyle(mrDoc, rName);
171  }
172 
174  {
175  return mrDoc.MakeTextFormatColl(rName,
176  mrDoc.GetDfltTextFormatColl());
177  }
178 
179  template<> class MapperImpl<SwCharFormat>
180  {
181  private:
183  public:
184  MapperImpl(SwDoc &rDoc) : mrDoc(rDoc) {}
185  SwCharFormat* GetBuiltInStyle(ww::sti eSti);
186  SwCharFormat* GetStyle(const OUString &rName);
187  SwCharFormat* MakeStyle(const OUString &rName);
188  };
189 
191  {
193  switch (eSti)
194  {
195  case ww::stiFootnoteRef:
196  eLookup = RES_POOLCHR_FOOTNOTE;
197  break;
198  case ww::stiLnn:
199  eLookup = RES_POOLCHR_LINENUM;
200  break;
201  case ww::stiPgn:
202  eLookup = RES_POOLCHR_PAGENO;
203  break;
204  case ww::stiEdnRef:
205  eLookup = RES_POOLCHR_ENDNOTE;
206  break;
207  case ww::stiHyperlink:
208  eLookup = RES_POOLCHR_INET_NORMAL;
209  break;
211  eLookup = RES_POOLCHR_INET_VISIT;
212  break;
213  case ww::stiStrong:
214  eLookup = RES_POOLCHR_HTML_STRONG;
215  break;
216  case ww::stiEmphasis:
217  eLookup = RES_POOLCHR_HTML_EMPHASIS;
218  break;
219  default:
220  eLookup = RES_POOLCHR_NORMAL_END;
221  break;
222  }
223  SwCharFormat *pRet = nullptr;
224  if (eLookup != RES_POOLCHR_NORMAL_END)
225  pRet = mrDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( static_cast< sal_uInt16 >(eLookup) );
226  return pRet;
227  }
228 
230  {
231  return sw::util::GetCharStyle(mrDoc, rName);
232  }
233 
235  {
236  return mrDoc.MakeCharFormat(rName, mrDoc.GetDfltCharFormat());
237  }
238 
239  template<class C> class StyleMapperImpl
240  {
241  private:
244  C* MakeNonCollidingStyle(const OUString& rName);
245  public:
246  typedef std::pair<C*, bool> StyleResult;
247  explicit StyleMapperImpl(SwDoc &rDoc) : maHelper(rDoc) {}
248  StyleResult GetStyle(const OUString& rName, ww::sti eSti);
249  };
250 
251  template<class C>
252  typename StyleMapperImpl<C>::StyleResult
253  StyleMapperImpl<C>::GetStyle(const OUString& rName, ww::sti eSti)
254  {
255  C *pRet = maHelper.GetBuiltInStyle(eSti);
256 
257  //If we've used it once, don't reuse it
258  if (pRet && (maUsedStyles.end() != maUsedStyles.find(pRet)))
259  pRet = nullptr;
260 
261  if (!pRet)
262  {
263  pRet = maHelper.GetStyle(rName);
264  //If we've used it once, don't reuse it
265  if (pRet && (maUsedStyles.end() != maUsedStyles.find(pRet)))
266  pRet = nullptr;
267  }
268 
269  bool bStyExist = pRet != nullptr;
270 
271  if (!pRet)
272  {
273  OUString aName(rName);
274  sal_Int32 nIdx = rName.indexOf(',');
275  // No commas allow in SW style names
276  if (-1 != nIdx)
277  aName = rName.copy( 0, nIdx );
278  pRet = MakeNonCollidingStyle( aName );
279  }
280 
281  if (pRet)
282  maUsedStyles.insert(pRet);
283 
284  return StyleResult(pRet, bStyExist);
285  }
286 
287  template<class C>
289  {
290  OUString aName(rName);
291  C* pColl = 0;
292 
293  if (0 != (pColl = maHelper.GetStyle(aName)))
294  {
295  //If the style collides first stick WW- in front of it, unless
296  //it already has it and then successively add a larger and
297  //larger number after it, it's got to work at some stage!
298  if (!aName.startsWith("WW-"))
299  aName = "WW-" + aName;
300 
301  sal_Int32 nI = 1;
302  OUString aBaseName = aName;
303  while (
304  0 != (pColl = maHelper.GetStyle(aName)) &&
305  (nI < SAL_MAX_INT32)
306  )
307  {
308  aName = aBaseName + OUString::number(nI++);
309  }
310  }
311 
312  return pColl ? 0 : maHelper.MakeStyle(aName);
313  }
314 
315  static OUString FindBestMSSubstituteFont(const OUString &rFont)
316  {
317  if (IsStarSymbol(rFont))
318  return "Arial Unicode MS";
319  return GetSubsFontName(rFont, SubsFontFlags::ONLYONE | SubsFontFlags::MS);
320  }
321 
322  namespace {
323 
324  //Utility to remove entries before a given starting position
325  class IfBeforeStart
326  {
327  private:
328  sal_Int32 mnStart;
329  public:
330  explicit IfBeforeStart(sal_Int32 nStart) : mnStart(nStart) {}
331  bool operator()(const sw::util::CharRunEntry &rEntry) const
332  {
333  return rEntry.mnEndPos < mnStart;
334  }
335  };
336 
337  }
338 }
339 
342 {
343  SvxLRSpaceItem aLR(rFormat.GetLRSpace());
344  const SvxBoxItem& rBox = rFormat.GetBox();
345 
346  aLR.SetLeft(aLR.GetLeft() + rBox.GetDistance(SvxBoxItemLine::LEFT));
347  if (const editeng::SvxBorderLine* pLeft = rBox.GetLeft())
348  aLR.SetLeft(aLR.GetLeft() + pLeft->GetWidth());
349 
350  aLR.SetRight(aLR.GetRight() + rBox.GetDistance(SvxBoxItemLine::RIGHT));
351  if (const editeng::SvxBorderLine* pRight = rBox.GetRight())
352  aLR.SetRight(aLR.GetRight() + pRight->GetWidth());
353 
354  return aLR;
355 }
356 
357 namespace sw
358 {
359  namespace util
360  {
361 
362  bool IsPlausableSingleWordSection(const SwFrameFormat &rTitleFormat, const SwFrameFormat &rFollowFormat)
363  {
364  bool bPlausableSingleWordSection = true;
365 
366  const SwFormatCol& rFirstCols = rTitleFormat.GetCol();
367  const SwFormatCol& rFollowCols = rFollowFormat.GetCol();
368  const SwColumns& rFirstColumns = rFirstCols.GetColumns();
369  const SwColumns& rFollowColumns = rFollowCols.GetColumns();
370  SvxLRSpaceItem aOneLR = lcl_getWordLRSpace(rTitleFormat);
371  SvxLRSpaceItem aTwoLR = lcl_getWordLRSpace(rFollowFormat);
372  const SwFormatFrameSize& rFirstFrameSize = rTitleFormat.GetFrameSize();
373  const SwFormatFrameSize& rFollowFrameSize = rFollowFormat.GetFrameSize();
374 
375  if (rFirstColumns.size() != rFollowColumns.size())
376  {
377  //e.g. #i4320#
378  bPlausableSingleWordSection = false;
379  }
380  else if (aOneLR != aTwoLR)
381  bPlausableSingleWordSection = false;
382  else if (rFirstFrameSize != rFollowFrameSize)
383  bPlausableSingleWordSection = false;
384  else
385  {
386  HdFtDistanceGlue aOne(rTitleFormat.GetAttrSet());
387  HdFtDistanceGlue aTwo(rFollowFormat.GetAttrSet());
388  //e.g. #i14509#
389  if (!aOne.StrictEqualTopBottom(aTwo))
390  bPlausableSingleWordSection = false;
391  }
392  return bPlausableSingleWordSection;
393  }
394 
395  HdFtDistanceGlue::HdFtDistanceGlue(const SfxItemSet &rPage)
396  {
397  if (const SvxBoxItem *pBox = rPage.GetItem<SvxBoxItem>(RES_BOX))
398  {
399  dyaHdrTop = pBox->CalcLineSpace( SvxBoxItemLine::TOP, /*bEvenIfNoLine*/true );
400  dyaHdrBottom = pBox->CalcLineSpace( SvxBoxItemLine::BOTTOM, /*bEvenIfNoLine*/true );
401  }
402  else
403  {
404  dyaHdrTop = dyaHdrBottom = 0;
405  }
406  const SvxULSpaceItem &rUL =
407  ItemGet<SvxULSpaceItem>(rPage, RES_UL_SPACE);
408  dyaHdrTop += rUL.GetUpper();
409  dyaHdrBottom += rUL.GetLower();
410 
411  dyaTop = dyaHdrTop;
412  dyaBottom = dyaHdrBottom;
413 
414  const SwFormatHeader *pHd = rPage.GetItem<SwFormatHeader>(RES_HEADER);
415  if (pHd && pHd->IsActive() && pHd->GetHeaderFormat())
416  {
417  mbHasHeader = true;
418  dyaTop = dyaTop + static_cast< sal_uInt16 >( (myImplHelpers::CalcHdDist(*(pHd->GetHeaderFormat()))) );
419  }
420  else
421  mbHasHeader = false;
422 
423  const SwFormatFooter *pFt = rPage.GetItem<SwFormatFooter>(RES_FOOTER);
424  if (pFt && pFt->IsActive() && pFt->GetFooterFormat())
425  {
426  mbHasFooter = true;
427  dyaBottom = dyaBottom + static_cast< sal_uInt16 >( (myImplHelpers::CalcFtDist(*(pFt->GetFooterFormat()))) );
428  }
429  else
430  mbHasFooter = false;
431  }
432 
433  bool HdFtDistanceGlue::StrictEqualTopBottom(const HdFtDistanceGlue &rOther)
434  const
435  {
436  // Check top only if both object have a header or if
437  // both object don't have a header
438  if (HasHeader() == rOther.HasHeader())
439  {
440  if (dyaTop != rOther.dyaTop)
441  return false;
442  }
443 
444  // Check bottom only if both object have a footer or if
445  // both object don't have a footer
446  if (HasFooter() == rOther.HasFooter())
447  {
448  if (dyaBottom != rOther.dyaBottom)
449  return false;
450  }
451 
452  return true;
453  }
454 
455  ParaStyleMapper::ParaStyleMapper(SwDoc &rDoc)
456  : mpImpl(new myImplHelpers::StyleMapperImpl<SwTextFormatColl>(rDoc))
457  {
458  }
459 
461  {
462  }
463 
465  const OUString& rName, ww::sti eSti)
466  {
467  return mpImpl->GetStyle(rName, eSti);
468  }
469 
471  : mpImpl(new myImplHelpers::StyleMapperImpl<SwCharFormat>(rDoc))
472  {
473  }
474 
476  {
477  }
478 
480  const OUString& rName, ww::sti eSti)
481  {
482  return mpImpl->GetStyle(rName, eSti);
483  }
484 
485  FontMapExport::FontMapExport(const OUString &rFamilyName)
486  {
487  sal_Int32 nIndex = 0;
488  msPrimary = GetNextFontToken(rFamilyName, nIndex);
490  if (msSecondary.isEmpty() && nIndex != -1)
491  msSecondary = GetNextFontToken(rFamilyName, nIndex);
492  }
493 
494  bool ItemSort::operator()(sal_uInt16 nA, sal_uInt16 nB) const
495  {
496  /*
497  #i24291#
498  All we want to do is ensure for now is that if a charfmt exist
499  in the character properties that it rises to the top and is
500  exported first. In the future we might find more ordering
501  dependencies for export, in which case this is the place to do
502  it
503  */
504  if (nA == nB)
505  return false;
506  if (nA == RES_TXTATR_CHARFMT)
507  return true;
508  if (nB == RES_TXTATR_CHARFMT)
509  return false;
510  if (nA == RES_TXTATR_INETFMT)
511  return true;
512  if (nB == RES_TXTATR_INETFMT)
513  return false;
514  return nA < nB;
515  }
516 
518  {
519  const OUString &rText = rTextNd.GetText();
520 
521  bool bParaIsRTL = false;
522  OSL_ENSURE(rTextNd.GetDoc(), "No document for node?, suspicious");
523  if (rTextNd.GetDoc())
524  {
525  if (SvxFrameDirection::Horizontal_RL_TB ==
526  rTextNd.GetDoc()->GetTextDirection(SwPosition(rTextNd)))
527  {
528  bParaIsRTL = true;
529  }
530  }
531 
532  using namespace ::com::sun::star::i18n;
533 
534  sal_uInt16 nScript = i18n::ScriptType::LATIN;
536  if (!rText.isEmpty())
537  nScript = g_pBreakIt->GetBreakIter()->getScriptType(rText, 0);
538 
539  rtl_TextEncoding eChrSet = ItemGet<SvxFontItem>(rTextNd,
540  GetWhichOfScript(RES_CHRATR_FONT, nScript)).GetCharSet();
541  eChrSet = GetExtendedTextEncoding(eChrSet);
542 
543  CharRuns aRunChanges;
544 
545  if (rText.isEmpty())
546  {
547  aRunChanges.emplace_back(0, nScript, eChrSet,
548  bParaIsRTL);
549  return aRunChanges;
550  }
551 
552  typedef std::pair<int32_t, bool> DirEntry;
553  typedef std::pair<sal_Int32, sal_uInt16> ScriptEntry;
554  std::vector<DirEntry> aDirChanges;
555  std::vector<ScriptEntry> aScripts;
556 
557  UBiDiDirection eDefaultDir = bParaIsRTL ? UBIDI_RTL : UBIDI_LTR;
558  UErrorCode nError = U_ZERO_ERROR;
559  UBiDi* pBidi = ubidi_openSized(rText.getLength(), 0, &nError);
560  ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(rText.getStr()), rText.getLength(),
561  static_cast< UBiDiLevel >(eDefaultDir), nullptr, &nError);
562 
563  sal_Int32 nCount = ubidi_countRuns(pBidi, &nError);
564  aDirChanges.reserve(nCount);
565 
566  int32_t nStart = 0;
567  int32_t nEnd;
568  UBiDiLevel nCurrDir;
569 
570  for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
571  {
572  ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir);
573  /*
574  UBiDiLevel is the type of the level values in this BiDi
575  implementation.
576 
577  It holds an embedding level and indicates the visual direction
578  by its bit 0 (even/odd value).
579 
580  The value for UBIDI_DEFAULT_LTR is even and the one for
581  UBIDI_DEFAULT_RTL is odd
582  */
583  aDirChanges.emplace_back(nEnd, nCurrDir & 0x1);
584  nStart = nEnd;
585  }
586  ubidi_close(pBidi);
587 
589 
590  sal_Int32 nLen = rText.getLength();
591  sal_Int32 nPos = 0;
592  while (nPos < nLen)
593  {
594  sal_Int32 nEnd2 = g_pBreakIt->GetBreakIter()->endOfScript(rText, nPos,
595  nScript);
596  if (nEnd2 < 0)
597  break;
598  nPos = nEnd2;
599  aScripts.emplace_back(nPos, nScript);
600  nScript = g_pBreakIt->GetBreakIter()->getScriptType(rText, nPos);
601  }
602 
603  auto aBiDiEnd = aDirChanges.cend();
604  auto aScriptEnd = aScripts.cend();
605 
606  auto aBiDiIter = aDirChanges.cbegin();
607  auto aScriptIter = aScripts.cbegin();
608 
609  bool bCharIsRTL = bParaIsRTL;
610 
611  while (
612  aBiDiIter != aBiDiEnd ||
613  aScriptIter != aScriptEnd
614  )
615  {
616  sal_Int32 nMinPos = rText.getLength();
617 
618  if (aBiDiIter != aBiDiEnd)
619  {
620  if (aBiDiIter->first < nMinPos)
621  nMinPos = aBiDiIter->first;
622  bCharIsRTL = aBiDiIter->second;
623  }
624 
625  if (aScriptIter != aScriptEnd)
626  {
627  if (aScriptIter->first < nMinPos)
628  nMinPos = aScriptIter->first;
629  nScript = aScriptIter->second;
630  }
631 
632  aRunChanges.emplace_back(nMinPos, nScript, eChrSet, bCharIsRTL);
633 
634  if (aBiDiIter != aBiDiEnd)
635  {
636  if (aBiDiIter->first == nMinPos)
637  ++aBiDiIter;
638  }
639 
640  if (aScriptIter != aScriptEnd)
641  {
642  if (aScriptIter->first == nMinPos)
643  ++aScriptIter;
644  }
645  }
646 
647  aRunChanges.erase(std::remove_if(aRunChanges.begin(),
648  aRunChanges.end(), myImplHelpers::IfBeforeStart(0/*nTextStart*/)), aRunChanges.end());
649 
650  return aRunChanges;
651  }
652  }
653 
654  namespace ms
655  {
656  sal_uInt8 rtl_TextEncodingToWinCharset(rtl_TextEncoding eTextEncoding)
657  {
658  sal_uInt8 nRet =
659  rtl_getBestWindowsCharsetFromTextEncoding(eTextEncoding);
660  switch (eTextEncoding)
661  {
662  case RTL_TEXTENCODING_DONTKNOW:
663  case RTL_TEXTENCODING_UCS2:
664  case RTL_TEXTENCODING_UTF7:
665  case RTL_TEXTENCODING_UTF8:
666  case RTL_TEXTENCODING_JAVA_UTF8:
667  nRet = 0x01;
668  break;
669  default:
670  break;
671  }
672  return nRet;
673  }
674 
675  static bool
676  CanEncode(OUString const& rString, rtl_TextEncoding const eEncoding)
677  {
678  OString tmp;
679  return rString.convertToString(&tmp, eEncoding,
680  RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
681  RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR);
682  }
683 
685  OUString const& rFontName, OUString const& rAltName,
686  rtl_TextEncoding eTextEncoding)
687  {
688  sal_uInt8 nRet =
689  rtl_getBestWindowsCharsetFromTextEncoding(eTextEncoding);
690  rtl_TextEncoding enc2 = rtl_getTextEncodingFromWindowsCharset(nRet);
691  if (!rtl_isOctetTextEncoding(enc2) /* check to avoid asserts */ ||
692  !(CanEncode(rFontName, enc2) && CanEncode(rAltName, enc2)))
693  {
694  static struct { rtl_TextEncoding enc; sal_uInt8 charset; }
695  const s_fallbacks [] = {
696  { RTL_TEXTENCODING_MS_932, 0x80 }, // Shift-JIS
697  { RTL_TEXTENCODING_MS_936, 0x86 }, // GB-2312
698  { RTL_TEXTENCODING_MS_950, 0x88 }, // Big5
699  { RTL_TEXTENCODING_MS_949, 0x81 }, // EUC-KR
700  };
701  for (const auto & i : s_fallbacks)
702  {
703  // fall back to a charset that can at least encode the
704  // font's name
705  if (CanEncode(rFontName, i.enc)
706  && CanEncode(rAltName, i.enc))
707  {
708  return i.charset;
709  }
710  }
711  SAL_INFO("sw.rtf", "no fallback charset found for font: "
712  << rFontName << " " << rAltName);
713  nRet = 0x01; // all hope lost: "default", whatever that is
714  }
715  return nRet;
716  }
717 
718  sal_uInt32 DateTime2DTTM( const DateTime& rDT )
719  {
720  /*
721  mint short :6 0000003F minutes (0-59)
722  hr short :5 000007C0 hours (0-23)
723  dom short :5 0000F800 days of month (1-31)
724  mon short :4 000F0000 months (1-12)
725  yr short :9 1FF00000 years (1900-2411)-1900
726  wdy short :3 E0000000 weekday(Sunday=0
727  Monday=1
728  ( wdy can be ignored ) Tuesday=2
729  Wednesday=3
730  Thursday=4
731  Friday=5
732  Saturday=6)
733  */
734 
735  if ( rDT.GetDate() == 0 )
736  return 0;
737  sal_uInt32 nDT = ( rDT.GetDayOfWeek() + 1 ) % 7;
738  nDT <<= 9;
739  nDT += ( rDT.GetYear() - 1900 ) & 0x1ff;
740  nDT <<= 4;
741  nDT += rDT.GetMonth() & 0xf;
742  nDT <<= 5;
743  nDT += rDT.GetDay() & 0x1f;
744  nDT <<= 5;
745  nDT += rDT.GetHour() & 0x1f;
746  nDT <<= 6;
747  nDT += rDT.GetMin() & 0x3f;
748  return nDT;
749  }
750 
751 
755  static sal_Int32 findUnquoted( const OUString& rParams, sal_Unicode cFind, sal_Int32 nFromPos )
756  {
757  const sal_Int32 nLen = rParams.getLength();
758  if (nFromPos < 0 || nLen <= nFromPos)
759  return -1;
760  for (sal_Int32 nI = nFromPos; nI < nLen; ++nI)
761  {
762  const sal_Unicode c = rParams[nI];
763  if (c == '\\')
764  ++nI;
765  else if (c == '\"')
766  {
767  ++nI;
768  // While not at the end and not at an unescaped end quote
769  while (nI < nLen)
770  {
771  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
772  break;
773  ++nI;
774  }
775  }
776  else //normal unquoted section
777  {
778  if (c == cFind)
779  return nI;
780  }
781  }
782  return -1;
783  }
784 
788  static bool replaceUnquoted( OUString& rParams, const OUString& rFind, const OUString& rReplace )
789  {
790  bool bReplaced = false;
791  if (rFind.isEmpty())
792  return bReplaced;
793  const sal_Unicode cFirst = rFind[0];
794 
795  sal_Int32 nLen = rParams.getLength();
796  for (sal_Int32 nI = 0; nI < nLen; ++nI)
797  {
798  const sal_Unicode c = rParams[nI];
799  if (rParams[nI] == '\\')
800  ++nI;
801  else if (rParams[nI] == '\"')
802  {
803  ++nI;
804  // While not at the end and not at an unescaped end quote
805  while (nI < nLen)
806  {
807  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
808  break;
809  ++nI;
810  }
811  }
812  else //normal unquoted section
813  {
814  if (c == cFirst && rParams.match( rFind, nI))
815  {
816  const sal_Int32 nFindLen = rFind.getLength();
817  const sal_Int32 nDiff = rReplace.getLength() - nFindLen;
818  rParams = rParams.replaceAt( nI, nFindLen, rReplace);
819  nI += nFindLen + nDiff - 1;
820  nLen += nDiff;
821  bReplaced = true;
822  }
823  }
824  }
825  return bReplaced;
826  }
827 
829  SvNumberFormatter *pFormatter, LanguageType &rLang, bool bHijri,
830  LanguageType nDocLang)
831  {
832  // tell the Formatter about the new entry
833  sal_Int32 nCheckPos = 0;
834  SvNumFormatType nType = SvNumFormatType::DEFINED;
835  sal_uInt32 nKey = 0;
836 
837  SwapQuotesInField(rParams);
838 
839  // Force to Japanese when finding one of 'geE'.
840  // XXX This actually may not be correct, all era keywords could be
841  // used in other locales as well. I just don't know about Word. But
842  // this is how it was for 10 years...
843  bool bForceJapanese = (-1 != findUnquoted( rParams, 'g', 0));
844  // XXX Why replace? The number formatter does handle them and this
845  // effectively changes from Gengou to Gregorian calendar. Legacy
846  // because it wasn't supported a decade ago and now moot? Or is
847  // that a Word specialty?
848  bForceJapanese |= replaceUnquoted( rParams, "ee", "yyyy");
849  bForceJapanese |= replaceUnquoted( rParams, "EE", "YYYY");
850  if (LANGUAGE_FRENCH != nDocLang)
851  {
852  // Handle the 'a' case here
853  sal_Int32 nLastPos = 0;
854  do
855  {
856  sal_Int32 nPos = findUnquoted( rParams, 'a', nLastPos + 1 );
857  bForceJapanese |= ( nPos != -1 && IsNotAM( rParams, nPos ) );
858  nLastPos = nPos;
859  } while ( -1 != nLastPos );
860  }
861 
862  // Force to NatNum when finding one of 'oOA'
863  bool bForceNatNum = replaceUnquoted( rParams, "o", "m")
864  || replaceUnquoted( rParams, "O", "M");
865  if (LANGUAGE_FRENCH != nDocLang)
866  {
867  // Handle the 'A' case here
868  sal_Int32 nLastPos = 0;
869  do
870  {
871  sal_Int32 nPos = findUnquoted( rParams, 'A', nLastPos + 1 );
872  bool bIsCharA = ( nPos != -1 && IsNotAM( rParams, nPos ) );
873  bForceNatNum |= bIsCharA;
874  if ( bIsCharA )
875  rParams = rParams.replaceAt( nPos, 1, "D" );
876  nLastPos = nPos;
877  } while ( -1 != nLastPos );
878  }
879 
880  sal_Int32 nLen = rParams.getLength();
881  for (sal_Int32 nI = 0; nI < nLen; ++nI)
882  {
883  if (rParams[nI] == '\\')
884  ++nI;
885  else if (rParams[nI] == '\"')
886  {
887  ++nI;
888  // While not at the end and not at an unescaped end quote
889  while (nI < nLen)
890  {
891  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
892  break;
893  ++nI;
894  }
895  }
896  else //normal unquoted section
897  {
898  sal_Unicode nChar = rParams[nI];
899 
900  // Change the localized word string to english
901  if ( nDocLang == LANGUAGE_FRENCH )
902  {
903  if ( ( nChar == 'a' || nChar == 'A' ) && IsNotAM(rParams, nI) )
904  rParams = rParams.replaceAt(nI, 1, "Y");
905  }
906  if (nChar == '/')
907  {
908  // MM: We have to escape '/' in case it's used as a char.
909  // But not if it's a '/' inside AM/PM
910  if (!(IsPreviousAM(rParams, nI) && IsNextPM(rParams, nI)))
911  {
912  rParams = rParams.replaceAt(nI, 1, "\\/");
913  nLen++;
914  }
915  nI++;
916  }
917 
918  // Deal with language differences in date format expression.
919  // Should be made with i18n framework.
920  // The list of the mappings and of those "special" locales is to be found at:
921  // http://l10n.openoffice.org/i18n_framework/LocaleData.html
922  if ( !bForceJapanese && !bForceNatNum )
923  {
924  // Convert to the localized equivalent for OOo
925  if ( rLang == LANGUAGE_FINNISH )
926  {
927  if (nChar == 'y' || nChar == 'Y')
928  rParams = rParams.replaceAt(nI, 1, "V");
929  else if (nChar == 'm' || nChar == 'M')
930  rParams = rParams.replaceAt(nI, 1, "K");
931  else if (nChar == 'd' || nChar == 'D')
932  rParams = rParams.replaceAt(nI, 1, "P");
933  else if (nChar == 'h' || nChar == 'H')
934  rParams = rParams.replaceAt(nI, 1, "T");
935  }
936  else if ( rLang.anyOf(
943  {
944  if (nChar == 'h' || nChar == 'H')
945  rParams = rParams.replaceAt(nI, 1, "T");
946  }
947  else if ( rLang.anyOf(
970  {
971  if (nChar == 'a' || nChar == 'A')
972  rParams = rParams.replaceAt(nI, 1, "O");
973  else if (nChar == 'y' || nChar == 'Y')
974  rParams = rParams.replaceAt(nI, 1, "A");
975  }
976  else if ( rLang.anyOf(
979  {
980  if (nChar == 'y' || nChar == 'Y')
981  rParams = rParams.replaceAt(nI, 1, "J");
982  else if (nChar == 'u' || nChar == 'U')
983  rParams = rParams.replaceAt(nI, 1, "H");
984  }
985  else if ( rLang.anyOf(
988  {
989  if (nChar == 'a' || nChar == 'A')
990  rParams = rParams.replaceAt(nI, 1, "O");
991  else if (nChar == 'g' || nChar == 'G')
992  rParams = rParams.replaceAt(nI, 1, "X");
993  else if (nChar == 'y' || nChar == 'Y')
994  rParams = rParams.replaceAt(nI, 1, "A");
995  else if (nChar == 'd' || nChar == 'D')
996  rParams = rParams.replaceAt(nI, 1, "G");
997  }
998  else if ( rLang.anyOf(
1004  {
1005  if (nChar == 'y' || nChar == 'Y')
1006  rParams = rParams.replaceAt(nI, 1, "J");
1007  else if (nChar == 'd' || nChar == 'D')
1008  rParams = rParams.replaceAt(nI, 1, "T");
1009  }
1010  else if ( rLang.anyOf(
1017  {
1018  if (nChar == 'y' || nChar == 'Y' || nChar == 'a')
1019  rParams = rParams.replaceAt(nI, 1, "A");
1020  else if (nChar == 'd' || nChar == 'D' || nChar == 'j')
1021  rParams = rParams.replaceAt(nI, 1, "J");
1022  }
1023  }
1024  }
1025  }
1026 
1027  if (bForceNatNum)
1028  bForceJapanese = true;
1029 
1030  if (bForceJapanese)
1031  rLang = LANGUAGE_JAPANESE;
1032 
1033  if (bForceNatNum)
1034  rParams = "[NatNum1][$-411]" + rParams;
1035 
1036  if (bHijri)
1037  rParams = "[~hijri]" + rParams;
1038 
1039  pFormatter->PutEntry(rParams, nCheckPos, nType, nKey, rLang);
1040 
1041  return nKey;
1042  }
1043 
1044  bool IsPreviousAM(OUString const & rParams, sal_Int32 nPos)
1045  {
1046  return nPos>=2 && rParams.matchIgnoreAsciiCase("am", nPos-2);
1047  }
1048  bool IsNextPM(OUString const & rParams, sal_Int32 nPos)
1049  {
1050  return nPos+2<rParams.getLength() && rParams.matchIgnoreAsciiCase("pm", nPos+1);
1051  }
1052  bool IsNotAM(OUString const & rParams, sal_Int32 nPos)
1053  {
1054  ++nPos;
1055  return nPos>=rParams.getLength() || (rParams[nPos]!='M' && rParams[nPos]!='m');
1056  }
1057 
1058  void SwapQuotesInField(OUString &rFormat)
1059  {
1060  //Swap unescaped " and ' with ' and "
1061  const sal_Int32 nLen = rFormat.getLength();
1062  for (sal_Int32 nI = 0; nI < nLen; ++nI)
1063  {
1064  if (!nI || rFormat[nI-1]!='\\')
1065  {
1066  if (rFormat[nI]=='\"')
1067  rFormat = rFormat.replaceAt(nI, 1, "\'");
1068  else if (rFormat[nI]=='\'')
1069  rFormat = rFormat.replaceAt(nI, 1, "\"");
1070  }
1071  }
1072  }
1073 
1074  }
1075 }
1076 
1077 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool GetValue() const
#define LANGUAGE_SPANISH_PANAMA
#define LANGUAGE_GERMAN
#define LANGUAGE_SPANISH_EL_SALVADOR
constexpr TypedWhichId< SwHeaderAndFooterEatSpacingItem > RES_HEADER_FOOTER_EAT_SPACING(121)
sal_Int32 nIndex
#define LANGUAGE_SPANISH_VENEZUELA
const SwFormatCol & GetCol(bool=true) const
Definition: fmtclds.hxx:168
Represents the style of a paragraph.
Definition: fmtcol.hxx:55
Marks a position in the document model.
Definition: pam.hxx:35
std::vector< SwColumn > SwColumns
Definition: fmtclds.hxx:57
DayOfWeek GetDayOfWeek() const
#define LANGUAGE_DANISH
#define LANGUAGE_DUTCH_BELGIAN
sal_uInt16 GetLower() const
sal_Int32 mnStart
const OUString & GetText() const
Definition: ndtxt.hxx:211
constexpr TypedWhichId< SwFormatHeader > RES_HEADER(96)
sal_uLong MSDateTimeFormatToSwFormat(OUString &rParams, SvNumberFormatter *pFormatter, LanguageType &rLang, bool bHijri, LanguageType nDocLang)
Convert from Word Date/Time field str to Writer's Date Time str.
Pages/field.
Definition: poolfmt.hxx:115
#define LANGUAGE_SPANISH_GUATEMALA
sal_uIntPtr sal_uLong
Doc. subtitle.
Definition: poolfmt.hxx:424
#define LANGUAGE_SPANISH_ECUADOR
Definition: doc.hxx:184
bool IsNotAM(OUString const &rParams, sal_Int32 nPos)
Used by MSDateTimeFormatToSwFormat to identify AM time fields.
void Height(long nNew)
Definition: swrect.hxx:191
Content 1st level.
Definition: poolfmt.hxx:375
OUString GetSubsFontName(const OUString &rName, SubsFontFlags nFlags)
#define LANGUAGE_FRENCH_MONACO
long SwTwips
Definition: swtypes.hxx:49
SvxFrameDirection GetTextDirection(const SwPosition &rPos, const Point *pPt=nullptr) const
Definition: doclay.cxx:1611
Dialog to specify the properties of date form field.
#define LANGUAGE_FRENCH_SWISS
#define LANGUAGE_GERMAN_AUSTRIAN
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
static SwTwips CalcHdDist(const SwFrameFormat &rFormat)
static SvxLRSpaceItem lcl_getWordLRSpace(const SwFrameFormat &rFormat)
Count what Word calls left/right margin from a format's LRSpace + Box.
#define LANGUAGE_FRENCH_CANADIAN
#define C
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
std::unique_ptr<::myImplHelpers::StyleMapperImpl< SwTextFormatColl > > mpImpl
Definition: msfilter.hxx:149
#define LANGUAGE_SPANISH_NICARAGUA
Content 5th level.
Definition: poolfmt.hxx:379
const SvxBoxItem & GetBox(bool=true) const
Definition: frmatr.hxx:84
bool IsActive() const
Definition: fmthdft.hxx:89
#define LANGUAGE_NORWEGIAN_NYNORSK
sal_uInt16 GetHour() const
#define LANGUAGE_SPANISH_HONDURAS
#define LANGUAGE_PORTUGUESE
sal_uInt16 sal_Unicode
StyleResult GetStyle(const OUString &rName, ww::sti eSti)
Get the writer style which the word style should map to.
#define LANGUAGE_SWEDISH
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
sal_uInt16 GetMonth() const
#define LANGUAGE_ITALIAN
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
Footer, for pageformats Client of FrameFormat describing the footer.
Definition: fmthdft.hxx:64
int nCount
sal_uInt16 GetMin() const
Content 6th level.
Definition: poolfmt.hxx:389
std::pair< SwTextFormatColl *, bool > StyleResult
StyleResult StyleResult is a std::pair of a pointer to a style and a flag which is true if the style ...
Definition: msfilter.hxx:158
bool operator()(sal_uInt16 nA, sal_uInt16 nB) const
constexpr TypedWhichId< SwFormatCharFormat > RES_TXTATR_CHARFMT(52)
sal_Int32 GetDate() const
Content 2nd level.
Definition: poolfmt.hxx:376
Text body indent.
Definition: poolfmt.hxx:254
#define LANGUAGE_SWEDISH_FINLAND
#define LANGUAGE_NORWEGIAN_BOKMAL
bool PutEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge=LANGUAGE_DONTKNOW)
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
#define LANGUAGE_NORWEGIAN
#define SAL_N_ELEMENTS(arr)
Content 3rd level.
Definition: poolfmt.hxx:377
rtl_TextEncoding GetExtendedTextEncoding(rtl_TextEncoding eEncoding)
sal_Int16 GetYear() const
#define LANGUAGE_SPANISH_COLOMBIA
#define LANGUAGE_ITALIAN_SWISS
Style of a layout element.
Definition: frmfmt.hxx:57
#define LANGUAGE_SPANISH_DOMINICAN_REPUBLIC
#define SAL_MAX_INT32
bool IsPreviousAM(OUString const &rParams, sal_Int32 nPos)
Internet visited.
Definition: poolfmt.hxx:122
int i
const SwColumns & GetColumns() const
Definition: fmtclds.hxx:112
const SwFrameFormat * GetFooterFormat() const
Definition: fmthdft.hxx:85
Subgroup headings.
Definition: poolfmt.hxx:261
Subgroup footer.
Definition: poolfmt.hxx:336
static bool CanEncode(OUString const &rString, rtl_TextEncoding const eEncoding)
sal_uInt8 rtl_TextEncodingToWinCharsetRTF(OUString const &rFontName, OUString const &rAltName, rtl_TextEncoding eTextEncoding)
MSOffice appears to set the charset of unicode fonts to MS 932.
Text body.
Definition: poolfmt.hxx:251
#define LANGUAGE_GERMAN_LIECHTENSTEIN
#define LANGUAGE_SPANISH_MEXICAN
bool IsNextPM(OUString const &rParams, sal_Int32 nPos)
const SvxPageUsage aArr[]
std::pair< C *, bool > StyleResult
static SwTwips CalcFtDist(const SwFrameFormat &rFormat)
SwDoc * GetDoc()
Definition: node.hxx:702
Internet normal.
Definition: poolfmt.hxx:121
Header Left&Right.
Definition: poolfmt.hxx:331
static SwTwips CalcHdFtDist(const SwFrameFormat &rFormat, sal_uInt16 nSpacing)
sal_uInt16 GetWhichOfScript(sal_uInt16 nWhich, sal_uInt16 nScript)
Definition: hints.cxx:195
sal_uInt16 GetDay() const
static OUString FindBestMSSubstituteFont(const OUString &rFont)
SvNumFormatType
sti
Definition: wwstyles.hxx:27
o3tl::sorted_vector< const C * > maUsedStyles
#define LANGUAGE_GERMAN_LUXEMBOURG
#define LANGUAGE_SPANISH_BOLIVIA
RES_POOL_CHRFMT_TYPE
Ranges for the IDs of the formats.
Definition: poolfmt.hxx:109
#define LANGUAGE_SPANISH_PUERTO_RICO
#define LANGUAGE_SPANISH_MODERN
CharRuns GetPseudoCharRuns(const SwTextNode &rTextNd)
Collect the ranges of Text which share.
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
SwTextFormatColl * GetParaStyle(SwDoc &rDoc, const OUString &rName)
Get a Paragraph Style which fits a given name.
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:80
#define LANGUAGE_PORTUGUESE_BRAZILIAN
Content 9th level.
Definition: poolfmt.hxx:392
const SvxULSpaceItem & GetULSpace(bool=true) const
Definition: frmatr.hxx:76
#define LANGUAGE_SPANISH_URUGUAY
#define LANGUAGE_FRENCH
#define LANGUAGE_SPANISH_COSTARICA
#define LANGUAGE_SPANISH_PERU
Make export a word section top/bottom values easy.
unsigned char sal_uInt8
sal_uInt8 rtl_TextEncodingToWinCharset(rtl_TextEncoding eTextEncoding)
MSOffice appears to set the charset of unicode fonts to MS 932.
sal_uInt32 DateTime2DTTM(const DateTime &rDT)
Convert from DTTM to Writer's DateTime.
#define SAL_INFO(area, stream)
OUString aName
Content 4th level.
Definition: poolfmt.hxx:378
#define LANGUAGE_DUTCH
std::pair< SwCharFormat *, bool > StyleResult
StyleResult StyleResult is a std::pair of a pointer to a style and a flag which is true if the style ...
Definition: msfilter.hxx:215
RES_POOL_COLLFMT_TYPE
Definition: poolfmt.hxx:245
Content 8th level.
Definition: poolfmt.hxx:391
FontMapExport(const OUString &rFontDescription)
StyleResult GetStyle(const OUString &rName, ww::sti eSti)
Get the writer style which the word style should map to.
QPRO_FUNC_TYPE nType
bool IsPlausableSingleWordSection(const SwFrameFormat &rTitleFormat, const SwFrameFormat &rFollowFormat)
See if two page formats can be expressed as a single word section.
Header, for PageFormats Client of FrameFormat describing the header.
Definition: fmthdft.hxx:33
constexpr TypedWhichId< SvxBoxItem > RES_BOX(106)
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
static sal_Int32 findUnquoted(const OUString &rParams, sal_Unicode cFind, sal_Int32 nFromPos)
Find cFind in rParams if not embedded in " double quotes.
#define LANGUAGE_FRENCH_LUXEMBOURG
OUString GetNextFontToken(const OUString &rTokenStr, sal_Int32 &rIndex)
constexpr TypedWhichId< SwFormatFooter > RES_FOOTER(97)
Line numbering.
Definition: poolfmt.hxx:126
#define LANGUAGE_FINNISH
Content 7th level.
Definition: poolfmt.hxx:390
#define LANGUAGE_SPANISH_PARAGUAY
Subgroup index tables.
Definition: poolfmt.hxx:367
#define LANGUAGE_FRENCH_BELGIAN
std::vector< CharRunEntry > CharRuns
Definition: msfilter.hxx:374
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:116
bool IsStarSymbol(const OUString &rFontName)
Frame is variable in Var-direction.
bool IsActive() const
Definition: fmthdft.hxx:58
void SwapQuotesInField(OUString &rFormat)
Another function used by MSDateTimeFormatToSwFormat.
long GetHeight() const
const SfxPoolItem * GetItem(sal_uInt16 nWhich, bool bSearchInParent=true) const
SwCharFormat * GetCharStyle(SwDoc &rDoc, const OUString &rName)
Get a Character Style which fits a given name.
#define LANGUAGE_JAPANESE
#define LANGUAGE_SPANISH_DATED
#define LANGUAGE_GERMAN_SWISS
constexpr TypedWhichId< SvxULSpaceItem > RES_UL_SPACE(92)
std::unique_ptr<::myImplHelpers::StyleMapperImpl< SwCharFormat > > mpImpl
Definition: msfilter.hxx:206
#define LANGUAGE_SPANISH_ARGENTINA
const SwFrameFormat * GetHeaderFormat() const
Definition: fmthdft.hxx:54
sal_uInt16 nPos
#define LANGUAGE_SPANISH_CHILE
bool anyOf(strong_int v) const
sal_uInt16 GetUpper() const
SwFrameSize GetHeightSizeType() const
Definition: fmtfsize.hxx:80
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:74
static bool replaceUnquoted(OUString &rParams, const OUString &rFind, const OUString &rReplace)
Find all rFind in rParams if not embedded in " double quotes and replace with rReplace.