📄 keycode_filebased.java
字号:
/* KeyCode_FileBased.java
* Component: ProperJavaRDP
*
* Revision: $Revision: 1.4 $
* Author: $Author: telliott $
* Date: $Date: 2005/09/27 14:15:39 $
*
* Copyright (c) 2005 Propero Limited
*
* Purpose: Read and supply keymapping information
* from a file
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
* (See gpl.txt for details of the GNU General Public License.)
*
*/
package net.propero.rdp.keymapping;
import java.awt.event.KeyEvent;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.Vector;
import net.propero.rdp.Input;
import net.propero.rdp.Options;
import org.apache.log4j.Logger;
public abstract class KeyCode_FileBased {
private Hashtable keysCurrentlyDown = new Hashtable();
private KeyEvent lastKeyEvent = null;
private boolean lastEventMatched = false;
protected static Logger logger = Logger.getLogger(Input.class);
public static final int SCANCODE_EXTENDED = 0x80;
public static final int DOWN = 1;
public static final int UP = 0;
public static final int QUIETUP = 2;
public static final int QUIETDOWN = 3;
private int mapCode = -1;
private boolean altQuiet = false;
public boolean useLockingKeyState = true;
public boolean capsLockDown = false;
Vector keyMap = new Vector();
private void updateCapsLock(KeyEvent e) {
}
public KeyCode_FileBased(InputStream fstream) throws KeyMapException{
readMapFile(fstream);
}
/**
* Constructor for a keymap generated from a specified file, formatted in
* the manner of a file generated by the writeToFile method
*
* @param keyMapFile
* File containing keymap data
*/
public KeyCode_FileBased(String keyMapFile) throws KeyMapException {
// logger.info("String called keycode reader");
int lineNum = 0; // current line number being parsed
String line = ""; // contents of line being parsed
boolean mapCodeSet = false;
FileInputStream fstream;
try {
fstream = new FileInputStream(keyMapFile);
readMapFile(fstream);
} catch (FileNotFoundException e) {
throw new KeyMapException("KeyMap file not found: " + keyMapFile);
}
}
/**
* Read in a keymap definition file and add mappings to internal keymap
* @param fstream Stream connected to keymap file
* @throws KeyMapException
*/
public void readMapFile(InputStream fstream) throws KeyMapException {
// logger.info("Stream-based keycode reader");
int lineNum = 0; // current line number being parsed
String line = ""; // contents of line being parsed
if (fstream == null)
throw new KeyMapException("Could not find specified keymap file");
boolean mapCodeSet = false;
try {
DataInputStream in = new DataInputStream(fstream);
if (in == null)
logger.warn("in == null");
while (in.available() != 0) {
lineNum++;
line = in.readLine();
char fc = 0x0;
if ((line != null) && (line.length() > 0))
fc = line.charAt(0);
// ignore blank and commented lines
if ((line != null) && (line.length() > 0) && (fc != '#') && (fc != 'c')) {
keyMap.add(new MapDef(line)); // parse line into a MapDef
// object and add to list
} else if (fc == 'c') {
StringTokenizer st = new StringTokenizer(line);
String s = st.nextToken();
s = st.nextToken();
mapCode = Integer.decode(s).intValue();
mapCodeSet = true;
}
}
// Add a set of mappings for alphabet characters with ctrl and alt
// pressed
Vector newMap = new Vector();
Iterator i = keyMap.iterator();
while (i.hasNext()) {
MapDef current = (MapDef) i.next();
if (current.isCharacterDef() && !(current.isAltDown() || current.isCtrlDown() || current.isShiftDown() || current.isCapslockOn())) {
int code = getCodeFromAlphaChar(current.getKeyChar());
if (code > -1) {
newMap.add(new MapDef(code, 0, current.getScancode(),
true, false, false, false));
newMap.add(new MapDef(code, 0, current.getScancode(),
false, false, true, false));
}
}
}
// Commit added mapping definitions
keyMap.addAll(newMap);
in.close();
} catch (IOException e) {
throw new KeyMapException("File input error: " + e.getMessage());
} catch (NumberFormatException nfEx) {
throw new KeyMapException("" + nfEx.getMessage()
+ " is not numeric at line " + lineNum);
} catch (NoSuchElementException nseEx) {
throw new KeyMapException(
"Not enough parameters in definition at line " + lineNum);
} catch (KeyMapException kmEx) {
throw new KeyMapException("Error parsing keymap file: "
+ kmEx.getMessage() + " at line " + lineNum);
} catch (Exception e) {
logger.error(e.getClass().getName() + ": " + e.getMessage());
e.printStackTrace();
throw new KeyMapException(e.getClass().getName() + ": "
+ e.getMessage());
}
if (!mapCodeSet)
throw new KeyMapException("No map identifier found in file");
}
/**
* Given an alphanumeric character, return an AWT keycode
* @param keyChar Alphanumeric character
* @return AWT keycode representing input character, -1 if character not alphanumeric
*/
private int getCodeFromAlphaChar(char keyChar) {
if (('a' <= keyChar) && (keyChar <= 'z')) {
return KeyEvent.VK_A + keyChar - 'a';
}
if (('A' <= keyChar) && (keyChar <= 'Z')) {
return KeyEvent.VK_A + keyChar - 'A';
}
return -1;
}
/**
* Get the RDP code specifying the key map in use
* @return ID for current key map
*/
public int getMapCode() {
return mapCode;
}
/**
* Construct a list of changes to key states in order to correctly send the
* key action jointly defined by the supplied key event and mapping
* definition.
*
* @param e
* Key event received by Java (defining current state)
* @param theDef
* Key mapping to define desired keypress on server end
*/
public String stateChanges(KeyEvent e, MapDef theDef) {
String changes = "";
final int SHIFT = 0;
final int CTRL = 1;
final int ALT = 2;
final int CAPSLOCK = 3;
int BEFORE = 0;
int AFTER = 1;
boolean[][] state = new boolean[4][2];
state[SHIFT][BEFORE] = e.isShiftDown();
state[SHIFT][AFTER] = theDef.isShiftDown();
state[CTRL][BEFORE] = e.isControlDown() || e.isAltGraphDown();
state[CTRL][AFTER] = theDef.isCtrlDown();
state[ALT][BEFORE] = e.isAltDown() || e.isAltGraphDown();
state[ALT][AFTER] = theDef.isAltDown();
updateCapsLock(e);
state[CAPSLOCK][BEFORE] = capsLockDown;
state[CAPSLOCK][AFTER] = theDef.isCapslockOn();
if (e.getID() == KeyEvent.KEY_RELEASED) {
AFTER = 0;
BEFORE = 1;
}
if ((e == null) || (theDef == null) || (!theDef.isCharacterDef()))
return "";
String up = "" + ((char) UP);
String down = "" + ((char) DOWN);
String quietup = up;
String quietdown = down;
quietup = "" + ((char) QUIETUP);
quietdown = "" + ((char) QUIETDOWN);
if (state[SHIFT][BEFORE] != state[SHIFT][AFTER]) {
if (state[SHIFT][BEFORE])
changes += ((char) 0x2a) + up;
else
changes += ((char) 0x2a) + down;
}
if (state[CTRL][BEFORE] != state[CTRL][AFTER]) {
if (state[CTRL][BEFORE])
changes += ((char) 0x1d) + up;
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -