nss: upgrade to release 3.73
[LibreOffice.git] / sw / source / core / fields / authfld.cxx
blobd922c1269584cb1f7a2067f77e8f1a4d3d8100d0
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 <memory>
21 #include <comphelper/string.hxx>
22 #include <i18nlangtag/languagetag.hxx>
23 #include <o3tl/any.hxx>
24 #include <swtypes.hxx>
25 #include <strings.hrc>
26 #include <authfld.hxx>
27 #include <expfld.hxx>
28 #include <pam.hxx>
29 #include <cntfrm.hxx>
30 #include <rootfrm.hxx>
31 #include <tox.hxx>
32 #include <txmsrt.hxx>
33 #include <fmtfld.hxx>
34 #include <txtfld.hxx>
35 #include <ndtxt.hxx>
36 #include <doc.hxx>
37 #include <IDocumentFieldsAccess.hxx>
38 #include <IDocumentLayoutAccess.hxx>
39 #include <unofldmid.h>
40 #include <unoprnms.hxx>
41 #include <calbck.hxx>
43 #include <com/sun/star/beans/PropertyValues.hpp>
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::beans;
47 using namespace ::com::sun::star::lang;
49 SwAuthEntry::SwAuthEntry(const SwAuthEntry& rCopy)
50 : SimpleReferenceObject()
52 for(int i = 0; i < AUTH_FIELD_END; ++i)
53 m_aAuthFields[i] = rCopy.m_aAuthFields[i];
56 bool SwAuthEntry::operator==(const SwAuthEntry& rComp) const
58 for(int i = 0; i < AUTH_FIELD_END; ++i)
59 if(m_aAuthFields[i] != rComp.m_aAuthFields[i])
60 return false;
61 return true;
64 SwAuthorityFieldType::SwAuthorityFieldType(SwDoc* pDoc)
65 : SwFieldType( SwFieldIds::TableOfAuthorities ),
66 m_pDoc(pDoc),
67 m_cPrefix('['),
68 m_cSuffix(']'),
69 m_bIsSequence(false),
70 m_bSortByDocument(true),
71 m_eLanguage(::GetAppLanguage())
75 SwAuthorityFieldType::~SwAuthorityFieldType()
79 std::unique_ptr<SwFieldType> SwAuthorityFieldType::Copy() const
81 return std::make_unique<SwAuthorityFieldType>(m_pDoc);
84 void SwAuthorityFieldType::RemoveField(const SwAuthEntry* pEntry)
86 for(SwAuthDataArr::size_type j = 0; j < m_DataArr.size(); ++j)
88 if(m_DataArr[j].get() == pEntry)
90 if (m_DataArr[j]->m_nCount <= 1)
92 m_DataArr.erase(m_DataArr.begin() + j);
93 //re-generate positions of the fields
94 DelSequenceArray();
96 return;
99 assert(false);
100 OSL_FAIL("Field unknown" );
103 SwAuthEntry* SwAuthorityFieldType::AddField(const OUString& rFieldContents)
105 rtl::Reference<SwAuthEntry> pEntry(new SwAuthEntry);
106 sal_Int32 nIdx{ 0 };
107 for( sal_Int32 i = 0; i < AUTH_FIELD_END; ++i )
108 pEntry->SetAuthorField( static_cast<ToxAuthorityField>(i),
109 rFieldContents.getToken( 0, TOX_STYLE_DELIMITER, nIdx ));
111 for (auto &rpTemp : m_DataArr)
113 if (*rpTemp == *pEntry)
115 return rpTemp.get();
119 //if it is a new Entry - insert
120 m_DataArr.push_back(std::move(pEntry));
121 //re-generate positions of the fields
122 DelSequenceArray();
123 return m_DataArr.back().get();
126 void SwAuthorityFieldType::GetAllEntryIdentifiers(
127 std::vector<OUString>& rToFill )const
129 for (const auto & rpTemp : m_DataArr)
131 rToFill.push_back(rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER));
135 SwAuthEntry* SwAuthorityFieldType::GetEntryByIdentifier(
136 const OUString& rIdentifier)const
138 for (const auto &rpTemp : m_DataArr)
140 if (rIdentifier == rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER))
142 return rpTemp.get();
145 return nullptr;
148 bool SwAuthorityFieldType::ChangeEntryContent(const SwAuthEntry* pNewEntry)
150 for (auto &rpTemp : m_DataArr)
152 if (rpTemp->GetAuthorField(AUTH_FIELD_IDENTIFIER) ==
153 pNewEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER))
155 for(int i = 0; i < AUTH_FIELD_END; ++i)
157 rpTemp->SetAuthorField(static_cast<ToxAuthorityField>(i),
158 pNewEntry->GetAuthorField(static_cast<ToxAuthorityField>(i)));
160 return true;
163 return false;
166 /// appends a new entry (if new) and returns the array position
167 sal_uInt16 SwAuthorityFieldType::AppendField( const SwAuthEntry& rInsert )
169 for( SwAuthDataArr::size_type nRet = 0; nRet < m_DataArr.size(); ++nRet )
171 if( *m_DataArr[ nRet ] == rInsert )
172 return nRet;
175 //if it is a new Entry - insert
176 m_DataArr.push_back(new SwAuthEntry(rInsert));
177 return m_DataArr.size()-1;
180 sal_uInt16 SwAuthorityFieldType::GetSequencePos(const SwAuthEntry* pAuthEntry,
181 SwRootFrame const*const pLayout)
183 //find the field in a sorted array of handles,
184 if(!m_SequArr.empty() && m_SequArr.size() != m_DataArr.size())
185 DelSequenceArray();
186 if(m_SequArr.empty())
188 IDocumentRedlineAccess const& rIDRA(m_pDoc->getIDocumentRedlineAccess());
189 SwTOXInternational aIntl(m_eLanguage, SwTOIOptions::NONE, m_sSortAlgorithm);
190 // sw_redlinehide: need 2 arrays because the sorting may be different,
191 // if multiple fields refer to the same entry and first one is deleted
192 std::vector<std::unique_ptr<SwTOXSortTabBase>> aSortArr;
193 std::vector<std::unique_ptr<SwTOXSortTabBase>> aSortArrRLHidden;
194 std::vector<SwFormatField*> vFields;
195 GatherFields(vFields);
196 for(SwFormatField* pFormatField : vFields)
198 const SwTextField* pTextField = pFormatField->GetTextField();
199 if(!pTextField || !pTextField->GetpTextNode())
201 continue;
203 const SwTextNode& rFieldTextNode = pTextField->GetTextNode();
204 SwPosition aFieldPos(rFieldTextNode);
205 SwDoc& rDoc = const_cast<SwDoc&>(rFieldTextNode.GetDoc());
206 SwContentFrame *pFrame = rFieldTextNode.getLayoutFrame( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() );
207 const SwTextNode* pTextNode = nullptr;
208 if(pFrame && !pFrame->IsInDocBody())
209 pTextNode = GetBodyTextNode( rDoc, aFieldPos, *pFrame );
210 //if no text node could be found or the field is in the document
211 //body the directly available text node will be used
212 if(!pTextNode)
213 pTextNode = &rFieldTextNode;
214 if (pTextNode->GetText().isEmpty()
215 || !pTextNode->getLayoutFrame(rDoc.getIDocumentLayoutAccess().GetCurrentLayout())
216 || !pTextNode->GetNodes().IsDocNodes())
218 continue;
220 auto const InsertImpl = [&aIntl, pTextNode, pFormatField]
221 (std::vector<std::unique_ptr<SwTOXSortTabBase>> & rSortArr)
223 std::unique_ptr<SwTOXAuthority> pNew(
224 new SwTOXAuthority(*pTextNode, *pFormatField, aIntl));
226 for (size_t i = 0; i < rSortArr.size(); ++i)
228 SwTOXSortTabBase* pOld = rSortArr[i].get();
229 if (pOld->equivalent(*pNew))
231 //only the first occurrence in the document
232 //has to be in the array
233 if (pOld->sort_lt(*pNew))
234 pNew.reset();
235 else // remove the old content
236 rSortArr.erase(rSortArr.begin() + i);
237 break;
240 //if it still exists - insert at the correct position
241 if (pNew)
243 size_t j {0};
245 while (j < rSortArr.size())
247 SwTOXSortTabBase* pOld = rSortArr[j].get();
248 if (pNew->sort_lt(*pOld))
249 break;
250 ++j;
252 rSortArr.insert(rSortArr.begin() + j, std::move(pNew));
255 InsertImpl(aSortArr);
256 if (!sw::IsFieldDeletedInModel(rIDRA, *pTextField))
258 InsertImpl(aSortArrRLHidden);
262 for(auto & pBase : aSortArr)
264 SwFormatField& rFormatField = static_cast<SwTOXAuthority&>(*pBase).GetFieldFormat();
265 SwAuthorityField* pAField = static_cast<SwAuthorityField*>(rFormatField.GetField());
266 m_SequArr.push_back(pAField->GetAuthEntry());
268 for (auto & pBase : aSortArrRLHidden)
270 SwFormatField& rFormatField = static_cast<SwTOXAuthority&>(*pBase).GetFieldFormat();
271 SwAuthorityField* pAField = static_cast<SwAuthorityField*>(rFormatField.GetField());
272 m_SequArrRLHidden.push_back(pAField->GetAuthEntry());
275 //find nHandle
276 auto const& rSequArr(pLayout && pLayout->IsHideRedlines() ? m_SequArrRLHidden : m_SequArr);
277 for (std::vector<sal_IntPtr>::size_type i = 0; i < rSequArr.size(); ++i)
279 if (rSequArr[i] == pAuthEntry)
281 return i + 1;
284 return 0;
287 void SwAuthorityFieldType::QueryValue( Any& rVal, sal_uInt16 nWhichId ) const
289 switch( nWhichId )
291 case FIELD_PROP_PAR1:
292 case FIELD_PROP_PAR2:
294 OUString sVal;
295 sal_Unicode uRet = FIELD_PROP_PAR1 == nWhichId ? m_cPrefix : m_cSuffix;
296 if(uRet)
297 sVal = OUString(uRet);
298 rVal <<= sVal;
300 break;
301 case FIELD_PROP_PAR3:
302 rVal <<= GetSortAlgorithm();
303 break;
305 case FIELD_PROP_BOOL1:
306 rVal <<= m_bIsSequence;
307 break;
309 case FIELD_PROP_BOOL2:
310 rVal <<= m_bSortByDocument;
311 break;
313 case FIELD_PROP_LOCALE:
314 rVal <<= LanguageTag(GetLanguage()).getLocale();
315 break;
317 case FIELD_PROP_PROP_SEQ:
319 Sequence<PropertyValues> aRet(m_SortKeyArr.size());
320 PropertyValues* pValues = aRet.getArray();
321 for(SortKeyArr::size_type i = 0; i < m_SortKeyArr.size(); ++i)
323 const SwTOXSortKey* pKey = &m_SortKeyArr[i];
324 pValues[i].realloc(2);
325 PropertyValue* pValue = pValues[i].getArray();
326 pValue[0].Name = UNO_NAME_SORT_KEY;
327 pValue[0].Value <<= sal_Int16(pKey->eField);
328 pValue[1].Name = UNO_NAME_IS_SORT_ASCENDING;
329 pValue[1].Value <<= pKey->bSortAscending;
331 rVal <<= aRet;
333 break;
334 default:
335 assert(false);
339 void SwAuthorityFieldType::PutValue( const Any& rAny, sal_uInt16 nWhichId )
341 switch( nWhichId )
343 case FIELD_PROP_PAR1:
344 case FIELD_PROP_PAR2:
346 OUString sTmp;
347 rAny >>= sTmp;
348 const sal_Unicode uSet = !sTmp.isEmpty() ? sTmp[0] : 0;
349 if( FIELD_PROP_PAR1 == nWhichId )
350 m_cPrefix = uSet;
351 else
352 m_cSuffix = uSet;
354 break;
355 case FIELD_PROP_PAR3:
357 OUString sTmp;
358 rAny >>= sTmp;
359 SetSortAlgorithm(sTmp);
360 break;
362 case FIELD_PROP_BOOL1:
363 m_bIsSequence = *o3tl::doAccess<bool>(rAny);
364 break;
365 case FIELD_PROP_BOOL2:
366 m_bSortByDocument = *o3tl::doAccess<bool>(rAny);
367 break;
369 case FIELD_PROP_LOCALE:
371 css::lang::Locale aLocale;
372 if( rAny >>= aLocale )
373 SetLanguage( LanguageTag::convertToLanguageType( aLocale ));
375 break;
377 case FIELD_PROP_PROP_SEQ:
379 Sequence<PropertyValues> aSeq;
380 if( rAny >>= aSeq )
382 m_SortKeyArr.clear();
383 const PropertyValues* pValues = aSeq.getConstArray();
384 //TODO: Limiting to the first SAL_MAX_UINT16 elements of aSeq so that size of
385 // m_SortKeyArr remains in range of sal_uInt16, as GetSortKeyCount and GetSortKey
386 // still expect m_SortKeyArr to be indexed by sal_uInt16:
387 auto nSize = std::min<sal_Int32>(aSeq.getLength(), SAL_MAX_UINT16);
388 for(sal_Int32 i = 0; i < nSize; i++)
390 SwTOXSortKey aSortKey;
391 for(const PropertyValue& rValue : pValues[i])
393 if(rValue.Name == UNO_NAME_SORT_KEY)
395 sal_Int16 nVal = -1; rValue.Value >>= nVal;
396 if(nVal >= 0 && nVal < AUTH_FIELD_END)
397 aSortKey.eField = static_cast<ToxAuthorityField>(nVal);
399 else if(rValue.Name == UNO_NAME_IS_SORT_ASCENDING)
401 aSortKey.bSortAscending = *o3tl::doAccess<bool>(rValue.Value);
404 m_SortKeyArr.push_back(aSortKey);
408 break;
409 default:
410 assert(false);
414 void SwAuthorityFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew )
416 //re-generate positions of the fields
417 DelSequenceArray();
418 NotifyClients( pOld, pNew );
421 sal_uInt16 SwAuthorityFieldType::GetSortKeyCount() const
423 return m_SortKeyArr.size();
426 const SwTOXSortKey* SwAuthorityFieldType::GetSortKey(sal_uInt16 nIdx) const
428 if(m_SortKeyArr.size() > nIdx)
429 return &m_SortKeyArr[nIdx];
430 OSL_FAIL("Sort key not found");
431 return nullptr;
434 void SwAuthorityFieldType::SetSortKeys(sal_uInt16 nKeyCount, SwTOXSortKey const aKeys[])
436 m_SortKeyArr.clear();
437 for(sal_uInt16 i = 0; i < nKeyCount; i++)
438 if(aKeys[i].eField < AUTH_FIELD_END)
439 m_SortKeyArr.push_back(aKeys[i]);
442 SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
443 const OUString& rFieldContents )
444 : SwField(pInitType)
445 , m_nTempSequencePos( -1 )
446 , m_nTempSequencePosRLHidden( -1 )
448 m_xAuthEntry = pInitType->AddField( rFieldContents );
451 SwAuthorityField::SwAuthorityField( SwAuthorityFieldType* pInitType,
452 SwAuthEntry* pAuthEntry )
453 : SwField( pInitType )
454 , m_xAuthEntry( pAuthEntry )
455 , m_nTempSequencePos( -1 )
456 , m_nTempSequencePosRLHidden( -1 )
460 SwAuthorityField::~SwAuthorityField()
462 static_cast<SwAuthorityFieldType* >(GetTyp())->RemoveField(m_xAuthEntry.get());
465 OUString SwAuthorityField::ExpandImpl(SwRootFrame const*const pLayout) const
467 return ConditionalExpandAuthIdentifier(pLayout);
470 OUString SwAuthorityField::ConditionalExpandAuthIdentifier(
471 SwRootFrame const*const pLayout) const
473 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
474 OUString sRet;
475 if(pAuthType->GetPrefix())
476 sRet = OUString(pAuthType->GetPrefix());
478 if( pAuthType->IsSequence() )
480 sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines()
481 ? m_nTempSequencePosRLHidden : m_nTempSequencePos);
482 if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked())
483 rnTempSequencePos = pAuthType->GetSequencePos(m_xAuthEntry.get(), pLayout);
484 if (0 <= rnTempSequencePos)
485 sRet += OUString::number(rnTempSequencePos);
487 else
489 //TODO: Expand to: identifier, number sequence, ...
490 if(m_xAuthEntry)
492 OUString sIdentifier(m_xAuthEntry->GetAuthorField(AUTH_FIELD_IDENTIFIER));
493 // tdf#107784 Use title if it's a ooxml citation
494 if (sIdentifier.trim().startsWith("CITATION"))
495 return m_xAuthEntry->GetAuthorField(AUTH_FIELD_TITLE);
496 else
497 sRet += sIdentifier;
500 if(pAuthType->GetSuffix())
501 sRet += OUStringChar(pAuthType->GetSuffix());
502 return sRet;
505 OUString SwAuthorityField::ExpandCitation(ToxAuthorityField eField,
506 SwRootFrame const*const pLayout) const
508 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
509 OUString sRet;
511 if( pAuthType->IsSequence() )
513 sal_IntPtr & rnTempSequencePos(pLayout && pLayout->IsHideRedlines()
514 ? m_nTempSequencePosRLHidden : m_nTempSequencePos);
515 if(!pAuthType->GetDoc()->getIDocumentFieldsAccess().IsExpFieldsLocked())
516 rnTempSequencePos = pAuthType->GetSequencePos(m_xAuthEntry.get(), pLayout);
517 if (0 <= rnTempSequencePos)
518 sRet += OUString::number(rnTempSequencePos);
520 else
522 //TODO: Expand to: identifier, number sequence, ...
523 if(m_xAuthEntry)
524 sRet += m_xAuthEntry->GetAuthorField(eField);
526 return sRet;
529 std::unique_ptr<SwField> SwAuthorityField::Copy() const
531 SwAuthorityFieldType* pAuthType = static_cast<SwAuthorityFieldType*>(GetTyp());
532 return std::make_unique<SwAuthorityField>(pAuthType, m_xAuthEntry.get());
535 const OUString & SwAuthorityField::GetFieldText(ToxAuthorityField eField) const
537 return m_xAuthEntry->GetAuthorField( eField );
540 void SwAuthorityField::SetPar1(const OUString& rStr)
542 SwAuthorityFieldType* pInitType = static_cast<SwAuthorityFieldType* >(GetTyp());
543 pInitType->RemoveField(m_xAuthEntry.get());
544 m_xAuthEntry = pInitType->AddField(rStr);
547 OUString SwAuthorityField::GetDescription() const
549 return SwResId(STR_AUTHORITY_ENTRY);
552 const char* const aFieldNames[] =
554 "Identifier",
555 "BibiliographicType",
556 "Address",
557 "Annote",
558 "Author",
559 "Booktitle",
560 "Chapter",
561 "Edition",
562 "Editor",
563 "Howpublished",
564 "Institution",
565 "Journal",
566 "Month",
567 "Note",
568 "Number",
569 "Organizations",
570 "Pages",
571 "Publisher",
572 "School",
573 "Series",
574 "Title",
575 "Report_Type",
576 "Volume",
577 "Year",
578 "URL",
579 "Custom1",
580 "Custom2",
581 "Custom3",
582 "Custom4",
583 "Custom5",
584 "ISBN"
587 bool SwAuthorityField::QueryValue( Any& rAny, sal_uInt16 /*nWhichId*/ ) const
589 if(!GetTyp())
590 return false;
591 if(!m_xAuthEntry)
592 return false;
593 Sequence <PropertyValue> aRet(AUTH_FIELD_END);
594 PropertyValue* pValues = aRet.getArray();
595 for(int i = 0; i < AUTH_FIELD_END; ++i)
597 pValues[i].Name = OUString::createFromAscii(aFieldNames[i]);
598 const OUString& sField = m_xAuthEntry->GetAuthorField(static_cast<ToxAuthorityField>(i));
599 if(i == AUTH_FIELD_AUTHORITY_TYPE)
600 pValues[i].Value <<= sal_Int16(sField.toInt32());
601 else
602 pValues[i].Value <<= sField;
604 rAny <<= aRet;
605 /* FIXME: it is weird that we always return false here */
606 return false;
609 static sal_Int32 lcl_Find(const OUString& rFieldName)
611 for(sal_Int32 i = 0; i < AUTH_FIELD_END; ++i)
612 if(rFieldName.equalsAscii(aFieldNames[i]))
613 return i;
614 return -1;
617 bool SwAuthorityField::PutValue( const Any& rAny, sal_uInt16 /*nWhichId*/ )
619 if(!GetTyp() || !m_xAuthEntry)
620 return false;
622 Sequence <PropertyValue> aParam;
623 if(!(rAny >>= aParam))
624 return false;
626 OUStringBuffer sBuf;
627 comphelper::string::padToLength(sBuf, AUTH_FIELD_ISBN, TOX_STYLE_DELIMITER);
628 OUString sToSet(sBuf.makeStringAndClear());
629 for(const PropertyValue& rParam : std::as_const(aParam))
631 const sal_Int32 nFound = lcl_Find(rParam.Name);
632 if(nFound >= 0)
634 OUString sContent;
635 if(AUTH_FIELD_AUTHORITY_TYPE == nFound)
637 sal_Int16 nVal = 0;
638 rParam.Value >>= nVal;
639 sContent = OUString::number(nVal);
641 else
642 rParam.Value >>= sContent;
643 sToSet = comphelper::string::setToken(sToSet, nFound, TOX_STYLE_DELIMITER, sContent);
647 static_cast<SwAuthorityFieldType*>(GetTyp())->RemoveField(m_xAuthEntry.get());
648 m_xAuthEntry = static_cast<SwAuthorityFieldType*>(GetTyp())->AddField(sToSet);
650 /* FIXME: it is weird that we always return false here */
651 return false;
654 SwFieldType* SwAuthorityField::ChgTyp( SwFieldType* pFieldTyp )
656 SwAuthorityFieldType* pSrcTyp = static_cast<SwAuthorityFieldType*>(GetTyp()),
657 * pDstTyp = static_cast<SwAuthorityFieldType*>(pFieldTyp);
658 if( pSrcTyp != pDstTyp )
660 const SwAuthEntry* pSrcEntry = m_xAuthEntry.get();
661 pDstTyp->AppendField( *pSrcEntry );
662 pSrcTyp->RemoveField( pSrcEntry );
663 SwField::ChgTyp( pFieldTyp );
665 return pSrcTyp;
668 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */