1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
29 #include <IDocumentLayoutAccess.hxx>
30 #include <IDocumentMarkAccess.hxx>
33 #include <rootfrm.hxx>
34 #include <modeltoviewhelper.hxx>
37 #include <txttxmrk.hxx>
42 #include <swtable.hxx>
44 #include <authfld.hxx>
45 #include <toxwrap.hxx>
47 #include <strings.hrc>
52 using namespace ::com::sun::star
;
53 using namespace ::com::sun::star::uno
;
56 SwTOIOptions
SwTOXSortTabBase::nOpt
= SwTOIOptions::NONE
;
58 SwTOXInternational::SwTOXInternational( LanguageType nLang
, SwTOIOptions nOpt
,
59 OUString aSortAlgorithm
) :
61 m_sSortAlgorithm(std::move(aSortAlgorithm
)),
67 SwTOXInternational::SwTOXInternational( const SwTOXInternational
& rIntl
) :
68 m_eLang( rIntl
.m_eLang
),
69 m_sSortAlgorithm(rIntl
.m_sSortAlgorithm
),
70 m_nOptions( rIntl
.m_nOptions
)
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 );
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 )
151 n
= pTextMark
->GetStart();
152 SwTOXSource
aTmp( pNd
, n
, pTextMark
&& pTextMark
->GetTOXMark().IsMainEntry() );
153 aTOXSources
.push_back(aTmp
);
155 nPos
= pNd
->GetIndex();
159 case TOX_SORT_CONTENT
:
162 // If they are in a special areas, we should get the position at the
164 if( nPos
< pNd
->GetNodes().GetEndOfExtras().GetIndex() )
166 // Then get the 'anchor' (body) position
168 std::pair
<Point
, bool> tmp(aPt
, false);
169 const SwContentFrame
*const pFrame
= pNd
->getLayoutFrame(
170 pNd
->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout(),
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();
189 std::pair
<OUString
, bool> SwTOXSortTabBase::GetURL(SwRootFrame
const*const pLayout
) const
192 SwTOXType
const& rType(*pTextMark
->GetTOXMark().GetTOXType());
193 switch (rType
.GetType())
202 typeName
= "U" + rType
.GetTypeName();
205 assert(false); // other tox can't have toxmarks as source
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
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();
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() );
253 bool SwTOXSortTabBase::sort_lt(const SwTOXSortTabBase
& rCmp
)
255 if( nPos
< rCmp
.nPos
)
258 if( nPos
== rCmp
.nPos
)
260 if( nCntPos
< rCmp
.nCntPos
)
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() )
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
)
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
);
301 // Sorted keyword entry
302 SwTOXIndex::SwTOXIndex( const SwTextNode
& rNd
,
303 const SwTextTOXMark
* pMark
, SwTOIOptions nOptions
,
305 const SwTOXInternational
& rIntl
,
306 const lang::Locale
& rLocale
)
307 : SwTOXSortTabBase( TOX_SORT_INDEX
, &rNd
, pMark
, &rIntl
, &rLocale
),
310 nPos
= rNd
.GetIndex();
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
)
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
;
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
;
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();
370 case FORM_PRIMARY_KEY
:
372 aRet
.sText
= rTOXMark
.GetPrimaryKey();
373 aRet
.sReading
= rTOXMark
.GetPrimaryKeyReading();
376 case FORM_SECONDARY_KEY
:
378 aRet
.sText
= rTOXMark
.GetSecondaryKey();
379 aRet
.sReading
= rTOXMark
.GetSecondaryKeyReading();
384 aRet
.sText
= rTOXMark
.GetText(pLayout
);
385 aRet
.sReading
= rTOXMark
.GetTextReading();
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);
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();
405 if( pEnd
&& !pTextMark
->GetTOXMark().IsAlternativeText() &&
406 !(GetOptions() & SwTOIOptions::KeyAsEntry
))
408 aRet
.sText
= static_cast<const SwTextNode
*>(aTOXSources
[0].pNd
)->GetExpandText(
410 pTextMark
->GetStart(),
411 *pEnd
- pTextMark
->GetStart(),
413 ExpandMode::ExpandFootnote
414 | (pLayout
&& pLayout
->IsHideRedlines()
415 ? ExpandMode::HideDeletions
417 if(SwTOIOptions::InitialCaps
& nOpt
&& pTOXIntl
&& !aRet
.sText
.isEmpty())
419 aRet
.sText
= pTOXIntl
->ToUpper( aRet
.sText
, 0 ) + aRet
.sText
.subView(1);
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() )
445 SwTOXCustom::SwTOXCustom(TextAndReading aKey
,
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
473 TextAndReading
SwTOXCustom::GetText_Impl(SwRootFrame
const*const) const
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(
495 pTextMark
->GetStart(),
496 *pEnd
- pTextMark
->GetStart(),
498 ExpandMode::ExpandFootnote
499 | (pLayout
&& pLayout
->IsHideRedlines()
500 ? ExpandMode::HideDeletions
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
);
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 ),
540 m_sSequenceName(std::move( sSeqName
))
542 // tdf#123313 create any missing bookmarks *before* generating ToX nodes!
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
);
556 TextAndReading
SwTOXPara::GetText_Impl(SwRootFrame
const*const pLayout
) const
558 const SwContentNode
* pNd
= aTOXSources
[0].pNd
;
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(
568 nEndIndex
== -1 ? -1 : nEndIndex
- nStartIndex
,
570 pLayout
&& pLayout
->IsHideRedlines()
571 ? ExpandMode::HideDeletions
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
),
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();
595 return TextAndReading(pFly
->GetName(), OUString());
597 OSL_ENSURE( false, "Graphic/object without name" );
598 TranslateId pId
= SwTOXElement::Ole
== eType
600 : SwTOXElement::Graphic
== eType
601 ? STR_GRAPHIC_DEFNAME
603 return TextAndReading(SwResId(pId
), OUString());
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 );
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 );
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();
672 nRet
= o3tl::narrowing
<sal_uInt16
>(nTmp
);
677 std::pair
<OUString
, bool> SwTOXPara::GetURL(SwRootFrame
const*const) const
680 const SwContentNode
* pNd
= aTOXSources
[0].pNd
;
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(
693 IDocumentMarkAccess::MarkType::CROSSREF_HEADING_BOOKMARK
);
694 aText
= "#" + pMark
->GetName();
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();
706 aText
= "#" + pFly
->GetName() + OUStringChar(cMarkSeparator
);
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;
716 aText
+= OUString::createFromAscii( pStr
);
720 case SwTOXElement::Sequence
:
722 aText
= "#" + m_sSequenceName
+ OUStringChar(cMarkSeparator
)
728 return std::make_pair(aText
, false);
731 bool SwTOXPara::IsFullPara() const
735 case SwTOXElement::Sequence
:
736 case SwTOXElement::Template
:
737 case SwTOXElement::OutlineLevel
:
738 return nStartIndex
== 0 && nEndIndex
== -1;
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
;
756 const SwTableNode
* pTableNd
=
757 pNd
->FindTableNode();
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
773 std::pair
<OUString
, bool> SwTOXTable::GetURL(SwRootFrame
const*const) const
775 const SwNode
* pNd
= aTOXSources
[0].pNd
;
777 return std::make_pair(OUString(), false);
779 pNd
= pNd
->FindTableNode();
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
),
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
804 if( pTOXIntl
->IsNumeric( sText
) )
806 nRet
= sText
.toUInt32();
809 //illegal values are also set to 'ARTICLE' as non-numeric values are
810 if(nRet
> AUTH_TYPE_END
)
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());
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();
844 sText
= SwAuthorityFieldType::GetAuthTypeName(static_cast<ToxAuthorityType
>(--nLevel
));
847 sText
= pField
->GetFieldText(static_cast<ToxAuthorityField
>(nAuthField
));
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
)
865 "SwTOXAuthority::GetSourceURL: failed to parse url: " << rException
.Message
);
867 if (xUriRef
.is() && xUriRef
->getFragment().startsWith("page="))
869 xUriRef
->clearFragment();
870 aText
= xUriRef
->getUriReference();
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(':');
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
)
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
)
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())
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
)))
949 if (pThis
->GetAuthorField(eField
) != pOther
->GetAuthorField(eField
))
958 bool SwTOXAuthority::sort_lt(const SwTOXSortTabBase
& rBase
)
961 SwAuthorityField
* pField
= static_cast<SwAuthorityField
*>(m_rField
.GetField());
962 SwAuthorityFieldType
* pType
= static_cast<SwAuthorityFieldType
*>(
964 if(pType
->IsSortByDocument())
965 bRet
= SwTOXSortTabBase::sort_lt(rBase
);
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() );
982 bRet
= (-1 == nComp
) == pKey
->bSortAscending
;
990 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */