--- a/src/jdk.internal.le/share/classes/jdk/internal/jline/WindowsTerminal.java Thu Sep 13 01:49:48 2018 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,617 +0,0 @@
-/*
- * Copyright (c) 2002-2016, the original author or authors.
- *
- * 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 java.io.OutputStream;
-
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.BufferState;
-import jdk.internal.jline.extra.AnsiInterpretingOutputStream.Performer;
-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
- * directoy (determined by the setting of the <em>java.io.tmpdir</em> System
- * property), loading the library, and then calling the Win32 APIs <a
- * href="http://msdn.microsoft.com/library/default.asp?
- * url=/library/en-us/dllproc/base/setconsolemode.asp">SetConsoleMode</a> and
- * <a href="http://msdn.microsoft.com/library/default.asp?
- * url=/library/en-us/dllproc/base/getconsolemode.asp">GetConsoleMode</a> to
- * disable character echoing.
- * <p/>
- * <p>
- * By default, the {@link #wrapInIfNeeded(java.io.InputStream)} method will attempt
- * to test to see if the specified {@link InputStream} is {@link System#in} or a wrapper
- * around {@link FileDescriptor#in}, and if so, will bypass the character reading to
- * directly invoke the readc() method in the JNI library. This is so the class
- * can read special keys (like arrow keys) which are otherwise inaccessible via
- * the {@link System#in} stream. Using JNI reading can be bypassed by setting
- * the <code>jline.WindowsTerminal.directConsole</code> system property
- * to <code>false</code>.
- * </p>
- *
- * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
- * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
- * @since 2.0
- */
-public class WindowsTerminal
- extends TerminalSupport
-{
- public static final String DIRECT_CONSOLE = WindowsTerminal.class.getName() + ".directConsole";
-
- public static final String ANSI = WindowsTerminal.class.getName() + ".ansi";
-
- private boolean directConsole;
-
- private int originalMode;
-
- public WindowsTerminal() throws Exception {
- super(true);
- }
-
- @Override
- public void init() throws Exception {
- super.init();
-
-// setAnsiSupported(Configuration.getBoolean(ANSI, true));
- setAnsiSupported(true);
-
- //
- // FIXME: Need a way to disable direct console and sysin detection muck
- //
-
- setDirectConsole(Configuration.getBoolean(DIRECT_CONSOLE, true));
-
- this.originalMode = getConsoleMode();
- setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT.code);
- setEchoEnabled(false);
- }
-
- /**
- * Restore the original terminal configuration, which can be used when
- * shutting down the console reader. The ConsoleReader cannot be
- * used after calling this method.
- */
- @Override
- public void restore() throws Exception {
- // restore the old console mode
- setConsoleMode(originalMode);
- super.restore();
- }
-
- @Override
- public int getWidth() {
- int w = getWindowsTerminalWidth();
- return w < 1 ? DEFAULT_WIDTH : w;
- }
-
- @Override
- public int getHeight() {
- int h = getWindowsTerminalHeight();
- return h < 1 ? DEFAULT_HEIGHT : h;
- }
-
- @Override
- public void setEchoEnabled(final boolean enabled) {
- // Must set these four modes at the same time to make it work fine.
- if (enabled) {
- setConsoleMode(getConsoleMode() |
- ENABLE_ECHO_INPUT.code |
- ENABLE_LINE_INPUT.code |
- ENABLE_WINDOW_INPUT.code);
- }
- else {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_LINE_INPUT.code |
- ENABLE_ECHO_INPUT.code |
- ENABLE_WINDOW_INPUT.code));
- }
- super.setEchoEnabled(enabled);
- }
-
- public void disableInterruptCharacter() {
- setConsoleMode(getConsoleMode() &
- ~(ENABLE_PROCESSED_INPUT.code));
- }
-
- public void enableInterruptCharacter() {
- setConsoleMode(getConsoleMode() |
- ENABLE_PROCESSED_INPUT.code);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public void setDirectConsole(final boolean flag) {
- this.directConsole = flag;
- Log.debug("Direct console: ", flag);
- }
-
- /**
- * Whether or not to allow the use of the JNI console interaction.
- */
- public Boolean getDirectConsole() {
- return directConsole;
- }
-
-
- @Override
- public InputStream wrapInIfNeeded(InputStream in) throws IOException {
- if (directConsole && isSystemIn(in)) {
- return new InputStream() {
- private byte[] buf = null;
- int bufIdx = 0;
-
- @Override
- public int read() throws IOException {
- while (buf == null || bufIdx == buf.length) {
- buf = readConsoleInput();
- bufIdx = 0;
- }
- int c = buf[bufIdx] & 0xFF;
- bufIdx++;
- return c;
- }
- };
- } else {
- return super.wrapInIfNeeded(in);
- }
- }
-
- protected boolean isSystemIn(final InputStream in) throws IOException {
- if (in == null) {
- return false;
- }
- else if (in == System.in) {
- return true;
- }
- else if (in instanceof FileInputStream && ((FileInputStream) in).getFD() == FileDescriptor.in) {
- return true;
- }
-
- return false;
- }
-
- @Override
- public OutputStream wrapOutIfNeeded(OutputStream out) {
- return new AnsiInterpretingOutputStream(getOutputEncoding(), out, new Performer() {
- @Override
- public BufferState getBufferState() throws IOException {
- out.flush();
- return WindowsTerminal.this.getBufferState();
- }
- @Override
- public void setCursorPosition(int cursorX, int cursorY) throws IOException {
- out.flush();
- WindowsTerminal.this.setCursorPosition(cursorX, cursorY);
- }
- });
- }
-
- @Override
- public String getOutputEncoding() {
- int codepage = getConsoleOutputCodepage();
- //http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
- String charsetMS = "ms" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetMS)) {
- return charsetMS;
- }
- String charsetCP = "cp" + codepage;
- if (java.nio.charset.Charset.isSupported(charsetCP)) {
- return charsetCP;
- }
- 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
- //
- static {
- System.loadLibrary("le");
- initIDs();
- }
-
- private static native void initIDs();
-
- protected native int getConsoleMode();
-
- protected 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
- // xterm escape codes: E. Moy, S. Gildea and T. Dickey, "XTerm Control Sequences":
- // http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
- // http://xorg.freedesktop.org/releases/X11R6.8.1/PDF/ctlseqs.pdf
- // just add support for basic editing keys and function 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;
- case 0x70: // VK_F1
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOP", "\u001BO%dP");
- break;
- case 0x71: // VK_F2
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOQ", "\u001BO%dQ");
- break;
- case 0x72: // VK_F3
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOR", "\u001BO%dR");
- break;
- case 0x73: // VK_F4
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001BOS", "\u001BO%dS");
- break;
- case 0x74: // VK_F5
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[15~", "\u001B[15;%d~");
- break;
- case 0x75: // VK_F6
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[17~", "\u001B[17;%d~");
- break;
- case 0x76: // VK_F7
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[18~", "\u001B[18;%d~");
- break;
- case 0x77: // VK_F8
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[19~", "\u001B[19;%d~");
- break;
- case 0x78: // VK_F9
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[20~", "\u001B[20;%d~");
- break;
- case 0x79: // VK_F10
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[21~", "\u001B[21;%d~");
- break;
- case 0x7A: // VK_F11
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[23~", "\u001B[23;%d~");
- break;
- case 0x7B: // VK_F12
- escapeSequence = escapeSequence(keyEvent.controlKeyState, "\u001B[24~", "\u001B[24;%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();
-
- private native BufferState getBufferState();
-
- private native void setCursorPosition(int x, int y);
-
- /**
- * Console mode
- * <p/>
- * Constants copied <tt>wincon.h</tt>.
- */
- public static enum ConsoleMode
- {
- /**
- * The ReadFile or ReadConsole function returns only when a carriage return
- * character is read. If this mode is disable, the functions return when one
- * or more characters are available.
- */
- ENABLE_LINE_INPUT(2),
-
- /**
- * Characters read by the ReadFile or ReadConsole function are written to
- * the active screen buffer as they are read. This mode can be used only if
- * the ENABLE_LINE_INPUT mode is also enabled.
- */
- ENABLE_ECHO_INPUT(4),
-
- /**
- * CTRL+C is processed by the system and is not placed in the input buffer.
- * If the input buffer is being read by ReadFile or ReadConsole, other
- * control keys are processed by the system and are not returned in the
- * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also
- * enabled, backspace, carriage return, and linefeed characters are handled
- * by the system.
- */
- ENABLE_PROCESSED_INPUT(1),
-
- /**
- * User interactions that change the size of the console screen buffer are
- * reported in the console's input buffee. Information about these events
- * can be read from the input buffer by applications using
- * theReadConsoleInput function, but not by those using ReadFile
- * orReadConsole.
- */
- ENABLE_WINDOW_INPUT(8),
-
- /**
- * If the mouse pointer is within the borders of the console window and the
- * window has the keyboard focus, mouse events generated by mouse movement
- * and button presses are placed in the input buffer. These events are
- * discarded by ReadFile or ReadConsole, even when this mode is enabled.
- */
- ENABLE_MOUSE_INPUT(16),
-
- /**
- * When enabled, text entered in a console window will be inserted at the
- * current cursor location and all text following that location will not be
- * overwritten. When disabled, all following text will be overwritten. An OR
- * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS
- * flag to enable this functionality.
- */
- ENABLE_PROCESSED_OUTPUT(1),
-
- /**
- * This flag enables the user to use the mouse to select and edit text. To
- * enable this option, use the OR to combine this flag with
- * ENABLE_EXTENDED_FLAGS.
- */
- ENABLE_WRAP_AT_EOL_OUTPUT(2),;
-
- public final int code;
-
- ConsoleMode(final int code) {
- this.code = code;
- }
- }
-
-}