Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / uibase / uno / unoatxt.cxx
blob3f11446ab59ec61c7f3f5f627ddf21f983026abb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <com/sun/star/io/IOException.hpp>
23 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
24 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
25 #include <com/sun/star/container/ElementExistException.hpp>
26 #include <o3tl/safeint.hxx>
27 #include <osl/diagnose.h>
28 #include <rtl/character.hxx>
29 #include <utility>
30 #include <vcl/svapp.hxx>
31 #include <svtools/unoevent.hxx>
32 #include <sfx2/event.hxx>
33 #include <glosdoc.hxx>
34 #include <shellio.hxx>
35 #include <initui.hxx>
36 #include <gloslst.hxx>
37 #include <unoatxt.hxx>
38 #include <unomap.hxx>
39 #include <unotextbodyhf.hxx>
40 #include <unotextrange.hxx>
41 #include <TextCursorHelper.hxx>
42 #include <doc.hxx>
43 #include <IDocumentContentOperations.hxx>
44 #include <IDocumentRedlineAccess.hxx>
45 #include <IDocumentFieldsAccess.hxx>
46 #include <IDocumentState.hxx>
47 #include <docsh.hxx>
48 #include <swdll.hxx>
49 #include <svl/hint.hxx>
50 #include <tools/urlobj.hxx>
51 #include <svl/macitem.hxx>
52 #include <editeng/acorrcfg.hxx>
53 #include <comphelper/servicehelper.hxx>
54 #include <cppuhelper/exc_hlp.hxx>
55 #include <cppuhelper/supportsservice.hxx>
57 #include <memory>
59 using namespace ::com::sun::star;
61 SwXAutoTextContainer::SwXAutoTextContainer()
63 m_pGlossaries = ::GetGlossaries();
67 SwXAutoTextContainer::~SwXAutoTextContainer()
72 sal_Int32 SwXAutoTextContainer::getCount()
74 OSL_ENSURE(m_pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32),
75 "SwXAutoTextContainer::getCount: too many items");
76 return static_cast<sal_Int32>(m_pGlossaries->GetGroupCnt());
79 uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex)
81 SolarMutexGuard aGuard;
82 const size_t nCount = m_pGlossaries->GetGroupCnt();
83 if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount )
84 throw lang::IndexOutOfBoundsException();
85 return getByName(m_pGlossaries->GetGroupName( static_cast<size_t>(nIndex) ));
88 uno::Type SwXAutoTextContainer::getElementType()
90 return cppu::UnoType<text::XAutoTextGroup>::get();
94 sal_Bool SwXAutoTextContainer::hasElements()
96 // At least standard should always exists!
97 return true;
100 uno::Any SwXAutoTextContainer::getByName(const OUString& GroupName)
102 SolarMutexGuard aGuard;
104 uno::Reference< text::XAutoTextGroup > xGroup;
105 if ( m_pGlossaries && hasByName( GroupName ) ) // group name already known?
106 // true = create group if not already available
107 xGroup = m_pGlossaries->GetAutoTextGroup( GroupName );
109 if ( !xGroup.is() )
110 throw container::NoSuchElementException();
112 return css::uno::Any( xGroup );
115 uno::Sequence< OUString > SwXAutoTextContainer::getElementNames()
117 SolarMutexGuard aGuard;
118 const size_t nCount = m_pGlossaries->GetGroupCnt();
119 OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32),
120 "SwXAutoTextContainer::getElementNames: too many groups");
122 uno::Sequence< OUString > aGroupNames(static_cast<sal_Int32>(nCount));
123 OUString *pArr = aGroupNames.getArray();
125 for ( size_t i = 0; i < nCount; ++i )
127 // The names will be passed without a path extension.
128 pArr[i] = m_pGlossaries->GetGroupName(i).getToken(0, GLOS_DELIM);
130 return aGroupNames;
132 // Finds group names with or without path index.
133 sal_Bool SwXAutoTextContainer::hasByName(const OUString& Name)
135 SolarMutexGuard aGuard;
136 OUString sGroupName( m_pGlossaries->GetCompleteGroupName( Name ) );
137 if(!sGroupName.isEmpty())
138 return true;
139 return false;
142 uno::Reference< text::XAutoTextGroup > SwXAutoTextContainer::insertNewByName(
143 const OUString& aGroupName)
145 SolarMutexGuard aGuard;
146 if(hasByName(aGroupName))
147 throw container::ElementExistException();
148 //check for non-ASCII characters
149 if(aGroupName.isEmpty())
151 lang::IllegalArgumentException aIllegal;
152 aIllegal.Message = "group name must not be empty";
153 throw aIllegal;
155 for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++)
157 sal_Unicode cChar = aGroupName[nPos];
158 if (rtl::isAsciiAlphanumeric(cChar) ||
159 (cChar == '_') ||
160 (cChar == 0x20) ||
161 (cChar == GLOS_DELIM) )
163 continue;
165 lang::IllegalArgumentException aIllegal;
166 aIllegal.Message = "group name must contain a-z, A-z, '_', ' ' only";
167 throw aIllegal;
169 OUString sGroup(aGroupName);
170 if (sGroup.indexOf(GLOS_DELIM)<0)
172 sGroup += OUStringChar(GLOS_DELIM) + "0";
174 m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM));
176 uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup );
177 OSL_ENSURE( xGroup.is(), "SwXAutoTextContainer::insertNewByName: no UNO object created? How this?" );
178 // We just inserted the group into the glossaries, so why doesn't it exist?
180 return xGroup;
183 void SwXAutoTextContainer::removeByName(const OUString& aGroupName)
185 SolarMutexGuard aGuard;
186 // At first find the name with path extension
187 OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName );
188 if(sGroupName.isEmpty())
189 throw container::NoSuchElementException();
190 m_pGlossaries->DelGroupDoc(sGroupName);
193 OUString SwXAutoTextContainer::getImplementationName()
195 return "SwXAutoTextContainer";
198 sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
200 return cppu::supportsService(this, rServiceName);
203 uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
205 return { "com.sun.star.text.AutoTextContainer" };
208 SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName,
209 SwGlossaries* pGlos) :
210 m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)),
211 m_pGlossaries(pGlos),
212 m_sName(rName),
213 m_sGroupName(rName)
215 OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ),
216 "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" );
219 SwXAutoTextGroup::~SwXAutoTextGroup()
223 uno::Sequence< OUString > SwXAutoTextGroup::getTitles()
225 SolarMutexGuard aGuard;
226 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
227 if (!pGlosGroup || pGlosGroup->GetError())
228 throw uno::RuntimeException();
229 const sal_uInt16 nCount = pGlosGroup->GetCount();
231 uno::Sequence< OUString > aEntryTitles(nCount);
232 OUString *pArr = aEntryTitles.getArray();
234 for ( sal_uInt16 i = 0; i < nCount; i++ )
235 pArr[i] = pGlosGroup->GetLongName(i);
236 return aEntryTitles;
239 void SwXAutoTextGroup::renameByName(const OUString& aElementName,
240 const OUString& aNewElementName, const OUString& aNewElementTitle)
242 SolarMutexGuard aGuard;
243 // throw exception only if the programmatic name is to be changed into an existing name
244 if(aNewElementName != aElementName && hasByName(aNewElementName))
245 throw container::ElementExistException();
246 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
247 if(!pGlosGroup || pGlosGroup->GetError())
248 throw uno::RuntimeException();
250 const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName);
251 if(USHRT_MAX == nIdx)
252 throw lang::IllegalArgumentException();
253 OUString aNewShort(aNewElementName);
254 OUString aNewName(aNewElementTitle);
255 sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort );
256 sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName );
258 if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx)
259 && (nOldIdx == USHRT_MAX || nOldIdx == nIdx))
261 pGlosGroup->Rename( nIdx, &aNewShort, &aNewName );
262 if(pGlosGroup->GetError() != ERRCODE_NONE)
263 throw io::IOException();
268 static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange)
270 SwNodes& rNds = rInsDoc.GetNodes();
272 SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
273 SwContentNode * pNd = aIdx.GetNode().GetContentNode();
274 SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0);
276 bool bRet = false;
277 rInsDoc.getIDocumentFieldsAccess().LockExpFields();
279 SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc());
280 SwPaM aPam(pDoc->GetNodes());
281 SwPaM * pPam(nullptr);
282 if(pxCursor)
284 pPam = pxCursor->GetPaM();
286 else
288 if (pxRange->GetPositions(aPam))
290 pPam = & aPam;
293 if (!pPam) { return false; }
294 bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly)
295 || bRet;
298 rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
299 if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
300 rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
302 return bRet;
305 uno::Reference< text::XAutoTextEntry > SwXAutoTextGroup::insertNewByName(const OUString& aName,
306 const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange)
308 SolarMutexGuard aGuard;
309 if(hasByName(aName))
310 throw container::ElementExistException();
311 if(!xTextRange.is())
312 throw uno::RuntimeException();
314 std::unique_ptr<SwTextBlocks> pGlosGroup;
315 if (m_pGlossaries)
316 pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName);
317 const OUString& sShortName(aName);
318 const OUString& sLongName(aTitle);
319 if (pGlosGroup && !pGlosGroup->GetError())
321 SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
322 OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
324 OUString sOnlyText;
325 OUString* pOnlyText = nullptr;
326 bool bNoAttr = !pxCursor && !pxRange;
327 if(bNoAttr)
329 sOnlyText = xTextRange->getString();
330 pOnlyText = &sOnlyText;
333 const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
335 SwDoc* pGDoc = pGlosGroup->GetDoc();
337 // Until there is an option for that, delete base util::URL
338 if(rCfg.IsSaveRelFile())
340 INetURLObject aTemp(pGlosGroup->GetFileName());
341 pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE));
343 else
344 pGlosGroup->SetBaseURL( OUString() );
346 sal_uInt16 nRet = USHRT_MAX;
347 if( pOnlyText )
348 nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText );
349 else
351 pGlosGroup->ClearDoc();
352 if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) )
354 pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
355 lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange);
356 pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE);
357 nRet = pGlosGroup->PutDoc();
361 if (nRet == USHRT_MAX)
363 throw uno::RuntimeException();
366 pGlosGroup.reset();
368 uno::Reference< text::XAutoTextEntry > xEntry;
372 xEntry = m_pGlossaries ?
373 m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) :
374 uno::Reference< text::XAutoTextEntry >();
375 OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::insertNewByName: no UNO object created? How this?" );
376 // we just inserted the entry into the group, so why doesn't it exist?
378 catch (const container::ElementExistException&)
380 throw;
382 catch (const uno::RuntimeException&)
384 throw;
386 catch (const uno::Exception&)
388 css::uno::Any anyEx = cppu::getCaughtException();
389 throw css::lang::WrappedTargetRuntimeException(
390 "Error Getting AutoText!",
391 static_cast < OWeakObject * > ( this ),
392 anyEx );
395 return xEntry;
398 void SwXAutoTextGroup::removeByName(const OUString& aEntryName)
400 SolarMutexGuard aGuard;
401 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
402 if(!pGlosGroup || pGlosGroup->GetError())
403 throw container::NoSuchElementException();
405 sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName);
406 if ( nIdx == USHRT_MAX )
407 throw container::NoSuchElementException();
409 pGlosGroup->Delete(nIdx);
412 OUString SwXAutoTextGroup::getName()
414 SolarMutexGuard aGuard;
415 return m_sName;
418 void SwXAutoTextGroup::setName(const OUString& rName)
420 SolarMutexGuard aGuard;
421 if( !m_pGlossaries )
422 throw uno::RuntimeException();
424 sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM );
425 sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM );
427 OUString aNewSuffix;
428 if (nNewDelimPos > -1)
429 aNewSuffix = rName.copy( nNewDelimPos + 1 );
430 OUString aOldSuffix;
431 if (nOldDelimPos > -1)
432 aOldSuffix = m_sName.copy( nOldDelimPos + 1 );
434 sal_Int32 nNewNumeric = aNewSuffix.toInt32();
435 sal_Int32 nOldNumeric = aOldSuffix.toInt32();
437 OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName );
438 OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName );
440 if ( m_sName == rName ||
441 ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) )
442 return;
443 OUString sNewGroup(rName);
444 if (sNewGroup.indexOf(GLOS_DELIM)<0)
446 sNewGroup += OUStringChar(GLOS_DELIM) + "0";
449 //the name must be saved, the group may be invalidated while in RenameGroupDoc()
450 SwGlossaries* pTempGlossaries = m_pGlossaries;
452 OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) );
453 if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) )
454 throw uno::RuntimeException();
455 m_sName = rName;
456 m_sGroupName = sNewGroup;
457 m_pGlossaries = pTempGlossaries;
460 sal_Int32 SwXAutoTextGroup::getCount()
462 SolarMutexGuard aGuard;
463 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
464 if (!pGlosGroup || pGlosGroup->GetError())
465 throw uno::RuntimeException();
466 return static_cast<sal_Int32>(pGlosGroup->GetCount());
469 uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex)
471 SolarMutexGuard aGuard;
472 if (!m_pGlossaries)
473 throw uno::RuntimeException();
474 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName));
475 if (!pGlosGroup || pGlosGroup->GetError())
476 throw uno::RuntimeException();
477 const sal_uInt16 nCount = pGlosGroup->GetCount();
478 if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount)
479 throw lang::IndexOutOfBoundsException();
480 return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex)));
483 uno::Type SwXAutoTextGroup::getElementType()
485 return cppu::UnoType<text::XAutoTextEntry>::get();
489 sal_Bool SwXAutoTextGroup::hasElements()
491 SolarMutexGuard aGuard;
492 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
493 if (!pGlosGroup || pGlosGroup->GetError())
494 throw uno::RuntimeException();
495 return pGlosGroup->GetCount() > 0;
499 uno::Any SwXAutoTextGroup::getByName(const OUString& _rName)
501 SolarMutexGuard aGuard;
502 uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName );
503 OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" );
504 // we told it to create the object, so why didn't it?
505 return css::uno::Any( xEntry );
508 uno::Sequence< OUString > SwXAutoTextGroup::getElementNames()
510 SolarMutexGuard aGuard;
511 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
512 if (!pGlosGroup || pGlosGroup->GetError())
513 throw uno::RuntimeException();
515 const sal_uInt16 nCount = pGlosGroup->GetCount();
516 uno::Sequence< OUString > aEntryNames(nCount);
517 OUString *pArr = aEntryNames.getArray();
519 for ( sal_uInt16 i = 0; i < nCount; i++ )
520 pArr[i] = pGlosGroup->GetShortName(i);
521 return aEntryNames;
524 sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName)
526 SolarMutexGuard aGuard;
527 bool bRet = false;
528 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
529 if (!pGlosGroup || pGlosGroup->GetError())
530 throw uno::RuntimeException();
532 const sal_uInt16 nCount = pGlosGroup->GetCount();
533 for( sal_uInt16 i = 0; i < nCount; ++i )
535 OUString sCompare(pGlosGroup->GetShortName(i));
536 if(sCompare.equalsIgnoreAsciiCase(rName))
538 bRet = true;
539 break;
542 return bRet;
545 uno::Reference< beans::XPropertySetInfo > SwXAutoTextGroup::getPropertySetInfo()
547 static uno::Reference< beans::XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
548 return xRet;
551 void SwXAutoTextGroup::setPropertyValue(
552 const OUString& rPropertyName, const uno::Any& aValue)
554 SolarMutexGuard aGuard;
555 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
557 if(!pEntry)
558 throw beans::UnknownPropertyException(rPropertyName);
560 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
561 if(!pGlosGroup || pGlosGroup->GetError())
562 throw uno::RuntimeException();
563 switch(pEntry->nWID)
565 case WID_GROUP_TITLE:
567 OUString sNewTitle;
568 aValue >>= sNewTitle;
569 if(sNewTitle.isEmpty())
570 throw lang::IllegalArgumentException();
571 bool bChanged = sNewTitle != pGlosGroup->GetName();
572 pGlosGroup->SetName(sNewTitle);
573 if(bChanged && HasGlossaryList())
574 GetGlossaryList()->ClearGroups();
576 break;
580 uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName)
582 SolarMutexGuard aGuard;
583 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
585 if(!pEntry)
586 throw beans::UnknownPropertyException(rPropertyName);
587 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
588 if(!pGlosGroup || pGlosGroup->GetError())
589 throw uno::RuntimeException();
591 uno::Any aAny;
592 switch(pEntry->nWID)
594 case WID_GROUP_PATH:
595 aAny <<= pGlosGroup->GetFileName();
596 break;
597 case WID_GROUP_TITLE:
598 aAny <<= pGlosGroup->GetName();
599 break;
601 return aAny;
604 void SwXAutoTextGroup::addPropertyChangeListener(
605 const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
609 void SwXAutoTextGroup::removePropertyChangeListener(
610 const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
614 void SwXAutoTextGroup::addVetoableChangeListener(
615 const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
619 void SwXAutoTextGroup::removeVetoableChangeListener(
620 const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
624 void SwXAutoTextGroup::Invalidate()
626 m_pGlossaries = nullptr;
627 m_sName.clear();
628 m_sGroupName.clear();
631 OUString SwXAutoTextGroup::getImplementationName()
633 return "SwXAutoTextGroup";
636 sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
638 return cppu::supportsService(this, rServiceName);
641 uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
643 uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextGroup" };
644 return aRet;
647 SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName,
648 OUString aEntryName) :
649 m_pGlossaries(pGlss),
650 m_sGroupName(std::move(aGroupName)),
651 m_sEntryName(std::move(aEntryName))
655 SwXAutoTextEntry::~SwXAutoTextEntry()
657 SolarMutexGuard aGuard;
659 // ensure that any pending modifications are written
660 implFlushDocument( true );
663 void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc )
665 if ( !m_xDocSh.is() )
666 return;
668 if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () )
669 m_xDocSh->Save();
671 if ( _bCloseDoc )
673 // stop listening at the document
674 EndListening( *m_xDocSh );
676 m_xDocSh->DoClose();
677 m_xDocSh.clear();
681 void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
683 if ( &_rBC != m_xDocSh.get() )
684 return;
686 // it's our document
687 if (const SfxEventHint* pEventHint = dynamic_cast<const SfxEventHint*>(&_rHint))
689 if (SfxEventHintId::PrepareCloseDoc == pEventHint->GetEventId())
691 implFlushDocument();
692 mxBodyText.clear();
693 EndListening( *m_xDocSh );
694 m_xDocSh.clear();
697 else
699 if ( SfxHintId::Deinitializing == _rHint.GetId() )
701 // our document is dying (possibly because we're shutting down, and the document was notified
702 // earlier than we are?)
703 // stop listening at the docu
704 EndListening( *m_xDocSh );
705 // and release our reference
706 m_xDocSh.clear();
711 void SwXAutoTextEntry::GetBodyText ()
713 SolarMutexGuard aGuard;
715 m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false );
716 OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" );
718 // start listening at the document
719 StartListening( *m_xDocSh );
721 mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() );
724 void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&)
726 SolarMutexGuard g;
727 implFlushDocument(true);
730 uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursor()
732 SolarMutexGuard aGuard;
733 EnsureBodyText();
734 return mxBodyText->createTextCursor();
737 uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursorByRange(
738 const uno::Reference< text::XTextRange > & aTextPosition)
740 SolarMutexGuard aGuard;
741 EnsureBodyText();
742 return mxBodyText->createTextCursorByRange ( aTextPosition );
745 void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb)
747 SolarMutexGuard aGuard;
748 EnsureBodyText();
749 mxBodyText->insertString ( xRange, aString, bAbsorb );
752 void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange,
753 sal_Int16 nControlCharacter, sal_Bool bAbsorb)
755 SolarMutexGuard aGuard;
756 EnsureBodyText();
757 mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb );
760 void SwXAutoTextEntry::insertTextContent(
761 const uno::Reference< text::XTextRange > & xRange,
762 const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb)
764 SolarMutexGuard aGuard;
765 EnsureBodyText();
766 mxBodyText->insertTextContent ( xRange, xContent, bAbsorb );
769 void SwXAutoTextEntry::removeTextContent(
770 const uno::Reference< text::XTextContent > & xContent)
772 SolarMutexGuard aGuard;
773 EnsureBodyText();
774 mxBodyText->removeTextContent ( xContent );
777 uno::Reference< text::XText > SwXAutoTextEntry::getText()
779 SolarMutexGuard aGuard;
780 uno::Reference< text::XText > xRet = static_cast<text::XText*>(this);
781 return xRet;
784 uno::Reference< text::XTextRange > SwXAutoTextEntry::getStart()
786 SolarMutexGuard aGuard;
787 EnsureBodyText();
788 return mxBodyText->getStart();
791 uno::Reference< text::XTextRange > SwXAutoTextEntry::getEnd()
793 SolarMutexGuard aGuard;
794 EnsureBodyText();
795 return mxBodyText->getEnd();
798 OUString SwXAutoTextEntry::getString()
800 SolarMutexGuard aGuard;
801 EnsureBodyText();
802 return mxBodyText->getString();
805 void SwXAutoTextEntry::setString(const OUString& aString)
807 SolarMutexGuard aGuard;
808 EnsureBodyText();
809 mxBodyText->setString( aString );
812 void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange)
814 SolarMutexGuard aGuard;
816 // ensure that any pending modifications are written
817 // reason is that we're holding the _copy_ of the auto text, while the real auto text
818 // is stored somewhere. And below, we're not working with our copy, but only tell the target
819 // TextRange to work with the stored version.
820 // #96380# - 2003-03-03 - fs@openoffice.org
821 implFlushDocument();
822 // TODO: think about if we should pass "true" here
823 // The difference would be that when the next modification is made to this instance here, then
824 // we would be forced to open the document again, instead of working on our current copy.
825 // This means that we would reflect any changes which were done to the AutoText by foreign instances
826 // in the meantime
828 // The reference to xKeepAlive is needed during the whole call, likely because it could be a
829 // different object, not xTextRange itself, and the reference guards it from preliminary death
830 auto xKeepAlive( xTextRange );
831 SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
832 OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
833 SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get());
835 SwDoc* pDoc = nullptr;
836 if (pRange)
837 pDoc = &pRange->GetDoc();
838 else if ( pCursor )
839 pDoc = pCursor->GetDoc();
840 else if ( pText && pText->GetDoc() )
842 xKeepAlive = pText->getStart();
843 pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get());
844 if (pCursor)
845 pDoc = pText->GetDoc();
848 if(!pDoc)
849 throw uno::RuntimeException();
851 SwPaM InsertPaM(pDoc->GetNodes());
852 if (pRange)
854 if (!pRange->GetPositions(InsertPaM))
856 throw uno::RuntimeException();
859 else
861 InsertPaM = *pCursor->GetPaM();
864 std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName));
865 const bool bResult = pBlock && !pBlock->GetError()
866 && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM);
868 if(!bResult)
869 throw uno::RuntimeException();
872 OUString SwXAutoTextEntry::getImplementationName()
874 return "SwXAutoTextEntry";
877 sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
879 return cppu::supportsService(this, rServiceName);
882 uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
884 uno::Sequence<OUString> aRet { "com.sun.star.text.AutoTextEntry" };
885 return aRet;
888 uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents()
890 return new SwAutoTextEventDescriptor( *this );
893 const struct SvEventDescription aAutotextEvents[] =
895 { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" },
896 { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" },
897 { SvMacroItemId::NONE, nullptr }
900 SwAutoTextEventDescriptor::SwAutoTextEventDescriptor(
901 SwXAutoTextEntry& rAutoText ) :
902 SvBaseEventDescriptor(aAutotextEvents),
903 m_rAutoTextEntry(rAutoText)
907 SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor()
911 OUString SwAutoTextEventDescriptor::getImplementationName()
913 return "SwAutoTextEventDescriptor";
916 void SwAutoTextEventDescriptor::replaceByName(
917 const SvMacroItemId nEvent,
918 const SvxMacro& rMacro)
920 OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(),
921 "Strangely enough, the AutoText vanished!" );
922 OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
923 (nEvent == SvMacroItemId::SwStartInsGlossary) ,
924 "Unknown event ID" );
926 SwGlossaries *const pGlossaries =
927 const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
928 std::unique_ptr<SwTextBlocks> pBlocks(
929 pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
930 OSL_ENSURE( pBlocks,
931 "can't get autotext group; SwAutoTextEntry has illegal name?");
933 if( !pBlocks || pBlocks->GetError())
934 return;
936 sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
937 if( nIndex != USHRT_MAX )
939 SvxMacroTableDtor aMacroTable;
940 if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
942 aMacroTable.Insert( nEvent, rMacro );
943 pBlocks->SetMacroTable( nIndex, aMacroTable );
946 // else: ignore
949 void SwAutoTextEventDescriptor::getByName(
950 SvxMacro& rMacro,
951 const SvMacroItemId nEvent )
953 OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" );
954 OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
955 (nEvent == SvMacroItemId::SwStartInsGlossary) ,
956 "Unknown event ID" );
958 SwGlossaries *const pGlossaries =
959 const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
960 std::unique_ptr<SwTextBlocks> pBlocks(
961 pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
962 OSL_ENSURE( pBlocks,
963 "can't get autotext group; SwAutoTextEntry has illegal name?");
965 // return empty macro, unless macro is found
966 OUString sEmptyStr;
967 SvxMacro aEmptyMacro(sEmptyStr, sEmptyStr);
968 rMacro = aEmptyMacro;
970 if ( !pBlocks || pBlocks->GetError())
971 return;
973 sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
974 if( nIndex != USHRT_MAX )
976 SvxMacroTableDtor aMacroTable;
977 if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
979 SvxMacro *pMacro = aMacroTable.Get( nEvent );
980 if( pMacro )
981 rMacro = *pMacro;
986 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
987 SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*,
988 css::uno::Sequence<css::uno::Any> const &)
990 //the module may not be loaded
991 SolarMutexGuard aGuard;
992 SwGlobals::ensure();
993 return cppu::acquire(new SwXAutoTextContainer());
996 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */