992 lines
31 KiB
C++
992 lines
31 KiB
C++
/* -*- 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(u"group name must not be empty"_ustr, 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(u"group name must contain a-z, A-z, '_', ' ' only"_ustr, 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 u"SwXAutoTextContainer"_ustr;
|
|
}
|
|
|
|
sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
|
|
{
|
|
return cppu::supportsService(this, rServiceName);
|
|
}
|
|
|
|
uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
|
|
{
|
|
return { u"com.sun.star.text.AutoTextContainer"_ustr };
|
|
}
|
|
|
|
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();
|
|
const OUString& aNewShort(aNewElementName);
|
|
const 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(
|
|
u"Error Getting AutoText!"_ustr,
|
|
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 u"SwXAutoTextGroup"_ustr;
|
|
}
|
|
|
|
sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
|
|
{
|
|
return cppu::supportsService(this, rServiceName);
|
|
}
|
|
|
|
uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
|
|
{
|
|
uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextGroup"_ustr };
|
|
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 u"SwXAutoTextEntry"_ustr;
|
|
}
|
|
|
|
sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
|
|
{
|
|
return cppu::supportsService(this, rServiceName);
|
|
}
|
|
|
|
uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
|
|
{
|
|
uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextEntry"_ustr };
|
|
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 u"SwAutoTextEventDescriptor"_ustr;
|
|
}
|
|
|
|
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;
|
|
rMacro = SvxMacro(sEmptyStr, sEmptyStr);
|
|
|
|
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: */
|