< prev index next >
jdk/src/jdk.jline/share/classes/jdk/internal/jline/WindowsTerminal.java
Print this page
@@ -4,28 +4,27 @@
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* http://www.opensource.org/licenses/bsd-license.php
*/
-package jline;
+package jdk.internal.jline;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
-import jline.internal.Configuration;
-import jline.internal.Log;
-import org.fusesource.jansi.internal.WindowsSupport;
-import org.fusesource.jansi.internal.Kernel32;
-import static org.fusesource.jansi.internal.Kernel32.*;
-
-import static jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
-import static jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
-import static jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
-import static jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
-import static jline.internal.Preconditions.checkNotNull;
+import jdk.internal.jline.internal.Configuration;
+import jdk.internal.jline.internal.Log;
+//import org.fusesource.jansi.internal.WindowsSupport;
+//import org.fusesource.jansi.internal.Kernel32;
+//import static org.fusesource.jansi.internal.Kernel32.*;
+
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_ECHO_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_LINE_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_PROCESSED_INPUT;
+import static jdk.internal.jline.WindowsTerminal.ConsoleMode.ENABLE_WINDOW_INPUT;
/**
* Terminal implementation for Microsoft Windows. Terminal initialization in
* {@link #init} is accomplished by extracting the
* <em>jline_<i>version</i>.dll</em>, saving it to the system temporary
@@ -63,17 +62,19 @@
private int originalMode;
public WindowsTerminal() throws Exception {
super(true);
+ System.loadLibrary("jline");
}
@Override
public void init() throws Exception {
super.init();
- setAnsiSupported(Configuration.getBoolean(ANSI, true));
+// setAnsiSupported(Configuration.getBoolean(ANSI, true));
+ setAnsiSupported(false);
//
// FIXME: Need a way to disable direct console and sysin detection muck
//
@@ -196,116 +197,277 @@
Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")...");
return super.getOutputEncoding();
}
//
+ // Original code:
+ //
+// private int getConsoleMode() {
+// return WindowsSupport.getConsoleMode();
+// }
+//
+// private void setConsoleMode(int mode) {
+// WindowsSupport.setConsoleMode(mode);
+// }
+//
+// private byte[] readConsoleInput() {
+// // XXX does how many events to read in one call matter?
+// INPUT_RECORD[] events = null;
+// try {
+// events = WindowsSupport.readConsoleInput(1);
+// } catch (IOException e) {
+// Log.debug("read Windows console input error: ", e);
+// }
+// if (events == null) {
+// return new byte[0];
+// }
+// StringBuilder sb = new StringBuilder();
+// for (int i = 0; i < events.length; i++ ) {
+// KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
+// //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
+// if (keyEvent.keyDown) {
+// if (keyEvent.uchar > 0) {
+// // support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
+// // http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
+// final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
+// // Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
+// // otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
+// final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
+// if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
+// && ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
+// sb.append('\u001B'); // ESC
+// }
+//
+// sb.append(keyEvent.uchar);
+// continue;
+// }
+// // virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
+// // just add support for basic editing keys (no control state, no numpad keys)
+// String escapeSequence = null;
+// switch (keyEvent.keyCode) {
+// case 0x21: // VK_PRIOR PageUp
+// escapeSequence = "\u001B[5~";
+// break;
+// case 0x22: // VK_NEXT PageDown
+// escapeSequence = "\u001B[6~";
+// break;
+// case 0x23: // VK_END
+// escapeSequence = "\u001B[4~";
+// break;
+// case 0x24: // VK_HOME
+// escapeSequence = "\u001B[1~";
+// break;
+// case 0x25: // VK_LEFT
+// escapeSequence = "\u001B[D";
+// break;
+// case 0x26: // VK_UP
+// escapeSequence = "\u001B[A";
+// break;
+// case 0x27: // VK_RIGHT
+// escapeSequence = "\u001B[C";
+// break;
+// case 0x28: // VK_DOWN
+// escapeSequence = "\u001B[B";
+// break;
+// case 0x2D: // VK_INSERT
+// escapeSequence = "\u001B[2~";
+// break;
+// case 0x2E: // VK_DELETE
+// escapeSequence = "\u001B[3~";
+// break;
+// default:
+// break;
+// }
+// if (escapeSequence != null) {
+// for (int k = 0; k < keyEvent.repeatCount; k++) {
+// sb.append(escapeSequence);
+// }
+// }
+// } else {
+// // key up event
+// // support ALT+NumPad input method
+// if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
+// sb.append(keyEvent.uchar);
+// }
+// }
+// }
+// return sb.toString().getBytes();
+// }
+//
+// private int getConsoleOutputCodepage() {
+// return Kernel32.GetConsoleOutputCP();
+// }
+//
+// private int getWindowsTerminalWidth() {
+// return WindowsSupport.getWindowsTerminalWidth();
+// }
+//
+// private int getWindowsTerminalHeight() {
+// return WindowsSupport.getWindowsTerminalHeight();
+// }
+
+ //
// Native Bits
//
- private int getConsoleMode() {
- return WindowsSupport.getConsoleMode();
- }
+ private native int getConsoleMode();
- private void setConsoleMode(int mode) {
- WindowsSupport.setConsoleMode(mode);
- }
+ private native void setConsoleMode(int mode);
private byte[] readConsoleInput() {
- // XXX does how many events to read in one call matter?
- INPUT_RECORD[] events = null;
- try {
- events = WindowsSupport.readConsoleInput(1);
- } catch (IOException e) {
- Log.debug("read Windows console input error: ", e);
+ KEY_EVENT_RECORD keyEvent = readKeyEvent();
+
+ return convertKeys(keyEvent).getBytes();
}
- if (events == null) {
- return new byte[0];
+
+ public static String convertKeys(KEY_EVENT_RECORD keyEvent) {
+ if (keyEvent == null) {
+ return "";
}
+
StringBuilder sb = new StringBuilder();
- for (int i = 0; i < events.length; i++ ) {
- KEY_EVENT_RECORD keyEvent = events[i].keyEvent;
- //Log.trace(keyEvent.keyDown? "KEY_DOWN" : "KEY_UP", "key code:", keyEvent.keyCode, "char:", (long)keyEvent.uchar);
+
if (keyEvent.keyDown) {
if (keyEvent.uchar > 0) {
// support some C1 control sequences: ALT + [@-_] (and [a-z]?) => ESC <ascii>
// http://en.wikipedia.org/wiki/C0_and_C1_control_codes#C1_set
- final int altState = KEY_EVENT_RECORD.LEFT_ALT_PRESSED | KEY_EVENT_RECORD.RIGHT_ALT_PRESSED;
+ final int altState = KEY_EVENT_RECORD.ALT_PRESSED;
// Pressing "Alt Gr" is translated to Alt-Ctrl, hence it has to be checked that Ctrl is _not_ pressed,
// otherwise inserting of "Alt Gr" codes on non-US keyboards would yield errors
- final int ctrlState = KEY_EVENT_RECORD.LEFT_CTRL_PRESSED | KEY_EVENT_RECORD.RIGHT_CTRL_PRESSED;
+ final int ctrlState = KEY_EVENT_RECORD.CTRL_PRESSED;
+
+ boolean handled = false;
+
+ if ((keyEvent.controlKeyState & ctrlState) != 0) {
+ switch (keyEvent.keyCode) {
+ case 0x43: //Ctrl-C
+ sb.append("\003");
+ handled = true;
+ break;
+ }
+ }
+
+ if ((keyEvent.controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
+ switch (keyEvent.keyCode) {
+ case 0x09: //Shift-Tab
+ sb.append("\033\133\132");
+ handled = true;
+ break;
+ }
+ }
+
+ if (!handled) {
if (((keyEvent.uchar >= '@' && keyEvent.uchar <= '_') || (keyEvent.uchar >= 'a' && keyEvent.uchar <= 'z'))
&& ((keyEvent.controlKeyState & altState) != 0) && ((keyEvent.controlKeyState & ctrlState) == 0)) {
sb.append('\u001B'); // ESC
}
sb.append(keyEvent.uchar);
- continue;
}
+ } else {
// virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
// just add support for basic editing keys (no control state, no numpad keys)
String escapeSequence = null;
switch (keyEvent.keyCode) {
case 0x21: // VK_PRIOR PageUp
- escapeSequence = "\u001B[5~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~");
break;
case 0x22: // VK_NEXT PageDown
- escapeSequence = "\u001B[6~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~");
break;
case 0x23: // VK_END
- escapeSequence = "\u001B[4~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~");
break;
case 0x24: // VK_HOME
- escapeSequence = "\u001B[1~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~");
break;
case 0x25: // VK_LEFT
- escapeSequence = "\u001B[D";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD");
break;
case 0x26: // VK_UP
- escapeSequence = "\u001B[A";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA");
break;
case 0x27: // VK_RIGHT
- escapeSequence = "\u001B[C";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC");
break;
case 0x28: // VK_DOWN
- escapeSequence = "\u001B[B";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB");
break;
case 0x2D: // VK_INSERT
- escapeSequence = "\u001B[2~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~");
break;
case 0x2E: // VK_DELETE
- escapeSequence = "\u001B[3~";
+ escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[3~", "\u001B[3;%d~");
break;
default:
break;
}
if (escapeSequence != null) {
for (int k = 0; k < keyEvent.repeatCount; k++) {
sb.append(escapeSequence);
}
}
+ }
} else {
// key up event
// support ALT+NumPad input method
if (keyEvent.keyCode == 0x12/*VK_MENU ALT key*/ && keyEvent.uchar > 0) {
sb.append(keyEvent.uchar);
}
}
+ return sb.toString();
+ }
+
+ private static String escapeSequence(int controlKeyState, String noControlSequence, String withControlSequence) {
+ int controlNum = 1;
+
+ if ((controlKeyState & KEY_EVENT_RECORD.SHIFT_PRESSED) != 0) {
+ controlNum += 1;
+ }
+
+ if ((controlKeyState & KEY_EVENT_RECORD.ALT_PRESSED) != 0) {
+ controlNum += 2;
}
- return sb.toString().getBytes();
+
+ if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) {
+ controlNum += 4;
}
- private int getConsoleOutputCodepage() {
- return Kernel32.GetConsoleOutputCP();
+ if (controlNum > 1) {
+ return String.format(withControlSequence, controlNum);
+ } else {
+ return noControlSequence;
}
+ }
+
+ private native KEY_EVENT_RECORD readKeyEvent();
- private int getWindowsTerminalWidth() {
- return WindowsSupport.getWindowsTerminalWidth();
+ public static class KEY_EVENT_RECORD {
+ public final static int ALT_PRESSED = 0x3;
+ public final static int CTRL_PRESSED = 0xC;
+ public final static int SHIFT_PRESSED = 0x10;
+ public final boolean keyDown;
+ public final char uchar;
+ public final int controlKeyState;
+ public final int keyCode;
+ public final int repeatCount;
+
+ public KEY_EVENT_RECORD(boolean keyDown, char uchar, int controlKeyState, int keyCode, int repeatCount) {
+ this.keyDown = keyDown;
+ this.uchar = uchar;
+ this.controlKeyState = controlKeyState;
+ this.keyCode = keyCode;
+ this.repeatCount = repeatCount;
}
- private int getWindowsTerminalHeight() {
- return WindowsSupport.getWindowsTerminalHeight();
}
+ private native int getConsoleOutputCodepage();
+
+ private native int getWindowsTerminalWidth();
+
+ private native int getWindowsTerminalHeight();
+
/**
* Console mode
* <p/>
* Constants copied <tt>wincon.h</tt>.
*/
< prev index next >