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