docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / uibase / uno / unoatxt.cxx
blobc0e02e17f77e0c2212e44e6a13e4b417257fca54
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 throw lang::IllegalArgumentException(u"group name must not be empty"_ustr, nullptr, 0);
153 for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++)
155 sal_Unicode cChar = aGroupName[nPos];
156 if (rtl::isAsciiAlphanumeric(cChar) ||
157 (cChar == '_') ||
158 (cChar == 0x20) ||
159 (cChar == GLOS_DELIM) )
161 continue;
163 throw lang::IllegalArgumentException(u"group name must contain a-z, A-z, '_', ' ' only"_ustr, nullptr, 0);
165 OUString sGroup(aGroupName);
166 if (sGroup.indexOf(GLOS_DELIM)<0)
168 sGroup += OUStringChar(GLOS_DELIM) + "0";
170 m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM));
172 uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup );
173 OSL_ENSURE( xGroup.is(), "SwXAutoTextContainer::insertNewByName: no UNO object created? How this?" );
174 // We just inserted the group into the glossaries, so why doesn't it exist?
176 return xGroup;
179 void SwXAutoTextContainer::removeByName(const OUString& aGroupName)
181 SolarMutexGuard aGuard;
182 // At first find the name with path extension
183 OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName );
184 if(sGroupName.isEmpty())
185 throw container::NoSuchElementException();
186 m_pGlossaries->DelGroupDoc(sGroupName);
189 OUString SwXAutoTextContainer::getImplementationName()
191 return u"SwXAutoTextContainer"_ustr;
194 sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
196 return cppu::supportsService(this, rServiceName);
199 uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
201 return { u"com.sun.star.text.AutoTextContainer"_ustr };
204 SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName,
205 SwGlossaries* pGlos) :
206 m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)),
207 m_pGlossaries(pGlos),
208 m_sName(rName),
209 m_sGroupName(rName)
211 OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ),
212 "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" );
215 SwXAutoTextGroup::~SwXAutoTextGroup()
219 uno::Sequence< OUString > SwXAutoTextGroup::getTitles()
221 SolarMutexGuard aGuard;
222 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
223 if (!pGlosGroup || pGlosGroup->GetError())
224 throw uno::RuntimeException();
225 const sal_uInt16 nCount = pGlosGroup->GetCount();
227 uno::Sequence< OUString > aEntryTitles(nCount);
228 OUString *pArr = aEntryTitles.getArray();
230 for ( sal_uInt16 i = 0; i < nCount; i++ )
231 pArr[i] = pGlosGroup->GetLongName(i);
232 return aEntryTitles;
235 void SwXAutoTextGroup::renameByName(const OUString& aElementName,
236 const OUString& aNewElementName, const OUString& aNewElementTitle)
238 SolarMutexGuard aGuard;
239 // throw exception only if the programmatic name is to be changed into an existing name
240 if(aNewElementName != aElementName && hasByName(aNewElementName))
241 throw container::ElementExistException();
242 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
243 if(!pGlosGroup || pGlosGroup->GetError())
244 throw uno::RuntimeException();
246 const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName);
247 if(USHRT_MAX == nIdx)
248 throw lang::IllegalArgumentException();
249 const OUString& aNewShort(aNewElementName);
250 const OUString& aNewName(aNewElementTitle);
251 sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort );
252 sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName );
254 if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx)
255 && (nOldIdx == USHRT_MAX || nOldIdx == nIdx))
257 pGlosGroup->Rename( nIdx, &aNewShort, &aNewName );
258 if(pGlosGroup->GetError() != ERRCODE_NONE)
259 throw io::IOException();
264 static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange)
266 SwNodes& rNds = rInsDoc.GetNodes();
268 SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
269 SwContentNode * pNd = aIdx.GetNode().GetContentNode();
270 SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0);
272 bool bRet = false;
273 rInsDoc.getIDocumentFieldsAccess().LockExpFields();
275 SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc());
276 SwPaM aPam(pDoc->GetNodes());
277 SwPaM * pPam(nullptr);
278 if(pxCursor)
280 pPam = pxCursor->GetPaM();
282 else
284 if (pxRange->GetPositions(aPam))
286 pPam = & aPam;
289 if (!pPam) { return false; }
290 bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly)
291 || bRet;
294 rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
295 if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
296 rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
298 return bRet;
301 uno::Reference< text::XAutoTextEntry > SwXAutoTextGroup::insertNewByName(const OUString& aName,
302 const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange)
304 SolarMutexGuard aGuard;
305 if(hasByName(aName))
306 throw container::ElementExistException();
307 if(!xTextRange.is())
308 throw uno::RuntimeException();
310 std::unique_ptr<SwTextBlocks> pGlosGroup;
311 if (m_pGlossaries)
312 pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName);
313 const OUString& sShortName(aName);
314 const OUString& sLongName(aTitle);
315 if (pGlosGroup && !pGlosGroup->GetError())
317 SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
318 OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
320 OUString sOnlyText;
321 OUString* pOnlyText = nullptr;
322 bool bNoAttr = !pxCursor && !pxRange;
323 if(bNoAttr)
325 sOnlyText = xTextRange->getString();
326 pOnlyText = &sOnlyText;
329 const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
331 SwDoc* pGDoc = pGlosGroup->GetDoc();
333 // Until there is an option for that, delete base util::URL
334 if(rCfg.IsSaveRelFile())
336 INetURLObject aTemp(pGlosGroup->GetFileName());
337 pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE));
339 else
340 pGlosGroup->SetBaseURL( OUString() );
342 sal_uInt16 nRet = USHRT_MAX;
343 if( pOnlyText )
344 nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText );
345 else
347 pGlosGroup->ClearDoc();
348 if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) )
350 pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
351 lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange);
352 pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE);
353 nRet = pGlosGroup->PutDoc();
357 if (nRet == USHRT_MAX)
359 throw uno::RuntimeException();
362 pGlosGroup.reset();
364 uno::Reference< text::XAutoTextEntry > xEntry;
368 xEntry = m_pGlossaries ?
369 m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) :
370 uno::Reference< text::XAutoTextEntry >();
371 OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::insertNewByName: no UNO object created? How this?" );
372 // we just inserted the entry into the group, so why doesn't it exist?
374 catch (const container::ElementExistException&)
376 throw;
378 catch (const uno::RuntimeException&)
380 throw;
382 catch (const uno::Exception&)
384 css::uno::Any anyEx = cppu::getCaughtException();
385 throw css::lang::WrappedTargetRuntimeException(
386 u"Error Getting AutoText!"_ustr,
387 getXWeak(),
388 anyEx );
391 return xEntry;
394 void SwXAutoTextGroup::removeByName(const OUString& aEntryName)
396 SolarMutexGuard aGuard;
397 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
398 if(!pGlosGroup || pGlosGroup->GetError())
399 throw container::NoSuchElementException();
401 sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName);
402 if ( nIdx == USHRT_MAX )
403 throw container::NoSuchElementException();
405 pGlosGroup->Delete(nIdx);
408 OUString SwXAutoTextGroup::getName()
410 SolarMutexGuard aGuard;
411 return m_sName;
414 void SwXAutoTextGroup::setName(const OUString& rName)
416 SolarMutexGuard aGuard;
417 if( !m_pGlossaries )
418 throw uno::RuntimeException();
420 sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM );
421 sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM );
423 OUString aNewSuffix;
424 if (nNewDelimPos > -1)
425 aNewSuffix = rName.copy( nNewDelimPos + 1 );
426 OUString aOldSuffix;
427 if (nOldDelimPos > -1)
428 aOldSuffix = m_sName.copy( nOldDelimPos + 1 );
430 sal_Int32 nNewNumeric = aNewSuffix.toInt32();
431 sal_Int32 nOldNumeric = aOldSuffix.toInt32();
433 OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName );
434 OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName );
436 if ( m_sName == rName ||
437 ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) )
438 return;
439 OUString sNewGroup(rName);
440 if (sNewGroup.indexOf(GLOS_DELIM)<0)
442 sNewGroup += OUStringChar(GLOS_DELIM) + "0";
445 //the name must be saved, the group may be invalidated while in RenameGroupDoc()
446 SwGlossaries* pTempGlossaries = m_pGlossaries;
448 OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) );
449 if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) )
450 throw uno::RuntimeException();
451 m_sName = rName;
452 m_sGroupName = sNewGroup;
453 m_pGlossaries = pTempGlossaries;
456 sal_Int32 SwXAutoTextGroup::getCount()
458 SolarMutexGuard aGuard;
459 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
460 if (!pGlosGroup || pGlosGroup->GetError())
461 throw uno::RuntimeException();
462 return static_cast<sal_Int32>(pGlosGroup->GetCount());
465 uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex)
467 SolarMutexGuard aGuard;
468 if (!m_pGlossaries)
469 throw uno::RuntimeException();
470 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName));
471 if (!pGlosGroup || pGlosGroup->GetError())
472 throw uno::RuntimeException();
473 const sal_uInt16 nCount = pGlosGroup->GetCount();
474 if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount)
475 throw lang::IndexOutOfBoundsException();
476 return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex)));
479 uno::Type SwXAutoTextGroup::getElementType()
481 return cppu::UnoType<text::XAutoTextEntry>::get();
485 sal_Bool SwXAutoTextGroup::hasElements()
487 SolarMutexGuard aGuard;
488 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
489 if (!pGlosGroup || pGlosGroup->GetError())
490 throw uno::RuntimeException();
491 return pGlosGroup->GetCount() > 0;
495 uno::Any SwXAutoTextGroup::getByName(const OUString& _rName)
497 SolarMutexGuard aGuard;
498 uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName );
499 OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" );
500 // we told it to create the object, so why didn't it?
501 return css::uno::Any( xEntry );
504 uno::Sequence< OUString > SwXAutoTextGroup::getElementNames()
506 SolarMutexGuard aGuard;
507 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
508 if (!pGlosGroup || pGlosGroup->GetError())
509 throw uno::RuntimeException();
511 const sal_uInt16 nCount = pGlosGroup->GetCount();
512 uno::Sequence< OUString > aEntryNames(nCount);
513 OUString *pArr = aEntryNames.getArray();
515 for ( sal_uInt16 i = 0; i < nCount; i++ )
516 pArr[i] = pGlosGroup->GetShortName(i);
517 return aEntryNames;
520 sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName)
522 SolarMutexGuard aGuard;
523 bool bRet = false;
524 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
525 if (!pGlosGroup || pGlosGroup->GetError())
526 throw uno::RuntimeException();
528 const sal_uInt16 nCount = pGlosGroup->GetCount();
529 for( sal_uInt16 i = 0; i < nCount; ++i )
531 OUString sCompare(pGlosGroup->GetShortName(i));
532 if(sCompare.equalsIgnoreAsciiCase(rName))
534 bRet = true;
535 break;
538 return bRet;
541 uno::Reference< beans::XPropertySetInfo > SwXAutoTextGroup::getPropertySetInfo()
543 static uno::Reference< beans::XPropertySetInfo > xRet = m_pPropSet->getPropertySetInfo();
544 return xRet;
547 void SwXAutoTextGroup::setPropertyValue(
548 const OUString& rPropertyName, const uno::Any& aValue)
550 SolarMutexGuard aGuard;
551 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
553 if(!pEntry)
554 throw beans::UnknownPropertyException(rPropertyName);
556 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
557 if(!pGlosGroup || pGlosGroup->GetError())
558 throw uno::RuntimeException();
559 switch(pEntry->nWID)
561 case WID_GROUP_TITLE:
563 OUString sNewTitle;
564 aValue >>= sNewTitle;
565 if(sNewTitle.isEmpty())
566 throw lang::IllegalArgumentException();
567 bool bChanged = sNewTitle != pGlosGroup->GetName();
568 pGlosGroup->SetName(sNewTitle);
569 if(bChanged && HasGlossaryList())
570 GetGlossaryList()->ClearGroups();
572 break;
576 uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName)
578 SolarMutexGuard aGuard;
579 const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
581 if(!pEntry)
582 throw beans::UnknownPropertyException(rPropertyName);
583 std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
584 if(!pGlosGroup || pGlosGroup->GetError())
585 throw uno::RuntimeException();
587 uno::Any aAny;
588 switch(pEntry->nWID)
590 case WID_GROUP_PATH:
591 aAny <<= pGlosGroup->GetFileName();
592 break;
593 case WID_GROUP_TITLE:
594 aAny <<= pGlosGroup->GetName();
595 break;
597 return aAny;
600 void SwXAutoTextGroup::addPropertyChangeListener(
601 const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
605 void SwXAutoTextGroup::removePropertyChangeListener(
606 const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
610 void SwXAutoTextGroup::addVetoableChangeListener(
611 const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
615 void SwXAutoTextGroup::removeVetoableChangeListener(
616 const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
620 void SwXAutoTextGroup::Invalidate()
622 m_pGlossaries = nullptr;
623 m_sName.clear();
624 m_sGroupName.clear();
627 OUString SwXAutoTextGroup::getImplementationName()
629 return u"SwXAutoTextGroup"_ustr;
632 sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
634 return cppu::supportsService(this, rServiceName);
637 uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
639 uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextGroup"_ustr };
640 return aRet;
643 SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName,
644 OUString aEntryName) :
645 m_pGlossaries(pGlss),
646 m_sGroupName(std::move(aGroupName)),
647 m_sEntryName(std::move(aEntryName))
651 SwXAutoTextEntry::~SwXAutoTextEntry()
653 SolarMutexGuard aGuard;
655 // ensure that any pending modifications are written
656 implFlushDocument( true );
659 void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc )
661 if ( !m_xDocSh.is() )
662 return;
664 if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () )
665 m_xDocSh->Save();
667 if ( _bCloseDoc )
669 // stop listening at the document
670 EndListening( *m_xDocSh );
672 m_xDocSh->DoClose();
673 m_xDocSh.clear();
677 void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
679 if ( &_rBC != m_xDocSh.get() )
680 return;
682 // it's our document
683 if (_rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
685 const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(_rHint);
686 if (SfxEventHintId::PrepareCloseDoc == rEventHint.GetEventId())
688 implFlushDocument();
689 mxBodyText.clear();
690 EndListening( *m_xDocSh );
691 m_xDocSh.clear();
694 else
696 if ( SfxHintId::Deinitializing == _rHint.GetId() )
698 // our document is dying (possibly because we're shutting down, and the document was notified
699 // earlier than we are?)
700 // stop listening at the docu
701 EndListening( *m_xDocSh );
702 // and release our reference
703 m_xDocSh.clear();
708 void SwXAutoTextEntry::GetBodyText ()
710 SolarMutexGuard aGuard;
712 m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false );
713 OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" );
715 // start listening at the document
716 StartListening( *m_xDocSh );
718 mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() );
721 void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&)
723 SolarMutexGuard g;
724 implFlushDocument(true);
727 uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursor()
729 SolarMutexGuard aGuard;
730 EnsureBodyText();
731 return mxBodyText->createTextCursor();
734 uno::Reference< text::XTextCursor > SwXAutoTextEntry::createTextCursorByRange(
735 const uno::Reference< text::XTextRange > & aTextPosition)
737 SolarMutexGuard aGuard;
738 EnsureBodyText();
739 return mxBodyText->createTextCursorByRange ( aTextPosition );
742 void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb)
744 SolarMutexGuard aGuard;
745 EnsureBodyText();
746 mxBodyText->insertString ( xRange, aString, bAbsorb );
749 void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange,
750 sal_Int16 nControlCharacter, sal_Bool bAbsorb)
752 SolarMutexGuard aGuard;
753 EnsureBodyText();
754 mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb );
757 void SwXAutoTextEntry::insertTextContent(
758 const uno::Reference< text::XTextRange > & xRange,
759 const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb)
761 SolarMutexGuard aGuard;
762 EnsureBodyText();
763 mxBodyText->insertTextContent ( xRange, xContent, bAbsorb );
766 void SwXAutoTextEntry::removeTextContent(
767 const uno::Reference< text::XTextContent > & xContent)
769 SolarMutexGuard aGuard;
770 EnsureBodyText();
771 mxBodyText->removeTextContent ( xContent );
774 uno::Reference< text::XText > SwXAutoTextEntry::getText()
776 SolarMutexGuard aGuard;
777 uno::Reference< text::XText > xRet = static_cast<text::XText*>(this);
778 return xRet;
781 uno::Reference< text::XTextRange > SwXAutoTextEntry::getStart()
783 SolarMutexGuard aGuard;
784 EnsureBodyText();
785 return mxBodyText->getStart();
788 uno::Reference< text::XTextRange > SwXAutoTextEntry::getEnd()
790 SolarMutexGuard aGuard;
791 EnsureBodyText();
792 return mxBodyText->getEnd();
795 OUString SwXAutoTextEntry::getString()
797 SolarMutexGuard aGuard;
798 EnsureBodyText();
799 return mxBodyText->getString();
802 void SwXAutoTextEntry::setString(const OUString& aString)
804 SolarMutexGuard aGuard;
805 EnsureBodyText();
806 mxBodyText->setString( aString );
809 void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange)
811 SolarMutexGuard aGuard;
813 // ensure that any pending modifications are written
814 // reason is that we're holding the _copy_ of the auto text, while the real auto text
815 // is stored somewhere. And below, we're not working with our copy, but only tell the target
816 // TextRange to work with the stored version.
817 // #96380# - 2003-03-03 - fs@openoffice.org
818 implFlushDocument();
819 // TODO: think about if we should pass "true" here
820 // The difference would be that when the next modification is made to this instance here, then
821 // we would be forced to open the document again, instead of working on our current copy.
822 // This means that we would reflect any changes which were done to the AutoText by foreign instances
823 // in the meantime
825 // The reference to xKeepAlive is needed during the whole call, likely because it could be a
826 // different object, not xTextRange itself, and the reference guards it from preliminary death
827 auto xKeepAlive( xTextRange );
828 SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
829 OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
830 SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get());
832 SwDoc* pDoc = nullptr;
833 if (pRange)
834 pDoc = &pRange->GetDoc();
835 else if ( pCursor )
836 pDoc = pCursor->GetDoc();
837 else if ( pText && pText->GetDoc() )
839 xKeepAlive = pText->getStart();
840 pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get());
841 if (pCursor)
842 pDoc = pText->GetDoc();
845 if(!pDoc)
846 throw uno::RuntimeException();
848 SwPaM InsertPaM(pDoc->GetNodes());
849 if (pRange)
851 if (!pRange->GetPositions(InsertPaM))
853 throw uno::RuntimeException();
856 else
858 InsertPaM = *pCursor->GetPaM();
861 std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName));
862 const bool bResult = pBlock && !pBlock->GetError()
863 && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM);
865 if(!bResult)
866 throw uno::RuntimeException();
869 OUString SwXAutoTextEntry::getImplementationName()
871 return u"SwXAutoTextEntry"_ustr;
874 sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
876 return cppu::supportsService(this, rServiceName);
879 uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
881 uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextEntry"_ustr };
882 return aRet;
885 uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents()
887 return new SwAutoTextEventDescriptor( *this );
890 const struct SvEventDescription aAutotextEvents[] =
892 { SvMacroItemId::SwStartInsGlossary, "OnInsertStart" },
893 { SvMacroItemId::SwEndInsGlossary, "OnInsertDone" },
894 { SvMacroItemId::NONE, nullptr }
897 SwAutoTextEventDescriptor::SwAutoTextEventDescriptor(
898 SwXAutoTextEntry& rAutoText ) :
899 SvBaseEventDescriptor(aAutotextEvents),
900 m_rAutoTextEntry(rAutoText)
904 SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor()
908 OUString SwAutoTextEventDescriptor::getImplementationName()
910 return u"SwAutoTextEventDescriptor"_ustr;
913 void SwAutoTextEventDescriptor::replaceByName(
914 const SvMacroItemId nEvent,
915 const SvxMacro& rMacro)
917 OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(),
918 "Strangely enough, the AutoText vanished!" );
919 OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
920 (nEvent == SvMacroItemId::SwStartInsGlossary) ,
921 "Unknown event ID" );
923 SwGlossaries *const pGlossaries =
924 const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
925 std::unique_ptr<SwTextBlocks> pBlocks(
926 pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
927 OSL_ENSURE( pBlocks,
928 "can't get autotext group; SwAutoTextEntry has illegal name?");
930 if( !pBlocks || pBlocks->GetError())
931 return;
933 sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
934 if( nIndex != USHRT_MAX )
936 SvxMacroTableDtor aMacroTable;
937 if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
939 aMacroTable.Insert( nEvent, rMacro );
940 pBlocks->SetMacroTable( nIndex, aMacroTable );
943 // else: ignore
946 void SwAutoTextEventDescriptor::getByName(
947 SvxMacro& rMacro,
948 const SvMacroItemId nEvent )
950 OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" );
951 OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
952 (nEvent == SvMacroItemId::SwStartInsGlossary) ,
953 "Unknown event ID" );
955 SwGlossaries *const pGlossaries =
956 const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
957 std::unique_ptr<SwTextBlocks> pBlocks(
958 pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
959 OSL_ENSURE( pBlocks,
960 "can't get autotext group; SwAutoTextEntry has illegal name?");
962 // return empty macro, unless macro is found
963 OUString sEmptyStr;
964 rMacro = SvxMacro(sEmptyStr, sEmptyStr);
966 if ( !pBlocks || pBlocks->GetError())
967 return;
969 sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
970 if( nIndex != USHRT_MAX )
972 SvxMacroTableDtor aMacroTable;
973 if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
975 SvxMacro *pMacro = aMacroTable.Get( nEvent );
976 if( pMacro )
977 rMacro = *pMacro;
982 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
983 SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*,
984 css::uno::Sequence<css::uno::Any> const &)
986 //the module may not be loaded
987 SolarMutexGuard aGuard;
988 SwGlobals::ensure();
989 return cppu::acquire(new SwXAutoTextContainer());
992 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */