summaryrefslogtreecommitdiffstats
path: root/sw/source/uibase/uno/unoatxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/uibase/uno/unoatxt.cxx')
-rw-r--r--sw/source/uibase/uno/unoatxt.cxx993
1 files changed, 993 insertions, 0 deletions
diff --git a/sw/source/uibase/uno/unoatxt.cxx b/sw/source/uibase/uno/unoatxt.cxx
new file mode 100644
index 0000000000..7ea3d9db4e
--- /dev/null
+++ b/sw/source/uibase/uno/unoatxt.cxx
@@ -0,0 +1,993 @@
+/* -*- 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 <com/sun/star/io/IOException.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/container/ElementExistException.hpp>
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <rtl/character.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <svtools/unoevent.hxx>
+#include <sfx2/event.hxx>
+#include <glosdoc.hxx>
+#include <shellio.hxx>
+#include <initui.hxx>
+#include <gloslst.hxx>
+#include <unoatxt.hxx>
+#include <unomap.hxx>
+#include <unotextbodyhf.hxx>
+#include <unotextrange.hxx>
+#include <TextCursorHelper.hxx>
+#include <doc.hxx>
+#include <IDocumentContentOperations.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentFieldsAccess.hxx>
+#include <IDocumentState.hxx>
+#include <docsh.hxx>
+#include <swdll.hxx>
+#include <svl/hint.hxx>
+#include <tools/urlobj.hxx>
+#include <svl/macitem.hxx>
+#include <editeng/acorrcfg.hxx>
+#include <comphelper/servicehelper.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <cppuhelper/supportsservice.hxx>
+
+#include <memory>
+
+using namespace ::com::sun::star;
+
+SwXAutoTextContainer::SwXAutoTextContainer()
+{
+ m_pGlossaries = ::GetGlossaries();
+
+}
+
+SwXAutoTextContainer::~SwXAutoTextContainer()
+{
+
+}
+
+sal_Int32 SwXAutoTextContainer::getCount()
+{
+ OSL_ENSURE(m_pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32),
+ "SwXAutoTextContainer::getCount: too many items");
+ return static_cast<sal_Int32>(m_pGlossaries->GetGroupCnt());
+}
+
+uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ const size_t nCount = m_pGlossaries->GetGroupCnt();
+ if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount )
+ throw lang::IndexOutOfBoundsException();
+ return getByName(m_pGlossaries->GetGroupName( static_cast<size_t>(nIndex) ));
+}
+
+uno::Type SwXAutoTextContainer::getElementType()
+{
+ return cppu::UnoType<text::XAutoTextGroup>::get();
+
+}
+
+sal_Bool SwXAutoTextContainer::hasElements()
+{
+ // At least standard should always exists!
+ return true;
+}
+
+uno::Any SwXAutoTextContainer::getByName(const OUString& GroupName)
+{
+ SolarMutexGuard aGuard;
+
+ uno::Reference< text::XAutoTextGroup > xGroup;
+ if ( m_pGlossaries && hasByName( GroupName ) ) // group name already known?
+ // true = create group if not already available
+ xGroup = m_pGlossaries->GetAutoTextGroup( GroupName );
+
+ if ( !xGroup.is() )
+ throw container::NoSuchElementException();
+
+ return css::uno::Any( xGroup );
+}
+
+uno::Sequence< OUString > SwXAutoTextContainer::getElementNames()
+{
+ SolarMutexGuard aGuard;
+ const size_t nCount = m_pGlossaries->GetGroupCnt();
+ OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32),
+ "SwXAutoTextContainer::getElementNames: too many groups");
+
+ uno::Sequence< OUString > aGroupNames(static_cast<sal_Int32>(nCount));
+ OUString *pArr = aGroupNames.getArray();
+
+ for ( size_t i = 0; i < nCount; ++i )
+ {
+ // The names will be passed without a path extension.
+ pArr[i] = m_pGlossaries->GetGroupName(i).getToken(0, GLOS_DELIM);
+ }
+ return aGroupNames;
+}
+// Finds group names with or without path index.
+sal_Bool SwXAutoTextContainer::hasByName(const OUString& Name)
+{
+ SolarMutexGuard aGuard;
+ OUString sGroupName( m_pGlossaries->GetCompleteGroupName( Name ) );
+ if(!sGroupName.isEmpty())
+ return true;
+ return false;
+}
+
+uno::Reference< text::XAutoTextGroup > SwXAutoTextContainer::insertNewByName(
+ const OUString& aGroupName)
+{
+ SolarMutexGuard aGuard;
+ if(hasByName(aGroupName))
+ throw container::ElementExistException();
+ //check for non-ASCII characters
+ if(aGroupName.isEmpty())
+ {
+ throw lang::IllegalArgumentException("group name must not be empty", nullptr, 0);
+ }
+ for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++)
+ {
+ sal_Unicode cChar = aGroupName[nPos];
+ if (rtl::isAsciiAlphanumeric(cChar) ||
+ (cChar == '_') ||
+ (cChar == 0x20) ||
+ (cChar == GLOS_DELIM) )
+ {
+ continue;
+ }
+ throw lang::IllegalArgumentException("group name must contain a-z, A-z, '_', ' ' only", nullptr, 0);
+ }
+ OUString sGroup(aGroupName);
+ if (sGroup.indexOf(GLOS_DELIM)<0)
+ {
+ sGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+ m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM));
+
+ uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup );
+ OSL_ENSURE( xGroup.is(), "SwXAutoTextContainer::insertNewByName: no UNO object created? How this?" );
+ // We just inserted the group into the glossaries, so why doesn't it exist?
+
+ return xGroup;
+}
+
+void SwXAutoTextContainer::removeByName(const OUString& aGroupName)
+{
+ SolarMutexGuard aGuard;
+ // At first find the name with path extension
+ OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName );
+ if(sGroupName.isEmpty())
+ throw container::NoSuchElementException();
+ m_pGlossaries->DelGroupDoc(sGroupName);
+}
+
+OUString SwXAutoTextContainer::getImplementationName()
+{
+ return "SwXAutoTextContainer";
+}
+
+sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
+{
+ return { "com.sun.star.text.AutoTextContainer" };
+}
+
+SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName,
+ SwGlossaries* pGlos) :
+ m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)),
+ m_pGlossaries(pGlos),
+ m_sName(rName),
+ m_sGroupName(rName)
+{
+ OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ),
+ "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" );
+}
+
+SwXAutoTextGroup::~SwXAutoTextGroup()
+{
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getTitles()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+
+ uno::Sequence< OUString > aEntryTitles(nCount);
+ OUString *pArr = aEntryTitles.getArray();
+
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ pArr[i] = pGlosGroup->GetLongName(i);
+ return aEntryTitles;
+}
+
+void SwXAutoTextGroup::renameByName(const OUString& aElementName,
+ const OUString& aNewElementName, const OUString& aNewElementTitle)
+{
+ SolarMutexGuard aGuard;
+ // throw exception only if the programmatic name is to be changed into an existing name
+ if(aNewElementName != aElementName && hasByName(aNewElementName))
+ throw container::ElementExistException();
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName);
+ if(USHRT_MAX == nIdx)
+ throw lang::IllegalArgumentException();
+ OUString aNewShort(aNewElementName);
+ OUString aNewName(aNewElementTitle);
+ sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort );
+ sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName );
+
+ if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx)
+ && (nOldIdx == USHRT_MAX || nOldIdx == nIdx))
+ {
+ pGlosGroup->Rename( nIdx, &aNewShort, &aNewName );
+ if(pGlosGroup->GetError() != ERRCODE_NONE)
+ throw io::IOException();
+ }
+
+}
+
+static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange)
+{
+ SwNodes& rNds = rInsDoc.GetNodes();
+
+ SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
+ SwContentNode * pNd = aIdx.GetNode().GetContentNode();
+ SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0);
+
+ bool bRet = false;
+ rInsDoc.getIDocumentFieldsAccess().LockExpFields();
+ {
+ SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc());
+ SwPaM aPam(pDoc->GetNodes());
+ SwPaM * pPam(nullptr);
+ if(pxCursor)
+ {
+ pPam = pxCursor->GetPaM();
+ }
+ else
+ {
+ if (pxRange->GetPositions(aPam))
+ {
+ pPam = & aPam;
+ }
+ }
+ if (!pPam) { return false; }
+ bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly)
+ || bRet;
+ }
+
+ rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
+ if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
+ rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
+
+ return bRet;
+}
+
+uno::Reference< text::XAutoTextEntry > SwXAutoTextGroup::insertNewByName(const OUString& aName,
+ const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+ if(hasByName(aName))
+ throw container::ElementExistException();
+ if(!xTextRange.is())
+ throw uno::RuntimeException();
+
+ std::unique_ptr<SwTextBlocks> pGlosGroup;
+ if (m_pGlossaries)
+ pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName);
+ const OUString& sShortName(aName);
+ const OUString& sLongName(aTitle);
+ if (pGlosGroup && !pGlosGroup->GetError())
+ {
+ SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+
+ OUString sOnlyText;
+ OUString* pOnlyText = nullptr;
+ bool bNoAttr = !pxCursor && !pxRange;
+ if(bNoAttr)
+ {
+ sOnlyText = xTextRange->getString();
+ pOnlyText = &sOnlyText;
+ }
+
+ const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
+
+ SwDoc* pGDoc = pGlosGroup->GetDoc();
+
+ // Until there is an option for that, delete base util::URL
+ if(rCfg.IsSaveRelFile())
+ {
+ INetURLObject aTemp(pGlosGroup->GetFileName());
+ pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE));
+ }
+ else
+ pGlosGroup->SetBaseURL( OUString() );
+
+ sal_uInt16 nRet = USHRT_MAX;
+ if( pOnlyText )
+ nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText );
+ else
+ {
+ pGlosGroup->ClearDoc();
+ if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) )
+ {
+ pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
+ lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange);
+ pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE);
+ nRet = pGlosGroup->PutDoc();
+ }
+ }
+
+ if (nRet == USHRT_MAX)
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ pGlosGroup.reset();
+
+ uno::Reference< text::XAutoTextEntry > xEntry;
+
+ try
+ {
+ xEntry = m_pGlossaries ?
+ m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) :
+ uno::Reference< text::XAutoTextEntry >();
+ OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::insertNewByName: no UNO object created? How this?" );
+ // we just inserted the entry into the group, so why doesn't it exist?
+ }
+ catch (const container::ElementExistException&)
+ {
+ throw;
+ }
+ catch (const uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (const uno::Exception&)
+ {
+ css::uno::Any anyEx = cppu::getCaughtException();
+ throw css::lang::WrappedTargetRuntimeException(
+ "Error Getting AutoText!",
+ getXWeak(),
+ anyEx );
+ }
+
+ return xEntry;
+}
+
+void SwXAutoTextGroup::removeByName(const OUString& aEntryName)
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw container::NoSuchElementException();
+
+ sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName);
+ if ( nIdx == USHRT_MAX )
+ throw container::NoSuchElementException();
+
+ pGlosGroup->Delete(nIdx);
+}
+
+OUString SwXAutoTextGroup::getName()
+{
+ SolarMutexGuard aGuard;
+ return m_sName;
+}
+
+void SwXAutoTextGroup::setName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+ if( !m_pGlossaries )
+ throw uno::RuntimeException();
+
+ sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM );
+ sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM );
+
+ OUString aNewSuffix;
+ if (nNewDelimPos > -1)
+ aNewSuffix = rName.copy( nNewDelimPos + 1 );
+ OUString aOldSuffix;
+ if (nOldDelimPos > -1)
+ aOldSuffix = m_sName.copy( nOldDelimPos + 1 );
+
+ sal_Int32 nNewNumeric = aNewSuffix.toInt32();
+ sal_Int32 nOldNumeric = aOldSuffix.toInt32();
+
+ OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName );
+ OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName );
+
+ if ( m_sName == rName ||
+ ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) )
+ return;
+ OUString sNewGroup(rName);
+ if (sNewGroup.indexOf(GLOS_DELIM)<0)
+ {
+ sNewGroup += OUStringChar(GLOS_DELIM) + "0";
+ }
+
+ //the name must be saved, the group may be invalidated while in RenameGroupDoc()
+ SwGlossaries* pTempGlossaries = m_pGlossaries;
+
+ OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) );
+ if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) )
+ throw uno::RuntimeException();
+ m_sName = rName;
+ m_sGroupName = sNewGroup;
+ m_pGlossaries = pTempGlossaries;
+}
+
+sal_Int32 SwXAutoTextGroup::getCount()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ return static_cast<sal_Int32>(pGlosGroup->GetCount());
+}
+
+uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex)
+{
+ SolarMutexGuard aGuard;
+ if (!m_pGlossaries)
+ throw uno::RuntimeException();
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName));
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount)
+ throw lang::IndexOutOfBoundsException();
+ return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex)));
+}
+
+uno::Type SwXAutoTextGroup::getElementType()
+{
+ return cppu::UnoType<text::XAutoTextEntry>::get();
+
+}
+
+sal_Bool SwXAutoTextGroup::hasElements()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ return pGlosGroup->GetCount() > 0;
+
+}
+
+uno::Any SwXAutoTextGroup::getByName(const OUString& _rName)
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName );
+ OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" );
+ // we told it to create the object, so why didn't it?
+ return css::uno::Any( xEntry );
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getElementNames()
+{
+ SolarMutexGuard aGuard;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ uno::Sequence< OUString > aEntryNames(nCount);
+ OUString *pArr = aEntryNames.getArray();
+
+ for ( sal_uInt16 i = 0; i < nCount; i++ )
+ pArr[i] = pGlosGroup->GetShortName(i);
+ return aEntryNames;
+}
+
+sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName)
+{
+ SolarMutexGuard aGuard;
+ bool bRet = false;
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if (!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ const sal_uInt16 nCount = pGlosGroup->GetCount();
+ for( sal_uInt16 i = 0; i < nCount; ++i )
+ {
+ OUString sCompare(pGlosGroup->GetShortName(i));
+ if(sCompare.equalsIgnoreAsciiCase(rName))
+ {
+ bRet = true;
+ break;
+ }
+ }
+ return bRet;
+}
+
+uno::Reference< beans::XPropertySetInfo > SwXAutoTextGroup::getPropertySetInfo()
+{
+ static uno::Reference< beans::XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
+ return xRet;
+}
+
+void SwXAutoTextGroup::setPropertyValue(
+ const OUString& rPropertyName, const uno::Any& aValue)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
+
+ if(!pEntry)
+ throw beans::UnknownPropertyException(rPropertyName);
+
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+ switch(pEntry->nWID)
+ {
+ case WID_GROUP_TITLE:
+ {
+ OUString sNewTitle;
+ aValue >>= sNewTitle;
+ if(sNewTitle.isEmpty())
+ throw lang::IllegalArgumentException();
+ bool bChanged = sNewTitle != pGlosGroup->GetName();
+ pGlosGroup->SetName(sNewTitle);
+ if(bChanged && HasGlossaryList())
+ GetGlossaryList()->ClearGroups();
+ }
+ break;
+ }
+}
+
+uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName)
+{
+ SolarMutexGuard aGuard;
+ const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
+
+ if(!pEntry)
+ throw beans::UnknownPropertyException(rPropertyName);
+ std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
+ if(!pGlosGroup || pGlosGroup->GetError())
+ throw uno::RuntimeException();
+
+ uno::Any aAny;
+ switch(pEntry->nWID)
+ {
+ case WID_GROUP_PATH:
+ aAny <<= pGlosGroup->GetFileName();
+ break;
+ case WID_GROUP_TITLE:
+ aAny <<= pGlosGroup->GetName();
+ break;
+ }
+ return aAny;
+}
+
+void SwXAutoTextGroup::addPropertyChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::removePropertyChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::addVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::removeVetoableChangeListener(
+ const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+{
+}
+
+void SwXAutoTextGroup::Invalidate()
+{
+ m_pGlossaries = nullptr;
+ m_sName.clear();
+ m_sGroupName.clear();
+}
+
+OUString SwXAutoTextGroup::getImplementationName()
+{
+ return "SwXAutoTextGroup";
+}
+
+sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextGroup" };
+ return aRet;
+}
+
+SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName,
+ OUString aEntryName) :
+ m_pGlossaries(pGlss),
+ m_sGroupName(std::move(aGroupName)),
+ m_sEntryName(std::move(aEntryName))
+{
+}
+
+SwXAutoTextEntry::~SwXAutoTextEntry()
+{
+ SolarMutexGuard aGuard;
+
+ // ensure that any pending modifications are written
+ implFlushDocument( true );
+}
+
+void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc )
+{
+ if ( !m_xDocSh.is() )
+ return;
+
+ if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () )
+ m_xDocSh->Save();
+
+ if ( _bCloseDoc )
+ {
+ // stop listening at the document
+ EndListening( *m_xDocSh );
+
+ m_xDocSh->DoClose();
+ m_xDocSh.clear();
+ }
+}
+
+void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
+{
+ if ( &_rBC != m_xDocSh.get() )
+ return;
+
+// it's our document
+ if (_rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
+ {
+ const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(_rHint);
+ if (SfxEventHintId::PrepareCloseDoc == rEventHint.GetEventId())
+ {
+ implFlushDocument();
+ mxBodyText.clear();
+ EndListening( *m_xDocSh );
+ m_xDocSh.clear();
+ }
+ }
+ else
+ {
+ if ( SfxHintId::Deinitializing == _rHint.GetId() )
+ {
+ // our document is dying (possibly because we're shutting down, and the document was notified
+ // earlier than we are?)
+ // stop listening at the docu
+ EndListening( *m_xDocSh );
+ // and release our reference
+ m_xDocSh.clear();
+ }
+ }
+}
+
+void SwXAutoTextEntry::GetBodyText ()
+{
+ SolarMutexGuard aGuard;
+
+ m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false );
+ OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" );
+
+ // start listening at the document
+ StartListening( *m_xDocSh );
+
+ mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() );
+}
+
+void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&)
+{
+ SolarMutexGuard g;
+ implFlushDocument(true);
+}
+
+uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursor()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->createTextCursor();
+}
+
+uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursorByRange(
+ const uno::Reference< text::XTextRange > & aTextPosition)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->createTextCursorByRange ( aTextPosition );
+}
+
+void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertString ( xRange, aString, bAbsorb );
+}
+
+void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange,
+ sal_Int16 nControlCharacter, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb );
+}
+
+void SwXAutoTextEntry::insertTextContent(
+ const uno::Reference< text::XTextRange > & xRange,
+ const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->insertTextContent ( xRange, xContent, bAbsorb );
+}
+
+void SwXAutoTextEntry::removeTextContent(
+ const uno::Reference< text::XTextContent > & xContent)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->removeTextContent ( xContent );
+}
+
+uno::Reference< text::XText > SwXAutoTextEntry::getText()
+{
+ SolarMutexGuard aGuard;
+ uno::Reference< text::XText > xRet = static_cast<text::XText*>(this);
+ return xRet;
+}
+
+uno::Reference< text::XTextRange > SwXAutoTextEntry::getStart()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getStart();
+}
+
+uno::Reference< text::XTextRange > SwXAutoTextEntry::getEnd()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getEnd();
+}
+
+OUString SwXAutoTextEntry::getString()
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ return mxBodyText->getString();
+}
+
+void SwXAutoTextEntry::setString(const OUString& aString)
+{
+ SolarMutexGuard aGuard;
+ EnsureBodyText();
+ mxBodyText->setString( aString );
+}
+
+void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange)
+{
+ SolarMutexGuard aGuard;
+
+ // ensure that any pending modifications are written
+ // reason is that we're holding the _copy_ of the auto text, while the real auto text
+ // is stored somewhere. And below, we're not working with our copy, but only tell the target
+ // TextRange to work with the stored version.
+ // #96380# - 2003-03-03 - fs@openoffice.org
+ implFlushDocument();
+ // TODO: think about if we should pass "true" here
+ // The difference would be that when the next modification is made to this instance here, then
+ // we would be forced to open the document again, instead of working on our current copy.
+ // This means that we would reflect any changes which were done to the AutoText by foreign instances
+ // in the meantime
+
+ // The reference to xKeepAlive is needed during the whole call, likely because it could be a
+ // different object, not xTextRange itself, and the reference guards it from preliminary death
+ auto xKeepAlive( xTextRange );
+ SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+ OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
+ SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get());
+
+ SwDoc* pDoc = nullptr;
+ if (pRange)
+ pDoc = &pRange->GetDoc();
+ else if ( pCursor )
+ pDoc = pCursor->GetDoc();
+ else if ( pText && pText->GetDoc() )
+ {
+ xKeepAlive = pText->getStart();
+ pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get());
+ if (pCursor)
+ pDoc = pText->GetDoc();
+ }
+
+ if(!pDoc)
+ throw uno::RuntimeException();
+
+ SwPaM InsertPaM(pDoc->GetNodes());
+ if (pRange)
+ {
+ if (!pRange->GetPositions(InsertPaM))
+ {
+ throw uno::RuntimeException();
+ }
+ }
+ else
+ {
+ InsertPaM = *pCursor->GetPaM();
+ }
+
+ std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName));
+ const bool bResult = pBlock && !pBlock->GetError()
+ && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM);
+
+ if(!bResult)
+ throw uno::RuntimeException();
+}
+
+OUString SwXAutoTextEntry::getImplementationName()
+{
+ return "SwXAutoTextEntry";
+}
+
+sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
+{
+ return cppu::supportsService(this, rServiceName);
+}
+
+uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
+{
+ uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextEntry" };
+ return aRet;
+}
+
+uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents()
+{
+ return new SwAutoTextEventDescriptor( *this );
+}
+
+const struct SvEventDescription aAutotextEvents[] =
+{
+ { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" },
+ { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" },
+ { SvMacroItemId::NONE, nullptr }
+};
+
+SwAutoTextEventDescriptor::SwAutoTextEventDescriptor(
+ SwXAutoTextEntry& rAutoText ) :
+ SvBaseEventDescriptor(aAutotextEvents),
+ m_rAutoTextEntry(rAutoText)
+{
+}
+
+SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor()
+{
+}
+
+OUString SwAutoTextEventDescriptor::getImplementationName()
+{
+ return "SwAutoTextEventDescriptor";
+}
+
+void SwAutoTextEventDescriptor::replaceByName(
+ const SvMacroItemId nEvent,
+ const SvxMacro& rMacro)
+{
+ OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(),
+ "Strangely enough, the AutoText vanished!" );
+ OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
+ (nEvent == SvMacroItemId::SwStartInsGlossary) ,
+ "Unknown event ID" );
+
+ SwGlossaries *const pGlossaries =
+ const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
+ std::unique_ptr<SwTextBlocks> pBlocks(
+ pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
+ OSL_ENSURE( pBlocks,
+ "can't get autotext group; SwAutoTextEntry has illegal name?");
+
+ if( !pBlocks || pBlocks->GetError())
+ return;
+
+ sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
+ if( nIndex != USHRT_MAX )
+ {
+ SvxMacroTableDtor aMacroTable;
+ if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
+ {
+ aMacroTable.Insert( nEvent, rMacro );
+ pBlocks->SetMacroTable( nIndex, aMacroTable );
+ }
+ }
+ // else: ignore
+}
+
+void SwAutoTextEventDescriptor::getByName(
+ SvxMacro& rMacro,
+ const SvMacroItemId nEvent )
+{
+ OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" );
+ OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
+ (nEvent == SvMacroItemId::SwStartInsGlossary) ,
+ "Unknown event ID" );
+
+ SwGlossaries *const pGlossaries =
+ const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
+ std::unique_ptr<SwTextBlocks> pBlocks(
+ pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
+ OSL_ENSURE( pBlocks,
+ "can't get autotext group; SwAutoTextEntry has illegal name?");
+
+ // return empty macro, unless macro is found
+ OUString sEmptyStr;
+ SvxMacro aEmptyMacro(sEmptyStr, sEmptyStr);
+ rMacro = aEmptyMacro;
+
+ if ( !pBlocks || pBlocks->GetError())
+ return;
+
+ sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
+ if( nIndex != USHRT_MAX )
+ {
+ SvxMacroTableDtor aMacroTable;
+ if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
+ {
+ SvxMacro *pMacro = aMacroTable.Get( nEvent );
+ if( pMacro )
+ rMacro = *pMacro;
+ }
+ }
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
+SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*,
+ css::uno::Sequence<css::uno::Any> const &)
+{
+ //the module may not be loaded
+ SolarMutexGuard aGuard;
+ SwGlobals::ensure();
+ return cppu::acquire(new SwXAutoTextContainer());
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */