Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / tox / txmsrt.cxx
blob4dcbd49fe70bb4eaf1ba0fb0b05bb025d765c4e6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uri/UriReferenceFactory.hpp>
22 #include <unotools/charclass.hxx>
23 #include <osl/diagnose.h>
24 #include <tools/urlobj.hxx>
25 #include <comphelper/processfactory.hxx>
26 #include <officecfg/Office/Common.hxx>
27 #include <txtfld.hxx>
28 #include <doc.hxx>
29 #include <IDocumentLayoutAccess.hxx>
30 #include <IDocumentMarkAccess.hxx>
31 #include <cntfrm.hxx>
32 #include <txtfrm.hxx>
33 #include <rootfrm.hxx>
34 #include <modeltoviewhelper.hxx>
35 #include <node.hxx>
36 #include <pam.hxx>
37 #include <txttxmrk.hxx>
38 #include <frmfmt.hxx>
39 #include <fmtfld.hxx>
40 #include <txmsrt.hxx>
41 #include <ndtxt.hxx>
42 #include <swtable.hxx>
43 #include <expfld.hxx>
44 #include <authfld.hxx>
45 #include <toxwrap.hxx>
47 #include <strings.hrc>
48 #include <reffld.hxx>
49 #include <docsh.hxx>
50 #include <utility>
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::uno;
55 // Initialize strings
56 SwTOIOptions SwTOXSortTabBase::nOpt = SwTOIOptions::NONE;
58 SwTOXInternational::SwTOXInternational( LanguageType nLang, SwTOIOptions nOpt,
59 OUString aSortAlgorithm ) :
60 m_eLang( nLang ),
61 m_sSortAlgorithm(std::move(aSortAlgorithm)),
62 m_nOptions( nOpt )
64 Init();
67 SwTOXInternational::SwTOXInternational( const SwTOXInternational& rIntl ) :
68 m_eLang( rIntl.m_eLang ),
69 m_sSortAlgorithm(rIntl.m_sSortAlgorithm),
70 m_nOptions( rIntl.m_nOptions )
72 Init();
75 void SwTOXInternational::Init()
77 m_pIndexWrapper.reset( new IndexEntrySupplierWrapper() );
79 const lang::Locale aLcl( LanguageTag::convertToLocale( m_eLang ) );
80 m_pIndexWrapper->SetLocale( aLcl );
82 if(m_sSortAlgorithm.isEmpty())
84 Sequence < OUString > aSeq( m_pIndexWrapper->GetAlgorithmList( aLcl ));
85 if(aSeq.hasElements())
86 m_sSortAlgorithm = aSeq.getConstArray()[0];
89 if ( m_nOptions & SwTOIOptions::CaseSensitive )
90 m_pIndexWrapper->LoadAlgorithm( aLcl, m_sSortAlgorithm, 0 );
91 else
92 m_pIndexWrapper->LoadAlgorithm( aLcl, m_sSortAlgorithm, SW_COLLATOR_IGNORES );
94 m_oCharClass.emplace( LanguageTag( aLcl ) );
98 SwTOXInternational::~SwTOXInternational()
100 m_oCharClass.reset();
101 m_pIndexWrapper.reset();
104 OUString SwTOXInternational::ToUpper( const OUString& rStr, sal_Int32 nPos ) const
106 return m_oCharClass->uppercase( rStr, nPos, 1 );
109 bool SwTOXInternational::IsNumeric( const OUString& rStr ) const
111 return m_oCharClass->isNumeric( rStr );
114 sal_Int32 SwTOXInternational::Compare( const TextAndReading& rTaR1,
115 const lang::Locale& rLocale1,
116 const TextAndReading& rTaR2,
117 const lang::Locale& rLocale2 ) const
119 return m_pIndexWrapper->CompareIndexEntry( rTaR1.sText, rTaR1.sReading, rLocale1,
120 rTaR2.sText, rTaR2.sReading, rLocale2 );
123 OUString SwTOXInternational::GetIndexKey( const TextAndReading& rTaR,
124 const lang::Locale& rLocale ) const
126 return m_pIndexWrapper->GetIndexKey( rTaR.sText, rTaR.sReading, rLocale );
129 OUString SwTOXInternational::GetFollowingText( bool bMorePages ) const
131 return m_pIndexWrapper->GetFollowingText( bMorePages );
134 // SortElement for TOX entries
135 SwTOXSortTabBase::SwTOXSortTabBase( TOXSortType nTyp, const SwContentNode* pNd,
136 const SwTextTOXMark* pMark,
137 const SwTOXInternational* pInter,
138 const lang::Locale* pLocale )
139 : pTOXNd( nullptr ), pTextMark( pMark ), pTOXIntl( pInter ),
140 nPos( 0 ), nCntPos( 0 ), nType( o3tl::narrowing<sal_uInt16>(nTyp) )
141 , m_bValidText( false )
143 if ( pLocale )
144 aLocale = *pLocale;
146 if( !pNd )
147 return;
149 sal_Int32 n = 0;
150 if( pTextMark )
151 n = pTextMark->GetStart();
152 SwTOXSource aTmp( pNd, n, pTextMark && pTextMark->GetTOXMark().IsMainEntry() );
153 aTOXSources.push_back(aTmp);
155 nPos = pNd->GetIndex();
157 switch( nTyp )
159 case TOX_SORT_CONTENT:
160 case TOX_SORT_PARA:
161 case TOX_SORT_TABLE:
162 // If they are in a special areas, we should get the position at the
163 // body
164 if( nPos < pNd->GetNodes().GetEndOfExtras().GetIndex() )
166 // Then get the 'anchor' (body) position
167 Point aPt;
168 std::pair<Point, bool> tmp(aPt, false);
169 const SwContentFrame *const pFrame = pNd->getLayoutFrame(
170 pNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
171 nullptr, &tmp);
172 if( pFrame )
174 SwPosition aPos( *pNd );
175 const SwDoc& rDoc = pNd->GetDoc();
176 bool const bResult = GetBodyTextNode( rDoc, aPos, *pFrame );
177 OSL_ENSURE(bResult, "where is the text node");
178 nPos = aPos.GetNodeIndex();
179 nCntPos = aPos.GetContentIndex();
182 else
183 nCntPos = n;
184 break;
185 default: break;
189 std::pair<OUString, bool> SwTOXSortTabBase::GetURL(SwRootFrame const*const pLayout) const
191 OUString typeName;
192 SwTOXType const& rType(*pTextMark->GetTOXMark().GetTOXType());
193 switch (rType.GetType())
195 case TOX_INDEX:
196 typeName = "A";
197 break;
198 case TOX_CONTENT:
199 typeName = "C";
200 break;
201 case TOX_USER:
202 typeName = "U" + rType.GetTypeName();
203 break;
204 default:
205 assert(false); // other tox can't have toxmarks as source
206 break;
208 OUString const decodedUrl( // counter will be added by caller!
209 OUStringChar(toxMarkSeparator) + pTextMark->GetTOXMark().GetText(pLayout)
210 + OUStringChar(toxMarkSeparator) + typeName
211 + OUStringChar(cMarkSeparator) + "toxmark" );
213 return std::make_pair(decodedUrl, true);
216 bool SwTOXSortTabBase::IsFullPara() const
218 return false;
221 void SwTOXSortTabBase::FillText( SwTextNode& rNd, const SwContentIndex& rInsPos,
222 sal_uInt16, SwRootFrame const*const) const
224 rNd.InsertText( GetText().sText, rInsPos );
227 bool SwTOXSortTabBase::equivalent(const SwTOXSortTabBase& rCmp)
229 bool bRet = nPos == rCmp.nPos && nCntPos == rCmp.nCntPos &&
230 (!aTOXSources[0].pNd || !rCmp.aTOXSources[0].pNd ||
231 aTOXSources[0].pNd == rCmp.aTOXSources[0].pNd );
233 if( TOX_SORT_CONTENT == nType )
235 bRet = bRet && pTextMark && rCmp.pTextMark &&
236 pTextMark->GetStart() == rCmp.pTextMark->GetStart();
238 if( bRet )
240 // Both pointers exist -> compare text
241 // else -> compare AlternativeText
242 const sal_Int32 *pEnd = pTextMark->End();
243 const sal_Int32 *pEndCmp = rCmp.pTextMark->End();
245 bRet = ( ( pEnd && pEndCmp ) || ( !pEnd && !pEndCmp ) ) &&
246 pTOXIntl->IsEqual( GetText(), GetLocale(),
247 rCmp.GetText(), rCmp.GetLocale() );
250 return bRet;
253 bool SwTOXSortTabBase::sort_lt(const SwTOXSortTabBase& rCmp)
255 if( nPos < rCmp.nPos )
256 return true;
258 if( nPos == rCmp.nPos )
260 if( nCntPos < rCmp.nCntPos )
261 return true;
263 if( nCntPos == rCmp.nCntPos )
265 const SwNode* pFirst = aTOXSources[0].pNd;
266 const SwNode* pNext = rCmp.aTOXSources[0].pNd;
268 if( pFirst && pFirst == pNext )
270 if( TOX_SORT_CONTENT == nType && pTextMark && rCmp.pTextMark )
272 if( pTextMark->GetStart() < rCmp.pTextMark->GetStart() )
273 return true;
275 if( pTextMark->GetStart() == rCmp.pTextMark->GetStart() )
277 const sal_Int32 *pEnd = pTextMark->End();
278 const sal_Int32 *pEndCmp = rCmp.pTextMark->End();
280 // Both pointers exist -> compare text
281 // else -> compare AlternativeText
282 if( ( pEnd && pEndCmp ) || ( !pEnd && !pEndCmp ) )
284 return pTOXIntl->IsLess( GetText(), GetLocale(),
285 rCmp.GetText(), rCmp.GetLocale() );
287 if( pEnd && !pEndCmp )
288 return true;
292 else if( pFirst && pFirst->IsTextNode() &&
293 pNext && pNext->IsTextNode() )
294 return ::IsFrameBehind( *static_cast<const SwTextNode*>(pNext), nCntPos,
295 *static_cast<const SwTextNode*>(pFirst), nCntPos );
298 return false;
301 // Sorted keyword entry
302 SwTOXIndex::SwTOXIndex( const SwTextNode& rNd,
303 const SwTextTOXMark* pMark, SwTOIOptions nOptions,
304 sal_uInt8 nKyLevel,
305 const SwTOXInternational& rIntl,
306 const lang::Locale& rLocale )
307 : SwTOXSortTabBase( TOX_SORT_INDEX, &rNd, pMark, &rIntl, &rLocale ),
308 nKeyLevel(nKyLevel)
310 nPos = rNd.GetIndex();
311 nOpt = nOptions;
314 // Compare keywords. Only relates to the text.
316 bool SwTOXIndex::equivalent(const SwTOXSortTabBase& rCmpBase)
318 const SwTOXIndex& rCmp = static_cast<const SwTOXIndex&>(rCmpBase);
320 // Respect case taking dependencies into account
321 if(GetLevel() != rCmp.GetLevel() || nKeyLevel != rCmp.nKeyLevel)
322 return false;
324 OSL_ENSURE(pTextMark, "pTextMark == 0, No keyword");
326 bool bRet = pTOXIntl->IsEqual( GetText(), GetLocale(),
327 rCmp.GetText(), rCmp.GetLocale() );
329 // If we don't summarize we need to evaluate the Pos
330 if(bRet && !(GetOptions() & SwTOIOptions::SameEntry))
331 bRet = nPos == rCmp.nPos;
333 return bRet;
336 // operator, only depends on the text
338 bool SwTOXIndex::sort_lt(const SwTOXSortTabBase& rCmpBase)
340 OSL_ENSURE(pTextMark, "pTextMark == 0, No keyword");
342 const TextAndReading aMyTaR(GetText());
343 const TextAndReading aOtherTaR(rCmpBase.GetText());
345 bool bRet = GetLevel() == rCmpBase.GetLevel() &&
346 pTOXIntl->IsLess( aMyTaR, GetLocale(),
347 aOtherTaR, rCmpBase.GetLocale() );
349 // If we don't summarize we need to evaluate the Pos
350 if( !bRet && !(GetOptions() & SwTOIOptions::SameEntry) )
352 bRet = pTOXIntl->IsEqual( aMyTaR, GetLocale(),
353 aOtherTaR, rCmpBase.GetLocale() ) &&
354 nPos < rCmpBase.nPos;
357 return bRet;
360 // The keyword itself
362 TextAndReading SwTOXIndex::GetText_Impl(SwRootFrame const*const pLayout) const
364 OSL_ENSURE(pTextMark, "pTextMark == 0, No keyword");
365 const SwTOXMark& rTOXMark = pTextMark->GetTOXMark();
367 TextAndReading aRet;
368 switch(nKeyLevel)
370 case FORM_PRIMARY_KEY :
372 aRet.sText = rTOXMark.GetPrimaryKey();
373 aRet.sReading = rTOXMark.GetPrimaryKeyReading();
375 break;
376 case FORM_SECONDARY_KEY :
378 aRet.sText = rTOXMark.GetSecondaryKey();
379 aRet.sReading = rTOXMark.GetSecondaryKeyReading();
381 break;
382 case FORM_ENTRY :
384 aRet.sText = rTOXMark.GetText(pLayout);
385 aRet.sReading = rTOXMark.GetTextReading();
387 break;
389 // if SwTOIOptions::InitialCaps is set, first character is to be capitalized
390 if( SwTOIOptions::InitialCaps & nOpt && pTOXIntl && !aRet.sText.isEmpty())
392 aRet.sText = pTOXIntl->ToUpper( aRet.sText, 0 ) + aRet.sText.subView(1);
395 return aRet;
398 void SwTOXIndex::FillText( SwTextNode& rNd, const SwContentIndex& rInsPos, sal_uInt16,
399 SwRootFrame const*const pLayout) const
401 assert(!"sw_redlinehide: this is dead code, Bibliography only has SwTOXAuthority");
402 const sal_Int32* pEnd = pTextMark->End();
404 TextAndReading aRet;
405 if( pEnd && !pTextMark->GetTOXMark().IsAlternativeText() &&
406 !(GetOptions() & SwTOIOptions::KeyAsEntry))
408 aRet.sText = static_cast<const SwTextNode*>(aTOXSources[0].pNd)->GetExpandText(
409 pLayout,
410 pTextMark->GetStart(),
411 *pEnd - pTextMark->GetStart(),
412 false, false, false,
413 ExpandMode::ExpandFootnote
414 | (pLayout && pLayout->IsHideRedlines()
415 ? ExpandMode::HideDeletions
416 : ExpandMode(0)));
417 if(SwTOIOptions::InitialCaps & nOpt && pTOXIntl && !aRet.sText.isEmpty())
419 aRet.sText = pTOXIntl->ToUpper( aRet.sText, 0 ) + aRet.sText.subView(1);
422 else
423 aRet = GetText();
425 rNd.InsertText( aRet.sText, rInsPos );
428 sal_uInt16 SwTOXIndex::GetLevel() const
430 OSL_ENSURE(pTextMark, "pTextMark == 0, No keyword");
432 sal_uInt16 nForm = FORM_PRIMARY_KEY;
434 if( !(GetOptions() & SwTOIOptions::KeyAsEntry)&&
435 !pTextMark->GetTOXMark().GetPrimaryKey().isEmpty() )
437 nForm = FORM_SECONDARY_KEY;
438 if( !pTextMark->GetTOXMark().GetSecondaryKey().isEmpty() )
439 nForm = FORM_ENTRY;
441 return nForm;
444 // Key and separator
445 SwTOXCustom::SwTOXCustom(TextAndReading aKey,
446 sal_uInt16 nLevel,
447 const SwTOXInternational& rIntl,
448 const lang::Locale& rLocale )
449 : SwTOXSortTabBase( TOX_SORT_CUSTOM, nullptr, nullptr, &rIntl, &rLocale ),
450 m_aKey(std::move(aKey)), nLev(nLevel)
454 bool SwTOXCustom::equivalent(const SwTOXSortTabBase& rCmpBase)
456 return GetLevel() == rCmpBase.GetLevel() &&
457 pTOXIntl->IsEqual( GetText(), GetLocale(),
458 rCmpBase.GetText(), rCmpBase.GetLocale() );
461 bool SwTOXCustom::sort_lt(const SwTOXSortTabBase& rCmpBase)
463 return GetLevel() <= rCmpBase.GetLevel() &&
464 pTOXIntl->IsLess( GetText(), GetLocale(),
465 rCmpBase.GetText(), rCmpBase.GetLocale() );
468 sal_uInt16 SwTOXCustom::GetLevel() const
470 return nLev;
473 TextAndReading SwTOXCustom::GetText_Impl(SwRootFrame const*const) const
475 return m_aKey;
478 // Sorts the TOX entries
479 SwTOXContent::SwTOXContent( const SwTextNode& rNd, const SwTextTOXMark* pMark,
480 const SwTOXInternational& rIntl)
481 : SwTOXSortTabBase( TOX_SORT_CONTENT, &rNd, pMark, &rIntl )
485 // The content's text
487 TextAndReading SwTOXContent::GetText_Impl(SwRootFrame const*const pLayout) const
489 const sal_Int32* pEnd = pTextMark->End();
490 if( pEnd && !pTextMark->GetTOXMark().IsAlternativeText() )
492 return TextAndReading(
493 static_cast<const SwTextNode*>(aTOXSources[0].pNd)->GetExpandText(
494 pLayout,
495 pTextMark->GetStart(),
496 *pEnd - pTextMark->GetStart(),
497 false, false, false,
498 ExpandMode::ExpandFootnote
499 | (pLayout && pLayout->IsHideRedlines()
500 ? ExpandMode::HideDeletions
501 : ExpandMode(0))),
502 pTextMark->GetTOXMark().GetTextReading());
505 return TextAndReading(pTextMark->GetTOXMark().GetAlternativeText(), OUString());
508 void SwTOXContent::FillText(SwTextNode& rNd, const SwContentIndex& rInsPos, sal_uInt16,
509 SwRootFrame const*const pLayout) const
511 assert(!"sw_redlinehide: this is dead code, Bibliography only has SwTOXAuthority");
512 const sal_Int32* pEnd = pTextMark->End();
513 if( pEnd && !pTextMark->GetTOXMark().IsAlternativeText() )
514 // sw_redlinehide: this probably won't HideDeletions
515 static_cast<const SwTextNode*>(aTOXSources[0].pNd)->CopyExpandText(
516 rNd, &rInsPos, pTextMark->GetStart(),
517 *pEnd - pTextMark->GetStart(), pLayout);
518 else
520 rNd.InsertText( GetText().sText, rInsPos );
524 // The level for displaying it
526 sal_uInt16 SwTOXContent::GetLevel() const
528 return pTextMark->GetTOXMark().GetLevel();
531 // TOX assembled from paragraphs
532 // Watch out for OLE/graphics when sorting!
533 // The position must not come from the document, but from the "anchor"!
534 SwTOXPara::SwTOXPara(SwContentNode& rNd, SwTOXElement eT, sal_uInt16 nLevel, OUString sSeqName)
535 : SwTOXSortTabBase( TOX_SORT_PARA, &rNd, nullptr, nullptr ),
536 eType( eT ),
537 m_nLevel(nLevel),
538 nStartIndex(0),
539 nEndIndex(-1),
540 m_sSequenceName(std::move( sSeqName ))
542 // tdf#123313 create any missing bookmarks *before* generating ToX nodes!
543 switch (eType)
545 case SwTOXElement::Template:
546 case SwTOXElement::OutlineLevel:
547 assert(rNd.IsTextNode());
548 rNd.GetDoc().getIDocumentMarkAccess()->getMarkForTextNode(
549 *rNd.GetTextNode(), IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK);
550 break;
551 default:
552 break;
556 TextAndReading SwTOXPara::GetText_Impl(SwRootFrame const*const pLayout) const
558 const SwContentNode* pNd = aTOXSources[0].pNd;
559 switch( eType )
561 case SwTOXElement::Sequence:
562 if (nStartIndex != 0 || nEndIndex != -1)
564 // sw_redlinehide: "captions" are a rather fuzzily defined concept anyway
565 return TextAndReading(static_cast<const SwTextNode*>(pNd)->GetExpandText(
566 pLayout,
567 nStartIndex,
568 nEndIndex == -1 ? -1 : nEndIndex - nStartIndex,
569 false, false, false,
570 pLayout && pLayout->IsHideRedlines()
571 ? ExpandMode::HideDeletions
572 : ExpandMode(0)),
573 OUString());
575 [[fallthrough]];
576 case SwTOXElement::Template:
577 case SwTOXElement::OutlineLevel:
579 assert(nStartIndex == 0);
580 assert(nEndIndex == -1);
581 return TextAndReading(sw::GetExpandTextMerged(
582 pLayout, *static_cast<const SwTextNode*>(pNd),
583 false, false, ExpandMode::HideInvisible | ExpandMode::HideDeletions),
584 OUString());
586 break;
588 case SwTOXElement::Ole:
589 case SwTOXElement::Graphic:
590 case SwTOXElement::Frame:
592 // Find the FlyFormat; the object/graphic name is there
593 SwFrameFormat* pFly = pNd->GetFlyFormat();
594 if( pFly )
595 return TextAndReading(pFly->GetName(), OUString());
597 OSL_ENSURE( false, "Graphic/object without name" );
598 TranslateId pId = SwTOXElement::Ole == eType
599 ? STR_OBJECT_DEFNAME
600 : SwTOXElement::Graphic == eType
601 ? STR_GRAPHIC_DEFNAME
602 : STR_FRAME_DEFNAME;
603 return TextAndReading(SwResId(pId), OUString());
605 break;
606 default: break;
608 return TextAndReading();
611 void SwTOXPara::FillText( SwTextNode& rNd, const SwContentIndex& rInsPos, sal_uInt16,
612 SwRootFrame const*const pLayout) const
614 assert(!"sw_redlinehide: this is dead code, Bibliography only has SwTOXAuthority");
615 if( SwTOXElement::Template == eType || SwTOXElement::Sequence == eType || SwTOXElement::OutlineLevel == eType)
617 const SwTextNode* pSrc = static_cast<const SwTextNode*>(aTOXSources[0].pNd);
618 if (SwTOXElement::Sequence == eType
619 && (nStartIndex != 0 || nEndIndex != -1))
621 pSrc->CopyExpandText( rNd, &rInsPos, nStartIndex,
622 nEndIndex == -1 ? -1 : nEndIndex - nStartIndex,
623 pLayout, false, false, true );
625 else
627 assert(nStartIndex == 0);
628 assert(nEndIndex == -1);
629 // sw_redlinehide: this probably won't HideDeletions
630 pSrc->CopyExpandText( rNd, &rInsPos, 0, -1,
631 pLayout, false, false, true );
632 if (pLayout && pLayout->HasMergedParas())
634 if (SwTextFrame const*const pFrame = static_cast<SwTextFrame*>(pSrc->getLayoutFrame(pLayout)))
636 if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
638 // pSrc already copied above
639 assert(pSrc == pMerged->pParaPropsNode);
640 for (SwNodeOffset i = pSrc->GetIndex() + 1;
641 i <= pMerged->pLastNode->GetIndex(); ++i)
643 SwNode *const pTmp(pSrc->GetNodes()[i]);
644 if (pTmp->GetRedlineMergeFlag() == SwNode::Merge::NonFirst)
647 pTmp->GetTextNode()->CopyExpandText(
648 rNd, &rInsPos, 0, -1,
649 pLayout, false, false, false );
657 else
659 rNd.InsertText( GetText().sText.replace('\t', ' '), rInsPos );
663 sal_uInt16 SwTOXPara::GetLevel() const
665 sal_uInt16 nRet = m_nLevel;
666 const SwContentNode* pNd = aTOXSources[0].pNd;
668 if( SwTOXElement::OutlineLevel == eType && pNd->GetTextNode() )
670 const int nTmp = static_cast<const SwTextNode*>(pNd)->GetAttrOutlineLevel();
671 if(nTmp != 0 )
672 nRet = o3tl::narrowing<sal_uInt16>(nTmp);
674 return nRet;
677 std::pair<OUString, bool> SwTOXPara::GetURL(SwRootFrame const*const) const
679 OUString aText;
680 const SwContentNode* pNd = aTOXSources[0].pNd;
681 switch( eType )
683 case SwTOXElement::Template:
684 case SwTOXElement::OutlineLevel:
686 const SwTextNode * pTextNd = pNd->GetTextNode();
688 SwDoc& rDoc = const_cast<SwDoc&>( pTextNd->GetDoc() );
689 // tdf#123313: this *must not* create a bookmark, its Undo would
690 // be screwed! create it as preparatory step, in ctor!
691 ::sw::mark::IMark const * const pMark = rDoc.getIDocumentMarkAccess()->getMarkForTextNode(
692 *pTextNd,
693 IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK);
694 aText = "#" + pMark->GetName();
696 break;
698 case SwTOXElement::Ole:
699 case SwTOXElement::Graphic:
700 case SwTOXElement::Frame:
702 // Find the FlyFormat; the object/graphic name is there
703 SwFrameFormat* pFly = pNd->GetFlyFormat();
704 if( pFly )
706 aText = "#" + pFly->GetName() + OUStringChar(cMarkSeparator);
707 const char* pStr;
708 switch( eType )
710 case SwTOXElement::Ole: pStr = "ole"; break;
711 case SwTOXElement::Graphic: pStr = "graphic"; break;
712 case SwTOXElement::Frame: pStr = "frame"; break;
713 default: pStr = nullptr;
715 if( pStr )
716 aText += OUString::createFromAscii( pStr );
719 break;
720 case SwTOXElement::Sequence:
722 aText = "#" + m_sSequenceName + OUStringChar(cMarkSeparator)
723 + "sequence";
725 break;
726 default: break;
728 return std::make_pair(aText, false);
731 bool SwTOXPara::IsFullPara() const
733 switch (eType)
735 case SwTOXElement::Sequence:
736 case SwTOXElement::Template:
737 case SwTOXElement::OutlineLevel:
738 return nStartIndex == 0 && nEndIndex == -1;
739 default:
740 return false;
744 // Table
745 SwTOXTable::SwTOXTable( const SwContentNode& rNd )
746 : SwTOXSortTabBase( TOX_SORT_TABLE, &rNd, nullptr, nullptr ),
747 nLevel(FORM_ALPHA_DELIMITER)
751 TextAndReading SwTOXTable::GetText_Impl(SwRootFrame const*const) const
753 const SwNode* pNd = aTOXSources[0].pNd;
754 if( pNd )
756 const SwTableNode* pTableNd =
757 pNd->FindTableNode();
758 if (pTableNd)
760 return TextAndReading(pTableNd->GetTable().GetFrameFormat()->GetName(), OUString());
764 OSL_ENSURE( false, "Where's my table?" );
765 return TextAndReading(SwResId( STR_TABLE_DEFNAME ), OUString());
768 sal_uInt16 SwTOXTable::GetLevel() const
770 return nLevel;
773 std::pair<OUString, bool> SwTOXTable::GetURL(SwRootFrame const*const) const
775 const SwNode* pNd = aTOXSources[0].pNd;
776 if (!pNd)
777 return std::make_pair(OUString(), false);
779 pNd = pNd->FindTableNode();
780 if (!pNd)
781 return std::make_pair(OUString(), false);
783 const OUString sName = static_cast<const SwTableNode*>(pNd)->GetTable().GetFrameFormat()->GetName();
784 if ( sName.isEmpty() )
785 return std::make_pair(OUString(), false);
787 return std::make_pair("#" + sName + OUStringChar(cMarkSeparator) + "table", false);
790 SwTOXAuthority::SwTOXAuthority( const SwContentNode& rNd,
791 SwFormatField& rField, const SwTOXInternational& rIntl ) :
792 SwTOXSortTabBase( TOX_SORT_AUTHORITY, &rNd, nullptr, &rIntl ),
793 m_rField(rField)
795 if(rField.GetTextField())
796 nCntPos = rField.GetTextField()->GetStart();
799 sal_uInt16 SwTOXAuthority::GetLevel() const
801 OUString sText(static_cast<SwAuthorityField*>(m_rField.GetField())->GetFieldText(AUTH_FIELD_AUTHORITY_TYPE));
802 //#i18655# the level '0' is the heading level therefore the values are incremented here
803 sal_uInt16 nRet = 1;
804 if( pTOXIntl->IsNumeric( sText ) )
806 nRet = sText.toUInt32();
807 nRet++;
809 //illegal values are also set to 'ARTICLE' as non-numeric values are
810 if(nRet > AUTH_TYPE_END)
811 nRet = 1;
812 return nRet;
815 static OUString lcl_GetText(SwFormatField const& rField, SwRootFrame const*const pLayout)
817 return rField.GetField()->ExpandField(true, pLayout);
820 TextAndReading SwTOXAuthority::GetText_Impl(SwRootFrame const*const pLayout) const
822 return TextAndReading(lcl_GetText(m_rField, pLayout), OUString());
825 OUString SwTOXAuthority::GetText(sal_uInt16 nAuthField, const SwRootFrame* pLayout) const
827 SwAuthorityField* pField = static_cast<SwAuthorityField*>(m_rField.GetField());
828 OUString sText;
829 if(AUTH_FIELD_IDENTIFIER == nAuthField)
831 sText = lcl_GetText(m_rField, pLayout);
832 const SwAuthorityFieldType* pType = static_cast<const SwAuthorityFieldType*>(pField->GetTyp());
833 sal_Unicode cChar = pType->GetPrefix();
834 if(cChar && cChar != ' ')
835 sText = sText.copy(1);
836 cChar = pType->GetSuffix();
837 if(cChar && cChar != ' ')
838 sText = sText.copy(0, sText.getLength() - 1);
840 else if(AUTH_FIELD_AUTHORITY_TYPE == nAuthField)
842 sal_uInt16 nLevel = GetLevel();
843 if(nLevel)
844 sText = SwAuthorityFieldType::GetAuthTypeName(static_cast<ToxAuthorityType>(--nLevel));
846 else
847 sText = pField->GetFieldText(static_cast<ToxAuthorityField>(nAuthField));
848 return sText;
851 OUString SwTOXAuthority::GetSourceURL(const OUString& rText)
853 OUString aText = rText;
855 uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
856 = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
857 uno::Reference<uri::XUriReference> xUriRef;
860 xUriRef = xUriReferenceFactory->parse(aText);
862 catch (const uno::Exception& rException)
864 SAL_WARN("sw.core",
865 "SwTOXAuthority::GetSourceURL: failed to parse url: " << rException.Message);
867 if (xUriRef.is() && xUriRef->getFragment().startsWith("page="))
869 xUriRef->clearFragment();
870 aText = xUriRef->getUriReference();
873 return aText;
876 void SwTOXAuthority::FillText(SwTextNode& rNd, const SwContentIndex& rInsPos, sal_uInt16 nAuthField,
877 SwRootFrame const* const pLayout) const
879 OUString aText = GetText(nAuthField, pLayout);
880 if (nAuthField == AUTH_FIELD_URL)
882 aText = GetSourceURL(aText);
884 // Convert URL to a relative one if requested.
885 SwDoc* pDoc = static_cast<SwAuthorityFieldType*>(m_rField.GetField()->GetTyp())->GetDoc();
886 SwDocShell* pDocShell = pDoc->GetDocShell();
887 const OUString aBaseURL = pDocShell->getDocumentBaseURL();
888 std::u16string_view aBaseURIScheme;
889 sal_Int32 nSep = aBaseURL.indexOf(':');
890 if (nSep != -1)
892 aBaseURIScheme = aBaseURL.subView(0, nSep);
895 uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
896 = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
897 uno::Reference<uri::XUriReference> xUriRef;
900 xUriRef = xUriReferenceFactory->parse(aText);
902 catch (const uno::Exception& rException)
904 SAL_WARN("sw.core",
905 "SwTOXAuthority::FillText: failed to parse url: " << rException.Message);
908 bool bSaveRelFSys = officecfg::Office::Common::Save::URL::FileSystem::get();
909 if (xUriRef.is() && bSaveRelFSys && xUriRef->getScheme() == aBaseURIScheme)
911 aText = INetURLObject::GetRelURL(aBaseURL, aText);
915 rNd.InsertText(aText, rInsPos);
918 bool SwTOXAuthority::equivalent(const SwTOXSortTabBase& rCmp)
920 if (nType != rCmp.nType)
922 return false;
925 // Compare our SwAuthEntry and rCmp's SwAuthEntry, but the URL is considered equivalent, as long
926 // as it only differs in a page number, as that's still the same source.
927 const SwAuthEntry* pThis = static_cast<SwAuthorityField*>(m_rField.GetField())->GetAuthEntry();
928 const SwAuthEntry* pOther = static_cast<SwAuthorityField*>(
929 static_cast<const SwTOXAuthority&>(rCmp).m_rField.GetField())
930 ->GetAuthEntry();
931 if (pThis == pOther)
933 return true;
936 for (int i = 0; i < AUTH_FIELD_END; ++i)
938 auto eField = static_cast<ToxAuthorityField>(i);
939 if (eField == AUTH_FIELD_URL)
941 if (GetSourceURL(pThis->GetAuthorField(AUTH_FIELD_URL))
942 != GetSourceURL(pOther->GetAuthorField(AUTH_FIELD_URL)))
944 return false;
946 continue;
949 if (pThis->GetAuthorField(eField) != pOther->GetAuthorField(eField))
951 return false;
955 return true;
958 bool SwTOXAuthority::sort_lt(const SwTOXSortTabBase& rBase)
960 bool bRet = false;
961 SwAuthorityField* pField = static_cast<SwAuthorityField*>(m_rField.GetField());
962 SwAuthorityFieldType* pType = static_cast<SwAuthorityFieldType*>(
963 pField->GetTyp());
964 if(pType->IsSortByDocument())
965 bRet = SwTOXSortTabBase::sort_lt(rBase);
966 else
968 SwAuthorityField* pCmpField =
969 static_cast<SwAuthorityField*>(static_cast<const SwTOXAuthority&>(rBase).m_rField.GetField());
971 for(sal_uInt16 i = 0; i < pType->GetSortKeyCount(); i++)
973 const SwTOXSortKey* pKey = pType->GetSortKey(i);
974 const TextAndReading aMy(pField->GetFieldText(pKey->eField), OUString());
975 const TextAndReading aOther(pCmpField->GetFieldText(pKey->eField), OUString());
977 sal_Int32 nComp = pTOXIntl->Compare( aMy, GetLocale(),
978 aOther, rBase.GetLocale() );
980 if( nComp )
982 bRet = (-1 == nComp) == pKey->bSortAscending;
983 break;
987 return bRet;
990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */