Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/sd/source/ui/unoidl/unosrch.cxx
Line
Count
Source
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 <memory>
21
#include <sal/config.h>
22
23
#include <com/sun/star/drawing/XShapes.hpp>
24
#include <com/sun/star/drawing/XDrawPage.hpp>
25
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
26
#include <utility>
27
#include <vcl/svapp.hxx>
28
29
#include <svx/svdobj.hxx>
30
#include <svx/svdpool.hxx>
31
#include <editeng/unoipset.hxx>
32
#include <editeng/unotext.hxx>
33
#include <tools/debug.hxx>
34
35
#include <unoprnms.hxx>
36
#include <unosrch.hxx>
37
38
using namespace ::com::sun::star;
39
40
0
#define WID_SEARCH_BACKWARDS    0
41
0
#define WID_SEARCH_CASE         1
42
0
#define WID_SEARCH_WORDS        2
43
44
static std::span<const SfxItemPropertyMapEntry> ImplGetSearchPropertyMap()
45
0
{
46
0
    static const SfxItemPropertyMapEntry aSearchPropertyMap_Impl[] =
47
0
    {
48
0
        { u"" UNO_NAME_SEARCH_BACKWARDS ""_ustr,  WID_SEARCH_BACKWARDS,   cppu::UnoType<bool>::get(),    0,  0 },
49
0
        { u"" UNO_NAME_SEARCH_CASE ""_ustr,       WID_SEARCH_CASE,        cppu::UnoType<bool>::get(),    0,  0 },
50
0
        { u"" UNO_NAME_SEARCH_WORDS ""_ustr,      WID_SEARCH_WORDS,       cppu::UnoType<bool>::get(),    0,  0 },
51
0
    };
52
53
0
    return aSearchPropertyMap_Impl;
54
0
}
55
56
namespace {
57
58
class SearchContext_impl
59
{
60
    uno::Reference< drawing::XShapes > mxShapes;
61
    sal_Int32 mnIndex;
62
63
public:
64
    SearchContext_impl(uno::Reference<drawing::XShapes> xShapes)
65
0
        : mxShapes(std::move( xShapes )), mnIndex( -1 ) {}
66
67
    uno::Reference< drawing::XShape > firstShape()
68
0
    {
69
0
        mnIndex = -1;
70
0
        return nextShape();
71
0
    }
72
73
    uno::Reference< drawing::XShape > nextShape()
74
0
    {
75
0
        uno::Reference< drawing::XShape >  xShape;
76
0
        mnIndex++;
77
0
        if( mxShapes.is() && mxShapes->getCount() > mnIndex )
78
0
        {
79
0
            mxShapes->getByIndex( mnIndex ) >>= xShape;
80
0
        }
81
0
        return xShape;
82
0
    }
83
};
84
85
}
86
87
/* ================================================================= */
88
/** this class implements a search or replace operation on a given
89
    page or a given sdrobj
90
  */
91
92
SdUnoSearchReplaceShape::SdUnoSearchReplaceShape( drawing::XDrawPage* pPage ) noexcept
93
310k
    : mpPage(pPage)
94
310k
{
95
310k
}
96
97
SdUnoSearchReplaceShape::~SdUnoSearchReplaceShape() noexcept
98
310k
{
99
310k
}
100
101
// util::XReplaceable
102
uno::Reference< util::XReplaceDescriptor > SAL_CALL SdUnoSearchReplaceShape::createReplaceDescriptor()
103
0
{
104
0
    return new SdUnoSearchReplaceDescriptor;
105
0
}
106
107
sal_Int32 SAL_CALL SdUnoSearchReplaceShape::replaceAll( const uno::Reference< util::XSearchDescriptor >& xDesc )
108
0
{
109
0
    SdUnoSearchReplaceDescriptor* pDescr = dynamic_cast<SdUnoSearchReplaceDescriptor*>( xDesc.get() );
110
0
    if( pDescr == nullptr )
111
0
        return 0;
112
113
0
    sal_Int32 nFound    = 0;
114
115
0
    uno::Reference< drawing::XShapes >  xShapes;
116
0
    uno::Reference< drawing::XShape >  xShape;
117
118
0
    std::vector<SearchContext_impl> aContexts;
119
0
    if(mpPage)
120
0
    {
121
0
        xShapes = mpPage;
122
123
0
        if( xShapes->getCount() )
124
0
        {
125
0
            aContexts.push_back(SearchContext_impl(xShapes));
126
0
            xShape = aContexts.back().firstShape();
127
0
        }
128
0
        else
129
0
        {
130
0
            xShapes = nullptr;
131
0
        }
132
0
    }
133
134
0
    while( xShape.is() )
135
0
    {
136
        // replace in xShape
137
0
        uno::Reference< text::XText >  xText(xShape, uno::UNO_QUERY);
138
0
        uno::Reference< text::XTextRange >  xRange = xText;
139
0
        uno::Reference< text::XTextRange >  xFound;
140
141
0
        while( xRange.is() )
142
0
        {
143
0
            xFound = Search( xRange, pDescr );
144
0
            if( !xFound.is() )
145
0
                break;
146
147
0
            xFound->setString( pDescr->getReplaceString() );
148
0
            xRange = xFound->getEnd();
149
0
            nFound++;
150
0
        }
151
        // done with xShape -> get next shape
152
153
        // test if it's a group
154
0
        uno::Reference< drawing::XShapes > xGroupShape( xShape, uno::UNO_QUERY );
155
0
        if( xGroupShape.is() && ( xGroupShape->getCount() > 0 ) )
156
0
        {
157
0
            aContexts.push_back(SearchContext_impl(xGroupShape));
158
0
            xShape = aContexts.back().firstShape();
159
0
        }
160
0
        else
161
0
        {
162
0
            if (!aContexts.empty())
163
0
                xShape = aContexts.back().nextShape();
164
0
            else
165
0
                xShape = nullptr;
166
0
        }
167
168
        // test parent contexts for next shape if none
169
        // is found in the current context
170
0
        while (!aContexts.empty() && !xShape.is())
171
0
        {
172
0
            aContexts.pop_back();
173
0
            if (!aContexts.empty())
174
0
                xShape = aContexts.back().nextShape();
175
0
        }
176
0
    }
177
178
0
    return nFound;
179
0
}
180
181
// XSearchable
182
uno::Reference< css::util::XSearchDescriptor > SAL_CALL SdUnoSearchReplaceShape::createSearchDescriptor(  )
183
0
{
184
0
    return new SdUnoSearchReplaceDescriptor;
185
0
}
186
187
uno::Reference< css::container::XIndexAccess > SAL_CALL SdUnoSearchReplaceShape::findAll( const css::uno::Reference< css::util::XSearchDescriptor >& xDesc )
188
0
{
189
0
    SdUnoSearchReplaceDescriptor* pDescr = dynamic_cast<SdUnoSearchReplaceDescriptor*>( xDesc.get() );
190
0
    if( pDescr == nullptr )
191
0
        return uno::Reference< container::XIndexAccess > ();
192
193
0
    sal_Int32 nSequence = 32;
194
0
    sal_Int32 nFound    = 0;
195
196
0
    uno::Sequence < uno::Reference< uno::XInterface >  > aSeq( nSequence );
197
198
0
    uno::Reference< uno::XInterface > * pArray = aSeq.getArray();
199
200
0
    uno::Reference< drawing::XShapes >  xShapes;
201
0
    uno::Reference< drawing::XShape >  xShape;
202
203
0
    std::vector<SearchContext_impl> aContexts;
204
0
    if(mpPage)
205
0
    {
206
0
        xShapes = mpPage;
207
208
0
        if( xShapes->getCount() > 0 )
209
0
        {
210
0
            aContexts.push_back(SearchContext_impl(xShapes));
211
0
            xShape = aContexts.back().firstShape();
212
0
        }
213
0
        else
214
0
        {
215
0
            xShapes = nullptr;
216
0
        }
217
0
    }
218
219
0
    while( xShape.is() )
220
0
    {
221
        // find in xShape
222
0
        uno::Reference< text::XText >  xText(xShape, uno::UNO_QUERY);
223
0
        uno::Reference< text::XTextRange >  xRange = xText;
224
0
        uno::Reference< text::XTextRange >  xFound;
225
226
0
        while( xRange.is() )
227
0
        {
228
0
            xFound = Search( xRange, pDescr );
229
0
            if( !xFound.is() )
230
0
                break;
231
232
0
            if( nFound >= nSequence )
233
0
            {
234
0
                nSequence += 32;
235
0
                aSeq.realloc( nSequence );
236
0
                pArray = aSeq.getArray();
237
0
            }
238
239
0
            pArray[nFound++] = xFound;
240
241
0
            xRange = xFound->getEnd();
242
0
        }
243
        // done with shape -> get next shape
244
245
        // test if it's a group
246
0
        uno::Reference< drawing::XShapes >  xGroupShape;
247
0
        xGroupShape.set( xShape, uno::UNO_QUERY );
248
249
0
        if( xGroupShape.is() && xGroupShape->getCount() > 0 )
250
0
        {
251
0
            aContexts.push_back(SearchContext_impl(xGroupShape));
252
0
            xShape = aContexts.back().firstShape();
253
0
        }
254
0
        else
255
0
        {
256
0
            if (!aContexts.empty())
257
0
                xShape = aContexts.back().nextShape();
258
0
            else
259
0
                xShape = nullptr;
260
0
        }
261
262
        // test parent contexts for next shape if none
263
        // is found in the current context
264
0
        while (!aContexts.empty() && !xShape.is())
265
0
        {
266
0
            aContexts.pop_back();
267
0
            if (!aContexts.empty())
268
0
                xShape = aContexts.back().nextShape();
269
0
        }
270
0
    }
271
272
0
    if( nFound != nSequence )
273
0
        aSeq.realloc( nFound );
274
275
0
    uno::Reference<css::container::XIndexAccess> xRet(new SdUnoFindAllAccess(aSeq));
276
0
    return xRet;
277
0
}
278
279
uno::Reference< css::uno::XInterface > SAL_CALL SdUnoSearchReplaceShape::findFirst( const css::uno::Reference< css::util::XSearchDescriptor >& xDesc )
280
0
{
281
0
    uno::Reference< text::XTextRange > xRange( GetCurrentShape(), uno::UNO_QUERY );
282
0
    if( xRange.is() )
283
0
        return findNext( xRange, xDesc );
284
285
0
    return uno::Reference< uno::XInterface > ();
286
0
}
287
288
uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetCurrentShape() const noexcept
289
0
{
290
0
    uno::Reference< drawing::XShape >  xShape;
291
292
0
    if( mpPage && mpPage->getCount() > 0)
293
0
        mpPage->getByIndex(0) >>= xShape;
294
295
0
    return xShape;
296
297
0
}
298
299
uno::Reference< css::uno::XInterface > SAL_CALL SdUnoSearchReplaceShape::findNext( const css::uno::Reference< css::uno::XInterface >& xStartAt, const css::uno::Reference< css::util::XSearchDescriptor >& xDesc )
300
0
{
301
0
    SdUnoSearchReplaceDescriptor* pDescr = dynamic_cast<SdUnoSearchReplaceDescriptor*>( xDesc.get() );
302
303
0
    uno::Reference< uno::XInterface > xFound;
304
305
0
    uno::Reference< text::XTextRange > xRange( xStartAt, uno::UNO_QUERY );
306
0
    if(pDescr && xRange.is() )
307
0
    {
308
309
0
        uno::Reference< text::XTextRange > xCurrentRange( xStartAt, uno::UNO_QUERY );
310
311
0
        uno::Reference< drawing::XShape > xCurrentShape( GetShape( xCurrentRange ) );
312
313
0
        while(!xFound.is() && xRange.is())
314
0
        {
315
0
            xFound = Search( xRange, pDescr );
316
0
            if(!xFound.is())
317
0
            {
318
                // we need a new starting range now
319
0
                xRange = nullptr;
320
321
0
                if(mpPage)
322
0
                {
323
                    // we do a page wide search, so skip to the next shape here
324
                    // get next shape on our page
325
0
                    uno::Reference< drawing::XShape > xFound2( GetNextShape( mpPage, xCurrentShape ) );
326
0
                    if( xFound2.is() && (xFound2.get() != xCurrentShape.get()) )
327
0
                        xCurrentShape = std::move(xFound2);
328
0
                    else
329
0
                        xCurrentShape = nullptr;
330
331
0
                    xRange.set( xCurrentShape, uno::UNO_QUERY );
332
0
                    if(!(xCurrentShape.is() && (xRange.is())))
333
0
                        xRange = nullptr;
334
0
                }
335
0
                else
336
0
                {
337
                    // we search only in this shape, so end search if we have
338
                    // not found anything
339
0
                }
340
0
            }
341
0
        }
342
0
    }
343
0
    return xFound;
344
0
}
345
346
/** this method returns the shape that follows xCurrentShape in the shape collection xShapes.
347
    It steps recursive into groupshapes and returns the xCurrentShape if it is the last
348
    shape in this collection */
