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