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