349
uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetNextShape( const uno::Reference< container::XIndexAccess >&  xShapes, const uno::Reference< drawing::XShape >&  xCurrentShape ) noexcept
350
0
{
351
0
    uno::Reference< drawing::XShape >  xFound;
352
353
0
    if(xShapes.is() && xCurrentShape.is())
354
0
    {
355
0
        const sal_Int32 nCount = xShapes->getCount();
356
0
        for( sal_Int32 i = 0; i < nCount; i++ )
357
0
        {
358
0
            uno::Reference< drawing::XShape > xSearchShape;
359
0
            xShapes->getByIndex(i) >>= xSearchShape;
360
361
0
            if( xSearchShape.is() )
362
0
            {
363
0
                uno::Reference< container::XIndexAccess > xGroup( xSearchShape, uno::UNO_QUERY );
364
365
0
                if( xCurrentShape.get() == xSearchShape.get() )
366
0
                {
367
0
                    if( xGroup.is() && xGroup->getCount() > 0 )
368
0
                    {
369
0
                        xGroup->getByIndex( 0 ) >>= xFound;
370
0
                    }
371
0
                    else
372
0
                    {
373
0
                        i++;
374
0
                        if( i < nCount )
375
0
                            xShapes->getByIndex( i ) >>= xFound;
376
0
                        else
377
0
                            xFound = xCurrentShape;
378
0
                    }
379
380
0
                    break;
381
0
                }
382
0
                else if( xGroup.is() )
383
0
                {
384
0
                    xFound = GetNextShape( xGroup, xCurrentShape );
385
0
                    if( xFound.is() )
386
0
                    {
387
0
                        if( xFound.get() == xCurrentShape.get() )
388
0
                        {
389
                            // the current shape was found at the end of the group
390
0
                            i++;
391
0
                            if( i < nCount )
392
0
                            {
393
0
                                xShapes->getByIndex(i) >>= xFound;
394
0
                            }
395
0
                        }
396
0
                        break;
397
0
                    }
398
0
                }
399
0
            }
400
0
        }
401
0
    }
402
403
0
    return xFound;
404
0
}
405
406
uno::Reference< text::XTextRange >  SdUnoSearchReplaceShape::Search( const uno::Reference< text::XTextRange >&  xText, SdUnoSearchReplaceDescriptor* pDescr )
407
0
{
408
0
    if(!xText.is())
409
0
        return uno::Reference< text::XTextRange > ();
410
411
0
    uno::Reference< text::XText > xParent( xText->getText() );
412
413
0
    if( !xParent.is() )
414
0
    {
415
0
        xParent.set( xText, uno::UNO_QUERY );
416
0
    }
417
418
0
    const OUString aText( xParent->getString() );
419
420
0
    const sal_Int32 nTextLen = aText.getLength();
421
422
0
    std::unique_ptr<sal_Int32[]> pConvertPos( new sal_Int32[nTextLen+2] );
423
0
    std::unique_ptr<sal_Int32[]> pConvertPara( new sal_Int32[nTextLen+2] );
424
425
0
    sal_Int32* pPos = pConvertPos.get();
426
0
    sal_Int32* pPara = pConvertPara.get();
427
428
0
    sal_Int32 nLastPos = 0, nLastPara = 0;
429
430
0
    uno::Reference< container::XEnumerationAccess > xEnumAccess( xParent, uno::UNO_QUERY );
431
432
    // first we fill the arrays with the position and paragraph for every character
433
    // inside the text
434
0
    if( xEnumAccess.is() )
435
0
    {
436
0
        uno::Reference< container::XEnumeration >  xParaEnum( xEnumAccess->createEnumeration() );
437
438
0
        while(xParaEnum->hasMoreElements())
439
0
        {
440
0
            int ndbg = 0;
441
0
            uno::Reference< text::XTextContent >  xParagraph( xParaEnum->nextElement(), uno::UNO_QUERY );
442
0
            if( xParagraph.is() )
443
0
                xEnumAccess.set(xParagraph, css::uno::UNO_QUERY);
444
0
            else
445
0
                xEnumAccess.clear();
446
447
0
            if( xEnumAccess.is() )
448
0
            {
449
0
                uno::Reference< container::XEnumeration >  xPortionEnum( xEnumAccess->createEnumeration() );
450
0
                if( xPortionEnum.is() )
451
0
                {
452
0
                    while(xPortionEnum->hasMoreElements())
453
0
                    {
454
0
                        uno::Reference< text::XTextRange >  xPortion( xPortionEnum->nextElement(), uno::UNO_QUERY );
455
0
                        if( xPortion.is() )
456
0
                        {
457
0
                            const OUString aPortion( xPortion->getString() );
458
0
                            const sal_Int32 nLen = aPortion.getLength();
459
460
0
                            ESelection aStartSel( GetSelection( xPortion->getStart() ) );
461
0
                            ESelection aEndSel( GetSelection( xPortion->getEnd() ) );
462
463
                            // special case for empty portions with content or length one portions with content (fields)
464
0
                            if( (aStartSel.start.nIndex == aEndSel.start.nIndex) || ( (aStartSel.start.nIndex == (aEndSel.start.nIndex - 1)) && (nLen > 1) ) )
465
0
                            {
466
0
                                for( sal_Int32 i = 0; i < nLen; i++ )
467
0
                                {
468
0
                                    if( ndbg < (nTextLen+2) )
469
0
                                    {
470
0
                                        *pPos++ = aStartSel.start.nIndex;
471
0
                                        *pPara++ = aStartSel.start.nPara;
472
473
0
                                        ndbg += 1;
474
0
                                    }
475
0
                                    else
476
0
                                    {
477
0
                                        OSL_FAIL( "array overflow while searching" );
478
0
                                    }
479
0
                                }
480
481
0
                                nLastPos = aStartSel.start.nIndex;
482
0
                            }
483
                            // normal case
484
0
                            else
485
0
                            {
486
0
                                for( sal_Int32 i = 0; i < nLen; i++ )
487
0
                                {
488
0
                                    if( ndbg < (nTextLen+2) )
489
0
                                    {
490
0
                                        *pPos++ = aStartSel.start.nIndex++;
491
0
                                        *pPara++ = aStartSel.start.nPara;
492
493
0
                                        ndbg += 1;
494
0
                                    }
495
0
                                    else
496
0
                                    {
497
0
                                        OSL_FAIL( "array overflow while searching" );
498
0
                                    }
499
0
                                }
500
501
0
                                nLastPos = aStartSel.start.nIndex - 1;
502
0
                                DBG_ASSERT( aEndSel.start.nIndex == aStartSel.start.nIndex, "Search is not working" );
503
0
                            }
504
0
                            nLastPara = aStartSel.start.nPara;
505
0
                        }
506
0
                    }
507
0
                }
508
0
            }
509
510
0
            if( ndbg < (nTextLen+2) )
511
0
            {
512
0
                *pPos++ = nLastPos + 1;
513
0
                *pPara++ = nLastPara;
514
0
            }
515
0
            else
516
0
            {
517
0
                OSL_FAIL( "array overflow while searching" );
518
0
            }
519
0
        }
520
0
    }
521
522
0
    ESelection aSel;
523
524
0
    if( xText.is() )
525
0
        aSel = GetSelection( xText );
526
527
0
    sal_Int32 nStartPos;
528
0
    sal_Int32 nEndPos   = 0;
529
0
    for( nStartPos = 0; nStartPos < nTextLen; nStartPos++ )
530
0
    {
531
0
        if( pConvertPara[nStartPos] == aSel.start.nPara && pConvertPos[nStartPos] == aSel.start.nIndex )
532
0
            break;
533
0
    }
534
535
0
    if( !Search( aText, nStartPos, nEndPos, pDescr ) )
536
0
        return nullptr;
537
538
0
    if( nStartPos > nTextLen || nEndPos > nTextLen )
539
0
    {
540
0
        OSL_FAIL("Array overflow while searching!");
541
0
        return nullptr;
542
0
    }
543
544
0
    ESelection aSelection( pConvertPara[nStartPos], pConvertPos[nStartPos],
545
0
                     pConvertPara[nEndPos], pConvertPos[nEndPos] );
546
547
0
    SvxUnoTextBase* pParent = comphelper::getFromUnoTunnel<SvxUnoTextBase>( xParent );
548
0
    if(!pParent)
549
0
        return nullptr;
550
551
0
    rtl::Reference<SvxUnoTextRange> pRange = new SvxUnoTextRange( *pParent );
552
0
    pRange->SetSelection(aSelection);
553
554
0
    return pRange;
555
0
}
556
557
bool SdUnoSearchReplaceShape::Search( const OUString& rText, sal_Int32& nStartPos, sal_Int32& nEndPos, SdUnoSearchReplaceDescriptor* pDescr ) noexcept
558
0
{
559
0
    OUString aSearchStr( pDescr->getSearchString() );
560
0
    OUString aText( rText );
561
562
0
    if( !pDescr->IsCaseSensitive() )
563
0
    {
564
0
        aText = aText.toAsciiLowerCase();
565
0
        aSearchStr = aSearchStr.toAsciiLowerCase();
566
0
    }
567
568
0
    sal_Int32 nFound = aText.indexOf( aSearchStr, nStartPos );
569
0
    if( nFound != -1 )
570
0
    {
571
0
        nStartPos = nFound;
572
0
        nEndPos   = nFound + aSearchStr.getLength();
573
574
0
        if(pDescr->IsWords())
575
0
        {
576
0
            if( (nStartPos > 0 && aText[nStartPos-1] > ' ') ||
577
0
                (nEndPos < aText.getLength() && aText[nEndPos] > ' ') )
578
0
            {
579
0
                nStartPos++;
580
0
                return Search( aText, nStartPos, nEndPos, pDescr );
581
0
            }
582
0
        }
583
584
0
        return true;
585
0
    }
586
0
    else
587
0
        return false;
588
0
}
589
590
ESelection SdUnoSearchReplaceShape::GetSelection( const uno::Reference< text::XTextRange >&  xTextRange ) noexcept
591
0
{
592
0
    ESelection aSel;
593
0
    SvxUnoTextRangeBase* pRange = comphelper::getFromUnoTunnel<SvxUnoTextRangeBase>( xTextRange );
594
595
0
    if(pRange)
596
0
        aSel = pRange->GetSelection();
597
598
0
    return aSel;
599
0
}
600
601
uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetShape( const uno::Reference< text::XTextRange >&  xTextRange ) noexcept
602
0
{
603
0
    uno::Reference< drawing::XShape >  xShape;
604
605
0
    if(xTextRange.is())
606
0
    {
607
0
        uno::Reference< text::XText >  xText( xTextRange->getText() );
608
609
0
        if(xText.is())
610
0
        {
611
0
            do
612
0
            {
613
0
                xShape.set( xText, uno::UNO_QUERY );
614
0
                if(!xShape.is())
615
0
                {
616
0
                    uno::Reference< text::XText > xParent( xText->getText() );
617
0
                    if(!xParent.is() || xText.get() == xParent.get())
618
0
                        return xShape;
619
620
0
                    xText = std::move(xParent);
621
0
                }
622
0
            } while( !xShape.is() );
623
0
        }
624
0
    }
625
626
0
    return xShape;
627
0
}
628
629
/* ================================================================= */
630
/** this class holds the parameters and status of a search or replace
631
    operation performed by class SdUnoSearchReplaceShape
632
  */
633
634
SdUnoSearchReplaceDescriptor::SdUnoSearchReplaceDescriptor()
635
0
{
636
0
    mpPropSet.reset( new SvxItemPropertySet(ImplGetSearchPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool()) );
637
638
0
    mbBackwards = false;
639
0
    mbCaseSensitive = false;
640
0
    mbWords = false;
641
0
}
642
643
SdUnoSearchReplaceDescriptor::~SdUnoSearchReplaceDescriptor() noexcept
644
0
{
645
0
}
646
647
// XSearchDescriptor
648
OUString SAL_CALL SdUnoSearchReplaceDescriptor::getSearchString()
649
0
{
650
0
    return maSearchStr;
651
0
}
652
653
void SAL_CALL SdUnoSearchReplaceDescriptor::setSearchString( const OUString& aString )
654
0
{
655
0
    maSearchStr = aString;
656
0
}
657
658
// XReplaceDescriptor
659
OUString SAL_CALL SdUnoSearchReplaceDescriptor::getReplaceString()
660
0
{
661
0
    return maReplaceStr;
662
0
}
663
664
void SAL_CALL SdUnoSearchReplaceDescriptor::setReplaceString( const OUString& aReplaceString )
665
0
{
666
0
    maReplaceStr = aReplaceString;
667
0
}
668
669
// XPropertySet
670
uno::Reference< css::beans::XPropertySetInfo > SAL_CALL SdUnoSearchReplaceDescriptor::getPropertySetInfo()
671
0
{
672
0
    SolarMutexGuard aGuard;
673
0
    return mpPropSet->getPropertySetInfo();
674
0
}
675
676
void SAL_CALL SdUnoSearchReplaceDescriptor::setPropertyValue( const OUString& aPropertyName, const css::uno::Any& aValue )
677
0
{
678
0
    SolarMutexGuard aGuard;
679
680
0
    const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
681
682
0
    bool bOk = false;
683
684
0
    switch( pEntry ? pEntry->nWID : -1 )
685
0
    {
686
0
    case WID_SEARCH_BACKWARDS:
687
0
        bOk = (aValue >>= mbBackwards);
688
0
        break;
689
0
    case WID_SEARCH_CASE:
690
0
        bOk = (aValue >>= mbCaseSensitive);
691
0
        break;
692
0
    case WID_SEARCH_WORDS:
693
0
        bOk = (aValue >>= mbWords);
694
0
        break;
695
0
    default:
696
0
        throw beans::UnknownPropertyException( aPropertyName, static_cast<cppu::OWeakObject*>(this));
697
0
    }
698
699
0
    if( !bOk )
700
0
        throw lang::IllegalArgumentException();
701
0
}
702
703
uno::Any SAL_CALL SdUnoSearchReplaceDescriptor::getPropertyValue( const OUString& PropertyName )
704
0
{
705
0
    SolarMutexGuard aGuard;
706
707
0
    uno::Any aAny;
708
709
0
    const SfxItemPropertyMapEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName);
710
711
0
    switch( pEntry ? pEntry->nWID : -1 )
712
0
    {
713
0
    case WID_SEARCH_BACKWARDS:
714
0
        aAny <<= mbBackwards;
715
0
        break;
716
0
    case WID_SEARCH_CASE:
717
0
        aAny <<= mbCaseSensitive;
718
0
        break;
719
0
    case WID_SEARCH_WORDS:
720
0
        aAny <<= mbWords;
721
0
        break;
722
0
    default:
723
0
        throw beans::UnknownPropertyException( PropertyName, static_cast<cppu::OWeakObject*>(this));
724
0
    }
725
726
0
    return aAny;
727
0
}
728
729
0
void SAL_CALL SdUnoSearchReplaceDescriptor::addPropertyChangeListener( const OUString& , const css::uno::Reference< css::beans::XPropertyChangeListener >&  ) {}
730
0
void SAL_CALL SdUnoSearchReplaceDescriptor::removePropertyChangeListener( const OUString& , const css::uno::Reference< css::beans::XPropertyChangeListener >&  ) {}
731
0
void SAL_CALL SdUnoSearchReplaceDescriptor::addVetoableChangeListener( const OUString& , const css::uno::Reference< css::beans::XVetoableChangeListener >&  ) {}
732
0
void SAL_CALL SdUnoSearchReplaceDescriptor::removeVetoableChangeListener( const OUString& , const css::uno::Reference< css::beans::XVetoableChangeListener >&  ) {}
733
734
/* ================================================================= */
735
736
SdUnoFindAllAccess::SdUnoFindAllAccess( uno::Sequence< uno::Reference< uno::XInterface >  > const & rSequence ) noexcept
737
0
:maSequence( rSequence )
738
0
{
739
0
}
740
741
SdUnoFindAllAccess::~SdUnoFindAllAccess() noexcept
742
0
{
743
0
}
744
745
// XElementAccess
746
uno::Type SAL_CALL SdUnoFindAllAccess::getElementType()
747
0
{
748
0
    return cppu::UnoType<text::XTextRange>::get();
749
0
}
750
751
sal_Bool SAL_CALL SdUnoFindAllAccess::hasElements()
752
0
{
753
0
    return maSequence.hasElements();
754
0
}
755
756
// XIndexAccess
757
sal_Int32 SAL_CALL SdUnoFindAllAccess::getCount()
758
0
{
759
0
    return maSequence.getLength();
760
0
}
761
762
uno::Any SAL_CALL SdUnoFindAllAccess::getByIndex( sal_Int32 Index )
763
0
{
764
0
    if( Index < 0 || Index >= getCount() )
765
0
        throw lang::IndexOutOfBoundsException();
766
767
0
    uno::Any aAny;
768
0
    aAny <<= maSequence[Index];
769
0
    return aAny;
770
0
}
771
772
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */