1 21 22 package org.armedbear.j; 23 24 import java.awt.event.KeyEvent ; 25 import javax.swing.SwingUtilities ; 26 import javax.swing.undo.CompoundEdit ; 27 28 public final class IncrementalFindTextFieldHandler extends DefaultTextFieldHandler 29 implements Constants 30 { 31 private final Display display; 32 private final Buffer buffer; 33 34 private Search search; 35 private CompoundEdit edit; 36 private boolean inHistory; 37 private KeyMap keyMap; 38 39 private final Position initialDot; 41 private final int initialDotCol; 42 private final Position initialMark; 43 44 public IncrementalFindTextFieldHandler(Editor editor, HistoryTextField textField) 45 { 46 super(editor, textField); 47 display = editor.getDisplay(); 48 buffer = editor.getBuffer(); 49 search = new Search(); 50 if (buffer.supportsUndo) { 51 edit = new CompoundEdit (); 52 edit.addEdit(new UndoFold(editor)); 53 edit.addEdit(new UndoMove(editor)); 54 } 55 initializeKeyMap(); 56 initialDot = editor.getDotCopy(); 58 initialDotCol = display.getCaretCol() + display.getShift(); 59 if (editor.getMark() != null) 60 initialMark = editor.getMark().copy(); 61 else 62 initialMark = null; 63 } 64 65 public void initializeKeyMap() 66 { 67 keyMap = new KeyMap(); 68 keyMap.addMappingsForCommand("incrementalFind", KeyMap.getGlobalKeyMap()); 69 keyMap.addMappingsForCommand("incrementalFind", buffer.getKeyMapForMode()); 70 keyMap.addMappingsForCommand("findNext", KeyMap.getGlobalKeyMap()); 71 keyMap.addMappingsForCommand("findNext", buffer.getKeyMapForMode()); 72 keyMap.addMappingsForCommand("findPrev", KeyMap.getGlobalKeyMap()); 73 keyMap.addMappingsForCommand("findPrev", buffer.getKeyMapForMode()); 74 } 75 76 public void escape() 77 { 78 restoreInitialState(); 79 editor.ensureActive(); 80 editor.setFocusToDisplay(); 81 editor.updateLocation(); 82 editor.status(""); 84 } 85 86 private void restoreInitialState() 87 { 88 editor.updateDotLine(); 89 editor.setDot(initialDot); 90 editor.updateDotLine(); 91 editor.setMark(initialMark); 92 if (initialMark != null && initialMark.getLine() != initialDot.getLine()) 93 editor.setUpdateFlag(REPAINT); 94 display.setCaretCol(initialDotCol - display.getShift()); 95 editor.setUpdateFlag(REFRAME); 96 editor.updateDisplay(); 97 } 98 99 public void keyPressed(KeyEvent e) 100 { 101 final char keyChar = e.getKeyChar(); 102 final int keyCode = e.getKeyCode(); 103 final int modifiers = e.getModifiers() & 0x0f; 105 switch (keyCode) { 106 case KeyEvent.VK_ESCAPE: 107 escape(); 108 e.consume(); 109 return; 110 case KeyEvent.VK_BACK_SPACE: 111 backspace(); 112 e.consume(); 113 return; 114 case KeyEvent.VK_N: 115 if (modifiers == CTRL_MASK) { 116 e.consume(); 117 retrieveHistory(1); 118 return; 119 } 120 break; 121 case KeyEvent.VK_P: 122 if (modifiers == CTRL_MASK) { 123 e.consume(); 124 retrieveHistory(-1); 125 return; 126 } 127 break; 128 case KeyEvent.VK_W: 129 if (modifiers == CTRL_MASK) { 130 e.consume(); 131 yankWord(); 132 } 133 break; 134 case KeyEvent.VK_ENTER: 135 e.consume(); case KeyEvent.VK_LEFT: 137 case KeyEvent.VK_KP_LEFT: 138 case KeyEvent.VK_RIGHT: 139 case KeyEvent.VK_KP_RIGHT: 140 case KeyEvent.VK_UP: 141 case KeyEvent.VK_KP_UP: 142 case KeyEvent.VK_DOWN: 143 case KeyEvent.VK_KP_DOWN: 144 case KeyEvent.VK_HOME: 145 case KeyEvent.VK_END: 146 if (modifiers == 0) 147 finish(e); 148 return; 149 default: 150 break; 151 } 152 KeyMapping mapping = keyMap.lookup(keyChar, keyCode, modifiers); 153 if (mapping != null) { 154 Object command = mapping.getCommand(); 155 if (command == "incrementalFind" || command == "findNext") { 156 e.consume(); 157 findNext(); 158 return; 159 } 160 if (command == "findPrev") { 161 e.consume(); 162 findPrev(); 163 return; 164 } 165 } 166 } 167 168 private void retrieveHistory(int direction) 169 { 170 History history = textField.getHistory(); 171 if (history == null) 172 return; 173 if (!inHistory) 174 history.reset(); 175 String s = direction < 0 ? history.getPrevious() : history.getNext(); 176 if (s != null && s.length() != 0) { 177 inHistory = true; 178 search.setPattern(s); 179 textField.setText(s); 180 textField.setCaretPosition(s.length()); 181 return; 182 } 183 } 184 185 private void yankWord() 186 { 187 inHistory = false; 188 int begin = editor.getDotOffset(); 189 int end = begin + search.getPatternLength(); 190 final Line dotLine = editor.getDotLine(); 191 final int limit = dotLine.length(); 192 final Mode mode = buffer.getMode(); 193 while (end < limit && !mode.isIdentifierPart(dotLine.charAt(end))) 195 ++end; 196 while (end < limit && mode.isIdentifierPart(dotLine.charAt(end))) 198 ++end; 199 String s = dotLine.substring(begin, end); 200 if (Utilities.isLowerCase(search.getPattern())) 203 s = s.toLowerCase(); 204 if (!s.equals(search.getPattern())) { 205 search.setPattern(s); 206 editor.markFoundPattern(search); 207 editor.updateDisplay(); 208 } 209 } 210 211 private void finish(KeyEvent e) 212 { 213 if (search.getPattern() != null && search.getPatternLength() > 0) { 214 editor.setLastSearch(search); 215 History history = textField.getHistory(); 216 if (history != null) { 217 history.append(search.getPattern()); 218 history.save(); 219 } 220 if (edit != null) { 221 edit.end(); 222 buffer.addEdit(edit); 223 } 224 } 225 final int keyCode = e.getKeyCode(); 226 if (keyCode == KeyEvent.VK_ENTER) { 227 String pattern = textField.getText(); 228 if (pattern == null || pattern.length() == 0) { 229 editor.updateLocation(); 230 FindDialog.find(editor); 231 editor.updateDisplay(); 232 return; 233 } 234 } else { 235 editor.handleKeyEvent(e.getKeyChar(), keyCode, e.getModifiers()); 236 editor.updateDisplay(); 238 } 239 editor.ensureActive(); 240 editor.setFocusToDisplay(); 241 editor.updateLocation(); 242 } 243 244 public void keyReleased(KeyEvent e) 245 { 246 textField.setText(search.getPattern()); 247 textField.setCaretPosition(search.getPatternLength()); 248 } 249 250 public void keyTyped(KeyEvent e) 251 { 252 final int modifiers = e.getModifiers() & 0x0f; 254 if (modifiers == 0 || modifiers == SHIFT_MASK) 255 handleKeyEvent(e); 256 } 257 258 private void handleKeyEvent(KeyEvent e) 259 { 260 int modifiers = e.getModifiers() & 0x0f; 262 if (modifiers != 0 && modifiers != KeyEvent.SHIFT_MASK) 263 return; 264 char c = e.getKeyChar(); 265 if (c == KeyEvent.CHAR_UNDEFINED) 266 return; 267 if (c == 8) { 268 e.consume(); 269 return; 270 } 271 inHistory = false; 272 search.appendCharToPattern(c); 273 search.setIgnoreCase(Utilities.isLowerCase(search.getPattern())); 276 Position pos = search.findString(buffer, editor.getDot(), true); 277 if (pos != null) 278 found(pos); 279 else 280 search.notFound(editor); 281 } 282 283 private void backspace() 284 { 285 String s = textField.getText(); 286 if (s.length() > 0) { 287 s = s.substring(0, s.length()-1); 288 textField.setText(s); 289 search.setPattern(s); 290 search.setIgnoreCase(Utilities.isLowerCase(s)); 291 if (s.length() > 0) { 292 Position pos = search.findString(buffer, initialDot, true); 293 if (pos != null) { 294 found(pos); 295 editor.status(""); 297 } else 298 search.notFound(editor); 299 } else 300 restoreInitialState(); 301 } 302 } 303 304 private void findNext() 305 { 306 if (search.getPatternLength() > 0) { 307 if (!inHistory) { 311 if (editor.getDotOffset() < editor.getDotLine().length()) 312 editor.getDot().skip(1); 313 else if (editor.getDotLine().next() != null) 314 editor.setDot(editor.getDotLine().next(), 0); 315 else 316 editor.setDot(buffer.getFirstLine(), 0); 318 } 319 } else { 320 History history = textField.getHistory(); 322 if (history != null) { 323 history.reset(); 324 String s = history.getPrevious(); 325 if (s == null) 326 s = ""; 327 search.setPattern(s); 328 if (s.length() == 0) 329 return; 330 textField.setText(s); 331 textField.setCaretPosition(s.length()); 332 } 333 } 334 inHistory = false; 335 search.setIgnoreCase(Utilities.isLowerCase(search.getPattern())); 338 Position pos = search.findString(buffer, editor.getDot(), true); 339 if (pos != null) 340 found(pos); 341 } 342 343 private void findPrev() 344 { 345 if (search.getPatternLength() > 0) { 346 Position start; 347 if (editor.getMark() != null) 348 start = new Region(editor).getBegin(); 349 else 350 start = editor.getDotCopy(); 351 boolean wrapped = false; 352 if (!start.prev()) { 353 start = buffer.getEnd(); 354 wrapped = true; 355 } 356 Position pos = search.reverseFindString(buffer, start); 357 if (pos == null && !wrapped) 358 pos = search.reverseFindString(buffer, buffer.getEnd()); 359 if (pos != null) 360 found(pos); 361 } 362 } 363 364 private boolean dirty; 365 366 private void found(Position pos) 367 { 368 if (editor.getMark() != null) 369 if (editor.getMarkLine() != editor.getDotLine()) 370 editor.setUpdateFlag(REPAINT); 371 editor.updateDotLine(); 372 editor.getDot().moveTo(pos); 373 editor.updateDotLine(); 374 editor.setUpdateFlag(REFRAME); 375 dirty = true; 376 SwingUtilities.invokeLater(foundRunnable); 377 } 378 379 private final Runnable foundRunnable = new Runnable () { 380 public void run() 381 { 382 if (dirty) { 383 editor.markFoundPattern(search); 384 editor.updateDisplay(); 385 dirty = false; 386 } 387 } 388 }; 389 } 390 | Popular Tags |