< prev index next >

jdk/src/jdk.jline/share/classes/jdk/internal/jline/WindowsTerminal.java

Print this page

        

*** 4,31 **** * 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; 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; /** * 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 --- 4,30 ---- * 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 jdk.internal.jline; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; ! 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,79 **** private int originalMode; public WindowsTerminal() throws Exception { super(true); } @Override public void init() throws Exception { super.init(); ! setAnsiSupported(Configuration.getBoolean(ANSI, true)); // // FIXME: Need a way to disable direct console and sysin detection muck // --- 62,80 ---- 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(false); // // FIXME: Need a way to disable direct console and sysin detection muck //
*** 196,311 **** Log.debug("can't figure out the Java Charset of this code page (" + codepage + ")..."); return super.getOutputEncoding(); } // // Native Bits // ! 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(); } /** * Console mode * <p/> * Constants copied <tt>wincon.h</tt>. */ --- 197,473 ---- 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 native int getConsoleMode(); ! private native void setConsoleMode(int mode); private byte[] readConsoleInput() { ! KEY_EVENT_RECORD keyEvent = readKeyEvent(); ! ! return convertKeys(keyEvent).getBytes(); } ! ! public static String convertKeys(KEY_EVENT_RECORD keyEvent) { ! if (keyEvent == null) { ! return ""; } + StringBuilder sb = new StringBuilder(); ! 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.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.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); } + } 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 = escapeSequence(keyEvent.controlKeyState, "\u001B[5~", "\u001B[5;%d~"); break; case 0x22: // VK_NEXT PageDown ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[6~", "\u001B[6;%d~"); break; case 0x23: // VK_END ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[4~", "\u001B[4;%d~"); break; case 0x24: // VK_HOME ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[1~", "\u001B[1;%d~"); break; case 0x25: // VK_LEFT ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[D", "\u001B[1;%dD"); break; case 0x26: // VK_UP ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[A", "\u001B[1;%dA"); break; case 0x27: // VK_RIGHT ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[C", "\u001B[1;%dC"); break; case 0x28: // VK_DOWN ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[B", "\u001B[1;%dB"); break; case 0x2D: // VK_INSERT ! escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[2~", "\u001B[2;%d~"); break; case 0x2E: // VK_DELETE ! 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; } ! ! if ((controlKeyState & KEY_EVENT_RECORD.CTRL_PRESSED) != 0) { ! controlNum += 4; } ! if (controlNum > 1) { ! return String.format(withControlSequence, controlNum); ! } else { ! return noControlSequence; } + } + + private native KEY_EVENT_RECORD readKeyEvent(); ! 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 native int getConsoleOutputCodepage(); + + private native int getWindowsTerminalWidth(); + + private native int getWindowsTerminalHeight(); + /** * Console mode * <p/> * Constants copied <tt>wincon.h</tt>. */
< prev index next >