⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ekeymap.java

📁 A framework written in Java for implementing high-level and dynamic languages, compiling them into J
💻 JAVA
字号:
// Copyright (c) 2002  Per M.A. Bothner.// This is free software;  for terms and warranty disclaimer see ./COPYING.package gnu.jemacs.buffer;import gnu.lists.*;import gnu.math.IntNum;import gnu.text.Char;import gnu.mapping.*;import java.awt.event.KeyEvent;public class EKeymap extends gnu.kawa.util.RangeTableimplements gnu.mapping.Named{  public static final EKeymap[] empty = new EKeymap[0];  EKeymap[] parents = empty;  public static int PRESSED = 0x100;  public static int RELEASED = 0x200;  Object defaultBinding;  String name;  /** The magic key that indicates a (Emacs) meta prefix.   * I.e. we saw either an Escape or a meta modifier. */  public static final int  metaKey = '\033';  /** The Emacs global map. */  public static EKeymap globalKeymap = new EKeymap();  /** The Emacs global escape (meta) map. */  public static EKeymap metaKeymap = new EKeymap("ESC-map");  static  {    globalKeymap.setAction(metaKey, metaKeymap);  }  public static final int CTRL_MASK = java.awt.event.InputEvent.CTRL_MASK;  public static final int SHIFT_MASK = java.awt.event.InputEvent.SHIFT_MASK;  // Note ALT_MASK and META_MASK are shifted!  public static final int META_MASK = java.awt.event.InputEvent.ALT_MASK;  public static final int ALT_MASK = java.awt.event.InputEvent.META_MASK;  public EKeymap (String name)  {    this.name = name;  }  public EKeymap ()  {  }  public String getName()  {    return name;  }  public Object getSymbol ()  {    return name;  }  public void setName (String name)  {    this.name = name;  }  public final Object getDefaultBinding ()  {    return defaultBinding;  }  public void setDefaultBinding (Object value)  {    defaultBinding = value;  }  public static int getModifiers (int code)  {    return (code >> 16) & 0xFF;  }  public EKeymap[] getParents ()  {    return parents;  }  public void setParents (EKeymap[] parents)  {    this.parents = parents;  }  public void setParent (EKeymap parent)  {    if (parent == null)      this.parents = empty;    else      this.parents = new EKeymap[] { parent };  }  public EKeymap getParent ()  {    int num = parents.length;    if (num == 0)      return null;    if (num == 1)      return parents[0];    throw new Error("multiple parents - set getParents, not getParent");  }  public void setAction(int key, Object command)  {    set(key, command);  }  public Object get (int key, int modifiers, boolean acceptDefaults)  {    return get (key | (modifiers << 16), acceptDefaults);  }  protected Object get (int key, boolean acceptDefaults)  {    Object value = super.lookup(key, null);    if (value != null)      return value;    if (acceptDefaults && defaultBinding != null)      return defaultBinding;    int plen = parents.length;    for (int i = 0;  i <plen;  i++)      {	value = parents[i].get(key, acceptDefaults);	if (value != null)	  return value;      }    return null;  }  public String toString ()  {    StringBuffer sbuf = new StringBuffer(40);    sbuf.append("#<keymap ");    if (name != null)      {	sbuf.append(name);	sbuf.append(' ');      }    /*    sbuf.append("size ");    sbuf.append('?');    */    sbuf.append("0x");    sbuf.append(Integer.toHexString(System.identityHashCode(this)));    sbuf.append('>');    return sbuf.toString();  }  /** Get or create keymap associate with a prefix key in a given keymap. */  public EKeymap definePrefix(int key)  {    Object command = get(key, false);    Object cc = command;    Object x;    if (command == null)      {        EKeymap next = new EKeymap(null);        set(key, next);        return next;      }    command = Command.resolveSymbol(command);    if (command instanceof EKeymap)      return (EKeymap) command;    else      {        throw new Error("prefix command cannot override exiting action: "			+ cc+ " : "+cc.getClass()+" -> "+command+" key "+key+"="+toString(key)+" in "+this);      }  }  public void defineKey(Object keySpec, Object binding)  {    EKeymap keymap = this;    if (keySpec instanceof Sequence && ! (keySpec instanceof LList))      {        // Handle key sequence.	Sequence value = (Sequence) keySpec;        boolean hackMeta = keySpec instanceof FString;        int len = value.size();        for (int i = 0;  i < len; )          {            Object keyValue = value.get(i);            boolean sawMeta = false;            i++;	    int key = asKeyStroke(keyValue);	    if (key == 0)	      throw new Error("unknown keyspec: "+keyValue);	    if (hackMeta && key > 127 && key <= 255)	      {		sawMeta = true;		key = key - 128;	      }	    if ((getModifiers(key) & META_MASK) != 0)	      {		key = stripMeta(key);		sawMeta = true;	      }            if (sawMeta)              keymap = keymap.definePrefix(metaKey);            if (i < len)              keymap = keymap.definePrefix(key);            else              keymap.defineKey(key, binding);          }      }    else      {        // Handle single key.	int key = asKeyStroke(keySpec);	if (key == 0)	  throw new Error("unknown keyspec: "+keySpec);        defineKey(key, binding);      }  }  public void defineKey(int key, Object binding)  {    boolean sawMeta = false;    if ((getModifiers(key) & META_MASK) != 0)      {	key = stripMeta(key);	sawMeta = true;      }    EKeymap keymap = this;    if (sawMeta)      keymap = keymap.definePrefix(metaKey);    keymap.setAction(key, binding);  }  public static int asKeyStroke(char ch, int mods)  {    if (mods == SHIFT_MASK && Character.isLetter(ch))      {	ch = Character.toUpperCase(ch);	mods = 0;      }    if (ch < ' ')      {        mods |= CTRL_MASK|PRESSED;        ch = ch == '\0' ? ' ' : (char) ('@' + (ch & 31));      }    return ch | (mods << 16);  }  /** Map an Emacs key name to one of the KeyEVent VK_XXX codes.   * Returns VK_UNDEFINED if the name isn't recognized.   */  public static int getKeyForName (String name)  {    name = name.toLowerCase();    int len = name.length();    if (len == 0)      return KeyEvent.VK_UNDEFINED;    char c0 = name.charAt(0);    if (len == 1)      return c0;    switch (c0)      {       case 'b':	if (name == "backspace")       return KeyEvent.VK_BACK_SPACE;	break;      case 'd':	if (name == "delete")          return KeyEvent.VK_DELETE;	if (name == "down")            return KeyEvent.VK_DOWN;	break;      case 'e':	if (name == "enter")           return KeyEvent.VK_ENTER;	break;      case 'f':	if (len == 2)	  {	    char c1 = name.charAt(1);	    if (c1 > '0' && c1 <= '9')	      return KeyEvent.VK_F1 + c1 - '1';	  }	else if (len == 3 && name.charAt(0) == 'f')	  {	    int c1 = name.charAt(1);	    int c2 = name.charAt(2);	    if (c1 > '0' && c1 <= '9'		&& c2 > '0' && c2 <= '9'		&& (c1 = (c1 - '0') * 10 + (c2 - '0')) <= 24)	      {		if (c1 <= 12)		  return KeyEvent.VK_F10 + c2 - '0';		else		  return KeyEvent.VK_F13 + c1 - 13;	      }	  }	break;      case 'h':	if (name == "help")            return KeyEvent.VK_HELP;	break;      case 'k':	if (name == "kp-left")         return KeyEvent.VK_KP_LEFT;	else if (name == "kp-right")   return KeyEvent.VK_KP_RIGHT;	else if (name == "kp-up")      return KeyEvent.VK_KP_UP;	else if (name == "kp-down")    return KeyEvent.VK_KP_DOWN;	else if (name == "kp-delete")  return KeyEvent.VK_DELETE;	break;      case 'l':	if (name == "left")            return KeyEvent.VK_LEFT;	break;      case 'n':	if (name == "next")            return KeyEvent.VK_PAGE_DOWN;	break;      case 'p':	if (name == "prior")           return KeyEvent.VK_PAGE_UP;	break;      case 'r':	if (name == "enter")           return KeyEvent.VK_ENTER;	if (name == "return")          return '\r';	if (name == "right")           return KeyEvent.VK_RIGHT;	break;      case 't':	if (name == "tab")             return KeyEvent.VK_TAB;	break;      case 'u':	if (name == "up")              return KeyEvent.VK_UP;	break;      }    return KeyEvent.VK_UNDEFINED;  }  public static int asKeyStroke(Object key)  {    int m = 0;    while (key instanceof Pair)      {	Pair pair = (Pair) key;	if (pair.cdr == LList.Empty)	  key = pair.car;	else	  {	    Object car = pair.car;	    if (car instanceof Symbol)	      car = ((Symbol) car).getName();	    if (car == "control")	      m |= CTRL_MASK;	    if (car == "meta")	      m |= META_MASK;	    if (car == "shift")	      m |= SHIFT_MASK;	    if (car == "alt")	      m |= ALT_MASK;	    key = pair.cdr;	  }      }    if (key instanceof Char)      {	return asKeyStroke(((Char) key).charValue(), m);      }    if (key instanceof IntNum)      {	return asKeyStroke((char) ((IntNum) key).intValue(), m);      }    if (key instanceof String || key instanceof Symbol)      {	String name = key instanceof String ? (String) key	  : ((Symbol) key).getName();	if (name.length() == 1)	  {	    char ch = name.charAt(0);	    if (m == 0)	      return asKeyStroke((char) ch, 0);	    else	      {		ch = Character.toUpperCase(ch);		return asKeyStroke(ch, m);	      }	  }	int code = getKeyForName(name);	if (code == KeyEvent.VK_UNDEFINED)	  throw new Error("unknown key-name: "+name);	return code | ((m|PRESSED) << 16);      }    return 0; // FIXME toInt((KeyStroke) key);  }  public static int stripMeta(int key)  {    int mods = getModifiers(key);    if ((mods & META_MASK) == 0)      return key;    mods &= ~ META_MASK;    int code = key & 0xFFFF;    boolean onRelease = (key & (RELEASED << 16)) != 0;    if ((mods & ~SHIFT_MASK) != 0 || onRelease        || code > 127 || code < ' ')      return code | ((mods|RELEASED) << 16);    else      {        if (code >= 'A' && code <= 'Z'&& mods != SHIFT_MASK)          code = code + 'a' - 'A';        return code;      }  }  /**   * True for a KeyStroke if the default action should be to ignore it.   * For example, pressing a shift key should not be an action!   * We also have the complication that both KEY-PRESSED and KEY_TYPED   * events and we typically want to ignore one but not both.   * (If both are handled, we have problems with default actions, as   * well as when to abort a prefix sequence.  Swing does not have   * this problem because it does not have prefix sequences and hence state.)   */  public static boolean ignorable (int key)  {    if ((key & (RELEASED << 16)) != 0)      return true;    int mods = getModifiers(key);    // If there are no modifiers, and it's a normal non-control character,    // we prefer the KEY_TYPED (keyChar) event.    // Otherwise, we prefer the KEY_PRESSED (keyCode) event.    int code = key & 0xFFFF;    if ((key & (PRESSED << 16)) == 0)      { // It's a KEY_TYPED (keyChar) event.        char ch = (char) key;        return (ch < ' ' && ch != metaKey) || ch >= 127;      }    else      { // It's a KEY_PRESSED (keyCODE) event.        // Basically, in the case of KEY_PRESSED events that will        // map without loss of information into normal KEY_TYPED events,        // we prefer the KEY_TYPED events (as they don't depend on the        // keyboard layout).	if (code == KeyEvent.VK_CONTROL || code == KeyEvent.VK_SHIFT	    || code == KeyEvent.VK_ALT || code == KeyEvent.VK_META            || code == KeyEvent.VK_ESCAPE)	  return true;        return (mods & ~SHIFT_MASK) == 0	  && code >= KeyEvent.VK_SPACE && code < KeyEvent.VK_DELETE;      }  }  /*  public static String toString(KeyStroke key)  {    StringBuffer sbuf = new StringBuffer();    sbuf.append('[');    char ch = key.getKeyChar();    if (ch != '\0')      {        sbuf.append("char:'");        gnu.jemacs.lang.ELisp.readableChar(ch, sbuf, true);        sbuf.append("'");      }    int code = key.getKeyCode();    if (code != 0)      {        sbuf.append("code:");        sbuf.append(code);      }    int mods = key.getModifiers();    if (mods != 0)      {        sbuf.append(" mods:");        sbuf.append(mods);      }    if (key.isOnKeyRelease())      sbuf.append(" release");    sbuf.append(']');    return sbuf.toString();  }  */  public static String toString(int code)  {    StringBuffer sbuf = new StringBuffer();    sbuf.append('[');    if (((code >> 16) & (PRESSED|RELEASED)) == 0)      {        sbuf.append("char:'");        gnu.jemacs.lang.ELisp.readableChar((char) code, sbuf, true);        sbuf.append("'");      }    else      {        sbuf.append("code:");        sbuf.append(code & 0xFFFF);      }    int mods = (code >> 16) & 0xff;    if (mods != 0)      {        sbuf.append(" mods:");        sbuf.append(mods);      }    if ((code & (RELEASED << 16)) != 0)      sbuf.append(" release");    sbuf.append(']');    return sbuf.toString();  }  public Object  lookupKey(Sequence keys, boolean acceptDefaults)  {    int nKeys = keys.size();    int[] prefixKeys = new int[nKeys];    java.util.Enumeration enumKeys = keys.elements();    for (int i = 0;  enumKeys.hasMoreElements();  i++)      {        prefixKeys[i] = asKeyStroke(enumKeys.nextElement());      }    return lookupKey(prefixKeys, nKeys, 0, acceptDefaults);  }  public Object lookupKey(int[] prefixKeys, int nPrefix,			  int key, boolean acceptDefaults)  {    EKeymap keymap = this;    int nKeys = nPrefix + (key != 0 ? 1 : 0);    boolean pendingMeta = false;    if (nKeys == 0)     throw new Error("no keys");    for (int i = 0;  ; )      {        int key_i = i == nPrefix ? key : prefixKeys[i];        if (pendingMeta)          key_i |= ((META_MASK|PRESSED) << 16);        Object command = keymap.get(key_i, false);        Object metaCommand;        if (command == null            && (getModifiers(key_i) & META_MASK) != 0            && (metaCommand = keymap.get(metaKey, false)) instanceof EKeymap)          {            command = ((EKeymap) metaCommand).get(stripMeta(key_i), false);          }        i++;        if (command == null)          {            if (ignorable(key))            {              return EToolkit.getInstance().getIgnoreAction();            }            else	      return keymap.getDefaultBinding();          }        if (i == nKeys)          return command;	Object comm;	if (command instanceof String || command instanceof Symbol)	  command = Command.resolveSymbol(command);	if (command instanceof EKeymap)	  keymap = (EKeymap) command;	else	  return null;      }  }  /*   * For debugging    */  public static String show(int binary)   {    StringBuffer sb = new StringBuffer(Integer.toBinaryString(binary));    for (int i = 32 - sb.length() - 1; i >= 0; i--)      sb.insert(0, '0');    return sb.toString();  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -