LibreOffice Module sw (master)  1
tox.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 <calbck.hxx>
21 #include <doc.hxx>
22 #include <docary.hxx>
23 #include <editeng/tstpitem.hxx>
24 #include <hintids.hxx>
25 #include <hints.hxx>
26 #include <ndtxt.hxx>
27 #include <paratr.hxx>
28 #include <rootfrm.hxx>
29 #include <scriptinfo.hxx>
30 #include <strings.hrc>
31 #include <swtypes.hxx>
32 #include <tox.hxx>
33 #include <txtfrm.hxx>
34 #include <txttxmrk.hxx>
35 
36 #include <optional>
37 #include <sal/log.hxx>
38 #include <o3tl/string_view.hxx>
39 #include <osl/diagnose.h>
40 
41 #include <algorithm>
42 #include <string_view>
43 
44 
45 const sal_Unicode C_NUM_REPL = '@';
47 
48 namespace
49 {
50 void lcl_FillAuthPattern(SwFormTokens &rAuthTokens, sal_uInt16 nTypeId)
51 {
52  rAuthTokens.reserve(9); // Worst case: Start+Sep1+Auth+3*(Sep2+Auth)
53 
54  SwFormToken aStartToken( TOKEN_AUTHORITY );
56  rAuthTokens.push_back( aStartToken );
57  SwFormToken aSeparatorToken( TOKEN_TEXT );
58  aSeparatorToken.sText = ": ";
59  rAuthTokens.push_back( aSeparatorToken );
60 
61  --nTypeId; // compensate +1 offset introduced by caller
62 
63  SwFormToken aTextToken( TOKEN_TEXT );
64  aTextToken.sText = ", ";
65 
66  const ToxAuthorityField nVals[4] = {
71  };
72 
73  for(size_t i = 0; i < SAL_N_ELEMENTS(nVals); ++i)
74  {
75  if(nVals[i] == AUTH_FIELD_END)
76  break;
77  if( i > 0 )
78  rAuthTokens.push_back( aTextToken );
79 
80  // -> #i21237#
82 
83  aToken.nAuthorityField = nVals[i];
84  rAuthTokens.push_back(aToken);
85  // <- #i21237#
86  }
87 }
88 }
89 
93  , m_pType(nullptr)
94  , m_pTextAttr(nullptr)
95  , m_nLevel(0)
96  , m_bAutoGenerated(false)
97  , m_bMainEntry(false)
98 {
99 }
100 
103  , m_pType(pType)
104  , m_pTextAttr(nullptr)
105  , m_nLevel(0)
106  , m_bAutoGenerated(false)
107  , m_bMainEntry(false)
108 {
109  StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
110 }
111 
114  , SvtListener()
115  , m_pType(rCopy.m_pType)
116  , m_aPrimaryKey(rCopy.m_aPrimaryKey)
117  , m_aSecondaryKey(rCopy.m_aSecondaryKey)
118  , m_aTextReading(rCopy.m_aTextReading)
119  , m_aPrimaryKeyReading(rCopy.m_aPrimaryKeyReading)
120  , m_aSecondaryKeyReading(rCopy.m_aSecondaryKeyReading)
121  , m_pTextAttr(nullptr)
122  , m_nLevel(rCopy.m_nLevel)
123  , m_bAutoGenerated(rCopy.m_bAutoGenerated)
124  , m_bMainEntry(rCopy.m_bMainEntry)
125 {
126  if(m_pType)
127  StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
128  // Copy AlternativString
129  m_aAltText = rCopy.m_aAltText;
130 }
131 
133 {
134 }
135 
137 {
139  m_pType = &rType;
140  StartListening(rType.GetNotifier());
141 }
142 
143 bool SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
144 {
145  assert(SfxPoolItem::operator==(rAttr));
146  return m_pType == static_cast<const SwTOXMark&>(rAttr).m_pType;
147 }
148 
150 {
151  return new SwTOXMark( *this );
152 }
153 
154 void SwTOXMark::Notify(const SfxHint& rHint)
155 {
156  if (rHint.GetId() == SfxHintId::SwLegacyModify)
157  {
158  auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
159  CallSwClientNotify(rHint);
160  if (pLegacyHint->m_pOld && (RES_REMOVE_UNO_OBJECT == pLegacyHint->m_pOld->Which()))
161  SetXTOXMark(css::uno::Reference<css::text::XDocumentIndexMark>(nullptr));
162  } else if (auto pCollectHint = dynamic_cast<const sw::CollectTextMarksHint*>(&rHint))
163  {
164  if(GetTextTOXMark())
165  pCollectHint->m_rMarks.push_back(this);
166  } else if (auto pCollectLayoutHint = dynamic_cast<const sw::CollectTextTOXMarksForLayoutHint*>(&rHint))
167  {
168  if(!GetTextTOXMark())
169  return;
170  auto& rTextMark = *GetTextTOXMark();
171  auto& rNode = rTextMark.GetTextNode();
172  auto pLayout = pCollectLayoutHint->m_pLayout;
173  // Check basic sanity and that it is part of our layout and not in undo
174  if(!rNode.GetNodes().IsDocNodes() || !rNode.GetText().getLength() || !rNode.HasWriterListeners() || !rNode.getLayoutFrame(pLayout))
175  return;
176  // Check for being hidden
177  if(rNode.IsHiddenByParaField() || SwScriptInfo::IsInHiddenRange(rNode, rTextMark.GetStart()))
178  return;
179  // Check for being hidden by hidden redlines
180  if (pLayout && pLayout->HasMergedParas() && sw::IsMarkHintHidden(*pLayout, rNode, rTextMark))
181  return;
182  pCollectLayoutHint->m_rMarks.push_back(rTextMark);
183  }
184 }
185 
187 {
188  const SwPtrMsgPoolItem aMsgHint(RES_REMOVE_UNO_OBJECT, &static_cast<sw::BroadcastingModify&>(*this));
189  CallSwClientNotify(sw::LegacyModifyHint(&aMsgHint, &aMsgHint));
190 }
191 
192 OUString SwTOXMark::GetText(SwRootFrame const*const pLayout) const
193 {
194  if( !m_aAltText.isEmpty() )
195  return m_aAltText;
196 
198  {
199  const sal_Int32* pEndIdx = m_pTextAttr->GetEnd();
200  OSL_ENSURE( pEndIdx, "TOXMark without mark!");
201  if( pEndIdx )
202  {
203  const sal_Int32 nStt = m_pTextAttr->GetStart();
204  return m_pTextAttr->GetpTextNd()->GetExpandText(pLayout, nStt, *pEndIdx-nStt);
205  }
206  }
207 
208  return OUString();
209 }
210 
211 // Manage types of TOX
212 SwTOXType::SwTOXType(SwDoc& rDoc, TOXTypes eTyp, const OUString& rName)
213  : m_rDoc(rDoc)
214  , m_aName(rName)
215  , m_eType(eTyp)
216 {
217 }
218 
220  : m_rDoc(rCopy.m_rDoc)
221  , m_aName(rCopy.m_aName)
222  , m_eType(rCopy.m_eType)
223 {
224  if (auto pRegisteredIn = const_cast<SwTOXType&>(rCopy).GetRegisteredIn())
225  pRegisteredIn->Add(this);
226 }
227 
229 {
230  // Subcategory Index-Directories
231  STR_POOLCOLL_TOX_IDXH,
232  STR_POOLCOLL_TOX_IDX1,
233  STR_POOLCOLL_TOX_IDX2,
234  STR_POOLCOLL_TOX_IDX3,
235  STR_POOLCOLL_TOX_IDXBREAK
236 };
237 
239 {
240  // Subcategory Tables of Contents
241  STR_POOLCOLL_TOX_CNTNTH,
242  STR_POOLCOLL_TOX_CNTNT1,
243  STR_POOLCOLL_TOX_CNTNT2,
244  STR_POOLCOLL_TOX_CNTNT3,
245  STR_POOLCOLL_TOX_CNTNT4,
246  STR_POOLCOLL_TOX_CNTNT5
247 };
248 
250 {
251  // Subcategory Table of Contents more Levels 5 - 10
252  STR_POOLCOLL_TOX_CNTNT6,
253  STR_POOLCOLL_TOX_CNTNT7,
254  STR_POOLCOLL_TOX_CNTNT8,
255  STR_POOLCOLL_TOX_CNTNT9,
256  STR_POOLCOLL_TOX_CNTNT10
257 };
258 
260 {
261  // Subcategory User-Directories:
262  STR_POOLCOLL_TOX_USERH,
263  STR_POOLCOLL_TOX_USER1,
264  STR_POOLCOLL_TOX_USER2,
265  STR_POOLCOLL_TOX_USER3,
266  STR_POOLCOLL_TOX_USER4,
267  STR_POOLCOLL_TOX_USER5
268 };
269 
271 {
272  // Subcategory User-Directories more Levels 5 - 10
273  STR_POOLCOLL_TOX_USER6,
274  STR_POOLCOLL_TOX_USER7,
275  STR_POOLCOLL_TOX_USER8,
276  STR_POOLCOLL_TOX_USER9,
277  STR_POOLCOLL_TOX_USER10
278 };
279 
281 {
282  // Illustrations Index
283  STR_POOLCOLL_TOX_ILLUSH,
284  STR_POOLCOLL_TOX_ILLUS1
285 };
286 
288 {
289  // Object Index
290  STR_POOLCOLL_TOX_OBJECTH,
291  STR_POOLCOLL_TOX_OBJECT1
292 };
293 
295 {
296  // Tables Index
297  STR_POOLCOLL_TOX_TABLESH,
298  STR_POOLCOLL_TOX_TABLES1
299 };
300 
302 {
303  // Index of Authorities
304  STR_POOLCOLL_TOX_AUTHORITIESH,
305  STR_POOLCOLL_TOX_AUTHORITIES1
306 };
307 
309 {
310  STR_POOLCOLL_TOX_CITATION
311 };
312 
313 // Edit forms
314 SwForm::SwForm( TOXTypes eTyp ) // #i21237#
315  : m_eType( eTyp ), m_nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
316 // nFirstTabPos( lNumberIndent ),
317  m_bCommaSeparated(false)
318 {
319  //bHasFirstTabPos =
320  m_bIsRelTabPos = true;
321 
322  // The table of contents has a certain number of headlines + headings
323  // The user has 10 levels + headings
324  // Keyword has 3 levels + headings+ separator
325  // Indexes of tables, object illustrations and authorities consist of a heading and one level
326 
327  const TranslateId* pPoolId;
328  switch( m_eType )
329  {
330  case TOX_INDEX: pPoolId = STR_POOLCOLL_TOX_ARY; break;
331  case TOX_USER: pPoolId = STR_POOLCOLL_TOX_USER_ARY; break;
332  case TOX_CONTENT: pPoolId = STR_POOLCOLL_TOX_CNTNT_ARY; break;
333  case TOX_ILLUSTRATIONS: pPoolId = STR_POOLCOLL_TOX_ILLUS_ARY; break;
334  case TOX_OBJECTS : pPoolId = STR_POOLCOLL_TOX_OBJECT_ARY; break;
335  case TOX_TABLES : pPoolId = STR_POOLCOLL_TOX_TABLES_ARY; break;
336  case TOX_AUTHORITIES : pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY; break;
337  case TOX_CITATION : pPoolId = STR_POOLCOLL_TOX_CITATION_ARY; break;
338  default:
339  OSL_ENSURE( false, "invalid TOXTyp");
340  return ;
341  }
342 
343  SwFormTokens aTokens;
345  {
346  SwFormToken aLinkStt (TOKEN_LINK_START);
347  aLinkStt.sCharStyleName = SwResId(STR_POOLCHR_TOXJUMP);
348  aTokens.push_back(aLinkStt);
349  }
350 
351  if (TOX_CONTENT == m_eType)
352  {
353  aTokens.emplace_back(TOKEN_ENTRY_NO);
354  aTokens.emplace_back(TOKEN_ENTRY_TEXT);
355  }
356  else
357  aTokens.emplace_back(TOKEN_ENTRY);
358 
359  if (TOX_AUTHORITIES != m_eType)
360  {
361  SwFormToken aToken(TOKEN_TAB_STOP);
362  aToken.nTabStopPosition = 0;
363 
364  // #i36870# right aligned tab for all
365  aToken.cTabFillChar = '.';
366  aToken.eTabAlign = SvxTabAdjust::End;
367 
368  aTokens.push_back(aToken);
369  aTokens.emplace_back(TOKEN_PAGE_NUMS);
370  }
371 
373  aTokens.emplace_back(TOKEN_LINK_END);
374 
375  SetTemplate(0, SwResId(*pPoolId++));
376 
377  if(TOX_INDEX == m_eType)
378  {
379  for( sal_uInt16 i = 1; i < 5; ++i )
380  {
381  if(1 == i)
382  {
383  SwFormTokens aTmpTokens;
384  SwFormToken aTmpToken(TOKEN_ENTRY);
385  aTmpTokens.push_back(aTmpToken);
386 
387  SetPattern( i, std::move(aTmpTokens) );
388  SetTemplate(i, SwResId(STR_POOLCOLL_TOX_IDXBREAK));
389  }
390  else
391  {
392  SetPattern( i, std::vector(aTokens) );
393  SetTemplate(i, SwResId(STR_POOLCOLL_TOX_ARY[i - 1]));
394  }
395  }
396  }
397  else
398  {
399  for (sal_uInt16 i = 1; i < GetFormMax(); ++i, ++pPoolId) // Number 0 is the title
400  {
401  if (TOX_AUTHORITIES == m_eType)
402  {
403  SwFormTokens aAuthTokens;
404  lcl_FillAuthPattern(aAuthTokens, i);
405  SetPattern(i, std::move(aAuthTokens));
406  }
407  else
408  SetPattern( i, std::vector(aTokens) );
409 
410  if( TOX_CONTENT == m_eType && 6 == i )
412  else if( TOX_USER == m_eType && 6 == i )
414  else if( TOX_AUTHORITIES == m_eType ) //reuse the same STR_POOLCOLL_TOX_AUTHORITIES1 id each time
415  pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY + 1;
416  SetTemplate(i, SwResId(*pPoolId));
417  }
418  }
419 }
420 
421 SwForm::SwForm(const SwForm& rForm)
422  : m_eType( rForm.m_eType )
423 {
424  *this = rForm;
425 }
426 
428 {
429  m_eType = rForm.m_eType;
431 // nFirstTabPos = rForm.nFirstTabPos;
432 // bHasFirstTabPos = rForm.bHasFirstTabPos;
435  for(sal_uInt16 i=0; i < m_nFormMaxLevel; ++i)
436  {
437  m_aPattern[i] = rForm.m_aPattern[i];
438  m_aTemplate[i] = rForm.m_aTemplate[i];
439  }
440  return *this;
441 }
442 
443 sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
444 {
445  switch( eTOXType )
446  {
447  case TOX_INDEX:
448  return 5;
449  case TOX_USER:
450  case TOX_CONTENT:
451  return MAXLEVEL + 1;
452  case TOX_ILLUSTRATIONS:
453  case TOX_OBJECTS:
454  case TOX_TABLES:
455  return 2;
456  case TOX_BIBLIOGRAPHY:
457  case TOX_CITATION:
458  case TOX_AUTHORITIES:
459  return AUTH_TYPE_END + 1;
460  }
461  return 0;
462 }
463 
464 void SwForm::AdjustTabStops( SwDoc const & rDoc ) // #i21237#
465 {
466  const sal_uInt16 nFormMax = GetFormMax();
467  for ( sal_uInt16 nLevel = 1; nLevel < nFormMax; ++nLevel )
468  {
469  SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( GetTemplate(nLevel) );
470  if( pColl == nullptr )
471  {
472  // Paragraph Style for this level has not been created.
473  // --> No need to propagate default values
474  continue;
475  }
476 
477  const SvxTabStopItem& rTabStops = pColl->GetTabStops(false);
478  const sal_uInt16 nTabCount = rTabStops.Count();
479  if (nTabCount != 0)
480  {
481  SwFormTokens aCurrentPattern = GetPattern(nLevel);
482  SwFormTokens::iterator aIt = aCurrentPattern.begin();
483 
484  bool bChanged = false;
485  for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
486  {
487  const SvxTabStop& rTab = rTabStops[nTab];
488 
489  if ( rTab.GetAdjustment() == SvxTabAdjust::Default )
490  continue; // ignore the default tab stop
491 
492  aIt = find_if( aIt, aCurrentPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_TAB_STOP) );
493  if ( aIt != aCurrentPattern.end() )
494  {
495  bChanged = true;
496  aIt->nTabStopPosition = rTab.GetTabPos();
497  aIt->eTabAlign =
498  ( nTab == nTabCount - 1
499  && rTab.GetAdjustment() == SvxTabAdjust::Right )
500  ? SvxTabAdjust::End
501  : rTab.GetAdjustment();
502  aIt->cTabFillChar = rTab.GetFill();
503  ++aIt;
504  }
505  else
506  break; // no more tokens to replace
507  }
508 
509  if ( bChanged )
510  SetPattern( nLevel, std::move(aCurrentPattern) );
511  }
512  }
513 }
514 
515 OUString SwForm::GetFormEntry() {return "<E>";}
516 OUString SwForm::GetFormTab() {return "<T>";}
517 OUString SwForm::GetFormPageNums() {return "<#>";}
518 OUString SwForm::GetFormLinkStt() {return "<LS>";}
519 OUString SwForm::GetFormLinkEnd() {return "<LE>";}
520 OUString SwForm::GetFormEntryNum() {return "<E#>";}
521 OUString SwForm::GetFormEntryText() {return "<ET>";}
522 OUString SwForm::GetFormChapterMark() {return "<C>";}
523 OUString SwForm::GetFormText() {return "<X>";}
524 OUString SwForm::GetFormAuth() {return "<A>";}
525 
526 SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
527  SwTOXElement nCreaType, const OUString& rTitle )
528  : SwClient(const_cast<sw::BroadcastingModify*>(static_cast<sw::BroadcastingModify const *>(pTyp)))
529  , m_aForm(rForm)
530  , m_aTitle(rTitle)
531  , m_eLanguage(::GetAppLanguage())
532  , m_nCreateType(nCreaType)
533  , m_nOLEOptions(SwTOOElements::NONE)
534  , m_eCaptionDisplay(CAPTION_COMPLETE)
535  , m_bProtected( true )
536  , m_bFromChapter(false)
537  , m_bFromObjectNames(false)
538  , m_bLevelFromChapter(false)
539  , maMSTOCExpression()
540  , mbKeepExpression(true)
541 {
542  m_aData.nOptions = SwTOIOptions::NONE;
543 }
544 
545 SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
546  : SwClient( rSource.GetRegisteredInNonConst() )
547  , mbKeepExpression(true)
548 {
549  CopyTOXBase( pDoc, rSource );
550 }
551 
553 {
554  rType.Add( this );
555 }
556 
557 void SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
558 {
560  SwTOXType* pType = const_cast<SwTOXType*>(rSource.GetTOXType());
561  if( pDoc &&
562  std::find_if(pDoc->GetTOXTypes().begin(), pDoc->GetTOXTypes().end(),
563  [=](const std::unique_ptr<SwTOXType> & p) { return p.get() == pType; })
564  == pDoc->GetTOXTypes().end())
565  {
566  // type not in pDoc, so create it now
567  const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
568  bool bFound = false;
569  for( size_t n = rTypes.size(); n; )
570  {
571  const SwTOXType* pCmp = rTypes[ --n ].get();
572  if( pCmp->GetType() == pType->GetType() &&
573  pCmp->GetTypeName() == pType->GetTypeName() )
574  {
575  pType = const_cast<SwTOXType*>(pCmp);
576  bFound = true;
577  break;
578  }
579  }
580 
581  if( !bFound )
582  pType = const_cast<SwTOXType*>(pDoc->InsertTOXType( *pType ));
583  }
584  pType->Add( this );
585 
586  m_nCreateType = rSource.m_nCreateType;
587  m_aTitle = rSource.m_aTitle;
588  m_aForm = rSource.m_aForm;
590  m_bProtected = rSource.m_bProtected;
591  m_bFromChapter = rSource.m_bFromChapter;
596  m_nOLEOptions = rSource.m_nOLEOptions;
597  m_eLanguage = rSource.m_eLanguage;
600 
601  for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
602  m_aStyleNames[i] = rSource.m_aStyleNames[i];
603 
604  // it's the same data type!
605  m_aData.nOptions = rSource.m_aData.nOptions;
606 
607  if( !pDoc || pDoc->IsCopyIsMove() )
608  m_aName = rSource.GetTOXName();
609  else
610  m_aName = pDoc->GetUniqueTOXBaseName( *pType, rSource.GetTOXName() );
611 }
612 
613 // TOX specific functions
615 {
616 // if( GetTOXType()->GetType() == TOX_USER )
617 // delete aData.pTemplateName;
618 }
619 
620 void SwTOXBase::SetTitle(const OUString& rTitle)
621  { m_aTitle = rTitle; }
622 
623 void SwTOXBase::SetBookmarkName(const OUString& bName)
624 {
625  m_aBookmarkName = bName;
626 }
627 
629 {
630  m_aForm = rSource.m_aForm;
631  m_aName = rSource.m_aName;
632  m_aTitle = rSource.m_aTitle;
635  for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
638  m_eLanguage = rSource.m_eLanguage;
640  m_aData = rSource.m_aData;
641  m_nCreateType = rSource.m_nCreateType;
642  m_nOLEOptions = rSource.m_nOLEOptions;
644  m_bProtected = rSource.m_bProtected;
645  m_bFromChapter = rSource.m_bFromChapter;
648 
649  if (rSource.GetAttrSet())
650  SetAttrSet(*rSource.GetAttrSet());
651 
652  return *this;
653 }
654 
655 OUString SwFormToken::GetString() const
656 {
657  OUString sToken;
658 
659  switch( eTokenType )
660  {
661  case TOKEN_ENTRY_NO:
662  sToken = SwForm::GetFormEntryNum();
663  break;
664  case TOKEN_ENTRY_TEXT:
665  sToken = SwForm::GetFormEntryText();
666  break;
667  case TOKEN_ENTRY:
668  sToken = SwForm::GetFormEntry();
669  break;
670  case TOKEN_TAB_STOP:
671  sToken = SwForm::GetFormTab();
672  break;
673  case TOKEN_TEXT:
674  // Return a Token only if Text is not empty!
675  if( sText.isEmpty() )
676  {
677  return OUString();
678  }
679  sToken = SwForm::GetFormText();
680  break;
681  case TOKEN_PAGE_NUMS:
682  sToken = SwForm::GetFormPageNums();
683  break;
684  case TOKEN_CHAPTER_INFO:
685  sToken = SwForm::GetFormChapterMark();
686  break;
687  case TOKEN_LINK_START:
688  sToken = SwForm::GetFormLinkStt();
689  break;
690  case TOKEN_LINK_END:
691  sToken = SwForm::GetFormLinkEnd();
692  break;
693  case TOKEN_AUTHORITY:
694  {
695  sToken = SwForm::GetFormAuth();
696  }
697  break;
698  case TOKEN_END:
699  break;
700  }
701 
702  OUString sData = " " + sCharStyleName + "," + OUString::number( nPoolId ) + ",";
703 
704  // TabStopPosition and TabAlign or ChapterInfoFormat
705  switch (eTokenType)
706  {
707  case TOKEN_TAB_STOP:
708  sData += OUString::number( nTabStopPosition ) + ","
709  + OUString::number( static_cast< sal_Int32 >(eTabAlign) ) + ","
710  + OUStringChar(cTabFillChar) + ","
711  + OUString::number( bWithTab ? 1 : 0 );
712  break;
713  case TOKEN_CHAPTER_INFO:
714  case TOKEN_ENTRY_NO:
715  // add also maximum permitted level
716  sData += OUString::number( nChapterFormat ) + ","
717  + OUString::number( nOutlineLevel );
718  break;
719  case TOKEN_TEXT:
720  sData += OUStringChar(TOX_STYLE_DELIMITER)
721  + sText.replaceAll(OUStringChar(TOX_STYLE_DELIMITER), "")
722  + OUStringChar(TOX_STYLE_DELIMITER);
723  break;
724  case TOKEN_AUTHORITY:
725  if (nAuthorityField<10)
726  {
727  sData = "0" + OUString::number( nAuthorityField ) + sData;
728  }
729  else
730  {
731  sData = OUString::number( nAuthorityField ) + sData;
732  }
733  break;
734  default:
735  break;
736  }
737 
738  return sToken.subView(0, sToken.getLength()-1) + sData + sToken.subView(sToken.getLength()-1);
739 }
740 
741 // -> #i21237#
742 
751 static FormTokenType lcl_GetTokenType(std::u16string_view sToken,
752  sal_Int32 & rTokenLen)
753 {
754  static struct
755  {
756  OUString sTokenStart;
757  sal_Int16 nTokenLength;
758  FormTokenType eTokenType;
759  } const aTokenArr[] = {
760  { SwForm::GetFormTab().copy(0, 2), 3, TOKEN_TAB_STOP },
761  { SwForm::GetFormPageNums().copy(0, 2), 3, TOKEN_PAGE_NUMS },
762  { SwForm::GetFormLinkStt().copy(0, 3), 4, TOKEN_LINK_START },
763  { SwForm::GetFormLinkEnd().copy(0, 3), 4, TOKEN_LINK_END },
764  { SwForm::GetFormEntryNum().copy(0, 3), 4, TOKEN_ENTRY_NO },
765  { SwForm::GetFormEntryText().copy(0, 3), 4, TOKEN_ENTRY_TEXT },
766  { SwForm::GetFormChapterMark().copy(0, 2), 3, TOKEN_CHAPTER_INFO },
767  { SwForm::GetFormText().copy(0, 2), 3, TOKEN_TEXT },
768  { SwForm::GetFormEntry().copy(0, 2), 3, TOKEN_ENTRY },
769  { SwForm::GetFormAuth().copy(0, 2), 5, TOKEN_AUTHORITY }
770  };
771 
772  for(const auto & i : aTokenArr)
773  {
774  if( o3tl::starts_with( sToken, i.sTokenStart ) )
775  {
776  rTokenLen = i.nTokenLength;
777  return i.eTokenType;
778  }
779  }
780 
781  SAL_WARN("sw.core", "SwFormTokensHelper: invalid token");
782  return TOKEN_END;
783 }
784 
793 static OUString
794 lcl_SearchNextToken(const OUString & sPattern, sal_Int32 const nStt)
795 {
796  sal_Int32 nEnd = sPattern.indexOf( '>', nStt );
797  if (nEnd >= 0)
798  {
799  // apparently the TOX_STYLE_DELIMITER act as a bracketing for
800  // TOKEN_TEXT tokens so that the user can have '>' inside the text...
801  const sal_Int32 nTextSeparatorFirst = sPattern.indexOf( TOX_STYLE_DELIMITER, nStt );
802  if ( nTextSeparatorFirst >= 0
803  && nTextSeparatorFirst + 1 < sPattern.getLength()
804  && nTextSeparatorFirst < nEnd)
805  {
806  const sal_Int32 nTextSeparatorSecond = sPattern.indexOf( TOX_STYLE_DELIMITER,
807  nTextSeparatorFirst + 1 );
808  // Since nEnd>=0 we don't need to check if nTextSeparatorSecond<0!
809  if( nEnd < nTextSeparatorSecond )
810  nEnd = sPattern.indexOf( '>', nTextSeparatorSecond );
811  // FIXME: No check to verify that nEnd is still >=0?
812  assert(nEnd >= 0);
813  }
814 
815  ++nEnd;
816 
817  return sPattern.copy( nStt, nEnd - nStt );
818  }
819 
820  return OUString();
821 }
822 
831 static std::optional<SwFormToken>
832 lcl_BuildToken(const OUString & sPattern, sal_Int32 & nCurPatternPos)
833 {
834  OUString sToken( lcl_SearchNextToken(sPattern, nCurPatternPos) );
835  nCurPatternPos += sToken.getLength();
836  sal_Int32 nTokenLen = 0;
837  FormTokenType const eTokenType = lcl_GetTokenType(sToken, nTokenLen);
838  if (TOKEN_END == eTokenType) // invalid input? skip it
839  {
840  nCurPatternPos = sPattern.getLength();
841  return std::optional<SwFormToken>();
842  }
843 
844  // at this point sPattern contains the
845  // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
846  // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
847  // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
848  SwFormToken eRet( eTokenType );
849  const OUString sAuthFieldEnum = sToken.copy( 2, 2 );
850  sToken = sToken.copy( nTokenLen, sToken.getLength() - nTokenLen - 1);
851 
852  sal_Int32 nIdx{ 0 };
853  eRet.sCharStyleName = sToken.getToken( 0, ',', nIdx );
854  OUString sTmp( sToken.getToken( 0, ',', nIdx ));
855  if( !sTmp.isEmpty() )
856  eRet.nPoolId = o3tl::narrowing<sal_uInt16>(sTmp.toInt32());
857 
858  switch( eTokenType )
859  {
860 //i53420
861  case TOKEN_CHAPTER_INFO:
862 //i53420
863  case TOKEN_ENTRY_NO:
864  sTmp = sToken.getToken( 0, ',', nIdx ); // token 2
865  if( !sTmp.isEmpty() )
866  eRet.nChapterFormat = o3tl::narrowing<sal_uInt16>(sTmp.toInt32());
867  sTmp = sToken.getToken( 0, ',', nIdx ); // token 3
868  if( !sTmp.isEmpty() )
869  eRet.nOutlineLevel = o3tl::narrowing<sal_uInt16>(sTmp.toInt32()); //the maximum outline level to examine
870  break;
871 
872  case TOKEN_TEXT:
873  {
874  const sal_Int32 nStartText = sToken.indexOf( TOX_STYLE_DELIMITER );
875  if( nStartText>=0 && nStartText+1<sToken.getLength())
876  {
877  const sal_Int32 nEndText = sToken.indexOf( TOX_STYLE_DELIMITER,
878  nStartText + 1);
879  if( nEndText>=0 )
880  {
881  eRet.sText = sToken.copy( nStartText + 1,
882  nEndText - nStartText - 1);
883  }
884  }
885  }
886  break;
887 
888  case TOKEN_TAB_STOP:
889  sTmp = sToken.getToken( 0, ',', nIdx ); // token 2
890  if( !sTmp.isEmpty() )
891  eRet.nTabStopPosition = sTmp.toInt32();
892 
893  sTmp = sToken.getToken( 0, ',', nIdx ); // token 3
894  if( !sTmp.isEmpty() )
895  eRet.eTabAlign = static_cast<SvxTabAdjust>(sTmp.toInt32());
896 
897  sTmp = sToken.getToken( 0, ',', nIdx ); // token 4
898  if( !sTmp.isEmpty() )
899  eRet.cTabFillChar = sTmp[0];
900 
901  sTmp = sToken.getToken( 0, ',', nIdx ); // token 5
902  if( !sTmp.isEmpty() )
903  eRet.bWithTab = 0 != sTmp.toInt32();
904  break;
905 
906  case TOKEN_AUTHORITY:
907  eRet.nAuthorityField = o3tl::narrowing<sal_uInt16>(sAuthFieldEnum.toInt32());
908  break;
909  default: break;
910  }
911  return eRet;
912 }
913 
914 SwFormTokensHelper::SwFormTokensHelper(const OUString & rPattern)
915 {
916  sal_Int32 nCurPatternPos = 0;
917 
918  while (nCurPatternPos < rPattern.getLength())
919  {
920  std::optional<SwFormToken> const oToken(
921  lcl_BuildToken(rPattern, nCurPatternPos));
922  if (oToken)
923  m_Tokens.push_back(*oToken);
924  }
925 }
926 
927 // <- #i21237#
928 
929 void SwForm::SetPattern(sal_uInt16 nLevel, SwFormTokens&& rTokens)
930 {
931  OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
932  m_aPattern[nLevel] = std::move(rTokens);
933 }
934 
935 void SwForm::SetPattern(sal_uInt16 nLevel, const OUString & rStr)
936 {
937  OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
938 
940  m_aPattern[nLevel] = aHelper.GetTokens();
941 }
942 
943 const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
944 {
945  OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
946  return m_aPattern[nLevel];
947 }
948 
949 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const TranslateId STR_POOLCOLL_TOX_USER_EXTRA_ARY[]
Definition: tox.cxx:270
const SwFormTokens & GetTokens() const
Returns vector of tokens.
Definition: tox.hxx:310
std::vector< SwFormToken > SwFormTokens
Vector of tokens.
Definition: tox.hxx:286
SwCaptionDisplay m_eCaptionDisplay
Definition: tox.hxx:447
OUString m_aStyleNames[MAXLEVEL]
Definition: tox.hxx:434
const sal_Unicode C_NUM_REPL
Definition: tox.cxx:45
const SfxItemSet * GetAttrSet() const
Definition: doctxm.cxx:2037
TOXTypes
Definition: toxe.hxx:39
bool IsMarkHintHidden(SwRootFrame const &rLayout, SwTextNode const &rNode, SwTextAttrEnd const &rHint)
Definition: reffld.cxx:1113
void SetAttrSet(const SfxItemSet &)
Definition: doctxm.cxx:2045
void Add(SwClient *pDepend)
Definition: calbck.cxx:173
const SvxTabStopItem & GetTabStops(bool=true) const
Definition: paratr.hxx:228
const TranslateId STR_POOLCOLL_TOX_USER_ARY[]
Definition: tox.cxx:259
SwTOXMark()
pool default constructor
Definition: tox.cxx:91
Represents the style of a paragraph.
Definition: fmtcol.hxx:56
sal_uInt16 Count() const
OUString m_sSequenceName
Definition: tox.hxx:435
static OUString lcl_SearchNextToken(const OUString &sPattern, sal_Int32 const nStt)
Returns the string of a token.
Definition: tox.cxx:794
SwTextTOXMark * m_pTextAttr
Definition: tox.hxx:98
OUString m_aName
SwTOXType(SwDoc &rDoc, TOXTypes eTyp, const OUString &rName)
Definition: tox.cxx:212
sal_uInt16 nOutlineLevel
Definition: tox.hxx:252
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(181)
SwTOOElements
Definition: tox.hxx:409
Definition: tox.hxx:313
OUString m_aTitle
Definition: tox.hxx:429
const SwTOXType * InsertTOXType(const SwTOXType &rTyp)
Definition: doctxm.cxx:628
const TranslateId STR_POOLCOLL_TOX_CNTNT_ARY[]
Definition: tox.cxx:238
SwTextFormatColl * FindTextFormatCollByName(const OUString &rName) const
Definition: doc.hxx:799
OUString m_aBookmarkName
Definition: tox.hxx:430
SAL_DLLPRIVATE void SetXTOXMark(css::uno::Reference< css::text::XDocumentIndexMark > const &xMark)
Definition: tox.hxx:165
static OUString GetFormLinkStt()
Definition: tox.cxx:518
OUString const & GetTemplate(sal_uInt16 nLevel) const
Definition: tox.hxx:672
void SetTitle(const OUString &rTitle)
Definition: tox.cxx:620
#define TOX_STYLE_DELIMITER
Definition: tox.hxx:422
sal_Int64 n
Definition: doc.hxx:188
SwForm(TOXTypes eTOXType=TOX_CONTENT)
Definition: tox.cxx:314
constexpr sal_uInt8 MAXLEVEL
Definition: swtypes.hxx:93
union SwTOXBase::@30 m_aData
sal_uInt16 m_nFormMaxLevel
Definition: tox.hxx:319
sal_uInt16 GetFormMax() const
Definition: tox.hxx:683
Dialog to specify the properties of date form field.
static OUString GetFormTab()
Definition: tox.cxx:516
SwFormTokens m_Tokens
the tokens
Definition: tox.hxx:295
sal_uInt16 nLevel
Definition: tox.hxx:441
static std::optional< SwFormToken > lcl_BuildToken(const OUString &sPattern, sal_Int32 &nCurPatternPos)
Builds a token from its string representation.
Definition: tox.cxx:832
bool m_bFromChapter
Definition: tox.hxx:449
sal_uInt16 nPoolId
Definition: tox.hxx:249
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
bool bWithTab
Definition: tox.hxx:255
virtual ~SwTOXMark() override
Definition: tox.cxx:132
SfxHintId GetId() const
void InvalidateTOXMark()
Definition: tox.cxx:186
bool m_bLevelFromChapter
Definition: tox.hxx:452
sal_Unicode cTabFillChar
Definition: tox.hxx:254
constexpr bool starts_with(std::basic_string_view< charT, traits > sv, std::basic_string_view< charT, traits > x) noexcept
SwTOIOptions nOptions
Definition: tox.hxx:442
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:165
SwDoc & m_rDoc
Definition: docbm.cxx:1204
const TranslateId STR_POOLCOLL_TOX_ARY[]
Definition: tox.cxx:228
sal_uInt16 sal_Unicode
const SwTOXType * GetTOXType() const
Definition: tox.hxx:698
SwTOXElement m_nCreateType
Definition: tox.hxx:445
void RegisterToTOXType(SwTOXType &rMark)
Definition: tox.cxx:552
void SetTemplate(sal_uInt16 nLevel, const OUString &rName)
Definition: tox.hxx:666
OUString sText
Definition: tox.hxx:245
sal_Int32 & GetTabPos()
sal_Int32 GetStart() const
Definition: txatbase.hxx:86
static OUString GetFormEntry()
Definition: tox.cxx:515
bool m_bProtected
Definition: tox.hxx:448
LanguageType m_eLanguage
Definition: tox.hxx:437
void SetPattern(sal_uInt16 nLevel, SwFormTokens &&rName)
Definition: tox.cxx:929
OUString maMSTOCExpression
Definition: tox.hxx:457
SvxTabAdjust & GetAdjustment()
static FormTokenType lcl_GetTokenType(std::u16string_view sToken, sal_Int32 &rTokenLen)
Returns the type of a token.
Definition: tox.cxx:751
static OUString GetFormEntryNum()
Definition: tox.cxx:520
#define SAL_N_ELEMENTS(arr)
virtual const sal_Int32 * GetEnd() const override
end position
Definition: atrtox.cxx:49
sal_Int32 m_nLevel
void EndListeningAll()
OUString GetString() const
Definition: tox.cxx:655
const TranslateId STR_POOLCOLL_TOX_AUTHORITIES_ARY[]
Definition: tox.cxx:301
int i
SwTOXElement
Definition: tox.hxx:365
virtual void Notify(const SfxHint &rHint) override
Definition: tox.cxx:154
FormTokenType eTokenType
Definition: tox.hxx:248
const SwFormTokens & GetPattern(sal_uInt16 nLevel) const
Definition: tox.cxx:943
OUString sCharStyleName
Definition: tox.hxx:246
bool m_bIsRelTabPos
Definition: tox.hxx:321
void SetBookmarkName(const OUString &bName)
Definition: tox.cxx:623
Any aHelper
void RegisterToTOXType(SwTOXType &rMark)
Definition: tox.cxx:136
OUString GetText(SwRootFrame const *pLayout) const
Definition: tox.cxx:192
SwTOXBase(const SwTOXType *pTyp, const SwForm &rForm, SwTOXElement nCreaType, const OUString &rTitle)
Definition: tox.cxx:526
const OUString & GetTypeName() const
Definition: tox.hxx:690
const SwTextNode * GetpTextNd() const
Definition: txttxmrk.hxx:44
static OUString GetFormChapterMark()
Definition: tox.cxx:522
SwTOOElements m_nOLEOptions
Definition: tox.hxx:446
SwForm & operator=(const SwForm &rForm)
Definition: tox.cxx:427
sal_uInt16 nChapterFormat
Definition: tox.hxx:251
sal_uInt16 nAuthorityField
Definition: tox.hxx:253
bool StartListening(SvtBroadcaster &rBroadcaster)
static sal_uInt16 GetFormMaxLevel(TOXTypes eType)
Definition: tox.cxx:443
virtual ~SwTOXBase() override
Definition: tox.cxx:614
SwForm m_aForm
Definition: tox.hxx:427
const TranslateId STR_POOLCOLL_TOX_CITATION_ARY[]
Definition: tox.cxx:308
OUString m_sSortAlgorithm
Definition: tox.hxx:438
const sal_Unicode C_END_PAGE_NUM
Definition: tox.cxx:46
void CopyTOXBase(SwDoc *, const SwTOXBase &)
Definition: tox.cxx:557
const SwTOXTypes & GetTOXTypes() const
Definition: doc.hxx:979
const TranslateId STR_POOLCOLL_TOX_OBJECT_ARY[]
Definition: tox.cxx:287
ToxAuthorityField
Definition: toxe.hxx:82
SwTOXBase & operator=(const SwTOXBase &rSource)
Definition: tox.cxx:628
OUString m_aAltText
Definition: tox.hxx:89
SvtBroadcaster & GetNotifier()
Definition: calbck.hxx:102
bool m_bFromObjectNames
Definition: tox.hxx:450
OUString GetExpandText(SwRootFrame const *pLayout, const sal_Int32 nIdx=0, const sal_Int32 nLen=-1, const bool bWithNum=false, const bool bAddSpaceAfterListLabelStr=false, const bool bWithSpacesForLevel=false, const ExpandMode eAdditionalMode=ExpandMode::ExpandFootnote) const
add 4th optional parameter indicating, when that a spa...
Definition: ndtxt.cxx:3336
SwTwips nTabStopPosition
Definition: tox.hxx:247
OUString GetUniqueTOXBaseName(const SwTOXType &rType, const OUString &sChkStr) const
Definition: doctxm.cxx:635
sal_Unicode & GetFill()
bool IsCopyIsMove() const
Definition: doc.hxx:1372
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
LanguageType GetAppLanguage()
Definition: init.cxx:723
TOXTypes m_eType
Definition: tox.hxx:318
const SwTOXType * m_pType
Definition: tox.hxx:88
const SwModify * GetRegisteredIn() const
Definition: calbck.hxx:165
OUString m_sMainEntryCharStyle
Definition: tox.hxx:432
OUString m_aTemplate[AUTH_TYPE_END+1]
Definition: tox.hxx:316
static OUString GetFormLinkEnd()
Definition: tox.cxx:519
void * p
static OUString GetFormText()
Definition: tox.cxx:523
static OUString GetFormEntryText()
Definition: tox.cxx:521
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
virtual bool operator==(const SfxPoolItem &) const override
Definition: tox.cxx:143
TOXTypes GetType() const
Definition: tox.hxx:693
virtual void CallSwClientNotify(const SfxHint &rHint) const override
Definition: calbck.cxx:326
static bool IsInHiddenRange(const SwTextNode &rNode, sal_Int32 nPos)
Definition: porlay.cxx:1991
SvxTabAdjust eTabAlign
Definition: tox.hxx:250
const TranslateId STR_POOLCOLL_TOX_ILLUS_ARY[]
Definition: tox.cxx:280
#define SAL_WARN(area, stream)
const TranslateId STR_POOLCOLL_TOX_CNTNT_EXTRA_ARY[]
Definition: tox.cxx:249
const SwTextTOXMark * GetTextTOXMark() const
Definition: tox.hxx:160
const EnumerationType m_eType
SwFormTokens m_aPattern[AUTH_TYPE_END+1]
Definition: tox.hxx:315
Helper class that converts vectors of tokens to strings and vice versa.
Definition: tox.hxx:292
static OUString GetFormAuth()
Definition: tox.cxx:524
virtual SwTOXMark * Clone(SfxItemPool *pPool=nullptr) const override
Definition: tox.cxx:149
void AdjustTabStops(SwDoc const &rDoc)
Definition: tox.cxx:464
FormTokenType
Definition: tox.hxx:228
bool m_bCommaSeparated
Definition: tox.hxx:322
const OUString & GetTOXName() const
Definition: tox.hxx:481
const TranslateId STR_POOLCOLL_TOX_TABLES_ARY[]
Definition: tox.cxx:294
SwFormTokensHelper(const OUString &rStr)
constructor
Definition: tox.cxx:914
OUString m_aName
Definition: tox.hxx:428
static OUString GetFormPageNums()
Definition: tox.cxx:517