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