xref: /AOO41X/main/sd/source/ui/unoidl/unosrch.cxx (revision 24c56ab9f1bd1305754aa2f564704f38ff57627e)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sd.hxx"
26 #include <vcl/svapp.hxx>
27 #include <vos/mutex.hxx>
28 
29 #include <svx/unoshape.hxx>
30 #include <svx/svdpool.hxx>
31 #include <svx/unoprov.hxx>
32 #include <editeng/unotext.hxx>
33 
34 #include <comphelper/extract.hxx>
35 #include <rtl/uuid.h>
36 #include <rtl/memory.h>
37 
38 #include "unohelp.hxx"
39 #include "unoprnms.hxx"
40 #include "unosrch.hxx"
41 
42 using namespace ::vos;
43 using namespace ::rtl;
44 using namespace ::com::sun::star;
45 
46 #define WID_SEARCH_BACKWARDS    0
47 #define WID_SEARCH_CASE         1
48 #define WID_SEARCH_WORDS        2
49 
ImplGetSearchPropertyMap()50 const SfxItemPropertyMapEntry* ImplGetSearchPropertyMap()
51 {
52     static const SfxItemPropertyMapEntry aSearchPropertyMap_Impl[] =
53     {
54         { MAP_CHAR_LEN(UNO_NAME_SEARCH_BACKWARDS),  WID_SEARCH_BACKWARDS,   &::getBooleanCppuType(),    0,  0 },
55         { MAP_CHAR_LEN(UNO_NAME_SEARCH_CASE),       WID_SEARCH_CASE,        &::getBooleanCppuType(),    0,  0 },
56         { MAP_CHAR_LEN(UNO_NAME_SEARCH_WORDS),      WID_SEARCH_WORDS,       &::getBooleanCppuType(),    0,  0 },
57         { 0,0,0,0,0,0}
58     };
59 
60     return aSearchPropertyMap_Impl;
61 }
62 
63 class SearchContext_impl
64 {
65     uno::Reference< drawing::XShapes > mxShapes;
66     sal_Int32 mnIndex;
67     SearchContext_impl* mpParent;
68 
69 public:
SearchContext_impl(uno::Reference<drawing::XShapes> xShapes,SearchContext_impl * pParent=NULL)70     SearchContext_impl( uno::Reference< drawing::XShapes >  xShapes, SearchContext_impl* pParent = NULL )
71         : mxShapes( xShapes ), mnIndex( -1 ), mpParent( pParent ) {}
72 
73 
firstShape()74     uno::Reference< drawing::XShape > firstShape()
75     {
76         mnIndex = -1;
77         return nextShape();
78     }
79 
nextShape()80     uno::Reference< drawing::XShape > nextShape()
81     {
82         uno::Reference< drawing::XShape >  xShape;
83         mnIndex++;
84         if( mxShapes.is() && mxShapes->getCount() > mnIndex )
85         {
86             mxShapes->getByIndex( mnIndex ) >>= xShape;
87         }
88         return xShape;
89     }
90 
getParent() const91     SearchContext_impl* getParent() const { return mpParent; }
92 };
93 
94 /* ================================================================= */
95 /** this class implements a search or replace operation on a given
96     page or a given sdrobj
97   */
98 
SdUnoSearchReplaceShape(drawing::XDrawPage * pPage)99 SdUnoSearchReplaceShape::SdUnoSearchReplaceShape( drawing::XDrawPage* pPage ) throw()
100 {
101     mpPage = pPage;
102 }
103 
~SdUnoSearchReplaceShape()104 SdUnoSearchReplaceShape::~SdUnoSearchReplaceShape() throw()
105 {
106 }
107 
108 // util::XReplaceable
createReplaceDescriptor()109 uno::Reference< util::XReplaceDescriptor > SAL_CALL SdUnoSearchReplaceShape::createReplaceDescriptor()
110     throw( uno::RuntimeException )
111 {
112     return new SdUnoSearchReplaceDescriptor(sal_True);
113 }
114 
replaceAll(const uno::Reference<util::XSearchDescriptor> & xDesc)115 sal_Int32 SAL_CALL SdUnoSearchReplaceShape::replaceAll( const uno::Reference< util::XSearchDescriptor >& xDesc )
116     throw( uno::RuntimeException )
117 {
118     SdUnoSearchReplaceDescriptor* pDescr = SdUnoSearchReplaceDescriptor::getImplementation( xDesc );
119     if( pDescr == NULL )
120         return 0;
121 
122     sal_Int32 nFound    = 0;
123 
124     uno::Reference< drawing::XShapes >  xShapes;
125     uno::Reference< drawing::XShape >  xShape;
126 
127     SearchContext_impl* pContext = NULL;
128     if(mpPage)
129     {
130         uno::Reference< drawing::XDrawPage > xPage( mpPage );
131 
132         xPage->queryInterface( ITYPE( drawing::XShapes ) ) >>= xShapes;
133 
134         if( xShapes.is() && (xShapes->getCount() > 0) )
135         {
136             pContext = new SearchContext_impl( xShapes );
137             xShape = pContext->firstShape();
138         }
139         else
140         {
141             xShapes = NULL;
142         }
143     }
144     else
145     {
146         xShape = mpShape;
147     }
148 
149     while( xShape.is() )
150     {
151         // replace in xShape
152         uno::Reference< text::XText >  xText(xShape, uno::UNO_QUERY);
153         uno::Reference< text::XTextRange >  xRange(xText, uno::UNO_QUERY);
154         uno::Reference< text::XTextRange >  xFound;
155 
156         while( xRange.is() )
157         {
158             xFound = Search( xRange, pDescr );
159             if( !xFound.is() )
160                 break;
161 
162             xFound->setString( pDescr->getReplaceString() );
163             xRange = xFound->getEnd();
164             nFound++;
165         }
166         // done with xShape -> get next shape
167 
168         // test if its a group
169         uno::Reference< drawing::XShapes > xGroupShape( xShape, uno::UNO_QUERY );
170         if( xGroupShape.is() && ( xGroupShape->getCount() > 0 ) )
171         {
172             pContext = new SearchContext_impl( xGroupShape, pContext );
173             xShape = pContext->firstShape();
174         }
175         else
176         {
177             if( pContext )
178                 xShape = pContext->nextShape();
179             else
180                 xShape = NULL;
181         }
182 
183         // test parent contexts for next shape if none
184         // is found in the current context
185         while( pContext && !xShape.is() )
186         {
187             if( pContext->getParent() )
188             {
189                 SearchContext_impl* pOldContext = pContext;
190                 pContext = pContext->getParent();
191                 delete pOldContext;
192                 xShape = pContext->nextShape();
193             }
194             else
195             {
196                 delete pContext;
197                 pContext = NULL;
198                 xShape = NULL;
199             }
200         }
201     }
202 
203     return nFound;
204 }
205 
206 // XSearchable
createSearchDescriptor()207 uno::Reference< ::com::sun::star::util::XSearchDescriptor > SAL_CALL SdUnoSearchReplaceShape::createSearchDescriptor(  )
208     throw(::com::sun::star::uno::RuntimeException)
209 {
210     return new SdUnoSearchReplaceDescriptor(sal_False);
211 }
212 
findAll(const::com::sun::star::uno::Reference<::com::sun::star::util::XSearchDescriptor> & xDesc)213 uno::Reference< ::com::sun::star::container::XIndexAccess > SAL_CALL SdUnoSearchReplaceShape::findAll( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XSearchDescriptor >& xDesc )
214     throw(::com::sun::star::uno::RuntimeException)
215 {
216     SdUnoSearchReplaceDescriptor* pDescr = SdUnoSearchReplaceDescriptor::getImplementation( xDesc );
217     if( pDescr == NULL )
218         return uno::Reference< container::XIndexAccess > ();
219 
220 
221     sal_Int32 nSequence = 32;
222     sal_Int32 nFound    = 0;
223 
224     uno::Sequence < uno::Reference< uno::XInterface >  > aSeq( nSequence );
225 
226     uno::Reference< uno::XInterface > * pArray = aSeq.getArray();
227 
228     uno::Reference< drawing::XShapes >  xShapes;
229     uno::Reference< drawing::XShape >  xShape;
230 
231     SearchContext_impl* pContext = NULL;
232     if(mpPage)
233     {
234         uno::Reference< drawing::XDrawPage >  xPage( mpPage );
235         xPage->queryInterface( ITYPE( drawing::XShapes ) ) >>= xShapes;
236 
237         if( xShapes.is() && xShapes->getCount() > 0 )
238         {
239             pContext = new SearchContext_impl( xShapes );
240             xShape = pContext->firstShape();
241         }
242         else
243         {
244             xShapes = NULL;
245         }
246     }
247     else
248     {
249         xShape = mpShape;
250     }
251     while( xShape.is() )
252     {
253         // find in xShape
254         uno::Reference< text::XText >  xText(xShape, uno::UNO_QUERY);
255         uno::Reference< text::XTextRange >  xRange(xText, uno::UNO_QUERY);
256         uno::Reference< text::XTextRange >  xFound;
257 
258         while( xRange.is() )
259         {
260             xFound = Search( xRange, pDescr );
261             if( !xFound.is() )
262                 break;
263 
264             if( nFound >= nSequence )
265             {
266                 nSequence += 32;
267                 aSeq.realloc( nSequence );
268                 pArray = aSeq.getArray();
269             }
270 
271             pArray[nFound++] = xFound;
272 
273             xRange = xFound->getEnd();
274         }
275         // done with shape -> get next shape
276 
277         // test if its a group
278         uno::Reference< drawing::XShapes >  xGroupShape;
279         uno::Any aAny( xShape->queryInterface( ITYPE( drawing::XShapes )));
280 
281         if( (aAny >>= xGroupShape ) && xGroupShape->getCount() > 0 )
282         {
283             pContext = new SearchContext_impl( xGroupShape, pContext );
284             xShape = pContext->firstShape();
285         }
286         else
287         {
288             if( pContext )
289                 xShape = pContext->nextShape();
290             else
291                 xShape = NULL;
292         }
293 
294         // test parent contexts for next shape if none
295         // is found in the current context
296         while( pContext && !xShape.is() )
297         {
298             if( pContext->getParent() )
299             {
300                 SearchContext_impl* pOldContext = pContext;
301                 pContext = pContext->getParent();
302                 delete pOldContext;
303                 xShape = pContext->nextShape();
304             }
305             else
306             {
307                 delete pContext;
308                 pContext = NULL;
309                 xShape = NULL;
310             }
311         }
312     }
313 
314     if( nFound != nSequence )
315         aSeq.realloc( nFound );
316 
317     return (container::XIndexAccess*)new SdUnoFindAllAccess( aSeq );
318 }
319 
findFirst(const::com::sun::star::uno::Reference<::com::sun::star::util::XSearchDescriptor> & xDesc)320 uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SdUnoSearchReplaceShape::findFirst( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XSearchDescriptor >& xDesc )
321     throw(::com::sun::star::uno::RuntimeException)
322 {
323     uno::Reference< text::XTextRange > xRange( GetCurrentShape(), uno::UNO_QUERY );
324     if( xRange.is() )
325         return findNext( xRange, xDesc );
326 
327     return uno::Reference< uno::XInterface > ();
328 }
329 
GetCurrentShape() const330 uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetCurrentShape() const throw()
331 {
332     uno::Reference< drawing::XShape >  xShape;
333 
334     if( mpPage )
335     {
336         uno::Reference< drawing::XDrawPage >  xPage( mpPage );
337         uno::Reference< container::XIndexAccess >  xShapes( xPage, uno::UNO_QUERY );
338         if( xShapes.is() )
339         {
340             if(xShapes->getCount() > 0)
341             {
342                 xShapes->getByIndex(0) >>= xShape;
343             }
344         }
345     }
346     else if( mpShape )
347     {
348         xShape = mpShape;
349     }
350 
351     return xShape;
352 
353 }
354 
findNext(const::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> & xStartAt,const::com::sun::star::uno::Reference<::com::sun::star::util::XSearchDescriptor> & xDesc)355 uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL SdUnoSearchReplaceShape::findNext( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xStartAt, const ::com::sun::star::uno::Reference< ::com::sun::star::util::XSearchDescriptor >& xDesc )
356     throw(::com::sun::star::uno::RuntimeException)
357 {
358     SdUnoSearchReplaceDescriptor* pDescr = SdUnoSearchReplaceDescriptor::getImplementation( xDesc );
359 
360     uno::Reference< uno::XInterface > xFound;
361 
362     uno::Reference< text::XTextRange > xRange( xStartAt, uno::UNO_QUERY );
363     if(pDescr && xRange.is() )
364     {
365 
366         uno::Reference< text::XTextRange > xCurrentRange( xStartAt, uno::UNO_QUERY );
367 
368         uno::Reference< drawing::XShape > xCurrentShape( GetShape( xCurrentRange ) );
369 
370         while(!xFound.is() && xRange.is())
371         {
372             xFound = Search( xRange, pDescr );
373             if(!xFound.is())
374             {
375                 // we need a new starting range now
376                 xRange = NULL;
377 
378                 if(mpPage)
379                 {
380                     uno::Reference< drawing::XDrawPage >  xPage( mpPage );
381 
382                     // we do a page wide search, so skip to the next shape here
383                     uno::Reference< container::XIndexAccess > xShapes( xPage, uno::UNO_QUERY );
384 
385                     // get next shape on our page
386                     if( xShapes.is() )
387                     {
388                         uno::Reference< drawing::XShape > xFound2( GetNextShape( xShapes, xCurrentShape ) );
389                         if( xFound2.is() && (xFound2.get() != xCurrentShape.get()) )
390                             xCurrentShape = xFound2;
391                         else
392                             xCurrentShape = NULL;
393 
394                         xCurrentShape->queryInterface( ITYPE( text::XTextRange ) ) >>= xRange;
395                         if(!(xCurrentShape.is() && (xRange.is())))
396                             xRange = NULL;
397                     }
398                 }
399                 else
400                 {
401                     // we search only in this shape, so end search if we have
402                     // not found anything
403                 }
404             }
405         }
406     }
407     return xFound;
408 }
409 
410 /** this method returns the shape that follows xCurrentShape in the shape collection xShapes.
411     It steps recursive into groupshapes and returns the xCurrentShape if it is the last
412     shape in this collection */
GetNextShape(uno::Reference<container::XIndexAccess> xShapes,uno::Reference<drawing::XShape> xCurrentShape)413 uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetNextShape( uno::Reference< container::XIndexAccess >  xShapes, uno::Reference< drawing::XShape >  xCurrentShape ) throw()
414 {
415     uno::Reference< drawing::XShape >  xFound;
416     uno::Any aAny;
417 
418     if(xShapes.is() && xCurrentShape.is())
419     {
420         const sal_Int32 nCount = xShapes->getCount();
421         for( sal_Int32 i = 0; i < nCount; i++ )
422         {
423             uno::Reference< drawing::XShape > xSearchShape;
424             xShapes->getByIndex(i) >>= xSearchShape;
425 
426             if( xSearchShape.is() )
427             {
428                 uno::Reference< container::XIndexAccess > xGroup( xSearchShape, uno::UNO_QUERY );
429 
430                 if( xCurrentShape.get() == xSearchShape.get() )
431                 {
432                     if( xGroup.is() && xGroup->getCount() > 0 )
433                     {
434                         xGroup->getByIndex( 0 ) >>= xFound;
435                     }
436                     else
437                     {
438                         i++;
439                         if( i < nCount )
440                             xShapes->getByIndex( i ) >>= xFound;
441                         else
442                             xFound = xCurrentShape;
443                     }
444 
445                     break;
446                 }
447                 else if( xGroup.is() )
448                 {
449                     xFound = GetNextShape( xGroup, xCurrentShape );
450                     if( xFound.is() )
451                     {
452                         if( xFound.get() == xCurrentShape.get() )
453                         {
454                             // the current shape was found at the end of the group
455                             i++;
456                             if( i < nCount )
457                             {
458                                 xShapes->getByIndex(i) >>= xFound;
459                             }
460                         }
461                         break;
462                     }
463                 }
464             }
465         }
466     }
467 
468     return xFound;
469 }
470 
Search(uno::Reference<text::XTextRange> xText,SdUnoSearchReplaceDescriptor * pDescr)471 uno::Reference< text::XTextRange >  SdUnoSearchReplaceShape::Search( uno::Reference< text::XTextRange >  xText, SdUnoSearchReplaceDescriptor* pDescr ) throw()
472 {
473     if(!xText.is())
474         return uno::Reference< text::XTextRange > ();
475 
476     uno::Reference< text::XText > xParent( xText->getText() );
477 
478     if( !xParent.is() )
479     {
480         uno::Any aAny( xText->queryInterface( ITYPE( text::XText )) );
481         aAny >>= xParent;
482     }
483 
484     const OUString aText( xParent->getString() );
485 
486     const sal_Int32 nTextLen = aText.getLength();
487 
488     sal_Int32* pConvertPos = new sal_Int32[nTextLen+2];
489     sal_Int32* pConvertPara = new sal_Int32[nTextLen+2];
490 
491     int ndbg = 0;
492     const sal_Unicode* pText = aText.getStr();
493 
494     sal_Int32* pPos = pConvertPos;
495     sal_Int32* pPara = pConvertPara;
496 
497     sal_Int32 nLastPos = 0, nLastPara = 0;
498 
499     uno::Reference< container::XEnumerationAccess > xEnumAccess( xParent, uno::UNO_QUERY );
500 
501     // first we fill the arrys with the position and paragraph for every character
502     // inside the text
503     if( xEnumAccess.is() )
504     {
505         uno::Reference< container::XEnumeration >  xParaEnum( xEnumAccess->createEnumeration() );
506 
507         while(xParaEnum->hasMoreElements())
508         {
509             uno::Reference< text::XTextContent >  xParagraph( xParaEnum->nextElement(), uno::UNO_QUERY );
510             if( xParagraph.is() )
511                 xEnumAccess.query( xParagraph );
512             else
513                 xEnumAccess.clear();
514 
515             if( xEnumAccess.is() )
516             {
517                  uno::Reference< container::XEnumeration >  xPortionEnum( xEnumAccess->createEnumeration() );
518                  if( xPortionEnum.is() )
519                  {
520                     while(xPortionEnum->hasMoreElements())
521                     {
522                         uno::Reference< text::XTextRange >  xPortion( xPortionEnum->nextElement(), uno::UNO_QUERY );
523                         if( xPortion.is() )
524                         {
525                             const OUString aPortion( xPortion->getString() );
526                             const sal_Int32 nLen = aPortion.getLength();
527 
528                             ESelection aStartSel( GetSelection( xPortion->getStart() ) );
529                             ESelection aEndSel( GetSelection( xPortion->getEnd() ) );
530 
531                             // special case for empty portions with content or length one portions with content (fields)
532                             if( (aStartSel.nStartPos == aEndSel.nStartPos) || ( (aStartSel.nStartPos == (aEndSel.nStartPos - 1)) && (nLen > 1) ) )
533                             {
534                                 for( sal_Int32 i = 0; i < nLen; i++ )
535                                 {
536                                     if( ndbg < (nTextLen+2) )
537                                     {
538                                         *pPos++ = aStartSel.nStartPos;
539                                         *pPara++ = aStartSel.nStartPara;
540 
541                                         ndbg += 1;
542                                         pText++;
543                                     }
544                                     else
545                                     {
546                                         DBG_ERROR( "array overflow while searching" );
547                                     }
548                                 }
549 
550                                 nLastPos = aStartSel.nStartPos;
551                             }
552                             // normal case
553                             else
554                             {
555                                 for( sal_Int32 i = 0; i < nLen; i++ )
556                                 {
557                                     if( ndbg < (nTextLen+2) )
558                                     {
559                                         *pPos++ = aStartSel.nStartPos++;
560                                         *pPara++ = aStartSel.nStartPara;
561 
562                                         ndbg += 1;
563                                         pText++;
564                                     }
565                                     else
566                                     {
567                                         DBG_ERROR( "array overflow while searching" );
568                                     }
569                                 }
570 
571                                 nLastPos = aStartSel.nStartPos - 1;
572                                 DBG_ASSERT( aEndSel.nStartPos == aStartSel.nStartPos, "Search is not working" );
573                             }
574                             nLastPara = aStartSel.nStartPara;
575                         }
576                     }
577                 }
578             }
579 
580             if( ndbg < (nTextLen+2) )
581             {
582                 *pPos++ = nLastPos + 1;
583                 *pPara++ = nLastPara;
584 
585                 ndbg += 1;
586                 pText++;
587             }
588             else
589             {
590                 DBG_ERROR( "array overflow while searching" );
591             }
592         }
593     }
594 
595     uno::Reference< text::XText >  xFound;
596     ESelection aSel;
597 
598     uno::Reference< text::XTextRange > xRangeRef( xText, uno::UNO_QUERY );
599     if( xRangeRef.is() )
600         aSel = GetSelection( xRangeRef );
601 
602     sal_Int32 nStartPos;
603     sal_Int32 nEndPos   = 0;
604     for( nStartPos = 0; nStartPos < nTextLen; nStartPos++ )
605     {
606         if( pConvertPara[nStartPos] == aSel.nStartPara && pConvertPos[nStartPos] == aSel.nStartPos )
607             break;
608     }
609 
610     if( Search( aText, nStartPos, nEndPos, pDescr ) )
611     {
612         if( nStartPos <= nTextLen && nEndPos <= nTextLen )
613         {
614             ESelection aSelection( (sal_uInt16)pConvertPara[nStartPos], (sal_uInt16)pConvertPos[nStartPos],
615                              (sal_uInt16)pConvertPara[nEndPos], (sal_uInt16)pConvertPos[nEndPos] );
616             SvxUnoTextRange *pRange;
617 
618             SvxUnoTextBase* pParent = SvxUnoTextBase::getImplementation( xParent );
619 
620             if(pParent)
621             {
622                 pRange = new SvxUnoTextRange( *pParent );
623                 xFound = (text::XText*)pRange;
624                 pRange->SetSelection(aSelection);
625 
626 //              pDescr->SetStartPos( nEndPos );
627             }
628         }
629         else
630         {
631             DBG_ERROR("Array overflow while searching!");
632         }
633     }
634 
635     delete[] pConvertPos;
636     delete[] pConvertPara;
637 
638     return uno::Reference< text::XTextRange > ( xFound, uno::UNO_QUERY );
639 }
640 
Search(const OUString & rText,sal_Int32 & nStartPos,sal_Int32 & nEndPos,SdUnoSearchReplaceDescriptor * pDescr)641 sal_Bool SdUnoSearchReplaceShape::Search( const OUString& rText, sal_Int32& nStartPos, sal_Int32& nEndPos, SdUnoSearchReplaceDescriptor* pDescr ) throw()
642 {
643     OUString aSearchStr( pDescr->getSearchString() );
644     OUString aText( rText );
645 
646     if( !pDescr->IsCaseSensitive() )
647     {
648         aText.toAsciiLowerCase();
649         aSearchStr.toAsciiLowerCase();
650     }
651 
652     sal_Int32 nFound = aText.indexOf( aSearchStr, nStartPos );
653     if( nFound != -1 )
654     {
655         nStartPos = nFound;
656         nEndPos   = nFound + aSearchStr.getLength();
657 
658         if(pDescr->IsWords())
659         {
660             if( (nStartPos > 0 && aText.getStr()[nStartPos-1] > ' ') ||
661                 (nEndPos < aText.getLength() && aText.getStr()[nEndPos] > ' ') )
662             {
663                 nStartPos++;
664                 return Search( aText, nStartPos, nEndPos, pDescr );
665             }
666         }
667 
668         return sal_True;
669     }
670     else
671         return sal_False;
672 }
673 
GetSelection(uno::Reference<text::XTextRange> xTextRange)674 ESelection SdUnoSearchReplaceShape::GetSelection( uno::Reference< text::XTextRange >  xTextRange ) throw()
675 {
676     ESelection aSel;
677     SvxUnoTextRangeBase* pRange = SvxUnoTextRangeBase::getImplementation( xTextRange );
678 
679     if(pRange)
680         aSel = pRange->GetSelection();
681 
682     return aSel;
683 }
684 
GetShape(uno::Reference<text::XTextRange> xTextRange)685 uno::Reference< drawing::XShape >  SdUnoSearchReplaceShape::GetShape( uno::Reference< text::XTextRange >  xTextRange ) throw()
686 {
687     uno::Reference< drawing::XShape >  xShape;
688 
689     if(xTextRange.is())
690     {
691         uno::Reference< text::XText >  xText( xTextRange->getText() );
692 
693         if(xText.is())
694         {
695             do
696             {
697                 xText->queryInterface( ITYPE( drawing::XShape )) >>= xShape;
698                 if(!xShape.is())
699                 {
700                     uno::Reference< text::XText > xParent( xText->getText() );
701                     if(!xParent.is() || xText.get() == xParent.get())
702                         return xShape;
703 
704                     xText = xParent;
705                 }
706             } while( !xShape.is() );
707         }
708     }
709 
710     return xShape;
711 }
712 
713 /* ================================================================= */
714 /** this class holds the parameters and status of a search or replace
715     operation performed by class SdUnoSearchReplaceShape
716   */
717 
718 UNO3_GETIMPLEMENTATION_IMPL( SdUnoSearchReplaceDescriptor );
719 
SdUnoSearchReplaceDescriptor(sal_Bool bReplace)720 SdUnoSearchReplaceDescriptor::SdUnoSearchReplaceDescriptor( sal_Bool bReplace ) throw()
721 {
722     mpPropSet = new SvxItemPropertySet(ImplGetSearchPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool());
723 
724     mbBackwards = sal_False;
725     mbCaseSensitive = sal_False;
726     mbWords = sal_False;
727 
728     mbReplace = bReplace;
729 }
730 
~SdUnoSearchReplaceDescriptor()731 SdUnoSearchReplaceDescriptor::~SdUnoSearchReplaceDescriptor() throw()
732 {
733     delete mpPropSet;
734 }
735 
736 // XSearchDescriptor
getSearchString()737 OUString SAL_CALL SdUnoSearchReplaceDescriptor::getSearchString()
738     throw(::com::sun::star::uno::RuntimeException)
739 {
740     return maSearchStr;
741 }
742 
setSearchString(const OUString & aString)743 void SAL_CALL SdUnoSearchReplaceDescriptor::setSearchString( const OUString& aString )
744     throw(::com::sun::star::uno::RuntimeException)
745 {
746     maSearchStr = aString;
747 }
748 
749 // XReplaceDescriptor
getReplaceString()750 OUString SAL_CALL SdUnoSearchReplaceDescriptor::getReplaceString()
751     throw(::com::sun::star::uno::RuntimeException)
752 {
753     return maReplaceStr;
754 }
755 
setReplaceString(const::rtl::OUString & aReplaceString)756 void SAL_CALL SdUnoSearchReplaceDescriptor::setReplaceString( const ::rtl::OUString& aReplaceString )
757     throw(::com::sun::star::uno::RuntimeException)
758 {
759     maReplaceStr = aReplaceString;
760 }
761 
762 // XPropertySet
getPropertySetInfo()763 uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL SdUnoSearchReplaceDescriptor::getPropertySetInfo()
764     throw(::com::sun::star::uno::RuntimeException)
765 {
766     OGuard aGuard( Application::GetSolarMutex() );
767     return mpPropSet->getPropertySetInfo();
768 }
769 
setPropertyValue(const::rtl::OUString & aPropertyName,const::com::sun::star::uno::Any & aValue)770 void SAL_CALL SdUnoSearchReplaceDescriptor::setPropertyValue( const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Any& aValue )
771     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
772 {
773     OGuard aGuard( Application::GetSolarMutex() );
774 
775     const SfxItemPropertySimpleEntry* pEntry = mpPropSet->getPropertyMapEntry(aPropertyName);
776 
777     sal_Bool bOk = sal_False;
778 
779     switch( pEntry ? pEntry->nWID : -1 )
780     {
781     case WID_SEARCH_BACKWARDS:
782         bOk = (aValue >>= mbBackwards);
783         break;
784     case WID_SEARCH_CASE:
785         bOk = (aValue >>= mbCaseSensitive);
786         break;
787     case WID_SEARCH_WORDS:
788         bOk = (aValue >>= mbWords);
789         break;
790     default:
791         throw beans::UnknownPropertyException();
792     }
793 
794     if( !bOk )
795         throw lang::IllegalArgumentException();
796 }
797 
getPropertyValue(const::rtl::OUString & PropertyName)798 uno::Any SAL_CALL SdUnoSearchReplaceDescriptor::getPropertyValue( const ::rtl::OUString& PropertyName )
799     throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
800 {
801     OGuard aGuard( Application::GetSolarMutex() );
802 
803     uno::Any aAny;
804 
805     const SfxItemPropertySimpleEntry* pEntry = mpPropSet->getPropertyMapEntry(PropertyName);
806 
807     switch( pEntry ? pEntry->nWID : -1 )
808     {
809     case WID_SEARCH_BACKWARDS:
810         aAny <<= (sal_Bool)mbBackwards;
811         break;
812     case WID_SEARCH_CASE:
813         aAny <<= (sal_Bool)mbCaseSensitive;
814         break;
815     case WID_SEARCH_WORDS:
816         aAny <<= (sal_Bool)mbWords;
817         break;
818     default:
819         throw beans::UnknownPropertyException();
820     }
821 
822     return aAny;
823 }
824 
addPropertyChangeListener(const::rtl::OUString &,const::com::sun::star::uno::Reference<::com::sun::star::beans::XPropertyChangeListener> &)825 void SAL_CALL SdUnoSearchReplaceDescriptor::addPropertyChangeListener( const ::rtl::OUString& , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >&  ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) {}
removePropertyChangeListener(const::rtl::OUString &,const::com::sun::star::uno::Reference<::com::sun::star::beans::XPropertyChangeListener> &)826 void SAL_CALL SdUnoSearchReplaceDescriptor::removePropertyChangeListener( const ::rtl::OUString& , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >&  ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) {}
addVetoableChangeListener(const::rtl::OUString &,const::com::sun::star::uno::Reference<::com::sun::star::beans::XVetoableChangeListener> &)827 void SAL_CALL SdUnoSearchReplaceDescriptor::addVetoableChangeListener( const ::rtl::OUString& , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >&  ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) {}
removeVetoableChangeListener(const::rtl::OUString &,const::com::sun::star::uno::Reference<::com::sun::star::beans::XVetoableChangeListener> &)828 void SAL_CALL SdUnoSearchReplaceDescriptor::removeVetoableChangeListener( const ::rtl::OUString& , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >&  ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) {}
829 
830 
831 /* ================================================================= */
832 
SdUnoFindAllAccess(uno::Sequence<uno::Reference<uno::XInterface>> & rSequence)833 SdUnoFindAllAccess::SdUnoFindAllAccess( uno::Sequence< uno::Reference< uno::XInterface >  >& rSequence ) throw()
834 :maSequence( rSequence )
835 {
836 }
837 
~SdUnoFindAllAccess()838 SdUnoFindAllAccess::~SdUnoFindAllAccess() throw()
839 {
840 }
841 
842 // XElementAccess
getElementType()843 uno::Type SAL_CALL SdUnoFindAllAccess::getElementType()
844     throw(::com::sun::star::uno::RuntimeException)
845 {
846     return ITYPE( text::XTextRange );
847 }
848 
hasElements()849 sal_Bool SAL_CALL SdUnoFindAllAccess::hasElements()
850     throw(::com::sun::star::uno::RuntimeException)
851 {
852     return maSequence.getLength() > 0;
853 }
854 
855 // XIndexAccess
getCount()856 sal_Int32 SAL_CALL SdUnoFindAllAccess::getCount()
857     throw(::com::sun::star::uno::RuntimeException)
858 {
859     return maSequence.getLength();
860 }
861 
getByIndex(sal_Int32 Index)862 uno::Any SAL_CALL SdUnoFindAllAccess::getByIndex( sal_Int32 Index )
863     throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
864 {
865     uno::Any aAny;
866 
867     if( Index < 0 || Index >= getCount() )
868         throw lang::IndexOutOfBoundsException();
869 
870     const uno::Reference< uno::XInterface >  *pRefs = maSequence.getConstArray();
871     if(pRefs)
872         aAny <<= pRefs[ Index ];
873     return aAny;
874 }
875 
876