LibreOffice Module sw (master)  1
ww8par5.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <sal/types.h>
23 #include <tools/solar.h>
25 #include <comphelper/string.hxx>
27 #include <com/sun/star/embed/XStorage.hpp>
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <com/sun/star/embed/XTransactedObject.hpp>
30 #include <com/sun/star/task/InteractionHandler.hpp>
31 
32 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
33 #include <svl/cintitem.hxx>
34 #include <svl/lngmisc.hxx>
35 #include <svl/urihelper.hxx>
36 #include <svl/zforlist.hxx>
37 #include <svl/zformat.hxx>
38 #include <sfx2/linkmgr.hxx>
39 #include <rtl/character.hxx>
40 #include <unotools/charclass.hxx>
41 
42 #include <ucbhelper/content.hxx>
44 
45 #include <com/sun/star/i18n/XBreakIterator.hpp>
46 #include <hintids.hxx>
47 #include <editeng/fontitem.hxx>
48 #include <editeng/fhgtitem.hxx>
49 #include <editeng/langitem.hxx>
50 #include <fmtfld.hxx>
51 #include <fmtanchr.hxx>
52 #include <pam.hxx>
53 #include <doc.hxx>
55 #include <IDocumentMarkAccess.hxx>
56 #include <IDocumentState.hxx>
57 #include <flddat.hxx>
58 #include <docufld.hxx>
59 #include <reffld.hxx>
60 #include <IMark.hxx>
61 #include <expfld.hxx>
62 #include <dbfld.hxx>
63 #include <tox.hxx>
64 #include <section.hxx>
65 #include <ndtxt.hxx>
66 #include <fmtinfmt.hxx>
67 #include <chpfld.hxx>
68 #include <fmtruby.hxx>
69 #include <charfmt.hxx>
70 #include <breakit.hxx>
71 #include <fmtclds.hxx>
72 #include <poolfmt.hxx>
73 #include <SwStyleNameMapper.hxx>
74 
75 #include "ww8scan.hxx"
76 #include "ww8par.hxx"
77 #include "writerhelper.hxx"
78 #include <o3tl/safeint.hxx>
79 #include <unotools/fltrcfg.hxx>
80 #include <xmloff/odffields.hxx>
81 #include <osl/diagnose.h>
82 
83 #include <algorithm>
84 
85 #define MAX_FIELDLEN 64000
86 
87 #define WW8_TOX_LEVEL_DELIM ':'
88 
89 using namespace ::com::sun::star;
90 using namespace msfilter::util;
91 using namespace sw::util;
92 using namespace sw::mark;
93 using namespace std; // #i24377#
94 using namespace nsSwDocInfoSubType;
95 
96 // Bookmarks
97 namespace
98 {
99  // #120879# - helper method to identify a bookmark name to match the internal TOC bookmark naming convention
100  bool IsTOCBookmarkName(const OUString& rName)
101  {
102  return rName.startsWith("_Toc") || rName.startsWith(OUString(IDocumentMarkAccess::GetCrossRefHeadingBookmarkNamePrefix()+"_Toc"));
103  }
104 
105  OUString EnsureTOCBookmarkName(const OUString& rName)
106  {
107  OUString sTmp = rName;
108  if ( IsTOCBookmarkName ( rName ) )
109  {
112  }
113  return sTmp;
114  }
115 }
116 
118 {
119  // should also work via pRes.nCo2OrIdx
120  WW8PLCFx_Book* pB = m_xPlcxMan->GetBook();
121  if( !pB )
122  {
123  OSL_ENSURE( pB, "WW8PLCFx_Book - Pointer does not exist" );
124  return 0;
125  }
126 
127  eBookStatus eB = pB->GetStatus();
128  if (eB & BOOK_IGNORE)
129  return 0; // ignore bookmark
130 
131  if (pB->GetIsEnd())
132  {
133  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
134  pB->GetHandle(), (eB & BOOK_FIELD)!=0);
135  return 0;
136  }
137 
138  // "_Hlt*" are unnecessary
139  const OUString* pName = pB->GetName();
140  // Now, as we read the TOC field completely, we also need the hyperlinks inside keep available.
141  // So the hidden bookmarks inside for hyperlink jumping also should be kept.
142  if ( !pName ||
143  pName->startsWithIgnoreAsciiCase( "_Hlt" ) )
144  {
145  return 0;
146  }
147 
148  // do NOT call ToUpper as the bookmark name can also be a hyperlink target!
149 
150  OUString aVal;
151  if( SwFltGetFlag( m_nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
152  {
153  // set variable for translation bookmark
154  tools::Long nLen = pB->GetLen();
155  if( nLen > MAX_FIELDLEN )
156  nLen = MAX_FIELDLEN;
157 
158  tools::Long nOldPos = m_pStrm->Tell();
159  m_xSBase->WW8ReadString( *m_pStrm, aVal, pB->GetStartPos(), nLen,
160  m_eStructCharSet );
161  m_pStrm->Seek( nOldPos );
162 
163  // now here the implementation of the old "QuoteString" and
164  // I hope with a better performance as before. It's also only
165  // needed if the filterflags say we will convert bookmarks
166  // to SetExpFields! And this the exception!
167 
168  bool bSetAsHex;
169  bool bAllowCr = SwFltGetFlag(m_nFieldFlags,
171 
172  for( sal_Int32 nI = 0;
173  nI < aVal.getLength() && aVal.getLength() < (MAX_FIELDLEN - 4);
174  ++nI )
175  {
176  const sal_Unicode cChar = aVal[nI];
177  switch( cChar )
178  {
179  case 0x0b:
180  case 0x0c:
181  case 0x0d:
182  if( bAllowCr )
183  {
184  aVal = aVal.replaceAt( nI, 1, "\n" );
185  bSetAsHex = false;
186  }
187  else
188  bSetAsHex = true;
189  break;
190 
191  case 0xFE:
192  case 0xFF:
193  bSetAsHex = true;
194  break;
195 
196  default:
197  bSetAsHex = 0x20 > cChar;
198  break;
199  }
200 
201  if( bSetAsHex )
202  {
203  //all Hex-Numbers with \x before
204  OUString sTmp( "\\x" );
205  if( cChar < 0x10 )
206  sTmp += "0";
207  sTmp += OUString::number( cChar, 16 );
208  aVal = aVal.replaceAt( nI, 1 , sTmp );
209  nI += sTmp.getLength() - 1;
210  }
211  }
212 
213  if ( aVal.getLength() > (MAX_FIELDLEN - 4))
214  aVal = aVal.copy( 0, MAX_FIELDLEN - 4 );
215  }
216 
217  //e.g. inserting bookmark around field result, so we need to put
218  //it around the entire writer field, as we don't have the separation
219  //of field and field result of word, see #i16941#
220  SwPosition aStart(*m_pPaM->GetPoint());
221  if (!m_aFieldStack.empty())
222  {
223  const WW8FieldEntry &rTest = m_aFieldStack.back();
224  aStart = rTest.maStartPos;
225  }
226 
227  const OUString sOrigName = BookmarkToWriter(*pName);
228  m_xReffedStck->NewAttr( aStart,
229  SwFltBookmark( EnsureTOCBookmarkName( sOrigName ), aVal, pB->GetHandle(), IsTOCBookmarkName( sOrigName ) ));
230  return 0;
231 }
232 
234 {
235  if (WW8PLCFx_AtnBook* pAtnBook = m_xPlcxMan->GetAtnBook())
236  {
237  if (pAtnBook->getIsEnd())
238  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_ANNOTATIONMARK, true, pAtnBook->getHandle());
239  else
240  m_xReffedStck->NewAttr(*m_pPaM->GetPoint(), CntUInt16Item(RES_FLTR_ANNOTATIONMARK, pAtnBook->getHandle()));
241  }
242  return 0;
243 }
244 
246 {
247  if (WW8PLCFx_FactoidBook* pFactoidBook = m_xPlcxMan->GetFactoidBook())
248  {
249  if (pFactoidBook->getIsEnd())
250  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_RDFMARK, true, pFactoidBook->getHandle());
251  else
252  {
253  SwFltRDFMark aMark;
254  aMark.SetHandle(pFactoidBook->getHandle());
255  GetSmartTagInfo(aMark);
256  m_xReffedStck->NewAttr(*m_pPaM->GetPoint(), aMark);
257  }
258  }
259  return 0;
260 }
261 
262 // general help methods to separate parameters
263 
266 OUString SwWW8ImplReader::ConvertFFileName(const OUString& rOrg)
267 {
268  OUString aName = rOrg.replaceAll("\\\\", "\\");
269  aName = aName.replaceAll("%20", " ");
270 
271  // remove attached quotation marks
272  if (aName.endsWith("\""))
273  aName = aName.copy(0, aName.getLength()-1);
274 
275  // Need the more sophisticated url converter.
276  if (!aName.isEmpty())
277  aName = URIHelper::SmartRel2Abs(
278  INetURLObject(m_sBaseURL), aName, Link<OUString *, bool>(), false);
279 
280  return aName;
281 }
282 
283 namespace
284 {
287  void ConvertUFName( OUString& rName )
288  {
289  rName = GetAppCharClass().uppercase( rName );
290  }
291 }
292 
293 static void lcl_ConvertSequenceName(OUString& rSequenceName)
294 {
295  ConvertUFName(rSequenceName);
296  if ('0' <= rSequenceName[0] && '9' >= rSequenceName[0])
297  rSequenceName = "_" + rSequenceName;
298 }
299 
300 // FindParaStart() finds 1st Parameter that follows '\' and cToken
301 // and returns start of this parameter or -1
302 static sal_Int32 FindParaStart( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
303 {
304  bool bStr = false; // ignore inside a string
305 
306  for( sal_Int32 nBuf = 0; nBuf+1 < rStr.getLength(); nBuf++ )
307  {
308  if( rStr[ nBuf ] == '"' )
309  bStr = !bStr;
310 
311  if( !bStr
312  && rStr[ nBuf ] == '\\'
313  && ( rStr[ nBuf + 1 ] == cToken
314  || rStr[ nBuf + 1 ] == cToken2 ) )
315  {
316  nBuf += 2;
317  // skip spaces between cToken and its parameters
318  while( nBuf < rStr.getLength()
319  && rStr[ nBuf ] == ' ' )
320  nBuf++;
321  // return start of parameters
322  return nBuf < rStr.getLength() ? nBuf : -1;
323  }
324  }
325  return -1;
326 }
327 
328 // FindPara() finds the first parameter including '\' and cToken.
329 // A new String will be allocated (has to be deallocated by the caller)
330 // and everything that is part of the parameter will be returned.
331 static OUString FindPara( const OUString& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
332 {
333  sal_Int32 n2; // end
334  sal_Int32 n = FindParaStart( rStr, cToken, cToken2 ); // start
335  if( n == -1)
336  return OUString();
337 
338  if( rStr[ n ] == '"'
339  || rStr[ n ] == 132 )
340  { // Quotationmark in front of parameter
341  n++; // Skip quotationmark
342  n2 = n; // search for the end starting from here
343  while( n2 < rStr.getLength()
344  && rStr[ n2 ] != 147
345  && rStr[ n2 ] != '"' )
346  n2++; // search end of parameter
347  }
348  else
349  { // no quotationmarks
350  n2 = n; // search for the end starting from here
351  while( n2 < rStr.getLength()
352  && rStr[ n2 ] != ' ' )
353  n2++; // search end of parameter
354  }
355  return rStr.copy( n, n2-n );
356 }
357 
358 static SvxNumType GetNumTypeFromName(const OUString& rStr,
359  bool bAllowPageDesc = false)
360 {
361  SvxNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
362  if( rStr.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 
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 {
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());
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
603  SwHiddenTextField aHTField(
604  static_cast<SwHiddenTextFieldType*>(pFieldType),
605  paramCondition,
606  paramTrue,
607  paramFalse,
609 
610  // insert new field into document
612  break;
613  }
614  default:
615  OUString aCode = m_aFieldStack.back().GetBookmarkCode();
616  if (!aCode.isEmpty() && !aCode.trim().startsWith("SHAPE"))
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 
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  tools::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
1117  }
1118  else
1119  { // tag normally
1120 
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 
1128  }
1129 }
1130 
1132 {
1133  tools::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 );
1185  }
1186 
1187  return eF_ResT::OK;
1188 }
1189 
1190 // GetFieldResult allocates a string and reads the resulted field
1192 {
1193  tools::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, "No pPlcxMan");
1285  tools::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  rDoc.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, "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 tools::Long nNo = MapBookmarkVariables(pF, sOrigName, aResult);
1401 
1404  SwSetExpField aField(pFT, aResult);
1406  aField.SetInputFlag(true);
1407  aField.SetPromptText( aQ );
1408 
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 );
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 
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 
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 
1520  SwChapterField aField(static_cast<SwChapterFieldType*>(pFieldType), CF_TITLE);
1521  aField.SetLevel(nResult - 1);
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 ) );
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);
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*>(
1763  DI_CREATE|DI_SUB_AUTHOR, OUString() );
1765  return eF_ResT::OK;
1766 }
1767 
1769 {
1770  SwTemplNameField aField( static_cast<SwTemplNameFieldType*>(
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;
1813  }
1814  else
1815  {
1816  nDT = SvNumFormatType::DATE;
1819  }
1820  }
1821 
1822  sal_uInt16 nDoNotRecalculate = (pF->nOpt & 0x10) ? FIXEDFLD : 0;
1823  if (nDoNotRecalculate)
1824  {
1825  // TODO: Doing this properly would require setting the field to the original date/time.
1826  // Unfortunately, none of the plumbing to do this exists AFAICS
1827  //SAL_WARN("DEBUG","Need to aField.SetDateTime() to ["<<GetFieldResult(pF)<<"] based on format string["<<aReadParam.GetResult()<<"]");
1828  // So instead, just drop the field and insert the plain text.
1829  // That is at least better than having the current date/time.
1830  return eF_ResT::TEXT;
1831  }
1832  if (nDT & SvNumFormatType::DATE)
1833  {
1834  SwDateTimeField aField(static_cast<SwDateTimeFieldType*>(
1836  (DATEFLD | nDoNotRecalculate),
1837  nFormat);
1838  ForceFieldLanguage(aField, nLang);
1840  }
1841  else if (nDT == SvNumFormatType::TIME)
1842  {
1843  SwDateTimeField aField(static_cast<SwDateTimeFieldType*>(
1845  (TIMEFLD | nDoNotRecalculate),
1846  nFormat);
1847  ForceFieldLanguage(aField, nLang);
1849  }
1850 
1851  return eF_ResT::OK;
1852 }
1853 
1855 {
1857  WW8ReadFieldParams aReadParam(rStr);
1858  for (;;)
1859  {
1860  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1861  if ( nRet==-1 )
1862  break;
1863  switch (nRet)
1864  {
1865  case 'p':
1866  eType = FF_PATHNAME;
1867  break;
1868  case '*':
1869  //Skip over MERGEFORMAT
1870  (void)aReadParam.SkipToNextToken();
1871  break;
1872  default:
1873  OSL_ENSURE(false, "unknown option in FileName field");
1874  break;
1875  }
1876  }
1877 
1878  SwFileNameField aField(
1879  static_cast<SwFileNameFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Filename)), eType);
1881  return eF_ResT::OK;
1882 }
1883 
1885 {
1886  sal_uInt16 nSub = DS_PAGE; // page number
1887  switch ( pF->nId ){
1888  case 27: nSub = DS_WORD; break; // number of words
1889  case 28: nSub = DS_CHAR; break; // number of characters
1890  }
1891  SwDocStatField aField( static_cast<SwDocStatFieldType*>(
1893  GetNumberPara( rStr ) );
1895  return eF_ResT::OK;
1896 }
1897 
1899 {
1900  // page number
1901  SwPageNumberField aField( static_cast<SwPageNumberFieldType*>(
1903  GetNumberPara(rStr, true));
1904 
1906  return eF_ResT::OK;
1907 }
1908 
1910 {
1911  //e.g. #i20118#
1912  OUString aQ;
1913  OUString aName;
1914  sal_Int32 nSize = 0;
1915  WW8ReadFieldParams aReadParam( rStr );
1916  for (;;)
1917  {
1918  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1919  if ( nRet==-1 )
1920  break;
1921  switch( nRet )
1922  {
1923  case -2:
1924  if( aQ.isEmpty() )
1925  aQ = aReadParam.GetResult();
1926  break;
1927  case 'f':
1928  case 'F':
1929  if ( aReadParam.GoToTokenParam() )
1930  aName = aReadParam.GetResult();
1931  break;
1932  case 's':
1933  case 'S':
1934  if ( aReadParam.GoToTokenParam() )
1935  {
1936  const OUString aSiz = aReadParam.GetResult();
1937  if (!aSiz.isEmpty())
1938  {
1939  bool bFail = o3tl::checked_multiply<sal_Int32>(aSiz.toInt32(), 20, nSize); // pT -> twip
1940  if (bFail)
1941  nSize = -1;
1942  }
1943  }
1944  break;
1945  }
1946  }
1947  if( aQ.isEmpty() )
1948  return eF_ResT::TAGIGN; // -> no 0-char in text
1949 
1950  sal_Unicode const cChar = static_cast<sal_Unicode>(aQ.toInt32());
1951  if (!linguistic::IsControlChar(cChar) || cChar == '\r' || cChar == '\n' || cChar == '\t')
1952  {
1953  if (!aName.isEmpty()) // Font Name set ?
1954  {
1955  SvxFontItem aFont(FAMILY_DONTKNOW, aName, OUString(),
1956  PITCH_DONTKNOW, RTL_TEXTENCODING_SYMBOL, RES_CHRATR_FONT);
1957  NewAttr(aFont); // new Font
1958  }
1959 
1960  if (nSize > 0) //#i20118#
1961  {
1962  SvxFontHeightItem aSz(nSize, 100, RES_CHRATR_FONTSIZE);
1963  NewAttr(aSz);
1964  }
1965 
1966  m_rDoc.getIDocumentContentOperations().InsertString(*m_pPaM, OUString(cChar));
1967 
1968  if (nSize > 0)
1969  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_CHRATR_FONTSIZE);
1970  if (!aName.isEmpty())
1971  m_xCtrlStck->SetAttr(*m_pPaM->GetPoint(), RES_CHRATR_FONT);
1972  }
1973  else
1974  {
1976  }
1977 
1978  return eF_ResT::OK;
1979 }
1980 
1981 // "EMBED"
1983 {
1984  WW8ReadFieldParams aReadParam( rStr );
1985  for (;;)
1986  {
1987  const sal_Int32 nRet = aReadParam.SkipToNextToken();
1988  if ( nRet==-1 )
1989  break;
1990  switch( nRet )
1991  {
1992  case -2:
1993  // sHost
1994  break;
1995 
1996  case 's':
1997  // use ObjectSize
1998  break;
1999  }
2000  }
2001 
2002  if( m_bObj && m_nPicLocFc )
2003  m_nObjLocFc = m_nPicLocFc;
2004  m_bEmbeddObj = true;
2005  return eF_ResT::TEXT;
2006 }
2007 
2008 // "SET"
2010 {
2011  OUString sOrigName;
2012  OUString sVal;
2013  WW8ReadFieldParams aReadParam( rStr );
2014  for (;;)
2015  {
2016  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2017  if ( nRet==-1 )
2018  break;
2019  switch( nRet )
2020  {
2021  case -2:
2022  if (sOrigName.isEmpty())
2023  sOrigName = aReadParam.GetResult();
2024  else if (sVal.isEmpty())
2025  sVal = aReadParam.GetResult();
2026  break;
2027  }
2028  }
2029 
2030  const tools::Long nNo = MapBookmarkVariables(pF, sOrigName, sVal);
2031 
2034  SwSetExpField aField( static_cast<SwSetExpFieldType*>(pFT), sVal, ULONG_MAX );
2036 
2038 
2039  m_xReffedStck->SetAttr(*m_pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
2040 
2041  return eF_ResT::OK;
2042 }
2043 
2044 // "REF"
2046 { // Reference - Field
2047  OUString sOrigBkmName;
2048  REFERENCEMARK eFormat = REF_CONTENT;
2049 
2050  WW8ReadFieldParams aReadParam( rStr );
2051  for (;;)
2052  {
2053  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2054  if ( nRet==-1 )
2055  break;
2056  switch( nRet )
2057  {
2058  case -2:
2059  if( sOrigBkmName.isEmpty() ) // get name of bookmark
2060  sOrigBkmName = aReadParam.GetResult();
2061  break;
2062 
2063  /* References to numbers in Word could be either to a numbered
2064  paragraph or to a chapter number. However Word does not seem to
2065  have the capability we do, of referring to the chapter number some
2066  other bookmark is in. As a result, cross-references to chapter
2067  numbers in a word document will be cross-references to a numbered
2068  paragraph, being the chapter heading paragraph. As it happens, our
2069  cross-references to numbered paragraphs will do the right thing
2070  when the target is a numbered chapter heading, so there is no need
2071  for us to use the REF_CHAPTER bookmark format on import.
2072  */
2073  case 'n':
2074  eFormat = REF_NUMBER_NO_CONTEXT;
2075  break;
2076  case 'r':
2077  eFormat = REF_NUMBER;
2078  break;
2079  case 'w':
2080  eFormat = REF_NUMBER_FULL_CONTEXT;
2081  break;
2082 
2083  case 'p':
2084  eFormat = REF_UPDOWN;
2085  break;
2086  case 'h':
2087  break;
2088  default:
2089  // unimplemented switch: just do 'nix nought nothing' :-)
2090  break;
2091  }
2092  }
2093 
2094  OUString sBkmName(GetMappedBookmark(sOrigBkmName));
2095 
2096  // #i120879# add cross reference bookmark name prefix, if it
2097  // matches internal TOC bookmark naming convention
2098  if ( IsTOCBookmarkName( sBkmName ) )
2099  {
2100  sBkmName = EnsureTOCBookmarkName(sBkmName);
2101  // track <sBookmarkName> as referenced TOC bookmark.
2102  m_xReffedStck->aReferencedTOCBookmarks.insert( sBkmName );
2103  }
2104 
2105  SwGetRefField aField(
2106  static_cast<SwGetRefFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef )),
2107  sBkmName,"",REF_BOOKMARK,0,eFormat);
2108 
2109  if (eFormat == REF_CONTENT)
2110  {
2111  /*
2112  If we are just inserting the contents of the bookmark, then it
2113  is possible that the bookmark is actually a variable, so we
2114  must store it until the end of the document to see if it was,
2115  in which case we'll turn it into a show variable
2116  */
2117  m_xReffingStck->NewAttr( *m_pPaM->GetPoint(), SwFormatField(aField) );
2118  m_xReffingStck->SetAttr( *m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2119  }
2120  else
2121  {
2123  }
2124  return eF_ResT::OK;
2125 }
2126 
2127 // Note Reference - Field
2129 {
2130  OUString aBkmName;
2131  bool bAboveBelow = false;
2132 
2133  WW8ReadFieldParams aReadParam( rStr );
2134  for (;;)
2135  {
2136  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2137  if ( nRet==-1 )
2138  break;
2139  switch( nRet )
2140  {
2141  case -2:
2142  if( aBkmName.isEmpty() ) // get name of foot/endnote
2143  aBkmName = aReadParam.GetResult();
2144  break;
2145  case 'r':
2146  // activate flag 'Chapter Number'
2147  break;
2148  case 'p':
2149  bAboveBelow = true;
2150  break;
2151  case 'h':
2152  break;
2153  default:
2154  // unimplemented switch: just do 'nix nought nothing' :-)
2155  break;
2156  }
2157  }
2158 
2159  // set Sequence No of corresponding Foot-/Endnote to Zero
2160  // (will be corrected in
2161  SwGetRefField aField( static_cast<SwGetRefFieldType*>(
2163  REF_ONLYNUMBER );
2164  m_xReffingStck->NewAttr(*m_pPaM->GetPoint(), SwFormatField(aField));
2165  m_xReffingStck->SetAttr(*m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2166  if (bAboveBelow)
2167  {
2168  SwGetRefField aField2( static_cast<SwGetRefFieldType*>(
2170  REF_UPDOWN );
2171  m_xReffingStck->NewAttr(*m_pPaM->GetPoint(), SwFormatField(aField2));
2172  m_xReffingStck->SetAttr(*m_pPaM->GetPoint(), RES_TXTATR_FIELD);
2173  }
2174  return eF_ResT::OK;
2175 }
2176 
2177 // "PAGEREF"
2179 {
2180  OUString sOrigName;
2181  WW8ReadFieldParams aReadParam( rStr );
2182  for (;;)
2183  {
2184  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2185  if ( nRet==-1 )
2186  break;
2187  else if ( nRet == -2 && sOrigName.isEmpty() )
2188  {
2189  sOrigName = aReadParam.GetResult();
2190  }
2191  }
2192 
2193  const OUString sName(GetMappedBookmark(sOrigName));
2194 
2195  // loading page reference field in TOX
2196  if (m_bLoadingTOXCache)
2197  {
2198  // insert page ref representation as plain text --> return FLD_TEXT
2199  // if there is no hyperlink settings for current toc and referenced bookmark is available,
2200  // assign link to current ref area
2201  if (!m_bLoadingTOXHyperlink && !sName.isEmpty())
2202  {
2203  // #i120879# add cross reference bookmark name prefix, if it
2204  // matches internal TOC bookmark naming convention
2205  OUString sBookmarkName;
2206  if ( IsTOCBookmarkName( sName ) )
2207  {
2208  sBookmarkName = EnsureTOCBookmarkName(sName);
2209  // track <sBookmarkName> as referenced TOC bookmark.
2210  m_xReffedStck->aReferencedTOCBookmarks.insert( sBookmarkName );
2211  }
2212  else
2213  {
2214  sBookmarkName = sName;
2215  }
2216  OUString sURL = "#" + sBookmarkName;
2217  SwFormatINetFormat aURL( sURL, "" );
2218  static const OUStringLiteral sLinkStyle(u"Index Link");
2219  const sal_uInt16 nPoolId =
2221  aURL.SetVisitedFormatAndId( sLinkStyle, nPoolId);
2222  aURL.SetINetFormatAndId( sLinkStyle, nPoolId );
2223  m_xCtrlStck->NewAttr( *m_pPaM->GetPoint(), aURL );
2224  }
2225  return eF_ResT::TEXT;
2226  }
2227 
2228  // #i120879# add cross reference bookmark name prefix, if it matches
2229  // internal TOC bookmark naming convention
2230  OUString sPageRefBookmarkName;
2231  if ( IsTOCBookmarkName( sName ) )
2232  {
2233  sPageRefBookmarkName = EnsureTOCBookmarkName(sName);
2234  // track <sPageRefBookmarkName> as referenced TOC bookmark.
2235  m_xReffedStck->aReferencedTOCBookmarks.insert( sPageRefBookmarkName );
2236  }
2237  else
2238  {
2239  sPageRefBookmarkName = sName;
2240  }
2241  SwGetRefField aField( static_cast<SwGetRefFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::GetRef )),
2242  sPageRefBookmarkName, "", REF_BOOKMARK, 0, REF_PAGE );
2244 
2245  return eF_ResT::OK;
2246 }
2247 
2248 //helper function
2249 //For MS MacroButton field, the symbol in plain text is always "(" (0x28),
2250 //which should be mapped according to the macro type
2251 static bool ConvertMacroSymbol( std::u16string_view rName, OUString& rReference )
2252 {
2253  bool bConverted = false;
2254  if( rReference == "(" )
2255  {
2256  bConverted = true;
2257  sal_Unicode cSymbol = sal_Unicode(); // silence false warning
2258  if (rName == u"CheckIt")
2259  cSymbol = 0xF06F;
2260  else if (rName == u"UncheckIt")
2261  cSymbol = 0xF0FE;
2262  else if (rName == u"ShowExample")
2263  cSymbol = 0xF02A;
2264  //else if... : todo
2265  else
2266  bConverted = false;
2267 
2268  if( bConverted )
2269  rReference = OUString(cSymbol);
2270  }
2271  return bConverted;
2272 }
2273 
2274 // "MACROBUTTON"
2276 {
2277  OUString aName;
2278  OUString aVText;
2279  bool bNewVText = true;
2280  bool bBracket = false;
2281  WW8ReadFieldParams aReadParam( rStr );
2282 
2283  sal_Int32 nOffset = 0;
2284 
2285  for (;;)
2286  {
2287  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2288  if ( nRet==-1 )
2289  break;
2290  switch( nRet )
2291  {
2292  case -2:
2293  if( aName.isEmpty() )
2294  aName = aReadParam.GetResult();
2295  else if( aVText.isEmpty() || bBracket )
2296  {
2297  nOffset = aReadParam.GetTokenSttPtr() + 1;
2298 
2299  if( bBracket )
2300  aVText += " ";
2301  aVText += aReadParam.GetResult();
2302  if (bNewVText)
2303  {
2304  bBracket = (aVText[0] == '[');
2305  bNewVText = false;
2306  }
2307  else if( aVText.endsWith("]") )
2308  bBracket = false;
2309  }
2310  break;
2311  }
2312  }
2313  if( aName.isEmpty() )
2314  return eF_ResT::TAGIGN; // makes no sense without Macro-Name
2315 
2316  NotifyMacroEventRead();
2317 
2318  //try converting macro symbol according to macro name
2319  bool bApplyWingdings = ConvertMacroSymbol( aName, aVText );
2320  aName = "StarOffice.Standard.Modul1." + aName;
2321 
2322  SwMacroField aField( static_cast<SwMacroFieldType*>(
2324 
2325  if( !bApplyWingdings )
2326  {
2327 
2329  WW8_CP nOldCp = m_xPlcxMan->Where();
2330  WW8_CP nCp = nOldCp + nOffset;
2331 
2332  SwPaM aPaM(*m_pPaM, m_pPaM);
2333  aPaM.SetMark();
2334  aPaM.Move(fnMoveBackward);
2335  aPaM.Exchange();
2336 
2337  m_pPostProcessAttrsInfo.reset(new WW8PostProcessAttrsInfo(nCp, nCp, aPaM));
2338  }
2339  else
2340  {
2341  //set Wingdings font
2342  sal_uInt16 i = 0;
2343  for ( ; i < m_xFonts->GetMax(); i++ )
2344  {
2345  FontFamily eFamily;
2346  OUString aFontName;
2347  FontPitch ePitch;
2348  rtl_TextEncoding eSrcCharSet;
2349  if( GetFontParams( i, eFamily, aFontName, ePitch, eSrcCharSet )
2350  && aFontName=="Wingdings" )
2351  {
2352  break;
2353  }
2354  }
2355 
2356  if ( i < m_xFonts->GetMax() )
2357  {
2358 
2359  SetNewFontAttr( i, true, RES_CHRATR_FONT );
2361  m_xCtrlStck->SetAttr( *m_pPaM->GetPoint(), RES_CHRATR_FONT );
2362  ResetCharSetVars();
2363  }
2364  }
2365 
2366  return eF_ResT::OK;
2367 }
2368 
2370  SwPaM & rPaM)
2371  : mbCopy(false)
2372  , mnCpStart(nCpStart)
2373  , mnCpEnd(nCpEnd)
2374  , mPaM(*rPaM.GetMark(), *rPaM.GetPoint())
2375  , mItemSet(rPaM.GetDoc().GetAttrPool(), svl::Items<RES_CHRATR_BEGIN, RES_PARATR_END - 1>{})
2376 {
2377 }
2378 
2379 bool CanUseRemoteLink(const OUString &rGrfName)
2380 {
2381  bool bUseRemote = false;
2382  try
2383  {
2384  // Related: tdf#102499, add a default css::ucb::XCommandEnvironment
2385  // in order to have https protocol manage certificates correctly
2386  uno::Reference< task::XInteractionHandler > xIH(
2387  task::InteractionHandler::createWithParent(comphelper::getProcessComponentContext(), nullptr));
2388 
2389  uno::Reference< ucb::XProgressHandler > xProgress;
2391  new ::ucbhelper::CommandEnvironment(new comphelper::SimpleFileAccessInteraction( xIH ), xProgress);
2392 
2393  ::ucbhelper::Content aCnt(rGrfName,
2394  static_cast< ucb::XCommandEnvironment* >(pCommandEnv.get()),
2396 
2397  if ( !INetURLObject( rGrfName ).isAnyKnownWebDAVScheme() )
2398  {
2399  OUString aTitle;
2400  aCnt.getPropertyValue("Title") >>= aTitle;
2401  bUseRemote = !aTitle.isEmpty();
2402  }
2403  else
2404  {
2405  // is a link to a WebDAV resource
2406  // need to use MediaType to check for link usability
2407  OUString aMediaType;
2408  aCnt.getPropertyValue("MediaType") >>= aMediaType;
2409  bUseRemote = !aMediaType.isEmpty();
2410  }
2411  }
2412  catch ( ... )
2413  {
2414  // this file did not exist, so we will not set this as graphiclink
2415  bUseRemote = false;
2416  }
2417  return bUseRemote;
2418 }
2419 
2420 // "INCLUDEPICTURE"
2422 {
2423  OUString aGrfName;
2424  bool bEmbedded = true;
2425 
2426  WW8ReadFieldParams aReadParam( rStr );
2427  for (;;)
2428  {
2429  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2430  if ( nRet==-1 )
2431  break;
2432  switch( nRet )
2433  {
2434  case -2:
2435  if (aGrfName.isEmpty())
2436  aGrfName = ConvertFFileName(aReadParam.GetResult());
2437  break;
2438 
2439  case 'd':
2440  bEmbedded = false;
2441  break;
2442 
2443  case 'c':// skip the converter name
2444  aReadParam.FindNextStringPiece();
2445  break;
2446  }
2447  }
2448 
2449  if (!bEmbedded)
2450  bEmbedded = !CanUseRemoteLink(aGrfName);
2451 
2452  if (!bEmbedded)
2453  {
2454  /*
2455  Special case:
2456 
2457  Now we write the Link into the Doc and remember the SwFlyFrameFormat.
2458  Since we end on return FLD_READ_FSPA below, the skip value will be set
2459  so that Char-1 will still be read.
2460  When we then call SwWW8ImplReader::ImportGraf() it will then recognize
2461  that we have inserted a graphic link and the suiting SwAttrSet will be
2462  inserted into the frame format.
2463  */
2465  RES_FRMATR_END-1>{} );
2466  aFlySet.Put( SwFormatAnchor( RndStdIds::FLY_AS_CHAR ) );
2467  aFlySet.Put( SwFormatVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
2470  aGrfName,
2471  OUString(),
2472  nullptr, // Graphic*
2473  &aFlySet,
2474  nullptr, nullptr); // SwFrameFormat*
2476  INetURLObject(aGrfName).GetBase());
2477  }
2478  return eF_ResT::READ_FSPA;
2479 }
2480 
2482 {
2483  const OUString aName(msFileLinkSeed + OUString::number(++mnFileSectionNo));
2484  return mrDoc.GetUniqueSectionName(&aName);
2485 }
2486 
2487 // "INCLUDETEXT"
2489 {
2490  OUString aPara;
2491  OUString aBook;
2492  WW8ReadFieldParams aReadParam( rStr );
2493  for (;;)
2494  {
2495  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2496  if ( nRet==-1 )
2497  break;
2498  switch( nRet )
2499  {
2500  case -2:
2501  if( aPara.isEmpty() )
2502  aPara = aReadParam.GetResult();
2503  else if( aBook.isEmpty() )
2504  aBook = aReadParam.GetResult();
2505  break;
2506  case '*':
2507  //Skip over MERGEFORMAT
2508  (void)aReadParam.SkipToNextToken();
2509  break;
2510  }
2511  }
2512  aPara = ConvertFFileName(aPara);
2513 
2514  if (!aBook.isEmpty() && aBook[ 0 ] != '\\')
2515  {
2516  // Section from Source (no switch)?
2517  ConvertUFName(aBook);
2518  aPara += OUStringChar(sfx2::cTokenSeparator)
2519  + OUStringChar(sfx2::cTokenSeparator) + aBook;
2520  }
2521 
2522  /*
2523  ##509##
2524  What we will do is insert a section to be linked to a file, but just in
2525  case the file is not available we will fill in the section with the stored
2526  content of this winword field as a fallback.
2527  */
2528  SwPosition aTmpPos(*m_pPaM->GetPoint());
2529 
2532  aSection.SetLinkFileName( aPara );
2533  aSection.SetProtectFlag(true);
2534 
2535  SwSection *const pSection =
2536  m_rDoc.InsertSwSection(*m_pPaM, aSection, nullptr, nullptr, false);
2537  OSL_ENSURE(pSection, "no section inserted");
2538  if (!pSection)
2539  return eF_ResT::TEXT;
2540  const SwSectionNode* pSectionNode = pSection->GetFormat()->GetSectionNode();
2541  OSL_ENSURE(pSectionNode, "no section node!");
2542  if (!pSectionNode)
2543  return eF_ResT::TEXT;
2544 
2545  m_pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
2547 
2548  //we have inserted a section before this point, so adjust pos
2549  //for future page/section segment insertion
2551 
2552  return eF_ResT::TEXT;
2553 }
2554 
2555 // "SERIALPRINT"
2557 {
2558 #if !HAVE_FEATURE_DBCONNECTIVITY
2559  (void) pF;
2560  (void) rStr;
2561 #else
2562  OUString aName;
2563  WW8ReadFieldParams aReadParam( rStr );
2564  for (;;)
2565  {
2566  const sal_Int32 nRet = aReadParam.SkipToNextToken();
2567  if ( nRet==-1 )
2568  break;
2569  switch( nRet )
2570  {
2571  case -2:
2572  if( aName.isEmpty() )
2573  aName = aReadParam.GetResult();
2574  break;
2575  }
2576  }
2577  SwDBFieldType aD( &m_rDoc, aName, SwDBData() ); // Database: nothing
2578 
2580  SwDBField aField( static_cast<SwDBFieldType*>(pFT) );
2581  aField.SetFieldCode( rStr );
2582 
2583  OUString aResult;
2584  m_xSBase->WW8ReadString( *m_pStrm, aResult, m_xPlcxMan->GetCpOfs()+
2585  pF->nSRes, pF->nLRes, m_eTextCharSet );
2586 
2587  aResult = aResult.replace( '\xb', '\n' );
2588 
2589  aField.InitContent(aResult);
2590 
2592 #endif
2593  return eF_ResT::OK;
2594 }
2595 
2596 // "NEXT"
2598 {
2599 #if HAVE_FEATURE_DBCONNECTIVITY
2602  SwDBNextSetField aField( static_cast<SwDBNextSetFieldType*>(pFT), OUString(),
2603  SwDBData() ); // Database: nothing
2605 #endif
2606  return eF_ResT::OK;
2607 }
2608 
2609 // "DATASET"
2611 {
2612 #if HAVE_FEATURE_DBCONNECTIVITY
2615  SwDBSetNumberField aField( static_cast<SwDBSetNumberFieldType*>(pFT),
2616  SwDBData() ); // Datenbase: nothing
2618 #endif
2619  return eF_ResT::OK;
2620 }
2621 
2622 /*
2623  EQ , only the usage for
2624  a. Combined Characters supported, must be exactly in the form that word
2625  only accepts as combined characters, i.e.
2626  eq \o(\s\up Y(XXX),\s\do Y(XXX))
2627  b. Ruby Text supported, must be in the form that word recognizes as being
2628  ruby text
2629  ...
2630 */
2632 {
2633  WW8ReadFieldParams aReadParam( rStr );
2634  const sal_Int32 cChar = aReadParam.SkipToNextToken();
2635  if ('o' == cChar || 'O' == cChar)
2636  {
2637  EquationResult aResult(ParseCombinedChars(rStr));
2638 
2639  if (aResult.sType == "Input")
2640  {
2641  SwInputField aField( static_cast<SwInputFieldType*>(m_rDoc.getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Input )),
2642  aResult.sResult, aResult.sResult, INP_TXT, 0 );
2643  m_rDoc.getIDocumentContentOperations().InsertPoolItem( *m_pPaM, SwFormatField( aField ) ); // insert input field
2644  }
2645  else if (aResult.sType == "CombinedCharacters")
2646  {
2647  SwCombinedCharField aField(static_cast<SwCombinedCharFieldType*>(
2650  }
2651  }
2652  else if ('*' == cChar)
2653  Read_SubF_Ruby(aReadParam);
2654 
2655  return eF_ResT::OK;
2656 }
2657 
2659 {
2660  sal_uInt16 nJustificationCode=0;
2661  OUString sFontName;
2662  sal_uInt32 nFontSize=0;
2663  OUString sRuby;
2664  OUString sText;
2665  for (;;)
2666  {
2667  const sal_Int32 nRet = rReadParam.SkipToNextToken();
2668  if ( nRet==-1 )
2669  break;
2670  switch( nRet )
2671  {
2672  case -2:
2673  {
2674  OUString sTemp = rReadParam.GetResult();
2675  if( sTemp.startsWithIgnoreAsciiCase( "jc" ) )
2676  {
2677  sTemp = sTemp.copy(2);
2678  nJustificationCode = static_cast<sal_uInt16>(sTemp.toInt32());
2679  }
2680  else if( sTemp.startsWithIgnoreAsciiCase( "hps" ) )
2681  {
2682  sTemp = sTemp.copy(3);
2683  nFontSize= static_cast<sal_uInt32>(sTemp.toInt32());
2684  }
2685  else if( sTemp.startsWithIgnoreAsciiCase( "Font:" ) )
2686  {
2687  sTemp = sTemp.copy(5);
2688  sFontName = sTemp;
2689  }
2690  }
2691  break;
2692  case '*':
2693  break;
2694  case 'o':
2695  for (;;)
2696  {
2697  const sal_Int32 nRes = rReadParam.SkipToNextToken();
2698  if ( nRes==-1 )
2699  break;
2700  if ('u' == nRes)
2701  {
2702  if (-2 == rReadParam.SkipToNextToken() &&
2703  rReadParam.GetResult().startsWithIgnoreAsciiCase("p"))
2704  {
2705  if (-2 == rReadParam.SkipToNextToken())
2706  {
2707  OUString sPart = rReadParam.GetResult();
2708  sal_Int32 nBegin = sPart.indexOf('(');
2709 
2710  //Word disallows brackets in this field,
2711  sal_Int32 nEnd = sPart.indexOf(')');
2712 
2713  if ((nBegin != -1) &&
2714  (nEnd != -1) && (nBegin < nEnd))
2715  {
2716  sRuby = sPart.copy(nBegin+1,nEnd-nBegin-1);
2717  }
2718  if (-1 != nEnd)
2719  {
2720  nBegin = sPart.indexOf(',',nEnd);
2721  if (-1 == nBegin)
2722  {
2723  nBegin = sPart.indexOf(';',nEnd);
2724  }
2725  nEnd = sPart.lastIndexOf(')');
2726  }
2727  if ((nBegin != -1) && (nEnd != -1) && (nBegin < nEnd))
2728  {
2729  sText = sPart.copy(nBegin+1,nEnd-nBegin-1);
2730  sText = sw::FilterControlChars(sText);
2731  }
2732  }
2733  }
2734  }
2735  }
2736  break;
2737  }
2738  }
2739 
2740  //Translate and apply
2741  if (sRuby.isEmpty() || sText.isEmpty() || sFontName.isEmpty() || !nFontSize)
2742  return;
2743 
2744  css::text::RubyAdjust eRubyAdjust;
2745  switch (nJustificationCode)
2746  {
2747  case 0:
2748  eRubyAdjust = css::text::RubyAdjust_CENTER;
2749  break;
2750  case 1:
2751  eRubyAdjust = css::text::RubyAdjust_BLOCK;
2752  break;
2753  case 2:
2754  eRubyAdjust = css::text::RubyAdjust_INDENT_BLOCK;
2755  break;
2756  default:
2757  case 3:
2758  eRubyAdjust = css::text::RubyAdjust_LEFT;
2759  break;
2760  case 4:
2761  eRubyAdjust = css::text::RubyAdjust_RIGHT;
2762  break;
2763  }
2764 
2765  SwFormatRuby aRuby(sRuby);
2766  const SwCharFormat *pCharFormat=nullptr;
2767  //Make a guess at which of asian of western we should be setting
2769  sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
2770 
2771  //Check to see if we already have a ruby charstyle that this fits
2772  for(const auto& rpCharFormat : m_aRubyCharFormats)
2773  {
2774  const SvxFontHeightItem &rFH =
2775  ItemGet<SvxFontHeightItem>(*rpCharFormat,
2777  if (rFH.GetHeight() == nFontSize*10)
2778  {
2779  const SvxFontItem &rF = ItemGet<SvxFontItem>(*rpCharFormat,
2781  if (rF.GetFamilyName() == sFontName)
2782  {
2783  pCharFormat = rpCharFormat;
2784  break;
2785  }
2786  }
2787  }
2788 
2789  //Create a new char style if necessary
2790  if (!pCharFormat)
2791  {
2792  OUString aNm;
2793  //Take this as the base name
2795  aNm+=OUString::number(m_aRubyCharFormats.size()+1);
2797  SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
2798  SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
2799  OUString(), PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
2800  aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
2801  aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
2802  pFormat->SetFormatAttr(aHeightItem);
2803  pFormat->SetFormatAttr(aFontItem);
2804  m_aRubyCharFormats.push_back(pFormat);
2805  pCharFormat = pFormat;
2806  }
2807 
2808  //Set the charstyle and justification
2809  aRuby.SetCharFormatName(pCharFormat->GetName());
2810  aRuby.SetCharFormatId(pCharFormat->GetPoolFormatId());
2811  aRuby.SetAdjustment(eRubyAdjust);
2812 
2813  NewAttr(aRuby);
2816 
2817 }
2818 
2819 // "table of ..." fields
2820 
2821 static void lcl_toxMatchACSwitch(SwDoc const & rDoc,
2822  SwTOXBase& rBase,
2823  WW8ReadFieldParams& rParam,
2824  SwCaptionDisplay eCaptionType)
2825 {
2826  if ( rParam.GoToTokenParam() )
2827  {
2828  SwTOXType* pType = const_cast<SwTOXType*>(rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0));
2829  rBase.RegisterToTOXType( *pType );
2830  rBase.SetCaptionDisplay( eCaptionType );
2831  // Read Sequence Name and store in TOXBase
2832  OUString sSeqName( rParam.GetResult() );
2833  lcl_ConvertSequenceName( sSeqName );
2834  rBase.SetSequenceName( sSeqName );
2835  }
2836 }
2837 
2839 {
2840  //If the TOC contains Template entries at levels > the evaluation level
2841  //that was initially taken from the max normal outline level of the word TOC
2842  //then we cannot use that for the evaluation level because writer cuts off
2843  //all styles above that level, while word just cuts off the "standard"
2844  //outline styles, we have no option but to expand to the highest level
2845  //Word included.
2846  if ((rBase.GetLevel() != MAXLEVEL) && (SwTOXElement::Template & rBase.GetCreateType()))
2847  {
2848  for (sal_uInt16 nI = MAXLEVEL; nI > 0; --nI)
2849  {
2850  if (!rBase.GetStyleNames(nI-1).isEmpty())
2851  {
2852  rBase.SetLevel(nI);
2853  break;
2854  }
2855  }
2856  }
2857 }
2858 
2859 static void lcl_toxMatchTSwitch(SwWW8ImplReader const & rReader, SwTOXBase& rBase,
2860  WW8ReadFieldParams& rParam)
2861 {
2862  if ( !rParam.GoToTokenParam() )
2863  return;
2864 
2865  OUString sParams( rParam.GetResult() );
2866  if( sParams.isEmpty() )
2867  return;
2868 
2869  sal_Int32 nIndex = 0;
2870 
2871  // Delimiters between styles and style levels appears to allow both ; and ,
2872 
2873  OUString sTemplate( sParams.getToken(0, ';', nIndex) );
2874  if( -1 == nIndex )
2875  {
2876  nIndex=0;
2877  sTemplate = sParams.getToken(0, ',', nIndex);
2878  }
2879  if( -1 == nIndex )
2880  {
2881  const SwFormat* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
2882  if( pStyle )
2883  sTemplate = pStyle->GetName();
2884  // Store Style for Level 0 into TOXBase
2885  rBase.SetStyleNames( sTemplate, 0 );
2886  }
2887  else while( -1 != nIndex )
2888  {
2889  sal_Int32 nOldIndex=nIndex;
2890  sal_uInt16 nLevel = static_cast<sal_uInt16>(
2891  sParams.getToken(0, ';', nIndex).toInt32());
2892  if( -1 == nIndex )
2893  {
2894  nIndex = nOldIndex;
2895  nLevel = static_cast<sal_uInt16>(
2896  sParams.getToken(0, ',', nIndex).toInt32());
2897  }
2898 
2899  if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
2900  {
2901  nLevel--;
2902  // Store Style and Level into TOXBase
2903  const SwFormat* pStyle
2904  = rReader.GetStyleWithOrgWWName( sTemplate );
2905 
2906  if( pStyle )
2907  sTemplate = pStyle->GetName();
2908 
2909  OUString sStyles( rBase.GetStyleNames( nLevel ) );
2910  if( !sStyles.isEmpty() )
2911  sStyles += OUStringChar(TOX_STYLE_DELIMITER);
2912  sStyles += sTemplate;
2913  rBase.SetStyleNames( sStyles, nLevel );
2914  }
2915  // read next style name...
2916  nOldIndex = nIndex;
2917  sTemplate = sParams.getToken(0, ';', nIndex);
2918  if( -1 == nIndex )
2919  {
2920  nIndex=nOldIndex;
2921  sTemplate = sParams.getToken(0, ',', nIndex);
2922  }
2923  }
2924 }
2925 
2927 {
2928  sal_uInt16 nIndexCols = 1;
2929  if (!maSegments.empty())
2930  nIndexCols = maSegments.back().maSep.ccolM1 + 1;
2931  return nIndexCols;
2932 }
2933 
2934 //Will there be a new pagebreak at this position (don't know what type
2935 //until later)
2937 {
2938  bool bRet = false;
2939  if (!maSegments.empty())
2940  {
2941  if (!maSegments.back().IsContinuous() &&
2942  maSegments.back().maStart == rIdx)
2943  {
2944  bRet = true;
2945  }
2946  }
2947  return bRet;
2948 }
2949 
2950 static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
2951 {
2952  // GetFormMax() returns level + 1, hence the -1
2953  sal_uInt16 nRet = rForm.GetFormMax()-1;
2954 
2955  // If the max of this type of TOC is greater than the max of a word
2956  // possible toc, then clip to the word max
2957  if (nRet > WW8ListManager::nMaxLevel)
2959 
2960  return nRet;
2961 }
2962 
2964 {
2965  if (!m_bLoadingTOXCache)
2966  {
2967  m_bLoadingTOXCache = true;
2968  }
2969  else
2970  {
2971  // Embedded TOX --> continue reading its content, but no further TOX
2972  // field
2974  return eF_ResT::TEXT;
2975  }
2976 
2977  if (pF->nLRes < 3)
2978  return eF_ResT::TEXT; // ignore (#i25440#)
2979 
2980  TOXTypes eTox; // create a ToxBase
2981  switch( pF->nId )
2982  {
2983  case 8:
2984  eTox = TOX_INDEX;
2985  break;
2986  case 13:
2987  eTox = TOX_CONTENT;
2988  break;
2989  default:
2990  eTox = TOX_USER;
2991  break;
2992  }
2993 
2995 
2996  sal_uInt16 nIndexCols = 1;
2997 
2998  const SwTOXType* pType = m_rDoc.GetTOXType( eTox, 0 );
2999  SwForm aOrigForm(eTox);
3000  std::shared_ptr<SwTOXBase> pBase = std::make_shared<SwTOXBase>( pType, aOrigForm, nCreateOf, OUString() );
3001  pBase->SetProtected(m_aSectionManager.CurrentSectionIsProtected());
3002  switch( eTox ){
3003  case TOX_INDEX:
3004  {
3006 
3007  // We set SwTOXElement::OutlineLevel only if
3008  // the parameter \o is within 1 to 9
3009  // or the parameter \f exists
3010  // or NO switch parameter are given at all.
3011  WW8ReadFieldParams aReadParam( rStr );
3012  for (;;)
3013  {
3014  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3015  if ( nRet==-1 )
3016  break;
3017  switch( nRet )
3018  {
3019  case 'c':
3020  if ( aReadParam.GoToTokenParam() )
3021  {
3022  const OUString sParams( aReadParam.GetResult() );
3023  // if NO OUString just ignore the \c
3024  if( !sParams.isEmpty() )
3025  {
3026  nIndexCols = static_cast<sal_uInt16>(sParams.toInt32());
3027  }
3028  }
3029  break;
3030  case 'e':
3031  {
3032  if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \e
3033  {
3034  OUString sDelimiter( aReadParam.GetResult() );
3035  SwForm aForm( pBase->GetTOXForm() );
3036 
3037  // Attention: if TOX_CONTENT brave
3038  // GetFormMax() returns MAXLEVEL + 1 !!
3039  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3040 
3041  for(sal_uInt16 nLevel = 1;
3042  nLevel <= nEnd;
3043  ++nLevel)
3044  {
3045  // Levels count from 1
3046  // Level 0 is reserved for CAPTION
3047 
3048  // Insert delimiter instead of tab in front of the page number if there is one:
3049  FormTokenType ePrevType = TOKEN_END;
3051  // -> #i21237#
3052  SwFormTokens aPattern =
3053  aForm.GetPattern(nLevel);
3054  SwFormTokens::iterator aIt = aPattern.begin();
3055  do
3056  {
3057  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3058 
3059  if (eType == TOKEN_PAGE_NUMS)
3060  {
3061  if (TOKEN_TAB_STOP == ePrevType)
3062  {
3063  --aIt;
3064 
3065  if(0x09 == sDelimiter[0])
3066  aIt->eTabAlign = SvxTabAdjust::End;
3067  else
3068  {
3069  SwFormToken aToken(TOKEN_TEXT);
3070  aToken.sText = sDelimiter;
3071  *aIt = aToken;
3072  }
3073  aForm.SetPattern(nLevel, aPattern);
3074  }
3075 
3076  eType = TOKEN_END;
3077  }
3078 
3079  ePrevType = eType;
3080  }
3081  while (TOKEN_END != eType);
3082  // <- #i21237#
3083  }
3084  pBase->SetTOXForm( aForm );
3085  }
3086  }
3087  break;
3088  case 'h':
3089  {
3090  eOptions |= SwTOIOptions::AlphaDelimiter;
3091  }
3092  break;
3093  }
3094  }
3095  pBase->SetOptions( eOptions );
3096  }
3097  break;
3098 
3099  case TOX_CONTENT:
3100  {
3101  bool bIsHyperlink = false;
3102  // We set SwTOXElement::OutlineLevel only if
3103  // the parameter \o is within 1 to 9
3104  // or the parameter \f exists
3105  // or NO switch parameter are given at all.
3106  SwTOXElement eCreateFrom = SwTOXElement::NONE;
3107  sal_Int32 nMaxLevel = 0;
3108  WW8ReadFieldParams aReadParam( rStr );
3109  for (;;)
3110  {
3111  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3112  if ( nRet==-1 )
3113  break;
3114  switch( nRet )
3115  {
3116  case 'h':
3117  bIsHyperlink = true;
3118  break;
3119  case 'a':
3120  case 'c':
3121  lcl_toxMatchACSwitch(m_rDoc, *pBase, aReadParam,
3122  ('c' == nRet)
3124  : CAPTION_TEXT );
3125  break;
3126  case 'o':
3127  {
3128  sal_Int32 nVal;
3129  if( !aReadParam.GetTokenSttFromTo(nullptr, &nVal, WW8ListManager::nMaxLevel) )
3130  nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
3131  if( nMaxLevel < nVal )
3132  nMaxLevel = nVal;
3133  eCreateFrom |= SwTOXElement::OutlineLevel;
3134  }
3135  break;
3136  case 'f':
3137  eCreateFrom |= SwTOXElement::Mark;
3138  break;
3139  case 'l':
3140  {
3141  sal_Int32 nVal;
3142  if( aReadParam.GetTokenSttFromTo(nullptr, &nVal, WW8ListManager::nMaxLevel) )
3143  {
3144  if( nMaxLevel < nVal )
3145  nMaxLevel = nVal;
3146  eCreateFrom |= SwTOXElement::Mark;
3147  }
3148  }
3149  break;
3150  case 't': // paragraphs using special styles shall
3151  // provide the TOX's content
3152  lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
3153  eCreateFrom |= SwTOXElement::Template;
3154  break;
3155  case 'p':
3156  {
3157  if ( aReadParam.GoToTokenParam() ) // if NO String just ignore the \p
3158  {
3159  OUString sDelimiter( aReadParam.GetResult() );
3160  SwForm aForm( pBase->GetTOXForm() );
3161 
3162  // Attention: if TOX_CONTENT brave
3163  // GetFormMax() returns MAXLEVEL + 1 !!
3164  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3165 
3166  for(sal_uInt16 nLevel = 1;
3167  nLevel <= nEnd;
3168  ++nLevel)
3169  {
3170  // Levels count from 1
3171  // Level 0 is reserved for CAPTION
3172 
3173  // Insert delimiter instead of tab in front of the pagenumber if there is one:
3174  FormTokenType ePrevType = TOKEN_END;
3176 
3177  // -> #i21237#
3178  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3179  SwFormTokens::iterator aIt = aPattern.begin();
3180  do
3181  {
3182  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3183 
3184  if (eType == TOKEN_PAGE_NUMS)
3185  {
3186  if (TOKEN_TAB_STOP == ePrevType)
3187  {
3188  --aIt;
3189 
3190  SwFormToken aToken(TOKEN_TEXT);
3191  aToken.sText = sDelimiter;
3192 
3193  *aIt = aToken;
3194  aForm.SetPattern(nLevel,
3195  aPattern);
3196  }
3197  eType = TOKEN_END;
3198  }
3199  ePrevType = eType;
3200  }
3201  while( TOKEN_END != eType );
3202  // <- #i21237#
3203  }
3204  pBase->SetTOXForm( aForm );
3205  }
3206  }
3207  break;
3208  case 'n': // don't print page numbers
3209  {
3210  // read START and END param
3211  sal_Int32 nStart(0);
3212  sal_Int32 nEnd(0);
3213  if( !aReadParam.GetTokenSttFromTo( &nStart, &nEnd,
3215  {
3216  nStart = 1;
3217  nEnd = aOrigForm.GetFormMax()-1;
3218  }
3219  // remove page numbers from this levels
3220  SwForm aForm( pBase->GetTOXForm() );
3221  if (aForm.GetFormMax() <= nEnd)
3222  nEnd = aForm.GetFormMax()-1;
3223  for ( sal_Int32 nLevel = nStart; nLevel<=nEnd; ++nLevel )
3224  {
3225  // Levels count from 1
3226  // Level 0 is reserved for CAPTION
3227 
3228  // Remove pagenumber and if necessary the tab in front of it:
3230  // -> #i21237#
3231  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3232  SwFormTokens::iterator aIt = aPattern.begin();
3233  do
3234  {
3235  eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
3236 
3237  if (eType == TOKEN_PAGE_NUMS)
3238  {
3239  aIt = aPattern.erase(aIt);
3240  --aIt;
3241  if (
3242  TOKEN_TAB_STOP ==
3243  aIt->eTokenType
3244  )
3245  {
3246  aPattern.erase(aIt);
3247  aForm.SetPattern(nLevel, aPattern);
3248  }
3249  eType = TOKEN_END;
3250  }
3251  }
3252  while (TOKEN_END != eType);
3253  // <- #i21237#
3254  }
3255  pBase->SetTOXForm( aForm );
3256  }
3257  break;
3258 
3259  /*
3260  // the following switches are not (yet) supported
3261  // by good old StarWriter:
3262  case 'b':
3263  case 's':
3264  case 'd':
3265  break;
3266  */
3267  }
3268  }
3269 
3270  // For loading the expression of TOC field, we need to mapping its parameters to TOX entries tokens
3271  // also include the hyperlinks and page references
3272  SwFormToken aLinkStart(TOKEN_LINK_START);
3273  SwFormToken aLinkEnd(TOKEN_LINK_END);
3274  aLinkStart.sCharStyleName = "Index Link";
3275  aLinkEnd.sCharStyleName = "Index Link";
3276  SwForm aForm(pBase->GetTOXForm());
3277  sal_uInt16 nEnd = aForm.GetFormMax()-1;
3278 
3279  for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
3280  {
3281  SwFormTokens aPattern = aForm.GetPattern(nLevel);
3282  if ( bIsHyperlink )
3283  {
3284  aPattern.insert(aPattern.begin(), aLinkStart);
3285  }
3286  else
3287  {
3288  auto aItr = std::find_if(aPattern.begin(), aPattern.end(),
3289  [](const SwFormToken& rToken) { return rToken.eTokenType == TOKEN_PAGE_NUMS; });
3290  if (aItr != aPattern.end())
3291  aPattern.insert(aItr, aLinkStart);
3292  }
3293  aPattern.push_back(aLinkEnd);
3294  aForm.SetPattern(nLevel, aPattern);
3295  }
3296  pBase->SetTOXForm(aForm);
3297 
3298  if (!nMaxLevel)
3299  nMaxLevel = WW8ListManager::nMaxLevel;
3300  pBase->SetLevel(nMaxLevel);
3301 
3302  const TOXTypes eType = pBase->GetTOXType()->GetType();
3303  switch( eType )
3304  {
3305  case TOX_CONTENT:
3306  {
3307  //If we would be created from outlines, either explicitly or by default
3308  //then see if we need extra styles added to the outlines
3309  SwTOXElement eEffectivelyFrom = eCreateFrom != SwTOXElement::NONE ? eCreateFrom : SwTOXElement::OutlineLevel;
3310  if (eEffectivelyFrom & SwTOXElement::OutlineLevel)
3311  {
3312  // #i19683# Insert a text token " " between the number and entry token.
3313  // In an ideal world we could handle the tab stop between the number and
3314  // the entry correctly, but I currently have no clue how to obtain
3315  // the tab stop position. It is _not_ set at the paragraph style.
3316  std::unique_ptr<SwForm> pForm;
3317  for (const SwWW8StyInf & rSI : m_vColl)
3318  {
3319  if (rSI.IsOutlineNumbered())
3320  {
3321  sal_uInt16 nStyleLevel = rSI.mnWW8OutlineLevel;
3322  const SwNumFormat& rFormat = rSI.GetOutlineNumrule()->Get( nStyleLevel );
3323  if ( SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType() )
3324  {
3325  ++nStyleLevel;
3326 
3327  if ( !pForm )
3328  pForm.reset(new SwForm( pBase->GetTOXForm() ));
3329 
3330  SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
3331  SwFormTokens::iterator aIt =
3332  find_if(aPattern.begin(), aPattern.end(),
3334 
3335  if ( aIt != aPattern.end() )
3336  {
3337  SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
3338  aNumberEntrySeparator.sText = " ";
3339  aPattern.insert( ++aIt, aNumberEntrySeparator );
3340  pForm->SetPattern( nStyleLevel, aPattern );
3341  }
3342  }
3343  }
3344  }
3345  if ( pForm )
3346  {
3347  pBase->SetTOXForm( *pForm );
3348  }
3349  }
3350 
3351  if (eCreateFrom != SwTOXElement::NONE)
3352  pBase->SetCreate(eCreateFrom);
3354  }
3355  break;
3356  case TOX_ILLUSTRATIONS:
3357  {
3358  if( eCreateFrom == SwTOXElement::NONE )
3359  eCreateFrom = SwTOXElement::Sequence;
3360  pBase->SetCreate( eCreateFrom );
3361 
3362  /*
3363  We don't know until here if we are an illustration
3364  or not, and so have being used a TOX_CONTENT so far
3365  which has 10 levels, while TOX has only two, this
3366  level is set only in the constructor of SwForm, so
3367  create a new one and copy over anything that could
3368  be set in the old one, and remove entries from the
3369  pattern which do not apply to illustration indices
3370  */
3371  SwForm aOldForm( pBase->GetTOXForm() );
3372  SwForm aNewForm( eType );
3373  sal_uInt16 nNewEnd = aNewForm.GetFormMax()-1;
3374 
3375  // #i21237#
3376  for(sal_uInt16 nLevel = 1; nLevel <= nNewEnd; ++nLevel)
3377  {
3378  SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
3379  SwFormTokens::iterator new_end =
3380  remove_if(aPattern.begin(), aPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
3381  aPattern.erase(new_end, aPattern.end() ); // table index imported with wrong page number format
3382  aForm.SetPattern( nLevel, aPattern );
3383  aForm.SetTemplate( nLevel, aOldForm.GetTemplate(nLevel) );
3384  }
3385 
3386  pBase->SetTOXForm( aNewForm );
3387  }
3388  break;
3389  default:
3390  OSL_ENSURE(false, "Unhandled toc options!");
3391  break;
3392  }
3393  }
3394  break;
3395  case TOX_USER:
3396  break;
3397  default:
3398  OSL_ENSURE(false, "Unhandled toc options!");
3399  break;
3400  } // ToxBase fertig
3401 
3402  // #i21237# - propagate tab stops from paragraph styles used in TOX to patterns of the TOX
3403  pBase->AdjustTabStops( m_rDoc );
3404 
3405  //#i10028# inserting a toc implicitly acts like a parabreak in word and writer
3406  if ( m_pPaM->End() &&
3407  m_pPaM->End()->nNode.GetNode().GetTextNode() &&
3408  m_pPaM->End()->nNode.GetNode().GetTextNode()->Len() != 0 )
3409  {
3410  m_bCareFirstParaEndInToc = true;
3411  }
3412 
3413  if (m_pPaM->GetPoint()->nContent.GetIndex())
3415 
3416  const SwPosition* pPos = m_pPaM->GetPoint();
3417 
3418  SwFltTOX aFltTOX( pBase );
3419 
3420  // test if there is already a break item on this node
3421  if(SwContentNode* pNd = pPos->nNode.GetNode().GetContentNode())
3422  {
3423  const SfxItemSet* pSet = pNd->GetpSwAttrSet();
3424  if( pSet )
3425  {
3426  if (SfxItemState::SET == pSet->GetItemState(RES_BREAK, false))
3427  aFltTOX.SetHadBreakItem(true);
3428  if (SfxItemState::SET == pSet->GetItemState(RES_PAGEDESC, false))
3429  aFltTOX.SetHadPageDescItem(true);
3430  }
3431  }
3432 
3433  //Will there be a new pagebreak at this position (don't know what type
3434  //until later)
3436  aFltTOX.SetHadPageDescItem(true);
3437 
3438  // Set start in stack
3439  m_xReffedStck->NewAttr( *pPos, aFltTOX );
3440 
3441  m_rDoc.InsertTableOf(*m_pPaM->GetPoint(), aFltTOX.GetBase());
3442 
3443  //The TOC field representation contents should be inserted into TOC section, but not after TOC section.
3444  //So we need update the document position when loading TOC representation and after loading TOC;
3445  m_pPosAfterTOC.reset(new SwPaM(*m_pPaM, m_pPaM));
3446  (*m_pPaM).Move(fnMoveBackward);
3447  SwPaM aRegion(*m_pPaM, m_pPaM);
3448 
3449  OSL_ENSURE(SwDoc::GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
3450  if (SwTOXBase* pBase2 = SwDoc::GetCurTOX(*aRegion.GetPoint()))
3451  {
3452  pBase2->SetMSTOCExpression(rStr);
3453 
3454  if ( nIndexCols > 1 )
3455  {
3456  // Set the column number for index
3458  SwFormatCol aCol;
3459  aCol.Init( nIndexCols, 708, USHRT_MAX );
3460  aSet.Put( aCol );
3461  pBase2->SetAttrSet( aSet );
3462  }
3463 
3464  // inserting a toc inserts a section before this point, so adjust pos
3465  // for future page/section segment insertion
3466  m_aSectionManager.PrependedInlineNode( *m_pPosAfterTOC->GetPoint(), aRegion.GetNode() );
3467  }
3468 
3469  // Set end in stack
3470  m_xReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
3471 
3472  if (!m_aApos.back()) //a para end in apo doesn't count
3473  m_bWasParaEnd = true;
3474 
3475  //Return FLD_TEXT, instead of FLD_OK
3476  //FLD_TEXT means the following content, commonly indicate the field representation content should be parsed
3477  //FLD_OK means the current field loading is finished. The rest part should be ignored.
3478  return eF_ResT::TEXT;
3479 }
3480 
3482 {
3483  /*
3484  #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
3485  to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
3486  the drawing that we are in the Shape field and respond accordingly
3487  */
3488  return eF_ResT::TEXT;
3489  }
3490 
3492 {
3493  OUString sURL, sTarget, sMark;
3494 
3495  //HYPERLINK "filename" [switches]
3496  rStr = comphelper::string::stripEnd(rStr, 1);
3497 
3498  bool bOptions = false;
3499  WW8ReadFieldParams aReadParam( rStr );
3500  for (;;)
3501  {
3502  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3503  if ( nRet==-1 )
3504  break;
3505  switch( nRet )
3506  {
3507  case -2:
3508  if (sURL.isEmpty() && !bOptions)
3509  sURL = ConvertFFileName(aReadParam.GetResult());
3510  break;
3511 
3512  case 'n':
3513  sTarget = "_blank";
3514  bOptions = true;
3515  break;
3516 
3517  case 'l':
3518  bOptions = true;
3519  if ( aReadParam.SkipToNextToken()==-2 )
3520  {
3521  sMark = aReadParam.GetResult();
3522  if( sMark.endsWith("\""))
3523  {
3524  sMark = sMark.copy( 0, sMark.getLength() - 1 );
3525  }
3526  // #120879# add cross reference bookmark name prefix, if it matches internal TOC bookmark naming convention
3527  if ( IsTOCBookmarkName( sMark ) )
3528  {
3529  sMark = EnsureTOCBookmarkName(sMark);
3530  // track <sMark> as referenced TOC bookmark.
3531  m_xReffedStck->aReferencedTOCBookmarks.insert( sMark );
3532  }
3533 
3534  if (m_bLoadingTOXCache)
3535  {
3536  m_bLoadingTOXHyperlink = true; //on loading a TOC field nested hyperlink field
3537  }
3538  }
3539  break;
3540  case 't':
3541  bOptions = true;
3542  if ( aReadParam.SkipToNextToken()==-2 )
3543  sTarget = aReadParam.GetResult();
3544  break;
3545  case 'h':
3546  case 'm':
3547  OSL_ENSURE( false, "Analysis still missing - unknown data" );
3548  [[fallthrough]];
3549  case 's': //worthless fake anchor option
3550  bOptions = true;
3551  break;
3552  }
3553  }
3554 
3555  // use the result
3556  OSL_ENSURE(!sURL.isEmpty() || !sMark.isEmpty(), "WW8: Empty URL");
3557 
3558  if( !sMark.isEmpty() )
3559  sURL += "#" + sMark;
3560 
3561  SwFormatINetFormat aURL(sURL, sTarget);
3562  // If on loading TOC field, change the default style into the "index link"
3563  if (m_bLoadingTOXCache)
3564  {
3565  OUString sLinkStyle("Index Link");
3566  sal_uInt16 nPoolId =
3568  aURL.SetVisitedFormatAndId( sLinkStyle, nPoolId );
3569  aURL.SetINetFormatAndId( sLinkStyle, nPoolId );
3570  }
3571 
3572  //As an attribute this needs to be closed, and that'll happen from
3573  //EndExtSprm in conjunction with the maFieldStack. If there are flyfrms
3574  //between the start and begin, their hyperlinks will be set at that time
3575  //as well.
3576  m_xCtrlStck->NewAttr( *m_pPaM->GetPoint(), aURL );
3577  return eF_ResT::TEXT;
3578 }
3579 
3580 static void lcl_ImportTox(SwDoc &rDoc, SwPaM const &rPaM, const OUString &rStr, bool bIdx)
3581 {
3582  TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX; // Default
3583 
3584  sal_uInt16 nLevel = 1;
3585 
3586  OUString sFieldText;
3587  WW8ReadFieldParams aReadParam(rStr);
3588  for (;;)
3589  {
3590  const sal_Int32 nRet = aReadParam.SkipToNextToken();
3591  if ( nRet==-1 )
3592  break;
3593  switch( nRet )
3594  {
3595  case -2:
3596  if( sFieldText.isEmpty() )
3597  {
3598  // PrimaryKey without ":", 2nd after
3599  sFieldText = aReadParam.GetResult();
3600  }
3601  break;
3602 
3603  case 'f':
3604  if ( aReadParam.GoToTokenParam() )
3605  {
3606  const OUString sParams( aReadParam.GetResult() );
3607  if( sParams[0]!='C' && sParams[0]!='c' )
3608  eTox = TOX_USER;
3609  }
3610  break;
3611 
3612  case 'l':
3613  if ( aReadParam.GoToTokenParam() )
3614  {
3615  const OUString sParams( aReadParam.GetResult() );
3616  // if NO String just ignore the \l
3617  if( !sParams.isEmpty() && sParams[0]>'0' && sParams[0]<='9' )
3618  {
3619  nLevel = static_cast<sal_uInt16>(sParams.toInt32());
3620  }
3621  }
3622  break;
3623  }
3624  }
3625 
3626  OSL_ENSURE( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0 :-(" );
3627 
3628  const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
3629  SwTOXMark aM( pT );
3630 
3631  if( eTox != TOX_INDEX )
3632  aM.SetLevel( nLevel );
3633  else
3634  {
3635  sal_Int32 nFnd = sFieldText.indexOf( WW8_TOX_LEVEL_DELIM );
3636  if( -1 != nFnd ) // it exist levels
3637  {
3638  aM.SetPrimaryKey( sFieldText.copy( 0, nFnd ) );
3639  sal_Int32 nScndFnd = sFieldText.indexOf( WW8_TOX_LEVEL_DELIM, nFnd+1 );
3640  if( -1 != nScndFnd )
3641  {
3642  aM.SetSecondaryKey( sFieldText.copy( nFnd+1, nScndFnd - nFnd - 1 ));
3643  nFnd = nScndFnd;
3644  }
3645  sFieldText = sFieldText.copy( nFnd+1 );
3646  }
3647  }
3648 
3649  if (!sFieldText.isEmpty())
3650  {
3651  aM.SetAlternativeText( sFieldText );
3652  rDoc.getIDocumentContentOperations().InsertPoolItem( rPaM, aM );
3653  }
3654 }
3655 
3656 void SwWW8ImplReader::ImportTox( int nFieldId, const OUString& aStr )
3657 {
3658  bool bIdx = (nFieldId != 9);
3659  lcl_ImportTox(m_rDoc, *m_pPaM, aStr, bIdx);
3660 }
3661 
3662 void SwWW8ImplReader::Read_FieldVanish( sal_uInt16, const sal_uInt8*, short nLen )
3663 {
3664  //Meaningless in a style
3665  if (m_pCurrentColl || !m_xPlcxMan)
3666  return;
3667 
3668  const int nChunk = 64; //number of characters to read at one time
3669 
3670  // Careful: MEMICMP doesn't work with fieldnames including umlauts!
3671  const static char *aFieldNames[] = { "\x06""INHALT", "\x02""XE", // dt.
3672  "\x02""TC" }; // us
3673  const static sal_uInt8 aFieldId[] = { 9, 4, 9 };
3674 
3675  if( nLen < 0 )
3676  {
3677  m_bIgnoreText = false;
3678  return;
3679  }
3680 
3681  // our method was called from
3682  // ''Skip attributes of field contents'' loop within ReadTextAttr()
3683  if( m_bIgnoreText )
3684  return;
3685 
3686  m_bIgnoreText = true;
3687  tools::Long nOldPos = m_pStrm->Tell();
3688 
3689  WW8_CP nStartCp = m_xPlcxMan->Where() + m_xPlcxMan->GetCpOfs();
3690 
3691  OUString sFieldName;
3692  sal_Int32 nFieldLen = m_xSBase->WW8ReadString( *m_pStrm, sFieldName, nStartCp,
3693  nChunk, m_eStructCharSet );
3694  nStartCp+=nFieldLen;
3695 
3696  sal_Int32 nC = 0;
3697  //If the first chunk did not start with a field start then
3698  //reset the stream position and give up
3699  if( !nFieldLen || sFieldName[nC]!=0x13 ) // Field Start Mark
3700  {
3701  // If Field End Mark found
3702  if( nFieldLen && sFieldName[nC]==0x15 )
3703  m_bIgnoreText = false;
3704  m_pStrm->Seek( nOldPos );
3705  return; // no field found
3706  }
3707 
3708  sal_Int32 nFnd;
3709  //If this chunk does not contain a field end, keep reading chunks
3710  //until we find one, or we run out of text,
3711  for (;;)
3712  {
3713  nFnd = sFieldName.indexOf(0x15);
3714  //found field end, we can stop now
3715  if (nFnd != -1)
3716  break;
3717  OUString sTemp;
3718  nFieldLen = m_xSBase->WW8ReadString( *m_pStrm, sTemp,
3719  nStartCp, nChunk, m_eStructCharSet );
3720  sFieldName+=sTemp;
3721  nStartCp+=nFieldLen;
3722  if (!nFieldLen)
3723  break;
3724  }
3725 
3726  m_pStrm->Seek( nOldPos );
3727 
3728  //if we have no 0x15 give up, otherwise erase everything from the 0x15
3729  //onwards
3730  if (nFnd<0)
3731  return;
3732 
3733  sFieldName = sFieldName.copy(0, nFnd);
3734 
3735  nC++;
3736  while ( sFieldName[nC]==' ' )
3737  nC++;
3738 
3739  for( int i = 0; i < 3; i++ )
3740  {
3741  const char* pName = aFieldNames[i];
3742  const sal_Int32 nNameLen = static_cast<sal_Int32>(*pName++);
3743  if( sFieldName.matchIgnoreAsciiCaseAsciiL( pName, nNameLen, nC ) )
3744  {
3745  ImportTox( aFieldId[i], sFieldName.copy( nC + nNameLen ) );
3746  break; // no duplicates allowed
3747  }
3748  }
3749  m_bIgnoreText = true;
3750  m_pStrm->Seek( nOldPos );
3751 }
3752 
3753 /* 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:2009
virtual void SetSubType(sal_uInt16 nType) override
Definition: expfld.cxx:887
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:83
std::vector< SwFormToken > SwFormTokens
Vector of tokens.
Definition: tox.hxx:288
TOXTypes
Definition: toxe.hxx:39
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(93)
Iterator for Booknotes.
Definition: ww8scan.hxx:749
std::unique_ptr< SwWW8FltControlStack > m_xCtrlStck
Definition: ww8par.hxx:1104
SVX_NUM_CHARS_UPPER_LETTER_N
bool bCodeNest
instruction used recursively
Definition: ww8scan.hxx:198
URL aURL
OUString msFileLinkSeed
Definition: ww8par.hxx:958
sal_uLong GetIndex() const
Definition: node.hxx:291
SwNode & GetNode(bool bPoint=true) const
Definition: pam.hxx:223
SwTOIOptions
Definition: tox.hxx:389
sal_Int32 nIndex
Handles the import of PlcfAtnBkf and PlcfAtnBkl: start / end position of annotation marks...
Definition: ww8scan.hxx:788
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:1291
void Read_FieldVanish(sal_uInt16 nId, const sal_uInt8 *pData, short nLen)
Definition: ww8par5.cxx:3662
bool m_bLoadingTOXCache
Definition: ww8par.hxx:1368
SwTOXElement GetCreateType() const
Definition: tox.hxx:716
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:1205
const SwTOXBase & GetBase() const
Definition: fltshell.hxx:290
#define ODF_OLE_PARAM
"Page"
Definition: reffld.hxx:48
eF_ResT Read_F_Num(WW8FieldDesc *pF, OUString &)
Definition: ww8par5.cxx:1884
sal_uInt16 End_Field()
Definition: ww8par5.cxx:500
void SetLinkFileName(OUString const &rNew)
Definition: section.hxx:117
#define LANGUAGE_ENGLISH_US
SwCharFormat * MakeCharFormat(const OUString &rFormatName, SwCharFormat *pDerivedFrom, bool bBroadcast=false)
Definition: docfmt.cxx:843
WW8_CP nSCode
start of instructions code
Definition: ww8scan.hxx:192
virtual SwFlyFrameFormat * InsertGraphic(const SwPaM &rRg, const OUString &rGrfName, const OUString &rFltName, const Graphic *pGraphic, const SfxItemSet *pFlyAttrSet, const SfxItemSet *pGrfAttrSet, SwFrameFormat *)=0
Insert graphic or formula.
SvNumberFormatter * GetNumberFormatter(bool bCreate=true)
Definition: doc.hxx:1412
const SwExtendedSubType SUB_INVISIBLE
Invisible.
Definition: fldbas.hxx:212
sal_uLong MSDateTimeFormatToSwFormat(OUString &rParams, SvNumberFormatter *pFormatter, LanguageType &rLang, bool bHijri, LanguageType nDocLang)
Convert from Word Date/Time field str to Writer's Date Time str.
eINCLUDETEXT
void SetBookmarkType(const OUString &bookmarkType)
Definition: ww8par5.cxx:743
static void FillUIName(const OUString &rName, OUString &rFillName, SwGetPoolIdFromName)
void SetLevel(sal_uInt16 nLevel)
Definition: tox.hxx:607
sal_uInt32 GetFormatIndex(NfIndexTableOffset, LanguageType eLnge=LANGUAGE_DONTKNOW)
static SwTOXBase * GetCurTOX(const SwPosition &rPos)
Get current table of contents.
Definition: doctxm.cxx:447
Definition: tox.hxx:315
SwNodeIndex nNode
Definition: pam.hxx:37
bool EndPosIsFieldEnd(WW8_CP &)
Definition: ww8scan.cxx:4059
void SetPromptText(const OUString &rStr)
Definition: expfld.hxx:255
eF_ResT Read_F_InputVar(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1360
eF_ResT Read_F_Author(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1758
eMERGEINC
#define WW8_TOX_LEVEL_DELIM
Definition: ww8par5.cxx:87
SVX_NUM_NUMBER_NONE
ErrCode GetError() const
void SetAdjustment(css::text::RubyAdjust nNew)
Definition: fmtruby.hxx:74
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:276
sal_uIntPtr sal_uLong
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_LANGUAGE(10)
long Long
ePRINTDATE
FAMILY_DONTKNOW
css::uno::Any getPropertyValue(const OUString &rPropertyName)
constexpr TypedWhichId< SvxFontHeightItem > RES_CHRATR_FONTSIZE(8)
wwFrameNamer m_aGrfNameGenerator
Definition: ww8par.hxx:1184
const sal_Unicode cTokenSeparator
Base class of all fields.
Definition: fldbas.hxx:289
void MakeTagString(OUString &rStr, const OUString &rOrg)
Definition: ww8par5.cxx:1038
void SetHandle(tools::Long nHandle)
Definition: fltshell.cxx:1048
#define TOX_STYLE_DELIMITER
Definition: tox.hxx:425
sal_Int64 n
Provides access to the marks of a document.
Definition: doc.hxx:187
constexpr sal_uInt16 RES_FRMATR_END(133)
eBookStatus
Definition: ww8scan.hxx:746
OUString GetUniqueSectionName(const OUString *pChkStr=nullptr) const
Definition: ndsect.cxx:1382
SvNumFormatType GetType(sal_uInt32 nFIndex) const
constexpr TypedWhichId< SwFltRDFMark > RES_FLTR_RDFMARK(196)
static SotStorage * OpenOLEStorage(css::uno::Reference< css::embed::XStorage > const &xStorage, OUString const &rEleName, StreamMode=StreamMode::STD_READWRITE)
#define ODF_CODE_PARAM
sal_uInt64 Seek(sal_uInt64 nPos)
constexpr TypedWhichId< SvxFormatBreakItem > RES_BREAK(94)
void ConvertLanguage(SvNumberFormatter &rConverter, LanguageType eConvertFrom, LanguageType eConvertTo)
const SwDocInfoSubType DI_COMMENT
Definition: docufld.hxx:73
SwNode & GetNode() const
Definition: ndindex.hxx:119
std::unique_ptr< SwPaM > m_pPosAfterTOC
Definition: ww8par.hxx:1373
WW8_CP nLen
total length (to skip over text)
Definition: ww8scan.hxx:191
static void EnsureMaxLevelForTemplates(SwTOXBase &rBase)
Definition: ww8par5.cxx:2838
bool isAnyKnownWebDAVScheme() const
static OUString FindPara(const OUString &rStr, sal_Unicode cToken, sal_Unicode cToken2)
Definition: ww8par5.cxx:331
SwSectionFormat * GetFormat()
Definition: section.hxx:336
REFERENCEMARK
Definition: reffld.hxx:45
sal_uInt16 GetFormMax() const
Definition: tox.hxx:698
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1794
void SetLevel(sal_uInt8)
Definition: chpfld.cxx:81
eCONTROL
bool StartPosIsFieldStart()
Definition: ww8scan.cxx:4052
virtual sal_uInt16 GetSubType() const override
Definition: expfld.cxx:895
eF_ResT Read_F_Macro(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2275
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:315
constexpr TypedWhichId< SvxFontItem > RES_CHRATR_FONT(7)
const OUString & GetFormatstring() const
eF_ResT Read_F_Shape(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:3481
bool Commit()
static void ParseIfFieldDefinition(const OUString &aFieldDefinition, OUString &rCondition, OUString &rTrue, OUString &rFalse)
Definition: docufld.cxx:1532
eF_ResT Read_F_Seq(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1430
tools::Long GetLen() const
Definition: ww8scan.cxx:4404
#define MAX_FIELDLEN
Definition: ww8par5.cxx:85
SvxNumType
static LanguageType nLang
Definition: srtdlg.cxx:51
eAUTOTEXT
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
void SetCharFormatName(const OUString &rNm)
Definition: fmtruby.hxx:65
virtual OUString GetPar1() const
Definition: fldbas.cxx:314
IDocumentFieldsAccess const & getIDocumentFieldsAccess() const
Definition: doc.cxx:357
SwDoc & m_rDoc
Definition: docbm.cxx:1208
sal_uInt16 sal_Unicode
Stores RDF statements on a paragraph (key-value pairs where the subject is the paragraph).
Definition: fltshell.hxx:263
static SW_DLLPUBLIC OUString GetCrossRefHeadingBookmarkNamePrefix()
Definition: docbm.cxx:512
const SwCharFormat * GetDfltCharFormat() const
Definition: doc.hxx:752
SwTOXBaseSection * InsertTableOf(const SwPosition &rPos, const SwTOXBase &rTOX, const SfxItemSet *pSet=nullptr, bool bExpand=false, SwRootFrame const *pLayout=nullptr)
Definition: doctxm.cxx:343
int n2
SotStorage * OpenSotStorage(const OUString &rEleName, StreamMode=StreamMode::STD_READWRITE, bool transacted=true)
ePAGEREF
SwIndex nContent
Definition: pam.hxx:38
void RegisterToTOXType(SwTOXType &rMark)
Definition: tox.cxx:552
Handles the import of PlcfBkfFactoid and PlcfBklFactoid: start / end position of factoids.
Definition: ww8scan.hxx:818
std::unique_ptr< SwWW8ReferencedFltEndStack > m_xReffedStck
Definition: ww8par.hxx:1118
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
size_t pos
std::vector< SwWW8StyInf > m_vColl
Definition: ww8par.hxx:1241
SwSectionNode * GetSectionNode()
Definition: section.cxx:957
constexpr TypedWhichId< SvxLanguageItem > RES_CHRATR_CTL_LANGUAGE(29)
"Number (full context)"
Definition: reffld.hxx:60
tools::Long GetHandle() const
Definition: ww8scan.cxx:4440
void SetFieldCode(const OUString &rStr)
access to the command string
Definition: dbfld.hxx:102
OUString sText
Definition: tox.hxx:247
const OUString & GetName() const
Definition: format.hxx:115
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:33
eF_ResT Read_F_DBNum(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2610
SvStream * m_pStrm
Definition: ww8par.hxx:1095
SVX_NUM_ARABIC
const SwDocInfoSubType DI_SUBJECT
Definition: docufld.hxx:71
const sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:95
void SetInitDBFields(bool b)
Definition: docfld.cxx:384
static SW_DLLPUBLIC sal_uInt16 GetPoolIdFromUIName(const OUString &rName, SwGetPoolIdFromName)
bool CopyTo(SotStorage *pDestStg)
SVX_NUM_ROMAN_UPPER
virtual void SetValue(const double &rVal) override
Definition: expfld.cxx:900
constexpr TypedWhichId< SwFormatRuby > RES_TXTATR_CJK_RUBY(53)
sal_uInt16 GetTOXTypeCount(TOXTypes eTyp) const
Manage table of content types.
Definition: doctxm.cxx:610
SVX_NUM_ROMAN_LOWER
virtual parameter_map_t * GetParameters()=0
"Category and Number"
Definition: reffld.hxx:53
void SetAutomaticLanguage(bool const bSet)
Definition: fldbas.hxx:382
void SetBookmarkCode(const OUString &bookmarkCode)
Definition: ww8par5.cxx:748
eF_ResT Read_F_IncludeText(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2488
const SwDoc & mrDoc
Definition: ww8par.hxx:957
constexpr TypedWhichId< SfxStringItem > RES_FLTR_BOOKMARK(RES_FLTRATTR_BEGIN)
Iterator for fields.
Definition: ww8scan.hxx:724
eF_ResT
Definition: ww8par.hxx:629
void SetAlternativeText(const OUString &rAlt)
Definition: tox.hxx:593
bool m_bLoadingTOXHyperlink
Definition: ww8par.hxx:1371
void SetHadPageDescItem(bool bVal)
Definition: fltshell.hxx:292
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:2178
sal_uInt16 GetPoolFormatId() const
Get and set Pool style IDs.
Definition: format.hxx:147
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
void Swap(WW8FieldEntry &rOther)
Definition: ww8par5.cxx:724
tools::Long nCp2OrIdx
Definition: ww8scan.hxx:854
constexpr OUStringLiteral aData
Definition: ww8scan.hxx:47
Base class for various Writer styles.
Definition: format.hxx:46
#define SAL_N_ELEMENTS(arr)
const SwDocInfoSubType DI_CUSTOM
Definition: docufld.hxx:79
WW8_CP nLCode
length
Definition: ww8scan.hxx:193
DocumentType eType
void SetHadBreakItem(bool bVal)
Definition: fltshell.hxx:291
tools::Long MapBookmarkVariables(const WW8FieldDesc *pF, OUString &rOrigName, const OUString &rData)
Definition: ww8par5.cxx:1281
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:750
void Read_SubF_Ruby(msfilter::util::WW8ReadFieldParams &rReadParam)
Definition: ww8par5.cxx:2658
eF_ResT Read_F_FormCheckBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:185
eF_ResT Read_F_DBField(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2556
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:2356
bool Move(SwMoveFnCollection const &fnMove=fnMoveForward, SwGoInDoc fnGo=GoInContent)
Movement of cursor.
Definition: pam.cxx:504
const SwDocInfoSubType DI_PRINT
Definition: docufld.hxx:76
eF_ResT Read_F_TemplName(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:1768
bool CurrentSectionIsProtected() const
Definition: ww8par2.cxx:136
T * get() const
virtual bool InsertString(const SwPaM &rRg, const OUString &, const SwInsertFlags nInsertMode=SwInsertFlags::EMPTYEXPAND)=0
Insert string into existing text node at position rRg.Point().
sal_uInt16 char * pName
bool bResNest
instruction inserted into result
Definition: ww8scan.hxx:199
bool GetPara(tools::Long nIdx, WW8FieldDesc &rF)
Definition: ww8scan.cxx:4130
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
eF_ResT Read_F_Symbol(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1909
constexpr TypedWhichId< CntUInt16Item > RES_FLTR_ANNOTATIONMARK(195)
static SvtFilterOptions & Get()
void SetUniqueGraphName(SwFrameFormat *pFrameFormat, std::u16string_view rFixedPart)
Definition: ww8graf.cxx:162
eAUTOTEXTLIST
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
wwSectionManager m_aSectionManager
Definition: ww8par.hxx:1156
SwFileNameFormat
Definition: fldbas.hxx:152
int i
SwDoc & m_rDoc
Definition: ww8par.hxx:1100
NF_TIME_START
void SetPrimaryKey(const OUString &rStr)
Definition: tox.hxx:613
bool PutandConvertEntry(OUString &rString, sal_Int32 &nCheckPos, SvNumFormatType &nType, sal_uInt32 &nKey, LanguageType eLnge, LanguageType eNewLnge, bool bConvertDateOrder)
SwTOXElement
Definition: tox.hxx:367
const SwPosition * GetPoint() const
Definition: pam.hxx:207
std::unique_ptr< WW8ScannerBase > m_xSBase
Definition: ww8par.hxx:1229
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:1854
OUString sCharStyleName
Definition: tox.hxx:248
#define LANGUAGE_SYSTEM
const SwDocInfoSubType DI_KEYS
Definition: docufld.hxx:72
bool SwFltGetFlag(sal_uLong nFieldFlags, int no)
Definition: fltshell.hxx:42
void Exchange()
Definition: pam.cxx:492
SwContentNode * GetContentNode()
Definition: node.hxx:619
const SwDocInfoSubType DI_CREATE
Definition: docufld.hxx:74
void SetSequenceName(const OUString &rSet)
Definition: tox.hxx:550
FlyAnchors.
Definition: fmtanchr.hxx:34
rtl_TextEncoding m_eTextCharSet
Definition: ww8par.hxx:1290
void SetCaptionDisplay(SwCaptionDisplay eSet)
Definition: tox.hxx:553
void NewAttr(const SfxPoolItem &rAttr, const bool bFirstLineOfStSet=false, const bool bLeftIndentSet=false)
Definition: ww8par6.cxx:2769
void AppendTextNode(SwPosition &rPos)
Definition: ww8par.cxx:2430
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
bool ForceFieldLanguage(SwField &rField, LanguageType nLang)
Definition: ww8par5.cxx:386
constexpr TypedWhichId< SwFltTOX > RES_FLTR_TOX(193)
float u
WW8_CP GetStartPos() const
Definition: ww8scan.hxx:775
sal_uInt16 GetWhichOfScript(sal_uInt16 nWhich, sal_uInt16 nScript)
Definition: hints.cxx:190
new reference format types for referencing bookmarks and set references
Definition: reffld.hxx:58
eF_ResT Read_F_Embedd(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:1982
eF_ResT Read_F_Ref(WW8FieldDesc *pF, OUString &)
Definition: ww8par5.cxx:2045
static sal_Int32 FindParaStart(const OUString &rStr, sal_Unicode cToken, sal_Unicode cToken2)
Definition: ww8par5.cxx:302
IDocumentState const & getIDocumentState() const
Definition: doc.cxx:394
eF_ResT Read_F_FormTextBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:92
PITCH_DONTKNOW
void ImportTox(int nFieldId, const OUString &aStr)
Definition: ww8par5.cxx:3656
SvNumFormatType
const sal_uInt8 * pSprm
Definition: ww8scan.hxx:94
eF_ResT Read_F_Tox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:2963
const SwDocInfoSubType DI_SUB_DATE
Definition: docufld.hxx:84
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
FontPitch
sal_uInt16 GetLevel() const
Definition: tox.hxx:749
eF_ResT Read_F_FormListBox(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par3.cxx:244
void InitContent()
Evaluation for header and footer.
Definition: dbfld.cxx:176
SVX_NUM_CHARS_LOWER_LETTER_N
tools::Long Read_FactoidBook(WW8PLCFManResult *)
Definition: ww8par5.cxx:245
std::deque< bool > m_aApos
Definition: ww8par.hxx:1211
const OUString * GetName() const
Definition: ww8scan.cxx:4528
tools::Long Read_AtnBook(WW8PLCFManResult *)
Definition: ww8par5.cxx:233
WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd, SwPaM &rPaM)
Definition: ww8par5.cxx:2369
sal_Int32 WW8_CP
Definition: ww8struc.hxx:153
eBookStatus GetStatus() const
Definition: ww8scan.cxx:4432
int m_nEmbeddedTOXLevel
Definition: ww8par.hxx:1369
eFORMTEXT
WW8_CP nLRes
length ( == 0, if no result )
Definition: ww8scan.hxx:195
bool IsControlChar(sal_Unicode cChar)
const SwDocInfoSubType DI_SUB_AUTHOR
Definition: docufld.hxx:82
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:62
std::vector< const SwCharFormat * > m_aRubyCharFormats
Definition: ww8par.hxx:1216
bool m_bCareFirstParaEndInToc
Definition: ww8par.hxx:1379
OUString ConvertFFileName(const OUString &rRaw)
translate FieldParameter names into the system character set and at the same time, double backslashes are converted into single ones
Definition: ww8par5.cxx:266
NF_DATE_START
FontFamily
tools::Long Read_Field(WW8PLCFManResult *pRes)
Definition: ww8par5.cxx:757
const OUString & GetFamilyName() const
#define ODF_UNHANDLED
std::unique_ptr< SfxPoolItem > pAttr
Definition: fltshell.hxx:90
OUString GetFieldResult(WW8FieldDesc const *pF)
Definition: ww8par5.cxx:1191
eCREATEDATE
SVX_NUM_PAGEDESC
"Reference"
Definition: reffld.hxx:50
const SwGetSetExpType GSE_SEQ
Sequence.
Definition: fldbas.hxx:204
OUString UniqueName()
Definition: ww8par5.cxx:2481
sal_uInt32 GetHeight() const
static OUString GetWordDefaultDateStringAsUS(SvNumberFormatter *pFormatter, LanguageType nLang)
Definition: ww8par5.cxx:405
OUString BookmarkToWriter(const OUString &rBookmark)
Definition: wrtw8nds.cxx:1217
SwFieldIds Which() const
ResId.
Definition: fldbas.cxx:243
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)
sal_uInt8 nOpt
WW-Flags ( e.g.: changed by user )
Definition: ww8scan.hxx:197
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
virtual void SetLanguage(LanguageType nLng)
Definition: fldbas.cxx:421
static bool ConvertMacroSymbol(std::u16string_view rName, OUString &rReference)
Definition: ww8par5.cxx:2251
eF_ResT Read_F_DBNext(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2597
unsigned char sal_uInt8
sal_uInt16 nId
WW-id for fields.
Definition: ww8scan.hxx:196
const SwDocInfoSubType DI_DOCNO
Definition: docufld.hxx:77
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:254
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:527
bool GetIsEnd() const
Definition: ww8scan.hxx:778
eSAVEDATE
static SvxNumType GetNumberPara(const OUString &rStr, bool bAllowPageDesc=false)
Definition: ww8par5.cxx:379
sal_uInt16 CurrentSectionColCount() const
Definition: ww8par5.cxx:2926
bool CanUseRemoteLink(const OUString &rGrfName)
Definition: ww8par5.cxx:2379
#define SAL_INFO(area, stream)
OUString aName
static void lcl_toxMatchACSwitch(SwDoc const &rDoc, SwTOXBase &rBase, WW8ReadFieldParams &rParam, SwCaptionDisplay eCaptionType)
Definition: ww8par5.cxx:2821
sal_Int32 GetIndex() const
Definition: index.hxx:91
void SetStyleNames(const OUString &rSet, sal_uInt16 nLevel)
Definition: tox.hxx:532
eF_ResT Read_F_OCX(WW8FieldDesc *, OUString &)
Definition: ww8par3.cxx:84
#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:95
void SetInputFlag(bool bInp)
Definition: expfld.hxx:261
const SwPosition * End() const
Definition: pam.hxx:217
bool m_bIgnoreText
Definition: ww8par.hxx:1320
constexpr sal_uInt16 RES_PARATR_END(82)
WW8_CP nSRes
start of result
Definition: ww8scan.hxx:194
"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
static void lcl_ImportTox(SwDoc &rDoc, SwPaM const &rPaM, const OUString &rStr, bool bIdx)
Definition: ww8par5.cxx:3580
auto FilterControlChars(OUString const &rString) -> OUString
Definition: ww8par.cxx:3437
eF_ResT Read_F_Styleref(WW8FieldDesc *, OUString &rStr)
Reads a STYLEREF field.
Definition: ww8par5.cxx:1506
void SetSecondaryKey(const OUString &rStr)
Definition: tox.hxx:619
eHYPERLINK
SwMoveFnCollection const & fnMoveBackward
Definition: paminit.cxx:58
eF_ResT Read_F_Hyperlink(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:3491
WW8FieldEntry(SwPosition const &rPos, sal_uInt16 nFieldId)
Definition: ww8par5.cxx:714
static sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
Definition: ww8par5.cxx:2950
std::shared_ptr< WW8PLCFMan > m_xPlcxMan
Definition: ww8par.hxx:1230
static void lcl_ConvertSequenceName(OUString &rSequenceName)
Definition: ww8par5.cxx:293
bool WillHavePageDescHere(const SwNodeIndex &rIdx) const
Definition: ww8par5.cxx:2936
virtual void SetUpdateExpFieldStat(bool b)=0
OUString GetMappedBookmark(const OUString &rOrigName)
Definition: ww8par5.cxx:1344
int mnFileSectionNo
Definition: ww8par.hxx:959
const SwGetSetExpType GSE_STRING
String.
Definition: fldbas.hxx:202
wwSectionNamer m_aSectionNameGenerator
Definition: ww8par.hxx:1174
virtual SwFieldType * GetSysFieldType(const SwFieldIds eWhich) const =0
if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
static void lcl_toxMatchTSwitch(SwWW8ImplReader const &rReader, SwTOXBase &rBase, WW8ReadFieldParams &rParam)
Definition: ww8par5.cxx:2859
const SwFormat * GetStyleWithOrgWWName(std::u16string_view rName) const
Definition: ww8par2.cxx:3571
const SwDocInfoSubType DI_CHANGE
Definition: docufld.hxx:75
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:478
bool m_bWasParaEnd
Definition: ww8par.hxx:1342
const SwTOXType * GetTOXType(TOXTypes eTyp, sal_uInt16 nId) const
Definition: doctxm.cxx:619
sw::hack::Position maStartPos
Definition: ww8par.hxx:573
void SetLevel(sal_uInt16)
Definition: tox.hxx:743
const char *const aFieldNames[]
Definition: authfld.cxx:649
SwFormat * m_pCurrentColl
Definition: ww8par.hxx:1237
void Init(sal_uInt16 nNumCols, sal_uInt16 nGutterWidth, sal_uInt16 nAct)
This function allows to (repeatedly) initialize the columns.
Definition: atrfrm.cxx:962
const SwDocInfoSubType DI_TITLE
Definition: docufld.hxx:70
SwSection * InsertSwSection(SwPaM const &rRange, SwSectionData &, std::tuple< SwTOXBase const *, sw::RedlineMode, sw::FieldmarkMode > const *pTOXBase, SfxItemSet const *const pAttr, bool const bUpdate=true)
Definition: ndsect.cxx:152
SwCaptionDisplay
Definition: tox.hxx:405
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:1898
eF_ResT Read_F_IncludePicture(WW8FieldDesc *, OUString &rStr)
Definition: ww8par5.cxx:2421
CharClass & GetAppCharClass()
Definition: init.cxx:712
std::deque< wwSection > maSegments
Definition: ww8par.hxx:835
eF_ResT Read_F_NoteReference(WW8FieldDesc *pF, OUString &rStr)
Definition: ww8par5.cxx:2128
constexpr sal_uInt16 RES_FRMATR_BEGIN(RES_PARATR_LIST_END)
aStr
FormTokenType
Definition: tox.hxx:230
SwPaM * m_pPaM
Definition: ww8par.hxx:1102
void SetINetFormatAndId(const OUString &rNm, const sal_uInt16 nId)
Definition: fmtinfmt.hxx:94
tools::Long Read_Book(WW8PLCFManResult *)
Definition: ww8par5.cxx:117
void SetCharFormatId(sal_uInt16 nNew)
Definition: fmtruby.hxx:68
#define ODF_ID_PARAM
virtual SwFormatField * Clone(SfxItemPool *pPool=nullptr) const override
Definition: atrfld.cxx:211
const SwAttrPool & GetAttrPool() const
Definition: doc.hxx:1320
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:845
bool GetTokenSttFromTo(sal_Int32 *_pFrom, sal_Int32 *_pTo, sal_Int32 _nMax)
eF_ResT Read_F_Equation(WW8FieldDesc *, OUString &)
Definition: ww8par5.cxx:2631
constexpr OUStringLiteral aObjectPool
Definition: ww8scan.hxx:44
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:317
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo