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;
535  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
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::vector<DirEntry> DirChanges;
554 
555  typedef std::pair<sal_Int32, sal_uInt16> ScriptEntry;
556  typedef std::vector<ScriptEntry> ScriptChanges;
557 
558  DirChanges aDirChanges;
559  ScriptChanges aScripts;
560 
561  UBiDiDirection eDefaultDir = bParaIsRTL ? UBIDI_RTL : UBIDI_LTR;
562  UErrorCode nError = U_ZERO_ERROR;
563  UBiDi* pBidi = ubidi_openSized(rText.getLength(), 0, &nError);
564  ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(rText.getStr()), rText.getLength(),
565  static_cast< UBiDiLevel >(eDefaultDir), nullptr, &nError);
566 
567  sal_Int32 nCount = ubidi_countRuns(pBidi, &nError);
568  aDirChanges.reserve(nCount);
569 
570  int32_t nStart = 0;
571  int32_t nEnd;
572  UBiDiLevel nCurrDir;
573 
574  for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
575  {
576  ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir);
577  /*
578  UBiDiLevel is the type of the level values in this BiDi
579  implementation.
580 
581  It holds an embedding level and indicates the visual direction
582  by its bit 0 (even/odd value).
583 
584  The value for UBIDI_DEFAULT_LTR is even and the one for
585  UBIDI_DEFAULT_RTL is odd
586  */
587  aDirChanges.emplace_back(nEnd, nCurrDir & 0x1);
588  nStart = nEnd;
589  }
590  ubidi_close(pBidi);
591 
592  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
593 
594  sal_Int32 nLen = rText.getLength();
595  sal_Int32 nPos = 0;
596  while (nPos < nLen)
597  {
598  sal_Int32 nEnd2 = g_pBreakIt->GetBreakIter()->endOfScript(rText, nPos,
599  nScript);
600  if (nEnd2 < 0)
601  break;
602  nPos = nEnd2;
603  aScripts.emplace_back(nPos, nScript);
604  nScript = g_pBreakIt->GetBreakIter()->getScriptType(rText, nPos);
605  }
606 
607  auto aBiDiEnd = aDirChanges.cend();
608  auto aScriptEnd = aScripts.cend();
609 
610  auto aBiDiIter = aDirChanges.cbegin();
611  auto aScriptIter = aScripts.cbegin();
612 
613  bool bCharIsRTL = bParaIsRTL;
614 
615  while (
616  aBiDiIter != aBiDiEnd ||
617  aScriptIter != aScriptEnd
618  )
619  {
620  sal_Int32 nMinPos = rText.getLength();
621 
622  if (aBiDiIter != aBiDiEnd)
623  {
624  if (aBiDiIter->first < nMinPos)
625  nMinPos = aBiDiIter->first;
626  bCharIsRTL = aBiDiIter->second;
627  }
628 
629  if (aScriptIter != aScriptEnd)
630  {
631  if (aScriptIter->first < nMinPos)
632  nMinPos = aScriptIter->first;
633  nScript = aScriptIter->second;
634  }
635 
636  aRunChanges.emplace_back(nMinPos, nScript, eChrSet, bCharIsRTL);
637 
638  if (aBiDiIter != aBiDiEnd)
639  {
640  if (aBiDiIter->first == nMinPos)
641  ++aBiDiIter;
642  }
643 
644  if (aScriptIter != aScriptEnd)
645  {
646  if (aScriptIter->first == nMinPos)
647  ++aScriptIter;
648  }
649  }
650 
651  aRunChanges.erase(std::remove_if(aRunChanges.begin(),
652  aRunChanges.end(), myImplHelpers::IfBeforeStart(0/*nTextStart*/)), aRunChanges.end());
653 
654  return aRunChanges;
655  }
656  }
657 
658  namespace ms
659  {
660  sal_uInt8 rtl_TextEncodingToWinCharset(rtl_TextEncoding eTextEncoding)
661  {
662  sal_uInt8 nRet =
663  rtl_getBestWindowsCharsetFromTextEncoding(eTextEncoding);
664  switch (eTextEncoding)
665  {
666  case RTL_TEXTENCODING_DONTKNOW:
667  case RTL_TEXTENCODING_UCS2:
668  case RTL_TEXTENCODING_UTF7:
669  case RTL_TEXTENCODING_UTF8:
670  case RTL_TEXTENCODING_JAVA_UTF8:
671  nRet = 0x01;
672  break;
673  default:
674  break;
675  }
676  return nRet;
677  }
678 
679  static bool
680  CanEncode(OUString const& rString, rtl_TextEncoding const eEncoding)
681  {
682  OString tmp;
683  return rString.convertToString(&tmp, eEncoding,
684  RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
685  RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR);
686  }
687 
689  OUString const& rFontName, OUString const& rAltName,
690  rtl_TextEncoding eTextEncoding)
691  {
692  sal_uInt8 nRet =
693  rtl_getBestWindowsCharsetFromTextEncoding(eTextEncoding);
694  rtl_TextEncoding enc2 = rtl_getTextEncodingFromWindowsCharset(nRet);
695  if (!rtl_isOctetTextEncoding(enc2) /* check to avoid asserts */ ||
696  !(CanEncode(rFontName, enc2) && CanEncode(rAltName, enc2)))
697  {
698  static struct { rtl_TextEncoding enc; sal_uInt8 charset; }
699  const s_fallbacks [] = {
700  { RTL_TEXTENCODING_MS_932, 0x80 }, // Shift-JIS
701  { RTL_TEXTENCODING_MS_936, 0x86 }, // GB-2312
702  { RTL_TEXTENCODING_MS_950, 0x88 }, // Big5
703  { RTL_TEXTENCODING_MS_949, 0x81 }, // EUC-KR
704  };
705  for (const auto & i : s_fallbacks)
706  {
707  // fall back to a charset that can at least encode the
708  // font's name
709  if (CanEncode(rFontName, i.enc)
710  && CanEncode(rAltName, i.enc))
711  {
712  return i.charset;
713  }
714  }
715  SAL_INFO("sw.rtf", "no fallback charset found for font: "
716  << rFontName << " " << rAltName);
717  nRet = 0x01; // all hope lost: "default", whatever that is
718  }
719  return nRet;
720  }
721 
722  sal_uInt32 DateTime2DTTM( const DateTime& rDT )
723  {
724  /*
725  mint short :6 0000003F minutes (0-59)
726  hr short :5 000007C0 hours (0-23)
727  dom short :5 0000F800 days of month (1-31)
728  mon short :4 000F0000 months (1-12)
729  yr short :9 1FF00000 years (1900-2411)-1900
730  wdy short :3 E0000000 weekday(Sunday=0
731  Monday=1
732  ( wdy can be ignored ) Tuesday=2
733  Wednesday=3
734  Thursday=4
735  Friday=5
736  Saturday=6)
737  */
738 
739  if ( rDT.GetDate() == 0 )
740  return 0;
741  sal_uInt32 nDT = ( rDT.GetDayOfWeek() + 1 ) % 7;
742  nDT <<= 9;
743  nDT += ( rDT.GetYear() - 1900 ) & 0x1ff;
744  nDT <<= 4;
745  nDT += rDT.GetMonth() & 0xf;
746  nDT <<= 5;
747  nDT += rDT.GetDay() & 0x1f;
748  nDT <<= 5;
749  nDT += rDT.GetHour() & 0x1f;
750  nDT <<= 6;
751  nDT += rDT.GetMin() & 0x3f;
752  return nDT;
753  }
754 
755 
759  static sal_Int32 findUnquoted( const OUString& rParams, sal_Unicode cFind, sal_Int32 nFromPos )
760  {
761  const sal_Int32 nLen = rParams.getLength();
762  if (nFromPos < 0 || nLen <= nFromPos)
763  return -1;
764  for (sal_Int32 nI = nFromPos; nI < nLen; ++nI)
765  {
766  const sal_Unicode c = rParams[nI];
767  if (c == '\\')
768  ++nI;
769  else if (c == '\"')
770  {
771  ++nI;
772  // While not at the end and not at an unescaped end quote
773  while (nI < nLen)
774  {
775  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
776  break;
777  ++nI;
778  }
779  }
780  else //normal unquoted section
781  {
782  if (c == cFind)
783  return nI;
784  }
785  }
786  return -1;
787  }
788 
792  static bool replaceUnquoted( OUString& rParams, const OUString& rFind, const OUString& rReplace )
793  {
794  bool bReplaced = false;
795  if (rFind.isEmpty())
796  return bReplaced;
797  const sal_Unicode cFirst = rFind[0];
798 
799  sal_Int32 nLen = rParams.getLength();
800  for (sal_Int32 nI = 0; nI < nLen; ++nI)
801  {
802  const sal_Unicode c = rParams[nI];
803  if (rParams[nI] == '\\')
804  ++nI;
805  else if (rParams[nI] == '\"')
806  {
807  ++nI;
808  // While not at the end and not at an unescaped end quote
809  while (nI < nLen)
810  {
811  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
812  break;
813  ++nI;
814  }
815  }
816  else //normal unquoted section
817  {
818  if (c == cFirst && rParams.match( rFind, nI))
819  {
820  const sal_Int32 nFindLen = rFind.getLength();
821  const sal_Int32 nDiff = rReplace.getLength() - nFindLen;
822  rParams = rParams.replaceAt( nI, nFindLen, rReplace);
823  nI += nFindLen + nDiff - 1;
824  nLen += nDiff;
825  bReplaced = true;
826  }
827  }
828  }
829  return bReplaced;
830  }
831 
833  SvNumberFormatter *pFormatter, LanguageType &rLang, bool bHijri,
834  LanguageType nDocLang)
835  {
836  // tell the Formatter about the new entry
837  sal_Int32 nCheckPos = 0;
838  SvNumFormatType nType = SvNumFormatType::DEFINED;
839  sal_uInt32 nKey = 0;
840 
841  SwapQuotesInField(rParams);
842 
843  // Force to Japanese when finding one of 'geE'.
844  // XXX This actually may not be correct, all era keywords could be
845  // used in other locales as well. I just don't know about Word. But
846  // this is how it was for 10 years...
847  bool bForceJapanese = (-1 != findUnquoted( rParams, 'g', 0));
848  // XXX Why replace? The number formatter does handle them and this
849  // effectively changes from Gengou to Gregorian calendar. Legacy
850  // because it wasn't supported a decade ago and now moot? Or is
851  // that a Word specialty?
852  bForceJapanese |= replaceUnquoted( rParams, "ee", "yyyy");
853  bForceJapanese |= replaceUnquoted( rParams, "EE", "YYYY");
854  if (LANGUAGE_FRENCH != nDocLang)
855  {
856  // Handle the 'a' case here
857  sal_Int32 nLastPos = 0;
858  do
859  {
860  sal_Int32 nPos = findUnquoted( rParams, 'a', nLastPos + 1 );
861  bForceJapanese |= ( nPos != -1 && IsNotAM( rParams, nPos ) );
862  nLastPos = nPos;
863  } while ( -1 != nLastPos );
864  }
865 
866  // Force to NatNum when finding one of 'oOA'
867  bool bForceNatNum = replaceUnquoted( rParams, "o", "m")
868  || replaceUnquoted( rParams, "O", "M");
869  if (LANGUAGE_FRENCH != nDocLang)
870  {
871  // Handle the 'A' case here
872  sal_Int32 nLastPos = 0;
873  do
874  {
875  sal_Int32 nPos = findUnquoted( rParams, 'A', nLastPos + 1 );
876  bool bIsCharA = ( nPos != -1 && IsNotAM( rParams, nPos ) );
877  bForceNatNum |= bIsCharA;
878  if ( bIsCharA )
879  rParams = rParams.replaceAt( nPos, 1, "D" );
880  nLastPos = nPos;
881  } while ( -1 != nLastPos );
882  }
883 
884  sal_Int32 nLen = rParams.getLength();
885  for (sal_Int32 nI = 0; nI < nLen; ++nI)
886  {
887  if (rParams[nI] == '\\')
888  ++nI;
889  else if (rParams[nI] == '\"')
890  {
891  ++nI;
892  // While not at the end and not at an unescaped end quote
893  while (nI < nLen)
894  {
895  if (rParams[nI] == '\"' && rParams[nI-1] != '\\')
896  break;
897  ++nI;
898  }
899  }
900  else //normal unquoted section
901  {
902  sal_Unicode nChar = rParams[nI];
903 
904  // Change the localized word string to english
905  if ( nDocLang == LANGUAGE_FRENCH )
906  {
907  if ( ( nChar == 'a' || nChar == 'A' ) && IsNotAM(rParams, nI) )
908  rParams = rParams.replaceAt(nI, 1, "Y");
909  }
910  if (nChar == '/')
911  {
912  // MM: We have to escape '/' in case it's used as a char.
913  // But not if it's a '/' inside AM/PM
914  if (!(IsPreviousAM(rParams, nI) && IsNextPM(rParams, nI)))
915  {
916  rParams = rParams.replaceAt(nI, 1, "\\/");
917  nLen++;
918  }
919  nI++;
920  }
921 
922  // Deal with language differences in date format expression.
923  // Should be made with i18n framework.
924  // The list of the mappings and of those "special" locales is to be found at:
925  // http://l10n.openoffice.org/i18n_framework/LocaleData.html
926  if ( !bForceJapanese && !bForceNatNum )
927  {
928  // Convert to the localized equivalent for OOo
929  if ( rLang == LANGUAGE_FINNISH )
930  {
931  if (nChar == 'y' || nChar == 'Y')
932  rParams = rParams.replaceAt(nI, 1, "V");
933  else if (nChar == 'm' || nChar == 'M')
934  rParams = rParams.replaceAt(nI, 1, "K");
935  else if (nChar == 'd' || nChar == 'D')
936  rParams = rParams.replaceAt(nI, 1, "P");
937  else if (nChar == 'h' || nChar == 'H')
938  rParams = rParams.replaceAt(nI, 1, "T");
939  }
940  else if ( rLang.anyOf(
947  {
948  if (nChar == 'h' || nChar == 'H')
949  rParams = rParams.replaceAt(nI, 1, "T");
950  }
951  else if ( rLang.anyOf(
974  {
975  if (nChar == 'a' || nChar == 'A')
976  rParams = rParams.replaceAt(nI, 1, "O");
977  else if (nChar == 'y' || nChar == 'Y')
978  rParams = rParams.replaceAt(nI, 1, "A");
979  }
980  else if ( rLang.anyOf(
983  {
984  if (nChar == 'y' || nChar == 'Y')
985  rParams = rParams.replaceAt(nI, 1, "J");
986  else if (nChar == 'u' || nChar == 'U')
987  rParams = rParams.replaceAt(nI, 1, "H");
988  }
989  else if ( rLang.anyOf(
992  {
993  if (nChar == 'a' || nChar == 'A')
994  rParams = rParams.replaceAt(nI, 1, "O");
995  else if (nChar == 'g' || nChar == 'G')
996  rParams = rParams.replaceAt(nI, 1, "X");
997  else if (nChar == 'y' || nChar == 'Y')
998  rParams = rParams.replaceAt(nI, 1, "A");
999  else if (nChar == 'd' || nChar == 'D')
1000  rParams = rParams.replaceAt(nI, 1, "G");
1001  }
1002  else if ( rLang.anyOf(
1008  {
1009  if (nChar == 'y' || nChar == 'Y')
1010  rParams = rParams.replaceAt(nI, 1, "J");
1011  else if (nChar == 'd' || nChar == 'D')
1012  rParams = rParams.replaceAt(nI, 1, "T");
1013  }
1014  else if ( rLang.anyOf(
1021  {
1022  if (nChar == 'y' || nChar == 'Y' || nChar == 'a')
1023  rParams = rParams.replaceAt(nI, 1, "A");
1024  else if (nChar == 'd' || nChar == 'D' || nChar == 'j')
1025  rParams = rParams.replaceAt(nI, 1, "J");
1026  }
1027  }
1028  }
1029  }
1030 
1031  if (bForceNatNum)
1032  bForceJapanese = true;
1033 
1034  if (bForceJapanese)
1035  rLang = LANGUAGE_JAPANESE;
1036 
1037  if (bForceNatNum)
1038  rParams = "[NatNum1][$-411]" + rParams;
1039 
1040  if (bHijri)
1041  rParams = "[~hijri]" + rParams;
1042 
1043  pFormatter->PutEntry(rParams, nCheckPos, nType, nKey, rLang);
1044 
1045  return nKey;
1046  }
1047 
1048  bool IsPreviousAM(OUString const & rParams, sal_Int32 nPos)
1049  {
1050  return nPos>=2 && rParams.matchIgnoreAsciiCase("am", nPos-2);
1051  }
1052  bool IsNextPM(OUString const & rParams, sal_Int32 nPos)
1053  {
1054  return nPos+2<rParams.getLength() && rParams.matchIgnoreAsciiCase("pm", nPos+1);
1055  }
1056  bool IsNotAM(OUString const & rParams, sal_Int32 nPos)
1057  {
1058  ++nPos;
1059  return nPos>=rParams.getLength() || (rParams[nPos]!='M' && rParams[nPos]!='m');
1060  }
1061 
1062  void SwapQuotesInField(OUString &rFormat)
1063  {
1064  //Swap unescaped " and ' with ' and "
1065  const sal_Int32 nLen = rFormat.getLength();
1066  for (sal_Int32 nI = 0; nI < nLen; ++nI)
1067  {
1068  if (!nI || rFormat[nI-1]!='\\')
1069  {
1070  if (rFormat[nI]=='\"')
1071  rFormat = rFormat.replaceAt(nI, 1, "\'");
1072  else if (rFormat[nI]=='\'')
1073  rFormat = rFormat.replaceAt(nI, 1, "\"");
1074  }
1075  }
1076  }
1077 
1078  }
1079 }
1080 
1081 /* 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:186
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:1610
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
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:375
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.