summaryrefslogtreecommitdiffstats
path: root/sw/source/core/tox/tox.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/tox/tox.cxx')
-rw-r--r--sw/source/core/tox/tox.cxx949
1 files changed, 949 insertions, 0 deletions
diff --git a/sw/source/core/tox/tox.cxx b/sw/source/core/tox/tox.cxx
new file mode 100644
index 000000000..53fc36d38
--- /dev/null
+++ b/sw/source/core/tox/tox.cxx
@@ -0,0 +1,949 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <calbck.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <editeng/tstpitem.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <ndtxt.hxx>
+#include <paratr.hxx>
+#include <rootfrm.hxx>
+#include <scriptinfo.hxx>
+#include <strings.hrc>
+#include <swtypes.hxx>
+#include <tox.hxx>
+#include <txtfrm.hxx>
+#include <txttxmrk.hxx>
+
+#include <optional>
+#include <sal/log.hxx>
+#include <o3tl/string_view.hxx>
+#include <osl/diagnose.h>
+
+#include <algorithm>
+#include <string_view>
+
+
+const sal_Unicode C_NUM_REPL = '@';
+const sal_Unicode C_END_PAGE_NUM = '~';
+
+namespace
+{
+void lcl_FillAuthPattern(SwFormTokens &rAuthTokens, sal_uInt16 nTypeId)
+{
+ rAuthTokens.reserve(9); // Worst case: Start+Sep1+Auth+3*(Sep2+Auth)
+
+ SwFormToken aStartToken( TOKEN_AUTHORITY );
+ aStartToken.nAuthorityField = AUTH_FIELD_IDENTIFIER;
+ rAuthTokens.push_back( aStartToken );
+ SwFormToken aSeparatorToken( TOKEN_TEXT );
+ aSeparatorToken.sText = ": ";
+ rAuthTokens.push_back( aSeparatorToken );
+
+ --nTypeId; // compensate +1 offset introduced by caller
+
+ SwFormToken aTextToken( TOKEN_TEXT );
+ aTextToken.sText = ", ";
+
+ const ToxAuthorityField nVals[4] = {
+ AUTH_FIELD_AUTHOR,
+ AUTH_FIELD_TITLE,
+ AUTH_FIELD_YEAR,
+ nTypeId == AUTH_TYPE_WWW ? AUTH_FIELD_URL : AUTH_FIELD_END
+ };
+
+ for(size_t i = 0; i < SAL_N_ELEMENTS(nVals); ++i)
+ {
+ if(nVals[i] == AUTH_FIELD_END)
+ break;
+ if( i > 0 )
+ rAuthTokens.push_back( aTextToken );
+
+ // -> #i21237#
+ SwFormToken aToken(TOKEN_AUTHORITY);
+
+ aToken.nAuthorityField = nVals[i];
+ rAuthTokens.push_back(aToken);
+ // <- #i21237#
+ }
+}
+}
+
+/// pool default constructor
+SwTOXMark::SwTOXMark()
+ : SfxPoolItem(RES_TXTATR_TOXMARK)
+ , m_pType(nullptr)
+ , m_pTextAttr(nullptr)
+ , m_nLevel(0)
+ , m_bAutoGenerated(false)
+ , m_bMainEntry(false)
+{
+}
+
+SwTOXMark::SwTOXMark(const SwTOXType* pType)
+ : SfxPoolItem(RES_TXTATR_TOXMARK)
+ , m_pType(pType)
+ , m_pTextAttr(nullptr)
+ , m_nLevel(0)
+ , m_bAutoGenerated(false)
+ , m_bMainEntry(false)
+{
+ StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
+}
+
+SwTOXMark::SwTOXMark(const SwTOXMark& rCopy)
+ : SfxPoolItem(RES_TXTATR_TOXMARK)
+ , SvtListener()
+ , m_pType(rCopy.m_pType)
+ , m_aPrimaryKey(rCopy.m_aPrimaryKey)
+ , m_aSecondaryKey(rCopy.m_aSecondaryKey)
+ , m_aTextReading(rCopy.m_aTextReading)
+ , m_aPrimaryKeyReading(rCopy.m_aPrimaryKeyReading)
+ , m_aSecondaryKeyReading(rCopy.m_aSecondaryKeyReading)
+ , m_pTextAttr(nullptr)
+ , m_nLevel(rCopy.m_nLevel)
+ , m_bAutoGenerated(rCopy.m_bAutoGenerated)
+ , m_bMainEntry(rCopy.m_bMainEntry)
+{
+ if(m_pType)
+ StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
+ // Copy AlternativString
+ m_aAltText = rCopy.m_aAltText;
+}
+
+SwTOXMark::~SwTOXMark()
+{
+}
+
+void SwTOXMark::RegisterToTOXType(SwTOXType& rType)
+{
+ SvtListener::EndListeningAll();
+ m_pType = &rType;
+ StartListening(rType.GetNotifier());
+}
+
+bool SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
+{
+ assert(SfxPoolItem::operator==(rAttr));
+ return m_pType == static_cast<const SwTOXMark&>(rAttr).m_pType;
+}
+
+SwTOXMark* SwTOXMark::Clone( SfxItemPool* ) const
+{
+ return new SwTOXMark( *this );
+}
+
+void SwTOXMark::Notify(const SfxHint& rHint)
+{
+ if (rHint.GetId() == SfxHintId::SwLegacyModify)
+ {
+ auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ CallSwClientNotify(rHint);
+ if (pLegacyHint->m_pOld && (RES_REMOVE_UNO_OBJECT == pLegacyHint->m_pOld->Which()))
+ SetXTOXMark(css::uno::Reference<css::text::XDocumentIndexMark>(nullptr));
+ } else if (auto pCollectHint = dynamic_cast<const sw::CollectTextMarksHint*>(&rHint))
+ {
+ if(GetTextTOXMark())
+ pCollectHint->m_rMarks.push_back(this);
+ } else if (auto pCollectLayoutHint = dynamic_cast<const sw::CollectTextTOXMarksForLayoutHint*>(&rHint))
+ {
+ if(!GetTextTOXMark())
+ return;
+ auto& rTextMark = *GetTextTOXMark();
+ auto& rNode = rTextMark.GetTextNode();
+ auto pLayout = pCollectLayoutHint->m_pLayout;
+ // Check basic sanity and that it is part of our layout and not in undo
+ if(!rNode.GetNodes().IsDocNodes() || !rNode.GetText().getLength() || !rNode.HasWriterListeners() || !rNode.getLayoutFrame(pLayout))
+ return;
+ // Check for being hidden
+ if(rNode.IsHiddenByParaField() || SwScriptInfo::IsInHiddenRange(rNode, rTextMark.GetStart()))
+ return;
+ // Check for being hidden by hidden redlines
+ if (pLayout && pLayout->HasMergedParas() && sw::IsMarkHintHidden(*pLayout, rNode, rTextMark))
+ return;
+ pCollectLayoutHint->m_rMarks.push_back(rTextMark);
+ }
+}
+
+void SwTOXMark::InvalidateTOXMark()
+{
+ const SwPtrMsgPoolItem aMsgHint(RES_REMOVE_UNO_OBJECT, &static_cast<sw::BroadcastingModify&>(*this));
+ CallSwClientNotify(sw::LegacyModifyHint(&aMsgHint, &aMsgHint));
+}
+
+OUString SwTOXMark::GetText(SwRootFrame const*const pLayout) const
+{
+ if( !m_aAltText.isEmpty() )
+ return m_aAltText;
+
+ if( m_pTextAttr && m_pTextAttr->GetpTextNd() )
+ {
+ const sal_Int32* pEndIdx = m_pTextAttr->GetEnd();
+ OSL_ENSURE( pEndIdx, "TOXMark without mark!");
+ if( pEndIdx )
+ {
+ const sal_Int32 nStt = m_pTextAttr->GetStart();
+ return m_pTextAttr->GetpTextNd()->GetExpandText(pLayout, nStt, *pEndIdx-nStt);
+ }
+ }
+
+ return OUString();
+}
+
+// Manage types of TOX
+SwTOXType::SwTOXType(SwDoc& rDoc, TOXTypes eTyp, const OUString& rName)
+ : m_rDoc(rDoc)
+ , m_aName(rName)
+ , m_eType(eTyp)
+{
+}
+
+SwTOXType::SwTOXType(const SwTOXType& rCopy)
+ : m_rDoc(rCopy.m_rDoc)
+ , m_aName(rCopy.m_aName)
+ , m_eType(rCopy.m_eType)
+{
+ if (auto pRegisteredIn = const_cast<SwTOXType&>(rCopy).GetRegisteredIn())
+ pRegisteredIn->Add(this);
+}
+
+const TranslateId STR_POOLCOLL_TOX_ARY[] =
+{
+ // Subcategory Index-Directories
+ STR_POOLCOLL_TOX_IDXH,
+ STR_POOLCOLL_TOX_IDX1,
+ STR_POOLCOLL_TOX_IDX2,
+ STR_POOLCOLL_TOX_IDX3,
+ STR_POOLCOLL_TOX_IDXBREAK
+};
+
+const TranslateId STR_POOLCOLL_TOX_CNTNT_ARY[] =
+{
+ // Subcategory Tables of Contents
+ STR_POOLCOLL_TOX_CNTNTH,
+ STR_POOLCOLL_TOX_CNTNT1,
+ STR_POOLCOLL_TOX_CNTNT2,
+ STR_POOLCOLL_TOX_CNTNT3,
+ STR_POOLCOLL_TOX_CNTNT4,
+ STR_POOLCOLL_TOX_CNTNT5
+};
+
+const TranslateId STR_POOLCOLL_TOX_CNTNT_EXTRA_ARY[] =
+{
+ // Subcategory Table of Contents more Levels 5 - 10
+ STR_POOLCOLL_TOX_CNTNT6,
+ STR_POOLCOLL_TOX_CNTNT7,
+ STR_POOLCOLL_TOX_CNTNT8,
+ STR_POOLCOLL_TOX_CNTNT9,
+ STR_POOLCOLL_TOX_CNTNT10
+};
+
+const TranslateId STR_POOLCOLL_TOX_USER_ARY[] =
+{
+ // Subcategory User-Directories:
+ STR_POOLCOLL_TOX_USERH,
+ STR_POOLCOLL_TOX_USER1,
+ STR_POOLCOLL_TOX_USER2,
+ STR_POOLCOLL_TOX_USER3,
+ STR_POOLCOLL_TOX_USER4,
+ STR_POOLCOLL_TOX_USER5
+};
+
+const TranslateId STR_POOLCOLL_TOX_USER_EXTRA_ARY[] =
+{
+ // Subcategory User-Directories more Levels 5 - 10
+ STR_POOLCOLL_TOX_USER6,
+ STR_POOLCOLL_TOX_USER7,
+ STR_POOLCOLL_TOX_USER8,
+ STR_POOLCOLL_TOX_USER9,
+ STR_POOLCOLL_TOX_USER10
+};
+
+const TranslateId STR_POOLCOLL_TOX_ILLUS_ARY[] =
+{
+ // Illustrations Index
+ STR_POOLCOLL_TOX_ILLUSH,
+ STR_POOLCOLL_TOX_ILLUS1
+};
+
+const TranslateId STR_POOLCOLL_TOX_OBJECT_ARY[] =
+{
+ // Object Index
+ STR_POOLCOLL_TOX_OBJECTH,
+ STR_POOLCOLL_TOX_OBJECT1
+};
+
+const TranslateId STR_POOLCOLL_TOX_TABLES_ARY[] =
+{
+ // Tables Index
+ STR_POOLCOLL_TOX_TABLESH,
+ STR_POOLCOLL_TOX_TABLES1
+};
+
+const TranslateId STR_POOLCOLL_TOX_AUTHORITIES_ARY[] =
+{
+ // Index of Authorities
+ STR_POOLCOLL_TOX_AUTHORITIESH,
+ STR_POOLCOLL_TOX_AUTHORITIES1
+};
+
+const TranslateId STR_POOLCOLL_TOX_CITATION_ARY[] =
+{
+ STR_POOLCOLL_TOX_CITATION
+};
+
+// Edit forms
+SwForm::SwForm( TOXTypes eTyp ) // #i21237#
+ : m_eType( eTyp ), m_nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
+// nFirstTabPos( lNumberIndent ),
+ m_bCommaSeparated(false)
+{
+ //bHasFirstTabPos =
+ m_bIsRelTabPos = true;
+
+ // The table of contents has a certain number of headlines + headings
+ // The user has 10 levels + headings
+ // Keyword has 3 levels + headings+ separator
+ // Indexes of tables, object illustrations and authorities consist of a heading and one level
+
+ const TranslateId* pPoolId;
+ switch( m_eType )
+ {
+ case TOX_INDEX: pPoolId = STR_POOLCOLL_TOX_ARY; break;
+ case TOX_USER: pPoolId = STR_POOLCOLL_TOX_USER_ARY; break;
+ case TOX_CONTENT: pPoolId = STR_POOLCOLL_TOX_CNTNT_ARY; break;
+ case TOX_ILLUSTRATIONS: pPoolId = STR_POOLCOLL_TOX_ILLUS_ARY; break;
+ case TOX_OBJECTS : pPoolId = STR_POOLCOLL_TOX_OBJECT_ARY; break;
+ case TOX_TABLES : pPoolId = STR_POOLCOLL_TOX_TABLES_ARY; break;
+ case TOX_AUTHORITIES : pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY; break;
+ case TOX_CITATION : pPoolId = STR_POOLCOLL_TOX_CITATION_ARY; break;
+ default:
+ OSL_ENSURE( false, "invalid TOXTyp");
+ return ;
+ }
+
+ SwFormTokens aTokens;
+ if (TOX_CONTENT == m_eType || TOX_ILLUSTRATIONS == m_eType )
+ {
+ SwFormToken aLinkStt (TOKEN_LINK_START);
+ aLinkStt.sCharStyleName = SwResId(STR_POOLCHR_TOXJUMP);
+ aTokens.push_back(aLinkStt);
+ }
+
+ if (TOX_CONTENT == m_eType)
+ {
+ aTokens.emplace_back(TOKEN_ENTRY_NO);
+ aTokens.emplace_back(TOKEN_ENTRY_TEXT);
+ }
+ else
+ aTokens.emplace_back(TOKEN_ENTRY);
+
+ if (TOX_AUTHORITIES != m_eType)
+ {
+ SwFormToken aToken(TOKEN_TAB_STOP);
+ aToken.nTabStopPosition = 0;
+
+ // #i36870# right aligned tab for all
+ aToken.cTabFillChar = '.';
+ aToken.eTabAlign = SvxTabAdjust::End;
+
+ aTokens.push_back(aToken);
+ aTokens.emplace_back(TOKEN_PAGE_NUMS);
+ }
+
+ if (TOX_CONTENT == m_eType || TOX_ILLUSTRATIONS == m_eType)
+ aTokens.emplace_back(TOKEN_LINK_END);
+
+ SetTemplate(0, SwResId(*pPoolId++));
+
+ if(TOX_INDEX == m_eType)
+ {
+ for( sal_uInt16 i = 1; i < 5; ++i )
+ {
+ if(1 == i)
+ {
+ SwFormTokens aTmpTokens;
+ SwFormToken aTmpToken(TOKEN_ENTRY);
+ aTmpTokens.push_back(aTmpToken);
+
+ SetPattern( i, std::move(aTmpTokens) );
+ SetTemplate(i, SwResId(STR_POOLCOLL_TOX_IDXBREAK));
+ }
+ else
+ {
+ SetPattern( i, std::vector(aTokens) );
+ SetTemplate(i, SwResId(STR_POOLCOLL_TOX_ARY[i - 1]));
+ }
+ }
+ }
+ else
+ {
+ for (sal_uInt16 i = 1; i < GetFormMax(); ++i, ++pPoolId) // Number 0 is the title
+ {
+ if (TOX_AUTHORITIES == m_eType)
+ {
+ SwFormTokens aAuthTokens;
+ lcl_FillAuthPattern(aAuthTokens, i);
+ SetPattern(i, std::move(aAuthTokens));
+ }
+ else
+ SetPattern( i, std::vector(aTokens) );
+
+ if( TOX_CONTENT == m_eType && 6 == i )
+ pPoolId = STR_POOLCOLL_TOX_CNTNT_EXTRA_ARY;
+ else if( TOX_USER == m_eType && 6 == i )
+ pPoolId = STR_POOLCOLL_TOX_USER_EXTRA_ARY;
+ else if( TOX_AUTHORITIES == m_eType ) //reuse the same STR_POOLCOLL_TOX_AUTHORITIES1 id each time
+ pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY + 1;
+ SetTemplate(i, SwResId(*pPoolId));
+ }
+ }
+}
+
+SwForm::SwForm(const SwForm& rForm)
+ : m_eType( rForm.m_eType )
+{
+ *this = rForm;
+}
+
+SwForm& SwForm::operator=(const SwForm& rForm)
+{
+ m_eType = rForm.m_eType;
+ m_nFormMaxLevel = rForm.m_nFormMaxLevel;
+// nFirstTabPos = rForm.nFirstTabPos;
+// bHasFirstTabPos = rForm.bHasFirstTabPos;
+ m_bIsRelTabPos = rForm.m_bIsRelTabPos;
+ m_bCommaSeparated = rForm.m_bCommaSeparated;
+ for(sal_uInt16 i=0; i < m_nFormMaxLevel; ++i)
+ {
+ m_aPattern[i] = rForm.m_aPattern[i];
+ m_aTemplate[i] = rForm.m_aTemplate[i];
+ }
+ return *this;
+}
+
+sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
+{
+ switch( eTOXType )
+ {
+ case TOX_INDEX:
+ return 5;
+ case TOX_USER:
+ case TOX_CONTENT:
+ return MAXLEVEL + 1;
+ case TOX_ILLUSTRATIONS:
+ case TOX_OBJECTS:
+ case TOX_TABLES:
+ return 2;
+ case TOX_BIBLIOGRAPHY:
+ case TOX_CITATION:
+ case TOX_AUTHORITIES:
+ return AUTH_TYPE_END + 1;
+ }
+ return 0;
+}
+
+void SwForm::AdjustTabStops( SwDoc const & rDoc ) // #i21237#
+{
+ const sal_uInt16 nFormMax = GetFormMax();
+ for ( sal_uInt16 nLevel = 1; nLevel < nFormMax; ++nLevel )
+ {
+ SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( GetTemplate(nLevel) );
+ if( pColl == nullptr )
+ {
+ // Paragraph Style for this level has not been created.
+ // --> No need to propagate default values
+ continue;
+ }
+
+ const SvxTabStopItem& rTabStops = pColl->GetTabStops(false);
+ const sal_uInt16 nTabCount = rTabStops.Count();
+ if (nTabCount != 0)
+ {
+ SwFormTokens aCurrentPattern = GetPattern(nLevel);
+ SwFormTokens::iterator aIt = aCurrentPattern.begin();
+
+ bool bChanged = false;
+ for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
+ {
+ const SvxTabStop& rTab = rTabStops[nTab];
+
+ if ( rTab.GetAdjustment() == SvxTabAdjust::Default )
+ continue; // ignore the default tab stop
+
+ aIt = find_if( aIt, aCurrentPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_TAB_STOP) );
+ if ( aIt != aCurrentPattern.end() )
+ {
+ bChanged = true;
+ aIt->nTabStopPosition = rTab.GetTabPos();
+ aIt->eTabAlign =
+ ( nTab == nTabCount - 1
+ && rTab.GetAdjustment() == SvxTabAdjust::Right )
+ ? SvxTabAdjust::End
+ : rTab.GetAdjustment();
+ aIt->cTabFillChar = rTab.GetFill();
+ ++aIt;
+ }
+ else
+ break; // no more tokens to replace
+ }
+
+ if ( bChanged )
+ SetPattern( nLevel, std::move(aCurrentPattern) );
+ }
+ }
+}
+
+OUString SwForm::GetFormEntry() {return "<E>";}
+OUString SwForm::GetFormTab() {return "<T>";}
+OUString SwForm::GetFormPageNums() {return "<#>";}
+OUString SwForm::GetFormLinkStt() {return "<LS>";}
+OUString SwForm::GetFormLinkEnd() {return "<LE>";}
+OUString SwForm::GetFormEntryNum() {return "<E#>";}
+OUString SwForm::GetFormEntryText() {return "<ET>";}
+OUString SwForm::GetFormChapterMark() {return "<C>";}
+OUString SwForm::GetFormText() {return "<X>";}
+OUString SwForm::GetFormAuth() {return "<A>";}
+
+SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
+ SwTOXElement nCreaType, const OUString& rTitle )
+ : SwClient(const_cast<sw::BroadcastingModify*>(static_cast<sw::BroadcastingModify const *>(pTyp)))
+ , m_aForm(rForm)
+ , m_aTitle(rTitle)
+ , m_eLanguage(::GetAppLanguage())
+ , m_nCreateType(nCreaType)
+ , m_nOLEOptions(SwTOOElements::NONE)
+ , m_eCaptionDisplay(CAPTION_COMPLETE)
+ , m_bProtected( true )
+ , m_bFromChapter(false)
+ , m_bFromObjectNames(false)
+ , m_bLevelFromChapter(false)
+ , maMSTOCExpression()
+ , mbKeepExpression(true)
+{
+ m_aData.nOptions = SwTOIOptions::NONE;
+}
+
+SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
+ : SwClient( rSource.GetRegisteredInNonConst() )
+ , mbKeepExpression(true)
+{
+ CopyTOXBase( pDoc, rSource );
+}
+
+void SwTOXBase::RegisterToTOXType( SwTOXType& rType )
+{
+ rType.Add( this );
+}
+
+void SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
+{
+ maMSTOCExpression = rSource.maMSTOCExpression;
+ SwTOXType* pType = const_cast<SwTOXType*>(rSource.GetTOXType());
+ if( pDoc &&
+ std::find_if(pDoc->GetTOXTypes().begin(), pDoc->GetTOXTypes().end(),
+ [=](const std::unique_ptr<SwTOXType> & p) { return p.get() == pType; })
+ == pDoc->GetTOXTypes().end())
+ {
+ // type not in pDoc, so create it now
+ const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
+ bool bFound = false;
+ for( size_t n = rTypes.size(); n; )
+ {
+ const SwTOXType* pCmp = rTypes[ --n ].get();
+ if( pCmp->GetType() == pType->GetType() &&
+ pCmp->GetTypeName() == pType->GetTypeName() )
+ {
+ pType = const_cast<SwTOXType*>(pCmp);
+ bFound = true;
+ break;
+ }
+ }
+
+ if( !bFound )
+ pType = const_cast<SwTOXType*>(pDoc->InsertTOXType( *pType ));
+ }
+ pType->Add( this );
+
+ m_nCreateType = rSource.m_nCreateType;
+ m_aTitle = rSource.m_aTitle;
+ m_aForm = rSource.m_aForm;
+ m_aBookmarkName = rSource.m_aBookmarkName;
+ m_bProtected = rSource.m_bProtected;
+ m_bFromChapter = rSource.m_bFromChapter;
+ m_bFromObjectNames = rSource.m_bFromObjectNames;
+ m_sMainEntryCharStyle = rSource.m_sMainEntryCharStyle;
+ m_sSequenceName = rSource.m_sSequenceName;
+ m_eCaptionDisplay = rSource.m_eCaptionDisplay;
+ m_nOLEOptions = rSource.m_nOLEOptions;
+ m_eLanguage = rSource.m_eLanguage;
+ m_sSortAlgorithm = rSource.m_sSortAlgorithm;
+ m_bLevelFromChapter = rSource.m_bLevelFromChapter;
+
+ for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
+ m_aStyleNames[i] = rSource.m_aStyleNames[i];
+
+ // it's the same data type!
+ m_aData.nOptions = rSource.m_aData.nOptions;
+
+ if( !pDoc || pDoc->IsCopyIsMove() )
+ m_aName = rSource.GetTOXName();
+ else
+ m_aName = pDoc->GetUniqueTOXBaseName( *pType, rSource.GetTOXName() );
+}
+
+// TOX specific functions
+SwTOXBase::~SwTOXBase()
+{
+// if( GetTOXType()->GetType() == TOX_USER )
+// delete aData.pTemplateName;
+}
+
+void SwTOXBase::SetTitle(const OUString& rTitle)
+ { m_aTitle = rTitle; }
+
+void SwTOXBase::SetBookmarkName(const OUString& bName)
+{
+ m_aBookmarkName = bName;
+}
+
+SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
+{
+ m_aForm = rSource.m_aForm;
+ m_aName = rSource.m_aName;
+ m_aTitle = rSource.m_aTitle;
+ m_aBookmarkName = rSource.m_aBookmarkName;
+ m_sMainEntryCharStyle = rSource.m_sMainEntryCharStyle;
+ for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
+ m_aStyleNames[nLevel] = rSource.m_aStyleNames[nLevel];
+ m_sSequenceName = rSource.m_sSequenceName;
+ m_eLanguage = rSource.m_eLanguage;
+ m_sSortAlgorithm = rSource.m_sSortAlgorithm;
+ m_aData = rSource.m_aData;
+ m_nCreateType = rSource.m_nCreateType;
+ m_nOLEOptions = rSource.m_nOLEOptions;
+ m_eCaptionDisplay = rSource.m_eCaptionDisplay;
+ m_bProtected = rSource.m_bProtected;
+ m_bFromChapter = rSource.m_bFromChapter;
+ m_bFromObjectNames = rSource.m_bFromObjectNames;
+ m_bLevelFromChapter = rSource.m_bLevelFromChapter;
+
+ if (rSource.GetAttrSet())
+ SetAttrSet(*rSource.GetAttrSet());
+
+ return *this;
+}
+
+OUString SwFormToken::GetString() const
+{
+ OUString sToken;
+
+ switch( eTokenType )
+ {
+ case TOKEN_ENTRY_NO:
+ sToken = SwForm::GetFormEntryNum();
+ break;
+ case TOKEN_ENTRY_TEXT:
+ sToken = SwForm::GetFormEntryText();
+ break;
+ case TOKEN_ENTRY:
+ sToken = SwForm::GetFormEntry();
+ break;
+ case TOKEN_TAB_STOP:
+ sToken = SwForm::GetFormTab();
+ break;
+ case TOKEN_TEXT:
+ // Return a Token only if Text is not empty!
+ if( sText.isEmpty() )
+ {
+ return OUString();
+ }
+ sToken = SwForm::GetFormText();
+ break;
+ case TOKEN_PAGE_NUMS:
+ sToken = SwForm::GetFormPageNums();
+ break;
+ case TOKEN_CHAPTER_INFO:
+ sToken = SwForm::GetFormChapterMark();
+ break;
+ case TOKEN_LINK_START:
+ sToken = SwForm::GetFormLinkStt();
+ break;
+ case TOKEN_LINK_END:
+ sToken = SwForm::GetFormLinkEnd();
+ break;
+ case TOKEN_AUTHORITY:
+ {
+ sToken = SwForm::GetFormAuth();
+ }
+ break;
+ case TOKEN_END:
+ break;
+ }
+
+ OUString sData = " " + sCharStyleName + "," + OUString::number( nPoolId ) + ",";
+
+ // TabStopPosition and TabAlign or ChapterInfoFormat
+ switch (eTokenType)
+ {
+ case TOKEN_TAB_STOP:
+ sData += OUString::number( nTabStopPosition ) + ","
+ + OUString::number( static_cast< sal_Int32 >(eTabAlign) ) + ","
+ + OUStringChar(cTabFillChar) + ","
+ + OUString::number( bWithTab ? 1 : 0 );
+ break;
+ case TOKEN_CHAPTER_INFO:
+ case TOKEN_ENTRY_NO:
+ // add also maximum permitted level
+ sData += OUString::number( nChapterFormat ) + ","
+ + OUString::number( nOutlineLevel );
+ break;
+ case TOKEN_TEXT:
+ sData += OUStringChar(TOX_STYLE_DELIMITER)
+ + sText.replaceAll(OUStringChar(TOX_STYLE_DELIMITER), "")
+ + OUStringChar(TOX_STYLE_DELIMITER);
+ break;
+ case TOKEN_AUTHORITY:
+ if (nAuthorityField<10)
+ {
+ sData = "0" + OUString::number( nAuthorityField ) + sData;
+ }
+ else
+ {
+ sData = OUString::number( nAuthorityField ) + sData;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return sToken.subView(0, sToken.getLength()-1) + sData + sToken.subView(sToken.getLength()-1);
+}
+
+// -> #i21237#
+
+/**
+ Returns the type of a token.
+
+ @param sToken the string representation of the token
+ @param rTokenLen return parameter the length of the head of the token
+
+ @return the type of the token
+*/
+static FormTokenType lcl_GetTokenType(std::u16string_view sToken,
+ sal_Int32 & rTokenLen)
+{
+ static struct
+ {
+ OUString sTokenStart;
+ sal_Int16 nTokenLength;
+ FormTokenType eTokenType;
+ } const aTokenArr[] = {
+ { SwForm::GetFormTab().copy(0, 2), 3, TOKEN_TAB_STOP },
+ { SwForm::GetFormPageNums().copy(0, 2), 3, TOKEN_PAGE_NUMS },
+ { SwForm::GetFormLinkStt().copy(0, 3), 4, TOKEN_LINK_START },
+ { SwForm::GetFormLinkEnd().copy(0, 3), 4, TOKEN_LINK_END },
+ { SwForm::GetFormEntryNum().copy(0, 3), 4, TOKEN_ENTRY_NO },
+ { SwForm::GetFormEntryText().copy(0, 3), 4, TOKEN_ENTRY_TEXT },
+ { SwForm::GetFormChapterMark().copy(0, 2), 3, TOKEN_CHAPTER_INFO },
+ { SwForm::GetFormText().copy(0, 2), 3, TOKEN_TEXT },
+ { SwForm::GetFormEntry().copy(0, 2), 3, TOKEN_ENTRY },
+ { SwForm::GetFormAuth().copy(0, 2), 5, TOKEN_AUTHORITY }
+ };
+
+ for(const auto & i : aTokenArr)
+ {
+ if( o3tl::starts_with( sToken, i.sTokenStart ) )
+ {
+ rTokenLen = i.nTokenLength;
+ return i.eTokenType;
+ }
+ }
+
+ SAL_WARN("sw.core", "SwFormTokensHelper: invalid token");
+ return TOKEN_END;
+}
+
+/**
+ Returns the string of a token.
+
+ @param sPattern the whole pattern
+ @param nStt starting position of the token
+
+ @return the string representation of the token
+*/
+static OUString
+lcl_SearchNextToken(const OUString & sPattern, sal_Int32 const nStt)
+{
+ sal_Int32 nEnd = sPattern.indexOf( '>', nStt );
+ if (nEnd >= 0)
+ {
+ // apparently the TOX_STYLE_DELIMITER act as a bracketing for
+ // TOKEN_TEXT tokens so that the user can have '>' inside the text...
+ const sal_Int32 nTextSeparatorFirst = sPattern.indexOf( TOX_STYLE_DELIMITER, nStt );
+ if ( nTextSeparatorFirst >= 0
+ && nTextSeparatorFirst + 1 < sPattern.getLength()
+ && nTextSeparatorFirst < nEnd)
+ {
+ const sal_Int32 nTextSeparatorSecond = sPattern.indexOf( TOX_STYLE_DELIMITER,
+ nTextSeparatorFirst + 1 );
+ // Since nEnd>=0 we don't need to check if nTextSeparatorSecond<0!
+ if( nEnd < nTextSeparatorSecond )
+ nEnd = sPattern.indexOf( '>', nTextSeparatorSecond );
+ // FIXME: No check to verify that nEnd is still >=0?
+ assert(nEnd >= 0);
+ }
+
+ ++nEnd;
+
+ return sPattern.copy( nStt, nEnd - nStt );
+ }
+
+ return OUString();
+}
+
+/**
+ Builds a token from its string representation.
+
+ @sPattern the whole pattern
+ @nCurPatternPos starting position of the token
+
+ @return the token
+ */
+static std::optional<SwFormToken>
+lcl_BuildToken(const OUString & sPattern, sal_Int32 & nCurPatternPos)
+{
+ OUString sToken( lcl_SearchNextToken(sPattern, nCurPatternPos) );
+ nCurPatternPos += sToken.getLength();
+ sal_Int32 nTokenLen = 0;
+ FormTokenType const eTokenType = lcl_GetTokenType(sToken, nTokenLen);
+ if (TOKEN_END == eTokenType) // invalid input? skip it
+ {
+ nCurPatternPos = sPattern.getLength();
+ return std::optional<SwFormToken>();
+ }
+
+ // at this point sPattern contains the
+ // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
+ // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
+ // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
+ SwFormToken eRet( eTokenType );
+ const OUString sAuthFieldEnum = sToken.copy( 2, 2 );
+ sToken = sToken.copy( nTokenLen, sToken.getLength() - nTokenLen - 1);
+
+ sal_Int32 nIdx{ 0 };
+ eRet.sCharStyleName = sToken.getToken( 0, ',', nIdx );
+ std::u16string_view sTmp( o3tl::getToken(sToken, 0, ',', nIdx ));
+ if( !sTmp.empty() )
+ eRet.nPoolId = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp));
+
+ switch( eTokenType )
+ {
+//i53420
+ case TOKEN_CHAPTER_INFO:
+//i53420
+ case TOKEN_ENTRY_NO:
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 2
+ if( !sTmp.empty() )
+ eRet.nChapterFormat = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp));
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 3
+ if( !sTmp.empty() )
+ eRet.nOutlineLevel = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp)); //the maximum outline level to examine
+ break;
+
+ case TOKEN_TEXT:
+ {
+ const sal_Int32 nStartText = sToken.indexOf( TOX_STYLE_DELIMITER );
+ if( nStartText>=0 && nStartText+1<sToken.getLength())
+ {
+ const sal_Int32 nEndText = sToken.indexOf( TOX_STYLE_DELIMITER,
+ nStartText + 1);
+ if( nEndText>=0 )
+ {
+ eRet.sText = sToken.copy( nStartText + 1,
+ nEndText - nStartText - 1);
+ }
+ }
+ }
+ break;
+
+ case TOKEN_TAB_STOP:
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 2
+ if( !sTmp.empty() )
+ eRet.nTabStopPosition = o3tl::toInt32(sTmp);
+
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 3
+ if( !sTmp.empty() )
+ eRet.eTabAlign = static_cast<SvxTabAdjust>(o3tl::toInt32(sTmp));
+
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 4
+ if( !sTmp.empty() )
+ eRet.cTabFillChar = sTmp[0];
+
+ sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 5
+ if( !sTmp.empty() )
+ eRet.bWithTab = 0 != o3tl::toInt32(sTmp);
+ break;
+
+ case TOKEN_AUTHORITY:
+ eRet.nAuthorityField = o3tl::narrowing<sal_uInt16>(sAuthFieldEnum.toInt32());
+ break;
+ default: break;
+ }
+ return eRet;
+}
+
+SwFormTokensHelper::SwFormTokensHelper(const OUString & rPattern)
+{
+ sal_Int32 nCurPatternPos = 0;
+
+ while (nCurPatternPos < rPattern.getLength())
+ {
+ std::optional<SwFormToken> const oToken(
+ lcl_BuildToken(rPattern, nCurPatternPos));
+ if (oToken)
+ m_Tokens.push_back(*oToken);
+ }
+}
+
+// <- #i21237#
+
+void SwForm::SetPattern(sal_uInt16 nLevel, SwFormTokens&& rTokens)
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+ m_aPattern[nLevel] = std::move(rTokens);
+}
+
+void SwForm::SetPattern(sal_uInt16 nLevel, const OUString & rStr)
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+
+ SwFormTokensHelper aHelper(rStr);
+ m_aPattern[nLevel] = aHelper.GetTokens();
+}
+
+const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
+{
+ OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
+ return m_aPattern[nLevel];
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */