1 22 23 package org.gjt.sp.jedit.gui; 24 25 import java.awt.event.*; 27 import java.util.*; 28 import org.gjt.sp.jedit.*; 29 import org.gjt.sp.util.Log; 30 import org.gjt.sp.util.StandardUtilities; 31 33 40 public class KeyEventTranslator 41 { 42 49 public static void addTranslation(Key key1, Key key2) 50 { 51 transMap.put(key1,key2); 52 } 54 56 protected static KeyEvent lastKeyPressEvent; 57 58 protected static boolean lastKeyPressAccepted; 59 60 66 public static Key translateKeyEvent(KeyEvent evt) 67 { 68 Key key = translateKeyEvent2(evt); 69 70 if (key!=null) { 71 if (key.isPhantom()) { 72 key = null; 73 } 74 } 75 76 return key; 77 } 78 79 85 public static Key translateKeyEvent2(KeyEvent evt) 86 { 87 if (Options.SIMPLIFIED_KEY_HANDLING) 88 { 90 104 char keyChar = evt.getKeyChar(); 105 int keyCode = evt.getKeyCode(); 106 int modifiers = evt.getModifiers(); 107 boolean usecooked = !evt.isActionKey(); 108 109 111 116 if ((modifiers&InputEvent.CTRL_MASK)!=0) { 117 if (keyChar<0x20) { 119 if (keyChar!=keyCode) { keyChar+=0x40; 123 124 if ((keyChar>='A')&&(keyChar<='Z')) { keyChar+=0x20; } 127 129 } 130 } 131 132 if (keyChar=='\\') { keyChar = 0; 135 keyCode = KeyEvent.VK_BACK_SLASH; 136 } 137 138 } 140 141 142 143 148 switch (keyChar) { 149 case 0x1b: case 0x08: case 0x7f: case 0x09: case 0x0a: case KeyEvent.CHAR_UNDEFINED: 155 usecooked = false; 156 keyChar = 0; 157 } 158 159 boolean accept = false; 160 boolean acceptAsPhantom = false; 161 if (true) { 162 switch(evt.getID()) { 163 case KeyEvent.KEY_PRESSED: 164 accept = !usecooked; 165 acceptAsPhantom = !accept; 166 lastKeyPressAccepted = accept; 167 lastKeyPressEvent = evt; 168 break; 169 case KeyEvent.KEY_TYPED: 170 if (lastKeyPressAccepted&&(lastKeyPressEvent!=null)&&(lastKeyPressEvent.getKeyChar()==evt.getKeyChar())) { 171 } else { 174 accept = usecooked; 175 acceptAsPhantom = !accept; 176 } 177 break; 178 default: 179 } 180 } else { 181 185 191 switch(evt.getID()) { 192 case KeyEvent.KEY_PRESSED: 193 accept = true; 194 if (usecooked) { keyCode = 0; 196 } 197 break; 198 default: 199 } 200 } 201 202 Key returnValue = null; 203 204 if (accept||acceptAsPhantom) { 205 if (!accept && acceptAsPhantom) { 206 if (keyChar!=0) { 207 keyCode = 0; 208 } 209 } 210 211 returnValue = new Key(modifiersToString(modifiers),keyCode,keyChar); 212 213 if (!accept && acceptAsPhantom) { 214 if (keyChar!=0) { 215 } 216 returnValue.setIsPhantom(true); 217 } 218 } 219 220 return returnValue; 221 } 222 else 223 { 224 int modifiers = evt.getModifiers(); 225 Key returnValue; 226 227 switch(evt.getID()) 228 { 229 case KeyEvent.KEY_PRESSED: 230 int keyCode = evt.getKeyCode(); 231 if((keyCode >= KeyEvent.VK_0 232 && keyCode <= KeyEvent.VK_9) 233 || (keyCode >= KeyEvent.VK_A 234 && keyCode <= KeyEvent.VK_Z)) 235 { 236 if(Debug.ALTERNATIVE_DISPATCHER) 237 return null; 238 else 239 { 240 returnValue = new Key( 241 modifiersToString(modifiers), 242 '\0',Character.toLowerCase( 243 (char)keyCode)); 244 } 245 } 246 else 247 { 248 if(keyCode == KeyEvent.VK_TAB) 249 { 250 evt.consume(); 251 returnValue = new Key( 252 modifiersToString(modifiers), 253 keyCode,'\0'); 254 } 255 else if(keyCode == KeyEvent.VK_SPACE) 256 { 257 if((modifiers & ~InputEvent.SHIFT_MASK) == 0) 264 returnValue = null; 265 else 266 { 267 returnValue = new Key( 268 modifiersToString(modifiers), 269 0,' '); 270 } 271 } 272 else 273 { 274 returnValue = new Key( 275 modifiersToString(modifiers), 276 keyCode,'\0'); 277 } 278 } 279 break; 280 case KeyEvent.KEY_TYPED: 281 char ch = evt.getKeyChar(); 282 283 if(KeyEventWorkaround.isMacControl(evt)) 284 ch |= 0x60; 285 286 switch(ch) 287 { 288 case '\n': 289 case '\t': 290 case '\b': 291 return null; 292 case ' ': 293 if((modifiers & ~InputEvent.SHIFT_MASK) != 0) 294 return null; 295 } 296 297 int ignoreMods; 298 if(Debug.ALT_KEY_PRESSED_DISABLED) 299 { 300 301 ignoreMods = InputEvent.SHIFT_MASK 302 | InputEvent.ALT_GRAPH_MASK 303 | InputEvent.ALT_MASK; 304 } 305 else 306 { 307 308 ignoreMods = InputEvent.SHIFT_MASK 309 | InputEvent.ALT_GRAPH_MASK; 310 } 311 312 if((modifiers & InputEvent.ALT_GRAPH_MASK) == 0 313 && evt.getWhen() 314 - KeyEventWorkaround.lastKeyTime < 750L 315 && (KeyEventWorkaround.modifiers & ~ignoreMods) 316 != 0) 317 { 318 if(Debug.ALTERNATIVE_DISPATCHER) 319 { 320 returnValue = new Key( 321 modifiersToString(modifiers), 322 0,ch); 323 } 324 else 325 return null; 326 } 327 else 328 { 329 if(ch == ' ') 330 { 331 returnValue = new Key( 332 modifiersToString(modifiers), 333 0,ch); 334 } 335 else 336 returnValue = new Key(null,0,ch); 337 } 338 break; 339 default: 340 return null; 341 } 342 343 346 Key trans = transMap.get(returnValue); 347 if(trans == null) 348 return returnValue; 349 else 350 return trans; 351 } 352 } 354 365 public static Key parseKey(String keyStroke) 366 { 367 if(keyStroke == null) 368 return null; 369 int index = keyStroke.indexOf('+'); 370 int modifiers = 0; 371 if(index != -1) 372 { 373 for(int i = 0; i < index; i++) 374 { 375 switch(Character.toUpperCase(keyStroke 376 .charAt(i))) 377 { 378 case 'A': 379 modifiers |= a; 380 break; 381 case 'C': 382 modifiers |= c; 383 break; 384 case 'M': 385 modifiers |= m; 386 break; 387 case 'S': 388 modifiers |= s; 389 break; 390 } 391 } 392 } 393 String key = keyStroke.substring(index + 1); 394 if(key.length() == 1) 395 { 396 return new Key(modifiersToString(modifiers),0,key.charAt(0)); 397 } 398 else if(key.length() == 0) 399 { 400 Log.log(Log.ERROR,KeyEventTranslator.class, 401 "Invalid key stroke: " + keyStroke); 402 return null; 403 } 404 else if(key.equals("SPACE")) 405 { 406 return new Key(modifiersToString(modifiers),0,' '); 407 } 408 else 409 { 410 int ch; 411 412 try 413 { 414 ch = KeyEvent.class.getField("VK_".concat(key)) 415 .getInt(null); 416 } 417 catch(Exception e) 418 { 419 Log.log(Log.ERROR,KeyEventTranslator.class, 420 "Invalid key stroke: " 421 + keyStroke); 422 return null; 423 } 424 425 return new Key(modifiersToString(modifiers),ch,'\0'); 426 } 427 } 429 454 public static void setModifierMapping(int c, int a, int m, int s) 455 { 456 457 int duplicateMapping = 458 (c & a) | (c & m) | (c & s) | (a & m) | (a & s) | (m & s); 459 460 if((duplicateMapping & InputEvent.CTRL_MASK) != 0) { 461 throw new IllegalArgumentException ( 462 "CTRL is mapped to more than one modifier"); 463 } 464 if((duplicateMapping & InputEvent.ALT_MASK) != 0) { 465 throw new IllegalArgumentException ( 466 "ALT is mapped to more than one modifier"); 467 } 468 if((duplicateMapping & InputEvent.META_MASK) != 0) { 469 throw new IllegalArgumentException ( 470 "META is mapped to more than one modifier"); 471 } 472 if((duplicateMapping & InputEvent.SHIFT_MASK) != 0) { 473 throw new IllegalArgumentException ( 474 "SHIFT is mapped to more than one modifier"); 475 } 476 477 KeyEventTranslator.c = c; 478 KeyEventTranslator.a = a; 479 KeyEventTranslator.m = m; 480 KeyEventTranslator.s = s; 481 } 483 492 public static char getSymbolicModifierName(int mod) 493 { 494 if((mod & c) != 0) 495 return 'C'; 496 else if((mod & a) != 0) 497 return 'A'; 498 else if((mod & m) != 0) 499 return 'M'; 500 else if((mod & s) != 0) 501 return 'S'; 502 else 503 return '\0'; 504 } 506 private static final int[] MODS = { 508 InputEvent.CTRL_MASK, 509 InputEvent.ALT_MASK, 510 InputEvent.META_MASK, 511 InputEvent.SHIFT_MASK 512 }; 513 514 public static String modifiersToString(int mods) 515 { 516 StringBuffer buf = null; 517 518 for(int i = 0; i < MODS.length; i++) 519 { 520 if((mods & MODS[i]) != 0) 521 buf = lazyAppend(buf,getSymbolicModifierName(MODS[i])); 522 } 523 524 if(buf == null) 525 return null; 526 else 527 return buf.toString(); 528 } 530 539 public static String getModifierString(InputEvent evt) 540 { 541 StringBuilder buf = new StringBuilder (); 542 if(evt.isControlDown()) 543 buf.append(getSymbolicModifierName(InputEvent.CTRL_MASK)); 544 if(evt.isAltDown()) 545 buf.append(getSymbolicModifierName(InputEvent.ALT_MASK)); 546 if(evt.isMetaDown()) 547 buf.append(getSymbolicModifierName(InputEvent.META_MASK)); 548 if(evt.isShiftDown()) 549 buf.append(getSymbolicModifierName(InputEvent.SHIFT_MASK)); 550 return buf.length() == 0 ? null : buf.toString(); 551 } 553 static int c, a, m, s; 554 555 557 private static final Map<Key, Key> transMap = new HashMap<Key, Key>(); 558 559 private static StringBuffer lazyAppend(StringBuffer buf, char ch) 560 { 561 if(buf == null) 562 buf = new StringBuffer (); 563 if(buf.indexOf(String.valueOf(ch)) == -1) 564 buf.append(ch); 565 return buf; 566 } 568 static 569 { 570 if(OperatingSystem.isMacOS()) 571 { 572 setModifierMapping( 573 InputEvent.META_MASK, 574 InputEvent.CTRL_MASK, 575 576 InputEvent.ALT_MASK, 577 InputEvent.SHIFT_MASK ); 578 } 579 else 580 { 581 setModifierMapping( 582 InputEvent.CTRL_MASK, 583 InputEvent.ALT_MASK, 584 InputEvent.META_MASK, 585 InputEvent.SHIFT_MASK); 586 } 587 } 589 public static class Key 591 { 592 public final String modifiers; 593 public final int key; 594 public final char input; 595 596 private final int hashCode; 597 600 protected boolean isFromGlobalContext; 601 602 608 protected boolean isPhantom; 609 610 public Key(String modifiers, int key, char input) 611 { 612 this.modifiers = modifiers; 613 this.key = key; 614 this.input = input; 615 hashCode = key + input; 616 } 617 618 public int hashCode() 619 { 620 return hashCode; 621 } 622 623 public boolean equals(Object o) 624 { 625 if(o instanceof Key) 626 { 627 Key k = (Key)o; 628 if(StandardUtilities.objectsEqual(modifiers, 629 k.modifiers) && key == k.key 630 && input == k.input) 631 { 632 return true; 633 } 634 } 635 636 return false; 637 } 638 639 public String toString() 640 { 641 return (modifiers == null ? "" : modifiers) 642 + '<' 643 + Integer.toString(key,16) 644 + ',' 645 + Integer.toString(input,16) 646 + '>'; 647 } 648 649 public void setIsFromGlobalContext(boolean to) { 650 isFromGlobalContext = to; 651 } 652 653 public boolean isFromGlobalContext() { 654 return isFromGlobalContext; 655 } 656 657 public void setIsPhantom(boolean to) { 658 isPhantom = to; 659 } 660 661 public boolean isPhantom() { 662 return isPhantom; 663 } 664 } } 666 | Popular Tags |