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