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