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