1 19 20 package org.netbeans.editor; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.util.HashMap ; 25 import java.util.ArrayList ; 26 import javax.swing.text.Position ; 27 import javax.swing.text.BadLocationException ; 28 import javax.swing.text.JTextComponent ; 29 30 37 38 public class WordMatch extends FinderFactory.AbstractFinder 39 implements SettingsChangeListener, PropertyChangeListener { 40 41 private static final Object NULL_DOC = new Object (); 42 43 44 private static final HashMap staticWordsDocs = new HashMap (); 45 46 51 char[] baseWord; 52 53 54 char[] word = new char[20]; 55 56 57 String lastWord; 58 59 60 String previousWord; 61 62 63 int wordLen; 64 65 66 StringMap wordsMap = new StringMap(); 67 68 69 ArrayList wordInfoList = new ArrayList (); 70 71 75 int wordsIndex; 76 77 78 boolean forwardSearch; 79 80 81 EditorUI editorUI; 82 83 84 boolean wrapSearch; 85 86 87 boolean matchCase; 88 89 90 boolean smartCase; 91 92 95 boolean realMatchCase; 96 97 100 boolean matchOneChar; 101 102 105 int maxSearchLen; 106 107 108 BaseDocument startDoc; 109 110 111 public WordMatch(EditorUI editorUI) { 112 this.editorUI = editorUI; 113 114 Settings.addSettingsChangeListener(this); 115 116 synchronized (editorUI.getComponentLock()) { 117 JTextComponent component = editorUI.getComponent(); 119 if (component != null) { 120 propertyChange(new PropertyChangeEvent (editorUI, 121 EditorUI.COMPONENT_PROPERTY, null, component)); 122 } 123 124 editorUI.addPropertyChangeListener(this); 125 } 126 } 127 128 131 public void settingsChange(SettingsChangeEvent evt) { 132 if (evt != null) { staticWordsDocs.clear(); 134 } 135 136 Class kitClass = Utilities.getKitClass(editorUI.getComponent()); 137 if (kitClass != null) { 138 maxSearchLen = SettingsUtil.getInteger(kitClass, SettingsNames.WORD_MATCH_SEARCH_LEN, 139 Integer.MAX_VALUE); 140 wrapSearch = SettingsUtil.getBoolean(kitClass, SettingsNames.WORD_MATCH_WRAP_SEARCH, 141 true); 142 matchOneChar = SettingsUtil.getBoolean(kitClass, SettingsNames.WORD_MATCH_MATCH_ONE_CHAR, 143 true); 144 matchCase = SettingsUtil.getBoolean(kitClass, SettingsNames.WORD_MATCH_MATCH_CASE, 145 false); 146 smartCase = SettingsUtil.getBoolean(kitClass, SettingsNames.WORD_MATCH_SMART_CASE, 147 false); 148 } 149 } 150 151 public void propertyChange(PropertyChangeEvent evt) { 152 String propName = evt.getPropertyName(); 153 154 if (EditorUI.COMPONENT_PROPERTY.equals(propName)) { 155 JTextComponent component = (JTextComponent )evt.getNewValue(); 156 if (component != null) { 158 settingsChange(null); 159 160 } else { 163 } 164 165 } 166 } 167 168 171 public synchronized void clear() { 172 if (baseWord != null) { 173 baseWord = null; 174 wordsMap.clear(); 175 wordInfoList.clear(); 176 wordsIndex = 0; 177 } 178 } 179 180 181 public void reset() { 182 super.reset(); 183 wordLen = 0; 184 } 185 186 189 public synchronized String getMatchWord(int startPos, boolean forward) { 190 int listSize = wordInfoList.size(); 191 boolean searchNext = (listSize == 0) 192 || (wordsIndex == (forward ? (listSize - 1) : 0)); 193 startDoc = (BaseDocument)editorUI.getComponent().getDocument(); 194 String ret = null; 195 196 if (baseWord == null) { 198 try { 199 String baseWordString = Utilities.getIdentifierBefore(startDoc, startPos); 200 if (baseWordString == null) { 201 baseWordString = ""; } 203 lastWord = baseWordString; 204 baseWord = baseWordString.toCharArray(); 205 206 WordInfo info = new WordInfo(baseWordString, 207 startDoc.createPosition(startPos - baseWord.length), startDoc); 208 wordsMap.put(info.word, info); 209 wordInfoList.add(info); 210 } catch (BadLocationException e) { 211 Utilities.annotateLoggable(e); 212 } 213 if (smartCase && !matchCase) { 214 realMatchCase = false; 215 for (int i = 0; i < baseWord.length; i++) { 216 if (Character.isUpperCase(baseWord[i])) { 217 realMatchCase = true; 218 } 219 } 220 } else { 221 realMatchCase = matchCase; 222 } 223 if (!realMatchCase) { 225 for (int i = 0; i < baseWord.length; i++) { 226 baseWord[i] = Character.toLowerCase(baseWord[i]); 227 } 228 } 229 } 230 231 if (searchNext) { 233 try { 234 BaseDocument doc; int pos; if (listSize > 0) { 238 WordInfo info = (WordInfo)wordInfoList.get(wordsIndex); 239 doc = info.doc; 240 pos = info.pos.getOffset(); 241 if (forward) { 242 pos += info.word.length(); 243 } 244 } else { 245 doc = startDoc; 246 pos = startPos; 247 } 248 249 while (doc != null) { 251 if (doc.getLength() > 0) { 252 int endPos; 253 if (doc == startDoc) { 254 if (forward) { 255 endPos = (pos >= startPos) ? -1 : startPos; 256 } else { endPos = (pos == -1 || pos > startPos) ? startPos : 0; 258 } 259 } else { endPos = -1; 261 } 262 263 this.forwardSearch = !(!forward && (doc == startDoc)); 264 int foundPos = doc.find(this, pos, endPos); 265 if (foundPos != -1) { if (forward) { 267 wordsIndex++; 268 } 269 WordInfo info = new WordInfo(new String (word, 0, wordLen), 270 doc.createPosition(foundPos), doc); 271 wordsMap.put(info.word, info); 272 wordInfoList.add(wordsIndex, info); 273 previousWord = lastWord; 274 lastWord = info.word; 275 return lastWord; 276 } 277 if (doc == startDoc) { 278 if (forward) { 279 pos = 0; 280 if (endPos != -1 || !wrapSearch) { 281 doc = getNextDoc(doc); 282 } 283 } else { if (pos == -1 || !wrapSearch) { 285 doc = getNextDoc(doc); 286 pos = 0; 287 } else { 288 pos = -1; } 290 } 291 } else { doc = getNextDoc(doc); 293 pos = 0; 294 } 295 } else { doc = getNextDoc(doc); 297 pos = 0; } 299 } 300 } catch (BadLocationException e) { 302 Utilities.annotateLoggable(e); 303 } 304 } else { wordsIndex += (forward ? 1 : -1); 306 previousWord = lastWord; 307 lastWord = ((WordInfo)wordInfoList.get(wordsIndex)).word; 308 ret = lastWord; 309 } 310 311 startDoc = null; 312 return ret; 313 } 314 315 public String getPreviousWord() { 316 return previousWord; 317 } 318 319 private void doubleWordSize() { 320 char[] tmp = new char[word.length * 2]; 321 System.arraycopy(word, 0, tmp, 0, word.length); 322 word = tmp; 323 } 324 325 private boolean checkWord() { 326 if (!matchOneChar && wordLen == 1) { 328 return false; 329 } 330 331 if (baseWord.length > 0) { 333 if (wordLen < baseWord.length) { 334 return false; 335 } 336 for (int i = 0; i < baseWord.length; i++) { 337 if (realMatchCase) { 338 if (word[i] != baseWord[i]) { 339 return false; 340 } 341 } else { if (Character.toLowerCase(word[i]) != baseWord[i]) { 343 return false; 344 } 345 } 346 } 347 } 348 349 if (wordsMap.containsKey(word, 0, wordLen)) { 351 return false; 352 } 353 return true; } 355 356 357 public int find(int bufferStartPos, char buffer[], 358 int offset1, int offset2, int reqPos, int limitPos) { 359 int offset = reqPos - bufferStartPos; 360 if (forwardSearch) { 361 int limitOffset = limitPos - bufferStartPos - 1; 362 while (offset < offset2) { 363 char ch = buffer[offset]; 364 boolean wp = startDoc.isIdentifierPart(ch); 365 if (wp) { if (wordLen == word.length) { 367 doubleWordSize(); 368 } 369 word[wordLen++] = ch; 370 } 371 372 if (!wp) { 373 if (wordLen > 0) { 374 if (checkWord()) { 375 found = true; 376 return bufferStartPos + offset - wordLen; 377 378 } else { 379 wordLen = 0; 380 } 381 } 382 383 } else { if (limitOffset == offset) { 385 if (checkWord()) { 386 found = true; 387 return bufferStartPos + offset - wordLen + 1; 389 390 } else { 391 wordLen = 0; 392 } 393 } 394 } 395 396 offset++; 397 } 398 } else { int limitOffset = limitPos - bufferStartPos; 400 while (offset >= offset1) { 401 char ch = buffer[offset]; 402 boolean wp = startDoc.isIdentifierPart(ch); 403 if (wp) { 404 if (wordLen == word.length) { 405 doubleWordSize(); 406 } 407 word[wordLen++] = ch; 408 } 409 if (!wp || (limitOffset == offset)) { 410 if (wordLen > 0) { 411 Analyzer.reverse(word, wordLen); if (checkWord()) { 413 found = true; 414 return (wp) ? bufferStartPos + offset + 1 415 : bufferStartPos + offset; 416 } else { 417 wordLen = 0; 418 } 419 } 420 } 421 offset--; 422 } 423 } 424 return bufferStartPos + offset; 425 } 426 427 428 private BaseDocument getNextDoc(BaseDocument doc) { 429 if (doc == getStaticWordsDoc()) { 430 return null; 431 } 432 BaseDocument nextDoc = Registry.getLessActiveDocument(doc); 433 if (nextDoc == null) { 434 nextDoc = getStaticWordsDoc(); 435 } 436 return nextDoc; 437 } 438 439 private BaseDocument getStaticWordsDoc() { 440 Class kitClass = Utilities.getKitClass(editorUI.getComponent()); 441 Object val = staticWordsDocs.get(kitClass); 442 if (val == NULL_DOC) { 443 return null; 444 } 445 BaseDocument doc = (BaseDocument)val; 446 if (doc == null) { 447 String staticWords = (String )Settings.getValue(kitClass, 448 SettingsNames.WORD_MATCH_STATIC_WORDS); 449 if (staticWords != null) { 450 doc = new BaseDocument(BaseKit.class, false); try { 452 doc.insertString(0, staticWords, null); 453 } catch (BadLocationException e) { 454 Utilities.annotateLoggable(e); 455 } 456 staticWordsDocs.put(kitClass, doc); 457 } else { staticWordsDocs.put(kitClass, NULL_DOC); 459 } 460 } 461 return doc; 462 } 463 464 467 private static final class WordInfo { 468 469 public WordInfo(String word, Position pos, BaseDocument doc) { 470 this.word = word; 471 this.pos = pos; 472 this.doc = doc; 473 } 474 475 476 String word; 477 478 482 Position pos; 483 484 485 BaseDocument doc; 486 487 public boolean equals(Object o) { 488 if (this == o) { 489 return true; 490 } 491 if (o instanceof WordMatch) { 492 WordMatch wm = (WordMatch)o; 493 return Analyzer.equals(word, wm.word, 0, wm.wordLen); 494 } 495 if (o instanceof WordInfo) { 496 return word.equals(((WordInfo)o).word); 497 } 498 if (o instanceof String ) { 499 return word.equals(o); 500 } 501 return false; 502 } 503 504 public int hashCode() { 505 return word.hashCode(); 506 } 507 508 public String toString() { 509 return "{word='" + word + "', pos=" + pos.getOffset() + ", doc=" + Registry.getID(doc) + "}"; } 512 513 } 514 515 public String toString() { 516 return "baseWord=" + ((baseWord != null) ? ("'" + baseWord.toString() + "'") : "null") + ", wrapSearch=" + wrapSearch + ", matchCase=" + matchCase + ", smartCase=" + smartCase + ", matchOneChar=" + matchOneChar + ", maxSearchLen=" + maxSearchLen + ", wordsMap=" + wordsMap + "\nwordInfoList=" + wordInfoList + "\nwordsIndex=" + wordsIndex; } 523 524 } 525 | Popular Tags |