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