LibreOffice Module sw (master)  1
ww8par5.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 <config_features.h>
21 #include <config_fuzzers.h>
22 
23 #include <sal/types.h>
24 #include <tools/solar.h>
26 #include <comphelper/string.hxx>
28 #include <com/sun/star/embed/XStorage.hpp>
29 #include <com/sun/star/embed/ElementModes.hpp>
30 #include <com/sun/star/embed/XTransactedObject.hpp>
31 #include <com/sun/star/task/InteractionHandler.hpp>
32 
33 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
34 #include <svl/cintitem.hxx>
35 #include <svl/lngmisc.hxx>
36 #include <svl/urihelper.hxx>
37 #include <svl/numformat.hxx>
38 #include <svl/zforlist.hxx>
39 #include <svl/zformat.hxx>
40 #include <sfx2/linkmgr.hxx>
41 #include <rtl/character.hxx>
42 #include <unotools/charclass.hxx>
43 
44 #include <ucbhelper/content.hxx>
46 
47 #include <com/sun/star/i18n/XBreakIterator.hpp>
48 #include <hintids.hxx>
49 #include <editeng/fontitem.hxx>
50 #include <editeng/fhgtitem.hxx>
51 #include <editeng/langitem.hxx>
52 #include <fmtfld.hxx>
53 #include <fmtanchr.hxx>
54 #include <pam.hxx>
55 #include <doc.hxx>
57 #include <IDocumentMarkAccess.hxx>
58 #include <IDocumentState.hxx>
59 #include <flddat.hxx>
60 #include <docufld.hxx>
61 #include <reffld.hxx>
62 #include <IMark.hxx>
63 #include <expfld.hxx>
64 #include <dbfld.hxx>
65 #include <tox.hxx>
66 #include <section.hxx>
67 #include <ndtxt.hxx>
68 #include <fmtinfmt.hxx>
69 #include <chpfld.hxx>
70 #include <fmtruby.hxx>
71 #include <charfmt.hxx>
72 #include <breakit.hxx>
73 #include <fmtclds.hxx>
74 #include <poolfmt.hxx>
75 #include <SwStyleNameMapper.hxx>
76 
77 #include "ww8scan.hxx"
78 #include "ww8par.hxx"
79 #include "writerhelper.hxx"
80 #include <o3tl/safeint.hxx>
81 #include <o3tl/string_view.hxx>
82 #include <unotools/fltrcfg.hxx>
83 #include <xmloff/odffields.hxx>
84 #include <osl/diagnose.h>
85 
86 #include <algorithm>
87 #include <string_view>
88 
89 #define MAX_FIELDLEN 64000
90 
91 #define WW8_TOX_LEVEL_DELIM ':'
92 
93 using namespace ::com::sun::star;
94 using namespace msfilter::util;
95 using namespace sw::util;
96 using namespace sw::mark;
97 using namespace nsSwDocInfoSubType;
98 
99 // Bookmarks
100 namespace
101 {
102  // #120879# - helper method to identify a bookmark name to match the internal TOC bookmark naming convention
103  bool IsTOCBookmarkName(std::u16string_view rName)
104  {
105  return o3tl::starts_with(rName, u"_Toc") || o3tl::starts_with(rName, OUStringConcatenation(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()+"_Toc"));
106  }
107 
108  OUString EnsureTOCBookmarkName(const OUString& rName)
109  {
110  OUString sTmp = rName;
111  if ( IsTOCBookmarkName ( rName ) )
112  {
115  }
116  return sTmp;
117  }
118 }
119 
121 {
122  // should also work via pRes.nCo2OrIdx
123  WW8PLCFx_Book* pB = m_xPlcxMan->GetBook();
124  if( !pB )
125  {
126  OSL_ENSURE( pB, "WW8PLCFx_Book - Pointer does not exist" );
127  return 0;
128  }
129 
130  eBookStatus eB = pB->GetStatus();
131  if (eB & BOOK_IGNORE)
132  return 0; // ignore bookmark
133 
134  if (pB->GetIsEnd())
135  {
136  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
137  pB->GetHandle(), (eB & BOOK_FIELD)!=0);
138  return 0;
139  }
140 
141  // "_Hlt*" are unnecessary
142  const OUString* pName = pB->GetName();
143  // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available.
144  // So the hidden bookmarks inside for hyperlink jumping also should be kept.
145  if ( !pName ||
146  pName->startsWithIgnoreAsciiCase( "_Hlt" ) )
147  {
148  return 0;
149  }
150 
151  // do NOT call ToUpper as the bookmark name can also be a hyperlink target!
152 
153  OUString aVal;
154  if( SwFltGetFlag( m_nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
155  {
156  // set variable for translation bookmark
157  tools::Long nLen = pB->GetLen();
158  if( nLen > MAX_FIELDLEN )
159  nLen = MAX_FIELDLEN;
160 
161  sal_uInt64 nOldPos = m_pStrm->Tell();
162  m_xSBase->WW8ReadString( *m_pStrm, aVal, pB->GetStartPos(), nLen,
163  m_eStructCharSet );
164  m_pStrm->Seek( nOldPos );
165 
166  // now here the implementation of the old "QuoteString" and
167  // I hope with a better performance as before. It's also only
168  // needed if the filterflags say we will convert bookmarks
169  // to SetExpFields! And this the exception!
170 
171  bool bSetAsHex;
172  bool bAllowCr = SwFltGetFlag(m_nFieldFlags,
174 
175  for( sal_Int32 nI = 0;
176  nI < aVal.getLength() && aVal.getLength() < (MAX_FIELDLEN - 4);
177  ++nI )
178  {
179  const sal_Unicode cChar = aVal[nI];
180  switch( cChar )
181  {
182  case 0x0b:
183  case 0x0c:
184  case 0x0d:
185  if( bAllowCr )
186  {
187  aVal = aVal.replaceAt( nI, 1, u"\n" );
188  bSetAsHex = false;
189  }
190  else
191  bSetAsHex = true;
192  break;
193 
194  case 0xFE:
195  case 0xFF:
196  bSetAsHex = true;
197  break;
198 
199  default:
200  bSetAsHex = 0x20 > cChar;
201  break;
202  }
203 
204  if( bSetAsHex )
205  {
206  //all Hex-Numbers with \x before
207  OUString sTmp( "\\x" );
208  if( cChar < 0x10 )
209  sTmp += "0";
210  sTmp += OUString::number( cChar, 16 );
211  aVal = aVal.replaceAt( nI, 1 , sTmp );
212  nI += sTmp.getLength() - 1;
213  }
214  }
215 
216  if ( aVal.getLength() > (MAX_FIELDLEN - 4))
217  aVal = aVal.copy( 0, MAX_FIELDLEN - 4 );
218  }
219 
220  //e.g. inserting bookmark around field result, so we need to put
221  //it around the entire writer field, as we don't have the separation
222  //of field and field result of word, see #i16941#
223  SwPosition aStart(*m_pPaM->GetPoint());
224  if (!m_aFieldStack.empty())
225  {
226  const WW8FieldEntry &rTest = m_aFieldStack.back();
227  aStart = rTest.maStartPos;
228  }
229 
230  const OUString sOrigName = BookmarkToWriter(*pName);
231  m_xReffedStck->NewAttr( aStart,
232  SwFltBookmark( EnsureTOCBookmarkName( sOrigName ), aVal, pB->GetHandle(), IsTOCBookmarkName( sOrigName ) ));
233  return 0;
234 }
235 
237 {
238  if (WW8PLCFx_AtnBook* pAtnBook = m_xPlcxMan->GetAtnBook())
239  {
240  if (pAtnBook->getIsEnd())
241  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_ANNOTATIONMARK, true, pAtnBook->getHandle());
242  else
243  m_xReffedStck->NewAttr(*m_pPaM->GetPoint(), CntUInt16Item(RES_FLTR_ANNOTATIONMARK, pAtnBook->getHandle()));
244  }
245  return 0;
246 }
247 
249 {
250  if (WW8PLCFx_FactoidBook* pFactoidBook = m_xPlcxMan->GetFactoidBook())
251  {
252  if (pFactoidBook->getIsEnd())
253  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_RDFMARK, true, pFactoidBook->getHandle());
254  else
255  {
256  SwFltRDFMark aMark;
257  aMark.SetHandle(pFactoidBook->getHandle());
258  GetSmartTagInfo(aMark);
259  m_xReffedStck->NewAttr(*m_pPaM->GetPoint(), aMark);
260  }
261  }
262  return 0;
263 }
264 
265 // general help methods to separate parameters
266 
269 OUString SwWW8ImplReader::ConvertFFileName(const OUString& rOrg)
270 {
271  OUString aName = rOrg.replaceAll("\\\\", "\\");
272  aName = aName.replaceAll("%20", " ");
273 
274  // remove attached quotation marks
275  if (aName.endsWith("\""))
276  aName = aName.copy(0, aName.getLength()-1);
277 
278  // Need the more sophisticated url converter.
279  if (!aName.isEmpty())
280  aName = URIHelper::SmartRel2Abs(
281  INetURLObject(m_sBaseURL), aName, Link<OUString *, bool>(), false);
282 
283  return aName;
284 }
285 
286 namespace
287 {
290  void ConvertUFName( OUString& rName )
291  {
292  rName = GetAppCharClass().uppercase( rName );
293  }
294 }
295 
296 static void lcl_ConvertSequenceName(OUString& rSequenceName)
297 {
298  ConvertUFName(rSequenceName);
299  if ('0' <= rSequenceName[0] && '9' >= rSequenceName[0])
300  rSequenceName = "_" + rSequenceName;
301 }
302 
303 // FindParaStart() finds 1st Parameter that follows '\' and cToken
304 // and returns start of this parameter or -1
305 static sal_Int32 FindParaStart( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
306 {
307  bool bStr = false; // ignore inside a string
308 
309  for( sal_Int32 nBuf = 0; nBuf+1 < rStr.getLength(); nBuf++ )
310  {
311  if( rStr[ nBuf ] == '"' )
312  bStr = !bStr;
313 
314  if( !bStr
315  && rStr[ nBuf ] == '\\'
316  && ( rStr[ nBuf + 1 ] == cToken
317  || rStr[ nBuf + 1 ] == cToken2 ) )
318  {
319  nBuf += 2;
320  // skip spaces between cToken and its parameters
321  while( nBuf < rStr.getLength()
322  && rStr[ nBuf ] == ' ' )
323  nBuf++;
324  // return start of parameters
325  return nBuf < rStr.getLength() ? nBuf : -1;
326  }
327  }
328  return -1;
329 }
330 
331 // FindPara() finds the first parameter including '\' and cToken.
332 // A new String will be allocated (has to be deallocated by the caller)
333 // and everything that is part of the parameter will be returned.
334 static OUString FindPara( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
335 {
336  sal_Int32 n2; // end
337  sal_Int32 n = FindParaStart( rStr, cToken, cToken2 ); // start
338  if( n == -1)
339  return OUString();
340 
341  if( rStr[ n ] == '"'
342  || rStr[ n ] == 132 )
343  { // Quotationmark in front of parameter
344  n++; // Skip quotationmark
345  n2 = n; // search for the end starting from here
346  while( n2 < rStr.getLength()
347  && rStr[ n2 ] != 147
348  && rStr[ n2 ] != '"' )
349  n2++; // search end of parameter
350  }
351  else
352  { // no quotationmarks
353  n2 = n; // search for the end starting from here
354  while( n2 < rStr.getLength()
355  && rStr[ n2 ] != ' ' )
356  n2++; // search end of parameter
357  }
358  return rStr.copy( n, n2-n );
359 }
360 
361 static SvxNumType GetNumTypeFromName(const OUString& rStr,
362  bool bAllowPageDesc = false)
363 {
364  SvxNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
365  if (rStr.isEmpty())
366  return eTyp;
367 
368  if( rStr.startsWithIgnoreAsciiCase( "Arabi" ) ) // Arabisch, Arabic
369  eTyp = SVX_NUM_ARABIC;
370  else if( rStr.startsWith( "misch" ) ) // r"omisch
371  eTyp = SVX_NUM_ROMAN_LOWER;
372  else if( rStr.startsWith( "MISCH" ) ) // R"OMISCH
373  eTyp = SVX_NUM_ROMAN_UPPER;
374  else if( rStr.startsWithIgnoreAsciiCase( "alphabeti" ) )// alphabetisch, alphabetic
375  eTyp = ( rStr[0] == 'A' )
378  else if( rStr.startsWithIgnoreAsciiCase( "roman" ) ) // us
379  eTyp = ( rStr[0] == 'R' )
382  return eTyp;
383 }
384 
385 static SvxNumType GetNumberPara(const OUString& rStr, bool bAllowPageDesc = false)
386 {
387  OUString s( FindPara( rStr, '*', '*' ) ); // Type of number
388  SvxNumType aType = GetNumTypeFromName( s, bAllowPageDesc );
389  return aType;
390 }
391 
393 {
394  bool bRet(false);
395 
396  const SvxLanguageItem *pLang =
397  static_cast<const SvxLanguageItem*>(GetFormatAttr(RES_CHRATR_LANGUAGE));
398  OSL_ENSURE(pLang, "impossible");
399  LanguageType nDefault = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
400 
401  if (nLang != nDefault)
402  {
403  rField.SetAutomaticLanguage(false);
404  rField.SetLanguage(nLang);
405  bRet = true;
406  }
407 
408  return bRet;
409 }
410 
412 {
413  //Get the system date in the correct final language layout, convert to
414  //a known language and modify the 2 digit year part to be 4 digit, and
415  //convert back to the correct language layout.
416  const sal_uInt32 nIndex = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, nLang);
417 
418  SvNumberformat aFormat = *(pFormatter->GetEntry(nIndex));
419  aFormat.ConvertLanguage(*pFormatter, nLang, LANGUAGE_ENGLISH_US);
420 
421  OUString sParams(aFormat.GetFormatstring());
422  // #i36594#
423  // Fix provided by mloiseleur@openoffice.org.
424  // A default date can have already 4 year digits, in some case
425  const sal_Int32 pos = sParams.indexOf("YYYY");
426  if ( pos == -1 )
427  {
428  sParams = sParams.replaceFirst("YY", "YYYY");
429  }
430  return sParams;
431 }
432 
433 SvNumFormatType SwWW8ImplReader::GetTimeDatePara(OUString const & rStr, sal_uInt32& rFormat,
434  LanguageType &rLang, int nWhichDefault, bool bHijri)
435 {
436  bool bRTL = false;
437  if (m_xPlcxMan && !m_bVer67)
438  {
439  SprmResult aResult = m_xPlcxMan->HasCharSprm(0x85A);
440  if (aResult.pSprm && aResult.nRemainingData >= 1 && *aResult.pSprm)
441  bRTL = true;
442  }
443  sal_uInt16 eLang = bRTL ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
444  const SvxLanguageItem *pLang = static_cast<const SvxLanguageItem*>(GetFormatAttr(eLang));
445  OSL_ENSURE(pLang, "impossible");
446  rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
447 
449  OUString sParams( FindPara( rStr, '@', '@' ) );// Date/Time
450  if (sParams.isEmpty())
451  {
452  bool bHasTime = false;
453  switch (nWhichDefault)
454  {
455  case ww::ePRINTDATE:
456  case ww::eSAVEDATE:
457  sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
458  sParams += " HH:MM:SS AM/PM";
459  bHasTime = true;
460  break;
461  case ww::eCREATEDATE:
462  sParams += "DD/MM/YYYY HH:MM:SS";
463  bHasTime = true;
464  break;
465  default:
466  case ww::eDATE:
467  sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
468  break;
469  }
470 
471  if (bHijri)
472  sParams = "[~hijri]" + sParams;
473 
474  sal_Int32 nCheckPos = 0;
475  SvNumFormatType nType = SvNumFormatType::DEFINED;
476  rFormat = 0;
477 
478  OUString sTemp(sParams);
479  pFormatter->PutandConvertEntry(sTemp, nCheckPos, nType, rFormat,
480  LANGUAGE_ENGLISH_US, rLang, false);
481  sParams = sTemp;
482 
483  return bHasTime ? SvNumFormatType::DATETIME : SvNumFormatType::DATE;
484  }
485 
486  sal_uLong nFormatIdx =
487  sw::ms::MSDateTimeFormatToSwFormat(sParams, pFormatter, rLang, bHijri,
488  GetFib().m_lid);
489  SvNumFormatType nNumFormatType = SvNumFormatType::UNDEFINED;
490  if (nFormatIdx)
491  nNumFormatType = pFormatter->GetType(nFormatIdx);
492  rFormat = nFormatIdx;
493 
494  return nNumFormatType;
495 }
496 
497 // Fields
498 
499 // Update respective fields after loading (currently references)
501 {
503  m_rDoc.SetInitDBFields(true); // Also update fields in the database
504 }
505 
507 {
508  sal_uInt16 nRet = 0;
509  WW8PLCFx_FLD* pF = m_xPlcxMan->GetField();
510  OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer not available");
511  WW8_CP nCP = 0;
512  if (!pF || !pF->EndPosIsFieldEnd(nCP))
513  return nRet;
514 
515  const SvtFilterOptions &rOpt = SvtFilterOptions::Get();
516  bool bUseEnhFields = rOpt.IsUseEnhancedFields();
517 
518  OSL_ENSURE(!m_aFieldStack.empty(), "Empty field stack");
519  if (!m_aFieldStack.empty())
520  {
521  /*
522  only hyperlinks currently need to be handled like this, for the other
523  cases we have inserted a field not an attribute with an unknown end
524  point
525  */
526  nRet = m_aFieldStack.back().mnFieldId;
527  switch (nRet)
528  {
529  case ww::eFORMTEXT:
530  if (bUseEnhFields && m_pPaM!=nullptr && m_pPaM->GetPoint()!=nullptr) {
531  SwPosition aEndPos = *m_pPaM->GetPoint();
532  SwPaM aFieldPam( m_aFieldStack.back().GetPtNode(), m_aFieldStack.back().GetPtContent(), aEndPos.nNode, aEndPos.nContent.GetIndex());
534  IFieldmark *pFieldmark = pMarksAccess->makeFieldBookmark(
535  aFieldPam, m_aFieldStack.back().GetBookmarkName(), ODF_FORMTEXT,
536  aFieldPam.Start() /*same pos as start!*/ );
537  OSL_ENSURE(pFieldmark!=nullptr, "hmmm; why was the bookmark not created?");
538  if (pFieldmark!=nullptr) {
539  // adapt redline positions to inserted field mark start
540  // dummy char (assume not necessary for end dummy char)
541  m_xRedlineStack->MoveAttrsFieldmarkInserted(*aFieldPam.Start());
542  const IFieldmark::parameter_map_t& rParametersToAdd = m_aFieldStack.back().getParameters();
543  pFieldmark->GetParameters()->insert(rParametersToAdd.begin(), rParametersToAdd.end());
544  }
545  }
546  break;
547  // Doing corresponding status management for TOX field, index field, hyperlink field and page reference field
548  case ww::eTOC://TOX
549  case ww::eINDEX://index
550  if (m_bLoadingTOXCache)
551  {
552  if (m_nEmbeddedTOXLevel > 0)
553  {
554  JoinNode(*m_pPaM);
555  --m_nEmbeddedTOXLevel;
556  }
557  else
558  {
559  m_aTOXEndCps.insert(nCP);
560  m_bLoadingTOXCache = false;
561  if ( m_pPaM->End() &&
562  m_pPaM->End()->nNode.GetNode().GetTextNode() &&
563  m_pPaM->End()->nNode.GetNode().GetTextNode()->Len() == 0 )
564  {
565  JoinNode(*m_pPaM);
566  }
567  else
568  {
569  m_bCareLastParaEndInToc = true;
570  }
571 
572  if (m_pPosAfterTOC)
573  {
574  *m_pPaM = *m_pPosAfterTOC;
575  m_pPosAfterTOC.reset();
576  }
577  }
578  }
579  break;
580  case ww::ePAGEREF: //REF
581  if (m_bLoadingTOXCache && !m_bLoadingTOXHyperlink)
582  {
583  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(),RES_TXTATR_INETFMT);
584  }
585  break;
586  case ww::eHYPERLINK:
587  if (m_bLoadingTOXHyperlink)
588  m_bLoadingTOXHyperlink = false;
589  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_TXTATR_INETFMT);
590  break;
591  case ww::eMERGEINC:
592  case ww::eINCLUDETEXT:
593  {
594  //Move outside the section associated with this type of field
595  SwPosition aRestorePos(m_aFieldStack.back().maStartPos);
596 
597  SwContentNode* pNd = aRestorePos.nNode.GetNode().GetContentNode();
598  sal_Int32 nMaxValidIndex = pNd ? pNd->Len() : 0;
599  if (aRestorePos.nContent.GetIndex() > nMaxValidIndex)
600  {
601  SAL_WARN("sw.ww8", "Attempt to restore to invalid content position");
602  aRestorePos.nContent.Assign(pNd, nMaxValidIndex);
603  }
604 
605  *m_pPaM->GetPoint() = aRestorePos;
606  break;
607  }
608  case ww::eIF: // IF-field
609  {
610  // conditional field parameters
611  const OUString& fieldDefinition = m_aFieldStack.back().GetBookmarkCode();
612 
613  OUString paramCondition;
614  OUString paramTrue;
615  OUString paramFalse;
616 
617  SwHiddenTextField::ParseIfFieldDefinition(fieldDefinition, paramCondition, paramTrue, paramFalse);
618 
619  // create new field
621  SwHiddenTextField aHTField(
622  static_cast<SwHiddenTextFieldType*>(pFieldType),
623  paramCondition,
624  paramTrue,
625  paramFalse,
627 
628  // insert new field into document
630  break;
631  }
632  default:
633  OUString aCode = m_aFieldStack.back().GetBookmarkCode();
634  if (!aCode.isEmpty() && !o3tl::starts_with(o3tl::trim(aCode), u"SHAPE"))
635  {
636  // Unhandled field with stored code
637  SwPosition aEndPos = *m_pPaM->GetPoint();
638  SwPaM aFieldPam(
639  m_aFieldStack.back().GetPtNode(), m_aFieldStack.back().GetPtContent(),
640  aEndPos.nNode, aEndPos.nContent.GetIndex());
641 
643 
644  IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
645  aFieldPam,
646  m_aFieldStack.back().GetBookmarkName(),
648  aFieldPam.Start() /*same pos as start!*/ );
649  if ( pFieldmark )
650  {
651  // adapt redline positions to inserted field mark start
652  // dummy char (assume not necessary for end dummy char)
653  m_xRedlineStack->MoveAttrsFieldmarkInserted(*aFieldPam.Start());
654  const IFieldmark::parameter_map_t& rParametersToAdd = m_aFieldStack.back().getParameters();
655  pFieldmark->GetParameters()->insert(rParametersToAdd.begin(), rParametersToAdd.end());
656  OUString sFieldId = OUString::number( m_aFieldStack.back().mnFieldId );
657  pFieldmark->GetParameters()->insert(
658  std::pair< OUString, uno::Any > (
659  ODF_ID_PARAM,
660  uno::Any( sFieldId ) ) );
661  pFieldmark->GetParameters()->insert(
662  std::pair< OUString, uno::Any > (
664  uno::Any( aCode ) ) );
665 
666  if ( m_aFieldStack.back().mnObjLocFc > 0 )
667  {
668  // Store the OLE object as an internal link
669  OUString sOleId = "_" +
670  OUString::number( m_aFieldStack.back().mnObjLocFc );
671 
673  tools::SvRef<SotStorage> xSrc1 = xSrc0->OpenSotStorage( sOleId, StreamMode::READ );
674 
675  // Store it now!
676  uno::Reference< embed::XStorage > xDocStg = GetDoc().GetDocStorage();
677  if (xDocStg.is())
678  {
679  uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
680  "OLELinks", embed::ElementModes::WRITE );
681  tools::SvRef<SotStorage> xObjDst = SotStorage::OpenOLEStorage( xOleStg, sOleId );
682 
683  if ( xObjDst.is() )
684  {
685  xSrc1->CopyTo( xObjDst.get() );
686 
687  if ( !xObjDst->GetError() )
688  xObjDst->Commit();
689  }
690 
691  uno::Reference< embed::XTransactedObject > xTransact( xOleStg, uno::UNO_QUERY );
692  if ( xTransact.is() )
693  xTransact->commit();
694  }
695 
696  // Store the OLE Id as a parameter
697  pFieldmark->GetParameters()->insert(
698  std::pair< OUString, uno::Any >(
699  ODF_OLE_PARAM, uno::Any( sOleId ) ) );
700  }
701  }
702  }
703 
704  break;
705  }
706  m_aFieldStack.pop_back();
707  }
708  return nRet;
709 }
710 
711 static bool AcceptableNestedField(sal_uInt16 nFieldCode)
712 {
713  switch (nFieldCode)
714  {
715  case ww::eINDEX: // allow recursive field in TOC...
716  case ww::eTOC: // allow recursive field in TOC...
717  case ww::eMERGEINC:
718  case ww::eINCLUDETEXT:
719  case ww::eAUTOTEXT:
720  case ww::eHYPERLINK:
721  // Accept AutoTextList field as nested field.
722  // Thus, the field result is imported as plain text.
723  case ww::eAUTOTEXTLIST:
724  // tdf#129247 CONTROL contains a nested SHAPE field in the result
725  case ww::eCONTROL:
726  return true;
727  default:
728  return false;
729  }
730 }
731 
732 WW8FieldEntry::WW8FieldEntry(SwPosition const &rPos, sal_uInt16 nFieldId) noexcept
733  : maStartPos(rPos), mnFieldId(nFieldId), mnObjLocFc(0)
734 {
735 }
736 
738  : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId), mnObjLocFc(rOther.mnObjLocFc)
739 {
740 }
741 
742 void WW8FieldEntry::Swap(WW8FieldEntry &rOther) noexcept
743 {
744  std::swap(maStartPos, rOther.maStartPos);
745  std::swap(mnFieldId, rOther.mnFieldId);
746 }
747 
749 {
750  WW8FieldEntry aTemp(rOther);
751  Swap(aTemp);
752  return *this;
753 }
754 
755 
756 void WW8FieldEntry::SetBookmarkName(const OUString& bookmarkName)
757 {
758  msBookmarkName=bookmarkName;
759 }
760 
761 void WW8FieldEntry::SetBookmarkType(const OUString& bookmarkType)
762 {
763  msMarkType=bookmarkType;
764 }
765 
766 void WW8FieldEntry::SetBookmarkCode(const OUString& bookmarkCode)
767 {
768  msMarkCode = bookmarkCode;
769 }
770 
771 
772 // Read_Field reads a field or returns 0 if the field cannot be read,
773 // so that the calling function reads the field in text format.
774 // Returnvalue: Total length of field
776 {
777  typedef eF_ResT (SwWW8ImplReader::*FNReadField)( WW8FieldDesc*, OUString& );
778  enum Limits {eMax = 96};
779  static const FNReadField aWW8FieldTab[eMax+1] =
780  {
781  nullptr,
783  nullptr,
785  nullptr,
786  nullptr,
788  nullptr,
790  nullptr,
792  nullptr,
815  nullptr,
816  nullptr,
821  nullptr,
823  nullptr,
824  nullptr,
826  nullptr,
827  nullptr,
828  nullptr,
829  nullptr,
831  nullptr,
836  nullptr,
837 
838  nullptr, // 56
839 
843  nullptr,
844  nullptr,
845  nullptr,
846  nullptr,
847  &SwWW8ImplReader::Read_F_DocInfo, // 64 - DOCVARIABLE
848  nullptr,
849  nullptr,
852  nullptr,
856  nullptr, /*&SwWW8ImplReader::Read_F_Tox*/
857  nullptr,
858  nullptr,
859  nullptr,
860  nullptr,
861  nullptr,
862  nullptr,
863  nullptr,
864  nullptr,
865  nullptr,
867  nullptr, // 84
869  nullptr, // 86
872  nullptr, // 89
873  nullptr, // 90
875  nullptr, // 92
876  nullptr, // 93
877  nullptr, // 94
879  nullptr // eMax - Dummy empty method
880  };
881  OSL_ENSURE( SAL_N_ELEMENTS( aWW8FieldTab ) == eMax+1, "FieldFunc table not right" );
882 
883  WW8PLCFx_FLD* pF = m_xPlcxMan->GetField();
884  OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer not available");
885 
886  if (!pF || !pF->StartPosIsFieldStart())
887  return 0;
888 
889  bool bNested = false;
890  if (!m_aFieldStack.empty())
891  {
892  bNested = std::any_of(m_aFieldStack.cbegin(), m_aFieldStack.cend(),
893  [](const WW8FieldEntry& aField) { return !AcceptableNestedField(aField.mnFieldId); });
894  }
895 
896  WW8FieldDesc aF;
897  bool bOk = pF->GetPara(pRes->nCp2OrIdx, aF);
898 
899  OSL_ENSURE(bOk, "WW8: Bad Field!");
900  if (aF.nId == 33) aF.bCodeNest=false; // do not recurse into nested page fields
901  bool bCodeNest = aF.bCodeNest;
902  if ( aF.nId == 6 ) bCodeNest = false; // We can handle them and lose the inner data
903  if (aF.nId == 70) bCodeNest = false; // need to import 0x01 in FORMTEXT
904 
905  m_aFieldStack.emplace_back(*m_pPaM->GetPoint(), aF.nId);
906 
907  if (bNested)
908  return 0;
909 
910  sal_uInt16 n = (aF.nId <= eMax) ? aF.nId : o3tl::narrowing<sal_uInt16>(eMax);
911  sal_uInt16 nI = n / 32; // # of sal_uInt32
912  sal_uInt32 nMask = 1 << ( n % 32 ); // Mask for bits
913 
914  if (SAL_N_ELEMENTS(m_nFieldTagAlways) <= nI)
915  { // if indexes larger than 95 are needed, then a new configuration
916  // item has to be added, and nFieldTagAlways/nFieldTagBad expanded!
917  return aF.nLen;
918  }
919 
920  if( m_nFieldTagAlways[nI] & nMask ) // Flag: Tag it
921  return Read_F_Tag( &aF ); // Result not as text
922 
923  if( !bOk || !aF.nId ) // Field corrupted
924  return aF.nLen; // -> ignore
925 
926  if( aF.nId > eMax - 1) // WW: Nested Field
927  {
928  if( m_nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
929  return Read_F_Tag( &aF ); // Result not as text
930  else
931  return aF.nLen;
932  }
933 
934  //Only one type of field (hyperlink) in drawing textboxes exists
935  if (aF.nId != 88 && m_xPlcxMan->GetDoingDrawTextBox())
936  return aF.nLen;
937 
938  bool bHasHandler = aWW8FieldTab[aF.nId] != nullptr;
939  if (aF.nId == 10) // STYLEREF
940  {
941  // STYLEREF, by default these are not handled.
942  bHasHandler = false;
943  sal_uInt64 nOldPos = m_pStrm->Tell();
944  OUString aStr;
945  aF.nLCode = m_xSBase->WW8ReadString(*m_pStrm, aStr, m_xPlcxMan->GetCpOfs() + aF.nSCode, aF.nLCode, m_eTextCharSet);
946  m_pStrm->Seek(nOldPos);
947 
948  WW8ReadFieldParams aReadParam(aStr);
949  sal_Int32 nRet = aReadParam.SkipToNextToken();
950  if (nRet == -2 && !aReadParam.GetResult().isEmpty())
951  // Single numeric argument: this can be handled by SwChapterField.
952  bHasHandler = rtl::isAsciiDigit(aReadParam.GetResult()[0]);
953 
954  if (bHasHandler)
955  {
956  nRet = aReadParam.SkipToNextToken();
957  // Handle using SwChapterField only in case there is no \[a-z]
958  // switch after the field argument.
959  bHasHandler = nRet < 0 || nRet == '*';
960  }
961  }
962 
963  // no routine available
964  if (!bHasHandler || bCodeNest)
965  {
966  if( m_nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
967  return Read_F_Tag( &aF ); // Result not as text
968  // only read result
969  if (aF.bResNest && !AcceptableNestedField(aF.nId))
970  return aF.nLen; // Result nested -> unusable
971 
972  sal_uInt64 nOldPos = m_pStrm->Tell();
973  OUString aStr;
974  aF.nLCode = m_xSBase->WW8ReadString( *m_pStrm, aStr, m_xPlcxMan->GetCpOfs()+
975  aF.nSCode, aF.nLCode, m_eTextCharSet );
976  m_pStrm->Seek( nOldPos );
977 
978  // field codes which contain '/' or '.' are not displayed in WinWord
979  // skip if it is formula field or found space before. see #i119446, #i119585.
980  const sal_Int32 nDotPos = aStr.indexOf('.');
981  const sal_Int32 nSlashPos = aStr.indexOf('/');
982  sal_Int32 nSpacePos = aStr.indexOf( ' ', 1 );
983  if ( nSpacePos<0 )
984  nSpacePos = aStr.getLength();
985 
986  if ( ( aStr.getLength() <= 1 || aStr[1] != '=') &&
987  (( nDotPos>=0 && nDotPos < nSpacePos ) ||
988  ( nSlashPos>=0 && nSlashPos < nSpacePos )))
989  return aF.nLen;
990  else
991  {
992  // Link fields aren't supported, but they are bound to an OLE object
993  // that needs to be roundtripped
994  if ( aF.nId == 56 )
995  m_bEmbeddObj = true;
996  // Field not supported: store the field code for later use
997  m_aFieldStack.back().SetBookmarkCode( aStr );
998  return aF.nLen - aF.nLRes - 1; // skipped too many, the resulted field will be read like main text
999  }
1000  }
1001  else
1002  { // read field
1003  auto nOldPos = m_pStrm->Tell();
1004  OUString aStr;
1005  if ( aF.nId == 6 && aF.bCodeNest )
1006  {
1007  // TODO Extract the whole code string using the nested codes
1008  aF.nLCode = m_xSBase->WW8ReadString( *m_pStrm, aStr, m_xPlcxMan->GetCpOfs() +
1009  aF.nSCode, aF.nSRes - aF.nSCode - 1, m_eTextCharSet );
1010  }
1011  else
1012  {
1013  aF.nLCode = m_xSBase->WW8ReadString( *m_pStrm, aStr, m_xPlcxMan->GetCpOfs()+
1014  aF.nSCode, aF.nLCode, m_eTextCharSet );
1015  }
1016 
1017  // #i51312# - graphics inside field code not supported by Writer.
1018  // Thus, delete character 0x01, which stands for such a graphic.
1019  if (aF.nId==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
1020  {
1021  aStr = aStr.replaceAll("\x01", "");
1022  }
1023 
1024  eF_ResT eRes = (this->*aWW8FieldTab[aF.nId])( &aF, aStr );
1025  m_pStrm->Seek(nOldPos);
1026 
1027  switch ( eRes )
1028  {
1029  case eF_ResT::OK:
1030  return aF.nLen;
1031  case eF_ResT::TEXT:
1032  // skipped too many, the resulted field will be read like main text
1033  // attributes can start at char 0x14 so skip one
1034  // char more back == "-2"
1035  if (aF.nLRes)
1036  return aF.nLen - aF.nLRes - 2;
1037  else
1038  return aF.nLen;
1039  case eF_ResT::TAGIGN:
1040  if ( m_nFieldTagBad[nI] & nMask ) // Flag: Tag bad
1041  return Read_F_Tag( &aF ); // Tag it
1042  return aF.nLen; // or ignore
1043  case eF_ResT::READ_FSPA:
1044  return aF.nLen - aF.nLRes - 2; // position on char 1
1045  default:
1046  return aF.nLen; // ignore
1047  }
1048  }
1049 }
1050 
1051 // Tag fields
1052 
1053 // MakeTagString() returns the position of the first CR / end of line / page break
1054 // in pText and converts only up to this point.
1055 // If none of these special characters is found, the function returns 0.
1056 void SwWW8ImplReader::MakeTagString( OUString& rStr, const OUString& rOrg )
1057 {
1058  bool bAllowCr = SwFltGetFlag( m_nFieldFlags, SwFltControlStack::TAGS_IN_TEXT )
1059  || SwFltGetFlag( m_nFieldFlags, SwFltControlStack::ALLOW_FLD_CR );
1060  sal_Unicode cChar;
1061  rStr = rOrg;
1062 
1063  for( sal_Int32 nI = 0;
1064  nI < rStr.getLength() && rStr.getLength() < (MAX_FIELDLEN - 4); ++nI )
1065  {
1066  bool bSetAsHex = false;
1067  cChar = rStr[ nI ];
1068  switch( cChar )
1069  {
1070  case 132: // Exchange typographical quotation marks for normal ones
1071  case 148:
1072  case 147:
1073  rStr = rStr.replaceAt( nI, 1, u"\"" );
1074  break;
1075  case 19:
1076  rStr = rStr.replaceAt( nI, 1, u"{" );
1077  break; // 19..21 to {|}
1078  case 20:
1079  rStr = rStr.replaceAt( nI, 1, u"|" );
1080  break;
1081  case 21:
1082  rStr = rStr.replaceAt( nI, 1, u"}" );
1083  break;
1084  case '\\': // Tag \{|} with \ ...
1085  case '{':
1086  case '|':
1087  case '}':
1088  rStr = rStr.replaceAt( nI, 0, u"\\" );
1089  ++nI;
1090  break;
1091  case 0x0b:
1092  case 0x0c:
1093  case 0x0d:
1094  if( bAllowCr )
1095  rStr = rStr.replaceAt( nI, 1, u"\n" );
1096  else
1097  bSetAsHex = true;
1098  break;
1099  case 0xFE:
1100  case 0xFF:
1101  bSetAsHex = true;
1102  break;
1103  default:
1104  bSetAsHex = 0x20 > cChar;
1105  break;
1106  }
1107 
1108  if( bSetAsHex )
1109  {
1110  //all Hex-Numbers with \x before
1111  OUString sTmp( "\\x" );
1112  if( cChar < 0x10 )
1113  sTmp += "0";
1114  sTmp += OUString::number( cChar, 16 );
1115  rStr = rStr.replaceAt( nI, 1 , sTmp );
1116  nI += sTmp.getLength() - 1;
1117  }
1118  }
1119 
1120  if( rStr.getLength() > (MAX_FIELDLEN - 4))
1121  rStr = rStr.copy( 0, MAX_FIELDLEN - 4 );
1122 }
1123 
1124 void SwWW8ImplReader::InsertTagField( const sal_uInt16 nId, const OUString& rTagText )
1125 {
1126  OUString aName("WwFieldTag");
1127  if( SwFltGetFlag( m_nFieldFlags, SwFltControlStack::TAGS_DO_ID ) ) // Number?
1128  aName += OUString::number( nId ); // return it?
1129 
1130  if( SwFltGetFlag(m_nFieldFlags, SwFltControlStack::TAGS_IN_TEXT))
1131  {
1132  aName += rTagText; // tag as text
1135  }
1136  else
1137  { // tag normally
1138 
1141  SwSetExpField aField( static_cast<SwSetExpFieldType*>(pFT), rTagText ); // SUB_INVISIBLE
1142  sal_uInt16 nSubType = ( SwFltGetFlag( m_nFieldFlags, SwFltControlStack::TAGS_VISIBLE ) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE;
1143  aField.SetSubType(nSubType | nsSwGetSetExpType::GSE_STRING);
1144 
1146  }
1147 }
1148 
1150 {
1151  sal_uInt64 nOldPos = m_pStrm->Tell();
1152 
1153  WW8_CP nStart = pF->nSCode - 1; // starting with 0x19
1154  WW8_CP nL = pF->nLen; // Total length with result and nest
1155  if( nL > MAX_FIELDLEN )
1156  nL = MAX_FIELDLEN; // MaxLength, by quoting
1157  // max. 4 times as big
1158  OUString sFText;
1159  m_xSBase->WW8ReadString( *m_pStrm, sFText,
1160  m_xPlcxMan->GetCpOfs() + nStart, nL, m_eStructCharSet);
1161 
1162  OUString aTagText;
1163  MakeTagString( aTagText, sFText );
1164  InsertTagField( pF->nId, aTagText );
1165 
1166  m_pStrm->Seek( nOldPos );
1167  return pF->nLen;
1168 }
1169 
1170 // normal fields
1171 
1173 {
1174  OUString aDef;
1175  OUString aQ;
1176  WW8ReadFieldParams aReadParam( rStr );
1177  for (;;)
1178  {
1179  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1180  if ( nRet==-1 )
1181  break;
1182  switch( nRet )
1183  {
1184  case -2:
1185  if( aQ.isEmpty() )
1186  aQ = aReadParam.GetResult();
1187  break;
1188  case 'd':
1189  case 'D':
1190  if ( aReadParam.GoToTokenParam() )
1191  aDef = aReadParam.GetResult();
1192  break;
1193  }
1194  }
1195  if( aDef.isEmpty() )
1196  aDef = GetFieldResult( pF );
1197 
1198  if ( pF->nId != 0x01 ) // 0x01 fields have no result
1199  {
1200  SwInputField aField( static_cast<SwInputFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Input )),
1201  aDef, aQ, INP_TXT, 0, false );
1203  }
1204 
1205  return eF_ResT::OK;
1206 }
1207 
1208 // GetFieldResult allocates a string and reads the resulted field
1210 {
1211  sal_uInt64 nOldPos = m_pStrm->Tell();
1212 
1213  WW8_CP nStart = pF->nSRes; // result start
1214  WW8_CP nL = pF->nLRes; // result length
1215  if( !nL )
1216  return OUString(); // no result
1217 
1218  if( nL > MAX_FIELDLEN )
1219  nL = MAX_FIELDLEN; // MaxLength, by quoting
1220  // max. 4 times as big
1221 
1222  OUString sRes;
1223  m_xSBase->WW8ReadString( *m_pStrm, sRes, m_xPlcxMan->GetCpOfs() + nStart,
1224  nL, m_eStructCharSet );
1225 
1226  m_pStrm->Seek( nOldPos );
1227 
1228  //replace both CR 0x0D and VT 0x0B with LF 0x0A
1229  // at least in the cases where the result is added to an SwInputField
1230  // there must not be control characters in it
1231  OUStringBuffer buf(sRes.getLength());
1232  for (sal_Int32 i = 0; i < sRes.getLength(); ++i)
1233  {
1234  sal_Unicode const ch(sRes[i]);
1235  if (!linguistic::IsControlChar(ch))
1236  {
1237  buf.append(ch);
1238  }
1239  else
1240  {
1241  switch (ch)
1242  {
1243  case 0x0B:
1244  case '\r':
1245  buf.append('\n');
1246  break;
1247  case '\n':
1248  case '\t':
1249  buf.append(ch);
1250  break;
1251  default:
1252  SAL_INFO("sw.ww8", "GetFieldResult(): filtering control character");
1253  break;
1254  }
1255  }
1256  }
1257  return buf.makeStringAndClear();
1258 }
1259 
1260 /*
1261 Bookmarks can be set with fields SET and ASK, and they can be referenced with
1262 REF. When set, they behave like variables in writer, otherwise they behave
1263 like normal bookmarks. We can check whether we should use a show variable
1264 instead of a normal bookmark ref by converting to "show variable" at the end
1265 of the document those refs which look for the content of a bookmark but whose
1266 bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
1267 
1268 The other piece of the puzzle is that refs that point to the "location" of the
1269 bookmark will in word actually point to the last location where the bookmark
1270 was set with SET or ASK, not the actual bookmark. This is only noticeable when
1271 a document sets the bookmark more than once. This is because word places the
1272 true bookmark at the location of the last set, but the refs will display the
1273 position of the first set before the ref.
1274 
1275 So what we will do is
1276 
1277 1) keep a list of all bookmarks that were set, any bookmark names mentioned
1278 here that are referred by content will be converted to show variables.
1279 
1280 2) create pseudo bookmarks for every position that a bookmark is set with SET
1281 or ASK but has no existing bookmark. We can then keep a map from the original
1282 bookmark name to the new one. As we parse the document new pseudo names will
1283 replace the older ones, so the map always contains the bookmark of the
1284 location that msword itself would use.
1285 
1286 3) word's bookmarks are case insensitive, writers are not. So we need to
1287 map case different versions together, regardless of whether they are
1288 variables or not.
1289 
1290 4) when a reference is (first) SET or ASK, the bookmark associated with it
1291 is placed around the 0x14 0x15 result part of the field. We will fiddle
1292 the placement to be the writer equivalent of directly before and after
1293 the field, which gives the same effect and meaning, to do so we must
1294 get any bookmarks in the field range, and begin them immediately before
1295 the set/ask field, and end them directly afterwards. MapBookmarkVariables
1296 returns an identifier of the bookmark attribute to close after inserting
1297 the appropriate set/ask field.
1298 */
1300  OUString &rOrigName, const OUString &rData)
1301 {
1302  OSL_ENSURE(m_xPlcxMan, "No pPlcxMan");
1303  tools::Long nNo;
1304  /*
1305  If there was no bookmark associated with this set field, then we create a
1306  pseudo one and insert it in the document.
1307  */
1308  sal_uInt16 nIndex;
1309  m_xPlcxMan->GetBook()->MapName(rOrigName);
1310  OUString sName = m_xPlcxMan->GetBook()->GetBookmark(
1311  pF->nSCode, pF->nSCode + pF->nLen, nIndex);
1312  if (!sName.isEmpty())
1313  {
1314  m_xPlcxMan->GetBook()->SetStatus(nIndex, BOOK_IGNORE);
1315  nNo = nIndex;
1316  }
1317  else
1318  {
1319  nNo = m_xReffingStck->m_aFieldVarNames.size()+1;
1320  sName = "WWSetBkmk" + OUString::number(nNo);
1321  nNo += m_xPlcxMan->GetBook()->GetIMax();
1322  }
1323  m_xReffedStck->NewAttr(*m_pPaM->GetPoint(),
1324  SwFltBookmark( BookmarkToWriter(sName), rData, nNo ));
1325  m_xReffingStck->m_aFieldVarNames[rOrigName] = sName;
1326  return nNo;
1327 }
1328 
1329 /*
1330 Word can set a bookmark with set or with ask, such a bookmark is equivalent to
1331 our variables, but until the end of a document we cannot be sure if a bookmark
1332 is a variable or not, at the end we will have a list of reference names which
1333 were set or asked, all bookmarks using the content of those bookmarks are
1334 converted to show variables, those that reference the position of the field
1335 can be left as references, because a bookmark is also inserted at the position
1336 of a set or ask field, either by word, or in some special cases by the import
1337 filter itself.
1338 */
1340  SwFltStackEntry &rEntry)
1341 {
1342  SwFltStackEntry *pRet=nullptr;
1343  if (pField && SwFieldIds::GetRef == pField->Which())
1344  {
1345  //Get the name of the ref field, and see if actually a variable
1346  const OUString sName = pField->GetPar1();
1347  std::map<OUString, OUString, SwWW8::ltstr>::const_iterator
1348  aResult = m_aFieldVarNames.find(sName);
1349 
1350  if (aResult != m_aFieldVarNames.end())
1351  {
1352  SwGetExpField aField( static_cast<SwGetExpFieldType*>(
1354  SwFormatField aTmp(aField);
1355  rEntry.m_pAttr.reset( aTmp.Clone() );
1356  pRet = &rEntry;
1357  }
1358  }
1359  return pRet;
1360 }
1361 
1362 OUString SwWW8ImplReader::GetMappedBookmark(std::u16string_view rOrigName)
1363 {
1364  OUString sName(BookmarkToWriter(rOrigName));
1365  OSL_ENSURE(m_xPlcxMan, "no pPlcxMan");
1366  m_xPlcxMan->GetBook()->MapName(sName);
1367 
1368  //See if there has been a variable set with this name, if so get
1369  //the pseudo bookmark name that was set with it.
1370  std::map<OUString, OUString, SwWW8::ltstr>::const_iterator aResult =
1371  m_xReffingStck->m_aFieldVarNames.find(sName);
1372 
1373  return (aResult == m_xReffingStck->m_aFieldVarNames.end())
1374  ? sName : (*aResult).second;
1375 }
1376 
1377 // "ASK"
1379 {
1380  OUString sOrigName, aQ;
1381  OUString aDef;
1382  WW8ReadFieldParams aReadParam( rStr );
1383  for (;;)
1384  {
1385  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1386  if ( nRet==-1 )
1387  break;
1388  switch( nRet )
1389  {
1390  case -2:
1391  if (sOrigName.isEmpty())
1392  sOrigName = aReadParam.GetResult();
1393  else if (aQ.isEmpty())
1394  aQ = aReadParam.GetResult();
1395  break;
1396  case 'd':
1397  case 'D':
1398  if ( aReadParam.GoToTokenParam() )
1399  aDef = aReadParam.GetResult();
1400  break;
1401  }
1402  }
1403 
1404  if (sOrigName.isEmpty())
1405  return eF_ResT::TAGIGN; // does not make sense without textmark
1406 
1407  const OUString aResult(GetFieldResult(pF));
1408 
1409  //#i24377#, munge Default Text into title as we have only one slot
1410  //available for aResult and aDef otherwise
1411  if (!aDef.isEmpty())
1412  {
1413  if (!aQ.isEmpty())
1414  aQ += " - ";
1415  aQ += aDef;
1416  }
1417 
1418  const tools::Long nNo = MapBookmarkVariables(pF, sOrigName, aResult);
1419 
1422  SwSetExpField aField(pFT, aResult);
1424  aField.SetInputFlag(true);
1425  aField.SetPromptText( aQ );
1426 
1428 
1429  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
1430  return eF_ResT::OK;
1431 }
1432 
1433 // "AUTONR"
1435 {
1436  if( !m_pNumFieldType ){ // 1st time
1438  m_pNumFieldType = m_rDoc.getIDocumentFieldsAccess().InsertFieldType( aT );
1439  }
1440  SwSetExpField aField( static_cast<SwSetExpFieldType*>(m_pNumFieldType), OUString(),
1441  GetNumberPara( rStr ) );
1442  aField.SetValue( ++m_nFieldNum, nullptr );
1444  return eF_ResT::OK;
1445 }
1446 
1447 // "SEQ"
1449 {
1450  OUString aSequenceName;
1451  OUString aBook;
1452  bool bHidden = false;
1453  bool bFormat = false;
1454  bool bCountOn = true;
1455  OUString sStart;
1456  SvxNumType eNumFormat = SVX_NUM_ARABIC;
1457  WW8ReadFieldParams aReadParam( rStr );
1458  for (;;)
1459  {
1460  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1461  if ( nRet==-1 )
1462  break;
1463  switch( nRet )
1464  {
1465  case -2:
1466  if( aSequenceName.isEmpty() )
1467  aSequenceName = aReadParam.GetResult();
1468  else if( aBook.isEmpty() )
1469  aBook = aReadParam.GetResult();
1470  break;
1471 
1472  case 'h':
1473  if( !bFormat )
1474  bHidden = true; // activate hidden flag
1475  break;
1476 
1477  case '*':
1478  bFormat = true; // activate format flag
1479  if ( aReadParam.SkipToNextToken()!=-2 )
1480  break;
1481  if ( aReadParam.GetResult()!="MERGEFORMAT" && aReadParam.GetResult()!="CHARFORMAT" )
1482  eNumFormat = GetNumTypeFromName( aReadParam.GetResult() );
1483  break;
1484 
1485  case 'r':
1486  bCountOn = false;
1487  if ( aReadParam.SkipToNextToken()==-2 )
1488  sStart = aReadParam.GetResult();
1489  break;
1490 
1491  case 'c':
1492  bCountOn = false;
1493  break;
1494 
1495  case 'n':
1496  bCountOn = true; // Increase value by one (default)
1497  break;
1498 
1499  case 's': // Outline Level
1500  //#i19682, what I have to do with this value?
1501  break;
1502  }
1503  }
1504  if (aSequenceName.isEmpty() && aBook.isEmpty())
1505  return eF_ResT::TAGIGN;
1506 
1508  SwSetExpFieldType( &m_rDoc, aSequenceName, nsSwGetSetExpType::GSE_SEQ ) ) );
1509  SwSetExpField aField( pFT, OUString(), eNumFormat );
1510 
1511  //#i120654# Add bHidden for /h flag (/h: Hide the field result.)
1512  if (bHidden)
1514 
1515  if (!sStart.isEmpty())
1516  aField.SetFormula( aSequenceName + "=" + sStart );
1517  else if (!bCountOn)
1518  aField.SetFormula(aSequenceName);
1519 
1521  return eF_ResT::OK;
1522 }
1523 
1525 {
1526  WW8ReadFieldParams aReadParam(rString);
1527  sal_Int32 nRet = aReadParam.SkipToNextToken();
1528  if (nRet != -2)
1529  // \param was found, not normal text.
1530  return eF_ResT::TAGIGN;
1531 
1532  OUString aResult = aReadParam.GetResult();
1533  sal_Int32 nResult = aResult.toInt32();
1534  if (nResult < 1)
1535  return eF_ResT::TAGIGN;
1536 
1538  SwChapterField aField(static_cast<SwChapterFieldType*>(pFieldType), CF_TITLE);
1539  aField.SetLevel(nResult - 1);
1541 
1542  return eF_ResT::OK;
1543 }
1544 
1546 {
1547  sal_uInt16 nSub=0;
1548  // RegInfoFormat, DefaultFormat for DocInfoFields
1549  sal_uInt16 nReg = DI_SUB_AUTHOR;
1550  bool bDateTime = false;
1551  const sal_uInt16 nFldLock = (pF->nOpt & 0x10) ? DI_SUB_FIXED : 0;
1552 
1553  if( 85 == pF->nId )
1554  {
1555  OUString aDocProperty;
1556  WW8ReadFieldParams aReadParam( rStr );
1557  for (;;)
1558  {
1559  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1560  if ( nRet==-1 )
1561  break;
1562  switch( nRet )
1563  {
1564  case -2:
1565  if( aDocProperty.isEmpty() )
1566  aDocProperty = aReadParam.GetResult();
1567  break;
1568  case '*':
1569  //Skip over MERGEFORMAT
1570  (void)aReadParam.SkipToNextToken();
1571  break;
1572  }
1573  }
1574 
1575  aDocProperty = aDocProperty.replaceAll("\"", "");
1576 
1577  /*
1578  There are up to 26 fields that may be meant by 'DocumentProperty'.
1579  Which of them is to be inserted here ?
1580  This Problem can only be solved by implementing a name matching
1581  method that compares the given Parameter String with the four
1582  possible name sets (english, german, french, spanish)
1583  */
1584 
1585  static const char* aName10 = "\x0F"; // SW field code
1586  static const char* aName11 // German
1587  = "TITEL";
1588  static const char* aName12 // French
1589  = "TITRE";
1590  static const char* aName13 // English
1591  = "TITLE";
1592  static const char* aName14 // Spanish
1593  = "TITRO";
1594  static const char* aName20 = "\x15"; // SW field code
1595  static const char* aName21 // German
1596  = "ERSTELLDATUM";
1597  static const char* aName22 // French
1598  = "CR\xC9\xC9";
1599  static const char* aName23 // English
1600  = "CREATED";
1601  static const char* aName24 // Spanish
1602  = "CREADO";
1603  static const char* aName30 = "\x16"; // SW field code
1604  static const char* aName31 // German
1605  = "ZULETZTGESPEICHERTZEIT";
1606  static const char* aName32 // French
1607  = "DERNIERENREGISTREMENT";
1608  static const char* aName33 // English
1609  = "SAVED";
1610  static const char* aName34 // Spanish
1611  = "MODIFICADO";
1612  static const char* aName40 = "\x17"; // SW field code
1613  static const char* aName41 // German
1614  = "ZULETZTGEDRUCKT";
1615  static const char* aName42 // French
1616  = "DERNI\xC8" "REIMPRESSION";
1617  static const char* aName43 // English
1618  = "LASTPRINTED";
1619  static const char* aName44 // Spanish
1620  = "HUPS PUPS";
1621  static const char* aName50 = "\x18"; // SW field code
1622  static const char* aName51 // German
1623  = "\xDC" "BERARBEITUNGSNUMMER";
1624  static const char* aName52 // French
1625  = "NUM\xC9" "RODEREVISION";
1626  static const char* aName53 // English
1627  = "REVISIONNUMBER";
1628  static const char* aName54 // Spanish
1629  = "SNUBBEL BUBBEL";
1630  static const sal_uInt16 nFieldCnt = 5;
1631 
1632  // additional fields are to be coded soon!
1633 
1634  static const sal_uInt16 nLangCnt = 4;
1635  static const char *aNameSet_26[nFieldCnt][nLangCnt+1] =
1636  {
1637  {aName10, aName11, aName12, aName13, aName14},
1638  {aName20, aName21, aName22, aName23, aName24},
1639  {aName30, aName31, aName32, aName33, aName34},
1640  {aName40, aName41, aName42, aName43, aName44},
1641  {aName50, aName51, aName52, aName53, aName54}
1642  };
1643 
1644  bool bFieldFound= false;
1645  sal_uInt16 nFIdx;
1646  for(sal_uInt16 nLIdx=1; !bFieldFound && (nLangCnt > nLIdx); ++nLIdx)
1647  {
1648  for(nFIdx = 0; !bFieldFound && (nFieldCnt > nFIdx); ++nFIdx)
1649  {
1650  if( aDocProperty == OUString( aNameSet_26[nFIdx][nLIdx], strlen(aNameSet_26[nFIdx][nLIdx]),
1651  RTL_TEXTENCODING_MS_1252 ) )
1652  {
1653  bFieldFound = true;
1654  pF->nId = aNameSet_26[nFIdx][0][0];
1655  }
1656  }
1657  }
1658 
1659  if( !bFieldFound )
1660  {
1661  // LO always automatically updates a DocInfo field from the File-Properties-Custom Prop
1662  // while MS Word requires the user to manually refresh the field (with F9).
1663  // In other words, Word lets the field to be out of sync with the controlling variable.
1664  // Marking as FIXEDFLD solves the automatic replacement problem, but of course prevents
1665  // Writer from making any changes, even on an F9 refresh.
1666  // TODO: Extend LO to allow a linked field that doesn't automatically update.
1668  const auto pType(static_cast<SwDocInfoFieldType*>(
1670  const OUString sDisplayed = GetFieldResult(pF);
1671  SwDocInfoField aField(pType, DI_CUSTOM | nReg, aDocProperty);
1672 
1673  // If text already matches the DocProperty var, then safe to treat as refreshable field.
1674  OUString sVariable = aField.ExpandField(/*bCache=*/false, nullptr);
1675  if (sDisplayed.getLength() != sVariable.getLength())
1676  {
1677  sal_Int32 nLen = sVariable.indexOf('\x0');
1678  if (nLen >= 0)
1679  sVariable = sVariable.copy(0, nLen);
1680  }
1681  if (sDisplayed == sVariable)
1682  rIDCO.InsertPoolItem(*m_pPaM, SwFormatField(aField));
1683  else
1684  {
1685  // They don't match, so use a fixed field to prevent LO from altering the contents.
1686  SwDocInfoField aFixedField(pType, DI_CUSTOM | DI_SUB_FIXED | nReg, aDocProperty,
1687  sDisplayed);
1688  rIDCO.InsertPoolItem(*m_pPaM, SwFormatField(aFixedField));
1689  }
1690 
1691  return eF_ResT::OK;
1692  }
1693  }
1694 
1695  switch( pF->nId )
1696  {
1697  case 14:
1698  /* supports all INFO variables! */
1699  nSub = DI_KEYS;
1700  break;
1701  case 15:
1702  nSub = DI_TITLE;
1703  break;
1704  case 16:
1705  nSub = DI_SUBJECT;
1706  break;
1707  case 18:
1708  nSub = DI_KEYS;
1709  break;
1710  case 19:
1711  nSub = DI_COMMENT;
1712  break;
1713  case 20:
1714  // MS Word never updates this automatically, so mark as fixed for best compatibility
1715  nSub = DI_CHANGE | DI_SUB_FIXED;
1716  nReg = DI_SUB_AUTHOR;
1717  break;
1718  case 21:
1719  // The real create date can never change, so mark as fixed for best compatibility
1720  nSub = DI_CREATE | DI_SUB_FIXED;
1721  nReg = DI_SUB_DATE;
1722  bDateTime = true;
1723  break;
1724  case 23:
1725  nSub = DI_PRINT | nFldLock;
1726  nReg = DI_SUB_DATE;
1727  bDateTime = true;
1728  break;
1729  case 24:
1730  nSub = DI_DOCNO;
1731  break;
1732  case 22:
1733  nSub = DI_CHANGE | nFldLock;
1734  nReg = DI_SUB_DATE;
1735  bDateTime = true;
1736  break;
1737  case 25:
1738  nSub = DI_CHANGE | nFldLock;
1739  nReg = DI_SUB_TIME;
1740  bDateTime = true;
1741  break;
1742  case 64: // DOCVARIABLE
1743  nSub = DI_CUSTOM;
1744  break;
1745  }
1746 
1747  sal_uInt32 nFormat = 0;
1748 
1750  if (bDateTime)
1751  {
1752  SvNumFormatType nDT = GetTimeDatePara(rStr, nFormat, nLang, pF->nId);
1753  switch (nDT)
1754  {
1755  case SvNumFormatType::DATE:
1756  nReg = DI_SUB_DATE;
1757  break;
1758  case SvNumFormatType::TIME:
1759  nReg = DI_SUB_TIME;
1760  break;
1761  case SvNumFormatType::DATETIME:
1762  nReg = DI_SUB_DATE;
1763  break;
1764  default:
1765  nReg = DI_SUB_DATE;
1766  break;
1767  }
1768  }
1769 
1770  OUString aData;
1771  // Extract DOCVARIABLE varname
1772  if ( 64 == pF->nId )
1773  {
1774  WW8ReadFieldParams aReadParam( rStr );
1775  for (;;)
1776  {
1777  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1778  if ( nRet==-1)
1779  break;
1780  switch( nRet )
1781  {
1782  case -2:
1783  if( aData.isEmpty() )
1784  aData = aReadParam.GetResult();
1785  break;
1786  case '*':
1787  //Skip over MERGEFORMAT
1788  (void)aReadParam.SkipToNextToken();
1789  break;
1790  }
1791  }
1792 
1793  aData = aData.replaceAll("\"", "");
1794  }
1795 
1796  const auto pType(static_cast<SwDocInfoFieldType*>(
1798  SwDocInfoField aField(pType, nSub|nReg, aData, GetFieldResult(pF), nFormat);
1799  if (bDateTime)
1800  ForceFieldLanguage(aField, nLang);
1802 
1803  return eF_ResT::OK;
1804 }
1805 
1807 {
1808  // SH: The SwAuthorField refers not to the original author but to the current user, better use DocInfo
1809  SwDocInfoField aField( static_cast<SwDocInfoFieldType*>(
1811  DI_CREATE|DI_SUB_AUTHOR|DI_SUB_FIXED, OUString(), GetFieldResult(pF));
1813  return eF_ResT::OK;
1814 }
1815 
1817 {
1818  SwTemplNameField aField( static_cast<SwTemplNameFieldType*>(
1821  return eF_ResT::OK;
1822 }
1823 
1824 // Both the date and the time fields can be used for showing a date a time or both.
1826 {
1827  bool bHijri = false;
1828  WW8ReadFieldParams aReadParam(rStr);
1829  for (;;)
1830  {
1831  const sal_Int32 nTok = aReadParam.SkipToNextToken();
1832  if ( nTok==-1 )
1833  break;
1834  switch (nTok)
1835  {
1836  default:
1837  case 'l':
1838  case -2:
1839  break;
1840  case 'h':
1841  bHijri = true;
1842  break;
1843  case 's':
1844  //Saka Calendar, should we do something with this ?
1845  break;
1846  }
1847  }
1848 
1849  sal_uInt32 nFormat = 0;
1850 
1852  SvNumFormatType nDT = GetTimeDatePara(rStr, nFormat, nLang, ww::eDATE, bHijri);
1853 
1854  if( SvNumFormatType::UNDEFINED == nDT ) // no D/T-Formatstring
1855  {
1856  if (32 == pF->nId)
1857  {
1858  nDT = SvNumFormatType::TIME;
1861  }
1862  else
1863  {
1864  nDT = SvNumFormatType::DATE;
1867  }
1868  }
1869 
1870  if (nDT & SvNumFormatType::DATE || nDT == SvNumFormatType::TIME)
1871  {
1872  SwDateTimeField aField(static_cast<SwDateTimeFieldType*>(
1874  nDT & SvNumFormatType::DATE ? DATEFLD : TIMEFLD, nFormat);
1875  if (pF->nOpt & 0x10) // Fixed field
1876  {
1877  double fSerial;
1878  if (!m_rDoc.GetNumberFormatter()->IsNumberFormat(GetFieldResult(pF), nFormat, fSerial,
1879  SvNumInputOptions::LAX_TIME))
1880  return eF_ResT::TEXT; // just drop the field and insert the plain text.
1881  aField.SetSubType(aField.GetSubType() | FIXEDFLD);
1882  DateTime aSetDateTime(m_rDoc.GetNumberFormatter()->GetNullDate());
1883  aSetDateTime.AddTime(fSerial);
1884  aField.SetDateTime(aSetDateTime);
1885  }
1886  ForceFieldLanguage(aField, nLang);
1888  }
1889 
1890  return eF_ResT::OK;
1891 }
1892 
1894 {
1896  WW8ReadFieldParams aReadParam(rStr);
1897  for (;;)
1898  {
1899  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1900  if ( nRet==-1 )
1901  break;
1902  switch (nRet)
1903  {
1904  case 'p':
1905  eType = FF_PATHNAME;
1906  break;
1907  case '*':
1908  //Skip over MERGEFORMAT
1909  (void)aReadParam.SkipToNextToken();
1910  break;
1911  default:
1912  OSL_ENSURE(false, "unknown option in FileName field");
1913  break;
1914  }
1915  }
1916 
1917  SwFileNameField aField(
1918  static_cast<SwFileNameFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Filename)), eType);
1920  return eF_ResT::OK;
1921 }
1922 
1924 {
1925  sal_uInt16 nSub = DS_PAGE; // page number
1926  switch ( pF->nId ){
1927  case 27: nSub = DS_WORD; break; // number of words
1928  case 28: nSub = DS_CHAR; break; // number of characters
1929  }
1930  SwDocStatField aField( static_cast<SwDocStatFieldType*>(
1932  GetNumberPara( rStr ) );
1934  return eF_ResT::OK;
1935 }
1936 
1938 {
1939  // page number
1940  SwPageNumberField aField( static_cast<SwPageNumberFieldType*>(
1942  GetNumberPara(rStr, true));
1943 
1945  return eF_ResT::OK;
1946 }
1947 
1949 {
1950  //e.g. #i20118#
1951  OUString aQ;
1952  OUString aName;
1953  sal_Int32 nSize = 0;
1954  WW8ReadFieldParams aReadParam( rStr );
1955  for (;;)
1956  {
1957  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1958  if ( nRet==-1 )
1959  break;
1960  switch( nRet )
1961  {
1962  case -2:
1963  if( aQ.isEmpty() )
1964  aQ = aReadParam.GetResult();
1965  break;
1966  case 'f':
1967  case 'F':
1968  if ( aReadParam.GoToTokenParam() )
1969  aName = aReadParam.GetResult();
1970  break;
1971  case 's':
1972  case 'S':
1973  if ( aReadParam.GoToTokenParam() )
1974  {
1975  const OUString aSiz = aReadParam.GetResult();
1976  if (!aSiz.isEmpty())
1977  {
1978  bool bFail = o3tl::checked_multiply<sal_Int32>(aSiz.toInt32(), 20, nSize); // pT -> twip
1979  if (bFail)
1980  nSize = -1;
1981  }
1982  }
1983  break;
1984  }
1985  }
1986  if( aQ.isEmpty() )
1987  return eF_ResT::TAGIGN; // -> no 0-char in text
1988 
1989  sal_Unicode const cChar = static_cast<sal_Unicode>(aQ.toInt32());
1990  if (!linguistic::IsControlChar(cChar) || cChar == '\r' || cChar == '\n' || cChar == '\t')
1991  {
1992  if (!aName.isEmpty()) // Font Name set ?
1993  {
1994  SvxFontItem aFont(FAMILY_DONTKNOW, aName, OUString(),
1995  PITCH_DONTKNOW, RTL_TEXTENCODING_SYMBOL, RES_CHRATR_FONT);
1996  NewAttr(aFont); // new Font
1997  }
1998 
1999  if (nSize > 0) //#i20118#
2000  {
2001  SvxFontHeightItem aSz(nSize, 100, RES_CHRATR_FONTSIZE);
2002  NewAttr(aSz);
2003  }
2004 
2005  m_rDoc.getIDocumentContentOperations().InsertString(*m_pPaM, OUString(cChar));
2006 
2007  if (nSize > 0)
2008  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_CHRATR_FONTSIZE);
2009  if (!aName.isEmpty())
2010  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_CHRATR_FONT);
2011  }
2012  else
2013  {
2015  }
2016 
2017  return eF_ResT::OK;
2018 }
2019 
2020 // "EMBED"
2022 {
2023  WW8ReadFieldParams aReadParam( rStr );
2024  for (;;)
2025  {
2026  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2027  if ( nRet==-1 )
2028  break;
2029  switch( nRet )
2030  {
2031  case -2:
2032  // sHost
2033  break;
2034 
2035  case 's':
2036  // use ObjectSize
2037  break;
2038  }
2039  }
2040 
2041  if( m_bObj && m_nPicLocFc )
2042  m_nObjLocFc = m_nPicLocFc;
2043  m_bEmbeddObj = true;
2044  return eF_ResT::TEXT;
2045 }
2046 
2047 // "SET"
2049 {
2050  OUString sOrigName;
2051  OUString sVal;
2052  WW8ReadFieldParams aReadParam( rStr );
2053  for (;;)
2054  {
2055  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2056  if ( nRet==-1 )
2057  break;
2058  switch( nRet )
2059  {
2060  case -2:
2061  if (sOrigName.isEmpty())
2062  sOrigName = aReadParam.GetResult();
2063  else if (sVal.isEmpty())
2064  sVal = aReadParam.GetResult();
2065  break;
2066  }
2067  }
2068 
2069  const tools::Long nNo = MapBookmarkVariables(pF, sOrigName, sVal);
2070 
2073  SwSetExpField aField( static_cast<SwSetExpFieldType*>(pFT), sVal, ULONG_MAX );
2075 
2077 
2078  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
2079 
2080  return eF_ResT::OK;
2081 }
2082 
2083 // "REF"
2085 { // Reference - Field
2086  OUString sOrigBkmName;
2087  REFERENCEMARK eFormat = REF_CONTENT;
2088 
2089  WW8ReadFieldParams aReadParam( rStr );
2090  for (;;)
2091  {
2092  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2093  if ( nRet==-1 )
2094  break;
2095  switch( nRet )
2096  {
2097  case -2:
2098  if( sOrigBkmName.isEmpty() ) // get name of bookmark
2099  sOrigBkmName = aReadParam.GetResult();
2100  break;
2101 
2102  /* References to numbers in Word could be either to a numbered
2103  paragraph or to a chapter number. However Word does not seem to
2104  have the capability we do, of referring to the chapter number some
2105  other bookmark is in. As a result, cross-references to chapter
2106  numbers in a word document will be cross-references to a numbered
2107  paragraph, being the chapter heading paragraph. As it happens, our
2108  cross-references to numbered paragraphs will do the right thing
2109  when the target is a numbered chapter heading, so there is no need
2110  for us to use the REF_CHAPTER bookmark format on import.
2111  */
2112  case 'n':
2113  eFormat = REF_NUMBER_NO_CONTEXT;
2114  break;
2115  case 'r':
2116  eFormat = REF_NUMBER;
2117  break;
2118  case 'w':
2119  eFormat = REF_NUMBER_FULL_CONTEXT;
2120  break;
2121 
2122  case 'p':
2123  eFormat = REF_UPDOWN;
2124  break;
2125  case 'h':
2126  break;
2127  default:
2128  // unimplemented switch: just do 'nix nought nothing' :-)
2129  break;
2130  }
2131  }
2132 
2133  OUString sBkmName(GetMappedBookmark(sOrigBkmName));
2134 
2135  // #i120879# add cross reference bookmark name prefix, if it
2136  // matches internal TOC bookmark naming convention
2137  if ( IsTOCBookmarkName( sBkmName ) )
2138  {
2139  sBkmName = EnsureTOCBookmarkName(sBkmName);
2140  // track <sBookmarkName> as referenced TOC bookmark.
2141  m_xReffedStck->m_aReferencedTOCBookmarks.insert( sBkmName );
2142  }
2143 
2144  SwGetRefField aField(
2145  static_cast<SwGetRefFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef )),
2146  sBkmName,"",REF_BOOKMARK,0,eFormat);
2147 
2148  if (eFormat == REF_CONTENT)
2149  {
2150  /*
2151  If we are just inserting the contents of the bookmark, then it
2152  is possible that the bookmark is actually a variable, so we
2153  must store it until the end of the document to see if it was,
2154  in which case we'll turn it into a show variable
2155  */
2156  m_xReffingStck->NewAttr( *m_pPaM->GetPoint(), SwFormatField(aField) );
2157  m_xReffingStck->SetAttr( *m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2158  }
2159  else
2160  {
2162  }
2163  return eF_ResT::OK;
2164 }
2165 
2166 // Note Reference - Field
2168 {
2169  OUString aBkmName;
2170  bool bAboveBelow = false;
2171 
2172  WW8ReadFieldParams aReadParam( rStr );
2173  for (;;)
2174  {
2175  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2176  if ( nRet==-1 )
2177  break;
2178  switch( nRet )
2179  {
2180  case -2:
2181  if( aBkmName.isEmpty() ) // get name of foot/endnote
2182  aBkmName = aReadParam.GetResult();
2183  break;
2184  case 'r':
2185  // activate flag 'Chapter Number'
2186  break;
2187  case 'p':
2188  bAboveBelow = true;
2189  break;
2190  case 'h':
2191  break;
2192  default:
2193  // unimplemented switch: just do 'nix nought nothing' :-)
2194  break;
2195  }
2196  }
2197 
2198  // set Sequence No of corresponding Foot-/Endnote to Zero
2199  // (will be corrected in
2200  SwGetRefField aField( static_cast<SwGetRefFieldType*>(
2202  REF_ONLYNUMBER );
2203  m_xReffingStck->NewAttr(*m_pPaM->GetPoint(), SwFormatField(aField));
2204  m_xReffingStck->SetAttr(*m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2205  if (bAboveBelow)
2206  {
2207  SwGetRefField aField2( static_cast<SwGetRefFieldType*>(
2209  REF_UPDOWN );
2210  m_xReffingStck->NewAttr(*m_pPaM->GetPoint(), SwFormatField(aField2));
2211  m_xReffingStck->SetAttr(*m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2212  }
2213  return eF_ResT::OK;
2214 }
2215 
2216 // "PAGEREF"
2218 {
2219  OUString sOrigName;
2220  WW8ReadFieldParams aReadParam( rStr );
2221  for (;;)
2222  {
2223  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2224  if ( nRet==-1 )
2225  break;
2226  else if ( nRet == -2 && sOrigName.isEmpty() )
2227  {
2228  sOrigName = aReadParam.GetResult();
2229  }
2230  }
2231 
2232  const OUString sName(GetMappedBookmark(sOrigName));
2233 
2234  // loading page reference field in TOX
2235  if (m_bLoadingTOXCache)
2236  {
2237  // insert page ref representation as plain text --> return FLD_TEXT
2238  // if there is no hyperlink settings for current toc and referenced bookmark is available,
2239  // assign link to current ref area
2240  if (!m_bLoadingTOXHyperlink && !sName.isEmpty())
2241  {
2242  // #i120879# add cross reference bookmark name prefix, if it
2243  // matches internal TOC bookmark naming convention
2244  OUString sBookmarkName;
2245  if ( IsTOCBookmarkName( sName ) )
2246  {
2247  sBookmarkName = EnsureTOCBookmarkName(sName);
2248  // track <sBookmarkName> as referenced TOC bookmark.
2249  m_xReffedStck->m_aReferencedTOCBookmarks.insert( sBookmarkName );
2250  }
2251  else
2252  {
2253  sBookmarkName = sName;
2254  }
2255  OUString sURL = "#" + sBookmarkName;
2256  SwFormatINetFormat aURL( sURL, "" );
2257  static const OUStringLiteral sLinkStyle(u"Index Link");
2258  const sal_uInt16 nPoolId =
2260  aURL.SetVisitedFormatAndId( sLinkStyle, nPoolId);
2261  aURL.SetINetFormatAndId( sLinkStyle, nPoolId );
2262  m_xCtrlStck->NewAttr( *m_pPaM->GetPoint(), aURL );
2263  }
2264  return eF_ResT::TEXT;
2265  }
2266 
2267  // #i120879# add cross reference bookmark name prefix, if it matches
2268  // internal TOC bookmark naming convention
2269  OUString sPageRefBookmarkName;
2270  if ( IsTOCBookmarkName( sName ) )
2271  {
2272  sPageRefBookmarkName = EnsureTOCBookmarkName(sName);
2273  // track <sPageRefBookmarkName> as referenced TOC bookmark.
2274  m_xReffedStck->m_aReferencedTOCBookmarks.insert( sPageRefBookmarkName );
2275  }
2276  else
2277  {
2278  sPageRefBookmarkName = sName;
2279  }
2280  SwGetRefField aField( static_cast<SwGetRefFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef )),
2281  sPageRefBookmarkName, "", REF_BOOKMARK, 0, REF_PAGE );
2283 
2284  return eF_ResT::OK;
2285 }
2286 
2287 //helper function
2288 //For MS MacroButton field, the symbol in plain text is always "(" (0x28),
2289 //which should be mapped according to the macro type
2290 static bool ConvertMacroSymbol( std::u16string_view rName, OUString& rReference )
2291 {
2292  bool bConverted = false;
2293  if( rReference == "(" )
2294  {
2295  bConverted = true;
2296  sal_Unicode cSymbol = sal_Unicode(); // silence false warning
2297  if (rName == u"CheckIt")
2298  cSymbol = 0xF06F;
2299  else if (rName == u"UncheckIt")
2300  cSymbol = 0xF0FE;
2301  else if (rName == u"ShowExample")
2302  cSymbol = 0xF02A;
2303  //else if... : todo
2304  else
2305  bConverted = false;
2306 
2307  if( bConverted )
2308  rReference = OUString(cSymbol);
2309  }
2310  return bConverted;
2311 }
2312 
2313 // "MACROBUTTON"
2315 {
2316  OUString aName;
2317  OUString aVText;
2318  bool bNewVText = true;
2319  bool bBracket = false;
2320  WW8ReadFieldParams aReadParam( rStr );
2321 
2322  sal_Int32 nOffset = 0;
2323 
2324  for (;;)
2325  {
2326  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2327  if ( nRet==-1 )
2328  break;
2329  switch( nRet )
2330  {
2331  case -2:
2332  if( aName.isEmpty() )
2333  aName = aReadParam.GetResult();
2334  else if( aVText.isEmpty() || bBracket )
2335  {
2336  nOffset = aReadParam.GetTokenSttPtr() + 1;
2337 
2338  if( bBracket )
2339  aVText += " ";
2340  aVText += aReadParam.GetResult();
2341  if (bNewVText)
2342  {
2343  bBracket = (aVText[0] == '[');
2344  bNewVText = false;
2345  }
2346  else if( aVText.endsWith("]") )
2347  bBracket = false;
2348  }
2349  break;
2350  }
2351  }
2352  if( aName.isEmpty() )
2353  return eF_ResT::TAGIGN; // makes no sense without Macro-Name
2354 
2355  NotifyMacroEventRead();
2356 
2357  //try converting macro symbol according to macro name
2358  bool bApplyWingdings = ConvertMacroSymbol( aName, aVText );
2359  aName = "StarOffice.Standard.Modul1." + aName;
2360 
2361  SwMacroField aField( static_cast<SwMacroFieldType*>(
2363 
2364  if( !bApplyWingdings )
2365  {
2366 
2368  WW8_CP nOldCp = m_xPlcxMan->Where();
2369  WW8_CP nCp = nOldCp + nOffset;
2370 
2371  SwPaM aPaM(*m_pPaM, m_pPaM);
2372  aPaM.SetMark();
2373  aPaM.Move(fnMoveBackward);
2374  aPaM.Exchange();
2375 
2376  m_pPostProcessAttrsInfo.reset(new WW8PostProcessAttrsInfo(nCp, nCp, aPaM));
2377  }
2378  else
2379  {
2380  //set Wingdings font
2381  sal_uInt16 i = 0;
2382  for ( ; i < m_xFonts->GetMax(); i++ )
2383  {
2384  FontFamily eFamily;
2385  OUString aFontName;
2386  FontPitch ePitch;
2387  rtl_TextEncoding eSrcCharSet;
2388  if( GetFontParams( i, eFamily, aFontName, ePitch, eSrcCharSet )
2389  && aFontName=="Wingdings" )
2390  {
2391  break;
2392  }
2393  }
2394 
2395  if ( i < m_xFonts->GetMax() )
2396  {
2397 
2398  SetNewFontAttr( i, true, RES_CHRATR_FONT );
2400  m_xCtrlStck->SetAttr( *m_pPaM->GetPoint(), RES_CHRATR_FONT );
2401  ResetCharSetVars();
2402  }
2403  }
2404 
2405  return eF_ResT::OK;
2406 }
2407 
2409  SwPaM & rPaM)
2410  : mbCopy(false)
2411  , mnCpStart(nCpStart)
2412  , mnCpEnd(nCpEnd)
2413  , mPaM(*rPaM.GetMark(), *rPaM.GetPoint())
2414  , mItemSet(rPaM.GetDoc().GetAttrPool(), svl::Items<RES_CHRATR_BEGIN, RES_PARATR_END - 1>)
2415 {
2416 }
2417 
2418 bool CanUseRemoteLink(const OUString &rGrfName)
2419 {
2420  bool bUseRemote = false;
2421  try
2422  {
2423  // Related: tdf#102499, add a default css::ucb::XCommandEnvironment
2424  // in order to have https protocol manage certificates correctly
2425  uno::Reference< task::XInteractionHandler > xIH(
2426  task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr));
2427 
2428  uno::Reference< ucb::XProgressHandler > xProgress;
2430  new ::ucbhelper::CommandEnvironment(new comphelper::SimpleFileAccessInteraction( xIH ), xProgress);
2431 
2432  ::ucbhelper::Content aCnt(rGrfName,
2433  static_cast< ucb::XCommandEnvironment* >(pCommandEnv.get()),
2435 
2436  if ( !INetURLObject( rGrfName ).isAnyKnownWebDAVScheme() )
2437  {
2438  OUString aTitle;
2439  aCnt.getPropertyValue("Title") >>= aTitle;
2440  bUseRemote = !aTitle.isEmpty();
2441  }
2442  else
2443  {
2444  // is a link to a WebDAV resource
2445  // need to use MediaType to check for link usability
2446  OUString aMediaType;
2447  aCnt.getPropertyValue("MediaType") >>= aMediaType;
2448  bUseRemote = !aMediaType.isEmpty();
2449  }
2450  }
2451  catch ( ... )
2452  {
2453  // this file did not exist, so we will not set this as graphiclink
2454  bUseRemote = false;
2455  }
2456  return bUseRemote;
2457 }
2458 
2459 // "INCLUDEPICTURE"
2461 {
2462  OUString aGrfName;
2463  bool bEmbedded = true;
2464 
2465  WW8ReadFieldParams aReadParam( rStr );
2466  for (;;)
2467  {
2468  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2469  if ( nRet==-1 )
2470  break;
2471  switch( nRet )
2472  {
2473  case -2:
2474  if (aGrfName.isEmpty())
2475  aGrfName = ConvertFFileName(aReadParam.GetResult());
2476  break;
2477 
2478  case 'd':
2479  bEmbedded = false;
2480  break;
2481 
2482  case 'c':// skip the converter name
2483  aReadParam.FindNextStringPiece();
2484  break;
2485  }
2486  }
2487 
2488  if (!bEmbedded)
2489  bEmbedded = !CanUseRemoteLink(aGrfName);
2490 
2491  if (!bEmbedded)
2492  {
2493  /*
2494  Special case:
2495 
2496  Now we write the Link into the Doc and remember the SwFlyFrameFormat.
2497  Since we end on return FLD_READ_FSPA below, the skip value will be set
2498  so that Char-1 will still be read.
2499  When we then call SwWW8ImplReader::ImportGraf() it will then recognize
2500  that we have inserted a graphic link and the suiting SwAttrSet will be
2501  inserted into the frame format.
2502  */
2504  aFlySet.Put( SwFormatAnchor( RndStdIds::FLY_AS_CHAR ) );
2505  aFlySet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
2508  aGrfName,
2509  OUString(),
2510  nullptr, // Graphic*
2511  &aFlySet,
2512  nullptr, nullptr); // SwFrameFormat*
2514  INetURLObject(aGrfName).GetBase());
2515  }
2516  return eF_ResT::READ_FSPA;
2517 }
2518 
2520 {
2521  const OUString aName(msFileLinkSeed + OUString::number(++mnFileSectionNo));
2522  return mrDoc.GetUniqueSectionName(&aName);
2523 }
2524 
2525 // "INCLUDETEXT"
2527 {
2528  OUString aPara;
2529  OUString aBook;
2530  WW8ReadFieldParams aReadParam( rStr );
2531  for (;;)
2532  {
2533  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2534  if ( nRet==-1 )
2535  break;
2536  switch( nRet )
2537  {
2538  case -2:
2539  if( aPara.isEmpty() )
2540  aPara = aReadParam.GetResult();
2541  else if( aBook.isEmpty() )
2542  aBook = aReadParam.GetResult();
2543  break;
2544  case '*':
2545  //Skip over MERGEFORMAT
2546  (void)aReadParam.SkipToNextToken();
2547  break;
2548  }
2549  }
2550  aPara = ConvertFFileName(aPara);
2551 
2552  if (!aBook.isEmpty() && aBook[ 0 ] != '\\')
2553  {
2554  // Section from Source (no switch)?
2555  ConvertUFName(aBook);
2556  aPara += OUStringChar(sfx2::cTokenSeparator)
2557  + OUStringChar(sfx2::cTokenSeparator) + aBook;
2558  }
2559 
2560  /*
2561  ##509##
2562  What we will do is insert a section to be linked to a file, but just in
2563  case the file is not available we will fill in the section with the stored
2564  content of this winword field as a fallback.
2565  */
2566  SwPosition aTmpPos(*m_pPaM->GetPoint());
2567 
2570  aSection.SetLinkFileName( aPara );
2571  aSection.SetProtectFlag(true);
2572 
2573  SwSection *const pSection =
2574  m_rDoc.InsertSwSection(*m_pPaM, aSection, nullptr, nullptr, false);
2575  OSL_ENSURE(pSection, "no section inserted");
2576  if (!pSection)
2577  return eF_ResT::TEXT;
2578  const SwSectionNode* pSectionNode = pSection->GetFormat()->GetSectionNode();
2579  OSL_ENSURE(pSectionNode, "no section node!");
2580  if (!pSectionNode)
2581  return eF_ResT::TEXT;
2582 
2583  m_pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
2585 
2586  //we have inserted a section before this point, so adjust pos
2587  //for future page/section segment insertion
2589 
2590  return eF_ResT::TEXT;
2591 }
2592 
2593 // "SERIALPRINT"
2595 {
2596 #if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
2597  (void) pF;
2598  (void) rStr;
2599 #else
2600  OUString aName;
2601  WW8ReadFieldParams aReadParam( rStr );
2602  for (;;)
2603  {
2604  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2605  if ( nRet==-1 )
2606  break;
2607  switch( nRet )
2608  {
2609  case -2:
2610  if( aName.isEmpty() )
2611  aName = aReadParam.GetResult();
2612  break;
2613  }
2614  }
2615  SwDBFieldType aD( &m_rDoc, aName, SwDBData() ); // Database: nothing
2616 
2618  SwDBField aField( static_cast<SwDBFieldType*>(pFT) );
2619  aField.SetFieldCode( rStr );
2620 
2621  OUString aResult;
2622  m_xSBase->WW8ReadString( *m_pStrm, aResult, m_xPlcxMan->GetCpOfs()+
2623  pF->nSRes, pF->nLRes, m_eTextCharSet );
2624 
2625  aResult = aResult.replace( '\xb', '\n' );
2626 
2627  aField.InitContent(aResult);
2628 
2630 #endif
2631  return eF_ResT::OK;
2632 }
2633 
2634 // "NEXT"
2636 {
2637 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
2640  SwDBNextSetField aField( static_cast<SwDBNextSetFieldType*>(pFT), OUString(),
2641  SwDBData() ); // Database: nothing
2643 #endif
2644  return eF_ResT::OK;
2645 }
2646 
2647 // "DATASET"
2649 {
2650 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
2653  SwDBSetNumberField aField( static_cast<SwDBSetNumberFieldType*>(pFT),
2654  SwDBData() ); // Datenbase: nothing
2656 #endif
2657  return eF_ResT::OK;
2658 }
2659 
2660 /*
2661  EQ , only the usage for
2662  a. Combined Characters supported, must be exactly in the form that word
2663  only accepts as combined characters, i.e.
2664  eq \o(\s\up Y(XXX),\s\do Y(XXX))
2665  b. Ruby Text supported, must be in the form that word recognizes as being
2666  ruby text
2667  ...
2668 */
2670 {
2671  WW8ReadFieldParams aReadParam( rStr );
2672  const sal_Int32 cChar = aReadParam.SkipToNextToken();
2673  if ('o' == cChar || 'O' == cChar)
2674  {
2675  EquationResult aResult(ParseCombinedChars(rStr));
2676 
2677  if (aResult.sType == "Input")
2678  {
2679  SwInputField aField( static_cast<SwInputFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Input )),
2680  aResult.sResult, aResult.sResult, INP_TXT, 0 );
2681  m_rDoc.getIDocumentContentOperations().InsertPoolItem( *m_pPaM, SwFormatField( aField ) ); // insert input field
2682  }
2683  else if (aResult.sType == "CombinedCharacters")
2684  {
2685  SwCombinedCharField aField(static_cast<SwCombinedCharFieldType*>(
2688  }
2689  }
2690  else if ('*' == cChar)
2691  Read_SubF_Ruby(aReadParam);
2692 
2693  return eF_ResT::OK;
2694 }
2695 
2697 {
2698  sal_uInt16 nJustificationCode=0;
2699  OUString sFontName;
2700  sal_uInt32 nFontSize=0;
2701  OUString sRuby;
2702  OUString sText;
2703  for (;;)
2704  {
2705  const sal_Int32 nRet = rReadParam.SkipToNextToken();
2706  if ( nRet==-1 )
2707  break;
2708  switch( nRet )
2709  {
2710  case -2:
2711  {
2712  OUString sTemp = rReadParam.GetResult();
2713  if( sTemp.startsWithIgnoreAsciiCase( "jc" ) )
2714  {
2715  sTemp = sTemp.copy(2);
2716  nJustificationCode = o3tl::narrowing<sal_uInt16>(sTemp.toInt32());
2717  }
2718  else if( sTemp.startsWithIgnoreAsciiCase( "hps" ) )
2719  {
2720  sTemp = sTemp.copy(3);
2721  nFontSize= static_cast<sal_uInt32>(sTemp.toInt32());
2722  }
2723  else if( sTemp.startsWithIgnoreAsciiCase( "Font:" ) )
2724  {
2725  sTemp = sTemp.copy(5);
2726  sFontName = sTemp;
2727  }
2728  }
2729  break;
2730  case '*':
2731  break;
2732  case 'o':
2733  for (;;)
2734  {
2735  const sal_Int32 nRes = rReadParam.SkipToNextToken();
2736  if ( nRes==-1 )
2737  break;
2738  if ('u' == nRes)
2739  {
2740  if (-2 == rReadParam.SkipToNextToken() &&
2741  rReadParam.GetResult().startsWithIgnoreAsciiCase("p"))
2742  {
2743  if (-2 == rReadParam.SkipToNextToken())
2744  {
2745  OUString sPart = rReadParam.GetResult();
2746  sal_Int32 nBegin = sPart.indexOf('(');
2747 
2748  //Word disallows brackets in this field,
2749  sal_Int32 nEnd = sPart.indexOf(')');
2750 
2751  if ((nBegin != -1) &&
2752  (nEnd != -1) && (nBegin < nEnd))
2753  {
2754  sRuby = sPart.copy(nBegin+1,nEnd-nBegin-1);
2755  }
2756  if (-1 != nEnd)
2757  {
2758  nBegin = sPart.indexOf(',',nEnd);
2759  if (-1 == nBegin)
2760  {
2761  nBegin = sPart.indexOf(';',nEnd);
2762  }
2763  nEnd = sPart.lastIndexOf(')');
2764  }
2765  if ((nBegin != -1) && (nEnd != -1) && (nBegin < nEnd))
2766  {
2767  sText = sPart.copy(nBegin+1,nEnd-nBegin-1);
2768  sText = sw::FilterControlChars(sText);
2769  }
2770  }
2771  }
2772  }
2773  }
2774  break;
2775  }
2776  }
2777 
2778  //Translate and apply
2779  if (sRuby.isEmpty() || sText.isEmpty() || sFontName.isEmpty() || !nFontSize)
2780  return;
2781 
2782  css::text::RubyAdjust eRubyAdjust;
2783  switch (nJustificationCode)
2784  {
2785  case 0:
2786  eRubyAdjust = css::text::RubyAdjust_CENTER;
2787  break;
2788  case 1:
2789  eRubyAdjust = css::text::RubyAdjust_BLOCK;
2790  break;
2791  case 2:
2792  eRubyAdjust = css::text::RubyAdjust_INDENT_BLOCK;
2793  break;
2794  default:
2795  case 3:
2796  eRubyAdjust = css::text::RubyAdjust_LEFT;
2797  break;
2798  case 4:
2799  eRubyAdjust = css::text::RubyAdjust_RIGHT;
2800  break;
2801  }
2802 
2803  SwFormatRuby aRuby(sRuby);
2804  const SwCharFormat *pCharFormat=nullptr;
2805  //Make a guess at which of asian of western we should be setting
2806  assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
2807  sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
2808 
2809  //Check to see if we already have a ruby charstyle that this fits
2810  for(const auto& rpCharFormat : m_aRubyCharFormats)
2811  {
2812  const SvxFontHeightItem &rFH =
2813  rpCharFormat->GetFormatAttr(
2815  if (rFH.GetHeight() == nFontSize*10)
2816  {
2817  const SvxFontItem &rF = rpCharFormat->GetFormatAttr(
2819  if (rF.GetFamilyName() == sFontName)
2820  {
2821  pCharFormat = rpCharFormat;
2822  break;
2823  }
2824  }
2825  }
2826 
2827  //Create a new char style if necessary
2828  if (!pCharFormat)
2829  {
2830  OUString aNm;
2831  //Take this as the base name
2833  aNm+=OUString::number(m_aRubyCharFormats.size()+1);
2835  SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
2836  SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
2837  OUString(), PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
2838  aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2839  aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
2840  pFormat->SetFormatAttr(aHeightItem);
2841  pFormat->SetFormatAttr(aFontItem);
2842  m_aRubyCharFormats.push_back(pFormat);
2843  pCharFormat = pFormat;
2844  }
2845 
2846  //Set the charstyle and justification
2847  aRuby.SetCharFormatName(pCharFormat->GetName());
2848  aRuby.SetCharFormatId(pCharFormat->GetPoolFormatId());
2849  aRuby.SetAdjustment(eRubyAdjust);
2850 
2851  NewAttr(aRuby);
2854 
2855 }
2856 
2857 // "table of ..." fields
2858 
2859 static void lcl_toxMatchACSwitch(SwDoc const & rDoc,
2860  SwTOXBase& rBase,
2861  WW8ReadFieldParams& rParam,
2862  SwCaptionDisplay eCaptionType)
2863 {
2864  if ( rParam.GoToTokenParam() )
2865  {
2866  SwTOXType* pType = const_cast<SwTOXType*>(rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0));
2867  rBase.RegisterToTOXType( *pType );
2868  rBase.SetCaptionDisplay( eCaptionType );
2869  // Read Sequence Name and store in TOXBase
2870  OUString sSeqName( rParam.GetResult() );
2871  lcl_ConvertSequenceName( sSeqName );
2872  rBase.SetSequenceName( sSeqName );
2873  }
2874 }
2875 
2877 {
2878  //If the TOC contains Template entries at levels > the evaluation level
2879  //that was initially taken from the max normal outline level of the word TOC
2880  //then we cannot use that for the evaluation level because writer cuts off
2881  //all styles above that level, while word just cuts off the "standard"
2882  //outline styles, we have no option but to expand to the highest level
2883  //Word included.
2884  if ((rBase.GetLevel() != MAXLEVEL) && (SwTOXElement::Template & rBase.GetCreateType()))
2885  {
2886  for (sal_uInt16 nI = MAXLEVEL; nI > 0; --nI)
2887  {
2888  if (!rBase.GetStyleNames(nI-1).isEmpty())
2889  {
2890  rBase.SetLevel(nI);
2891  break;
2892  }
2893  }
2894  }
2895 }
2896 
2897 static void lcl_toxMatchTSwitch(SwWW8ImplReader const & rReader, SwTOXBase& rBase,
2898  WW8ReadFieldParams& rParam)
2899 {
2900  if ( !rParam.GoToTokenParam() )
2901  return;
2902 
2903  OUString sParams( rParam.GetResult() );
2904  if( sParams.isEmpty() )
2905  return;
2906 
2907  sal_Int32 nIndex = 0;
2908 
2909  // Delimiters between styles and style levels appears to allow both ; and ,
2910 
2911  OUString sTemplate( sParams.getToken(0, ';', nIndex) );
2912  if( -1 == nIndex )
2913  {
2914  nIndex=0;
2915  sTemplate = sParams.getToken(0, ',', nIndex);
2916  }
2917  if( -1 == nIndex )
2918  {
2919  const SwFormat* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
2920  if( pStyle )
2921  sTemplate = pStyle->GetName();
2922  // Store Style for Level 0 into TOXBase
2923  rBase.SetStyleNames( sTemplate, 0 );
2924  }
2925  else while( -1 != nIndex )
2926  {
2927  sal_Int32 nOldIndex=nIndex;
2928  sal_uInt16 nLevel = o3tl::narrowing<sal_uInt16>(
2929  o3tl::toInt32(o3tl::getToken(sParams, 0, ';', nIndex)));
2930  if( -1 == nIndex )
2931  {
2932  nIndex = nOldIndex;
2933  nLevel = o3tl::narrowing<sal_uInt16>(
2934  o3tl::toInt32(o3tl::getToken(sParams, 0, ',', nIndex)));
2935  }
2936 
2937  if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
2938  {
2939  nLevel--;
2940  // Store Style and Level into TOXBase
2941  const SwFormat* pStyle
2942  = rReader.GetStyleWithOrgWWName( sTemplate );
2943 
2944  if( pStyle )
2945  sTemplate = pStyle->GetName();
2946 
2947  OUString sStyles( rBase.GetStyleNames( nLevel ) );
2948  if( !sStyles.isEmpty() )
2949  sStyles += OUStringChar(TOX_STYLE_DELIMITER);
2950  sStyles += sTemplate;
2951  rBase.SetStyleNames( sStyles, nLevel );
2952  }
2953  // read next style name...
2954  nOldIndex = nIndex;
2955  sTemplate = sParams.getToken(0, ';', nIndex);
2956  if( -1 == nIndex )
2957  {
2958  nIndex=nOldIndex;
2959  sTemplate = sParams.getToken(0, ',', nIndex);
2960  }
2961  }
2962 }
2963 
2965 {
2966  sal_uInt16 nIndexCols = 1;
2967  if (!maSegments.empty())
2968  nIndexCols = maSegments.back().maSep.ccolM1 + 1;
2969  return nIndexCols;
2970 }
2971 
2972 //Will there be a new pagebreak at this position (don't know what type
2973 //until later)
2975 {
2976  bool bRet = false;
2977  if (!maSegments.empty())
2978  {
2979  if (!maSegments.back().IsContinuous() &&
2980  maSegments.back().maStart == rIdx)
2981  {
2982  bRet = true;
2983  }
2984  }
2985  return bRet;
2986 }
2987 
2988 static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
2989 {
2990  // GetFormMax() returns level + 1, hence the -1
2991  sal_uInt16 nRet = rForm.GetFormMax()-1;
2992 
2993  // If the max of this type of TOC is greater than the max of a word
2994  // possible toc, then clip to the word max
2995  if (nRet > WW8ListManager::nMaxLevel)
2997 
2998  return nRet;
2999 }
3000 
3002 {
3003  if (!m_bLoadingTOXCache)
3004  {
3005  m_bLoadingTOXCache = true;
3006  }
3007  else
3008  {
3009  // Embedded TOX --> continue reading its content, but no further TOX
3010  // field
3012  return eF_ResT::TEXT;
3013  }
3014 
3015  if (pF->nLRes < 3)
3016  return eF_ResT::TEXT; // ignore (#i25440#)
3017 
3018  TOXTypes eTox; // create a ToxBase
3019  switch( pF->nId )
3020  {
3021  case 8:
3022  eTox = TOX_INDEX;
3023  break;
3024  case 13:
3025  eTox = TOX_CONTENT;
3026  break;
3027  default:
3028  eTox = TOX_USER;
3029  break;
3030  }
3031 
3033 
3034  sal_uInt16 nIndexCols = 1;
3035 
3036  const SwTOXType* pType = m_rDoc.GetTOXType( eTox, 0 );
3037  SwForm aOrigForm(eTox);
3038  std::shared_ptr<SwTOXBase> pBase = std::make_shared<SwTOXBase>( pType, aOrigForm, nCreateOf, OUString() );
3039  pBase->SetProtected(m_aSectionManager.CurrentSectionIsProtected());
3040  switch( eTox ){
3041  case TOX_INDEX:
3042  {
3044 
3045  // We set SwTOXElement::OutlineLevel only if
3046  // the parameter \o is within 1 to 9
3047  // or the parameter \f exists
3048  // or NO switch parameter are given at all.
3049  WW8ReadFieldParams aReadParam( rStr );
3050  for (;;)
3051  {
3052  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3053  if ( nRet==-1 )
3054  break;
3055  switch( nRet )
3056  {
3057  case 'c':
3058  if ( aReadParam.GoToTokenParam() )
3059  {
3060  const OUString sParams( aReadParam.GetResult() );
3061  // if NO OUString just ignore the \c
3062  if( !sParams.isEmpty() )
3063  {
3064  nIndexCols = o3tl::narrowing<sal_uInt16>(sParams.toInt32());
3065  }
3066  }
3067  break;
3068  case 'e':
3069  {
3070  if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \e
3071  {
3072  OUString sDelimiter( aReadParam.GetResult() );
3073  SwForm aForm( pBase->GetTOXForm() );
3074 
3075  // Attention: if TOX_CONTENT brave
3076  // GetFormMax() returns MAXLEVEL + 1 !!
3077  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3078 
3079  for(sal_uInt16 nLevel = 1;
3080  nLevel <= nEnd;
3081  ++nLevel)
3082  {
3083  // Levels count from 1
3084  // Level 0 is reserved for CAPTION
3085 
3086  // Insert delimiter instead of tab in front of the page number if there is one:
3087  FormTokenType ePrevType = TOKEN_END;
3089  // -> #i21237#
3090  SwFormTokens aPattern =
3091  aForm.GetPattern(nLevel);
3092  SwFormTokens::iterator aIt = aPattern.begin();
3093  do
3094  {
3095  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3096 
3097  if (eType == TOKEN_PAGE_NUMS)
3098  {
3099  if (TOKEN_TAB_STOP == ePrevType)
3100  {
3101  --aIt;
3102 
3103  if(0x09 == sDelimiter[0])
3104  aIt->eTabAlign = SvxTabAdjust::End;
3105  else
3106  {
3107  SwFormToken aToken(TOKEN_TEXT);
3108  aToken.sText = sDelimiter;
3109  *aIt = aToken;
3110  }
3111  aForm.SetPattern(nLevel, std::move(aPattern));
3112  }
3113 
3114  eType = TOKEN_END;
3115  }
3116 
3117  ePrevType = eType;
3118  }
3119  while (TOKEN_END != eType);
3120  // <- #i21237#
3121  }
3122  pBase->SetTOXForm( aForm );
3123  }
3124  }
3125  break;
3126  case 'h':
3127  {
3128  eOptions |= SwTOIOptions::AlphaDelimiter;
3129  }
3130  break;
3131  }
3132  }
3133  pBase->SetOptions( eOptions );
3134  }
3135  break;
3136 
3137  case TOX_CONTENT:
3138  {
3139  bool bIsHyperlink = false;
3140  // We set SwTOXElement::OutlineLevel only if
3141  // the parameter \o is within 1 to 9
3142  // or the parameter \f exists
3143  // or NO switch parameter are given at all.
3144  SwTOXElement eCreateFrom = SwTOXElement::NONE;
3145  sal_Int32 nMaxLevel = 0;
3146  WW8ReadFieldParams aReadParam( rStr );
3147  for (;;)
3148  {
3149  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3150  if ( nRet==-1 )
3151  break;
3152  switch( nRet )
3153  {
3154  case 'h':
3155  bIsHyperlink = true;
3156  break;
3157  case 'a':
3158  case 'c':
3159  lcl_toxMatchACSwitch(m_rDoc, *pBase, aReadParam,
3160  ('c' == nRet)
3162  : CAPTION_TEXT );
3163  break;
3164  case 'o':
3165  {
3166  sal_Int32 nVal;
3167  if( !aReadParam.GetTokenSttFromTo(nullptr, &nVal, WW8ListManager::nMaxLevel) )
3168  nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
3169  if( nMaxLevel < nVal )
3170  nMaxLevel = nVal;
3171  eCreateFrom |= SwTOXElement::OutlineLevel;
3172  }
3173  break;
3174  case 'f':
3175  eCreateFrom |= SwTOXElement::Mark;
3176  break;
3177  case 'l':
3178  {
3179  sal_Int32 nVal;
3180  if( aReadParam.GetTokenSttFromTo(nullptr, &nVal, WW8ListManager::nMaxLevel) )
3181  {
3182  if( nMaxLevel < nVal )
3183  nMaxLevel = nVal;
3184  eCreateFrom |= SwTOXElement::Mark;
3185  }
3186  }
3187  break;
3188  case 't': // paragraphs using special styles shall
3189  // provide the TOX's content
3190  lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
3191  eCreateFrom |= SwTOXElement::Template;
3192  break;
3193  case 'p':
3194  {
3195  if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \p
3196  {
3197  OUString sDelimiter( aReadParam.GetResult() );
3198  SwForm aForm( pBase->GetTOXForm() );
3199 
3200  // Attention: if TOX_CONTENT brave
3201  // GetFormMax() returns MAXLEVEL + 1 !!
3202  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3203 
3204  for(sal_uInt16 nLevel = 1;
3205  nLevel <= nEnd;
3206  ++nLevel)
3207  {
3208  // Levels count from 1
3209  // Level 0 is reserved for CAPTION
3210 
3211  // Insert delimiter instead of tab in front of the pagenumber if there is one:
3212  FormTokenType ePrevType = TOKEN_END;
3214 
3215  // -> #i21237#
3216  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3217  SwFormTokens::iterator aIt = aPattern.begin();
3218  do
3219  {
3220  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3221 
3222  if (eType == TOKEN_PAGE_NUMS)
3223  {
3224  if (TOKEN_TAB_STOP == ePrevType)
3225  {
3226  --aIt;
3227 
3228  SwFormToken aToken(TOKEN_TEXT);
3229  aToken.sText = sDelimiter;
3230 
3231  *aIt = aToken;
3232  aForm.SetPattern(nLevel,
3233  std::move(aPattern));
3234  }
3235  eType = TOKEN_END;
3236  }
3237  ePrevType = eType;
3238  }
3239  while( TOKEN_END != eType );
3240  // <- #i21237#
3241  }
3242  pBase->SetTOXForm( aForm );
3243  }
3244  }
3245  break;
3246  case 'n': // don't print page numbers
3247  {
3248  // read START and END param
3249  sal_Int32 nStart(0);
3250  sal_Int32 nEnd(0);
3251  if( !aReadParam.GetTokenSttFromTo( &nStart, &nEnd,
3253  {
3254  nStart = 1;
3255  nEnd = aOrigForm.GetFormMax()-1;
3256  }
3257  // remove page numbers from this levels
3258  SwForm aForm( pBase->GetTOXForm() );
3259  if (aForm.GetFormMax() <= nEnd)
3260  nEnd = aForm.GetFormMax()-1;
3261  for ( sal_Int32 nLevel = nStart; nLevel<=nEnd; ++nLevel )
3262  {
3263  // Levels count from 1
3264  // Level 0 is reserved for CAPTION
3265 
3266  // Remove pagenumber and if necessary the tab in front of it:
3268  // -> #i21237#
3269  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3270  SwFormTokens::iterator aIt = aPattern.begin();
3271  do
3272  {
3273  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3274 
3275  if (eType == TOKEN_PAGE_NUMS)
3276  {
3277  aIt = aPattern.erase(aIt);
3278  --aIt;
3279  if (
3280  TOKEN_TAB_STOP ==
3281  aIt->eTokenType
3282  )
3283  {
3284  aPattern.erase(aIt);
3285  aForm.SetPattern(nLevel, std::move(aPattern));
3286  }
3287  eType = TOKEN_END;
3288  }
3289  }
3290  while (TOKEN_END != eType);
3291  // <- #i21237#
3292  }
3293  pBase->SetTOXForm( aForm );
3294  }
3295  break;
3296 
3297  /*
3298  // the following switches are not (yet) supported
3299  // by good old StarWriter:
3300  case 'b':
3301  case 's':
3302  case 'd':
3303  break;
3304  */
3305  }
3306  }
3307 
3308  // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens
3309  // also include the hyperlinks and page references
3310  SwFormToken aLinkStart(TOKEN_LINK_START);
3311  SwFormToken aLinkEnd(TOKEN_LINK_END);
3312  aLinkStart.sCharStyleName = "Index Link";
3313  aLinkEnd.sCharStyleName = "Index Link";
3314  SwForm aForm(pBase->GetTOXForm());
3315  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3316 
3317  for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
3318  {
3319  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3320  if ( bIsHyperlink )
3321  {
3322  aPattern.insert(aPattern.begin(), aLinkStart);
3323  }
3324  else
3325  {
3326  auto aItr = std::find_if(aPattern.begin(), aPattern.end(),
3327  [](const SwFormToken& rToken) { return rToken.eTokenType == TOKEN_PAGE_NUMS; });
3328  if (aItr != aPattern.end())
3329  aPattern.insert(aItr, aLinkStart);
3330  }
3331  aPattern.push_back(aLinkEnd);
3332  aForm.SetPattern(nLevel, std::move(aPattern));
3333  }
3334  pBase->SetTOXForm(aForm);
3335 
3336  if (!nMaxLevel)
3337  nMaxLevel = WW8ListManager::nMaxLevel;
3338  pBase->SetLevel(nMaxLevel);
3339 
3340  const TOXTypes eType = pBase->GetTOXType()->GetType();
3341  switch( eType )
3342  {
3343  case TOX_CONTENT:
3344  {
3345  //If we would be created from outlines, either explicitly or by default
3346  //then see if we need extra styles added to the outlines
3347  SwTOXElement eEffectivelyFrom = eCreateFrom != SwTOXElement::NONE ? eCreateFrom : SwTOXElement::OutlineLevel;
3348  if (eEffectivelyFrom & SwTOXElement::OutlineLevel)
3349  {
3350  // #i19683# Insert a text token " " between the number and entry token.
3351  // In an ideal world we could handle the tab stop between the number and
3352  // the entry correctly, but I currently have no clue how to obtain
3353  // the tab stop position. It is _not_ set at the paragraph style.
3354  std::unique_ptr<SwForm> pForm;
3355  for (const SwWW8StyInf & rSI : m_vColl)
3356  {
3357  if (rSI.IsOutlineNumbered())
3358  {
3359  sal_uInt16 nStyleLevel = rSI.mnWW8OutlineLevel;
3360  const SwNumFormat& rFormat = rSI.GetOutlineNumrule()->Get( nStyleLevel );
3361  if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
3362  {
3363  ++nStyleLevel;
3364 
3365  if ( !pForm )
3366  pForm.reset(new SwForm( pBase->GetTOXForm() ));
3367 
3368  SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
3369  SwFormTokens::iterator aIt =
3370  find_if(aPattern.begin(), aPattern.end(),
3372 
3373  if ( aIt != aPattern.end() )
3374  {
3375  SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
3376  aNumberEntrySeparator.sText = " ";
3377  aPattern.insert( ++aIt, aNumberEntrySeparator );
3378  pForm->SetPattern( nStyleLevel, std::move(aPattern) );
3379  }
3380  }
3381  }
3382  }
3383  if ( pForm )
3384  {
3385  pBase->SetTOXForm( *pForm );
3386  }
3387  }
3388 
3389  if (eCreateFrom != SwTOXElement::NONE)
3390  pBase->SetCreate(eCreateFrom);
3392  }
3393  break;
3394  case TOX_ILLUSTRATIONS:
3395  {
3396  if( eCreateFrom == SwTOXElement::NONE )
3397  eCreateFrom = SwTOXElement::Sequence;
3398  pBase->SetCreate( eCreateFrom );
3399 
3400  /*
3401  We don't know until here if we are an illustration
3402  or not, and so have being used a TOX_CONTENT so far
3403  which has 10 levels, while TOX has only two, this
3404  level is set only in the constructor of SwForm, so
3405  create a new one and copy over anything that could
3406  be set in the old one, and remove entries from the
3407  pattern which do not apply to illustration indices
3408  */
3409  SwForm aOldForm( pBase->GetTOXForm() );
3410  SwForm aNewForm( eType );
3411  sal_uInt16 nNewEnd = aNewForm.GetFormMax()-1;
3412 
3413  // #i21237#
3414  for(sal_uInt16 nLevel = 1; nLevel <= nNewEnd; ++nLevel)
3415  {
3416  SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
3417  SwFormTokens::iterator new_end =
3418  remove_if(aPattern.begin(), aPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3419  aPattern.erase(new_end, aPattern.end() ); // table index imported with wrong page number format
3420  aForm.SetPattern( nLevel, std::move(aPattern) );
3421  aForm.SetTemplate( nLevel, aOldForm.GetTemplate(nLevel) );
3422  }
3423 
3424  pBase->SetTOXForm( aNewForm );
3425  }
3426  break;
3427  default:
3428  OSL_ENSURE(false, "Unhandled toc options!");
3429  break;
3430  }
3431  }
3432  break;
3433  case TOX_USER:
3434  break;
3435  default:
3436  OSL_ENSURE(false, "Unhandled toc options!");
3437  break;
3438  } // ToxBase fertig
3439 
3440  // #i21237# - propagate tab stops from paragraph styles used in TOX to patterns of the TOX
3441  pBase->AdjustTabStops( m_rDoc );
3442 
3443  //#i10028# inserting a toc implicitly acts like a parabreak in word and writer
3444  if ( m_pPaM->End() &&
3445  m_pPaM->End()->nNode.GetNode().GetTextNode() &&
3446  m_pPaM->End()->nNode.GetNode().GetTextNode()->Len() != 0 )
3447  {
3448  m_bCareFirstParaEndInToc = true;
3449  }
3450 
3451  if (m_pPaM->GetPoint()->nContent.GetIndex())
3453 
3454  const SwPosition* pPos = m_pPaM->GetPoint();
3455 
3456  SwFltTOX aFltTOX( pBase );
3457 
3458  // test if there is already a break item on this node
3459  if(SwContentNode* pNd = pPos->nNode.GetNode().GetContentNode())
3460  {
3461  const SfxItemSet* pSet = pNd->GetpSwAttrSet();
3462  if( pSet )
3463  {
3464  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false))
3465  aFltTOX.SetHadBreakItem(true);
3466  if (SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false))
3467  aFltTOX.SetHadPageDescItem(true);
3468  }
3469  }
3470 
3471  //Will there be a new pagebreak at this position (don't know what type
3472  //until later)
3474  aFltTOX.SetHadPageDescItem(true);
3475 
3476  // Set start in stack
3477  m_xReffedStck->NewAttr( *pPos, aFltTOX );
3478 
3479  m_rDoc.InsertTableOf(*m_pPaM->GetPoint(), aFltTOX.GetBase());
3480 
3481  //The TOC field representation contents should be inserted into TOC section, but not after TOC section.
3482  //So we need update the document position when loading TOC representation and after loading TOC;
3483  m_pPosAfterTOC.reset(new SwPaM(*m_pPaM, m_pPaM));
3484  (*m_pPaM).Move(fnMoveBackward);
3485  SwPaM aRegion(*m_pPaM, m_pPaM);
3486 
3487  OSL_ENSURE(SwDoc::GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
3488  if (SwTOXBase* pBase2 = SwDoc::GetCurTOX(*aRegion.GetPoint()))
3489  {
3490  pBase2->SetMSTOCExpression(rStr);
3491 
3492  if ( nIndexCols > 1 )
3493  {
3494  // Set the column number for index
3496  SwFormatCol aCol;
3497  aCol.Init( nIndexCols, 708, USHRT_MAX );
3498  aSet.Put( aCol );
3499  pBase2->SetAttrSet( aSet );
3500  }
3501 
3502  // inserting a toc inserts a section before this point, so adjust pos
3503  // for future page/section segment insertion
3504  m_aSectionManager.PrependedInlineNode( *m_pPosAfterTOC->GetPoint(), aRegion.GetNode() );
3505  }
3506 
3507  // Set end in stack
3508  m_xReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
3509 
3510  if (!m_aApos.back()) //a para end in apo doesn't count
3511  m_bWasParaEnd = true;
3512 
3513  //Return FLD_TEXT, instead of FLD_OK
3514  //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed
3515  //FLD_OK means the current field loading is finished. The rest part should be ignored.
3516  return eF_ResT::TEXT;
3517 }
3518 
3520 {
3521  /*
3522  #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3523  to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3524  the drawing that we are in the Shape field and respond accordingly
3525  */
3526  return eF_ResT::TEXT;
3527  }
3528 
3530 {
3531  OUString sURL, sTarget, sMark;
3532 
3533  //HYPERLINK "filename" [switches]
3534  rStr = comphelper::string::stripEnd(rStr, 1);
3535 
3536  bool bOptions = false;
3537  WW8ReadFieldParams aReadParam( rStr );
3538  for (;;)
3539  {
3540  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3541  if ( nRet==-1 )
3542  break;
3543  switch( nRet )
3544  {
3545  case -2:
3546  if (sURL.isEmpty() && !bOptions)
3547  sURL = ConvertFFileName(aReadParam.GetResult());
3548  break;
3549 
3550  case 'n':
3551  sTarget = "_blank";
3552  bOptions = true;
3553  break;
3554 
3555  case 'l':
3556  bOptions = true;
3557  if ( aReadParam.SkipToNextToken()==-2 )
3558  {
3559  sMark = aReadParam.GetResult();
3560  if( sMark.endsWith("\""))
3561  {
3562  sMark = sMark.copy( 0, sMark.getLength() - 1 );
3563  }
3564  // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
3565  if ( IsTOCBookmarkName( sMark ) )
3566  {
3567  sMark = EnsureTOCBookmarkName(sMark);
3568  // track <sMark> as referenced TOC bookmark.
3569  m_xReffedStck->m_aReferencedTOCBookmarks.insert( sMark );
3570  }
3571 
3572  if (m_bLoadingTOXCache)
3573  {
3574  m_bLoadingTOXHyperlink = true; //on loading a TOC field nested hyperlink field
3575  }
3576  }
3577  break;
3578  case 't':
3579  bOptions = true;
3580  if ( aReadParam.SkipToNextToken()==-2 )
3581  sTarget = aReadParam.GetResult();
3582  break;
3583  case 'h':
3584  case 'm':
3585  OSL_ENSURE( false, "Analysis still missing - unknown data" );
3586  [[fallthrough]];
3587  case 's': //worthless fake anchor option
3588  bOptions = true;
3589  break;
3590  }
3591  }
3592 
3593  // use the result
3594  OSL_ENSURE(!sURL.isEmpty() || !sMark.isEmpty(), "WW8: Empty URL");
3595 
3596  if( !sMark.isEmpty() )
3597  sURL += "#" + sMark;
3598 
3599  SwFormatINetFormat aURL(sURL, sTarget);
3600  // If on loading TOC field, change the default style into the "index link"
3601  if (m_bLoadingTOXCache)
3602  {
3603  OUString sLinkStyle("Index Link");
3604  sal_uInt16 nPoolId =
3606  aURL.SetVisitedFormatAndId( sLinkStyle, nPoolId );
3607  aURL.SetINetFormatAndId( sLinkStyle, nPoolId );
3608  }
3609 
3610  //As an attribute this needs to be closed, and that'll happen from
3611  //EndExtSprm in conjunction with the maFieldStack. If there are flyfrms
3612  //between the start and begin, their hyperlinks will be set at that time
3613  //as well.
3614  m_xCtrlStck->NewAttr( *m_pPaM->GetPoint(), aURL );
3615  return eF_ResT::TEXT;
3616 }
3617 
3618 static void lcl_ImportTox(SwDoc &rDoc, SwPaM const &rPaM, const OUString &rStr, bool bIdx)
3619 {
3620  TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX; // Default
3621 
3622  sal_uInt16 nLevel = 1;
3623 
3624  OUString sFieldText;
3625  WW8ReadFieldParams aReadParam(rStr);
3626  for (;;)
3627  {
3628  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3629  if ( nRet==-1 )
3630  break;
3631  switch( nRet )
3632  {
3633  case -2:
3634  if( sFieldText.isEmpty() )
3635  {
3636  // PrimaryKey without ":", 2nd after
3637  sFieldText = aReadParam.GetResult();
3638  }
3639  break;
3640 
3641  case 'f':
3642  if ( aReadParam.GoToTokenParam() )
3643  {
3644  const OUString sParams( aReadParam.GetResult() );
3645  if( sParams[0]!='C' && sParams[0]!='c' )
3646  eTox = TOX_USER;
3647  }
3648  break;
3649 
3650  case 'l':
3651  if ( aReadParam.GoToTokenParam() )
3652  {
3653  const OUString sParams( aReadParam.GetResult() );
3654  // if NO String just ignore the \l
3655  if( !sParams.isEmpty() && sParams[0]>'0' && sParams[0]<='9' )
3656  {
3657  nLevel = o3tl::narrowing<sal_uInt16>(sParams.toInt32());
3658  }
3659  }
3660  break;
3661  }
3662  }
3663 
3664  OSL_ENSURE( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0 :-(" );
3665 
3666  const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
3667  SwTOXMark aM( pT );
3668 
3669  if( eTox != TOX_INDEX )
3670  aM.SetLevel( nLevel );
3671  else
3672  {
3673  sal_Int32 nFnd = sFieldText.indexOf( WW8_TOX_LEVEL_DELIM );
3674  if( -1 != nFnd ) // it exist levels
3675  {
3676  aM.SetPrimaryKey( sFieldText.copy( 0, nFnd ) );
3677  sal_Int32 nScndFnd = sFieldText.indexOf( WW8_TOX_LEVEL_DELIM, nFnd+1 );
3678  if( -1 != nScndFnd )
3679  {
3680  aM.SetSecondaryKey( sFieldText.copy( nFnd+1, nScndFnd - nFnd - 1 ));
3681  nFnd = nScndFnd;
3682  }
3683  sFieldText = sFieldText.copy( nFnd+1 );
3684  }
3685  }
3686 
3687  if (!sFieldText.isEmpty())
3688  {
3689  aM.SetAlternativeText( sFieldText );
3690  rDoc.getIDocumentContentOperations().InsertPoolItem( rPaM, aM );
3691  }
3692 }
3693 
3694 void SwWW8ImplReader::ImportTox( int nFieldId, const OUString& aStr )
3695 {
3696  bool bIdx = (nFieldId != 9);
3697  lcl_ImportTox(m_rDoc, *m_pPaM, aStr, bIdx);
3698 }
3699 
3700 void SwWW8ImplReader::Read_FieldVanish( sal_uInt16, const sal_uInt8*, short nLen )
3701 {
3702  //Meaningless in a style
3703  if (m_pCurrentColl || !m_xPlcxMan)
3704  return;
3705 
3706  const int nChunk = 64; //number of characters to read at one time
3707 
3708  // Careful: MEMICMP doesn't work with fieldnames including umlauts!
3709  const static char *aFieldNames[] = { "\x06""INHALT", "\x02""XE", // dt.
3710  "\x02""TC" }; // us
3711  const static sal_uInt8 aFieldId[] = { 9, 4, 9 };
3712 
3713  if( nLen < 0 )
3714  {
3715  m_bIgnoreText = false;
3716  return;
3717  }
3718 
3719  // our method was called from
3720  // ''Skip attributes of field contents'' loop within ReadTextAttr()
3721  if( m_bIgnoreText )
3722  return;
3723 
3724  m_bIgnoreText = true;
3725  sal_uInt64 nOldPos = m_pStrm->Tell();
3726 
3727  WW8_CP nStartCp = m_xPlcxMan->Where() + m_xPlcxMan->GetCpOfs();
3728 
3729  OUString sFieldName;
3730  sal_Int32 nFieldLen = m_xSBase->WW8ReadString( *m_pStrm, sFieldName, nStartCp,
3731  nChunk, m_eStructCharSet );
3732  nStartCp+=nFieldLen;
3733 
3734  sal_Int32 nC = 0;
3735  //If the first chunk did not start with a field start then
3736  //reset the stream position and give up
3737  if( !nFieldLen || sFieldName[nC]!=0x13 ) // Field Start Mark
3738  {
3739  // If Field End Mark found
3740  if( nFieldLen && sFieldName[nC]==0x15 )
3741  m_bIgnoreText = false;
3742  m_pStrm->Seek( nOldPos );
3743  return; // no field found
3744  }
3745 
3746  sal_Int32 nFnd;
3747  //If this chunk does not contain a field end, keep reading chunks
3748  //until we find one, or we run out of text,
3749  for (;;)
3750  {
3751  nFnd = sFieldName.indexOf(0x15);
3752  //found field end, we can stop now
3753  if (nFnd != -1)
3754  break;
3755  OUString sTemp;
3756  nFieldLen = m_xSBase->WW8ReadString( *m_pStrm, sTemp,
3757  nStartCp, nChunk, m_eStructCharSet );
3758  sFieldName+=sTemp;
3759  nStartCp+=nFieldLen;
3760  if (!nFieldLen)
3761  break;
3762  }
3763 
3764  m_pStrm->Seek( nOldPos );
3765 
3766  //if we have no 0x15 give up, otherwise erase everything from the 0x15
3767  //onwards
3768  if (nFnd<0)
3769  return;
3770 
3771  sFieldName = sFieldName.copy(0, nFnd);
3772 
3773  nC++;
3774  while ( sFieldName[nC]==' ' )
3775  nC++;
3776 
3777  for( int i = 0; i < 3; i++ )
3778  {
3779  const char* pName = aFieldNames[i];
3780  const sal_Int32 nNameLen = static_cast<sal_Int32>(*pName++);
3781  if( sFieldName.matchIgnoreAsciiCaseAsciiL( pName, nNameLen, nC ) )
3782  {
3783  ImportTox( aFieldId[i], sFieldName.copy( nC + nNameLen ) );
3784  break; // no duplicates allowed
3785  }
3786  }
3787  m_bIgnoreText = true;
3788  m_pStrm->Seek( nOldPos );
3789 }
3790 
3791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OString stripEnd(const OString &rIn, char c)
eF_ResT Read_F_Set(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2048
virtual void SetSubType(sal_uInt16 nType) override
Definition: expfld.cxx:890
SvxNumType GetNumberingType() const
Instances of SwFields and those derived from it occur 0 to n times.
Definition: fldbas.hxx:241
void InsertTagField(const sal_uInt16 nId, const OUString &rTagText)
Definition: ww8par5.cxx:1124
bool is() const
const SwDocInfoSubType DI_SUB_TIME
Definition: docufld.hxx:84
std::vector< SwFormToken > SwFormTokens
Vector of tokens.
Definition: tox.hxx:284
virtual sal_Int32 Len() const
Definition: node.cxx:1243
TOXTypes
Definition: toxe.hxx:39
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
Iterator for Booknotes.
Definition: ww8scan.hxx:750
std::unique_ptr< SwWW8FltControlStack > m_xCtrlStck
Definition: ww8par.hxx:1130
SVX_NUM_CHARS_UPPER_LETTER_N
bool bCodeNest
instruction used recursively
Definition: ww8scan.hxx:199
virtual void SetSubType(sal_uInt16 nSub) override
Definition: flddat.cxx:100
URL aURL
OUString msFileLinkSeed
Definition: ww8par.hxx:984
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:224
SwTOIOptions
Definition: tox.hxx:384
sal_Int32 nIndex
Handles the import of PlcfAtnBkf and PlcfAtnBkl: start / end position of annotation marks...
Definition: ww8scan.hxx:789
std::map< OUString, css::uno::Any > parameter_map_t
Definition: IMark.hxx:94
Marks a position in the document model.
Definition: pam.hxx:36
rtl_TextEncoding m_eStructCharSet
Definition: ww8par.hxx:1319
void Read_FieldVanish(sal_uInt16 nId, const sal_uInt8 *pData, short nLen)
Definition: ww8par5.cxx:3700
WW8FieldEntry(SwPosition const &rPos, sal_uInt16 nFieldId) noexcept
Definition: ww8par5.cxx:732
bool m_bLoadingTOXCache
Definition: ww8par.hxx:1397
SwTOXElement GetCreateType() const
Definition: tox.hxx:699
Size & Swap(Size &rSize)
eF_ResT Read_F_DateTime(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1825
static bool AcceptableNestedField(sal_uInt16 nFieldCode)
Definition: ww8par5.cxx:711
SwFlyFrameFormat * m_pFlyFormatOfJustInsertedGraphic
Definition: ww8par.hxx:1232
const SwTOXBase & GetBase() const
Definition: fltshell.hxx:270
"Page"
Definition: reffld.hxx:48
eF_ResT Read_F_Num(WW8FieldDesc *pF, OUString &)
Definition: ww8par5.cxx:1923
sal_uInt16 End_Field()
Definition: ww8par5.cxx:506
void SetLinkFileName(OUString const &rNew)
Definition: section.hxx:116
#define LANGUAGE_ENGLISH_US
SwCharFormat * MakeCharFormat(const OUString &rFormatName, SwCharFormat *pDerivedFrom, bool bBroadcast=false)
Definition: docfmt.cxx:854
WW8_CP nSCode
start of instructions code
Definition: ww8scan.hxx:193
virtual SwFlyFrameFormat * InsertGraphic(const SwPaM &rRg, const OUString &rGrfName, const OUString &rFltName, const Graphic *pGraphic, const SfxItemSet *pFlyAttrSet, const SfxItemSet *pGrfAttrSet, SwFrameFormat *)=0
Insert graphic or formula.
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1410
const SwExtendedSubType SUB_INVISIBLE
Invisible.
Definition: fldbas.hxx:213
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.
eINCLUDETEXT
void SetBookmarkType(const OUString &bookmarkType)
Definition: ww8par5.cxx:761
static void FillUIName(const OUString &rName, OUString &rFillName, SwGetPoolIdFromName)
void SetLevel(sal_uInt16 nLevel)
Definition: tox.hxx:590
sal_uInt32 GetFormatIndex(NfIndexTableOffset, LanguageType eLnge=LANGUAGE_DONTKNOW)
static SwTOXBase * GetCurTOX(const SwPosition &rPos)
Get current table of contents.
Definition: doctxm.cxx:448
Definition: tox.hxx:311
SwNodeIndex nNode
Definition: pam.hxx:38
bool EndPosIsFieldEnd(WW8_CP &)
Definition: ww8scan.cxx:4065
void SetPromptText(const OUString &rStr)
Definition: expfld.hxx:259
eF_ResT Read_F_InputVar(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1378
eF_ResT Read_F_Author(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1806
eMERGEINC
#define WW8_TOX_LEVEL_DELIM
Definition: ww8par5.cxx:91
SVX_NUM_NUMBER_NONE
ErrCode GetError() const
void SetAdjustment(css::text::RubyAdjust nNew)
Definition: fmtruby.hxx:74
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:277
sal_uIntPtr sal_uLong
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_LANGUAGE(10)
long Long
virtual sal_uInt16 GetSubType() const override
Definition: flddat.cxx:95
ePRINTDATE
FAMILY_DONTKNOW
css::uno::Any getPropertyValue(const OUString &rPropertyName)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
wwFrameNamer m_aGrfNameGenerator
Definition: ww8par.hxx:1211
const sal_Unicode cTokenSeparator
Base class of all fields.
Definition: fldbas.hxx:291
void MakeTagString(OUString &rStr, const OUString &rOrg)
Definition: ww8par5.cxx:1056
void SetHandle(tools::Long nHandle)
Definition: fltshell.cxx:980
#define TOX_STYLE_DELIMITER
Definition: tox.hxx:420
sal_Int64 n
Provides access to the marks of a document.
Definition: doc.hxx:187
constexpr sal_uInt16 RES_FRMATR_END(133)
eBookStatus
Definition: ww8scan.hxx:747
OUString GetUniqueSectionName(const OUString *pChkStr=nullptr) const
Definition: ndsect.cxx:1410
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:92
SvNumFormatType GetType(sal_uInt32 nFIndex) const
constexpr TypedWhichId< SwFltRDFMark > RES_FLTR_RDFMARK(196)
static SotStorage * OpenOLEStorage(css::uno::Reference< css::embed::XStorage > const &xStorage, OUString const &rEleName, StreamMode=StreamMode::STD_READWRITE)
sal_uInt64 Seek(sal_uInt64 nPos)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
void ConvertLanguage(SvNumberFormatter &rConverter, LanguageType eConvertFrom, LanguageType eConvertTo)
const SwDocInfoSubType DI_COMMENT
Definition: docufld.hxx:74
SwNode & GetNode() const
Definition: ndindex.hxx:128
std::unique_ptr< SwPaM > m_pPosAfterTOC
Definition: ww8par.hxx:1402
WW8_CP nLen
total length (to skip over text)
Definition: ww8scan.hxx:192
static void EnsureMaxLevelForTemplates(SwTOXBase &rBase)
Definition: ww8par5.cxx:2876
bool isAnyKnownWebDAVScheme() const
static OUString FindPara(const OUString &rStr, sal_Unicode cToken, sal_Unicode cToken2)
Definition: ww8par5.cxx:334
SwSectionFormat * GetFormat()
Definition: section.hxx:336
REFERENCEMARK
Definition: reffld.hxx:45
sal_uInt16 GetFormMax() const
Definition: tox.hxx:681
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1792
virtual bool InsertPoolItem(const SwPaM &rRg, const SfxPoolItem &, const SetAttrMode nFlags=SetAttrMode::DEFAULT, SwRootFrame const *pLayout=nullptr, SwTextAttr **ppNewTextAttr=nullptr)=0
Insert an attribute.
void SetLevel(sal_uInt8)
Definition: chpfld.cxx:86
eCONTROL
bool StartPosIsFieldStart()
Definition: ww8scan.cxx:4058
virtual sal_uInt16 GetSubType() const override
Definition: expfld.cxx:898
eF_ResT Read_F_Macro(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2314
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
void SetDateTime(const DateTime &rDT)
Definition: flddat.cxx:117
const OUString & GetFormatstring() const
eF_ResT Read_F_Shape(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:3519
bool Commit()
static void ParseIfFieldDefinition(const OUString &aFieldDefinition, OUString &rCondition, OUString &rTrue, OUString &rFalse)
Definition: docufld.cxx:1533
eF_ResT Read_F_Seq(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1448
OUString GetMappedBookmark(std::u16string_view rOrigName)
Definition: ww8par5.cxx:1362
tools::Long GetLen() const
Definition: ww8scan.cxx:4410
#define MAX_FIELDLEN
Definition: ww8par5.cxx:89
SvxNumType
static LanguageType nLang
Definition: srtdlg.cxx:51
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
eAUTOTEXT
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:230
constexpr OUStringLiteral ODF_CODE_PARAM
void SetCharFormatName(const OUString &rNm)
Definition: fmtruby.hxx:65
virtual OUString GetPar1() const
Definition: fldbas.cxx:321
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
SwDoc & m_rDoc
Definition: docbm.cxx:1201
sal_uInt16 sal_Unicode
Stores RDF statements on a paragraph (key-value pairs where the subject is the paragraph).
Definition: fltshell.hxx:243
static SW_DLLPUBLIC OUString GetCrossRefHeadingBookmarkNamePrefix()
Definition: docbm.cxx:508
const SwCharFormat * GetDfltCharFormat() const
Definition: doc.hxx:752
SwTOXBaseSection * InsertTableOf(const SwPosition &rPos, const SwTOXBase &rTOX, const SfxItemSet *pSet=nullptr, bool bExpand=false, SwRootFrame const *pLayout=nullptr)
Definition: doctxm.cxx:344
int n2
SotStorage * OpenSotStorage(const OUString &rEleName, StreamMode=StreamMode::STD_READWRITE, bool transacted=true)
ePAGEREF
SwIndex nContent
Definition: pam.hxx:39
void RegisterToTOXType(SwTOXType &rMark)
Definition: tox.cxx:552
Handles the import of PlcfBkfFactoid and PlcfBklFactoid: start / end position of factoids.
Definition: ww8scan.hxx:819
std::unique_ptr< SwWW8ReferencedFltEndStack > m_xReffedStck
Definition: ww8par.hxx:1143
size_t pos
std::vector< SwWW8StyInf > m_vColl
Definition: ww8par.hxx:1268
SwSectionNode * GetSectionNode()
Definition: section.cxx:922
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CTL_LANGUAGE(29)
"Number (full context)"
Definition: reffld.hxx:60
tools::Long GetHandle() const
Definition: ww8scan.cxx:4446
void SetFieldCode(const OUString &rStr)
access to the command string
Definition: dbfld.hxx:103
OUString sText
Definition: tox.hxx:243
const OUString & GetName() const
Definition: format.hxx:131
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
eF_ResT Read_F_DBNum(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2648
SvStream * m_pStrm
Definition: ww8par.hxx:1121
SVX_NUM_ARABIC
const SwDocInfoSubType DI_SUBJECT
Definition: docufld.hxx:72
void SetInitDBFields(bool b)
Definition: docfld.cxx:424
static SW_DLLPUBLIC sal_uInt16 GetPoolIdFromUIName(const OUString &rName, SwGetPoolIdFromName)
bool CopyTo(SotStorage *pDestStg)
SVX_NUM_ROMAN_UPPER
virtual void SetValue(const double &rVal) override
Definition: expfld.cxx:903
constexpr TypedWhichId< SwFormatRuby > RES_TXTATR_CJK_RUBY(53)
sal_uInt16 GetTOXTypeCount(TOXTypes eTyp) const
Manage table of content types.
Definition: doctxm.cxx:611
SVX_NUM_ROMAN_LOWER
virtual parameter_map_t * GetParameters()=0
"Category and Number"
Definition: reffld.hxx:53
void SetAutomaticLanguage(bool const bSet)
Definition: fldbas.hxx:386
void SetBookmarkCode(const OUString &bookmarkCode)
Definition: ww8par5.cxx:766
eF_ResT Read_F_IncludeText(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2526
const SwDoc & mrDoc
Definition: ww8par.hxx:983
constexpr TypedWhichId< SfxStringItem > RES_FLTR_BOOKMARK(RES_FLTRATTR_BEGIN)
Iterator for fields.
Definition: ww8scan.hxx:725
eF_ResT
Definition: ww8par.hxx:618
void SetAlternativeText(const OUString &rAlt)
Definition: tox.hxx:580
bool m_bLoadingTOXHyperlink
Definition: ww8par.hxx:1400
void SetHadPageDescItem(bool bVal)
Definition: fltshell.hxx:272
const char * sName
SwFltStackEntry * RefToVar(const SwField *pField, SwFltStackEntry &rEntry)
Definition: ww8par5.cxx:1339
eF_ResT Read_F_PgRef(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2217
sal_uInt16 GetPoolFormatId() const
Get and set Pool style IDs.
Definition: format.hxx:163
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
tools::Long nCp2OrIdx
Definition: ww8scan.hxx:855
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:48
Base class for various Writer styles.
Definition: format.hxx:46
#define SAL_N_ELEMENTS(arr)
const SwDocInfoSubType DI_CUSTOM
Definition: docufld.hxx:80
WW8_CP nLCode
length
Definition: ww8scan.hxx:194
DocumentType eType
void SetHadBreakItem(bool bVal)
Definition: fltshell.hxx:271
tools::Long MapBookmarkVariables(const WW8FieldDesc *pF, OUString &rOrigName, const OUString &rData)
Definition: ww8par5.cxx:1299
WW8_CP Read_F_Tag(WW8FieldDesc *pF)
Definition: ww8par5.cxx:1149
void SetVisitedFormatAndId(const OUString &rNm, const sal_uInt16 nId)
Definition: fmtinfmt.hxx:112
void SetFormula(const OUString &rStr)
Definition: fldbas.cxx:771
void Read_SubF_Ruby(msfilter::util::WW8ReadFieldParams &rReadParam)
Definition: ww8par5.cxx:2696
constexpr OUStringLiteral ODF_ID_PARAM
eF_ResT Read_F_FormCheckBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:186
eF_ResT Read_F_DBField(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2594
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:137
void PrependedInlineNode(const SwPosition &rPos, const SwNode &rNode)
Definition: ww8par2.cxx:2362
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:502
const SwDocInfoSubType DI_PRINT
Definition: docufld.hxx:77
eF_ResT Read_F_TemplName(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1816
bool CurrentSectionIsProtected() const
Definition: ww8par2.cxx:136
T * get() const
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
sal_uInt16 char * pName
bool bResNest
instruction inserted into result
Definition: ww8scan.hxx:200
bool GetPara(tools::Long nIdx, WW8FieldDesc &rF)
Definition: ww8scan.cxx:4136
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
eF_ResT Read_F_Symbol(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1948
constexpr TypedWhichId< CntUInt16Item > RES_FLTR_ANNOTATIONMARK(195)
static SvtFilterOptions & Get()
void Swap(WW8FieldEntry &rOther) noexcept
Definition: ww8par5.cxx:742
void SetUniqueGraphName(SwFrameFormat *pFrameFormat, std::u16string_view rFixedPart)
Definition: ww8graf.cxx:164
eAUTOTEXTLIST
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
wwSectionManager m_aSectionManager
Definition: ww8par.hxx:1183
SwFileNameFormat
Definition: fldbas.hxx:153
int i
SwDoc & m_rDoc
Definition: ww8par.hxx:1126
NF_TIME_START
void SetPrimaryKey(const OUString &rStr)
Definition: tox.hxx:596
SwTOXElement
Definition: tox.hxx:363
const SwPosition * GetPoint() const
Definition: pam.hxx:208
std::unique_ptr< WW8ScannerBase > m_xSBase
Definition: ww8par.hxx:1256
EquationResult ParseCombinedChars(const OUString &rStr)
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:206
eF_ResT Read_F_FileName(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1893
OUString sCharStyleName
Definition: tox.hxx:244
#define LANGUAGE_SYSTEM
const SwDocInfoSubType DI_KEYS
Definition: docufld.hxx:73
constexpr OUStringLiteral ODF_OLE_PARAM
bool SwFltGetFlag(sal_uLong nFieldFlags, int no)
Definition: fltshell.hxx:42
void Exchange()
Definition: pam.cxx:490
constexpr OUStringLiteral ODF_FORMTEXT
SwContentNode * GetContentNode()
Definition: node.hxx:625
SwNodeOffset GetIndex() const
Definition: node.hxx:292
const SwDocInfoSubType DI_CREATE
Definition: docufld.hxx:75
void SetSequenceName(const OUString &rSet)
Definition: tox.hxx:540
FlyAnchors.
Definition: fmtanchr.hxx:34
rtl_TextEncoding m_eTextCharSet
Definition: ww8par.hxx:1318
void SetCaptionDisplay(SwCaptionDisplay eSet)
Definition: tox.hxx:543
void NewAttr(const SfxPoolItem &rAttr, const bool bFirstLineOfStSet=false, const bool bLeftIndentSet=false)
Definition: ww8par6.cxx:2801
void AppendTextNode(SwPosition &rPos)
Definition: ww8par.cxx:2404
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
bool ForceFieldLanguage(SwField &rField, LanguageType nLang)
Definition: ww8par5.cxx:392
constexpr TypedWhichId< SwFltTOX > RES_FLTR_TOX(193)
float u
WW8_CP GetStartPos() const
Definition: ww8scan.hxx:776
bool IsNumberFormat(const OUString &sString, sal_uInt32 &F_Index, double &fOutNumber, SvNumInputOptions eInputOptions=SvNumInputOptions::NONE)
sal_uInt16 GetWhichOfScript(sal_uInt16 nWhich, sal_uInt16 nScript)
Definition: hints.cxx:193
new reference format types for referencing bookmarks and set references
Definition: reffld.hxx:58
eF_ResT Read_F_Embedd(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2021
eF_ResT Read_F_Ref(WW8FieldDesc *pF, OUString &)
Definition: ww8par5.cxx:2084
static sal_Int32 FindParaStart(const OUString &rStr, sal_Unicode cToken, sal_Unicode cToken2)
Definition: ww8par5.cxx:305
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:394
eF_ResT Read_F_FormTextBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:93
PITCH_DONTKNOW
void ImportTox(int nFieldId, const OUString &aStr)
Definition: ww8par5.cxx:3694
SvNumFormatType
const sal_uInt8 * pSprm
Definition: ww8scan.hxx:95
eF_ResT Read_F_Tox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:3001
const SwDocInfoSubType DI_SUB_DATE
Definition: docufld.hxx:85
void UpdateFields()
Definition: ww8par5.cxx:500
Marks a node in the document model.
Definition: ndindex.hxx:30
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
Text operation/manipulation interface.
void SetBookmarkName(const OUString &bookmarkName)
Definition: ww8par5.cxx:756
FontPitch
sal_uInt16 GetLevel() const
Definition: tox.hxx:729
Represents the style of a text portion.
Definition: charfmt.hxx:26
eF_ResT Read_F_FormListBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:245
void InitContent()
Evaluation for header and footer.
Definition: dbfld.cxx:177
SVX_NUM_CHARS_LOWER_LETTER_N
tools::Long Read_FactoidBook(WW8PLCFManResult *)
Definition: ww8par5.cxx:248
std::unique_ptr< SfxPoolItem > m_pAttr
Definition: fltshell.hxx:90
std::deque< bool > m_aApos
Definition: ww8par.hxx:1238
const OUString * GetName() const
Definition: ww8scan.cxx:4534
tools::Long Read_AtnBook(WW8PLCFManResult *)
Definition: ww8par5.cxx:236
WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd, SwPaM &rPaM)
Definition: ww8par5.cxx:2408
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder, bool bReplaceBooleanEquivalent=true)
sal_Int32 WW8_CP
Definition: ww8struc.hxx:153
eBookStatus GetStatus() const
Definition: ww8scan.cxx:4438
int m_nEmbeddedTOXLevel
Definition: ww8par.hxx:1398
eFORMTEXT
WW8_CP nLRes
length ( == 0, if no result )
Definition: ww8scan.hxx:196
bool IsControlChar(sal_Unicode cChar)
const SwDocInfoSubType DI_SUB_AUTHOR
Definition: docufld.hxx:83
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
std::vector< const SwCharFormat * > m_aRubyCharFormats
Definition: ww8par.hxx:1243
bool m_bCareFirstParaEndInToc
Definition: ww8par.hxx:1408
OUString ConvertFFileName(const OUString &rRaw)
translate FieldParameter names into the system character set and at the same time, double backslashes are converted into single ones
Definition: ww8par5.cxx:269
NF_DATE_START
FontFamily
tools::Long Read_Field(WW8PLCFManResult *pRes)
Definition: ww8par5.cxx:775
const OUString & GetFamilyName() const
OUString GetFieldResult(WW8FieldDesc const *pF)
Definition: ww8par5.cxx:1209
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
eCREATEDATE
SVX_NUM_PAGEDESC
OUString ExpandField(bool bCached, SwRootFrame const *pLayout) const
expand the field.
Definition: fldbas.cxx:484
"Reference"
Definition: reffld.hxx:50
const SwGetSetExpType GSE_SEQ
Sequence.
Definition: fldbas.hxx:205
OUString UniqueName()
Definition: ww8par5.cxx:2519
sal_uInt32 GetHeight() const
static OUString GetWordDefaultDateStringAsUS(SvNumberFormatter *pFormatter, LanguageType nLang)
Definition: ww8par5.cxx:411
SwFieldIds Which() const
ResId.
Definition: fldbas.cxx:250
WW8FieldEntry & operator=(const WW8FieldEntry &rOther) noexcept
Definition: ww8par5.cxx:748
SvNumFormatType GetTimeDatePara(OUString const &rStr, sal_uInt32 &rFormat, LanguageType &rLang, int nWhichDefault, bool bHijri=false)
Definition: ww8par5.cxx:433
sal_Int32 FindNextStringPiece(sal_Int32 _nStart=-1)
sal_uInt8 nOpt
WW-Flags ( e.g.: changed by user )
Definition: ww8scan.hxx:198
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
virtual void SetLanguage(LanguageType nLng)
Definition: fldbas.cxx:442
static bool ConvertMacroSymbol(std::u16string_view rName, OUString &rReference)
Definition: ww8par5.cxx:2290
eF_ResT Read_F_DBNext(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2635
unsigned char sal_uInt8
sal_uInt16 nId
WW-id for fields.
Definition: ww8scan.hxx:197
const SwDocInfoSubType DI_DOCNO
Definition: docufld.hxx:78
const SvNumberformat * GetEntry(sal_uInt32 nKey) const
virtual SwFieldType * InsertFieldType(const SwFieldType &)=0
"Above/Below"
Definition: reffld.hxx:51
OUString const & GetStyleNames(sal_uInt16 nLevel) const
Definition: tox.hxx:517
bool GetIsEnd() const
Definition: ww8scan.hxx:779
eSAVEDATE
static SvxNumType GetNumberPara(const OUString &rStr, bool bAllowPageDesc=false)
Definition: ww8par5.cxx:385
sal_uInt16 CurrentSectionColCount() const
Definition: ww8par5.cxx:2964
bool CanUseRemoteLink(const OUString &rGrfName)
Definition: ww8par5.cxx:2418
#define SAL_INFO(area, stream)
OUString aName
static void lcl_toxMatchACSwitch(SwDoc const &rDoc, SwTOXBase &rBase, WW8ReadFieldParams &rParam, SwCaptionDisplay eCaptionType)
Definition: ww8par5.cxx:2859
sal_Int32 GetIndex() const
Definition: index.hxx:91
void SetStyleNames(const OUString &rSet, sal_uInt16 nLevel)
Definition: tox.hxx:522
eF_ResT Read_F_OCX(WW8FieldDesc *, OUString &)
Definition: ww8par3.cxx:85
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
eF_ResT Read_F_Input(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1172
eF_ResT Read_F_ANumber(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1434
NF_DATE_SYSTEM_SHORT
void AddTime(double fTimeInDays)
sal_Int32 nRemainingData
Definition: ww8scan.hxx:96
std::u16string_view trim(std::u16string_view str)
OUString BookmarkToWriter(std::u16string_view rBookmark)
Definition: wrtw8nds.cxx:1236
void SetInputFlag(bool bInp)
Definition: expfld.hxx:265
const SwPosition * End() const
Definition: pam.hxx:218
bool m_bIgnoreText
Definition: ww8par.hxx:1349
constexpr OUStringLiteral ODF_UNHANDLED
constexpr sal_uInt16 RES_PARATR_END(82)
WW8_CP nSRes
start of result
Definition: ww8scan.hxx:195
"Number (no context)"
Definition: reffld.hxx:59
sal_uInt64 Tell() const
Reference< XComponentContext > getProcessComponentContext()
QPRO_FUNC_TYPE nType
eF_ResT Read_F_DocInfo(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:1545
static void lcl_ImportTox(SwDoc &rDoc, SwPaM const &rPaM, const OUString &rStr, bool bIdx)
Definition: ww8par5.cxx:3618
auto FilterControlChars(OUString const &rString) -> OUString
Definition: ww8par.cxx:3425
eF_ResT Read_F_Styleref(WW8FieldDesc *, OUString &rStr)
Reads a STYLEREF field.
Definition: ww8par5.cxx:1524
void SetSecondaryKey(const OUString &rStr)
Definition: tox.hxx:602
eHYPERLINK
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
eF_ResT Read_F_Hyperlink(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:3529
static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
Definition: ww8par5.cxx:2988
std::shared_ptr< WW8PLCFMan > m_xPlcxMan
Definition: ww8par.hxx:1257
static void lcl_ConvertSequenceName(OUString &rSequenceName)
Definition: ww8par5.cxx:296
bool WillHavePageDescHere(const SwNodeIndex &rIdx) const
Definition: ww8par5.cxx:2974
#define SAL_WARN(area, stream)
virtual void SetUpdateExpFieldStat(bool b)=0
int mnFileSectionNo
Definition: ww8par.hxx:985
const SwGetSetExpType GSE_STRING
String.
Definition: fldbas.hxx:203
wwSectionNamer m_aSectionNameGenerator
Definition: ww8par.hxx:1201
virtual SwFieldType * GetSysFieldType(const SwFieldIds eWhich) const =0
const SwDocInfoSubType DI_SUB_FIXED
Definition: docufld.hxx:86
static void lcl_toxMatchTSwitch(SwWW8ImplReader const &rReader, SwTOXBase &rBase, WW8ReadFieldParams &rParam)
Definition: ww8par5.cxx:2897
const SwFormat * GetStyleWithOrgWWName(std::u16string_view rName) const
Definition: ww8par2.cxx:3588
const SwDocInfoSubType DI_CHANGE
Definition: docufld.hxx:76
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:476
bool m_bWasParaEnd
Definition: ww8par.hxx:1371
const SwTOXType * GetTOXType(TOXTypes eTyp, sal_uInt16 nId) const
Definition: doctxm.cxx:620
sw::hack::Position maStartPos
Definition: ww8par.hxx:562
void SetLevel(sal_uInt16)
Definition: tox.hxx:723
const char *const aFieldNames[]
Definition: authfld.cxx:650
SwFormat * m_pCurrentColl
Definition: ww8par.hxx:1264
const SwDocInfoSubType DI_TITLE
Definition: docufld.hxx:71
const Date & GetNullDate() const
SwSection * InsertSwSection(SwPaM const &rRange, SwSectionData &, std::tuple< SwTOXBase const *, sw::RedlineMode, sw::FieldmarkMode > const *pTOXBase, SfxItemSet const *const pAttr, bool const bUpdate=true)
Definition: ndsect.cxx:156
SwCaptionDisplay
Definition: tox.hxx:400
bool IsUseEnhancedFields() const
static SvxNumType GetNumTypeFromName(const OUString &rStr, bool bAllowPageDesc=false)
Definition: ww8par5.cxx:361
eF_ResT Read_F_CurPage(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1937
eF_ResT Read_F_IncludePicture(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2460
CharClass & GetAppCharClass()
Definition: init.cxx:705
std::deque< wwSection > maSegments
Definition: ww8par.hxx:824
eF_ResT Read_F_NoteReference(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:2167
constexpr sal_uInt16 RES_FRMATR_BEGIN(RES_PARATR_LIST_END)
aStr
FormTokenType
Definition: tox.hxx:226
SwPaM * m_pPaM
Definition: ww8par.hxx:1128
void SetINetFormatAndId(const OUString &rNm, const sal_uInt16 nId)
Definition: fmtinfmt.hxx:94
tools::Long Read_Book(WW8PLCFManResult *)
Definition: ww8par5.cxx:120
void SetCharFormatId(sal_uInt16 nNew)
Definition: fmtruby.hxx:68
virtual SwFormatField * Clone(SfxItemPool *pPool=nullptr) const override
Definition: atrfld.cxx:211
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1318
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:864
bool GetTokenSttFromTo(sal_Int32 *_pFrom, sal_Int32 *_pTo, sal_Int32 _nMax)
eF_ResT Read_F_Equation(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2669
constexpr OUStringLiteral aObjectPool
Definition: ww8scan.hxx:45
only the title
Definition: chpfld.hxx:33
bool m_bDetectedRangeSegmentation false
SVL_DLLPUBLIC OUString SmartRel2Abs(INetURLObject const &rTheBaseURIRef, OUString const &rTheRelURIRef, Link< OUString *, bool > const &rMaybeFileHdl=Link< OUString *, bool >(), bool bCheckFileExists=true, bool bIgnoreFragment=false, INetURLObject::EncodeMechanism eEncodeMechanism=INetURLObject::EncodeMechanism::WasEncoded, INetURLObject::DecodeMechanism eDecodeMechanism=INetURLObject::DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8, FSysStyle eStyle=FSysStyle::Detect)
eF_ResT Read_F_HTMLControl(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:318
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo