Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/sw/source/uibase/uno/unoatxt.cxx
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
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/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
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 .
18
 */
19
20
#include <sal/config.h>
21
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>
56
57
#include <memory>
58
59
using namespace ::com::sun::star;
60
61
SwXAutoTextContainer::SwXAutoTextContainer()
62
0
{
63
0
    m_pGlossaries = ::GetGlossaries();
64
65
0
}
66
67
SwXAutoTextContainer::~SwXAutoTextContainer()
68
0
{
69
70
0
}
71
72
sal_Int32 SwXAutoTextContainer::getCount()
73
0
{
74
0
    OSL_ENSURE(m_pGlossaries->GetGroupCnt() < o3tl::make_unsigned(SAL_MAX_INT32),
75
0
               "SwXAutoTextContainer::getCount: too many items");
76
0
    return static_cast<sal_Int32>(m_pGlossaries->GetGroupCnt());
77
0
}
78
79
uno::Any SwXAutoTextContainer::getByIndex(sal_Int32 nIndex)
80
0
{
81
0
    SolarMutexGuard aGuard;
82
0
    const size_t nCount = m_pGlossaries->GetGroupCnt();
83
0
    if ( nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount )
84
0
        throw lang::IndexOutOfBoundsException();
85
0
    return getByName(m_pGlossaries->GetGroupName( static_cast<size_t>(nIndex) ));
86
0
}
87
88
uno::Type SwXAutoTextContainer::getElementType()
89
0
{
90
0
    return cppu::UnoType<text::XAutoTextGroup>::get();
91
92
0
}
93
94
sal_Bool SwXAutoTextContainer::hasElements()
95
0
{
96
    // At least standard should always exists!
97
0
    return true;
98
0
}
99
100
uno::Any SwXAutoTextContainer::getByName(const OUString& GroupName)
101
0
{
102
0
    SolarMutexGuard aGuard;
103
104
0
    uno::Reference< text::XAutoTextGroup > xGroup;
105
0
    if ( m_pGlossaries && hasByName( GroupName ) )    // group name already known?
106
        // true = create group if not already available
107
0
        xGroup = m_pGlossaries->GetAutoTextGroup( GroupName );
108
109
0
    if ( !xGroup.is() )
110
0
        throw container::NoSuchElementException();
111
112
0
    return css::uno::Any( xGroup );
113
0
}
114
115
uno::Sequence< OUString > SwXAutoTextContainer::getElementNames()
116
0
{
117
0
    SolarMutexGuard aGuard;
118
0
    const size_t nCount = m_pGlossaries->GetGroupCnt();
119
0
    OSL_ENSURE(nCount < o3tl::make_unsigned(SAL_MAX_INT32),
120
0
               "SwXAutoTextContainer::getElementNames: too many groups");
121
122
0
    uno::Sequence< OUString > aGroupNames(static_cast<sal_Int32>(nCount));
123
0
    OUString *pArr = aGroupNames.getArray();
124
125
0
    for ( size_t i = 0; i < nCount; ++i )
126
0
    {
127
        // The names will be passed without a path extension.
128
0
        pArr[i] = m_pGlossaries->GetGroupName(i).getToken(0, GLOS_DELIM);
129
0
    }
130
0
    return aGroupNames;
131
0
}
132
// Finds group names with or without path index.
133
sal_Bool SwXAutoTextContainer::hasByName(const OUString& Name)
134
0
{
135
0
    SolarMutexGuard aGuard;
136
0
    OUString sGroupName( m_pGlossaries->GetCompleteGroupName( Name ) );
137
0
    if(!sGroupName.isEmpty())
138
0
        return true;
139
0
    return false;
140
0
}
141
142
uno::Reference< text::XAutoTextGroup >  SwXAutoTextContainer::insertNewByName(
143
    const OUString& aGroupName)
144
0
{
145
0
    SolarMutexGuard aGuard;
146
0
    if(hasByName(aGroupName))
147
0
        throw container::ElementExistException();
148
    //check for non-ASCII characters
149
0
    if(aGroupName.isEmpty())
150
0
    {
151
0
        throw lang::IllegalArgumentException(u"group name must not be empty"_ustr, nullptr, 0);
152
0
    }
153
0
    for(sal_Int32 nPos = 0; nPos < aGroupName.getLength(); nPos++)
154
0
    {
155
0
        sal_Unicode cChar = aGroupName[nPos];
156
0
        if (rtl::isAsciiAlphanumeric(cChar) ||
157
0
            (cChar == '_') ||
158
0
            (cChar == 0x20) ||
159
0
            (cChar == GLOS_DELIM) )
160
0
        {
161
0
            continue;
162
0
        }
163
0
        throw lang::IllegalArgumentException(u"group name must contain a-z, A-z, '_', ' ' only"_ustr, nullptr, 0);
164
0
    }
165
0
    OUString sGroup(aGroupName);
166
0
    if (sGroup.indexOf(GLOS_DELIM)<0)
167
0
    {
168
0
        sGroup += OUStringChar(GLOS_DELIM) + "0";
169
0
    }
170
0
    m_pGlossaries->NewGroupDoc(sGroup, sGroup.getToken(0, GLOS_DELIM));
171
172
0
    uno::Reference< text::XAutoTextGroup > xGroup = m_pGlossaries->GetAutoTextGroup( sGroup );
173
0
    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?
175
176
0
    return xGroup;
177
0
}
178
179
void SwXAutoTextContainer::removeByName(const OUString& aGroupName)
180
0
{
181
0
    SolarMutexGuard aGuard;
182
    // At first find the name with path extension
183
0
    OUString sGroupName = m_pGlossaries->GetCompleteGroupName( aGroupName );
184
0
    if(sGroupName.isEmpty())
185
0
        throw container::NoSuchElementException();
186
0
    m_pGlossaries->DelGroupDoc(sGroupName);
187
0
}
188
189
OUString SwXAutoTextContainer::getImplementationName()
190
0
{
191
0
    return u"SwXAutoTextContainer"_ustr;
192
0
}
193
194
sal_Bool SwXAutoTextContainer::supportsService(const OUString& rServiceName)
195
0
{
196
0
    return cppu::supportsService(this, rServiceName);
197
0
}
198
199
uno::Sequence< OUString > SwXAutoTextContainer::getSupportedServiceNames()
200
0
{
201
0
    return { u"com.sun.star.text.AutoTextContainer"_ustr };
202
0
}
203
204
SwXAutoTextGroup::SwXAutoTextGroup(const OUString& rName,
205
            SwGlossaries*   pGlos) :
206
0
    m_pPropSet(aSwMapProvider.GetPropertySet(PROPERTY_MAP_AUTO_TEXT_GROUP)),
207
0
    m_pGlossaries(pGlos),
208
0
    m_sName(rName),
209
0
    m_sGroupName(rName)
210
0
{
211
0
    OSL_ENSURE( -1 != rName.indexOf( GLOS_DELIM ),
212
0
        "SwXAutoTextGroup::SwXAutoTextGroup: to be constructed with a complete name only!" );
213
0
}
214
215
SwXAutoTextGroup::~SwXAutoTextGroup()
216
0
{
217
0
}
218
219
uno::Sequence< OUString > SwXAutoTextGroup::getTitles()
220
0
{
221
0
    SolarMutexGuard aGuard;
222
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
223
0
    if (!pGlosGroup || pGlosGroup->GetError())
224
0
        throw uno::RuntimeException();
225
0
    const sal_uInt16 nCount = pGlosGroup->GetCount();
226
227
0
    uno::Sequence< OUString > aEntryTitles(nCount);
228
0
    OUString *pArr = aEntryTitles.getArray();
229
230
0
    for ( sal_uInt16 i = 0; i < nCount; i++ )
231
0
        pArr[i] = pGlosGroup->GetLongName(i);
232
0
    return aEntryTitles;
233
0
}
234
235
void SwXAutoTextGroup::renameByName(const OUString& aElementName,
236
    const OUString& aNewElementName, const OUString& aNewElementTitle)
237
0
{
238
0
    SolarMutexGuard aGuard;
239
    // throw exception only if the programmatic name is to be changed into an existing name
240
0
    if(aNewElementName != aElementName && hasByName(aNewElementName))
241
0
        throw container::ElementExistException();
242
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
243
0
    if(!pGlosGroup || pGlosGroup->GetError())
244
0
        throw uno::RuntimeException();
245
246
0
    const sal_uInt16 nIdx = pGlosGroup->GetIndex( aElementName);
247
0
    if(USHRT_MAX == nIdx)
248
0
        throw lang::IllegalArgumentException();
249
0
    const OUString& aNewShort(aNewElementName);
250
0
    const OUString& aNewName(aNewElementTitle);
251
0
    sal_uInt16 nOldLongIdx = pGlosGroup->GetLongIndex( aNewShort );
252
0
    sal_uInt16 nOldIdx = pGlosGroup->GetIndex( aNewName );
253
254
0
    if ((nOldLongIdx == USHRT_MAX || nOldLongIdx == nIdx)
255
0
        && (nOldIdx == USHRT_MAX || nOldIdx == nIdx))
256
0
    {
257
0
        pGlosGroup->Rename( nIdx, &aNewShort, &aNewName );
258
0
        if(pGlosGroup->GetError() != ERRCODE_NONE)
259
0
            throw io::IOException();
260
0
    }
261
262
0
}
263
264
static bool lcl_CopySelToDoc(SwDoc& rInsDoc, OTextCursorHelper* pxCursor, SwXTextRange* pxRange)
265
0
{
266
0
    SwNodes& rNds = rInsDoc.GetNodes();
267
268
0
    SwNodeIndex aIdx( rNds.GetEndOfContent(), -1 );
269
0
    SwContentNode * pNd = aIdx.GetNode().GetContentNode();
270
0
    SwPosition aPos(aIdx, pNd, pNd ? pNd->Len() : 0);
271
272
0
    bool bRet = false;
273
0
    rInsDoc.getIDocumentFieldsAccess().LockExpFields();
274
0
    {
275
0
        SwDoc *const pDoc(pxCursor ? pxCursor->GetDoc() : &pxRange->GetDoc());
276
0
        SwPaM aPam(pDoc->GetNodes());
277
0
        SwPaM * pPam(nullptr);
278
0
        if(pxCursor)
279
0
        {
280
0
            pPam = pxCursor->GetPaM();
281
0
        }
282
0
        else
283
0
        {
284
0
            if (pxRange->GetPositions(aPam))
285
0
            {
286
0
                pPam = & aPam;
287
0
            }
288
0
        }
289
0
        if (!pPam) { return false; }
290
0
        bRet = pDoc->getIDocumentContentOperations().CopyRange(*pPam, aPos, SwCopyFlags::CheckPosInFly)
291
0
            || bRet;
292
0
    }
293
294
0
    rInsDoc.getIDocumentFieldsAccess().UnlockExpFields();
295
0
    if( !rInsDoc.getIDocumentFieldsAccess().IsExpFieldsLocked() )
296
0
        rInsDoc.getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
297
298
0
    return bRet;
299
0
}
300
301
uno::Reference< text::XAutoTextEntry >  SwXAutoTextGroup::insertNewByName(const OUString& aName,
302
        const OUString& aTitle, const uno::Reference< text::XTextRange > & xTextRange)
