android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / fields / authfld.cxx
blob77b640739760699618dd42eac2a8ca05588dc022
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 <sal/config.h>
22 #include <memory>
24 #include <libxml/xmlwriter.h>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/string.hxx>
28 #include <i18nlangtag/languagetag.hxx>
29 #include <o3tl/any.hxx>
30 #include <o3tl/string_view.hxx>
31 #include <officecfg/Office/Common.hxx>
32 #include <osl/diagnose.h>
33 #include <tools/urlobj.hxx>
34 #include <swtypes.hxx>
35 #include <strings.hrc>
36 #include <authfld.hxx>
37 #include <expfld.hxx>
38 #include <pam.hxx>
39 #include <cntfrm.hxx>
40 #include <rootfrm.hxx>
41 #include <tox.hxx>
42 #include <txmsrt.hxx>
43 #include <fmtfld.hxx>
44 #include <txtfld.hxx>
45 #include <ndtxt.hxx>
46 #include <doc.hxx>
47 #include <IDocumentFieldsAccess.hxx>
48 #include <IDocumentLayoutAccess.hxx>
49 #include <unofldmid.h>
50 #include <unoprnms.hxx>
51 #include <docsh.hxx>
53 #include <com/sun/star/beans/PropertyValues.hpp>
54 #include <com/sun/star/uri/UriReferenceFactory.hpp>
56 using namespace ::com::sun::star::uno;
57 using namespace ::com::sun::star::beans;
58 using namespace ::com::sun::star::lang;
60 SwAuthEntry::SwAuthEntry(const SwAuthEntry& rCopy)
61 : SimpleReferenceObject()
63 for(int i = 0; i < AUTH_FIELD_END; ++i)
64 m_aAuthFields[i] = rCopy.m_aAuthFields[i];
67 bool SwAuthEntry::operator==(const SwAuthEntry& rComp) const
69 for(int i = 0; i < AUTH_FIELD_END; ++i)
70 if(m_aAuthFields[i] != rComp.m_aAuthFields[i])
71 return false;
72 return true;
75 SwAuthorityFieldType::SwAuthorityFieldType(SwDoc* pDoc)
76 : SwFieldType( SwFieldIds::TableOfAuthorities ),
77 m_pDoc(pDoc),
78 m_cPrefix('['),
79 m_cSuffix(']'),
80 m_bIsSequence(false),
81 m_bSortByDocument(true),
82 m_eLanguage(::GetAppLanguage())
86 SwAuthorityFieldType::~SwAuthorityFieldType()
90 std::unique_ptr<SwFieldType> SwAuthorityFieldType::Copy() const
92 return std::make_unique<SwAuthorityFieldType>(m_pDoc);
95 void SwAuthorityFieldType::RemoveField(const SwAuthEntry* pEntry)
97 for(SwAuthDataArr::size_type j = 0; j < m_DataArr.size(); ++j)
99 if(m_DataArr[j].get() == pEntry)
101 if (m_DataArr[j]->m_nCount <= 1)
103 m_DataArr.erase(m_DataArr.begin() + j);
104 //re-generate positions of the fields
105 DelSequenceArray();
107 return;
110 assert(false && "SwAuthorityFieldType::RemoveField: pEntry was not added previously");
113 SwAuthEntry* SwAuthorityFieldType::AddField(std::u16string_view rFieldContents)
115 rtl::Reference<SwAuthEntry> pEntry(new SwAuthEntry);
116 sal_Int32 nIdx{ 0 };
117 for( sal_Int32 i = 0; i < AUTH_FIELD_END; ++i )
118 pEntry->SetAuthorField( static_cast<ToxAuthorityField>(i),
119 OUString(o3tl::getToken(rFieldContents, 0, TOX_STYLE_DELIMITER, nIdx )));
121 for (const auto &rpTemp : m_DataArr)
123 if (*rpTemp == *pEntry)
125 return rpTemp.get();
129 //if it is a new Entry - insert
130 m_DataArr.push_back(std::move(pEntry));
131 //re-generate positions of the fields
132 DelSequenceArray();
133 return m_DataArr.back().get();
136 void SwAuthorityFieldType::GetAllEntryIdentifiers(
137 std::vector<OUString>& rToFill )const
139 for (const auto & rpTemp : m_DataArr)
141 rToFill.push_back(rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER));
145 SwAuthEntry* SwAuthorityFieldType::GetEntryByIdentifier(
146 std::u16string_view rIdentifier)const
148 for (const auto &rpTemp : m_DataArr)
150 if (rIdentifier == rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER))
152 return rpTemp.get();
155 return nullptr;
158 bool SwAuthorityFieldType::ChangeEntryContent(const SwAuthEntry* pNewEntry)
160 for (auto &rpTemp : m_DataArr)
162 if (rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER) ==
163 pNewEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER))
165 for(int i = 0; i < AUTH_FIELD_END; ++i)
167 rpTemp->SetAuthorField(static_cast<ToxAuthorityField>(i),
168 pNewEntry->GetAuthorField(static_cast<ToxAuthorityField>(i)));
170 return true;
173 return false;
176 /// appends a new entry (if new) and returns the copied entry
177 SwAuthEntry* SwAuthorityFieldType::AppendField( const SwAuthEntry& rInsert )
179 for( SwAuthDataArr::size_type nRet = 0; nRet < m_DataArr.size(); ++nRet )
181 if( *m_DataArr[ nRet ] == rInsert )
182 return m_DataArr[ nRet ].get();
185 //if it is a new Entry - insert
186 m_DataArr.push_back(new SwAuthEntry(rInsert));
187 return m_DataArr.back().get();
190 std::unique_ptr<SwTOXInternational> SwAuthorityFieldType::CreateTOXInternational() const
192 return std::make_unique<SwTOXInternational>(m_eLanguage, SwTOIOptions::NONE, m_sSortAlgorithm);
195 sal_uInt16 SwAuthorityFieldType::GetSequencePos(const SwAuthEntry* pAuthEntry,
196 SwRootFrame const*const pLayout)
198 //find the field in a sorted array of handles,
199 if(!m_SequArr.empty() && m_SequArr.size() != m_DataArr.size())
200 DelSequenceArray();
201 if(m_SequArr.empty())
203 IDocumentRedlineAccess const& rIDRA(m_pDoc->getIDocumentRedlineAccess());
204 std::unique_ptr<SwTOXInternational> pIntl = CreateTOXInternational();
205 // sw_redlinehide: need 2 arrays because the sorting may be different,
206 // if multiple fields refer to the same entry and first one is deleted
207 std::vector<std::unique_ptr<SwTOXSortTabBase>> aSortArr;
208 std::vector<std::unique_ptr<SwTOXSortTabBase>> aSortArrRLHidden;
209 std::vector<SwFormatField*> vFields;
210 GatherFields(vFields);
211 for(SwFormatField* pFormatField : vFields)
213 const SwTextField* pTextField = pFormatField->GetTextField();
214 if(!pTextField || !pTextField->GetpTextNode())
216 continue;
218 const SwTextNode& rFieldTextNode = pTextField->GetTextNode();
219 SwPosition aFieldPos(rFieldTextNode);
220 SwDoc& rDoc = const_cast<SwDoc&>(rFieldTextNode.GetDoc());
221 SwContentFrame *pFrame = rFieldTextNode.getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() );
222 const SwTextNode* pTextNode = nullptr;
223 if(pFrame && !pFrame->IsInDocBody())
224 pTextNode = GetBodyTextNode( rDoc, aFieldPos, *pFrame );
225 //if no text node could be found or the field is in the document
226 //body the directly available text node will be used
227 if(!pTextNode)
228 pTextNode = &rFieldTextNode;
229 if (pTextNode->GetText().isEmpty()
230 || !pTextNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
231 || !pTextNode->GetNodes().IsDocNodes())
233 continue;
235 auto const InsertImpl = [&pIntl, pTextNode, pFormatField]
236 (std::vector<std::unique_ptr<SwTOXSortTabBase>> & rSortArr)
238 std::unique_ptr<SwTOXAuthority> pNew(
239 new SwTOXAuthority(*pTextNode, *pFormatField, *pIntl));
241 for (size_t i = 0; i < rSortArr.size(); ++i)
243 SwTOXSortTabBase* pOld = rSortArr[i].get();
244 if (pOld->equivalent(*pNew))
246 //only the first occurrence in the document
247 //has to be in the array
248 if (pOld->sort_lt(*pNew))
249 pNew.reset();
250 else // remove the old content
251 rSortArr.erase(rSortArr.begin() + i);
252 break;
255 //if it still exists - insert at the correct position
256 if (pNew)
258 size_t j {0};
260 while (j < rSortArr.size())
262 SwTOXSortTabBase* pOld = rSortArr[j].get();
263 if (pNew->sort_lt(*pOld))
264 break;
265 ++j;
267 rSortArr.insert(rSortArr.begin() + j, std::move(pNew));
270 InsertImpl(aSortArr);
271 if (!sw::IsFieldDeletedInModel(rIDRA, *pTextField))
273 InsertImpl(aSortArrRLHidden);
277 for(auto & pBase : aSortArr)
279 SwFormatField& rFormatField = static_cast<SwTOXAuthority&>(*pBase).GetFieldFormat();
280 SwAuthorityField* pAField = static_cast<SwAuthorityField*>(rFormatField.GetField());
281 m_SequArr.push_back(pAField->GetAuthEntry());
283 for (auto & pBase : aSortArrRLHidden)
285 SwFormatField& rFormatField = static_cast<SwTOXAuthority&>(*pBase).GetFieldFormat();
286 SwAuthorityField* pAField = static_cast<SwAuthorityField*>(rFormatField.GetField());
287 m_SequArrRLHidden.push_back(pAField->GetAuthEntry());
290 //find nHandle
291 auto const& rSequArr(pLayout && pLayout->IsHideRedlines() ? m_SequArrRLHidden : m_SequArr);
292 for (std::vector<sal_IntPtr>::size_type i = 0; i < rSequArr.size(); ++i)
294 if (rSequArr[i] == pAuthEntry)
296 return i + 1;
299 return 0;
302 void SwAuthorityFieldType::QueryValue( Any& rVal, sal_uInt16 nWhichId ) const
304 switch( nWhichId )
306 case FIELD_PROP_PAR1:
307 case FIELD_PROP_PAR2:
309 OUString sVal;
310 sal_Unicode uRet = FIELD_PROP_PAR1 == nWhichId ? m_cPrefix : m_cSuffix;
311 if(uRet)
312 sVal = OUString(uRet);
313 rVal <<= sVal;
315 break;
316 case FIELD_PROP_PAR3:
317 rVal <<= GetSortAlgorithm();
318 break;
320 case FIELD_PROP_BOOL1:
321 rVal <<= m_bIsSequence;
322 break;
324 case FIELD_PROP_BOOL2:
325 rVal <<= m_bSortByDocument;
326 break;
328 case FIELD_PROP_LOCALE:
329 rVal <<= LanguageTag(GetLanguage()).getLocale();
330 break;
332 case FIELD_PROP_PROP_SEQ:
334 Sequence<PropertyValues> aRet(m_SortKeyArr.size());
335 PropertyValues* pValues = aRet.getArray();
336 for(SortKeyArr::size_type i = 0; i < m_SortKeyArr.size(); ++i)
338 const SwTOXSortKey* pKey = &m_SortKeyArr[i];
339 pValues[i].realloc(2);
340 PropertyValue* pValue = pValues[i].getArray();
341 pValue[0].Name = UNO_NAME_SORT_KEY;
342 pValue[0].Value <<= sal_Int16(pKey->eField);
343 pValue[1].Name = UNO_NAME_IS_SORT_ASCENDING;
344 pValue[1].Value <<= pKey->bSortAscending;
346 rVal <<= aRet;
348 break;
349 default:
350 assert(false);
354 void SwAuthorityFieldType::PutValue( const Any& rAny, sal_uInt16 nWhichId )
356 switch( nWhichId )
358 case FIELD_PROP_PAR1:
359 case FIELD_PROP_PAR2:
361 OUString sTmp;
362 rAny >>= sTmp;
363 const sal_Unicode uSet = !sTmp.isEmpty() ? sTmp[0] : 0;
364 if( FIELD_PROP_PAR1 == nWhichId )
365 m_cPrefix = uSet;
366 else
367 m_cSuffix = uSet;
369 break;
370 case FIELD_PROP_PAR3:
372 OUString sTmp;
373 rAny >>= sTmp;
374 SetSortAlgorithm(sTmp);
375 break;
377 case FIELD_PROP_BOOL1:
378 m_bIsSequence = *o3tl::doAccess<bool>(rAny);
379 break;
380 case FIELD_PROP_BOOL2:
381 m_bSortByDocument = *o3tl::doAccess<bool>(rAny);
382 break;
384 case FIELD_PROP_LOCALE:
386 css::lang::Locale aLocale;
387 if( rAny >>= aLocale )
388 SetLanguage( LanguageTag::convertToLanguageType( aLocale ));
390 break;
392 case FIELD_PROP_PROP_SEQ:
394 Sequence<PropertyValues> aSeq;
395 if( rAny >>= aSeq )
397 m_SortKeyArr.clear();
398 const PropertyValues* pValues = aSeq.getConstArray();
399 //TODO: Limiting to the first SAL_MAX_UINT16 elements of aSeq so that size of
400 // m_SortKeyArr remains in range of sal_uInt16, as GetSortKeyCount and GetSortKey
401 // still expect m_SortKeyArr to be indexed by sal_uInt16:
402 auto nSize = std::min<sal_Int32>(aSeq.getLength(), SAL_MAX_UINT16);
403 for(sal_Int32 i = 0; i < nSize; i++)
405 SwTOXSortKey aSortKey;
406 for(const PropertyValue& rValue : pValues[i])
408 if(rValue.Name == UNO_NAME_SORT_KEY)
410 sal_Int16 nVal = -1; rValue.Value >>= nVal;
411 if(nVal >= 0 && nVal < AUTH_FIELD_END)
412 aSortKey.eField = static_cast<ToxAuthorityField>(nVal);
414 else if(rValue.Name == UNO_NAME_IS_SORT_ASCENDING)
416 aSortKey.bSortAscending = *o3tl::doAccess<bool>(rValue.Value);
419 m_SortKeyArr.push_back(aSortKey);
423 break;
424 default:
425 assert(false);
429 void SwAuthorityFieldType::SwClientNotify(const SwModify&, const SfxHint& rHint)
431 //re-generate positions of the fields
432 DelSequenceArray();
433 CallSwClientNotify(rHint);
436 sal_uInt16 SwAuthorityFieldType::GetSortKeyCount() const
438 return m_SortKeyArr.size();
441 const SwTOXSortKey* SwAuthorityFieldType::GetSortKey(sal_uInt16 nIdx) const
443 if(m_SortKeyArr.size() > nIdx)
444 return &m_SortKeyArr[nIdx];
445 OSL_FAIL("Sort key not found");
446 return nullptr;
449 void SwAuthorityFieldType::SetSortKeys(sal_uInt16 nKeyCount, SwTOXSortKey const aKeys[])
451 m_SortKeyArr.clear();
452 for(sal_uInt16 i = 0; i < nKeyCount; i++)
453 if(aKeys[i].eField < AUTH_FIELD_END)
454 m_SortKeyArr.push_back(aKeys[i]);
457 SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
458 std::u16string_view rFieldContents )
459 : SwField(pInitType)
460 , m_nTempSequencePos( -1 )
461 , m_nTempSequencePosRLHidden( -1 )
463 m_xAuthEntry = pInitType->AddField( rFieldContents );
466 SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
467 SwAuthEntry* pAuthEntry )
468 : SwField( pInitType )
469 , m_xAuthEntry( pAuthEntry )
470 , m_nTempSequencePos( -1 )
471 , m_nTempSequencePosRLHidden( -1 )
475 SwAuthorityField::~SwAuthorityField()
477 static_cast<SwAuthorityFieldType* >(GetTyp())->RemoveField(m_xAuthEntry.get());
480 OUString SwAuthorityField::ExpandImpl(SwRootFrame const*const pLayout) const
482 return ConditionalExpandAuthIdentifier(pLayout);
485 OUString SwAuthorityField::ConditionalExpandAuthIdentifier(
486 SwRootFrame const*const pLayout) const
488 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
489 OUString sRet;
490 if(pAuthType->GetPrefix())
491 sRet = OUString(pAuthType->GetPrefix());
493 if( pAuthType->IsSequence() )
495 sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines()
496 ? m_nTempSequencePosRLHidden : m_nTempSequencePos);
497 if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked())
498 rnTempSequencePos = pAuthType->GetSequencePos(m_xAuthEntry.get(), pLayout);
499 if (0 <= rnTempSequencePos)
500 sRet += OUString::number(rnTempSequencePos);
502 else
504 //TODO: Expand to: identifier, number sequence, ...
505 if(m_xAuthEntry)
507 OUString sIdentifier(m_xAuthEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER));
508 // tdf#107784 Use title if it's a ooxml citation
509 if (o3tl::starts_with(o3tl::trim(sIdentifier), u"CITATION"))
510 return m_xAuthEntry->GetAuthorField(AUTH_FIELD_TITLE);
511 else
512 sRet += sIdentifier;
515 if(pAuthType->GetSuffix())
516 sRet += OUStringChar(pAuthType->GetSuffix());
517 return sRet;
520 OUString SwAuthorityField::ExpandCitation(ToxAuthorityField eField,
521 SwRootFrame const*const pLayout) const
523 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
524 OUString sRet;
526 if( pAuthType->IsSequence() )
528 sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines()
529 ? m_nTempSequencePosRLHidden : m_nTempSequencePos);
530 if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked())
531 rnTempSequencePos = pAuthType->GetSequencePos(m_xAuthEntry.get(), pLayout);
532 if (0 <= rnTempSequencePos)
533 sRet += OUString::number(rnTempSequencePos);
535 else
537 //TODO: Expand to: identifier, number sequence, ...
538 if(m_xAuthEntry)
539 sRet += m_xAuthEntry->GetAuthorField(eField);
541 return sRet;
544 std::unique_ptr<SwField> SwAuthorityField::Copy() const
546 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
547 return std::make_unique<SwAuthorityField>(pAuthType, m_xAuthEntry.get());
550 const OUString & SwAuthorityField::GetFieldText(ToxAuthorityField eField) const
552 return m_xAuthEntry->GetAuthorField( eField );
555 void SwAuthorityField::SetPar1(const OUString& rStr)
557 SwAuthorityFieldType* pInitType = static_cast<SwAuthorityFieldType* >(GetTyp());
558 pInitType->RemoveField(m_xAuthEntry.get());
559 m_xAuthEntry = pInitType->AddField(rStr);
562 OUString SwAuthorityField::GetDescription() const
564 return SwResId(STR_AUTHORITY_ENTRY);
567 OUString SwAuthorityField::GetAuthority(const SwRootFrame* pLayout, const SwForm* pTOX) const
569 OUString aText;
571 std::unique_ptr<SwForm> pDefaultTOX;
572 if (!pTOX)
574 pDefaultTOX = std::make_unique<SwForm>(TOX_AUTHORITIES);
575 pTOX = pDefaultTOX.get();
578 SwAuthorityFieldType* pFieldType = static_cast<SwAuthorityFieldType*>(GetTyp());
579 std::unique_ptr<SwTOXInternational> pIntl(pFieldType->CreateTOXInternational());
581 // This is based on SwTOXAuthority::GetLevel()
582 OUString sText = GetFieldText(AUTH_FIELD_AUTHORITY_TYPE);
583 ToxAuthorityType nAuthorityKind = AUTH_TYPE_ARTICLE;
584 if (pIntl->IsNumeric(sText))
585 nAuthorityKind = static_cast<ToxAuthorityType>(sText.toUInt32());
586 if (nAuthorityKind > AUTH_TYPE_END)
587 nAuthorityKind = AUTH_TYPE_ARTICLE;
589 // Must be incremented by 1, since the pattern 0 is for the heading
590 const SwFormTokens& aPattern = pTOX->GetPattern(static_cast<int>(nAuthorityKind) + 1);
592 for (const auto& rToken : aPattern)
594 switch (rToken.eTokenType)
596 case TOKEN_TAB_STOP:
598 aText += "\t";
599 break;
601 case TOKEN_TEXT:
603 aText += rToken.sText;
604 break;
606 case TOKEN_AUTHORITY:
608 ToxAuthorityField eField = static_cast<ToxAuthorityField>(rToken.nAuthorityField);
610 if (AUTH_FIELD_IDENTIFIER == eField)
612 // Why isn't there a way to get the identifier without parentheses???
613 OUString sTmp = ExpandField(true, pLayout);
614 if (sal_Unicode cPref = pFieldType->GetPrefix(); cPref && cPref != ' ')
615 sTmp = sTmp.copy(1);
616 if (sal_Unicode cSuff = pFieldType->GetSuffix(); cSuff && cSuff != ' ')
617 sTmp = sTmp.copy(0, sTmp.getLength() - 1);
618 aText += sTmp;
620 else if (AUTH_FIELD_AUTHORITY_TYPE == eField)
622 aText += SwAuthorityFieldType::GetAuthTypeName(nAuthorityKind);
624 else if (AUTH_FIELD_URL == eField)
626 aText += GetURI(true);
628 else
630 aText += GetFieldText(eField);
632 break;
634 default:
635 break;
639 return aText;
642 SwAuthorityField::TargetType SwAuthorityField::GetTargetType() const
644 return SwAuthorityField::TargetType(GetAuthEntry()->GetAuthorField(AUTH_FIELD_TARGET_TYPE).toInt32());
647 OUString SwAuthorityField::GetAbsoluteURL() const
649 const OUString& rURL = GetAuthEntry()->GetAuthorField(
650 GetTargetType() == SwAuthorityField::TargetType::UseDisplayURL
651 ? AUTH_FIELD_URL : AUTH_FIELD_TARGET_URL);
652 SwDoc* pDoc = static_cast<SwAuthorityFieldType*>(GetTyp())->GetDoc();
653 SwDocShell* pDocShell = pDoc->GetDocShell();
654 OUString aBasePath = pDocShell->getDocumentBaseURL();
655 return INetURLObject::GetAbsURL(aBasePath, rURL, INetURLObject::EncodeMechanism::WasEncoded,
656 INetURLObject::DecodeMechanism::WithCharset);
659 OUString SwAuthorityField::GetURI(bool bRelative) const
661 OUString sTmp = GetFieldText(AUTH_FIELD_URL);
663 SwDoc* pDoc = static_cast<SwAuthorityFieldType*>(GetTyp())->GetDoc();
664 SwDocShell* pDocShell = pDoc->GetDocShell();
665 const OUString aBaseURL = pDocShell->getDocumentBaseURL();
666 std::u16string_view aBaseURIScheme;
667 sal_Int32 nSep = aBaseURL.indexOf(':');
668 if (nSep != -1)
670 aBaseURIScheme = aBaseURL.subView(0, nSep);
673 uno::Reference<uri::XUriReferenceFactory> xUriReferenceFactory
674 = uri::UriReferenceFactory::create(comphelper::getProcessComponentContext());
675 uno::Reference<uri::XUriReference> xUriRef;
678 xUriRef = xUriReferenceFactory->parse(sTmp);
680 catch (const uno::Exception& rException)
682 SAL_WARN("sw.core",
683 "SwTOXAuthority::GetSourceURL: failed to parse url: " << rException.Message);
685 if (xUriRef.is() && xUriRef->getFragment().startsWith("page="))
687 xUriRef->clearFragment();
688 sTmp = xUriRef->getUriReference();
691 // If the URI is not supposed to be relative, we return here the full URI
692 if (!bRelative)
693 return sTmp;
695 bool bSaveRelFSys = officecfg::Office::Common::Save::URL::FileSystem::get();
696 if (xUriRef.is() && bSaveRelFSys && xUriRef->getScheme() == aBaseURIScheme)
698 sTmp = INetURLObject::GetRelURL(aBaseURL, sTmp);
700 return sTmp;
703 void SwAuthorityField::dumpAsXml(xmlTextWriterPtr pWriter) const
705 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwAuthorityField"));
706 SwField::dumpAsXml(pWriter);
708 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_xAuthEntry"));
709 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", m_xAuthEntry.get());
710 if (m_xAuthEntry.is())
712 m_xAuthEntry->dumpAsXml(pWriter);
714 (void)xmlTextWriterEndElement(pWriter);
715 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_nTempSequencePos"));
716 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
717 BAD_CAST(OString::number(m_nTempSequencePos).getStr()));
718 (void)xmlTextWriterEndElement(pWriter);
719 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_nTempSequencePosRLHidden"));
720 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"),
721 BAD_CAST(OString::number(m_nTempSequencePosRLHidden).getStr()));
722 (void)xmlTextWriterEndElement(pWriter);
724 (void)xmlTextWriterEndElement(pWriter);
727 const char* const aFieldNames[] =
729 "Identifier",
730 "BibiliographicType",
731 "Address",
732 "Annote",
733 "Author",
734 "Booktitle",
735 "Chapter",
736 "Edition",
737 "Editor",
738 "Howpublished",
739 "Institution",
740 "Journal",
741 "Month",
742 "Note",
743 "Number",
744 "Organizations",
745 "Pages",
746 "Publisher",
747 "School",
748 "Series",
749 "Title",
750 "Report_Type",
751 "Volume",
752 "Year",
753 "URL",
754 "Custom1",
755 "Custom2",
756 "Custom3",
757 "Custom4",
758 "Custom5",
759 "ISBN",
760 "LocalURL",
761 "TargetType",
762 "TargetURL",
765 void SwAuthEntry::dumpAsXml(xmlTextWriterPtr pWriter) const
767 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwAuthEntry"));
769 for (int i = 0; i < AUTH_FIELD_END; ++i)
771 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("m_aAuthField"));
772 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("key"), BAD_CAST(aFieldNames[i]));
773 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("value"), BAD_CAST(m_aAuthFields[i].toUtf8().getStr()));
774 (void)xmlTextWriterEndElement(pWriter);
777 (void)xmlTextWriterEndElement(pWriter);
780 bool SwAuthorityField::QueryValue( Any& rAny, sal_uInt16 /*nWhichId*/ ) const
782 if(!GetTyp())
783 return false;
784 if(!m_xAuthEntry)
785 return false;
786 Sequence <PropertyValue> aRet(AUTH_FIELD_END);
787 PropertyValue* pValues = aRet.getArray();
788 for(int i = 0; i < AUTH_FIELD_END; ++i)
790 pValues[i].Name = OUString::createFromAscii(aFieldNames[i]);
791 const OUString& sField = m_xAuthEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
792 if(i == AUTH_FIELD_AUTHORITY_TYPE)
793 pValues[i].Value <<= sal_Int16(sField.toInt32());
794 else
795 pValues[i].Value <<= sField;
797 rAny <<= aRet;
798 /* FIXME: it is weird that we always return false here */
799 return false;
802 static sal_Int32 lcl_Find(std::u16string_view rFieldName)
804 for(sal_Int32 i = 0; i < AUTH_FIELD_END; ++i)
805 if(o3tl::equalsAscii(rFieldName, aFieldNames[i]))
806 return i;
807 return -1;
810 bool SwAuthorityField::PutValue( const Any& rAny, sal_uInt16 /*nWhichId*/ )
812 if(!GetTyp() || !m_xAuthEntry)
813 return false;
815 Sequence <PropertyValue> aParam;
816 if(!(rAny >>= aParam))
817 return false;
819 OUStringBuffer sBuf(+(AUTH_FIELD_END - 1));
820 comphelper::string::padToLength(sBuf, (AUTH_FIELD_END - 1), TOX_STYLE_DELIMITER);
821 OUString sToSet(sBuf.makeStringAndClear());
822 for(const PropertyValue& rParam : std::as_const(aParam))
824 const sal_Int32 nFound = lcl_Find(rParam.Name);
825 if(nFound >= 0)
827 OUString sContent;
828 if(AUTH_FIELD_AUTHORITY_TYPE == nFound)
830 sal_Int16 nVal = 0;
831 rParam.Value >>= nVal;
832 sContent = OUString::number(nVal);
834 else
835 rParam.Value >>= sContent;
836 sToSet = comphelper::string::setToken(sToSet, nFound, TOX_STYLE_DELIMITER, sContent);
840 static_cast<SwAuthorityFieldType*>(GetTyp())->RemoveField(m_xAuthEntry.get());
841 m_xAuthEntry = static_cast<SwAuthorityFieldType*>(GetTyp())->AddField(sToSet);
843 /* FIXME: it is weird that we always return false here */
844 return false;
847 SwFieldType* SwAuthorityField::ChgTyp( SwFieldType* pFieldTyp )
849 SwAuthorityFieldType* pSrcTyp = static_cast<SwAuthorityFieldType*>(GetTyp()),
850 * pDstTyp = static_cast<SwAuthorityFieldType*>(pFieldTyp);
851 if( pSrcTyp != pDstTyp )
853 const SwAuthEntry* pSrcEntry = m_xAuthEntry.get();
854 m_xAuthEntry = pDstTyp->AppendField( *pSrcEntry );
855 pSrcTyp->RemoveField( pSrcEntry );
856 SwField::ChgTyp( pFieldTyp );
858 return pSrcTyp;
861 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */