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