303
0
{
304
0
    SolarMutexGuard aGuard;
305
0
    if(hasByName(aName))
306
0
        throw container::ElementExistException();
307
0
    if(!xTextRange.is())
308
0
        throw uno::RuntimeException();
309
310
0
    std::unique_ptr<SwTextBlocks> pGlosGroup;
311
0
    if (m_pGlossaries)
312
0
        pGlosGroup = m_pGlossaries->GetGroupDoc(m_sGroupName);
313
0
    const OUString& sShortName(aName);
314
0
    const OUString& sLongName(aTitle);
315
0
    if (pGlosGroup && !pGlosGroup->GetError())
316
0
    {
317
0
        SwXTextRange* pxRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
318
0
        OTextCursorHelper* pxCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
319
320
0
        OUString sOnlyText;
321
0
        OUString* pOnlyText = nullptr;
322
0
        bool bNoAttr = !pxCursor && !pxRange;
323
0
        if(bNoAttr)
324
0
        {
325
0
            sOnlyText = xTextRange->getString();
326
0
            pOnlyText = &sOnlyText;
327
0
        }
328
329
0
        const SvxAutoCorrCfg& rCfg = SvxAutoCorrCfg::Get();
330
331
0
        SwDoc* pGDoc = pGlosGroup->GetDoc();
332
333
        // Until there is an option for that, delete base util::URL
334
0
        if(rCfg.IsSaveRelFile())
335
0
        {
336
0
            INetURLObject aTemp(pGlosGroup->GetFileName());
337
0
            pGlosGroup->SetBaseURL( aTemp.GetMainURL(INetURLObject::DecodeMechanism::NONE));
338
0
        }
339
0
        else
340
0
            pGlosGroup->SetBaseURL( OUString() );
341
342
0
        sal_uInt16 nRet = USHRT_MAX;
343
0
        if( pOnlyText )
344
0
            nRet = pGlosGroup->PutText( sShortName, sLongName, *pOnlyText );
345
0
        else
346
0
        {
347
0
            pGlosGroup->ClearDoc();
348
0
            if( pGlosGroup->BeginPutDoc( sShortName, sLongName ) )
349
0
            {
350
0
                pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );
351
0
                lcl_CopySelToDoc(*pGDoc, pxCursor, pxRange);
352
0
                pGDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern(RedlineFlags::NONE);
353
0
                nRet = pGlosGroup->PutDoc();
354
0
            }
355
0
        }
356
357
0
        if (nRet == USHRT_MAX)
358
0
        {
359
0
            throw uno::RuntimeException();
360
0
        }
361
0
    }
362
0
    pGlosGroup.reset();
363
364
0
    uno::Reference< text::XAutoTextEntry > xEntry;
365
366
0
    try
367
0
    {
368
0
        xEntry = m_pGlossaries ?
369
0
            m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, sShortName ) :
370
0
            uno::Reference< text::XAutoTextEntry >();
371
0
        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?
373
0
    }
374
0
    catch (const container::ElementExistException&)
375
0
    {
376
0
        throw;
377
0
    }
378
0
    catch (const uno::RuntimeException&)
379
0
    {
380
0
        throw;
381
0
    }
382
0
    catch (const uno::Exception&)
383
0
    {
384
0
        css::uno::Any anyEx = cppu::getCaughtException();
385
0
        throw css::lang::WrappedTargetRuntimeException(
386
0
               u"Error Getting AutoText!"_ustr,
387
0
               getXWeak(),
388
0
               anyEx );
389
0
    }
390
391
0
    return xEntry;
392
0
}
393
394
void SwXAutoTextGroup::removeByName(const OUString& aEntryName)
395
0
{
396
0
    SolarMutexGuard aGuard;
397
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
398
0
    if(!pGlosGroup || pGlosGroup->GetError())
399
0
        throw container::NoSuchElementException();
400
401
0
    sal_uInt16 nIdx = pGlosGroup->GetIndex(aEntryName);
402
0
    if ( nIdx == USHRT_MAX )
403
0
        throw container::NoSuchElementException();
404
405
0
    pGlosGroup->Delete(nIdx);
406
0
}
407
408
OUString SwXAutoTextGroup::getName()
409
0
{
410
0
    SolarMutexGuard aGuard;
411
0
    return m_sName;
412
0
}
413
414
void SwXAutoTextGroup::setName(const OUString& rName)
415
0
{
416
0
    SolarMutexGuard aGuard;
417
0
    if( !m_pGlossaries )
418
0
        throw uno::RuntimeException();
419
420
0
    sal_Int32 nNewDelimPos = rName.lastIndexOf( GLOS_DELIM );
421
0
    sal_Int32 nOldDelimPos = m_sName.lastIndexOf( GLOS_DELIM );
422
423
0
    OUString aNewSuffix;
424
0
    if (nNewDelimPos > -1)
425
0
        aNewSuffix = rName.copy( nNewDelimPos + 1 );
426
0
    OUString aOldSuffix;
427
0
    if (nOldDelimPos > -1)
428
0
        aOldSuffix = m_sName.copy( nOldDelimPos + 1 );
429
430
0
    sal_Int32 nNewNumeric = aNewSuffix.toInt32();
431
0
    sal_Int32 nOldNumeric = aOldSuffix.toInt32();
432
433
0
    OUString aNewPrefix( (nNewDelimPos > 1) ? rName.copy( 0, nNewDelimPos ) : rName );
434
0
    OUString aOldPrefix( (nOldDelimPos > 1) ? m_sName.copy( 0, nOldDelimPos ) : m_sName );
435
436
0
    if ( m_sName == rName ||
437
0
       ( nNewNumeric == nOldNumeric && aNewPrefix == aOldPrefix ) )
438
0
        return;
439
0
    OUString sNewGroup(rName);
440
0
    if (sNewGroup.indexOf(GLOS_DELIM)<0)
441
0
    {
442
0
        sNewGroup += OUStringChar(GLOS_DELIM) + "0";
443
0
    }
444
445
    //the name must be saved, the group may be invalidated while in RenameGroupDoc()
446
0
    SwGlossaries* pTempGlossaries = m_pGlossaries;
447
448
0
    OUString sPreserveTitle( m_pGlossaries->GetGroupTitle( m_sName ) );
449
0
    if ( !m_pGlossaries->RenameGroupDoc( m_sName, sNewGroup, sPreserveTitle ) )
450
0
        throw uno::RuntimeException();
451
0
    m_sName = rName;
452
0
    m_sGroupName = sNewGroup;
453
0
    m_pGlossaries = pTempGlossaries;
454
0
}
455
456
sal_Int32 SwXAutoTextGroup::getCount()
457
0
{
458
0
    SolarMutexGuard aGuard;
459
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
460
0
    if (!pGlosGroup || pGlosGroup->GetError())
461
0
        throw uno::RuntimeException();
462
0
    return static_cast<sal_Int32>(pGlosGroup->GetCount());
463
0
}
464
465
uno::Any SwXAutoTextGroup::getByIndex(sal_Int32 nIndex)
466
0
{
467
0
    SolarMutexGuard aGuard;
468
0
    if (!m_pGlossaries)
469
0
        throw uno::RuntimeException();
470
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries->GetGroupDoc(m_sGroupName));
471
0
    if (!pGlosGroup || pGlosGroup->GetError())
472
0
        throw uno::RuntimeException();
473
0
    const sal_uInt16 nCount = pGlosGroup->GetCount();
474
0
    if (nIndex < 0 || o3tl::make_unsigned(nIndex) >= nCount)
475
0
        throw lang::IndexOutOfBoundsException();
476
0
    return getByName(pGlosGroup->GetShortName(o3tl::narrowing<sal_uInt16>(nIndex)));
477
0
}
478
479
uno::Type SwXAutoTextGroup::getElementType()
480
0
{
481
0
    return cppu::UnoType<text::XAutoTextEntry>::get();
482
483
0
}
484
485
sal_Bool SwXAutoTextGroup::hasElements()
486
0
{
487
0
    SolarMutexGuard aGuard;
488
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
489
0
    if (!pGlosGroup || pGlosGroup->GetError())
490
0
        throw uno::RuntimeException();
491
0
    return pGlosGroup->GetCount() > 0;
492
493
0
}
494
495
uno::Any SwXAutoTextGroup::getByName(const OUString& _rName)
496
0
{
497
0
    SolarMutexGuard aGuard;
498
0
    uno::Reference< text::XAutoTextEntry > xEntry = m_pGlossaries->GetAutoTextEntry( m_sGroupName, m_sName, _rName );
499
0
    OSL_ENSURE( xEntry.is(), "SwXAutoTextGroup::getByName: GetAutoTextEntry is fractious!" );
500
        // we told it to create the object, so why didn't it?
501
0
    return css::uno::Any( xEntry );
502
0
}
503
504
uno::Sequence< OUString > SwXAutoTextGroup::getElementNames()
505
0
{
506
0
    SolarMutexGuard aGuard;
507
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
508
0
    if (!pGlosGroup || pGlosGroup->GetError())
509
0
        throw uno::RuntimeException();
510
511
0
    const sal_uInt16 nCount = pGlosGroup->GetCount();
512
0
    uno::Sequence< OUString > aEntryNames(nCount);
513
0
    OUString *pArr = aEntryNames.getArray();
514
515
0
    for ( sal_uInt16 i = 0; i < nCount; i++ )
516
0
        pArr[i] = pGlosGroup->GetShortName(i);
517
0
    return aEntryNames;
518
0
}
519
520
sal_Bool SwXAutoTextGroup::hasByName(const OUString& rName)
521
0
{
522
0
    SolarMutexGuard aGuard;
523
0
    bool bRet = false;
524
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
525
0
    if (!pGlosGroup || pGlosGroup->GetError())
526
0
        throw uno::RuntimeException();
527
528
0
    const sal_uInt16 nCount = pGlosGroup->GetCount();
529
0
    for( sal_uInt16 i = 0; i < nCount; ++i )
530
0
    {
531
0
        OUString sCompare(pGlosGroup->GetShortName(i));
532
0
        if(sCompare.equalsIgnoreAsciiCase(rName))
533
0
        {
534
0
            bRet = true;
535
0
            break;
536
0
        }
537
0
    }
538
0
    return bRet;
539
0
}
540
541
uno::Reference< beans::XPropertySetInfo >  SwXAutoTextGroup::getPropertySetInfo()
542
0
{
543
0
    static uno::Reference< beans::XPropertySetInfo >  xRet = m_pPropSet->getPropertySetInfo();
544
0
    return xRet;
545
0
}
546
547
void SwXAutoTextGroup::setPropertyValue(
548
    const OUString& rPropertyName, const uno::Any& aValue)
549
0
{
550
0
    SolarMutexGuard aGuard;
551
0
    const SfxItemPropertyMapEntry*   pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName );
552
553
0
    if(!pEntry)
554
0
        throw beans::UnknownPropertyException(rPropertyName);
555
556
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
557
0
    if(!pGlosGroup || pGlosGroup->GetError())
558
0
        throw uno::RuntimeException();
559
0
    switch(pEntry->nWID)
560
0
    {
561
0
        case  WID_GROUP_TITLE:
562
0
        {
563
0
            OUString sNewTitle;
564
0
            aValue >>= sNewTitle;
565
0
            if(sNewTitle.isEmpty())
566
0
                throw lang::IllegalArgumentException();
567
0
            bool bChanged = sNewTitle != pGlosGroup->GetName();
568
0
            pGlosGroup->SetName(sNewTitle);
569
0
            if(bChanged && HasGlossaryList())
570
0
                GetGlossaryList()->ClearGroups();
571
0
        }
572
0
        break;
573
0
    }
