xref: /trunk/main/sd/source/ui/unoidl/unosrch.cxx (revision d2d30fce)
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_uInt32)pConvertPara[nStartPos], (sal_uInt16)pConvertPos[nStartPos],
615 							 (sal_uInt32)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