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