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 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 44 SwVbaFind::~SwVbaFind() 45 { 46 } 47 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 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 64 void SwVbaFind::SetReplaceWith( const rtl::OUString& rText ) throw (uno::RuntimeException) 65 { 66 mxPropertyReplace->setReplaceString( rText ); 67 mbReplace = sal_True; 68 } 69 70 rtl::OUString SwVbaFind::GetReplaceWith() throw (uno::RuntimeException) 71 { 72 return mxPropertyReplace->getReplaceString(); 73 } 74 void SwVbaFind::SetReplace( sal_Int32 type ) 75 { 76 mnReplaceType = type; 77 mbReplace = sal_True; 78 } 79 #ifdef TOMORROW 80 rtl::OUString SwVbaFind::ReplaceWildcards( const rtl::OUString& /*rText*/ ) throw ( uno::RuntimeException ) 81 { 82 // TODO: 83 return rtl::OUString(); 84 } 85 #endif 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 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 189 ::rtl::OUString SAL_CALL SwVbaFind::getText() throw (uno::RuntimeException) 190 { 191 return mxPropertyReplace->getSearchString(); 192 } 193 194 void SAL_CALL SwVbaFind::setText( const ::rtl::OUString& _text ) throw (uno::RuntimeException) 195 { 196 mxPropertyReplace->setSearchString( _text ); 197 } 198 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 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 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 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 222 ::sal_Int32 SAL_CALL SwVbaFind::getWrap() throw (uno::RuntimeException) 223 { 224 // seems not supported in Writer 225 return mnWrap; 226 } 227 228 void SAL_CALL SwVbaFind::setWrap( ::sal_Int32 _wrap ) throw (uno::RuntimeException) 229 { 230 // seems not supported in Writer 231 mnWrap = _wrap; 232 } 233 234 ::sal_Bool SAL_CALL SwVbaFind::getFormat() throw (uno::RuntimeException) 235 { 236 return mxPropertyReplace->getValueSearch(); 237 } 238 239 void SAL_CALL SwVbaFind::setFormat( ::sal_Bool _format ) throw (uno::RuntimeException) 240 { 241 mxPropertyReplace->setValueSearch( _format ); 242 } 243 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 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 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 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 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 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 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 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 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 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 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 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 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 400 SwVbaFind::ClearFormatting( ) throw (uno::RuntimeException) 401 { 402 uno::Sequence< beans::PropertyValue > aSearchAttribs; 403 mxPropertyReplace->setSearchAttributes( aSearchAttribs ); 404 } 405 406 rtl::OUString& 407 SwVbaFind::getServiceImplName() 408 { 409 static rtl::OUString sImplName( RTL_CONSTASCII_USTRINGPARAM("SwVbaFind") ); 410 return sImplName; 411 } 412 413 uno::Sequence< rtl::OUString > 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