1 33 34 package edu.rice.cs.drjava.model; 35 36 import edu.rice.cs.drjava.model.definitions.reducedmodel.ReducedModelStates; 37 38 import edu.rice.cs.util.UnexpectedException; 39 import edu.rice.cs.util.swing.DocumentIterator; 40 import edu.rice.cs.util.swing.Utilities; 41 import edu.rice.cs.util.text.AbstractDocumentInterface; 42 import edu.rice.cs.util.Lambda; 43 import edu.rice.cs.util.Log; 44 import edu.rice.cs.util.StringOps; 45 46 import java.awt.EventQueue ; 47 48 import javax.swing.text.BadLocationException ; 49 import javax.swing.text.Position ; 50 51 54 public class FindReplaceMachine { 55 56 58 static private Log _log = new Log("FindReplace.txt", false); 59 60 61 private OpenDefinitionsDocument _doc; private OpenDefinitionsDocument _firstDoc; private Position _current; private String _findWord; private String _replaceWord; private boolean _matchCase; 68 private boolean _matchWholeWord; 69 private boolean _searchAllDocuments; private boolean _isForward; private boolean _ignoreCommentsAndStrings; private String _lastFindWord; private boolean _skipText; private DocumentIterator _docIterator; private SingleDisplayModel _model; 76 77 82 public FindReplaceMachine(SingleDisplayModel model, DocumentIterator docIterator) { 83 _skipText = false; 84 _model = model; 87 _docIterator = docIterator; 88 setFindAnyOccurrence(); 89 setFindWord(""); 90 setReplaceWord(""); 91 setSearchBackwards(false); 92 setMatchCase(true); 93 setSearchAllDocuments(false); 94 setIgnoreCommentsAndStrings(false); 95 } 96 97 public void cleanUp() { 98 _docIterator = null; 99 setFindWord(""); 100 _doc = null; 101 } 102 103 106 public void positionChanged() { 107 _lastFindWord = null; 108 _skipText = false; 109 } 110 111 public void setLastFindWord() { _lastFindWord = _findWord; } 112 113 public boolean getSearchBackwards() { return ! _isForward; } 114 115 public void setSearchBackwards(boolean searchBackwards) { 116 if (_isForward == searchBackwards) { 117 if (onMatch() && _findWord.equals(_lastFindWord)) _skipText = true; 120 else _skipText = false; 121 } 122 _isForward = ! searchBackwards; 123 } 124 125 public void setMatchCase(boolean matchCase) { _matchCase = matchCase; } 126 127 public void setMatchWholeWord() { _matchWholeWord = true; } 128 129 public void setFindAnyOccurrence() { _matchWholeWord = false; } 130 131 public void setSearchAllDocuments(boolean searchAllDocuments) { _searchAllDocuments = searchAllDocuments; } 132 133 public void setIgnoreCommentsAndStrings(boolean ignoreCommentsAndStrings) { 134 _ignoreCommentsAndStrings = ignoreCommentsAndStrings; 135 } 136 137 public void setDocument(OpenDefinitionsDocument doc) { _doc = doc; } 138 139 public void setFirstDoc(OpenDefinitionsDocument firstDoc) { _firstDoc = firstDoc; } 140 141 public void setPosition(int pos) { 142 try { _current = _doc.createPosition(pos); } 145 catch (BadLocationException ble) { throw new UnexpectedException(ble); } 146 } 147 148 149 public int getCurrentOffset() { return _current.getOffset(); } 150 151 public String getFindWord() { return _findWord; } 152 153 public String getReplaceWord() { return _replaceWord; } 154 155 public boolean getSearchAllDocuments() { return _searchAllDocuments; } 156 157 public OpenDefinitionsDocument getDocument() { return _doc; } 158 159 public OpenDefinitionsDocument getFirstDoc() { return _firstDoc; } 160 161 164 public void setFindWord(String word) { 165 _findWord = StringOps.replace(word, System.getProperty("line.separator"), "\n"); 166 } 167 168 171 public void setReplaceWord(String word) { 172 _replaceWord = StringOps.replace(word, System.getProperty("line.separator"),"\n"); 173 } 174 175 179 public boolean onMatch() { 180 181 183 String findWord = _findWord; 184 int wordLen, off; 185 186 if(_current == null) return false; 187 188 wordLen = findWord.length(); 189 if (_isForward) off = getCurrentOffset() - wordLen; 190 else off = getCurrentOffset(); 191 192 if (off < 0) return false; 193 194 String matchSpace; 195 try { 196 if (off + wordLen > _doc.getLength()) return false; 197 matchSpace = _doc.getText(off, wordLen); 198 } 199 catch (BadLocationException e) { throw new UnexpectedException(e); } 200 201 if (!_matchCase) { 202 matchSpace = matchSpace.toLowerCase(); 203 findWord = findWord.toLowerCase(); 204 } 205 return matchSpace.equals(findWord); 206 } 207 208 209 public boolean replaceCurrent() { 210 211 assert EventQueue.isDispatchThread(); 212 213 if (! onMatch()) return false; 214 _doc.acquireWriteLock(); 215 try { 216 int offset = getCurrentOffset(); 218 if (_isForward) offset -= _findWord.length(); 221 223 _doc.remove(offset, _findWord.length()); 224 225 _doc.insertString(getCurrentOffset(), _replaceWord, null); 227 228 if (_isForward) setPosition(offset + _replaceWord.length()); 230 else setPosition(offset); 231 232 return true; 233 } 234 catch (BadLocationException e) { throw new UnexpectedException(e); } 235 finally { _doc.releaseWriteLock(); } 236 } 237 238 242 public int replaceAll() { return replaceAll(_searchAllDocuments); } 243 244 248 private int replaceAll(boolean searchAll) { 249 if (searchAll) { 250 OpenDefinitionsDocument startDoc = _doc; 251 int count = 0; int n = _docIterator.getDocumentCount(); 253 for (int i = 0; i < n; i++) { 254 count += _replaceAllInCurrentDoc(); 256 _doc = _docIterator.getNextDocument(_doc); 257 } 258 259 _model.getDocumentNavigator().repaint(); 261 262 return count; 263 } 264 else return _replaceAllInCurrentDoc(); 265 } 266 267 278 private int _replaceAllInCurrentDoc() { 279 280 assert EventQueue.isDispatchThread(); 281 282 if (_isForward) setPosition(0); 283 else setPosition(_doc.getLength()); 284 285 int count = 0; 286 FindResult fr = findNext(false); 289 while (! fr.getWrapped()) { 290 replaceCurrent(); count++; 292 fr = findNext(false); } 296 return count; 297 } 298 299 304 public int processAll(Lambda<Void , FindResult> findAction) { return processAll(findAction, _searchAllDocuments); } 305 306 311 private int processAll(Lambda<Void , FindResult> findAction, boolean searchAll) { 312 313 assert EventQueue.isDispatchThread(); 314 315 if (searchAll) { 316 OpenDefinitionsDocument startDoc = _doc; 317 int count = 0; int n = _docIterator.getDocumentCount(); 319 for (int i = 0; i < n; i++) { 320 count += _processAllInCurrentDoc(findAction); 322 _doc = _docIterator.getNextDocument(_doc); 323 } 324 325 _model.getDocumentNavigator().repaint(); 327 328 return count; 329 } 330 else return _processAllInCurrentDoc(findAction); 331 } 332 333 343 private int _processAllInCurrentDoc(Lambda<Void , FindResult> findAction) { 344 345 if (_isForward) setPosition(0); 346 else setPosition(_doc.getLength()); 347 348 int count = 0; 349 FindResult fr = findNext(false); 351 while (! fr.getWrapped()) { 352 findAction.apply(fr); 353 count++; 354 fr = findNext(false); } 356 return count; 357 } 358 359 public FindResult findNext() { return findNext(_searchAllDocuments); } 360 361 371 private FindResult findNext(boolean searchAll) { 372 373 assert EventQueue.isDispatchThread(); 374 375 FindResult fr; 377 int start; 378 int len; 379 380 if (_skipText) { int wordLen = _lastFindWord.length(); 384 if (_isForward) setPosition(getCurrentOffset() + wordLen); 385 else setPosition(getCurrentOffset() - wordLen); 386 positionChanged(); 387 } 388 389 391 int offset = getCurrentOffset(); 392 if (_isForward) { 395 start = offset; 396 len = _doc.getLength() - offset; 397 } 398 else { 399 start = 0; 400 len = offset; 401 } 402 fr = _findNextInDoc(_doc, start, len, searchAll); 403 if ((fr.getFoundOffset() >= 0) || ! searchAll) return fr; 405 return _findNextInOtherDocs(_doc, start, len); 407 } 408 409 410 414 private FindResult _findNextInDoc(OpenDefinitionsDocument doc, int start, int len, boolean searchAll) { 415 _log.log("_findNextInDoc([" + doc.getText() + "], " + start + ", " + len + ", " + searchAll + ")"); 417 FindResult fr = _findNextInDocSegment(doc, start, len); 418 if (fr.getFoundOffset() >= 0 || searchAll) return fr; 419 420 return _findWrapped(doc, start, len, false); } 422 423 432 private FindResult _findWrapped(OpenDefinitionsDocument doc, int start, int len, boolean allWrapped) { 433 434 assert (_isForward && start + len == doc.getLength()) || (! _isForward && start == 0); 435 436 _log.log("_findWrapped(" + doc + ", " + start + ", " + len + ", " + allWrapped + ") docLength = " + 437 doc.getLength() + ", _isForward = " + _isForward); 438 439 if (doc.getLength() == 0) return new FindResult(doc, -1, true, allWrapped); 440 441 final int newLen, newStart; 442 if (_isForward) { 443 newStart = 0; 444 newLen = start; 445 } 446 else { 447 newStart = len; 448 newLen = doc.getLength() - len; 449 } 450 _log.log("Calling _findNextInDocSegment(" + doc.getText() + ", newStart = " + newStart + ", newLen = " + 451 newLen + ", allWrapped = " + allWrapped + ") and _isForward = " + _isForward); 452 return _findNextInDocSegment(doc, newStart, newLen, true, allWrapped); 453 } 454 455 456 private FindResult _findNextInDocSegment(OpenDefinitionsDocument doc, int start, int len) { 457 return _findNextInDocSegment(doc, start, len, false, false); 458 } 459 460 471 private FindResult _findNextInDocSegment(final OpenDefinitionsDocument doc, final int start, final int origLen, 472 final boolean wrapped, final boolean allWrapped) { 473 475 final int docLen = doc.getLength();; 477 final int len = (origLen < 0) ? docLen - start : origLen; 479 if (len == 0 || docLen == 0) return new FindResult(doc, -1, wrapped, allWrapped); 480 481 String text; final String findWord; final int wordLen = _findWord.length(); 485 try { 486 487 doc.acquireReadLock(); 489 try { text = doc.getText(start, len); } 490 finally { doc.releaseReadLock(); } 491 492 if (! _matchCase) { 493 text = text.toLowerCase(); 494 findWord = _findWord.toLowerCase(); } 496 else findWord = _findWord; 497 499 int foundOffset = _isForward? 0 : len; 506 int rem = len; 507 while (rem >= wordLen) { 509 510 foundOffset = _isForward ? text.indexOf(findWord, foundOffset) : text.lastIndexOf(findWord, foundOffset); 512 if (foundOffset < 0) break; int foundLocation = start + foundOffset; 515 int matchLocation; 516 517 if (_isForward) { 518 foundOffset += wordLen; rem = len - foundOffset; matchLocation = foundLocation + wordLen; } 524 else { 525 foundOffset -= wordLen; rem = foundOffset; matchLocation = foundLocation; } 531 doc.setCurrentLocation(foundLocation); 534 if (_shouldIgnore(foundLocation, doc)) continue; 536 537 _current = doc.createPosition(matchLocation); 539 541 return new FindResult(doc, matchLocation, wrapped, allWrapped); } 543 } 544 catch (BadLocationException e) { throw new UnexpectedException(e); } 545 546 return new FindResult(doc, -1, wrapped, allWrapped); 548 } 549 550 557 private FindResult _findNextInOtherDocs(final OpenDefinitionsDocument startDoc, int start, int len) { 558 559 561 boolean allWrapped = false; 562 _doc = _isForward ? _docIterator.getNextDocument(startDoc) : _docIterator.getPrevDocument(startDoc); 563 564 while (_doc != startDoc) { 565 if (_doc == _firstDoc) allWrapped = true; 566 567 569 572 573 _doc.acquireReadLock(); 575 FindResult fr; 576 try { fr = _findNextInDocSegment(_doc, 0, _doc.getLength(), false, allWrapped); } 577 finally { _doc.releaseReadLock(); } 578 579 if (fr.getFoundOffset() >= 0) return fr; 580 581 _doc = _isForward ? _docIterator.getNextDocument(_doc) : _docIterator.getPrevDocument(_doc); 583 } 585 586 startDoc.acquireReadLock(); 588 try { return _findWrapped(startDoc, start, len, true); } finally { startDoc.releaseReadLock(); } 590 } 591 592 597 private boolean wholeWordFoundAtCurrent(OpenDefinitionsDocument doc, int foundOffset) { 598 599 char leftOfMatch = 0; char rightOfMatch = 0; int leftLoc = foundOffset - 1; 602 int rightLoc = foundOffset + _findWord.length(); 603 boolean leftOutOfBounds = false; 604 boolean rightOutOfBounds = false; 605 606 doc.acquireReadLock(); 607 try { 608 try { leftOfMatch = doc.getText(leftLoc, 1).charAt(0); } 609 catch (BadLocationException e) { leftOutOfBounds = true; } 610 try { rightOfMatch = doc.getText(rightLoc, 1).charAt(0); } 611 catch (BadLocationException e) { rightOutOfBounds = true; } 612 } 613 finally {doc.releaseReadLock();} 614 615 if (! leftOutOfBounds && ! rightOutOfBounds) return isDelimiter(rightOfMatch) && isDelimiter(leftOfMatch); 616 if (! leftOutOfBounds) return isDelimiter(leftOfMatch); 617 if (! rightOutOfBounds) return isDelimiter(rightOfMatch); 618 return true; 619 } 620 621 626 private boolean isDelimiter(char ch) { return ! Character.isLetterOrDigit(ch); } 627 628 635 private boolean _shouldIgnore(int foundOffset, OpenDefinitionsDocument odd) { 636 637 assert EventQueue.isDispatchThread(); 638 639 return (_matchWholeWord && ! wholeWordFoundAtCurrent(odd, foundOffset)) || 640 (_ignoreCommentsAndStrings && odd.getStateAtCurrent() != ReducedModelStates.FREE); 641 } 642 } | Popular Tags |