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