< 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 >