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