574
0
}
575
576
uno::Any SwXAutoTextGroup::getPropertyValue(const OUString& rPropertyName)
577
0
{
578
0
    SolarMutexGuard aGuard;
579
0
    const SfxItemPropertyMapEntry*   pEntry = m_pPropSet->getPropertyMap().getByName( rPropertyName);
580
581
0
    if(!pEntry)
582
0
        throw beans::UnknownPropertyException(rPropertyName);
583
0
    std::unique_ptr<SwTextBlocks> pGlosGroup(m_pGlossaries ? m_pGlossaries->GetGroupDoc(m_sGroupName) : nullptr);
584
0
    if(!pGlosGroup  || pGlosGroup->GetError())
585
0
        throw uno::RuntimeException();
586
587
0
    uno::Any aAny;
588
0
    switch(pEntry->nWID)
589
0
    {
590
0
        case  WID_GROUP_PATH:
591
0
            aAny <<= pGlosGroup->GetFileName();
592
0
        break;
593
0
        case  WID_GROUP_TITLE:
594
0
            aAny <<= pGlosGroup->GetName();
595
0
        break;
596
0
    }
597
0
    return aAny;
598
0
}
599
600
void SwXAutoTextGroup::addPropertyChangeListener(
601
    const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
602
0
{
603
0
}
604
605
void SwXAutoTextGroup::removePropertyChangeListener(
606
    const OUString& /*PropertyName*/, const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
607
0
{
608
0
}
609
610
void SwXAutoTextGroup::addVetoableChangeListener(
611
    const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
612
0
{
613
0
}
614
615
void SwXAutoTextGroup::removeVetoableChangeListener(
616
    const OUString& /*PropertyName*/, const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
617
0
{
618
0
}
619
620
void SwXAutoTextGroup::Invalidate()
621
0
{
622
0
    m_pGlossaries = nullptr;
623
0
    m_sName.clear();
624
0
    m_sGroupName.clear();
625
0
}
626
627
OUString SwXAutoTextGroup::getImplementationName()
628
0
{
629
0
    return u"SwXAutoTextGroup"_ustr;
630
0
}
631
632
sal_Bool SwXAutoTextGroup::supportsService(const OUString& rServiceName)
633
0
{
634
0
    return cppu::supportsService(this, rServiceName);
635
0
}
636
637
uno::Sequence< OUString > SwXAutoTextGroup::getSupportedServiceNames()
638
0
{
639
0
    uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextGroup"_ustr };
640
0
    return aRet;
641
0
}
642
643
SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries* pGlss, OUString aGroupName,
644
                                            OUString aEntryName) :
645
0
    m_pGlossaries(pGlss),
646
0
    m_sGroupName(std::move(aGroupName)),
647
0
    m_sEntryName(std::move(aEntryName))
648
0
{
649
0
}
Unexecuted instantiation: SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries*, rtl::OUString, rtl::OUString)
Unexecuted instantiation: SwXAutoTextEntry::SwXAutoTextEntry(SwGlossaries*, rtl::OUString, rtl::OUString)
650
651
SwXAutoTextEntry::~SwXAutoTextEntry()
652
0
{
653
0
    SolarMutexGuard aGuard;
654
655
    // ensure that any pending modifications are written
656
0
    implFlushDocument( true );
657
0
}
658
659
void SwXAutoTextEntry::implFlushDocument( bool _bCloseDoc )
660
0
{
661
0
    if ( !m_xDocSh.is() )
662
0
        return;
663
664
0
    if ( m_xDocSh->GetDoc()->getIDocumentState().IsModified () )
665
0
        m_xDocSh->Save();
666
667
0
    if ( _bCloseDoc )
668
0
    {
669
        // stop listening at the document
670
0
        EndListening( *m_xDocSh );
671
672
0
        m_xDocSh->DoClose();
673
0
        m_xDocSh.clear();
674
0
    }
675
0
}
676
677
void SwXAutoTextEntry::Notify( SfxBroadcaster& _rBC, const SfxHint& _rHint )
678
0
{
679
0
    if ( &_rBC != m_xDocSh.get() )
680
0
        return;
681
682
// it's our document
683
0
    if (_rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint)
684
0
    {
685
0
        const SfxEventHint& rEventHint = static_cast<const SfxEventHint&>(_rHint);
686
0
        if (SfxEventHintId::PrepareCloseDoc == rEventHint.GetEventId())
687
0
        {
688
0
            implFlushDocument();
689
0
            mxBodyText.clear();
690
0
            EndListening( *m_xDocSh );
691
0
            m_xDocSh.clear();
692
0
        }
693
0
    }
694
0
    else
695
0
    {
696
0
        if ( SfxHintId::Deinitializing == _rHint.GetId() )
697
0
        {
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
0
            EndListening( *m_xDocSh );
702
            // and release our reference
703
0
            m_xDocSh.clear();
704
0
        }
705
0
    }
706
0
}
707
708
void SwXAutoTextEntry::GetBodyText ()
709
0
{
710
0
    SolarMutexGuard aGuard;
711
712
0
    m_xDocSh = m_pGlossaries->EditGroupDoc ( m_sGroupName, m_sEntryName, false );
713
0
    OSL_ENSURE( m_xDocSh.is(), "SwXAutoTextEntry::GetBodyText: unexpected: no doc returned by EditGroupDoc!" );
714
715
    // start listening at the document
716
0
    StartListening( *m_xDocSh );
717
718
0
    mxBodyText = new SwXBodyText ( m_xDocSh->GetDoc() );
719
0
}
720
721
void SwXAutoTextEntry::disposing(std::unique_lock<std::mutex>&)
722
0
{
723
0
    SolarMutexGuard g;
724
0
    implFlushDocument(true);
725
0
}
726
727
uno::Reference< text::XTextCursor >  SwXAutoTextEntry::createTextCursor()
728
0
{
729
0
    SolarMutexGuard aGuard;
730
0
    EnsureBodyText();
731
0
    return mxBodyText->createTextCursor();
732
0
}
733
734
uno::Reference< text::XTextCursor >  SwXAutoTextEntry::createTextCursorByRange(
735
    const uno::Reference< text::XTextRange > & aTextPosition)
736
0
{
737
0
    SolarMutexGuard aGuard;
738
0
    EnsureBodyText();
739
0
    return mxBodyText->createTextCursorByRange ( aTextPosition );
740
0
}
741
742
void SwXAutoTextEntry::insertString(const uno::Reference< text::XTextRange > & xRange, const OUString& aString, sal_Bool bAbsorb)
743
0
{
744
0
    SolarMutexGuard aGuard;
745
0
    EnsureBodyText();
746
0
    mxBodyText->insertString ( xRange, aString, bAbsorb );
747
0
}
748
749
void SwXAutoTextEntry::insertControlCharacter(const uno::Reference< text::XTextRange > & xRange,
750
    sal_Int16 nControlCharacter, sal_Bool bAbsorb)
751
0
{
752
0
    SolarMutexGuard aGuard;
753
0
    EnsureBodyText();
754
0
    mxBodyText->insertControlCharacter ( xRange, nControlCharacter, bAbsorb );
755
0
}
756
757
void SwXAutoTextEntry::insertTextContent(
758
    const uno::Reference< text::XTextRange > & xRange,
759
    const uno::Reference< text::XTextContent > & xContent, sal_Bool bAbsorb)
760
0
{
761
0
    SolarMutexGuard aGuard;
762
0
    EnsureBodyText();
763
0
    mxBodyText->insertTextContent ( xRange, xContent, bAbsorb );
764
0
}
765
766
void SwXAutoTextEntry::removeTextContent(
767
    const uno::Reference< text::XTextContent > & xContent)
768
0
{
769
0
    SolarMutexGuard aGuard;
770
0
    EnsureBodyText();
771
0
    mxBodyText->removeTextContent ( xContent );
772
0
}
773
774
uno::Reference< text::XText >  SwXAutoTextEntry::getText()
775
0
{
776
0
    SolarMutexGuard aGuard;
777
0
    uno::Reference< text::XText >  xRet =  static_cast<text::XText*>(this);
778
0
    return xRet;
779
0
}
780
781
uno::Reference< text::XTextRange >  SwXAutoTextEntry::getStart()
782
0
{
783
0
    SolarMutexGuard aGuard;
784
0
    EnsureBodyText();
785
0
    return mxBodyText->getStart();
786
0
}
787
788
uno::Reference< text::XTextRange >  SwXAutoTextEntry::getEnd()
789
0
{
790
0
    SolarMutexGuard aGuard;
791
0
    EnsureBodyText();
792
0
    return mxBodyText->getEnd();
793
0
}
794
795
OUString SwXAutoTextEntry::getString()
796
0
{
797
0
    SolarMutexGuard aGuard;
798
0
    EnsureBodyText();
799
0
    return mxBodyText->getString();
800
0
}
801
802
void SwXAutoTextEntry::setString(const OUString& aString)
803
0
{
804
0
    SolarMutexGuard aGuard;
805
0
    EnsureBodyText();
806
0
    mxBodyText->setString( aString );
807
0
}
808
809
void SwXAutoTextEntry::applyTo(const uno::Reference< text::XTextRange > & xTextRange)
810
0
{
811
0
    SolarMutexGuard aGuard;
812
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
0
    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
824
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
0
    auto xKeepAlive( xTextRange );
828
0
    SwXTextRange* pRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
829
0
    OTextCursorHelper* pCursor = dynamic_cast<OTextCursorHelper*>(xTextRange.get());
830
0
    SwXText *pText = dynamic_cast<SwXText*>(xTextRange.get());
831
832
0
    SwDoc* pDoc = nullptr;
833
0
    if (pRange)
834
0
        pDoc = &pRange->GetDoc();
835
0
    else if ( pCursor )
836
0
        pDoc = pCursor->GetDoc();
837
0
    else if ( pText && pText->GetDoc() )
838
0
    {
839
0
        xKeepAlive = pText->getStart();
840
0
        pCursor = dynamic_cast<OTextCursorHelper*>(xKeepAlive.get());
841
0
        if (pCursor)
842
0
            pDoc = pText->GetDoc();
843
0
    }
844
845
0
    if(!pDoc)
846
0
        throw uno::RuntimeException();
847
848
0
    SwPaM InsertPaM(pDoc->GetNodes());
849
0
    if (pRange)
850
0
    {
851
0
        if (!pRange->GetPositions(InsertPaM))
852
0
        {
853
0
            throw uno::RuntimeException();
854
0
        }
855
0
    }
856
0
    else
857
0
    {
858
0
        InsertPaM = *pCursor->GetPaM();
859
0
    }
860
861
0
    std::unique_ptr<SwTextBlocks> pBlock(m_pGlossaries->GetGroupDoc(m_sGroupName));
862
0
    const bool bResult = pBlock && !pBlock->GetError()
863
0
                    && pDoc->InsertGlossary( *pBlock, m_sEntryName, InsertPaM);
864
865
0
    if(!bResult)
866
0
        throw uno::RuntimeException();
867
0
}
868
869
OUString SwXAutoTextEntry::getImplementationName()
870
0
{
871
0
    return u"SwXAutoTextEntry"_ustr;
872
0
}
873
874
sal_Bool SwXAutoTextEntry::supportsService(const OUString& rServiceName)
875
0
{
876
0
    return cppu::supportsService(this, rServiceName);
877
0
}
878
879
uno::Sequence< OUString > SwXAutoTextEntry::getSupportedServiceNames()
880
0
{
881
0
    uno::Sequence<OUString> aRet { u"com.sun.star.text.AutoTextEntry"_ustr };
882
0
    return aRet;
883
0
}
884
885
uno::Reference< container::XNameReplace > SwXAutoTextEntry::getEvents()
886
0
{
887
0
    return new SwAutoTextEventDescriptor( *this );
888
0
}
889
890
const struct SvEventDescription aAutotextEvents[] =
891
{
892
    { SvMacroItemId::SwStartInsGlossary,  "OnInsertStart" },
893
    { SvMacroItemId::SwEndInsGlossary,    "OnInsertDone" },
894
    { SvMacroItemId::NONE, nullptr }
895
};
896
897
SwAutoTextEventDescriptor::SwAutoTextEventDescriptor(
898
    SwXAutoTextEntry& rAutoText ) :
899
0
        SvBaseEventDescriptor(aAutotextEvents),
900
0
        m_rAutoTextEntry(rAutoText)
901
0
{
902
0
}
903
904
SwAutoTextEventDescriptor::~SwAutoTextEventDescriptor()
905
0
{
906
0
}
907
908
OUString SwAutoTextEventDescriptor::getImplementationName()
909
0
{
910
0
    return u"SwAutoTextEventDescriptor"_ustr;
911
0
}
912
913
void SwAutoTextEventDescriptor::replaceByName(
914
    const SvMacroItemId nEvent,
915
    const SvxMacro& rMacro)
916
0
{
917
0
    OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(),
918
0
                "Strangely enough, the AutoText vanished!" );
919
0
    OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
920
0
                (nEvent == SvMacroItemId::SwStartInsGlossary) ,
921
0
                "Unknown event ID" );
922
923
0
    SwGlossaries *const pGlossaries =
924
0
        const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
925
0
    std::unique_ptr<SwTextBlocks> pBlocks(
926
0
        pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
927
0
    OSL_ENSURE( pBlocks,
928
0
                "can't get autotext group; SwAutoTextEntry has illegal name?");
929
930
0
    if( !pBlocks || pBlocks->GetError())
931
0
        return;
932
933
0
    sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
934
0
    if( nIndex != USHRT_MAX )
935
0
    {
936
0
        SvxMacroTableDtor aMacroTable;
937
0
        if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
938
0
        {
939
0
            aMacroTable.Insert( nEvent, rMacro );
940
0
            pBlocks->SetMacroTable( nIndex, aMacroTable );
941
0
        }
942
0
    }
943
    // else: ignore
944
0
}
945
946
void SwAutoTextEventDescriptor::getByName(
947
    SvxMacro& rMacro,
948
    const SvMacroItemId nEvent )
949
0
{
950
0
    OSL_ENSURE( nullptr != m_rAutoTextEntry.GetGlossaries(), "no AutoText" );
951
0
    OSL_ENSURE( (nEvent == SvMacroItemId::SwEndInsGlossary) ||
952
0
                (nEvent == SvMacroItemId::SwStartInsGlossary) ,
953
0
                "Unknown event ID" );
954
955
0
    SwGlossaries *const pGlossaries =
956
0
        const_cast<SwGlossaries*>(m_rAutoTextEntry.GetGlossaries());
957
0
    std::unique_ptr<SwTextBlocks> pBlocks(
958
0
        pGlossaries->GetGroupDoc( m_rAutoTextEntry.GetGroupName() ));
959
0
    OSL_ENSURE( pBlocks,
960
0
                "can't get autotext group; SwAutoTextEntry has illegal name?");
961
962
    // return empty macro, unless macro is found
963
0
    OUString sEmptyStr;
964
0
    rMacro = SvxMacro(sEmptyStr, sEmptyStr);
965
966
0
    if ( !pBlocks || pBlocks->GetError())
967
0
        return;
968
969
0
    sal_uInt16 nIndex = pBlocks->GetIndex( m_rAutoTextEntry.GetEntryName() );
970
0
    if( nIndex != USHRT_MAX )
971
0
    {
972
0
        SvxMacroTableDtor aMacroTable;
973
0
        if( pBlocks->GetMacroTable( nIndex, aMacroTable ) )
974
0
        {
975
0
            SvxMacro *pMacro = aMacroTable.Get( nEvent );
976
0
            if( pMacro )
977
0
                rMacro = *pMacro;
978
0
        }
979
0
    }
980
0
}
981
982
extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
983
SwXAutoTextContainer_get_implementation(css::uno::XComponentContext*,
984
        css::uno::Sequence<css::uno::Any> const &)
985
0
{
986
    //the module may not be loaded
987
0
    SolarMutexGuard aGuard;
988
0
    SwGlobals::ensure();
989
0
    return cppu::acquire(new SwXAutoTextContainer());
990
0
}
991
992
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */