summaryrefslogtreecommitdiffstats
path: root/sw/source/core/unocore/unofield.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/core/unocore/unofield.cxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/core/unocore/unofield.cxx')
-rw-r--r--sw/source/core/unocore/unofield.cxx3024
1 files changed, 3024 insertions, 0 deletions
diff --git a/sw/source/core/unocore/unofield.cxx b/sw/source/core/unocore/unofield.cxx
new file mode 100644
index 0000000000..d73c0b59b3
--- /dev/null
+++ b/sw/source/core/unocore/unofield.cxx
@@ -0,0 +1,3024 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+#include <algorithm>
+#include <memory>
+
+#include <unofield.hxx>
+#include <unofieldcoll.hxx>
+#include <unobookmark.hxx>
+#include <swtypes.hxx>
+#include <cmdid.h>
+#include <doc.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentStatistics.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <IDocumentState.hxx>
+#include <fmtfld.hxx>
+#include <txtfld.hxx>
+#include <ndtxt.hxx>
+#include <unomap.hxx>
+#include <unoprnms.hxx>
+#include <unotextrange.hxx>
+#include <unotextcursor.hxx>
+#include <unocoll.hxx>
+#include <sfx2/linkmgr.hxx>
+#include <editsh.hxx>
+#include <viewsh.hxx>
+#include <comphelper/interfacecontainer4.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <comphelper/string.hxx>
+#include <cppuhelper/supportsservice.hxx>
+#include <com/sun/star/util/DateTime.hpp>
+#include <com/sun/star/util/Date.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+//undef to prevent error (from sfx2/docfile.cxx)
+#undef SEQUENCE
+#include <com/sun/star/text/SetVariableType.hpp>
+#include <com/sun/star/text/WrapTextMode.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <authfld.hxx>
+#include <flddat.hxx>
+#include <dbfld.hxx>
+#include <usrfld.hxx>
+#include <docufld.hxx>
+#include <expfld.hxx>
+#include <chpfld.hxx>
+#include <flddropdown.hxx>
+#include <poolfmt.hxx>
+#include <strings.hrc>
+#include <pagedesc.hxx>
+#include <docary.hxx>
+#include <reffld.hxx>
+#include <ddefld.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <swunohelper.hxx>
+#include <unofldmid.h>
+#include <scriptinfo.hxx>
+#include <tools/datetime.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/itemprop.hxx>
+#include <svl/listener.hxx>
+#include <svx/dataaccessdescriptor.hxx>
+#include <o3tl/any.hxx>
+#include <o3tl/safeint.hxx>
+#include <mutex>
+#include <vcl/svapp.hxx>
+#include <textapi.hxx>
+#include <fmtmeta.hxx>
+#include <vector>
+
+using namespace ::com::sun::star;
+using namespace nsSwDocInfoSubType;
+
+// case-corrected version of the first part for the service names (see #i67811)
+constexpr OUString COM_TEXT_FLDMASTER_CC = u"com.sun.star.text.fieldmaster."_ustr;
+
+// note: this thing is indexed as an array, so do not insert/remove entries!
+const sal_uInt16 aDocInfoSubTypeFromService[] =
+{
+ DI_CHANGE | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_AUTHOR
+ DI_CHANGE | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_CHANGE_DATE_TIME
+ DI_EDIT | DI_SUB_TIME, //PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME
+ DI_COMMENT, //PROPERTY_MAP_FLDTYP_DOCINFO_DESCRIPTION
+ DI_CREATE | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_CREATE_AUTHOR
+ DI_CREATE | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_CREATE_DATE_TIME
+ 0, //DUMMY
+ 0, //DUMMY
+ 0, //DUMMY
+ 0, //DUMMY
+ DI_CUSTOM, //PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM
+ DI_PRINT | DI_SUB_AUTHOR, //PROPERTY_MAP_FLDTYP_DOCINFO_PRINT_AUTHOR
+ DI_PRINT | DI_SUB_DATE, //PROPERTY_MAP_FLDTYP_DOCINFO_PRINT_DATE_TIME
+ DI_KEYS, //PROPERTY_MAP_FLDTYP_DOCINFO_KEY_WORDS
+ DI_SUBJECT, //PROPERTY_MAP_FLDTYP_DOCINFO_SUBJECT
+ DI_TITLE, //PROPERTY_MAP_FLDTYP_DOCINFO_TITLE
+ DI_DOCNO //PROPERTY_MAP_FLDTYP_DOCINFO_REVISION
+};
+
+namespace {
+
+struct ServiceIdResId
+{
+ SwFieldIds nResId;
+ SwServiceType nServiceId;
+};
+
+}
+
+const ServiceIdResId aServiceToRes[] =
+{
+ {SwFieldIds::DateTime, SwServiceType::FieldTypeDateTime },
+ {SwFieldIds::User, SwServiceType::FieldTypeUser },
+ {SwFieldIds::SetExp, SwServiceType::FieldTypeSetExp },
+ {SwFieldIds::GetExp, SwServiceType::FieldTypeGetExp },
+ {SwFieldIds::Filename, SwServiceType::FieldTypeFileName },
+ {SwFieldIds::PageNumber, SwServiceType::FieldTypePageNum },
+ {SwFieldIds::Author, SwServiceType::FieldTypeAuthor },
+ {SwFieldIds::Chapter, SwServiceType::FieldTypeChapter },
+ {SwFieldIds::GetRef, SwServiceType::FieldTypeGetReference },
+ {SwFieldIds::HiddenText, SwServiceType::FieldTypeConditionedText },
+ {SwFieldIds::Postit, SwServiceType::FieldTypeAnnotation },
+ {SwFieldIds::Input, SwServiceType::FieldTypeInput },
+ {SwFieldIds::Macro, SwServiceType::FieldTypeMacro },
+ {SwFieldIds::Dde, SwServiceType::FieldTypeDDE },
+ {SwFieldIds::HiddenPara, SwServiceType::FieldTypeHiddenPara },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfo },
+ {SwFieldIds::TemplateName, SwServiceType::FieldTypeTemplateName },
+ {SwFieldIds::ExtUser, SwServiceType::FieldTypeUserExt },
+ {SwFieldIds::RefPageSet, SwServiceType::FieldTypeRefPageSet },
+ {SwFieldIds::RefPageGet, SwServiceType::FieldTypeRefPageGet },
+ {SwFieldIds::JumpEdit, SwServiceType::FieldTypeJumpEdit },
+ {SwFieldIds::Script, SwServiceType::FieldTypeScript },
+ {SwFieldIds::DbNextSet, SwServiceType::FieldTypeDatabaseNextSet },
+ {SwFieldIds::DbNumSet, SwServiceType::FieldTypeDatabaseNumSet },
+ {SwFieldIds::DbSetNumber, SwServiceType::FieldTypeDatabaseSetNum },
+ {SwFieldIds::Database, SwServiceType::FieldTypeDatabase },
+ {SwFieldIds::DatabaseName, SwServiceType::FieldTypeDatabaseName },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypePageCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeParagraphCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeWordCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeCharacterCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeTableCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeGraphicObjectCount },
+ {SwFieldIds::DocStat, SwServiceType::FieldTypeEmbeddedObjectCount },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoChangeAuthor },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoChangeDateTime },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoEditTime },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoDescription },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoCreateAuthor },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoCreateDateTime },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoCustom },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoPrintAuthor },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoPrintDateTime },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoKeywords },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoSubject },
+ {SwFieldIds::DocInfo, SwServiceType::FieldTypeDocInfoTitle },
+ {SwFieldIds::Input, SwServiceType::FieldTypeInputUser },
+ {SwFieldIds::HiddenText, SwServiceType::FieldTypeHiddenText },
+ {SwFieldIds::TableOfAuthorities, SwServiceType::FieldTypeBibliography },
+ {SwFieldIds::CombinedChars, SwServiceType::FieldTypeCombinedCharacters },
+ {SwFieldIds::Dropdown, SwServiceType::FieldTypeDropdown },
+ {SwFieldIds::Table, SwServiceType::FieldTypeTableFormula }
+};
+
+static SwFieldIds lcl_ServiceIdToResId(SwServiceType nServiceId)
+{
+ for (auto const& aEntry : aServiceToRes)
+ if (aEntry.nServiceId == nServiceId)
+ return aEntry.nResId;
+#if OSL_DEBUG_LEVEL > 0
+ OSL_FAIL("service id not found");
+#endif
+ return SwFieldIds::Unknown;
+}
+
+static SwServiceType lcl_GetServiceForField( const SwField& rField )
+{
+ const SwFieldIds nWhich = rField.Which();
+ SwServiceType nSrvId = SwServiceType::Invalid;
+ //special handling for some fields
+ switch( nWhich )
+ {
+ case SwFieldIds::Input:
+ if( INP_USR == (rField.GetSubType() & 0x00ff) )
+ nSrvId = SwServiceType::FieldTypeInputUser;
+ break;
+
+ case SwFieldIds::DocInfo:
+ {
+ const sal_uInt16 nSubType = rField.GetSubType();
+ switch( nSubType & 0xff )
+ {
+ case DI_CHANGE:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SwServiceType::FieldTypeDocInfoChangeAuthor
+ : SwServiceType::FieldTypeDocInfoChangeDateTime;
+ break;
+ case DI_CREATE:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SwServiceType::FieldTypeDocInfoCreateAuthor
+ : SwServiceType::FieldTypeDocInfoCreateDateTime;
+ break;
+ case DI_PRINT:
+ nSrvId = ((nSubType&0x300) == DI_SUB_AUTHOR)
+ ? SwServiceType::FieldTypeDocInfoPrintAuthor
+ : SwServiceType::FieldTypeDocInfoPrintDateTime;
+ break;
+ case DI_EDIT: nSrvId = SwServiceType::FieldTypeDocInfoEditTime;break;
+ case DI_COMMENT:nSrvId = SwServiceType::FieldTypeDocInfoDescription;break;
+ case DI_KEYS: nSrvId = SwServiceType::FieldTypeDocInfoKeywords;break;
+ case DI_SUBJECT:nSrvId = SwServiceType::FieldTypeDocInfoSubject; break;
+ case DI_TITLE: nSrvId = SwServiceType::FieldTypeDocInfoTitle; break;
+ case DI_DOCNO: nSrvId = SwServiceType::FieldTypeDocInfoRevision; break;
+ case DI_CUSTOM: nSrvId = SwServiceType::FieldTypeDocInfoCustom; break;
+ }
+ }
+ break;
+
+ case SwFieldIds::HiddenText:
+ nSrvId = SwFieldTypesEnum::ConditionalText == static_cast<SwFieldTypesEnum>(rField.GetSubType())
+ ? SwServiceType::FieldTypeConditionedText
+ : SwServiceType::FieldTypeHiddenText;
+ break;
+
+ case SwFieldIds::DocStat:
+ {
+ switch( rField.GetSubType() )
+ {
+ case DS_PAGE: nSrvId = SwServiceType::FieldTypePageCount; break;
+ case DS_PARA: nSrvId = SwServiceType::FieldTypeParagraphCount; break;
+ case DS_WORD: nSrvId = SwServiceType::FieldTypeWordCount ; break;
+ case DS_CHAR: nSrvId = SwServiceType::FieldTypeCharacterCount; break;
+ case DS_TBL: nSrvId = SwServiceType::FieldTypeTableCount ; break;
+ case DS_GRF: nSrvId = SwServiceType::FieldTypeGraphicObjectCount; break;
+ case DS_OLE: nSrvId = SwServiceType::FieldTypeEmbeddedObjectCount; break;
+ }
+ }
+ break;
+ default: break;
+ }
+ if( SwServiceType::Invalid == nSrvId )
+ {
+ for( const ServiceIdResId* pMap = aServiceToRes;
+ SwFieldIds::Unknown != pMap->nResId; ++pMap )
+ if( nWhich == pMap->nResId )
+ {
+ nSrvId = pMap->nServiceId;
+ break;
+ }
+ }
+#if OSL_DEBUG_LEVEL > 0
+ if( SwServiceType::Invalid == nSrvId )
+ OSL_FAIL("resid not found");
+#endif
+ return nSrvId;
+}
+
+static sal_uInt16 lcl_GetPropMapIdForFieldType( SwFieldIds nWhich )
+{
+ sal_uInt16 nId;
+ switch( nWhich )
+ {
+ case SwFieldIds::User: nId = PROPERTY_MAP_FLDMSTR_USER; break;
+ case SwFieldIds::Database: nId = PROPERTY_MAP_FLDMSTR_DATABASE; break;
+ case SwFieldIds::SetExp: nId = PROPERTY_MAP_FLDMSTR_SET_EXP; break;
+ case SwFieldIds::Dde: nId = PROPERTY_MAP_FLDMSTR_DDE; break;
+ case SwFieldIds::TableOfAuthorities:
+ nId = PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY; break;
+ default: nId = PROPERTY_MAP_FLDMSTR_DUMMY0;
+ }
+ return nId;
+}
+
+static sal_Int32 lcl_PropName2TokenPos(std::u16string_view rPropertyName)
+{
+ if (rPropertyName == UNO_NAME_DDE_COMMAND_TYPE)
+ return 0;
+
+ if (rPropertyName == UNO_NAME_DDE_COMMAND_FILE)
+ return 1;
+
+ if (rPropertyName == UNO_NAME_DDE_COMMAND_ELEMENT)
+ return 2;
+
+ if (rPropertyName == UNO_NAME_IS_AUTOMATIC_UPDATE)
+ return 3;
+
+ return SAL_MAX_INT32;
+}
+
+static sal_uInt16 GetFieldTypeMId( std::u16string_view rProperty, const SwFieldType& rTyp )
+{
+ sal_uInt16 nId = lcl_GetPropMapIdForFieldType( rTyp.Which() );
+ const SfxItemPropertySet* pSet = aSwMapProvider.GetPropertySet( nId );
+ if( !pSet )
+ nId = USHRT_MAX;
+ else
+ {
+ const SfxItemPropertyMapEntry* pEntry = pSet->getPropertyMap().getByName(rProperty);
+ nId = pEntry ? pEntry->nWID : USHRT_MAX;
+ }
+ return nId;
+}
+
+static sal_uInt16 lcl_GetPropertyMapOfService( SwServiceType nServiceId )
+{
+ sal_uInt16 nRet;
+ switch ( nServiceId)
+ {
+ case SwServiceType::FieldTypeDateTime: nRet = PROPERTY_MAP_FLDTYP_DATETIME; break;
+ case SwServiceType::FieldTypeUser: nRet = PROPERTY_MAP_FLDTYP_USER; break;
+ case SwServiceType::FieldTypeSetExp: nRet = PROPERTY_MAP_FLDTYP_SET_EXP; break;
+ case SwServiceType::FieldTypeGetExp: nRet = PROPERTY_MAP_FLDTYP_GET_EXP; break;
+ case SwServiceType::FieldTypeFileName: nRet = PROPERTY_MAP_FLDTYP_FILE_NAME; break;
+ case SwServiceType::FieldTypePageNum: nRet = PROPERTY_MAP_FLDTYP_PAGE_NUM; break;
+ case SwServiceType::FieldTypeAuthor: nRet = PROPERTY_MAP_FLDTYP_AUTHOR; break;
+ case SwServiceType::FieldTypeChapter: nRet = PROPERTY_MAP_FLDTYP_CHAPTER; break;
+ case SwServiceType::FieldTypeGetReference: nRet = PROPERTY_MAP_FLDTYP_GET_REFERENCE; break;
+ case SwServiceType::FieldTypeConditionedText: nRet = PROPERTY_MAP_FLDTYP_CONDITIONED_TEXT; break;
+ case SwServiceType::FieldTypeAnnotation: nRet = PROPERTY_MAP_FLDTYP_ANNOTATION; break;
+ case SwServiceType::FieldTypeInputUser:
+ case SwServiceType::FieldTypeInput: nRet = PROPERTY_MAP_FLDTYP_INPUT; break;
+ case SwServiceType::FieldTypeMacro: nRet = PROPERTY_MAP_FLDTYP_MACRO; break;
+ case SwServiceType::FieldTypeDDE: nRet = PROPERTY_MAP_FLDTYP_DDE; break;
+ case SwServiceType::FieldTypeHiddenPara: nRet = PROPERTY_MAP_FLDTYP_HIDDEN_PARA; break;
+ case SwServiceType::FieldTypeDocInfo: nRet = PROPERTY_MAP_FLDTYP_DOC_INFO; break;
+ case SwServiceType::FieldTypeTemplateName: nRet = PROPERTY_MAP_FLDTYP_TEMPLATE_NAME; break;
+ case SwServiceType::FieldTypeUserExt: nRet = PROPERTY_MAP_FLDTYP_USER_EXT; break;
+ case SwServiceType::FieldTypeRefPageSet: nRet = PROPERTY_MAP_FLDTYP_REF_PAGE_SET; break;
+ case SwServiceType::FieldTypeRefPageGet: nRet = PROPERTY_MAP_FLDTYP_REF_PAGE_GET; break;
+ case SwServiceType::FieldTypeJumpEdit: nRet = PROPERTY_MAP_FLDTYP_JUMP_EDIT; break;
+ case SwServiceType::FieldTypeScript: nRet = PROPERTY_MAP_FLDTYP_SCRIPT; break;
+ case SwServiceType::FieldTypeDatabaseNextSet: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NEXT_SET; break;
+ case SwServiceType::FieldTypeDatabaseNumSet: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NUM_SET; break;
+ case SwServiceType::FieldTypeDatabaseSetNum: nRet = PROPERTY_MAP_FLDTYP_DATABASE_SET_NUM; break;
+ case SwServiceType::FieldTypeDatabase: nRet = PROPERTY_MAP_FLDTYP_DATABASE; break;
+ case SwServiceType::FieldTypeDatabaseName: nRet = PROPERTY_MAP_FLDTYP_DATABASE_NAME; break;
+ case SwServiceType::FieldTypeTableFormula: nRet = PROPERTY_MAP_FLDTYP_TABLE_FORMULA; break;
+ case SwServiceType::FieldTypePageCount:
+ case SwServiceType::FieldTypeParagraphCount:
+ case SwServiceType::FieldTypeWordCount:
+ case SwServiceType::FieldTypeCharacterCount:
+ case SwServiceType::FieldTypeTableCount:
+ case SwServiceType::FieldTypeGraphicObjectCount:
+ case SwServiceType::FieldTypeEmbeddedObjectCount: nRet = PROPERTY_MAP_FLDTYP_DOCSTAT; break;
+ case SwServiceType::FieldTypeDocInfoChangeAuthor:
+ case SwServiceType::FieldTypeDocInfoCreateAuthor:
+ case SwServiceType::FieldTypeDocInfoPrintAuthor: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_AUTHOR; break;
+ case SwServiceType::FieldTypeDocInfoChangeDateTime:
+ case SwServiceType::FieldTypeDocInfoCreateDateTime:
+ case SwServiceType::FieldTypeDocInfoPrintDateTime: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_DATE_TIME; break;
+ case SwServiceType::FieldTypeDocInfoEditTime: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_EDIT_TIME; break;
+ case SwServiceType::FieldTypeDocInfoCustom: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_CUSTOM; break;
+ case SwServiceType::FieldTypeDocInfoDescription:
+ case SwServiceType::FieldTypeDocInfoKeywords:
+ case SwServiceType::FieldTypeDocInfoSubject:
+ case SwServiceType::FieldTypeDocInfoTitle: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_MISC; break;
+ case SwServiceType::FieldTypeDocInfoRevision: nRet = PROPERTY_MAP_FLDTYP_DOCINFO_REVISION; break;
+ case SwServiceType::FieldTypeBibliography: nRet = PROPERTY_MAP_FLDTYP_BIBLIOGRAPHY; break;
+ case SwServiceType::FieldTypeDummy0:
+ case SwServiceType::FieldTypeCombinedCharacters: nRet = PROPERTY_MAP_FLDTYP_COMBINED_CHARACTERS; break;
+ case SwServiceType::FieldTypeDropdown: nRet = PROPERTY_MAP_FLDTYP_DROPDOWN; break;
+ case SwServiceType::FieldTypeDummy4:
+ case SwServiceType::FieldTypeDummy5:
+ case SwServiceType::FieldTypeDummy6:
+ case SwServiceType::FieldTypeDummy7:
+ nRet = PROPERTY_MAP_FLDTYP_DUMMY_0; break;
+ case SwServiceType::FieldMasterUser: nRet = PROPERTY_MAP_FLDMSTR_USER; break;
+ case SwServiceType::FieldMasterDDE: nRet = PROPERTY_MAP_FLDMSTR_DDE; break;
+ case SwServiceType::FieldMasterSetExp: nRet = PROPERTY_MAP_FLDMSTR_SET_EXP; break;
+ case SwServiceType::FieldMasterDatabase: nRet = PROPERTY_MAP_FLDMSTR_DATABASE; break;
+ case SwServiceType::FieldMasterBibliography: nRet = PROPERTY_MAP_FLDMSTR_BIBLIOGRAPHY; break;
+ case SwServiceType::FieldMasterDummy2:
+ case SwServiceType::FieldMasterDummy3:
+ case SwServiceType::FieldMasterDummy4:
+ case SwServiceType::FieldMasterDummy5: nRet = PROPERTY_MAP_FLDMSTR_DUMMY0; break;
+ case SwServiceType::FieldTypeHiddenText: nRet = PROPERTY_MAP_FLDTYP_HIDDEN_TEXT; break;
+ default:
+ nRet = USHRT_MAX;
+ }
+ assert(nRet != USHRT_MAX && "wrong service id");
+ return nRet;
+}
+
+class SwXFieldMaster::Impl
+ : public SvtListener
+{
+public:
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper4
+
+ unotools::WeakReference<SwXFieldMaster> m_wThis;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners;
+
+ SwDoc* m_pDoc;
+ SwFieldType* m_pType;
+
+ SwFieldIds m_nResTypeId;
+
+ OUString m_sParam1; // Content / Database / NumberingSeparator
+ OUString m_sParam2; // - /DataTablename
+ OUString m_sParam3; // - /DataFieldName
+ OUString m_sParam5; // - /DataBaseURL
+ double m_fParam1; // Value / -
+ sal_Int8 m_nParam1; // ChapterNumberingLevel
+ bool m_bParam1; // IsExpression
+ sal_Int32 m_nParam2;
+
+ Impl(SwPageDesc* const pPageDesc, SwDoc* pDoc, SwFieldIds nResId)
+ : m_pDoc(pDoc)
+ , m_pType(nullptr)
+ , m_nResTypeId(nResId)
+ , m_fParam1(0.0)
+ , m_nParam1(-1)
+ , m_bParam1(false)
+ , m_nParam2(0)
+ {
+ StartListening(pPageDesc->GetNotifier());
+ }
+
+ Impl(SwFieldType* const pType, SwDoc* pDoc, SwFieldIds nResId)
+ : m_pDoc(pDoc)
+ , m_pType(pType)
+ , m_nResTypeId(nResId)
+ , m_fParam1(0.0)
+ , m_nParam1(-1)
+ , m_bParam1(false)
+ , m_nParam2(0)
+ {
+ StartListening(m_pType->GetNotifier());
+ }
+ void SetFieldType(SwFieldType* pType)
+ {
+ EndListeningAll();
+ m_pType = pType;
+ StartListening(m_pType->GetNotifier());
+ }
+protected:
+ virtual void Notify(const SfxHint& rHint) override;
+};
+
+OUString SAL_CALL
+SwXFieldMaster::getImplementationName()
+{
+ return "SwXFieldMaster";
+}
+
+namespace
+{
+
+OUString getServiceName(const SwFieldIds aId)
+{
+ const char* pEntry;
+ switch (aId)
+ {
+ case SwFieldIds::User:
+ pEntry = "User";
+ break;
+ case SwFieldIds::Database:
+ pEntry = "Database";
+ break;
+ case SwFieldIds::SetExp:
+ pEntry = "SetExpression";
+ break;
+ case SwFieldIds::Dde:
+ pEntry = "DDE";
+ break;
+ case SwFieldIds::TableOfAuthorities:
+ pEntry = "Bibliography";
+ break;
+ default:
+ return OUString();
+ }
+
+ return "com.sun.star.text.fieldmaster." + OUString::createFromAscii(pEntry);
+}
+
+}
+
+sal_Bool SAL_CALL SwXFieldMaster::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL
+SwXFieldMaster::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.TextFieldMaster", getServiceName(m_pImpl->m_nResTypeId) };
+}
+
+SwXFieldMaster::SwXFieldMaster(SwDoc& rDoc, SwFieldIds const nResId)
+ : m_pImpl(new Impl(rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD), &rDoc, nResId))
+{
+}
+
+SwXFieldMaster::SwXFieldMaster(SwFieldType& rType, SwDoc * pDoc)
+ : m_pImpl(new Impl(&rType, pDoc, rType.Which()))
+{
+}
+
+SwXFieldMaster::~SwXFieldMaster()
+{
+}
+
+rtl::Reference<SwXFieldMaster>
+SwXFieldMaster::CreateXFieldMaster(SwDoc * pDoc, SwFieldType *const pType,
+ SwFieldIds nResId)
+{
+ // re-use existing SwXFieldMaster
+ rtl::Reference<SwXFieldMaster> xFM;
+ if (pType)
+ {
+ xFM = pType->GetXObject().get();
+ }
+ if (!xFM.is())
+ {
+ SwXFieldMaster *const pFM( pType
+ ? new SwXFieldMaster(*pType, pDoc)
+ : new SwXFieldMaster(*pDoc, nResId));
+ xFM.set(pFM);
+ if (pType)
+ {
+ pType->SetXObject(xFM);
+ }
+ // need a permanent Reference to initialize m_wThis
+ pFM->m_pImpl->m_wThis = xFM.get();
+ }
+ return xFM;
+}
+
+uno::Reference<beans::XPropertySetInfo> SAL_CALL
+SwXFieldMaster::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< beans::XPropertySetInfo > aRef =
+ aSwMapProvider.GetPropertySet(
+ lcl_GetPropMapIdForFieldType(m_pImpl->m_nResTypeId))->getPropertySetInfo();
+ return aRef;
+}
+
+void SAL_CALL SwXFieldMaster::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+{
+ SolarMutexGuard aGuard;
+ SwFieldType* pType = GetFieldType(true);
+ if(pType)
+ {
+ bool bSetValue = true;
+ if( rPropertyName == UNO_NAME_SUB_TYPE )
+ {
+ const std::vector<OUString>& rExtraArr(
+ SwStyleNameMapper::GetExtraUINameArray());
+ const OUString sTypeName = pType->GetName();
+ static sal_uInt16 nIds[] =
+ {
+ RES_POOLCOLL_LABEL_DRAWING - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_ABB - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_TABLE - RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FRAME- RES_POOLCOLL_EXTRA_BEGIN,
+ RES_POOLCOLL_LABEL_FIGURE - RES_POOLCOLL_EXTRA_BEGIN,
+ 0
+ };
+ for(const sal_uInt16 * pIds = nIds; *pIds; ++pIds)
+ {
+ if(sTypeName == rExtraArr[ *pIds ] )
+ {
+ bSetValue = false;
+ break;
+ }
+ }
+ }
+ if ( bSetValue )
+ {
+ // nothing special to be done here for the properties
+ // UNO_NAME_DATA_BASE_NAME and UNO_NAME_DATA_BASE_URL.
+ // We just call PutValue (empty string is allowed).
+ // Thus the last property set will be used as Data Source.
+
+ const sal_uInt16 nMemberValueId = GetFieldTypeMId( rPropertyName, *pType );
+ if ( USHRT_MAX == nMemberValueId )
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak() );
+ }
+
+ pType->PutValue( rValue, nMemberValueId );
+ if ( pType->Which() == SwFieldIds::User )
+ {
+ // trigger update of User field in order to get depending Input Fields updated.
+ pType->UpdateFields();
+ }
+
+ }
+ }
+ else if (m_pImpl->m_pDoc && rPropertyName == UNO_NAME_NAME)
+ {
+ OUString sTypeName;
+ rValue >>= sTypeName;
+ SwFieldType * pType2 = m_pImpl->m_pDoc->getIDocumentFieldsAccess().GetFieldType(
+ m_pImpl->m_nResTypeId, sTypeName, false);
+
+ if(pType2 ||
+ (SwFieldIds::SetExp == m_pImpl->m_nResTypeId &&
+ ( sTypeName == SwResId(STR_POOLCOLL_LABEL_TABLE) ||
+ sTypeName == SwResId(STR_POOLCOLL_LABEL_DRAWING) ||
+ sTypeName == SwResId(STR_POOLCOLL_LABEL_FRAME) ||
+ sTypeName == SwResId(STR_POOLCOLL_LABEL_ABB) ||
+ sTypeName == SwResId(STR_POOLCOLL_LABEL_FIGURE) )))
+ {
+ throw lang::IllegalArgumentException();
+ }
+
+ switch (m_pImpl->m_nResTypeId)
+ {
+ case SwFieldIds::User :
+ {
+ SwUserFieldType aType(m_pImpl->m_pDoc, sTypeName);
+ pType2 = m_pImpl->m_pDoc->getIDocumentFieldsAccess().InsertFieldType(aType);
+ static_cast<SwUserFieldType*>(pType2)->SetContent(m_pImpl->m_sParam1);
+ static_cast<SwUserFieldType*>(pType2)->SetValue(m_pImpl->m_fParam1);
+ static_cast<SwUserFieldType*>(pType2)->SetType(m_pImpl->m_bParam1
+ ? nsSwGetSetExpType::GSE_EXPR : nsSwGetSetExpType::GSE_STRING);
+ }
+ break;
+ case SwFieldIds::Dde :
+ {
+ SwDDEFieldType aType(sTypeName, m_pImpl->m_sParam1,
+ m_pImpl->m_bParam1 ? SfxLinkUpdateMode::ALWAYS : SfxLinkUpdateMode::ONCALL);
+ pType2 = m_pImpl->m_pDoc->getIDocumentFieldsAccess().InsertFieldType(aType);
+ }
+ break;
+ case SwFieldIds::SetExp :
+ {
+ SwSetExpFieldType aType(m_pImpl->m_pDoc, sTypeName);
+ if (!m_pImpl->m_sParam1.isEmpty())
+ aType.SetDelimiter(OUString(m_pImpl->m_sParam1[0]));
+ if (m_pImpl->m_nParam1 > -1 && m_pImpl->m_nParam1 < MAXLEVEL)
+ aType.SetOutlineLvl(m_pImpl->m_nParam1);
+ pType2 = m_pImpl->m_pDoc->getIDocumentFieldsAccess().InsertFieldType(aType);
+ }
+ break;
+ case SwFieldIds::Database :
+ {
+ rValue >>= m_pImpl->m_sParam3;
+ pType2 = GetFieldType();
+ }
+ break;
+ default: break;
+ }
+ if (!pType2)
+ {
+ throw uno::RuntimeException("no field type found!", *this);
+ }
+ m_pImpl->SetFieldType(pType2);
+ }
+ else
+ {
+ switch (m_pImpl->m_nResTypeId)
+ {
+ case SwFieldIds::User:
+ if(rPropertyName == UNO_NAME_CONTENT)
+ rValue >>= m_pImpl->m_sParam1;
+ else if(rPropertyName == UNO_NAME_VALUE)
+ {
+ if(rValue.getValueType() != ::cppu::UnoType<double>::get())
+ throw lang::IllegalArgumentException();
+ rValue >>= m_pImpl->m_fParam1;
+ }
+ else if(rPropertyName == UNO_NAME_IS_EXPRESSION)
+ {
+ if(rValue.getValueType() != cppu::UnoType<bool>::get())
+ throw lang::IllegalArgumentException();
+ rValue >>= m_pImpl->m_bParam1;
+ }
+
+ break;
+ case SwFieldIds::Database:
+ if(rPropertyName == UNO_NAME_DATA_BASE_NAME)
+ rValue >>= m_pImpl->m_sParam1;
+ else if(rPropertyName == UNO_NAME_DATA_TABLE_NAME)
+ rValue >>= m_pImpl->m_sParam2;
+ else if(rPropertyName == UNO_NAME_DATA_COLUMN_NAME)
+ rValue >>= m_pImpl->m_sParam3;
+ else if(rPropertyName == UNO_NAME_DATA_COMMAND_TYPE)
+ rValue >>= m_pImpl->m_nParam2;
+ if(rPropertyName == UNO_NAME_DATA_BASE_URL)
+ rValue >>= m_pImpl->m_sParam5;
+
+ if ( ( !m_pImpl->m_sParam1.isEmpty()
+ || !m_pImpl->m_sParam5.isEmpty())
+ && !m_pImpl->m_sParam2.isEmpty()
+ && !m_pImpl->m_sParam3.isEmpty())
+ {
+ GetFieldType();
+ }
+ break;
+ case SwFieldIds::SetExp:
+ if(rPropertyName == UNO_NAME_NUMBERING_SEPARATOR)
+ rValue >>= m_pImpl->m_sParam1;
+ else if(rPropertyName == UNO_NAME_CHAPTER_NUMBERING_LEVEL)
+ rValue >>= m_pImpl->m_nParam1;
+ break;
+ case SwFieldIds::Dde:
+ {
+ sal_Int32 nPart = lcl_PropName2TokenPos(rPropertyName);
+ if(nPart < 3 )
+ {
+ if (m_pImpl->m_sParam1.isEmpty())
+ {
+ m_pImpl->m_sParam1
+ = OUStringChar(sfx2::cTokenSeparator)
+ + OUStringChar(sfx2::cTokenSeparator);
+ }
+ OUString sTmp;
+ rValue >>= sTmp;
+ sal_Int32 nIndex(0);
+ sal_Int32 nStart(0);
+ while (nIndex < m_pImpl->m_sParam1.getLength())
+ {
+ if (m_pImpl->m_sParam1[nIndex] == sfx2::cTokenSeparator)
+ {
+ if (0 == nPart)
+ break;
+ nStart = nIndex + 1;
+ --nPart;
+ }
+ ++nIndex;
+ }
+ assert(0 == nPart);
+ m_pImpl->m_sParam1 = m_pImpl->m_sParam1.replaceAt(
+ nStart, nIndex - nStart, sTmp);
+ }
+ else if(3 == nPart)
+ {
+ rValue >>= m_pImpl->m_bParam1;
+ }
+ }
+ break;
+ default:
+ throw beans::UnknownPropertyException( "Unknown property: " + rPropertyName, getXWeak() );
+ }
+ }
+}
+
+SwFieldType* SwXFieldMaster::GetFieldType(bool const bDontCreate) const
+{
+ if (!bDontCreate && SwFieldIds::Database == m_pImpl->m_nResTypeId
+ && !m_pImpl->m_pType && m_pImpl->m_pDoc)
+ {
+ SwDBData aData;
+
+ // set DataSource
+ svx::ODataAccessDescriptor aAcc;
+ if (!m_pImpl->m_sParam1.isEmpty())
+ aAcc[svx::DataAccessDescriptorProperty::DataSource] <<= m_pImpl->m_sParam1; // DataBaseName
+ else if (!m_pImpl->m_sParam5.isEmpty())
+ aAcc[svx::DataAccessDescriptorProperty::DatabaseLocation] <<= m_pImpl->m_sParam5; // DataBaseURL
+ aData.sDataSource = aAcc.getDataSource();
+
+ aData.sCommand = m_pImpl->m_sParam2;
+ aData.nCommandType = m_pImpl->m_nParam2;
+
+ SwDBFieldType aType(m_pImpl->m_pDoc, m_pImpl->m_sParam3, std::move(aData));
+ SwFieldType *const pType = m_pImpl->m_pDoc->getIDocumentFieldsAccess().InsertFieldType(aType);
+ m_pImpl->SetFieldType(pType);
+ }
+ return m_pImpl->m_pType;
+}
+
+uno::Any SAL_CALL
+SwXFieldMaster::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwFieldType* pType = GetFieldType(true);
+ if( rPropertyName == UNO_NAME_INSTANCE_NAME )
+ {
+ OUString sName;
+ if(pType)
+ SwXTextFieldMasters::getInstanceName(*pType, sName);
+ aRet <<= sName;
+ }
+ else if(pType)
+ {
+ if(rPropertyName == UNO_NAME_NAME)
+ {
+ aRet <<= SwXFieldMaster::GetProgrammaticName(*pType, *m_pImpl->m_pDoc);
+ }
+ else if(rPropertyName == UNO_NAME_DEPENDENT_TEXT_FIELDS)
+ {
+ //fill all text fields into a sequence
+ std::vector<SwFormatField*> vpFields;
+ pType->GatherFields(vpFields);
+ uno::Sequence<uno::Reference <text::XDependentTextField> > aSeq(vpFields.size());
+ std::transform(vpFields.begin(), vpFields.end(), aSeq.getArray(),
+ [this](SwFormatField* pF) { return uno::Reference<text::XDependentTextField>(SwXTextField::CreateXTextField(m_pImpl->m_pDoc, pF)); });
+ aRet <<= aSeq;
+ }
+ else
+ {
+ //TODO: add properties for the other field types
+ const sal_uInt16 nMId = GetFieldTypeMId( rPropertyName, *pType );
+ if (USHRT_MAX == nMId)
+ {
+ throw beans::UnknownPropertyException(
+ "Unknown property: " + rPropertyName,
+ getXWeak());
+ }
+ pType->QueryValue( aRet, nMId );
+
+ if (rPropertyName == UNO_NAME_DATA_BASE_NAME ||
+ rPropertyName == UNO_NAME_DATA_BASE_URL)
+ {
+ OUString aDataSource;
+ aRet >>= aDataSource;
+ aRet <<= OUString();
+
+ OUString *pStr = nullptr; // only one of this properties will return
+ // a non-empty string.
+ INetURLObject aObj;
+ aObj.SetURL( aDataSource );
+ bool bIsURL = aObj.GetProtocol() != INetProtocol::NotValid;
+ if (bIsURL && rPropertyName == UNO_NAME_DATA_BASE_URL)
+ pStr = &aDataSource; // DataBaseURL
+ else if (!bIsURL && rPropertyName == UNO_NAME_DATA_BASE_NAME)
+ pStr = &aDataSource; // DataBaseName
+
+ if (pStr)
+ aRet <<= *pStr;
+ }
+ }
+ }
+ else
+ {
+ if(rPropertyName == UNO_NAME_DATA_COMMAND_TYPE)
+ aRet <<= m_pImpl->m_nParam2;
+ else if(rPropertyName == UNO_NAME_DEPENDENT_TEXT_FIELDS )
+ {
+ uno::Sequence<uno::Reference <text::XDependentTextField> > aRetSeq(0);
+ aRet <<= aRetSeq;
+ }
+ else
+ {
+ switch (m_pImpl->m_nResTypeId)
+ {
+ case SwFieldIds::User:
+ if( rPropertyName == UNO_NAME_CONTENT )
+ aRet <<= m_pImpl->m_sParam1;
+ else if(rPropertyName == UNO_NAME_VALUE)
+ aRet <<= m_pImpl->m_fParam1;
+ else if(rPropertyName == UNO_NAME_IS_EXPRESSION)
+ aRet <<= m_pImpl->m_bParam1;
+ break;
+ case SwFieldIds::Database:
+ if(rPropertyName == UNO_NAME_DATA_BASE_NAME ||
+ rPropertyName == UNO_NAME_DATA_BASE_URL)
+ {
+ // only one of these properties returns a non-empty string.
+ INetURLObject aObj;
+ aObj.SetURL(m_pImpl->m_sParam5); // SetSmartURL
+ bool bIsURL = aObj.GetProtocol() != INetProtocol::NotValid;
+ if (bIsURL && rPropertyName == UNO_NAME_DATA_BASE_URL)
+ aRet <<= m_pImpl->m_sParam5; // DataBaseURL
+ else if ( rPropertyName == UNO_NAME_DATA_BASE_NAME)
+ aRet <<= m_pImpl->m_sParam1; // DataBaseName
+ }
+ else if(rPropertyName == UNO_NAME_DATA_TABLE_NAME)
+ aRet <<= m_pImpl->m_sParam2;
+ else if(rPropertyName == UNO_NAME_DATA_COLUMN_NAME)
+ aRet <<= m_pImpl->m_sParam3;
+ break;
+ case SwFieldIds::SetExp:
+ if(rPropertyName == UNO_NAME_NUMBERING_SEPARATOR)
+ aRet <<= m_pImpl->m_sParam1;
+ else if(rPropertyName == UNO_NAME_CHAPTER_NUMBERING_LEVEL)
+ aRet <<= m_pImpl->m_nParam1;
+ break;
+ case SwFieldIds::Dde:
+ {
+ const sal_Int32 nPart = lcl_PropName2TokenPos(rPropertyName);
+ if(nPart < 3 )
+ aRet <<= m_pImpl->m_sParam1.getToken(nPart, sfx2::cTokenSeparator);
+ else if(3 == nPart)
+ aRet <<= m_pImpl->m_bParam1;
+ }
+ break;
+ default:
+ throw beans::UnknownPropertyException( "Unknown property: " + rPropertyName, getXWeak() );
+ }
+ }
+ }
+ return aRet;
+}
+
+void SwXFieldMaster::addPropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXFieldMaster::removePropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXFieldMaster::addVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXFieldMaster::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXFieldMaster::dispose()
+{
+ SolarMutexGuard aGuard;
+ SwFieldType *const pFieldType = GetFieldType(true);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ size_t nTypeIdx = SIZE_MAX;
+ const SwFieldTypes* pTypes = m_pImpl->m_pDoc->getIDocumentFieldsAccess().GetFieldTypes();
+ for( size_t i = 0; i < pTypes->size(); i++ )
+ {
+ if((*pTypes)[i].get()== pFieldType)
+ nTypeIdx = i;
+ }
+
+ // first delete all fields
+ std::vector<SwFormatField*> vpFields;
+ pFieldType->GatherFields(vpFields);
+ for(auto pField : vpFields)
+ SwTextField::DeleteTextField(*pField->GetTextField());
+ // then delete FieldType
+ m_pImpl->m_pDoc->getIDocumentFieldsAccess().RemoveFieldType(nTypeIdx);
+}
+
+void SAL_CALL SwXFieldMaster::addEventListener(
+ const uno::Reference<lang::XEventListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.addInterface(aGuard, xListener);
+}
+
+void SAL_CALL SwXFieldMaster::removeEventListener(
+ const uno::Reference<lang::XEventListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.removeInterface(aGuard, xListener);
+}
+
+void SwXFieldMaster::Impl::Notify(const SfxHint& rHint)
+{
+ if(rHint.GetId() == SfxHintId::Dying)
+ {
+ m_pDoc = nullptr;
+ m_pType = nullptr;
+ uno::Reference<uno::XInterface> const xThis(m_wThis);
+ if (!xThis.is())
+ { // fdo#72695: if UNO object is already dead, don't revive it with event
+ return;
+ }
+ lang::EventObject const ev(xThis);
+ std::unique_lock aGuard(m_Mutex);
+ m_EventListeners.disposeAndClear(aGuard, ev);
+ }
+}
+
+OUString SwXFieldMaster::GetProgrammaticName(const SwFieldType& rType, SwDoc& rDoc)
+{
+ const OUString sName(rType.GetName());
+ if(SwFieldIds::SetExp == rType.Which())
+ {
+ const SwFieldTypes* pTypes = rDoc.getIDocumentFieldsAccess().GetFieldTypes();
+ for( size_t i = 0; i <= o3tl::make_unsigned(INIT_FLDTYPES); i++ )
+ {
+ if((*pTypes)[i].get() == &rType)
+ {
+ return SwStyleNameMapper::GetProgName( sName, SwGetPoolIdFromName::TxtColl );
+ }
+ }
+ }
+ return sName;
+}
+
+OUString SwXFieldMaster::LocalizeFormula(
+ const SwSetExpField& rField,
+ const OUString& rFormula,
+ bool bQuery)
+{
+ const OUString sTypeName(rField.GetTyp()->GetName());
+ const OUString sProgName(
+ SwStyleNameMapper::GetProgName(sTypeName, SwGetPoolIdFromName::TxtColl ));
+ if(sProgName != sTypeName)
+ {
+ const OUString sSource = bQuery ? sTypeName : sProgName;
+ const OUString sDest = bQuery ? sProgName : sTypeName;
+ if(rFormula.startsWith(sSource))
+ {
+ return sDest + rFormula.subView(sSource.getLength());
+ }
+ }
+ return rFormula;
+}
+
+namespace {
+
+struct SwFieldProperties_Impl
+{
+ OUString sPar1;
+ OUString sPar2;
+ OUString sPar3;
+ OUString sPar4;
+ OUString sPar5;
+ OUString sPar6;
+ OUString sPar7;
+ Date aDate;
+ double fDouble;
+ uno::Sequence<beans::PropertyValue> aPropSeq;
+ uno::Sequence<OUString> aStrings;
+ std::unique_ptr<util::DateTime> pDateTime;
+
+ sal_Int32 nSubType;
+ sal_Int32 nFormat;
+ sal_uInt16 nUSHORT1;
+ sal_uInt16 nUSHORT2;
+ sal_uInt16 nUSHORT3;
+ sal_Int16 nSHORT1;
+ sal_Int8 nByte1;
+ bool bFormatIsDefault;
+ bool bBool1;
+ bool bBool2;
+ bool bBool3;
+ bool bBool4;
+
+ SwFieldProperties_Impl():
+ aDate( Date::EMPTY ),
+ fDouble(0.),
+ nSubType(0),
+ nFormat(0),
+ nUSHORT1(0),
+ nUSHORT2(0),
+ nUSHORT3(0),
+ nSHORT1(0),
+ nByte1(0),
+ bFormatIsDefault(true),
+ bBool1(false),
+ bBool2(false),
+ bBool3(false),
+ bBool4(true) //Automatic language
+ {}
+};
+
+}
+
+class SwXTextField::Impl
+ : public SvtListener
+{
+public:
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper4
+ SwFieldType* m_pFieldType;
+ SwFormatField* m_pFormatField;
+
+ unotools::WeakReference<SwXTextField> m_wThis;
+ ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_EventListeners;
+
+ SwDoc* m_pDoc;
+ rtl::Reference<SwTextAPIObject> m_xTextObject;
+ bool m_bIsDescriptor;
+ bool m_bCallUpdate;
+ SwServiceType m_nServiceId;
+ OUString m_sTypeName;
+ std::unique_ptr<SwFieldProperties_Impl> m_pProps;
+
+ Impl(SwDoc *const pDoc, SwFormatField *const pFormat, SwServiceType nServiceId)
+ : m_pFieldType(nullptr)
+ , m_pFormatField(pFormat)
+ , m_pDoc(pDoc)
+ , m_bIsDescriptor(pFormat == nullptr)
+ , m_bCallUpdate(false)
+ , m_nServiceId(pFormat
+ ? lcl_GetServiceForField(*pFormat->GetField())
+ : nServiceId)
+ , m_pProps(pFormat ? nullptr : new SwFieldProperties_Impl)
+ {
+ if(m_pFormatField)
+ StartListening(m_pFormatField->GetNotifier());
+ }
+
+ virtual ~Impl() override
+ {
+ if (m_xTextObject.is())
+ {
+ m_xTextObject->DisposeEditSource();
+ }
+ }
+
+ void SetFormatField(SwFormatField* pFormatField, SwDoc* pDoc)
+ {
+ m_pFormatField = pFormatField;
+ m_pDoc = pDoc;
+ if(m_pFormatField)
+ {
+ EndListeningAll();
+ StartListening(m_pFormatField->GetNotifier());
+ }
+ }
+ SwFormatField* GetFormatField()
+ {
+ return m_pFormatField;
+ }
+ bool IsDescriptor() const
+ {
+ // ideally should be: !m_pFormatField && m_pDoc
+ // but: SwXServiceProvider::MakeInstance() passes nullptr SwDoc, see comment there
+ return m_bIsDescriptor;
+ }
+ void Invalidate();
+
+ const SwField* GetField() const;
+
+ SwFieldType* GetFieldType() const
+ {
+ if(!m_pDoc && !IsDescriptor())
+ throw uno::RuntimeException();
+ else if (IsDescriptor())
+ return m_pFieldType;
+
+ return m_pFormatField->GetField()->GetTyp();
+ }
+ void SetFieldType(SwFieldType& rType)
+ {
+ EndListeningAll();
+ m_pFieldType = &rType;
+ StartListening(m_pFieldType->GetNotifier());
+ }
+ void ClearFieldType()
+ {
+ SvtListener::EndListeningAll();
+ m_pFieldType = nullptr;
+ }
+ virtual void Notify(const SfxHint&) override;
+};
+
+SwXTextField::SwXTextField(
+ SwServiceType nServiceId,
+ SwDoc* pDoc)
+ : m_pImpl(new Impl(pDoc, nullptr, nServiceId))
+{
+ //Set visible as default!
+ if ( SwServiceType::FieldTypeSetExp == nServiceId
+ || SwServiceType::FieldTypeDatabaseSetNum == nServiceId
+ || SwServiceType::FieldTypeDatabase == nServiceId
+ || SwServiceType::FieldTypeDatabaseName == nServiceId )
+ {
+ m_pImpl->m_pProps->bBool2 = true;
+ }
+ else if(SwServiceType::FieldTypeTableFormula == nServiceId)
+ {
+ m_pImpl->m_pProps->bBool1 = true;
+ }
+ if(SwServiceType::FieldTypeSetExp == nServiceId)
+ {
+ m_pImpl->m_pProps->nUSHORT2 = USHRT_MAX;
+ }
+}
+
+SwXTextField::SwXTextField(SwFormatField& rFormat, SwDoc & rDoc)
+ : m_pImpl(new Impl(&rDoc, &rFormat, SwServiceType::Invalid))
+{
+}
+
+SwXTextField::~SwXTextField()
+{
+}
+
+rtl::Reference<SwXTextField>
+SwXTextField::CreateXTextField(SwDoc *const pDoc, SwFormatField const* pFormat,
+ SwServiceType nServiceId)
+{
+ assert(!pFormat || pDoc);
+ assert(pFormat || nServiceId != SwServiceType::Invalid);
+ // re-use existing SwXTextField
+ rtl::Reference<SwXTextField> xField;
+ if (pFormat)
+ {
+ xField = pFormat->GetXTextField();
+ }
+ if (!xField.is())
+ {
+ SwXTextField *const pField( pFormat
+ ? new SwXTextField(const_cast<SwFormatField&>(*pFormat), *pDoc)
+ : new SwXTextField(nServiceId, pDoc));
+ xField.set(pField);
+ if (pFormat)
+ {
+ const_cast<SwFormatField *>(pFormat)->SetXTextField(xField);
+ }
+ // need a permanent Reference to initialize m_wThis
+ pField->m_pImpl->m_wThis = xField.get();
+ }
+ return xField;
+}
+
+SwServiceType SwXTextField::GetServiceId() const
+{
+ return m_pImpl->m_nServiceId;
+}
+
+/** Convert between SwSetExpField with InputFlag false and InputFlag true.
+ Unfortunately the InputFlag is exposed in the API as "Input" property
+ and is mutable; in the UI and in ODF these are 2 different types of
+ fields, so the API design is very questionable.
+ In order to keep the mutable property, the whole thing has to be
+ reconstructed from scratch, to replace the SwTextField hint with
+ SwTextInputField or vice versa.
+ The SwFormatField will be replaced - it must be, because the Which
+ changes - but the SwXTextField *must not* be disposed in the operation,
+ it has to be disconnected first and at the end connected to the
+ new instance!
+ */
+void SwXTextField::TransmuteLeadToInputField(SwSetExpField & rField)
+{
+ assert(rField.GetFormatField()->Which() == (rField.GetInputFlag() ? RES_TXTATR_INPUTFIELD : RES_TXTATR_FIELD));
+ rtl::Reference<SwXTextField> const pXField(
+ rField.GetFormatField()->GetXTextField());
+ if (pXField)
+ pXField->m_pImpl->SetFormatField(nullptr, nullptr);
+ SwTextField *const pOldAttr(rField.GetFormatField()->GetTextField());
+ SwSetExpField tempField(rField);
+ tempField.SetInputFlag(!rField.GetInputFlag());
+ SwFormatField tempFormat(tempField);
+ assert(tempFormat.GetField() != &rField);
+ assert(tempFormat.GetField() != &tempField); // this copies it again?
+ assert(tempFormat.Which() == (static_cast<SwSetExpField const*>(tempFormat.GetField())->GetInputFlag() ? RES_TXTATR_INPUTFIELD : RES_TXTATR_FIELD));
+ SwTextNode & rNode(pOldAttr->GetTextNode());
+ std::shared_ptr<SwPaM> pPamForTextField;
+ IDocumentContentOperations & rIDCO(rNode.GetDoc().getIDocumentContentOperations());
+ SwTextField::GetPamForTextField(*pOldAttr, pPamForTextField);
+ assert(pPamForTextField);
+ sal_Int32 const nStart(pPamForTextField->Start()->GetContentIndex());
+ rIDCO.DeleteAndJoin(*pPamForTextField);
+ // ATTENTION: rField is dead now! hope nobody accesses it...
+ bool bSuccess = rIDCO.InsertPoolItem(*pPamForTextField, tempFormat);
+ assert(bSuccess);
+ (void) bSuccess;
+ SwTextField const* pNewAttr(rNode.GetFieldTextAttrAt(nStart, ::sw::GetTextAttrMode::Default));
+ assert(pNewAttr);
+ SwFormatField const& rNewFormat(pNewAttr->GetFormatField());
+ assert(rNewFormat.Which() == (static_cast<SwSetExpField const*>(rNewFormat.GetField())->GetInputFlag() ? RES_TXTATR_INPUTFIELD : RES_TXTATR_FIELD));
+ assert(static_cast<SwSetExpField const*>(rNewFormat.GetField())->GetInputFlag() == (dynamic_cast<SwTextInputField const*>(pNewAttr) != nullptr));
+ if (pXField)
+ {
+ pXField->m_pImpl->SetFormatField(const_cast<SwFormatField*>(&rNewFormat), &rNode.GetDoc());
+ const_cast<SwFormatField&>(rNewFormat).SetXTextField(pXField);
+ }
+}
+
+void SAL_CALL SwXTextField::attachTextFieldMaster(
+ const uno::Reference< beans::XPropertySet > & xFieldMaster)
+{
+ SolarMutexGuard aGuard;
+
+ if (!m_pImpl->IsDescriptor())
+ throw uno::RuntimeException();
+ SwXFieldMaster* pMaster = dynamic_cast<SwXFieldMaster*>(xFieldMaster.get());
+
+ SwFieldType* pFieldType = pMaster ? pMaster->GetFieldType() : nullptr;
+ if (!pFieldType ||
+ pFieldType->Which() != lcl_ServiceIdToResId(m_pImpl->m_nServiceId))
+ {
+ throw lang::IllegalArgumentException();
+ }
+ m_pImpl->m_sTypeName = pFieldType->GetName();
+ m_pImpl->SetFieldType(*pFieldType);
+}
+
+uno::Reference< beans::XPropertySet > SAL_CALL
+SwXTextField::getTextFieldMaster()
+{
+ SolarMutexGuard aGuard;
+
+ SwFieldType* pType = m_pImpl->GetFieldType();
+ if (!pType && !m_pImpl->m_pDoc) // tdf#152619
+ return nullptr;
+ uno::Reference<beans::XPropertySet> const xRet(
+ SwXFieldMaster::CreateXFieldMaster(m_pImpl->m_pDoc, pType));
+ return xRet;
+}
+
+OUString SAL_CALL SwXTextField::getPresentation(sal_Bool bShowCommand)
+{
+ SolarMutexGuard aGuard;
+
+ SwField const*const pField = m_pImpl->GetField();
+ if (!pField)
+ {
+ throw uno::RuntimeException();
+ }
+ return bShowCommand ? pField->GetFieldName() : pField->ExpandField(true, nullptr);
+}
+
+void SAL_CALL SwXTextField::attach(
+ const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+ if (m_pImpl->IsDescriptor())
+ {
+ SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+
+ SwDoc* pDoc = pRange ? &pRange->GetDoc() : pCursor ? pCursor->GetDoc() : nullptr;
+ // if a FieldMaster was attached, then the document is already fixed!
+ // NOTE: sw.SwXAutoTextEntry unoapi test depends on m_pDoc = 0 being valid
+ if (!pDoc || (m_pImpl->m_pDoc && m_pImpl->m_pDoc != pDoc))
+ throw lang::IllegalArgumentException();
+
+ SwUnoInternalPaM aPam(*pDoc);
+ // this now needs to return TRUE
+ ::sw::XTextRangeToSwPaM(aPam, xTextRange);
+ std::unique_ptr<SwField> xField;
+ switch (m_pImpl->m_nServiceId)
+ {
+ case SwServiceType::FieldTypeAnnotation:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Postit);
+
+ DateTime aDateTime( DateTime::EMPTY );
+ if (m_pImpl->m_pProps->pDateTime)
+ {
+ aDateTime = *(m_pImpl->m_pProps->pDateTime);
+ }
+
+ sal_uInt32 nImportedId = 0;
+ if (!m_pImpl->m_pProps->sPar6.isEmpty())
+ nImportedId = m_pImpl->m_pProps->sPar6.toInt32(16);
+ sal_uInt32 nParentId = 0;
+ if (!m_pImpl->m_pProps->sPar5.isEmpty())
+ nParentId = m_pImpl->m_pProps->sPar5.toInt32(16);
+
+ SwPostItField* pPostItField = new SwPostItField(
+ static_cast<SwPostItFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1, // author
+ m_pImpl->m_pProps->sPar2, // content
+ m_pImpl->m_pProps->sPar3, // author's initials
+ m_pImpl->m_pProps->sPar4, // name
+ aDateTime,
+ m_pImpl->m_pProps->bBool1, // resolvedflag
+ 0, // id
+ nParentId, // parent id
+ nImportedId, // imported para id
+ 0, // PostIt Parent ID.
+ m_pImpl->m_pProps->sPar7
+ );
+ if ( m_pImpl->m_xTextObject.is() )
+ {
+ pPostItField->SetTextObject( m_pImpl->m_xTextObject->CreateText() );
+ pPostItField->SetPar2(m_pImpl->m_xTextObject->GetText());
+ }
+ xField.reset(pPostItField);
+ }
+ break;
+ case SwServiceType::FieldTypeScript:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Script);
+ xField.reset(new SwScriptField(static_cast<SwScriptFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1, m_pImpl->m_pProps->sPar2,
+ m_pImpl->m_pProps->bBool1));
+ }
+ break;
+ case SwServiceType::FieldTypeDateTime:
+ {
+ sal_uInt16 nSub = 0;
+ if (m_pImpl->m_pProps->bBool1)
+ nSub |= FIXEDFLD;
+ if (m_pImpl->m_pProps->bBool2)
+ nSub |= DATEFLD;
+ else
+ nSub |= TIMEFLD;
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DateTime);
+ SwDateTimeField *const pDTField = new SwDateTimeField(
+ static_cast<SwDateTimeFieldType*>(pFieldType),
+ nSub, m_pImpl->m_pProps->nFormat);
+ xField.reset(pDTField);
+ if (m_pImpl->m_pProps->fDouble > 0.)
+ {
+ pDTField->SetValue(m_pImpl->m_pProps->fDouble);
+ }
+ if (m_pImpl->m_pProps->pDateTime)
+ {
+ uno::Any aVal; aVal <<= *m_pImpl->m_pProps->pDateTime;
+ xField->PutValue( aVal, FIELD_PROP_DATE_TIME );
+ }
+ pDTField->SetOffset(m_pImpl->m_pProps->nSubType);
+ }
+ break;
+ case SwServiceType::FieldTypeFileName:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Filename);
+ sal_Int32 nFormat = m_pImpl->m_pProps->nFormat;
+ if (m_pImpl->m_pProps->bBool2)
+ nFormat |= FF_FIXED;
+ SwFileNameField *const pFNField = new SwFileNameField(
+ static_cast<SwFileNameFieldType*>(pFieldType), nFormat);
+ xField.reset(pFNField);
+ if (!m_pImpl->m_pProps->sPar3.isEmpty())
+ pFNField->SetExpansion(m_pImpl->m_pProps->sPar3);
+ uno::Any aFormat;
+ aFormat <<= m_pImpl->m_pProps->nFormat;
+ xField->PutValue( aFormat, FIELD_PROP_FORMAT );
+ }
+ break;
+ case SwServiceType::FieldTypeTemplateName:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::TemplateName);
+ xField.reset(new SwTemplNameField(static_cast<SwTemplNameFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nFormat));
+ uno::Any aFormat;
+ aFormat <<= m_pImpl->m_pProps->nFormat;
+ xField->PutValue(aFormat, FIELD_PROP_FORMAT);
+ }
+ break;
+ case SwServiceType::FieldTypeChapter:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Chapter);
+ SwChapterField *const pChapterField = new SwChapterField(
+ static_cast<SwChapterFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nUSHORT1);
+ xField.reset(pChapterField);
+ pChapterField->SetLevel(m_pImpl->m_pProps->nByte1);
+ uno::Any aVal;
+ aVal <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT1);
+ xField->PutValue(aVal, FIELD_PROP_USHORT1 );
+ }
+ break;
+ case SwServiceType::FieldTypeAuthor:
+ {
+ tools::Long nFormat = m_pImpl->m_pProps->bBool1 ? AF_NAME : AF_SHORTCUT;
+ if (m_pImpl->m_pProps->bBool2)
+ nFormat |= AF_FIXED;
+
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Author);
+ SwAuthorField *const pAuthorField = new SwAuthorField(
+ static_cast<SwAuthorFieldType*>(pFieldType), nFormat);
+ xField.reset(pAuthorField);
+ pAuthorField->SetExpansion(m_pImpl->m_pProps->sPar1);
+ }
+ break;
+ case SwServiceType::FieldTypeConditionedText:
+ case SwServiceType::FieldTypeHiddenText:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenText);
+ SwHiddenTextField *const pHTField = new SwHiddenTextField(
+ static_cast<SwHiddenTextFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1,
+ m_pImpl->m_pProps->sPar2, m_pImpl->m_pProps->sPar3,
+ SwServiceType::FieldTypeHiddenText == m_pImpl->m_nServiceId ?
+ SwFieldTypesEnum::HiddenText : SwFieldTypesEnum::ConditionalText);
+ xField.reset(pHTField);
+ pHTField->SetValue(m_pImpl->m_pProps->bBool1);
+ uno::Any aVal;
+ aVal <<= m_pImpl->m_pProps->sPar4;
+ xField->PutValue(aVal, FIELD_PROP_PAR4 );
+ }
+ break;
+ case SwServiceType::FieldTypeHiddenPara:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::HiddenPara);
+ SwHiddenParaField *const pHPField = new SwHiddenParaField(
+ static_cast<SwHiddenParaFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1);
+ xField.reset(pHPField);
+ pHPField->SetHidden(m_pImpl->m_pProps->bBool1);
+ }
+ break;
+ case SwServiceType::FieldTypeGetReference:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetRef);
+ xField.reset(new SwGetRefField(static_cast<SwGetRefFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1,
+ m_pImpl->m_pProps->sPar4,
+ 0,
+ 0,
+ 0,
+ 0));
+ if (!m_pImpl->m_pProps->sPar3.isEmpty())
+ static_cast<SwGetRefField*>(xField.get())->SetExpand(m_pImpl->m_pProps->sPar3);
+ uno::Any aVal;
+ aVal <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT1);
+ xField->PutValue(aVal, FIELD_PROP_USHORT1 );
+ aVal <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT2);
+ xField->PutValue(aVal, FIELD_PROP_USHORT2 );
+ aVal <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT3);
+ xField->PutValue(aVal, FIELD_PROP_USHORT3 );
+ aVal <<= m_pImpl->m_pProps->nSHORT1;
+ xField->PutValue(aVal, FIELD_PROP_SHORT1 );
+ }
+ break;
+ case SwServiceType::FieldTypeJumpEdit:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::JumpEdit);
+ xField.reset(new SwJumpEditField(static_cast<SwJumpEditFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nUSHORT1, m_pImpl->m_pProps->sPar2,
+ m_pImpl->m_pProps->sPar1));
+ }
+ break;
+ case SwServiceType::FieldTypeDocInfoChangeAuthor:
+ case SwServiceType::FieldTypeDocInfoChangeDateTime:
+ case SwServiceType::FieldTypeDocInfoEditTime:
+ case SwServiceType::FieldTypeDocInfoDescription:
+ case SwServiceType::FieldTypeDocInfoCreateAuthor:
+ case SwServiceType::FieldTypeDocInfoCreateDateTime:
+ case SwServiceType::FieldTypeDocInfoCustom:
+ case SwServiceType::FieldTypeDocInfoPrintAuthor:
+ case SwServiceType::FieldTypeDocInfoPrintDateTime:
+ case SwServiceType::FieldTypeDocInfoKeywords:
+ case SwServiceType::FieldTypeDocInfoSubject:
+ case SwServiceType::FieldTypeDocInfoTitle:
+ case SwServiceType::FieldTypeDocInfoRevision:
+ case SwServiceType::FieldTypeDocInfo:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocInfo);
+ sal_uInt16 nSubType = aDocInfoSubTypeFromService[
+ static_cast<sal_uInt16>(m_pImpl->m_nServiceId) - sal_uInt16(SwServiceType::FieldTypeDocInfoChangeAuthor)];
+ if (SwServiceType::FieldTypeDocInfoChangeDateTime == m_pImpl->m_nServiceId ||
+ SwServiceType::FieldTypeDocInfoCreateDateTime == m_pImpl->m_nServiceId ||
+ SwServiceType::FieldTypeDocInfoPrintDateTime == m_pImpl->m_nServiceId ||
+ SwServiceType::FieldTypeDocInfoEditTime == m_pImpl->m_nServiceId)
+ {
+ if (m_pImpl->m_pProps->bBool2) //IsDate
+ {
+ nSubType &= 0xf0ff;
+ nSubType |= DI_SUB_DATE;
+ }
+ else
+ {
+ nSubType &= 0xf0ff;
+ nSubType |= DI_SUB_TIME;
+ }
+ }
+ if (m_pImpl->m_pProps->bBool1)
+ nSubType |= DI_SUB_FIXED;
+ xField.reset(new SwDocInfoField(
+ static_cast<SwDocInfoFieldType*>(pFieldType), nSubType,
+ m_pImpl->m_pProps->sPar4, m_pImpl->m_pProps->nFormat));
+ if (!m_pImpl->m_pProps->sPar3.isEmpty())
+ static_cast<SwDocInfoField*>(xField.get())->SetExpansion(m_pImpl->m_pProps->sPar3);
+ }
+ break;
+ case SwServiceType::FieldTypeUserExt:
+ {
+ sal_Int32 nFormat = 0;
+ if (m_pImpl->m_pProps->bBool1)
+ nFormat = AF_FIXED;
+
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::ExtUser);
+ SwExtUserField *const pEUField = new SwExtUserField(
+ static_cast<SwExtUserFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nUSHORT1, nFormat);
+ xField.reset(pEUField);
+ pEUField->SetExpansion(m_pImpl->m_pProps->sPar1);
+ }
+ break;
+ case SwServiceType::FieldTypeUser:
+ {
+ SwFieldType* pFieldType =
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::User, m_pImpl->m_sTypeName, true);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ sal_uInt16 nUserSubType = (m_pImpl->m_pProps->bBool1)
+ ? nsSwExtendedSubType::SUB_INVISIBLE : 0;
+ if (m_pImpl->m_pProps->bBool2)
+ nUserSubType |= nsSwExtendedSubType::SUB_CMD;
+ if (m_pImpl->m_pProps->bFormatIsDefault &&
+ nsSwGetSetExpType::GSE_STRING == static_cast<SwUserFieldType*>(pFieldType)->GetType())
+ {
+ m_pImpl->m_pProps->nFormat = -1;
+ }
+ xField.reset(new SwUserField(static_cast<SwUserFieldType*>(pFieldType),
+ nUserSubType,
+ m_pImpl->m_pProps->nFormat));
+ }
+ break;
+ case SwServiceType::FieldTypeRefPageSet:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::RefPageSet);
+ xField.reset(new SwRefPageSetField( static_cast<SwRefPageSetFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nUSHORT1,
+ m_pImpl->m_pProps->bBool1 ));
+ }
+ break;
+ case SwServiceType::FieldTypeRefPageGet:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::RefPageGet);
+ SwRefPageGetField *const pRGField = new SwRefPageGetField(
+ static_cast<SwRefPageGetFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nUSHORT1 );
+ xField.reset(pRGField);
+ pRGField->SetText(m_pImpl->m_pProps->sPar1, nullptr);
+ }
+ break;
+ case SwServiceType::FieldTypePageNum:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::PageNumber);
+ SwPageNumberField *const pPNField = new SwPageNumberField(
+ static_cast<SwPageNumberFieldType*>(pFieldType), PG_RANDOM,
+ m_pImpl->m_pProps->nFormat,
+ m_pImpl->m_pProps->nUSHORT1);
+ xField.reset(pPNField);
+ pPNField->SetUserString(m_pImpl->m_pProps->sPar1);
+ uno::Any aVal;
+ aVal <<= m_pImpl->m_pProps->nSubType;
+ xField->PutValue( aVal, FIELD_PROP_SUBTYPE );
+ }
+ break;
+ case SwServiceType::FieldTypeDDE:
+ {
+ SwFieldType* pFieldType =
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Dde, m_pImpl->m_sTypeName, true);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ xField.reset(new SwDDEField( static_cast<SwDDEFieldType*>(pFieldType) ));
+ }
+ break;
+ case SwServiceType::FieldTypeDatabaseName:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DatabaseName);
+ SwDBData aData;
+ aData.sDataSource = m_pImpl->m_pProps->sPar1;
+ aData.sCommand = m_pImpl->m_pProps->sPar2;
+ aData.nCommandType = m_pImpl->m_pProps->nSHORT1;
+ xField.reset(new SwDBNameField(static_cast<SwDBNameFieldType*>(pFieldType), aData));
+ sal_uInt16 nSubType = xField->GetSubType();
+ if (m_pImpl->m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ xField->SetSubType(nSubType);
+ }
+ break;
+ case SwServiceType::FieldTypeDatabaseNextSet:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pImpl->m_pProps->sPar1;
+ aData.sCommand = m_pImpl->m_pProps->sPar2;
+ aData.nCommandType = m_pImpl->m_pProps->nSHORT1;
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DbNextSet);
+ xField.reset(new SwDBNextSetField(static_cast<SwDBNextSetFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar3, aData));
+ }
+ break;
+ case SwServiceType::FieldTypeDatabaseNumSet:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pImpl->m_pProps->sPar1;
+ aData.sCommand = m_pImpl->m_pProps->sPar2;
+ aData.nCommandType = m_pImpl->m_pProps->nSHORT1;
+ xField.reset(new SwDBNumSetField( static_cast<SwDBNumSetFieldType*>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DbNumSet)),
+ m_pImpl->m_pProps->sPar3,
+ OUString::number(m_pImpl->m_pProps->nFormat),
+ aData ));
+ }
+ break;
+ case SwServiceType::FieldTypeDatabaseSetNum:
+ {
+ SwDBData aData;
+ aData.sDataSource = m_pImpl->m_pProps->sPar1;
+ aData.sCommand = m_pImpl->m_pProps->sPar2;
+ aData.nCommandType = m_pImpl->m_pProps->nSHORT1;
+ SwDBSetNumberField *const pDBSNField =
+ new SwDBSetNumberField(static_cast<SwDBSetNumberFieldType*>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DbSetNumber)), aData,
+ m_pImpl->m_pProps->nUSHORT1);
+ xField.reset(pDBSNField);
+ pDBSNField->SetSetNumber(m_pImpl->m_pProps->nFormat);
+ sal_uInt16 nSubType = xField->GetSubType();
+ if (m_pImpl->m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ xField->SetSubType(nSubType);
+ }
+ break;
+ case SwServiceType::FieldTypeDatabase:
+ {
+ SwFieldType* pFieldType =
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Database, m_pImpl->m_sTypeName, false);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ xField.reset(new SwDBField(static_cast<SwDBFieldType*>(pFieldType),
+ m_pImpl->m_pProps->nFormat));
+ static_cast<SwDBField*>(xField.get())->InitContent(m_pImpl->m_pProps->sPar1);
+ sal_uInt16 nSubType = xField->GetSubType();
+ if (m_pImpl->m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ xField->SetSubType(nSubType);
+ }
+ break;
+ case SwServiceType::FieldTypeSetExp:
+ {
+ SwFieldType* pFieldType =
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::SetExp, m_pImpl->m_sTypeName, true);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ // detect the field type's sub type and set an appropriate number format
+ if (m_pImpl->m_pProps->bFormatIsDefault &&
+ nsSwGetSetExpType::GSE_STRING == static_cast<SwSetExpFieldType*>(pFieldType)->GetType())
+ {
+ m_pImpl->m_pProps->nFormat = -1;
+ }
+ SwSetExpField *const pSEField = new SwSetExpField(
+ static_cast<SwSetExpFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar2,
+ m_pImpl->m_pProps->nUSHORT2 != USHRT_MAX ? //#i79471# the field can have a number format or a number_ing_ format
+ m_pImpl->m_pProps->nUSHORT2 : m_pImpl->m_pProps->nFormat);
+ xField.reset(pSEField);
+
+ sal_uInt16 nSubType = xField->GetSubType();
+ if (m_pImpl->m_pProps->bBool2)
+ nSubType &= ~nsSwExtendedSubType::SUB_INVISIBLE;
+ else
+ nSubType |= nsSwExtendedSubType::SUB_INVISIBLE;
+ if (m_pImpl->m_pProps->bBool3)
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= ~nsSwExtendedSubType::SUB_CMD;
+ xField->SetSubType(nSubType);
+ pSEField->SetSeqNumber(m_pImpl->m_pProps->nUSHORT1);
+ pSEField->SetInputFlag(m_pImpl->m_pProps->bBool1);
+ pSEField->SetPromptText(m_pImpl->m_pProps->sPar3);
+ if (!m_pImpl->m_pProps->sPar4.isEmpty())
+ pSEField->ChgExpStr(m_pImpl->m_pProps->sPar4, nullptr);
+
+ }
+ break;
+ case SwServiceType::FieldTypeGetExp:
+ {
+ sal_uInt16 nSubType;
+ switch (m_pImpl->m_pProps->nSubType)
+ {
+ case text::SetVariableType::STRING: nSubType = nsSwGetSetExpType::GSE_STRING; break;
+ case text::SetVariableType::VAR: nSubType = nsSwGetSetExpType::GSE_EXPR; break;
+ //case text::SetVariableType::SEQUENCE: nSubType = nsSwGetSetExpType::GSE_SEQ; break;
+ case text::SetVariableType::FORMULA: nSubType = nsSwGetSetExpType::GSE_FORMULA; break;
+ default:
+ OSL_FAIL("wrong value");
+ nSubType = nsSwGetSetExpType::GSE_EXPR;
+ }
+ //make sure the SubType matches the field type
+ SwFieldType* pSetExpField = pDoc->getIDocumentFieldsAccess().GetFieldType(
+ SwFieldIds::SetExp, m_pImpl->m_pProps->sPar1, false);
+ bool bSetGetExpFieldUninitialized = false;
+ if (pSetExpField)
+ {
+ if (nSubType != nsSwGetSetExpType::GSE_STRING &&
+ static_cast< SwSetExpFieldType* >(pSetExpField)->GetType() == nsSwGetSetExpType::GSE_STRING)
+ nSubType = nsSwGetSetExpType::GSE_STRING;
+ }
+ else
+ bSetGetExpFieldUninitialized = true; // #i82544#
+
+ if (m_pImpl->m_pProps->bBool2)
+ nSubType |= nsSwExtendedSubType::SUB_CMD;
+ else
+ nSubType &= ~nsSwExtendedSubType::SUB_CMD;
+ SwGetExpField *const pGEField = new SwGetExpField(
+ static_cast<SwGetExpFieldType*>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::GetExp)),
+ m_pImpl->m_pProps->sPar1, nSubType,
+ m_pImpl->m_pProps->nFormat);
+ xField.reset(pGEField);
+ //TODO: evaluate SubType!
+ if (!m_pImpl->m_pProps->sPar4.isEmpty())
+ pGEField->ChgExpStr(m_pImpl->m_pProps->sPar4, nullptr);
+ // #i82544#
+ if (bSetGetExpFieldUninitialized)
+ pGEField->SetLateInitialization();
+ }
+ break;
+ case SwServiceType::FieldTypeInputUser:
+ case SwServiceType::FieldTypeInput:
+ {
+ SwFieldType* pFieldType =
+ pDoc->getIDocumentFieldsAccess().GetFieldType(SwFieldIds::Input, m_pImpl->m_sTypeName, true);
+ if (!pFieldType)
+ throw uno::RuntimeException();
+ sal_uInt16 nInpSubType =
+ sal::static_int_cast<sal_uInt16>(
+ SwServiceType::FieldTypeInputUser == m_pImpl->m_nServiceId
+ ? INP_USR : INP_TXT);
+ SwInputField * pTextField =
+ new SwInputField(static_cast<SwInputFieldType*>(pFieldType),
+ m_pImpl->m_pProps->sPar1,
+ m_pImpl->m_pProps->sPar2,
+ nInpSubType);
+ pTextField->SetHelp(m_pImpl->m_pProps->sPar3);
+ pTextField->SetToolTip(m_pImpl->m_pProps->sPar4);
+
+ xField.reset(pTextField);
+ }
+ break;
+ case SwServiceType::FieldTypeMacro:
+ {
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Macro);
+ OUString aName;
+
+ // support for Scripting Framework macros
+ if (!m_pImpl->m_pProps->sPar4.isEmpty())
+ {
+ aName = m_pImpl->m_pProps->sPar4;
+ }
+ else
+ {
+ SwMacroField::CreateMacroString(aName,
+ m_pImpl->m_pProps->sPar1, m_pImpl->m_pProps->sPar3);
+ }
+ xField.reset(new SwMacroField(static_cast<SwMacroFieldType*>(pFieldType), aName,
+ m_pImpl->m_pProps->sPar2));
+ }
+ break;
+ case SwServiceType::FieldTypePageCount:
+ case SwServiceType::FieldTypeParagraphCount:
+ case SwServiceType::FieldTypeWordCount:
+ case SwServiceType::FieldTypeCharacterCount:
+ case SwServiceType::FieldTypeTableCount:
+ case SwServiceType::FieldTypeGraphicObjectCount:
+ case SwServiceType::FieldTypeEmbeddedObjectCount:
+ {
+ sal_uInt16 nSubType = DS_PAGE;
+ switch (m_pImpl->m_nServiceId)
+ {
+ case SwServiceType::FieldTypeParagraphCount : nSubType = DS_PARA; break;
+ case SwServiceType::FieldTypeWordCount : nSubType = DS_WORD; break;
+ case SwServiceType::FieldTypeCharacterCount : nSubType = DS_CHAR; break;
+ case SwServiceType::FieldTypeTableCount : nSubType = DS_TBL; break;
+ case SwServiceType::FieldTypeGraphicObjectCount : nSubType = DS_GRF; break;
+ case SwServiceType::FieldTypeEmbeddedObjectCount : nSubType = DS_OLE; break;
+ default: break;
+ }
+ SwFieldType* pFieldType = pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::DocStat);
+ xField.reset(new SwDocStatField(
+ static_cast<SwDocStatFieldType*>(pFieldType),
+ nSubType, m_pImpl->m_pProps->nUSHORT2));
+ }
+ break;
+ case SwServiceType::FieldTypeBibliography:
+ {
+ SwAuthorityFieldType const type(pDoc);
+ xField.reset(new SwAuthorityField(static_cast<SwAuthorityFieldType*>(
+ pDoc->getIDocumentFieldsAccess().InsertFieldType(type)),
+ u""));
+ if (m_pImpl->m_pProps->aPropSeq.hasElements())
+ {
+ uno::Any aVal;
+ aVal <<= m_pImpl->m_pProps->aPropSeq;
+ xField->PutValue( aVal, FIELD_PROP_PROP_SEQ );
+ }
+ }
+ break;
+ case SwServiceType::FieldTypeCombinedCharacters:
+ // create field
+ xField.reset(new SwCombinedCharField( static_cast<SwCombinedCharFieldType*>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::CombinedChars)),
+ m_pImpl->m_pProps->sPar1));
+ break;
+ case SwServiceType::FieldTypeDropdown:
+ {
+ SwDropDownField *const pDDField = new SwDropDownField(
+ static_cast<SwDropDownFieldType *>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Dropdown)));
+ xField.reset(pDDField);
+
+ pDDField->SetItems(m_pImpl->m_pProps->aStrings);
+ pDDField->SetSelectedItem(m_pImpl->m_pProps->sPar1);
+ pDDField->SetName(m_pImpl->m_pProps->sPar2);
+ pDDField->SetHelp(m_pImpl->m_pProps->sPar3);
+ pDDField->SetToolTip(m_pImpl->m_pProps->sPar4);
+ }
+ break;
+
+ case SwServiceType::FieldTypeTableFormula:
+ {
+ // create field
+ sal_uInt16 nType = nsSwGetSetExpType::GSE_FORMULA;
+ if (m_pImpl->m_pProps->bBool1)
+ {
+ nType |= nsSwExtendedSubType::SUB_CMD;
+ if (m_pImpl->m_pProps->bFormatIsDefault)
+ m_pImpl->m_pProps->nFormat = -1;
+ }
+ xField.reset(new SwTableField( static_cast<SwTableFieldType*>(
+ pDoc->getIDocumentFieldsAccess().GetSysFieldType(SwFieldIds::Table)),
+ m_pImpl->m_pProps->sPar2,
+ nType,
+ m_pImpl->m_pProps->nFormat));
+ static_cast<SwTableField*>(xField.get())->ChgExpStr(m_pImpl->m_pProps->sPar1);
+ }
+ break;
+ default: OSL_FAIL("What kind of type is that?");
+ }
+
+ if (!xField)
+ throw uno::RuntimeException("no SwField created?");
+
+ xField->SetAutomaticLanguage(!m_pImpl->m_pProps->bBool4);
+ SwFormatField aFormat(*xField);
+
+ UnoActionContext aCont(pDoc);
+ if (aPam.HasMark() &&
+ m_pImpl->m_nServiceId != SwServiceType::FieldTypeAnnotation)
+ {
+ pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
+ }
+
+ SwXTextCursor const*const pTextCursor(dynamic_cast<SwXTextCursor*>(pCursor));
+ const bool bForceExpandHints(
+ pTextCursor
+ && pTextCursor->IsAtEndOfMeta() );
+ const SetAttrMode nInsertFlags =
+ bForceExpandHints
+ ? SetAttrMode::FORCEHINTEXPAND
+ : SetAttrMode::DEFAULT;
+
+ if (*aPam.GetPoint() != *aPam.GetMark() &&
+ m_pImpl->m_nServiceId == SwServiceType::FieldTypeAnnotation)
+ {
+ // Make sure we always insert the field at the end
+ SwPaM aEnd(*aPam.End(), *aPam.End());
+ pDoc->getIDocumentContentOperations().InsertPoolItem(aEnd, aFormat, nInsertFlags);
+ }
+ else
+ pDoc->getIDocumentContentOperations().InsertPoolItem(aPam, aFormat, nInsertFlags);
+
+ SwTextAttr* pTextAttr = aPam.GetPointNode().GetTextNode()->GetFieldTextAttrAt(aPam.GetPoint()->GetContentIndex()-1, ::sw::GetTextAttrMode::Default);
+
+ // What about updating the fields? (see fldmgr.cxx)
+ if (!pTextAttr)
+ throw uno::RuntimeException("no SwTextAttr inserted?"); // could theoretically happen, if paragraph is full
+
+ m_pImpl->ClearFieldType();
+ const SwFormatField& rField = pTextAttr->GetFormatField();
+ m_pImpl->SetFormatField(const_cast<SwFormatField*>(&rField), pDoc);
+
+ if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION
+ && *aPam.GetPoint() != *aPam.GetMark() )
+ {
+ // create annotation mark
+ const SwPostItField* pPostItField = dynamic_cast< const SwPostItField* >(pTextAttr->GetFormatField().GetField());
+ OSL_ENSURE( pPostItField != nullptr, "<SwXTextField::attachToRange(..)> - annotation field missing!" );
+ if ( pPostItField != nullptr )
+ {
+ IDocumentMarkAccess* pMarksAccess = pDoc->getIDocumentMarkAccess();
+ pMarksAccess->makeAnnotationMark( aPam, pPostItField->GetName() );
+ }
+ }
+
+ xField.reset();
+
+ assert(m_pImpl->GetFormatField());
+ m_pImpl->m_pDoc = pDoc;
+ m_pImpl->GetFormatField()->SetXTextField(this);
+ m_pImpl->m_wThis = this;
+ m_pImpl->m_bIsDescriptor = false;
+ m_pImpl->m_pProps.reset();
+ if (m_pImpl->m_bCallUpdate)
+ update();
+ }
+ else if ( !m_pImpl->IsDescriptor()
+ && m_pImpl->m_pDoc != nullptr
+ && m_pImpl->m_nServiceId == SwServiceType::FieldTypeAnnotation )
+ {
+ SwDoc* pDoc = m_pImpl->m_pDoc;
+ SwUnoInternalPaM aIntPam( *pDoc );
+ if ( !::sw::XTextRangeToSwPaM( aIntPam, xTextRange ) )
+ throw lang::IllegalArgumentException();
+
+ // Nothing to do, if the text range has a separate start and end, but they have the same
+ // value.
+ if (!aIntPam.HasMark() || *aIntPam.Start() != *aIntPam.End())
+ {
+ UnoActionContext aCont( pDoc );
+ // insert copy of annotation at new text range
+ std::unique_ptr<SwPostItField> pPostItField(static_cast< SwPostItField* >(m_pImpl->GetFormatField()->GetField()->CopyField().release()));
+ SwFormatField aFormatField( *pPostItField );
+ pPostItField.reset();
+ SwPaM aEnd( *aIntPam.End(), *aIntPam.End() );
+ pDoc->getIDocumentContentOperations().InsertPoolItem( aEnd, aFormatField );
+ // delete former annotation
+ {
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
+ SwTextNode& rTextNode = *pTextField->GetpTextNode();
+ SwPaM aPam( rTextNode, pTextField->GetStart() );
+ aPam.SetMark();
+ aPam.Move();
+ pDoc->getIDocumentContentOperations().DeleteAndJoin(aPam);
+ }
+ // keep inserted annotation
+ {
+ SwTextField *const pTextAttr = aEnd.GetPointNode().GetTextNode()->GetFieldTextAttrAt(aEnd.End()->GetContentIndex()-1, ::sw::GetTextAttrMode::Default);
+ if ( pTextAttr != nullptr )
+ {
+ m_pImpl->SetFormatField(const_cast<SwFormatField*>(&pTextAttr->GetFormatField()), pDoc);
+
+ if ( *aIntPam.GetPoint() != *aIntPam.GetMark() )
+ {
+ // create annotation mark
+ const SwPostItField* pField = dynamic_cast< const SwPostItField* >(pTextAttr->GetFormatField().GetField());
+ OSL_ENSURE( pField != nullptr, "<SwXTextField::attach(..)> - annotation field missing!" );
+ if ( pField != nullptr )
+ {
+ IDocumentMarkAccess* pMarksAccess = aIntPam.GetDoc().getIDocumentMarkAccess();
+ pMarksAccess->makeAnnotationMark( aIntPam, pField->GetName() );
+ }
+ }
+ }
+ }
+ }
+
+ }
+ else
+ throw lang::IllegalArgumentException();
+}
+
+uno::Reference< text::XTextRange > SAL_CALL
+SwXTextField::getAnchor()
+{
+ SolarMutexGuard aGuard;
+
+ SwField const*const pField = m_pImpl->GetField();
+ if (!pField)
+ return nullptr;
+
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
+ if (!pTextField)
+ throw uno::RuntimeException();
+
+ std::shared_ptr< SwPaM > pPamForTextField;
+ SwTextField::GetPamForTextField(*pTextField, pPamForTextField);
+ if (pPamForTextField == nullptr)
+ return nullptr;
+
+ // If this is a postit field, then return the range of its annotation mark if it has one.
+ if (pField->Which() == SwFieldIds::Postit)
+ {
+ const SwPostItField* pPostItField = static_cast<const SwPostItField*>(pField);
+ IDocumentMarkAccess* pMarkAccess = m_pImpl->m_pDoc->getIDocumentMarkAccess();
+ for (IDocumentMarkAccess::const_iterator_t ppMark = pMarkAccess->getAnnotationMarksBegin(); ppMark != pMarkAccess->getAnnotationMarksEnd(); ++ppMark)
+ {
+ if ((*ppMark)->GetName() == pPostItField->GetName())
+ {
+ pPamForTextField = std::make_shared<SwPaM>((*ppMark)->GetMarkStart(), (*ppMark)->GetMarkEnd());
+ break;
+ }
+ }
+ }
+
+ rtl::Reference<SwXTextRange> xRange = SwXTextRange::CreateXTextRange(
+ *m_pImpl->m_pDoc, *(pPamForTextField->GetPoint()), pPamForTextField->GetMark());
+ return xRange;
+}
+
+void SAL_CALL SwXTextField::dispose()
+{
+ SolarMutexGuard aGuard;
+ SwField const*const pField = m_pImpl->GetField();
+ if(pField && m_pImpl->m_pDoc)
+ {
+ UnoActionContext aContext(m_pImpl->m_pDoc);
+ assert(m_pImpl->GetFormatField()->GetTextField() && "<SwXTextField::dispose()> - missing <SwTextField> --> crash");
+ SwTextField::DeleteTextField(*(m_pImpl->GetFormatField()->GetTextField()));
+ }
+
+ if (m_pImpl->m_xTextObject.is())
+ {
+ m_pImpl->m_xTextObject->DisposeEditSource();
+ m_pImpl->m_xTextObject.clear();
+ }
+ m_pImpl->Invalidate();
+}
+
+void SAL_CALL SwXTextField::addEventListener(
+ const uno::Reference<lang::XEventListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.addInterface(aGuard, xListener);
+}
+
+void SAL_CALL SwXTextField::removeEventListener(
+ const uno::Reference<lang::XEventListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_EventListeners.removeInterface(aGuard, xListener);
+}
+
+uno::Reference< beans::XPropertySetInfo > SAL_CALL
+SwXTextField::getPropertySetInfo()
+{
+ SolarMutexGuard aGuard;
+ // no static
+ uno::Reference< beans::XPropertySetInfo > aRef;
+ if (m_pImpl->m_nServiceId == SwServiceType::Invalid)
+ {
+ throw uno::RuntimeException();
+ }
+ const SfxItemPropertySet* pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService(m_pImpl->m_nServiceId));
+ const uno::Reference<beans::XPropertySetInfo>& xInfo = pPropSet->getPropertySetInfo();
+ // extend PropertySetInfo!
+ const uno::Sequence<beans::Property> aPropSeq = xInfo->getProperties();
+ aRef = new SfxExtItemPropertySetInfo(
+ aSwMapProvider.GetPropertyMapEntries(PROPERTY_MAP_PARAGRAPH_EXTENSIONS),
+ aPropSeq );
+ return aRef;
+}
+
+void SAL_CALL
+SwXTextField::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& rValue)
+{
+ SolarMutexGuard aGuard;
+ SwField const*const pField = m_pImpl->GetField();
+ const SfxItemPropertySet* _pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService(m_pImpl->m_nServiceId));
+ const SfxItemPropertyMapEntry* pEntry = _pPropSet->getPropertyMap().getByName(rPropertyName);
+
+ if (!pEntry)
+ throw beans::UnknownPropertyException( "Unknown property: " + rPropertyName, getXWeak() );
+ if ( pEntry->nFlags & beans::PropertyAttribute::READONLY)
+ throw beans::PropertyVetoException( "Property is read-only: " + rPropertyName, getXWeak() );
+
+ if(pField)
+ {
+ // special treatment for mail merge fields
+ const SwFieldIds nWhich = pField->Which();
+ if( SwFieldIds::Database == nWhich &&
+ (rPropertyName == UNO_NAME_DATA_BASE_NAME ||
+ rPropertyName == UNO_NAME_DATA_BASE_URL||
+ rPropertyName == UNO_NAME_DATA_TABLE_NAME||
+ rPropertyName == UNO_NAME_DATA_COLUMN_NAME))
+ {
+ // here a new field type must be created and the field must
+ // be registered at the new type
+ OSL_FAIL("not implemented");
+ }
+ else
+ {
+ SwDoc * pDoc = m_pImpl->m_pDoc;
+ assert(pDoc);
+ const SwTextField* pTextField = m_pImpl->GetFormatField()->GetTextField();
+ if(!pTextField)
+ throw uno::RuntimeException();
+ SwPosition aPosition( pTextField->GetTextNode(), pTextField->GetStart() );
+ pDoc->getIDocumentFieldsAccess().PutValueToField( aPosition, rValue, pEntry->nWID);
+ }
+
+ //#i100374# notify SwPostIt about new field content
+ assert(m_pImpl->GetFormatField());
+ if (SwFieldIds::Postit == nWhich)
+ {
+ m_pImpl->GetFormatField()->Broadcast(
+ SwFormatFieldHint( nullptr, SwFormatFieldHintWhich::CHANGED ));
+ }
+
+ // fdo#42073 notify SwTextField about changes of the expanded string
+ if (m_pImpl->GetFormatField()->GetTextField())
+ {
+ m_pImpl->GetFormatField()->GetTextField()->ExpandTextField();
+ }
+
+ //#i100374# changing a document field should set the modify flag
+ SwDoc* pDoc = m_pImpl->m_pDoc;
+ if (pDoc)
+ pDoc->getIDocumentState().SetModified();
+
+ }
+ else if (m_pImpl->m_pProps)
+ {
+ bool* pBool = nullptr;
+ switch(pEntry->nWID)
+ {
+ case FIELD_PROP_PAR1:
+ rValue >>= m_pImpl->m_pProps->sPar1;
+ break;
+ case FIELD_PROP_PAR2:
+ rValue >>= m_pImpl->m_pProps->sPar2;
+ break;
+ case FIELD_PROP_PAR3:
+ rValue >>= m_pImpl->m_pProps->sPar3;
+ break;
+ case FIELD_PROP_PAR4:
+ rValue >>= m_pImpl->m_pProps->sPar4;
+ break;
+ case FIELD_PROP_PAR7:
+ rValue >>= m_pImpl->m_pProps->sPar7;
+ break;
+ case FIELD_PROP_PAR5:
+ rValue >>= m_pImpl->m_pProps->sPar5;
+ break;
+ case FIELD_PROP_PAR6:
+ rValue >>= m_pImpl->m_pProps->sPar6;
+ break;
+ case FIELD_PROP_FORMAT:
+ rValue >>= m_pImpl->m_pProps->nFormat;
+ m_pImpl->m_pProps->bFormatIsDefault = false;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ m_pImpl->m_pProps->nSubType = SWUnoHelper::GetEnumAsInt32(rValue);
+ break;
+ case FIELD_PROP_BYTE1 :
+ rValue >>= m_pImpl->m_pProps->nByte1;
+ break;
+ case FIELD_PROP_BOOL1 :
+ pBool = &m_pImpl->m_pProps->bBool1;
+ break;
+ case FIELD_PROP_BOOL2 :
+ pBool = &m_pImpl->m_pProps->bBool2;
+ break;
+ case FIELD_PROP_BOOL3 :
+ pBool = &m_pImpl->m_pProps->bBool3;
+ break;
+ case FIELD_PROP_BOOL4:
+ pBool = &m_pImpl->m_pProps->bBool4;
+ break;
+ case FIELD_PROP_DATE :
+ {
+ auto aTemp = o3tl::tryAccess<util::Date>(rValue);
+ if(!aTemp)
+ throw lang::IllegalArgumentException();
+
+ m_pImpl->m_pProps->aDate = Date(aTemp->Day, aTemp->Month, aTemp->Year);
+ }
+ break;
+ case FIELD_PROP_USHORT1:
+ case FIELD_PROP_USHORT2:
+ case FIELD_PROP_USHORT3:
+ {
+ sal_Int16 nVal = 0;
+ rValue >>= nVal;
+ if( FIELD_PROP_USHORT1 == pEntry->nWID)
+ m_pImpl->m_pProps->nUSHORT1 = nVal;
+ else if( FIELD_PROP_USHORT2 == pEntry->nWID)
+ m_pImpl->m_pProps->nUSHORT2 = nVal;
+ else
+ m_pImpl->m_pProps->nUSHORT3 = nVal;
+ }
+ break;
+ case FIELD_PROP_SHORT1:
+ rValue >>= m_pImpl->m_pProps->nSHORT1;
+ break;
+ case FIELD_PROP_DOUBLE:
+ if(rValue.getValueType() != ::cppu::UnoType<double>::get())
+ throw lang::IllegalArgumentException();
+ rValue >>= m_pImpl->m_pProps->fDouble;
+ break;
+
+ case FIELD_PROP_DATE_TIME :
+ if (!m_pImpl->m_pProps->pDateTime)
+ m_pImpl->m_pProps->pDateTime.reset( new util::DateTime );
+ rValue >>= *m_pImpl->m_pProps->pDateTime;
+ break;
+ case FIELD_PROP_PROP_SEQ:
+ rValue >>= m_pImpl->m_pProps->aPropSeq;
+ break;
+ case FIELD_PROP_STRINGS:
+ rValue >>= m_pImpl->m_pProps->aStrings;
+ break;
+ }
+ if (pBool)
+ {
+ std::optional<const bool> b = o3tl::tryAccess<bool>(rValue);
+ if( !b.has_value() )
+ throw lang::IllegalArgumentException();
+ *pBool = *b;
+
+ }
+ }
+ else
+ throw uno::RuntimeException();
+}
+
+uno::Any SAL_CALL SwXTextField::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ uno::Any aRet;
+ SwField const*const pField = m_pImpl->GetField();
+ const SfxItemPropertySet* _pPropSet = aSwMapProvider.GetPropertySet(
+ lcl_GetPropertyMapOfService(m_pImpl->m_nServiceId));
+ const SfxItemPropertyMapEntry* pEntry = _pPropSet->getPropertyMap().getByName(rPropertyName);
+ if(!pEntry )
+ {
+ const SfxItemPropertySet* _pParaPropSet = aSwMapProvider.GetPropertySet(PROPERTY_MAP_PARAGRAPH_EXTENSIONS);
+ pEntry = _pParaPropSet->getPropertyMap().getByName(rPropertyName);
+ }
+ if (!pEntry)
+ throw beans::UnknownPropertyException( "Unknown property: " + rPropertyName, getXWeak() );
+
+ switch( pEntry->nWID )
+ {
+ case FN_UNO_TEXT_WRAP:
+ aRet <<= text::WrapTextMode_NONE;
+ break;
+ case FN_UNO_ANCHOR_TYPE:
+ aRet <<= text::TextContentAnchorType_AS_CHARACTER;
+ break;
+ case FN_UNO_ANCHOR_TYPES:
+ {
+ uno::Sequence<text::TextContentAnchorType> aTypes { text::TextContentAnchorType_AS_CHARACTER };
+ aRet <<= aTypes;
+ }
+ break;
+
+ default:
+ if( pField )
+ {
+ if (FIELD_PROP_IS_FIELD_USED == pEntry->nWID ||
+ FIELD_PROP_IS_FIELD_DISPLAYED == pEntry->nWID)
+ {
+ bool bIsFieldUsed = false;
+ bool bIsFieldDisplayed = false;
+
+ // in order to have the information about fields
+ // correctly evaluated the document needs a layout
+ // (has to be already formatted)
+ SwDoc *pDoc = m_pImpl->m_pDoc;
+ SwViewShell *pViewShell = nullptr;
+ SwEditShell *pEditShell = nullptr;
+ if( pDoc )
+ {
+ pViewShell = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
+ pEditShell = pDoc->GetEditShell();
+ }
+
+ if (pEditShell)
+ pEditShell->CalcLayout();
+ else if (pViewShell) // a page preview has no SwEditShell it should only have a view shell
+ pViewShell->CalcLayout();
+ else
+ throw uno::RuntimeException();
+
+ // get text node for the text field
+ const SwFormatField *pFieldFormat =
+ (m_pImpl->GetField()) ? m_pImpl->GetFormatField() : nullptr;
+ const SwTextField* pTextField = pFieldFormat
+ ? m_pImpl->GetFormatField()->GetTextField() : nullptr;
+ if(!pTextField)
+ throw uno::RuntimeException();
+ const SwTextNode& rTextNode = pTextField->GetTextNode();
+
+ // skip fields that are currently not in the document
+ // e.g. fields in undo or redo array
+ if (rTextNode.GetNodes().IsDocNodes())
+ {
+ bool bFrame = 0 != rTextNode.FindLayoutRect().Width(); // or so
+ bool bHidden = rTextNode.IsHidden();
+ if ( !bHidden )
+ {
+ sal_Int32 nHiddenStart;
+ sal_Int32 nHiddenEnd;
+ bHidden = SwScriptInfo::GetBoundsOfHiddenRange( pTextField->GetTextNode(),
+ pTextField->GetStart(),
+ nHiddenStart, nHiddenEnd );
+ }
+
+ // !bFrame && !bHidden: most probably a field in an unused page style
+
+ // FME: Problem: hidden field in unused page template =>
+ // bIsFieldUsed = true
+ // bIsFieldDisplayed = false
+ bIsFieldUsed = bFrame || bHidden;
+ bIsFieldDisplayed = bIsFieldUsed && !bHidden;
+ }
+ aRet <<= (FIELD_PROP_IS_FIELD_USED == pEntry->nWID) ? bIsFieldUsed : bIsFieldDisplayed;
+ }
+ else
+ pField->QueryValue( aRet, pEntry->nWID );
+ }
+ else if (m_pImpl->m_pProps) // currently just a descriptor...
+ {
+ switch(pEntry->nWID)
+ {
+ case FIELD_PROP_TEXT:
+ {
+ if (!m_pImpl->m_xTextObject.is())
+ {
+ m_pImpl->m_xTextObject
+ = new SwTextAPIObject( std::make_unique<SwTextAPIEditSource>(m_pImpl->m_pDoc) );
+ }
+
+ uno::Reference<text::XText> xText(m_pImpl->m_xTextObject);
+ aRet <<= xText;
+ break;
+ }
+ case FIELD_PROP_PAR1:
+ aRet <<= m_pImpl->m_pProps->sPar1;
+ break;
+ case FIELD_PROP_PAR2:
+ aRet <<= m_pImpl->m_pProps->sPar2;
+ break;
+ case FIELD_PROP_PAR3:
+ aRet <<= m_pImpl->m_pProps->sPar3;
+ break;
+ case FIELD_PROP_PAR4:
+ aRet <<= m_pImpl->m_pProps->sPar4;
+ break;
+ case FIELD_PROP_PAR7:
+ aRet <<= m_pImpl->m_pProps->sPar7;
+ break;
+ case FIELD_PROP_PAR5:
+ aRet <<= m_pImpl->m_pProps->sPar5;
+ break;
+ case FIELD_PROP_PAR6:
+ aRet <<= m_pImpl->m_pProps->sPar6;
+ break;
+ case FIELD_PROP_FORMAT:
+ aRet <<= m_pImpl->m_pProps->nFormat;
+ break;
+ case FIELD_PROP_SUBTYPE:
+ aRet <<= m_pImpl->m_pProps->nSubType;
+ break;
+ case FIELD_PROP_BYTE1 :
+ aRet <<= m_pImpl->m_pProps->nByte1;
+ break;
+ case FIELD_PROP_BOOL1 :
+ aRet <<= m_pImpl->m_pProps->bBool1;
+ break;
+ case FIELD_PROP_BOOL2 :
+ aRet <<= m_pImpl->m_pProps->bBool2;
+ break;
+ case FIELD_PROP_BOOL3 :
+ aRet <<= m_pImpl->m_pProps->bBool3;
+ break;
+ case FIELD_PROP_BOOL4 :
+ aRet <<= m_pImpl->m_pProps->bBool4;
+ break;
+ case FIELD_PROP_DATE :
+ aRet <<= m_pImpl->m_pProps->aDate.GetUNODate();
+ break;
+ case FIELD_PROP_USHORT1:
+ aRet <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT1);
+ break;
+ case FIELD_PROP_USHORT2:
+ aRet <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT2);
+ break;
+ case FIELD_PROP_USHORT3:
+ aRet <<= static_cast<sal_Int16>(m_pImpl->m_pProps->nUSHORT3);
+ break;
+ case FIELD_PROP_SHORT1:
+ aRet <<= m_pImpl->m_pProps->nSHORT1;
+ break;
+ case FIELD_PROP_DOUBLE:
+ aRet <<= m_pImpl->m_pProps->fDouble;
+ break;
+ case FIELD_PROP_DATE_TIME :
+ if (m_pImpl->m_pProps->pDateTime)
+ aRet <<= *m_pImpl->m_pProps->pDateTime;
+ break;
+ case FIELD_PROP_PROP_SEQ:
+ aRet <<= m_pImpl->m_pProps->aPropSeq;
+ break;
+ case FIELD_PROP_STRINGS:
+ aRet <<= m_pImpl->m_pProps->aStrings;
+ break;
+ case FIELD_PROP_IS_FIELD_USED:
+ case FIELD_PROP_IS_FIELD_DISPLAYED:
+ aRet <<= false;
+ break;
+ }
+ }
+ else
+ throw uno::RuntimeException();
+ }
+ return aRet;
+}
+
+void SwXTextField::addPropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextField::removePropertyChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextField::addVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SwXTextField::removeVetoableChangeListener(const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+ OSL_FAIL("not implemented");
+}
+
+void SAL_CALL SwXTextField::update()
+{
+ SolarMutexGuard aGuard;
+ SwField * pField = const_cast<SwField*>(m_pImpl->GetField());
+ if (pField)
+ {
+ switch(pField->Which())
+ {
+ case SwFieldIds::DateTime:
+ static_cast<SwDateTimeField*>(pField)->SetDateTime( ::DateTime( ::DateTime::SYSTEM ) );
+ break;
+
+ case SwFieldIds::ExtUser:
+ {
+ SwExtUserField* pExtUserField = static_cast<SwExtUserField*>(pField);
+ pExtUserField->SetExpansion( SwExtUserFieldType::Expand(
+ pExtUserField->GetSubType() ) );
+ }
+ break;
+
+ case SwFieldIds::Author:
+ {
+ SwAuthorField* pAuthorField = static_cast<SwAuthorField*>(pField);
+ pAuthorField->SetExpansion( SwAuthorFieldType::Expand(
+ pAuthorField->GetFormat() ) );
+ }
+ break;
+
+ case SwFieldIds::Filename:
+ {
+ SwFileNameField* pFileNameField = static_cast<SwFileNameField*>(pField);
+ pFileNameField->SetExpansion( static_cast<SwFileNameFieldType*>(pField->GetTyp())->Expand(
+ pFileNameField->GetFormat() ) );
+ }
+ break;
+
+ case SwFieldIds::DocInfo:
+ {
+ SwDocInfoField* pDocInfField = static_cast<SwDocInfoField*>(pField);
+ pDocInfField->SetExpansion( static_cast<SwDocInfoFieldType*>(pField->GetTyp())->Expand(
+ pDocInfField->GetSubType(),
+ pDocInfField->GetFormat(),
+ pDocInfField->GetLanguage(),
+ pDocInfField->GetName() ) );
+ }
+ break;
+ default: break;
+ }
+ // Text formatting has to be triggered.
+ m_pImpl->GetFormatField()->ForceUpdateTextNode();
+ }
+ else
+ m_pImpl->m_bCallUpdate = true;
+}
+
+OUString SAL_CALL SwXTextField::getImplementationName()
+{
+ return "SwXTextField";
+}
+
+static OUString OldNameToNewName_Impl( const OUString &rOld )
+{
+ static const char aOldNamePart1[] = ".TextField.DocInfo.";
+ static const char aOldNamePart2[] = ".TextField.";
+ OUString sServiceNameCC( rOld );
+ sal_Int32 nIdx = sServiceNameCC.indexOf( aOldNamePart1 );
+ if (nIdx >= 0)
+ sServiceNameCC = sServiceNameCC.replaceAt( nIdx, strlen(aOldNamePart1), u".textfield.docinfo." );
+ nIdx = sServiceNameCC.indexOf( aOldNamePart2 );
+ if (nIdx >= 0)
+ sServiceNameCC = sServiceNameCC.replaceAt( nIdx, strlen(aOldNamePart2), u".textfield." );
+ return sServiceNameCC;
+}
+
+sal_Bool SAL_CALL SwXTextField::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SAL_CALL SwXTextField::getSupportedServiceNames()
+{
+ const OUString sServiceName =
+ SwXServiceProvider::GetProviderName(m_pImpl->m_nServiceId);
+
+ // case-corrected version of service-name (see #i67811)
+ // (need to supply both because of compatibility to older versions)
+ const OUString sServiceNameCC( OldNameToNewName_Impl( sServiceName ) );
+ sal_Int32 nLen = sServiceName == sServiceNameCC ? 2 : 3;
+
+ uno::Sequence< OUString > aRet( nLen );
+ OUString* pArray = aRet.getArray();
+ *pArray++ = sServiceName;
+ if (nLen == 3)
+ *pArray++ = sServiceNameCC;
+ *pArray++ = "com.sun.star.text.TextContent";
+ return aRet;
+}
+
+void SwXTextField::Impl::Invalidate()
+{
+ EndListeningAll();
+ m_pFormatField = nullptr;
+ m_pDoc = nullptr;
+ uno::Reference<uno::XInterface> const xThis(m_wThis);
+ if (!xThis.is())
+ { // fdo#72695: if UNO object is already dead, don't revive it with event
+ return;
+ }
+ lang::EventObject const ev(xThis);
+ std::unique_lock aGuard(m_Mutex);
+ m_EventListeners.disposeAndClear(aGuard, ev);
+}
+
+void SwXTextField::Impl::Notify(const SfxHint& rHint)
+{
+
+ if(rHint.GetId() == SfxHintId::Dying)
+ Invalidate();
+ else if (rHint.GetId() == SfxHintId::SwLegacyModify)
+ {
+ auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
+ switch(pLegacyHint->m_pOld ? pLegacyHint->m_pOld->Which() : 0)
+ {
+ case RES_REMOVE_UNO_OBJECT:
+ case RES_OBJECTDYING:
+ Invalidate();
+ break;
+ }
+ }
+}
+
+const SwField* SwXTextField::Impl::GetField() const
+{
+ return m_pFormatField ? m_pFormatField->GetField() : nullptr;
+}
+
+OUString SwXTextFieldMasters::getImplementationName()
+{
+ return "SwXTextFieldMasters";
+}
+
+sal_Bool SwXTextFieldMasters::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXTextFieldMasters::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.TextFieldMasters" };
+ return aRet;
+}
+
+SwXTextFieldMasters::SwXTextFieldMasters(SwDoc* _pDoc) :
+ SwUnoCollection(_pDoc)
+{
+}
+
+SwXTextFieldMasters::~SwXTextFieldMasters()
+{
+
+}
+
+/*
+ Iteration over non-standard field types
+ USER/SETEXP/DDE/DATABASE
+ Thus the names are:
+ "com.sun.star.text.fieldmaster.User" + <field type name>
+ "com.sun.star.text.fieldmaster.DDE" + <field type name>
+ "com.sun.star.text.fieldmaster.SetExpression" + <field type name>
+ "com.sun.star.text.fieldmaster.DataBase" + <field type name>
+
+ If too much, maybe one could leave out the "com.sun.star.text".
+ */
+static SwFieldIds lcl_GetIdByName( OUString& rName, OUString& rTypeName )
+{
+ if (rName.startsWithIgnoreAsciiCase(COM_TEXT_FLDMASTER_CC))
+ rName = rName.copy(COM_TEXT_FLDMASTER_CC.getLength());
+
+ SwFieldIds nResId = SwFieldIds::Unknown;
+ sal_Int32 nIdx = 0;
+ rTypeName = rName.getToken( 0, '.', nIdx );
+ if (rTypeName == "User")
+ nResId = SwFieldIds::User;
+ else if (rTypeName == "DDE")
+ nResId = SwFieldIds::Dde;
+ else if (rTypeName == "SetExpression")
+ {
+ nResId = SwFieldIds::SetExp;
+
+ const OUString sFieldTypName( rName.getToken( 0, '.', nIdx ));
+ const OUString sUIName( SwStyleNameMapper::GetSpecialExtraUIName( sFieldTypName ) );
+
+ if( sUIName != sFieldTypName )
+ rName = comphelper::string::setToken(rName, 1, '.', sUIName);
+ }
+ else if (rTypeName.equalsIgnoreAsciiCase("DataBase"))
+ {
+ rName = rName.copy(RTL_CONSTASCII_LENGTH("DataBase."));
+ if (!rName.isEmpty())
+ {
+ // #i51815#
+ rName = "DataBase." + rName;
+ nResId = SwFieldIds::Database;
+ }
+ }
+ else if (rTypeName == "Bibliography")
+ nResId = SwFieldIds::TableOfAuthorities;
+ return nResId;
+}
+
+uno::Any SwXTextFieldMasters::getByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+
+ OUString sName(rName), sTypeName;
+ const SwFieldIds nResId = lcl_GetIdByName( sName, sTypeName );
+ if( SwFieldIds::Unknown == nResId )
+ throw container::NoSuchElementException(
+ "SwXTextFieldMasters::getByName(" + rName + ")",
+ css::uno::Reference<css::uno::XInterface>());
+
+ sName = sName.copy(std::min(sTypeName.getLength()+1, sName.getLength()));
+ auto& rDoc = GetDoc();
+ SwFieldType* pType = rDoc.getIDocumentFieldsAccess().GetFieldType(nResId, sName, true);
+ if(!pType)
+ throw container::NoSuchElementException(
+ "SwXTextFieldMasters::getByName(" + rName + ")",
+ css::uno::Reference<css::uno::XInterface>());
+
+ uno::Reference<beans::XPropertySet> const xRet(
+ SwXFieldMaster::CreateXFieldMaster(&rDoc, pType));
+ return uno::Any(xRet);
+}
+
+bool SwXTextFieldMasters::getInstanceName(
+ const SwFieldType& rFieldType, OUString& rName)
+{
+ OUString sField;
+
+ switch( rFieldType.Which() )
+ {
+ case SwFieldIds::User:
+ sField = "User." + rFieldType.GetName();
+ break;
+ case SwFieldIds::Dde:
+ sField = "DDE." + rFieldType.GetName();
+ break;
+
+ case SwFieldIds::SetExp:
+ sField = "SetExpression." + SwStyleNameMapper::GetSpecialExtraProgName( rFieldType.GetName() );
+ break;
+
+ case SwFieldIds::Database:
+ sField = "DataBase." + rFieldType.GetName().replaceAll(OUStringChar(DB_DELIM), ".");
+ break;
+
+ case SwFieldIds::TableOfAuthorities:
+ sField = "Bibliography";
+ break;
+
+ default:
+ return false;
+ }
+
+ rName += COM_TEXT_FLDMASTER_CC + sField;
+ return true;
+}
+
+uno::Sequence< OUString > SwXTextFieldMasters::getElementNames()
+{
+ SolarMutexGuard aGuard;
+
+ const SwFieldTypes* pFieldTypes = GetDoc().getIDocumentFieldsAccess().GetFieldTypes();
+ const size_t nCount = pFieldTypes->size();
+
+ std::vector<OUString> aFieldNames;
+ for( size_t i = 0; i < nCount; ++i )
+ {
+ SwFieldType& rFieldType = *((*pFieldTypes)[i]);
+
+ OUString sFieldName;
+ if (SwXTextFieldMasters::getInstanceName(rFieldType, sFieldName))
+ {
+ aFieldNames.push_back(sFieldName);
+ }
+ }
+
+ return comphelper::containerToSequence(aFieldNames);
+}
+
+sal_Bool SwXTextFieldMasters::hasByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+
+ OUString sName(rName), sTypeName;
+ const SwFieldIds nResId = lcl_GetIdByName( sName, sTypeName );
+ bool bRet = false;
+ if( SwFieldIds::Unknown != nResId )
+ {
+ sName = sName.copy(std::min(sTypeName.getLength()+1, sName.getLength()));
+ bRet = nullptr != GetDoc().getIDocumentFieldsAccess().GetFieldType(nResId, sName, true);
+ }
+ return bRet;
+}
+
+uno::Type SwXTextFieldMasters::getElementType()
+{
+ return cppu::UnoType<beans::XPropertySet>::get();
+
+}
+
+sal_Bool SwXTextFieldMasters::hasElements()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return true;
+}
+
+class SwXTextFieldTypes::Impl
+{
+public:
+ std::mutex m_Mutex; // just for OInterfaceContainerHelper3
+ ::comphelper::OInterfaceContainerHelper4<util::XRefreshListener> m_RefreshListeners;
+};
+
+OUString SwXTextFieldTypes::getImplementationName()
+{
+ return "SwXTextFieldTypes";
+}
+
+sal_Bool SwXTextFieldTypes::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXTextFieldTypes::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.TextFields" };
+ return aRet;
+}
+
+SwXTextFieldTypes::SwXTextFieldTypes(SwDoc* _pDoc)
+ : SwUnoCollection (_pDoc)
+ , m_pImpl(new Impl)
+{
+}
+
+SwXTextFieldTypes::~SwXTextFieldTypes()
+{
+}
+
+void SwXTextFieldTypes::Invalidate()
+{
+ SwUnoCollection::Invalidate();
+ lang::EventObject const ev(getXWeak());
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.disposeAndClear(aGuard, ev);
+}
+
+uno::Reference< container::XEnumeration > SwXTextFieldTypes::createEnumeration()
+{
+ SolarMutexGuard aGuard;
+ return new SwXFieldEnumeration(GetDoc());
+}
+
+uno::Type SwXTextFieldTypes::getElementType()
+{
+ return cppu::UnoType<text::XDependentTextField>::get();
+}
+
+sal_Bool SwXTextFieldTypes::hasElements()
+{
+ SolarMutexGuard aGuard;
+ if(!IsValid())
+ throw uno::RuntimeException();
+ return true; // they always exist
+}
+
+void SAL_CALL SwXTextFieldTypes::refresh()
+{
+ {
+ SolarMutexGuard aGuard;
+ auto& rDoc = GetDoc();
+ UnoActionContext aContext(&rDoc);
+ rDoc.getIDocumentStatistics().UpdateDocStat(false, true);
+ rDoc.getIDocumentFieldsAccess().UpdateFields(false);
+ }
+ // call refresh listeners (without SolarMutex locked)
+ lang::EventObject const event(getXWeak());
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.notifyEach(aGuard,
+ & util::XRefreshListener::refreshed, event);
+}
+
+void SAL_CALL SwXTextFieldTypes::addRefreshListener(
+ const uno::Reference<util::XRefreshListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.addInterface(aGuard, xListener);
+}
+
+void SAL_CALL SwXTextFieldTypes::removeRefreshListener(
+ const uno::Reference<util::XRefreshListener> & xListener)
+{
+ std::unique_lock aGuard(m_pImpl->m_Mutex);
+ m_pImpl->m_RefreshListeners.removeInterface(aGuard, xListener);
+}
+
+class SwXFieldEnumeration::Impl
+ : public SvtListener
+{
+public:
+ SwDoc* m_pDoc;
+ std::vector<uno::Reference<text::XTextField>> m_Items;
+ sal_Int32 m_nNextIndex; ///< index of next element to be returned
+
+ explicit Impl(SwDoc& rDoc)
+ : m_pDoc(&rDoc)
+ , m_nNextIndex(0)
+ {
+ StartListening(rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD)->GetNotifier());
+ }
+
+ virtual void Notify(const SfxHint& rHint) override
+ {
+ if(rHint.GetId() == SfxHintId::Dying)
+ m_pDoc = nullptr;
+ }
+};
+
+OUString SAL_CALL
+SwXFieldEnumeration::getImplementationName()
+{
+ return "SwXFieldEnumeration";
+}
+
+sal_Bool SAL_CALL SwXFieldEnumeration::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence<OUString> SAL_CALL
+SwXFieldEnumeration::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.FieldEnumeration" };
+}
+
+SwXFieldEnumeration::SwXFieldEnumeration(SwDoc & rDoc)
+ : m_pImpl(new Impl(rDoc))
+{
+ // build sequence
+ m_pImpl->m_Items.clear();
+
+ const SwFieldTypes* pFieldTypes = m_pImpl->m_pDoc->getIDocumentFieldsAccess().GetFieldTypes();
+ const size_t nCount = pFieldTypes->size();
+ for(size_t nType = 0; nType < nCount; ++nType)
+ {
+ const SwFieldType* pCurType = (*pFieldTypes)[nType].get();
+ std::vector<SwFormatField*> vFormatFields;
+ pCurType->GatherFields(vFormatFields);
+ std::for_each(vFormatFields.begin(), vFormatFields.end(),
+ [this](SwFormatField* pF) { m_pImpl->m_Items.push_back(SwXTextField::CreateXTextField(m_pImpl->m_pDoc, pF)); });
+ }
+ // now handle meta-fields, which are not SwFields
+ const std::vector< uno::Reference<text::XTextField> > MetaFields(
+ m_pImpl->m_pDoc->GetMetaFieldManager().getMetaFields() );
+ for (const auto & rMetaField : MetaFields)
+ {
+ m_pImpl->m_Items.push_back( rMetaField );
+ }
+ // also add fieldmarks
+ IDocumentMarkAccess& rMarksAccess(*rDoc.getIDocumentMarkAccess());
+ for (auto iter = rMarksAccess.getFieldmarksBegin(); iter != rMarksAccess.getFieldmarksEnd(); ++iter)
+ {
+ m_pImpl->m_Items.emplace_back(cppu::getXWeak(SwXFieldmark::CreateXFieldmark(rDoc, *iter).get()), uno::UNO_QUERY);
+ }
+}
+
+SwXFieldEnumeration::~SwXFieldEnumeration()
+{
+}
+
+sal_Bool SAL_CALL SwXFieldEnumeration::hasMoreElements()
+{
+ SolarMutexGuard aGuard;
+
+ return m_pImpl->m_nNextIndex < static_cast<sal_Int32>(m_pImpl->m_Items.size());
+}
+
+uno::Any SAL_CALL SwXFieldEnumeration::nextElement()
+{
+ SolarMutexGuard aGuard;
+
+ if (m_pImpl->m_nNextIndex >= static_cast<sal_Int32>(m_pImpl->m_Items.size()))
+ throw container::NoSuchElementException(
+ "SwXFieldEnumeration::nextElement",
+ css::uno::Reference<css::uno::XInterface>());
+
+ uno::Reference< text::XTextField > &rxField =
+ m_pImpl->m_Items[ m_pImpl->m_nNextIndex++ ];
+ uno::Any aRet;
+ aRet <<= rxField;
+ rxField = nullptr; // free memory for item that is no longer used
+ return aRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */