xref: /aoo41x/main/sw/source/ui/vba/vbafind.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 #include "vbafind.hxx"
28 #include <vbahelper/vbahelper.hxx>
29 #include <tools/diagnose_ex.h>
30 #include "vbareplacement.hxx"
31 #include <ooo/vba/word/WdFindWrap.hpp>
32 #include <ooo/vba/word/WdReplace.hpp>
33 #include <com/sun/star/text/XTextRangeCompare.hpp>
34 #include "wordvbahelper.hxx"
35 
36 using namespace ::ooo::vba;
37 using namespace ::com::sun::star;
38 
39 SwVbaFind::SwVbaFind( const uno::Reference< ooo::vba::XHelperInterface >& rParent, const uno::Reference< uno::XComponentContext >& rContext, const uno::Reference< frame::XModel >& xModel, const uno::Reference< text::XTextRange >& xTextRange ) throw ( uno::RuntimeException ) :
40     SwVbaFind_BASE( rParent, rContext ), mxModel( xModel ), mxTextRange( xTextRange ), mbReplace( sal_False ), mnReplaceType( word::WdReplace::wdReplaceOne ), mnWrap( word::WdFindWrap::wdFindStop )
41 {
42     mxReplaceable.set( mxModel, uno::UNO_QUERY_THROW );
43     mxPropertyReplace.set( mxReplaceable->createReplaceDescriptor(), uno::UNO_QUERY_THROW );
44     mxTVC = word::getXTextViewCursor( mxModel );
45     mxSelSupp.set( mxModel->getCurrentController(), uno::UNO_QUERY_THROW );
46 }
47 
48 SwVbaFind::~SwVbaFind()
49 {
50 }
51 
52 sal_Bool SwVbaFind::InRange( const uno::Reference< text::XTextRange >& xCurrentRange ) throw ( uno::RuntimeException )
53 {
54     uno::Reference< text::XTextRangeCompare > xTRC( mxTextRange->getText(), uno::UNO_QUERY_THROW );
55     if( xTRC->compareRegionStarts( mxTextRange, xCurrentRange ) >= 0 && xTRC->compareRegionEnds( mxTextRange, xCurrentRange ) <= 0 )
56         return sal_True;
57     return sal_False;
58 }
59 
60 sal_Bool SwVbaFind::InEqualRange( const uno::Reference< text::XTextRange >& xCurrentRange ) throw ( uno::RuntimeException )
61 {
62     uno::Reference< text::XTextRangeCompare > xTRC( mxTextRange->getText(), uno::UNO_QUERY_THROW );
63     if( xTRC->compareRegionStarts( mxTextRange, xCurrentRange ) == 0 && xTRC->compareRegionEnds( mxTextRange, xCurrentRange ) == 0 )
64         return sal_True;
65     return sal_False;
66 }
67 
68 void SwVbaFind::SetReplaceWith( const rtl::OUString& rText ) throw (uno::RuntimeException)
69 {
70     mxPropertyReplace->setReplaceString( rText );
71     mbReplace = sal_True;
72 }
73 
74 rtl::OUString SwVbaFind::GetReplaceWith() throw (uno::RuntimeException)
75 {
76     return mxPropertyReplace->getReplaceString();
77 }
78 void SwVbaFind::SetReplace( sal_Int32 type )
79 {
80     mnReplaceType = type;
81     mbReplace = sal_True;
82 }
83 #ifdef TOMORROW
84 rtl::OUString SwVbaFind::ReplaceWildcards( const rtl::OUString& /*rText*/ ) throw ( uno::RuntimeException )
85 {
86     // TODO:
87     return rtl::OUString();
88 }
89 #endif
90 uno::Reference< text::XTextRange > SwVbaFind::FindOneElement() throw ( uno::RuntimeException )
91 {
92     uno::Reference< text::XTextRange > xFoundOne;
93     if( mxTVC->getString().getLength() > 0 )
94     {
95         if( getForward() )
96         {
97             xFoundOne.set( mxReplaceable->findNext( mxTextRange->getStart(), uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
98         }
99         else
100         {
101             xFoundOne.set( mxReplaceable->findNext( mxTextRange->getEnd(), uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
102         }
103 
104         if( xFoundOne.is() && InEqualRange( xFoundOne ) )
105         {
106             xFoundOne.set( mxReplaceable->findNext( xFoundOne, uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
107         }
108         else if( xFoundOne.is() && !InRange( xFoundOne ) )
109         {
110             xFoundOne = uno::Reference< text::XTextRange >();
111         }
112     }
113     else
114     {
115         xFoundOne.set( mxReplaceable->findNext( mxTextRange, uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
116     }
117 
118     if( !xFoundOne.is() && ( getWrap() == word::WdFindWrap::wdFindContinue || getWrap() == word::WdFindWrap::wdFindAsk ) )
119     {
120         if( getForward() )
121         {
122             mxTVC->gotoStart(sal_False);
123             xFoundOne.set( mxReplaceable->findNext( mxTextRange->getStart(), uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
124         }
125         else
126         {
127             mxTVC->gotoEnd( sal_False );
128             xFoundOne.set( mxReplaceable->findNext( mxTextRange->getEnd(), uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) ), uno::UNO_QUERY );
129 
130         }
131     }
132     return xFoundOne;
133 }
134 
135 sal_Bool SwVbaFind::SearchReplace() throw (uno::RuntimeException)
136 {
137     sal_Bool result = sal_False;
138 
139     // TODO: map wildcards in area to OOo wildcards
140 
141     if( mbReplace )
142     {
143         switch( mnReplaceType )
144         {
145             case word::WdReplace::wdReplaceNone:
146             {
147                 result = sal_True;
148                 break;
149             }
150             case word::WdReplace::wdReplaceOne:
151             {
152                 uno::Reference< text::XTextRange > xFindOne = FindOneElement();
153                 if( xFindOne.is() )
154                 {
155                     xFindOne->setString( GetReplaceWith() );
156                     result = mxSelSupp->select( uno::makeAny( xFindOne ) );
157                 }
158                 break;
159             }
160             case word::WdReplace::wdReplaceAll:
161             {
162                 uno::Reference< container::XIndexAccess > xIndexAccess = mxReplaceable->findAll( uno::Reference< util::XSearchDescriptor >( mxPropertyReplace, uno::UNO_QUERY_THROW ) );
163                 if( xIndexAccess->getCount() > 0 )
164                 {
165                     for( sal_Int32 i = 0; i < xIndexAccess->getCount(); i++ )
166                     {
167                         uno::Reference< text::XTextRange > xTextRange( xIndexAccess->getByIndex( i ), uno::UNO_QUERY_THROW );
168                         if( mnWrap == word::WdFindWrap::wdFindContinue || mnWrap == word::WdFindWrap::wdFindAsk || InRange( xTextRange ) )
169                         {
170                             xTextRange->setString( GetReplaceWith() );
171                             result = sal_True;
172                         }
173                     }
174                 }
175                 break;
176             }
177             default:
178             {
179                 result = sal_False;
180             }
181         }
182     }
183     else
184     {
185         uno::Reference< text::XTextRange > xFindOne = FindOneElement();
186         if( xFindOne.is() )
187             result = mxSelSupp->select( uno::makeAny( xFindOne ) );
188     }
189 
190     return result;
191 }
192 
193 ::rtl::OUString SAL_CALL SwVbaFind::getText() throw (uno::RuntimeException)
194 {
195     return mxPropertyReplace->getSearchString();
196 }
197 
198 void SAL_CALL SwVbaFind::setText( const ::rtl::OUString& _text ) throw (uno::RuntimeException)
199 {
200     mxPropertyReplace->setSearchString( _text );
201 }
202 
203 uno::Any SAL_CALL SwVbaFind::getReplacement() throw (uno::RuntimeException)
204 {
205     return uno::makeAny( uno::Reference< word::XReplacement >( new SwVbaReplacement( this, mxContext, mxPropertyReplace ) ) );
206 }
207 
208 void SAL_CALL SwVbaFind::setReplacement( const uno::Any& /*_replacement */ ) throw (uno::RuntimeException)
209 {
210     throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() );
211 }
212 
213 ::sal_Bool SAL_CALL SwVbaFind::getForward() throw (uno::RuntimeException)
214 {
215     sal_Bool bBackward = sal_False;
216     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchBackwards") ) ) >>= bBackward;
217     return !bBackward;
218 }
219 
220 void SAL_CALL SwVbaFind::setForward( ::sal_Bool _forward ) throw (uno::RuntimeException)
221 {
222     sal_Bool bBackward = !_forward;
223     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchBackwards") ), uno::makeAny( bBackward ) );
224 }
225 
226 ::sal_Int32 SAL_CALL SwVbaFind::getWrap() throw (uno::RuntimeException)
227 {
228     // seems not supported in Writer
229     return mnWrap;
230 }
231 
232 void SAL_CALL SwVbaFind::setWrap( ::sal_Int32 _wrap ) throw (uno::RuntimeException)
233 {
234     // seems not supported in Writer
235     mnWrap = _wrap;
236 }
237 
238 ::sal_Bool SAL_CALL SwVbaFind::getFormat() throw (uno::RuntimeException)
239 {
240     return mxPropertyReplace->getValueSearch();
241 }
242 
243 void SAL_CALL SwVbaFind::setFormat( ::sal_Bool _format ) throw (uno::RuntimeException)
244 {
245     mxPropertyReplace->setValueSearch( _format );
246 }
247 
248 ::sal_Bool SAL_CALL SwVbaFind::getMatchCase() throw (uno::RuntimeException)
249 {
250     sal_Bool value = sal_False;
251     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchCaseSensitive") ) ) >>= value;
252     return value;
253 }
254 
255 void SAL_CALL SwVbaFind::setMatchCase( ::sal_Bool _matchcase ) throw (uno::RuntimeException)
256 {
257     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchCaseSensitive") ), uno::makeAny( _matchcase ) );
258 }
259 
260 ::sal_Bool SAL_CALL SwVbaFind::getMatchWholeWord() throw (uno::RuntimeException)
261 {
262     sal_Bool value = sal_False;
263     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchWords") ) ) >>= value;
264     return value;
265 }
266 
267 void SAL_CALL SwVbaFind::setMatchWholeWord( ::sal_Bool _matchwholeword ) throw (uno::RuntimeException)
268 {
269     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchWords") ), uno::makeAny( _matchwholeword ) );
270 }
271 
272 ::sal_Bool SAL_CALL SwVbaFind::getMatchWildcards() throw (uno::RuntimeException)
273 {
274     sal_Bool value = sal_False;
275     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchRegularExpression") ) ) >>= value;
276     return value;
277 }
278 
279 void SAL_CALL SwVbaFind::setMatchWildcards( ::sal_Bool _matchwildcards ) throw (uno::RuntimeException)
280 {
281     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchRegularExpression") ), uno::makeAny( _matchwildcards ) );
282 }
283 
284 ::sal_Bool SAL_CALL SwVbaFind::getMatchSoundsLike() throw (uno::RuntimeException)
285 {
286     sal_Bool value = sal_False;
287     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarity") ) ) >>= value;
288     return value;
289 }
290 
291 void SAL_CALL SwVbaFind::setMatchSoundsLike( ::sal_Bool _matchsoundslike ) throw (uno::RuntimeException)
292 {
293     // seems not accurate
294     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarity") ), uno::makeAny( _matchsoundslike ) );
295 }
296 
297 ::sal_Bool SAL_CALL SwVbaFind::getMatchAllWordForms() throw (uno::RuntimeException)
298 {
299     sal_Bool value = sal_False;
300     mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarity") ) ) >>= value;
301     if( value )
302         mxPropertyReplace->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarityRelax") ) ) >>= value;
303     return value;
304 }
305 
306 void SAL_CALL SwVbaFind::setMatchAllWordForms( ::sal_Bool _matchallwordforms ) throw (uno::RuntimeException)
307 {
308     // seems not accurate
309     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarity") ), uno::makeAny( _matchallwordforms ) );
310     mxPropertyReplace->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("SearchSimilarityRelax") ), uno::makeAny( _matchallwordforms ) );
311 }
312 
313 uno::Any SAL_CALL SwVbaFind::getStyle() throw (uno::RuntimeException)
314 {
315     throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() );
316 }
317 
318 void SAL_CALL SwVbaFind::setStyle( const uno::Any& /*_style */ ) throw (uno::RuntimeException)
319 {
320     throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Not implemented") ), uno::Reference< uno::XInterface >() );
321 }
322 
323 sal_Bool SAL_CALL
324 SwVbaFind::Execute( const uno::Any& FindText, const uno::Any& MatchCase, const uno::Any& MatchWholeWord, const uno::Any& MatchWildcards, const uno::Any& MatchSoundsLike, const uno::Any& MatchAllWordForms, const uno::Any& Forward, const uno::Any& Wrap, const uno::Any& Format, const uno::Any& ReplaceWith, const uno::Any& Replace, const uno::Any& /*MatchKashida*/, const uno::Any& /*MatchDiacritics*/, const uno::Any& /*MatchAlefHamza*/, const uno::Any& /*MatchControl*/, const uno::Any& /*MatchPrefix*/, const uno::Any& /*MatchSuffix*/, const uno::Any& /*MatchPhrase*/, const uno::Any& /*IgnoreSpace*/, const uno::Any& /*IgnorePunct*/ ) throw (uno::RuntimeException)
325 {
326     sal_Bool result = sal_False;
327     if( FindText.hasValue() )
328     {
329         rtl::OUString sText;
330         FindText >>= sText;
331         setText( sText );
332     }
333 
334     sal_Bool bValue = sal_False;
335     if( MatchCase.hasValue() )
336     {
337         MatchCase >>= bValue;
338         setMatchCase( bValue );
339     }
340 
341     if( MatchWholeWord.hasValue() )
342     {
343         MatchWholeWord >>= bValue;
344         setMatchWholeWord( bValue );
345     }
346 
347     if( MatchWildcards.hasValue() )
348     {
349         MatchWildcards >>= bValue;
350         setMatchWildcards( bValue );
351     }
352 
353     if( MatchSoundsLike.hasValue() )
354     {
355         MatchSoundsLike >>= bValue;
356         setMatchSoundsLike( bValue );
357     }
358 
359     if( MatchAllWordForms.hasValue() )
360     {
361         MatchAllWordForms >>= bValue;
362         setMatchAllWordForms( bValue );
363     }
364 
365     if( Forward.hasValue() )
366     {
367         Forward >>= bValue;
368         setForward( bValue );
369     }
370 
371     if( Wrap.hasValue() )
372     {
373         sal_Int32 nWrapType = 0;
374         Wrap >>= nWrapType;
375         setWrap( nWrapType );
376     }
377 
378     if( Format.hasValue() )
379     {
380         Format >>= bValue;
381         setFormat( bValue );
382     }
383 
384     if( ReplaceWith.hasValue() )
385     {
386         rtl::OUString sValue;
387         ReplaceWith >>= sValue;
388         SetReplaceWith( sValue );
389     }
390 
391     if( Replace.hasValue() )
392     {
393         sal_Int32 nValue(0);
394         Replace >>= nValue;
395         SetReplace( nValue );
396     }
397 
398     result = SearchReplace();
399 
400     return result;
401 }
402 
403 void SAL_CALL
404 SwVbaFind::ClearFormatting(  ) throw (uno::RuntimeException)
405 {
406     uno::Sequence< beans::PropertyValue >  aSearchAttribs;
407     mxPropertyReplace->setSearchAttributes( aSearchAttribs );
408 }
409 
410 rtl::OUString&
411 SwVbaFind::getServiceImplName()
412 {
413 	static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaFind") );
414 	return sImplName;
415 }
416 
417 uno::Sequence< rtl::OUString >
418 SwVbaFind::getServiceNames()
419 {
420 	static uno::Sequence< rtl::OUString > aServiceNames;
421 	if ( aServiceNames.getLength() == 0 )
422 	{
423 		aServiceNames.realloc( 1 );
424 		aServiceNames[ 0 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Find" ) );
425 	}
426 	return aServiceNames;
427 }
428 
429