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