From f78835c6e224c1c1607cfb618ddbe8defe7723e8 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 10 Oct 2023 09:30:00 +0200 Subject: [PATCH 1/2] New JNI provider --- README.md | 3 + demo/pom.xml | 4 + jline/pom.xml | 21 + native/Makefile | 13 +- native/Makefile.common | 21 +- .../main/java/org/jline/nativ/CLibrary.java | 144 +++ .../main/java/org/jline/nativ/Kernel32.java | 533 ++++++++++ native/src/main/native/clibrary.c | 241 +++++ native/src/main/native/kernel32.c | 974 ++++++++++++++++++ .../jline/nativ/FreeBSD/x86/libjlinenative.so | Bin 4612 -> 8945 bytes .../nativ/FreeBSD/x86_64/libjlinenative.so | Bin 6376 -> 11637 bytes .../jline/nativ/Linux/arm/libjlinenative.so | Bin 7744 -> 20996 bytes .../jline/nativ/Linux/arm64/libjlinenative.so | Bin 8696 -> 14232 bytes .../jline/nativ/Linux/armv6/libjlinenative.so | Bin 8440 -> 14056 bytes .../jline/nativ/Linux/armv7/libjlinenative.so | Bin 7764 -> 13384 bytes .../jline/nativ/Linux/ppc64/libjlinenative.so | Bin 69760 -> 72000 bytes .../jline/nativ/Linux/x86/libjlinenative.so | Bin 14892 -> 16304 bytes .../nativ/Linux/x86_64/libjlinenative.so | Bin 8120 -> 13688 bytes .../nativ/Mac/arm64/libjlinenative.jnilib | Bin 16994 -> 51666 bytes .../jline/nativ/Mac/x86/libjlinenative.jnilib | Bin 8460 -> 13720 bytes .../nativ/Mac/x86_64/libjlinenative.jnilib | Bin 4408 -> 14228 bytes .../nativ/Windows/arm64/libjlinenative.so | Bin 0 -> 81920 bytes .../jline/nativ/Windows/x86/jlinenative.dll | Bin 86665 -> 114585 bytes .../nativ/Windows/x86_64/jlinenative.dll | Bin 102429 -> 129577 bytes pom.xml | 7 + .../terminal/impl/ExternalTerminalTest.java | 13 - terminal-jni/pom.xml | 62 ++ .../jline/terminal/impl/jni/JniNativePty.java | 218 ++++ .../impl/jni/JniTerminalProvider.java | 161 +++ .../impl/jni/freebsd/FreeBsdNativePty.java | 357 +++++++ .../impl/jni/linux/LinuxNativePty.java | 393 +++++++ .../terminal/impl/jni/osx/OsXNativePty.java | 386 +++++++ .../impl/jni/solaris/SolarisNativePty.java | 406 ++++++++ .../impl/jni/win/NativeWinConsoleWriter.java | 31 + .../impl/jni/win/NativeWinSysTerminal.java | 309 ++++++ .../impl/jni/win/WindowsAnsiWriter.java | 386 +++++++ .../native-image.properties | 1 + .../jline-terminal-jni/reflection-config.json | 11 + .../jline-terminal-jni/resource-config.json | 5 + .../services/org/jline/terminal/provider/jni | 16 + .../org/jline/terminal/TerminalBuilder.java | 16 +- .../java/org/jline/terminal/impl/Diag.java | 10 + 42 files changed, 4703 insertions(+), 39 deletions(-) create mode 100644 native/src/main/java/org/jline/nativ/CLibrary.java create mode 100644 native/src/main/java/org/jline/nativ/Kernel32.java create mode 100644 native/src/main/native/clibrary.c create mode 100644 native/src/main/native/kernel32.c create mode 100755 native/src/main/resources/org/jline/nativ/Windows/arm64/libjlinenative.so create mode 100644 terminal-jni/pom.xml create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniNativePty.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniTerminalProvider.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/freebsd/FreeBsdNativePty.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/linux/LinuxNativePty.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/osx/OsXNativePty.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/solaris/SolarisNativePty.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinConsoleWriter.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinSysTerminal.java create mode 100644 terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/WindowsAnsiWriter.java create mode 100644 terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/native-image.properties create mode 100644 terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/reflection-config.json create mode 100644 terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/resource-config.json create mode 100644 terminal-jni/src/main/resources/META-INF/services/org/jline/terminal/provider/jni diff --git a/README.md b/README.md index 79d04cad5..0e053b456 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,10 @@ The dependencies are minimal: you may use JLine without any dependency on *nix s You can also use fine grained jars: * `jline-terminal`: the `Terminal` api and implementations * `jline-terminal-jansi`: terminal implementations leveraging the `Jansi` library +* `jline-terminal-jni`: terminal implementations leveraging the JNI native library * `jline-terminal-jna`: terminal implementations leveraging the `JNA` library +* `jline-terminal-ffm`: terminal implementations leveraging the Foreign Functions & Mapping layer +* `jline-native`: the native library * `jline-reader`: the line reader (including completion, history, etc...) * `jline-style`: styling api * `jline-remote-ssh`: helpers for using jline with [Mina SSHD](http://mina.apache.org/sshd-project/) diff --git a/demo/pom.xml b/demo/pom.xml index 9c7ca7eea..8eb6eb17a 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -31,6 +31,10 @@ org.jline jline-terminal-ffm + + org.jline + jline-terminal-jni + org.jline jline-terminal-jansi diff --git a/jline/pom.xml b/jline/pom.xml index c10bd7fa8..ef47dae02 100644 --- a/jline/pom.xml +++ b/jline/pom.xml @@ -68,6 +68,11 @@ jline-terminal test + + org.jline + jline-terminal-jni + test + org.jline jline-terminal-jansi @@ -139,6 +144,14 @@ false ${project.build.directory}/generated-sources + + org.jline + jline-terminal-jni + sources + jar + false + ${project.build.directory}/generated-sources + org.jline jline-terminal-jansi @@ -213,6 +226,14 @@ ${project.build.directory}/generated-resources **/*.class + + org.jline + jline-terminal-jni + jar + false + ${project.build.directory}/generated-resources + **/*.class + org.jline jline-terminal-jansi diff --git a/native/Makefile b/native/Makefile index 08b450541..46e7eb8c5 100644 --- a/native/Makefile +++ b/native/Makefile @@ -23,6 +23,7 @@ linux-armv6-digest:=@sha256:7bad6ab302af34bdf6634c8c2b02c8dc6ac932c67da9ecc199c5 linux-x86-digest:=:latest windows-static-x86-digest:=@sha256:99d7069789560ef77a7504ead4a2b5e3c245cb45a45f964c74fecbf649398d3a windows-static-x64-digest:=@sha256:f159861bc80b29e5dafb223477167bec53ecec6cdacb051d31e90c5823542100 +windows-arm64-digest:=@sha256:f4b3c1a49ec8b53418cef1499dc3f9a54a5570b7a3ecdf42fc8c83eb94b01b7d cross-build-digest:=@sha256:8dbaa86462270db93ae1b1b319bdd88d89272faf3a68632daf4fa36b414a326e freebsd-crossbuild-digest:=@sha256:cda62697a15d8bdc0bc26e780b1771ee78f12c55e7d5813e62c478af5a747c43 mcandre-snek-digest:=@sha256:9f84e9fcdf66daafc1f1c3fb772a6c97977714e17800aeac2e3bbe5dc5039dd0 @@ -68,9 +69,9 @@ $(JLINENATIVE_OUT)/%.o: src/main/native/%.c ifeq ($(OS_NAME), Windows) $(JLINENATIVE_OUT)/$(LIBNAME): ducible endif -$(JLINENATIVE_OUT)/$(LIBNAME): $(JLINENATIVE_OUT)/jlinenative.o +$(JLINENATIVE_OUT)/$(LIBNAME): $(JLINENATIVE_OUT)/jlinenative.o $(JLINENATIVE_OUT)/clibrary.o $(JLINENATIVE_OUT)/kernel32.o @mkdir -p $(@D) - $(CC) $(CCFLAGS) -o $@ $(JLINENATIVE_OUT)/jlinenative.o $(LINKFLAGS) + $(CC) $(CCFLAGS) -o $@ $(JLINENATIVE_OUT)/jlinenative.o $(JLINENATIVE_OUT)/clibrary.o $(JLINENATIVE_OUT)/kernel32.o $(LINKFLAGS) ifeq ($(OS_NAME), Windows) target/ducible/ducible $(JLINENATIVE_OUT)/$(LIBNAME) endif @@ -82,7 +83,7 @@ NATIVE_DLL:=$(NATIVE_DIR)/$(LIBNAME) # For cross-compilation, install docker. See also https://github.com/dockcross/dockcross # Disabled linux-armv6 build because of this issue; https://github.com/dockcross/dockcross/issues/190 native-all: linux-x86 linux-x86_64 linux-arm linux-armv6 linux-armv7 \ - linux-arm64 linux-ppc64 win-x86 win-x86_64 mac-x86 mac-x86_64 mac-arm64 freebsd-x86 freebsd-x86_64 + linux-arm64 linux-ppc64 win-x86 win-x86_64 win-arm64 mac-x86 mac-x86_64 mac-arm64 freebsd-x86 freebsd-x86_64 native: $(NATIVE_DLL) @@ -139,6 +140,12 @@ target/dockcross/dockcross-windows-static-x64: dockcross win-x86_64: download-includes target/dockcross/dockcross-windows-static-x64 target/dockcross/dockcross-windows-static-x64 bash -c 'make clean-native native CROSS_PREFIX=x86_64-w64-mingw32.static- OS_NAME=Windows OS_ARCH=x86_64' +target/dockcross/dockcross-windows-arm64: dockcross + docker run --rm dockcross/windows-arm64$(windows-arm64-digest) > target/dockcross/dockcross-windows-arm64 + chmod +x target/dockcross/dockcross-windows-arm64 +win-arm64: download-includes target/dockcross/dockcross-windows-arm64 + target/dockcross/dockcross-windows-arm64 bash -c 'make clean-native native CROSS_PREFIX=aarch64-w64-mingw32- OS_NAME=Windows OS_ARCH=arm64' + mac-x86: download-includes docker run -it --rm -v $$PWD:/workdir --user $$(id -u):$$(id -g) \ -e CROSS_TRIPLE=i386-apple-darwin multiarch/crossbuild$(cross-build-digest) make clean-native native OS_NAME=Mac OS_ARCH=x86 diff --git a/native/Makefile.common b/native/Makefile.common index fdc17ff86..b4b12e5bd 100644 --- a/native/Makefile.common +++ b/native/Makefile.common @@ -32,105 +32,90 @@ Default_STRIP := $(CROSS_PREFIX)strip Default_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -fvisibility=hidden Default_LINKFLAGS := -shared Default_LIBNAME := libjlinenative.so -Default_JANSI_FLAGS := Linux-x86_CC := $(CROSS_PREFIX)gcc Linux-x86_STRIP := $(CROSS_PREFIX)strip Linux-x86_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -m32 -fvisibility=hidden Linux-x86_LINKFLAGS := -shared -static-libgcc Linux-x86_LIBNAME := libjlinenative.so -Linux-x86_JANSI_FLAGS := Linux-x86_64_CC := $(CROSS_PREFIX)gcc Linux-x86_64_STRIP := $(CROSS_PREFIX)strip Linux-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -m64 -fvisibility=hidden Linux-x86_64_LINKFLAGS := -shared -static-libgcc Linux-x86_64_LIBNAME := libjlinenative.so -Linux-x86_64_JANSI_FLAGS := Linux-arm_CC := $(CROSS_PREFIX)gcc Linux-arm_STRIP := $(CROSS_PREFIX)strip Linux-arm_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -mfloat-abi=softfp -mfpu=vfp -fvisibility=hidden Linux-arm_LINKFLAGS := -shared -static-libgcc Linux-arm_LIBNAME := libjlinenative.so -Linux-arm_JANSI_FLAGS := Linux-armv6_CC := $(CROSS_PREFIX)gcc Linux-armv6_STRIP := $(CROSS_PREFIX)strip Linux-armv6_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -mfloat-abi=hard -mfpu=vfp -fPIC -fvisibility=hidden Linux-armv6_LINKFLAGS := -shared -static-libgcc Linux-armv6_LIBNAME := libjlinenative.so -Linux-armv6_JANSI_FLAGS := Linux-armv7_CC := $(CROSS_PREFIX)gcc Linux-armv7_STRIP := $(CROSS_PREFIX)strip Linux-armv7_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -mfloat-abi=hard -mfpu=vfp -fPIC -fvisibility=hidden Linux-armv7_LINKFLAGS := -shared -static-libgcc Linux-armv7_LIBNAME := libjlinenative.so -Linux-armv7_JANSI_FLAGS := Linux-arm64_CC := $(CROSS_PREFIX)gcc Linux-arm64_STRIP := $(CROSS_PREFIX)strip Linux-arm64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -mfloat-abi=hard -mfpu=vfp -fPIC -fvisibility=hidden Linux-arm64_LINKFLAGS := -shared -static-libgcc Linux-arm64_LIBNAME := libjlinenative.so -Linux-arm64_JANSI_FLAGS := Linux-ppc64_CC := $(CROSS_PREFIX)gcc Linux-ppc64_STRIP := $(CROSS_PREFIX)strip Linux-ppc64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -fvisibility=hidden Linux-ppc64_LINKFLAGS := -shared -static-libgcc Linux-ppc64_LIBNAME := libjlinenative.so -Linux-ppc64_JANSI_FLAGS := DragonFly-x86_64_CC := $(CROSS_PREFIX)cc DragonFly-x86_64_STRIP := $(CROSS_PREFIX)strip DragonFly-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -O2 -fPIC -fvisibility=hidden DragonFly-x86_64_LINKFLAGS := -shared DragonFly-x86_64_LIBNAME := libjlinenative.so -DragonFly-x86_64_JANSI_FLAGS := FreeBSD-x86_CC := $(CROSS_PREFIX)gcc FreeBSD-x86_STRIP := $(CROSS_PREFIX)strip FreeBSD-x86_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -fvisibility=hidden FreeBSD-x86_LINKFLAGS := -shared FreeBSD-x86_LIBNAME := libjlinenative.so -FreeBSD-x86_JANSI_FLAGS := FreeBSD-x86_64_CC := $(CROSS_PREFIX)gcc FreeBSD-x86_64_STRIP := $(CROSS_PREFIX)strip FreeBSD-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -fvisibility=hidden FreeBSD-x86_64_LINKFLAGS := -shared FreeBSD-x86_64_LIBNAME := libjlinenative.so -FreeBSD-x86_64_JANSI_FLAGS := OpenBSD-x86_64_CC := $(CROSS_PREFIX)gcc OpenBSD-x86_64_STRIP := $(CROSS_PREFIX)strip OpenBSD-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -fvisibility=hidden OpenBSD-x86_64_LINKFLAGS := -shared OpenBSD-x86_64_LIBNAME := libjlinenative.so -OpenBSD-x86_64_JANSI_FLAGS := SunOS-sparcv9_CC := $(CROSS_PREFIX)gcc SunOS-sparcv9_STRIP := $(CROSS_PREFIX)strip SunOS-sparcv9_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -O2s-fPIC -m64 -fvisibility=hidden SunOS-sparcv9_LINKFLAGS := -shared -static-libgcc SunOS-sparcv9_LIBNAME := libjlinenative.so -SunOS-sparcv9_JANSI_FLAGS := HPUX-ia64_32_CC := cc HPUX-ia64_32_STRIP := strip HPUX-ia64_32_CCFLAGS := -Itarget/inc -Itarget/inc/unix +Osize +z -Bhidden HPUX-ia64_32_LINKFLAGS := -b -HPUX-ia64_32_LIBNAME := libjlinenative.so -HPUX-ia64_32_JANSI_FLAGS := +SHPUX-ia64_32_LIBNAME := libjlinenative.so Mac-x86_CC := gcc Mac-x86_STRIP := strip -x Mac-x86_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -fPIC -mmacosx-version-min=10.4 -fvisibility=hidden Mac-x86_LINKFLAGS := -dynamiclib Mac-x86_LIBNAME := libjlinenative.jnilib -Mac-x86_JANSI_FLAGS := -DJANSI_ENABLE_LOCKING_STYLE=0 Mac-x86_64_CC := gcc -arch $(OS_ARCH) Mac-x86_64_STRIP := strip -x @@ -141,7 +126,6 @@ endif Mac-x86_64_CCFLAGS := -I$(MAC_SDK)/System/Library/Frameworks/JavaVM.framework/Headers -Itarget/inc -Itarget/inc/unix -Os -fPIC -mmacosx-version-min=10.6 -fvisibility=hidden Mac-x86_64_LINKFLAGS := -dynamiclib Mac-x86_64_LIBNAME := libjlinenative.jnilib -Mac-x86_64_JANSI_FLAGS := Mac-arm64_CC := $(CROSS_PREFIX)clang -v Mac-arm64_STRIP := $(CROSS_PREFIX)strip -x @@ -149,21 +133,18 @@ MAC_SDK := /usr/local/osxcross/SDK/MacOSX11.3.sdk/ Mac-arm64_CCFLAGS := -I$(MAC_SDK)/System/Library/Frameworks/JavaVM.framework/Headers -Itarget/inc -Itarget/inc/unix -Os -fPIC -mmacosx-version-min=11.0 -fvisibility=hidden Mac-arm64_LINKFLAGS := -shared Mac-arm64_LIBNAME := libjlinenative.jnilib -Mac-arm64_JANSI_FLAGS := Windows-x86_CC := $(CROSS_PREFIX)gcc Windows-x86_STRIP := $(CROSS_PREFIX)strip Windows-x86_CCFLAGS := -D_JNI_IMPLEMENTATION_ -Itarget/inc -Itarget/inc/windows -Os Windows-x86_LINKFLAGS := -Wl,--kill-at -shared -static-libgcc Windows-x86_LIBNAME := jlinenative.dll -Windows-x86_JANSI_FLAGS := Windows-x86_64_CC := $(CROSS_PREFIX)gcc Windows-x86_64_STRIP := $(CROSS_PREFIX)strip Windows-x86_64_CCFLAGS := -D_JNI_IMPLEMENTATION_ -Itarget/inc -Itarget/inc/windows -Os Windows-x86_64_LINKFLAGS := -Wl,--kill-at -shared -static-libgcc Windows-x86_64_LIBNAME := jlinenative.dll -Windows-x86_64_JANSI_FLAGS := CC := $($(target)_CC) diff --git a/native/src/main/java/org/jline/nativ/CLibrary.java b/native/src/main/java/org/jline/nativ/CLibrary.java new file mode 100644 index 000000000..bc69f59d5 --- /dev/null +++ b/native/src/main/java/org/jline/nativ/CLibrary.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2009-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.nativ; + +/** + * Interface to access some low level POSIX functions,. + * + * @see JLineNativeLoader + */ +@SuppressWarnings("unused") +public class CLibrary { + + // + // Initialization + // + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + // + // Constants + // + + public static int TCSANOW; + public static int TCSADRAIN; + public static int TCSAFLUSH; + public static long TIOCGWINSZ; + public static long TIOCSWINSZ; + + /** + * test whether a file descriptor refers to a terminal + * + * @param fd file descriptor + * @return isatty() returns 1 if fd is an open file descriptor referring to a + * terminal; otherwise 0 is returned, and errno is set to indicate the + * error + * @see ISATTY(3) man-page + * @see ISATTY(3P) man-page + */ + public static native int isatty(int fd); + + public static native String ttyname(int filedes); + + /** + * The openpty() function finds an available pseudoterminal and returns + * file descriptors for the master and slave in amaster and aslave. + * + * @param amaster master return value + * @param aslave slave return value + * @param name filename return value + * @param termios optional pty attributes + * @param winsize optional size + * @return 0 on success + * @see OPENPTY(3) man-page + */ + public static native int openpty(int[] amaster, int[] aslave, byte[] name, Termios termios, WinSize winsize); + + public static native int tcgetattr(int filedes, Termios termios); + + public static native int tcsetattr(int filedes, int optional_actions, Termios termios); + + /** + * Control a STREAMS device. + * + * @see IOCTL(3P) man-page + */ + public static native int ioctl(int filedes, long request, int[] params); + + public static native int ioctl(int filedes, long request, WinSize params); + + public static short getTerminalWidth(int fd) { + WinSize sz = new WinSize(); + ioctl(fd, TIOCGWINSZ, sz); + return sz.ws_col; + } + + /** + * Window sizes. + * + * @see IOCTL_TTY(2) man-page + */ + public static class WinSize { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public short ws_row; + public short ws_col; + public short ws_xpixel; + public short ws_ypixel; + + public WinSize() {} + + public WinSize(short ws_row, short ws_col) { + this.ws_row = ws_row; + this.ws_col = ws_col; + } + } + + /** + * termios structure for termios functions, describing a general terminal interface that is + * provided to control asynchronous communications ports + * + * @see TERMIOS(3) man-page + */ + public static class Termios { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public long c_iflag; + public long c_oflag; + public long c_cflag; + public long c_lflag; + public byte[] c_cc = new byte[32]; + public long c_ispeed; + public long c_ospeed; + } +} diff --git a/native/src/main/java/org/jline/nativ/Kernel32.java b/native/src/main/java/org/jline/nativ/Kernel32.java new file mode 100644 index 000000000..66a525ffc --- /dev/null +++ b/native/src/main/java/org/jline/nativ/Kernel32.java @@ -0,0 +1,533 @@ +/* + * Copyright (c) 2009-2023, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.nativ; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/** + * Interface to access Win32 base APIs. + */ +@SuppressWarnings("unused") +public class Kernel32 { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static short FOREGROUND_BLUE; + public static short FOREGROUND_GREEN; + public static short FOREGROUND_RED; + public static short FOREGROUND_INTENSITY; + public static short BACKGROUND_BLUE; + public static short BACKGROUND_GREEN; + public static short BACKGROUND_RED; + public static short BACKGROUND_INTENSITY; + public static short COMMON_LVB_LEADING_BYTE; + public static short COMMON_LVB_TRAILING_BYTE; + public static short COMMON_LVB_GRID_HORIZONTAL; + public static short COMMON_LVB_GRID_LVERTICAL; + public static short COMMON_LVB_GRID_RVERTICAL; + public static short COMMON_LVB_REVERSE_VIDEO; + public static short COMMON_LVB_UNDERSCORE; + public static int FORMAT_MESSAGE_FROM_SYSTEM; + public static int STD_INPUT_HANDLE; + public static int STD_OUTPUT_HANDLE; + public static int STD_ERROR_HANDLE; + public static int INVALID_HANDLE_VALUE; + + public static native long malloc(long size); + + public static native void free(long ptr); + + /** + * http://msdn.microsoft.com/en-us/library/ms686311%28VS.85%29.aspx + */ + public static class SMALL_RECT { + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public short left; + public short top; + public short right; + public short bottom; + + public short width() { + return (short) (right - left); + } + + public short height() { + return (short) (bottom - top); + } + + public SMALL_RECT copy() { + SMALL_RECT rc = new SMALL_RECT(); + rc.left = left; + rc.top = top; + rc.right = right; + rc.bottom = bottom; + return rc; + } + } + + /** + * see http://msdn.microsoft.com/en-us/library/ms686047%28VS.85%29.aspx + */ + public static native int SetConsoleTextAttribute(long consoleOutput, short attributes); + + public static class COORD { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public short x; + public short y; + + public COORD copy() { + COORD rc = new COORD(); + rc.x = x; + rc.y = y; + return rc; + } + } + + /** + * http://msdn.microsoft.com/en-us/library/ms682093%28VS.85%29.aspx + */ + public static class CONSOLE_SCREEN_BUFFER_INFO { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public COORD size = new COORD(); + public COORD cursorPosition = new COORD(); + public short attributes; + public SMALL_RECT window = new SMALL_RECT(); + public COORD maximumWindowSize = new COORD(); + + public int windowWidth() { + return window.width() + 1; + } + + public int windowHeight() { + return window.height() + 1; + } + } + + // DWORD WINAPI WaitForSingleObject( + // _In_ HANDLE hHandle, + // _In_ DWORD dwMilliseconds + // ); + public static native int WaitForSingleObject(long hHandle, int dwMilliseconds); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms724211%28VS.85%29.aspx + */ + public static native int CloseHandle(long handle); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms679360(VS.85).aspx + */ + public static native int GetLastError(); + + public static native int FormatMessageW( + int flags, long source, int messageId, int languageId, byte[] buffer, int size, long[] args); + + /** + * See: http://msdn.microsoft.com/en-us/library/ms683171%28VS.85%29.aspx + */ + public static native int GetConsoleScreenBufferInfo( + long consoleOutput, CONSOLE_SCREEN_BUFFER_INFO consoleScreenBufferInfo); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683231%28VS.85%29.aspx + */ + public static native long GetStdHandle(int stdHandle); + + /** + * http://msdn.microsoft.com/en-us/library/ms686025%28VS.85%29.aspx + */ + public static native int SetConsoleCursorPosition(long consoleOutput, COORD cursorPosition); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms682663%28VS.85%29.aspx + */ + public static native int FillConsoleOutputCharacterW( + long consoleOutput, char character, int length, COORD writeCoord, int[] numberOfCharsWritten); + + /** + * see: https://msdn.microsoft.com/en-us/library/ms682662%28VS.85%29.aspx + */ + public static native int FillConsoleOutputAttribute( + long consoleOutput, short attribute, int length, COORD writeCoord, int[] numberOfAttrsWritten); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms687401(v=VS.85).aspx + */ + public static native int WriteConsoleW( + long consoleOutput, char[] buffer, int numberOfCharsToWrite, int[] numberOfCharsWritten, long reserved); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683167%28VS.85%29.aspx + */ + public static native int GetConsoleMode(long handle, int[] mode); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms686033%28VS.85%29.aspx + */ + public static native int SetConsoleMode(long handle, int mode); + + /** + * see: http://msdn.microsoft.com/en-us/library/078sfkak(VS.80).aspx + */ + public static native int _getch(); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms686050%28VS.85%29.aspx + * + * @return 0 if title was set successfully + */ + public static native int SetConsoleTitle(String title); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683169(v=VS.85).aspx + * + * @return the current output code page + */ + public static native int GetConsoleOutputCP(); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms686036(v=VS.85).aspx + * + * @return non 0 if code page was set + */ + public static native int SetConsoleOutputCP(int codePageID); + + /** + * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682013(v=vs.85).aspx + */ + public static class CHAR_INFO { + + static { + JLineNativeLoader.initialize(); + init(); + } + + private static native void init(); + + public static int SIZEOF; + + public short attributes; + public char unicodeChar; + } + + /** + * see: https://msdn.microsoft.com/en-us/library/windows/desktop/ms685107(v=vs.85).aspx + */ + public static native int ScrollConsoleScreenBuffer( + long consoleOutput, + SMALL_RECT scrollRectangle, + SMALL_RECT clipRectangle, + COORD destinationOrigin, + CHAR_INFO fill); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms684166(v=VS.85).aspx + */ + public static class KEY_EVENT_RECORD { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + public static int CAPSLOCK_ON; + public static int NUMLOCK_ON; + public static int SCROLLLOCK_ON; + public static int ENHANCED_KEY; + public static int LEFT_ALT_PRESSED; + public static int LEFT_CTRL_PRESSED; + public static int RIGHT_ALT_PRESSED; + public static int RIGHT_CTRL_PRESSED; + public static int SHIFT_PRESSED; + + public boolean keyDown; + public short repeatCount; + public short keyCode; + public short scanCode; + public char uchar; + public int controlKeyState; + + public String toString() { + return "KEY_EVENT_RECORD{" + "keyDown=" + + keyDown + ", repeatCount=" + + repeatCount + ", keyCode=" + + keyCode + ", scanCode=" + + scanCode + ", uchar=" + + uchar + ", controlKeyState=" + + controlKeyState + '}'; + } + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms684239(v=VS.85).aspx + */ + public static class MOUSE_EVENT_RECORD { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + public static int FROM_LEFT_1ST_BUTTON_PRESSED; + public static int FROM_LEFT_2ND_BUTTON_PRESSED; + public static int FROM_LEFT_3RD_BUTTON_PRESSED; + public static int FROM_LEFT_4TH_BUTTON_PRESSED; + public static int RIGHTMOST_BUTTON_PRESSED; + + public static int CAPSLOCK_ON; + public static int NUMLOCK_ON; + public static int SCROLLLOCK_ON; + public static int ENHANCED_KEY; + public static int LEFT_ALT_PRESSED; + public static int LEFT_CTRL_PRESSED; + public static int RIGHT_ALT_PRESSED; + public static int RIGHT_CTRL_PRESSED; + public static int SHIFT_PRESSED; + + public static int DOUBLE_CLICK; + public static int MOUSE_HWHEELED; + public static int MOUSE_MOVED; + public static int MOUSE_WHEELED; + + public COORD mousePosition = new COORD(); + public int buttonState; + public int controlKeyState; + public int eventFlags; + + public String toString() { + return "MOUSE_EVENT_RECORD{" + "mousePosition=" + + mousePosition + ", buttonState=" + + buttonState + ", controlKeyState=" + + controlKeyState + ", eventFlags=" + + eventFlags + '}'; + } + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms687093(v=VS.85).aspx + */ + public static class WINDOW_BUFFER_SIZE_RECORD { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + + public COORD size = new COORD(); + + public String toString() { + return "WINDOW_BUFFER_SIZE_RECORD{size=" + size + '}'; + } + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683149(v=VS.85).aspx + */ + public static class FOCUS_EVENT_RECORD { + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + public boolean setFocus; + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms684213(v=VS.85).aspx + */ + public static class MENU_EVENT_RECORD { + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + public int commandId; + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683499(v=VS.85).aspx + */ + public static class INPUT_RECORD { + + static { + if (JLineNativeLoader.initialize()) { + init(); + } + } + + private static native void init(); + + public static int SIZEOF; + public static short KEY_EVENT; + public static short MOUSE_EVENT; + public static short WINDOW_BUFFER_SIZE_EVENT; + public static short FOCUS_EVENT; + public static short MENU_EVENT; + public short eventType; + public KEY_EVENT_RECORD keyEvent = new KEY_EVENT_RECORD(); + public MOUSE_EVENT_RECORD mouseEvent = new MOUSE_EVENT_RECORD(); + public WINDOW_BUFFER_SIZE_RECORD windowBufferSizeEvent = new WINDOW_BUFFER_SIZE_RECORD(); + public MENU_EVENT_RECORD menuEvent = new MENU_EVENT_RECORD(); + public FOCUS_EVENT_RECORD focusEvent = new FOCUS_EVENT_RECORD(); + + public static native void memmove(INPUT_RECORD dest, long src, long size); + } + + /** + * see: http://msdn.microsoft.com/en-us/library/ms684961(v=VS.85).aspx + */ + private static native int ReadConsoleInputW(long handle, long inputRecord, int length, int[] eventsCount); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms684344(v=VS.85).aspx + */ + private static native int PeekConsoleInputW(long handle, long inputRecord, int length, int[] eventsCount); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683207(v=VS.85).aspx + */ + public static native int GetNumberOfConsoleInputEvents(long handle, int[] numberOfEvents); + + /** + * see: http://msdn.microsoft.com/en-us/library/ms683147(v=VS.85).aspx + */ + public static native int FlushConsoleInputBuffer(long handle); + + /** + * Return console input events. + */ + public static INPUT_RECORD[] readConsoleInputHelper(long handle, int count, boolean peek) throws IOException { + int[] length = new int[1]; + int res; + long inputRecordPtr = 0; + try { + inputRecordPtr = malloc(INPUT_RECORD.SIZEOF * count); + if (inputRecordPtr == 0) { + throw new IOException("cannot allocate memory with JNI"); + } + res = peek + ? PeekConsoleInputW(handle, inputRecordPtr, count, length) + : ReadConsoleInputW(handle, inputRecordPtr, count, length); + if (res == 0) { + int bufferSize = 160; + byte[] data = new byte[bufferSize]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, data, bufferSize, null); + String lastErrorMessage = new String(data, StandardCharsets.UTF_16LE).trim(); + throw new IOException("ReadConsoleInputW failed: " + lastErrorMessage); + } + if (length[0] <= 0) { + return new INPUT_RECORD[0]; + } + INPUT_RECORD[] records = new INPUT_RECORD[length[0]]; + for (int i = 0; i < records.length; i++) { + records[i] = new INPUT_RECORD(); + INPUT_RECORD.memmove(records[i], inputRecordPtr + i * INPUT_RECORD.SIZEOF, INPUT_RECORD.SIZEOF); + } + return records; + } finally { + if (inputRecordPtr != 0) { + free(inputRecordPtr); + } + } + } + + /** + * Return console input key events (discard other events). + * + * @param count requested number of events + * @return array possibly of size smaller then count + */ + public static INPUT_RECORD[] readConsoleKeyInput(long handle, int count, boolean peek) throws IOException { + while (true) { + // read events until we have keyboard events, the queue could be full + // of mouse events. + INPUT_RECORD[] evts = readConsoleInputHelper(handle, count, peek); + int keyEvtCount = 0; + for (INPUT_RECORD evt : evts) { + if (evt.eventType == INPUT_RECORD.KEY_EVENT) keyEvtCount++; + } + if (keyEvtCount > 0) { + INPUT_RECORD[] res = new INPUT_RECORD[keyEvtCount]; + int i = 0; + for (INPUT_RECORD evt : evts) { + if (evt.eventType == INPUT_RECORD.KEY_EVENT) { + res[i++] = evt; + } + } + return res; + } + } + } + + public static String getLastErrorMessage() { + int bufferSize = 160; + byte[] data = new byte[bufferSize]; + FormatMessageW(Kernel32.FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, data, bufferSize, null); + return new String(data, StandardCharsets.UTF_16LE).trim(); + } + + public static native int isatty(int fd); +} diff --git a/native/src/main/native/clibrary.c b/native/src/main/native/clibrary.c new file mode 100644 index 000000000..59b9c14d3 --- /dev/null +++ b/native/src/main/native/clibrary.c @@ -0,0 +1,241 @@ +/******************************************************************************* + * Copyright (C) 2009-2017 the original author(s). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +#include "jlinenative.h" + +#if !defined(_WIN32) && !defined(_WIN64) + +#define Termios_NATIVE(func) Java_org_jline_nativ_CLibrary_00024Termios_##func +#define WinSize_NATIVE(func) Java_org_jline_nativ_CLibrary_00024WinSize_##func +#define CLibrary_NATIVE(func) Java_org_jline_nativ_CLibrary_##func + +typedef struct Termios_FID_CACHE { + int cached; + jclass clazz; + jfieldID c_iflag, c_oflag, c_cflag, c_lflag, c_cc, c_ispeed, c_ospeed; +} Termios_FID_CACHE; + +Termios_FID_CACHE TermiosFc; + +void cacheTermiosFields(JNIEnv *env, jobject lpObject) +{ + if (TermiosFc.cached) return; + TermiosFc.clazz = (*env)->GetObjectClass(env, lpObject); + TermiosFc.c_iflag = (*env)->GetFieldID(env, TermiosFc.clazz, "c_iflag", "J"); + TermiosFc.c_oflag = (*env)->GetFieldID(env, TermiosFc.clazz, "c_oflag", "J"); + TermiosFc.c_cflag = (*env)->GetFieldID(env, TermiosFc.clazz, "c_cflag", "J"); + TermiosFc.c_lflag = (*env)->GetFieldID(env, TermiosFc.clazz, "c_lflag", "J"); + TermiosFc.c_cc = (*env)->GetFieldID(env, TermiosFc.clazz, "c_cc", "[B"); + TermiosFc.c_ispeed = (*env)->GetFieldID(env, TermiosFc.clazz, "c_ispeed", "J"); + TermiosFc.c_ospeed = (*env)->GetFieldID(env, TermiosFc.clazz, "c_ospeed", "J"); + hawtjni_w_barrier(); + TermiosFc.cached = 1; +} + +struct termios *getTermiosFields(JNIEnv *env, jobject lpObject, struct termios *lpStruct) +{ + if (!TermiosFc.cached) cacheTermiosFields(env, lpObject); + lpStruct->c_iflag = (*env)->GetLongField(env, lpObject, TermiosFc.c_iflag); + lpStruct->c_oflag = (*env)->GetLongField(env, lpObject, TermiosFc.c_oflag); + lpStruct->c_cflag = (*env)->GetLongField(env, lpObject, TermiosFc.c_cflag); + lpStruct->c_lflag = (*env)->GetLongField(env, lpObject, TermiosFc.c_lflag); + { + jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, TermiosFc.c_cc); + (*env)->GetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->c_cc), (jbyte *)lpStruct->c_cc); + } + lpStruct->c_ispeed = (*env)->GetLongField(env, lpObject, TermiosFc.c_ispeed); + lpStruct->c_ospeed = (*env)->GetLongField(env, lpObject, TermiosFc.c_ospeed); + return lpStruct; +} + +void setTermiosFields(JNIEnv *env, jobject lpObject, struct termios *lpStruct) +{ + if (!TermiosFc.cached) cacheTermiosFields(env, lpObject); + (*env)->SetLongField(env, lpObject, TermiosFc.c_iflag, (jlong)lpStruct->c_iflag); + (*env)->SetLongField(env, lpObject, TermiosFc.c_oflag, (jlong)lpStruct->c_oflag); + (*env)->SetLongField(env, lpObject, TermiosFc.c_cflag, (jlong)lpStruct->c_cflag); + (*env)->SetLongField(env, lpObject, TermiosFc.c_lflag, (jlong)lpStruct->c_lflag); + { + jbyteArray lpObject1 = (jbyteArray)(*env)->GetObjectField(env, lpObject, TermiosFc.c_cc); + (*env)->SetByteArrayRegion(env, lpObject1, 0, sizeof(lpStruct->c_cc), (jbyte *)lpStruct->c_cc); + } + (*env)->SetLongField(env, lpObject, TermiosFc.c_ispeed, (jlong)lpStruct->c_ispeed); + (*env)->SetLongField(env, lpObject, TermiosFc.c_ospeed, (jlong)lpStruct->c_ospeed); +} + +typedef struct WinSize_FID_CACHE { + int cached; + jclass clazz; + jfieldID ws_row, ws_col, ws_xpixel, ws_ypixel; +} WinSize_FID_CACHE; + +WinSize_FID_CACHE WinSizeFc; + +void cacheWinSizeFields(JNIEnv *env, jobject lpObject) +{ + if (WinSizeFc.cached) return; + WinSizeFc.clazz = (*env)->GetObjectClass(env, lpObject); + WinSizeFc.ws_row = (*env)->GetFieldID(env, WinSizeFc.clazz, "ws_row", "S"); + WinSizeFc.ws_col = (*env)->GetFieldID(env, WinSizeFc.clazz, "ws_col", "S"); + WinSizeFc.ws_xpixel = (*env)->GetFieldID(env, WinSizeFc.clazz, "ws_xpixel", "S"); + WinSizeFc.ws_ypixel = (*env)->GetFieldID(env, WinSizeFc.clazz, "ws_ypixel", "S"); + hawtjni_w_barrier(); + WinSizeFc.cached = 1; +} + +struct winsize *getWinSizeFields(JNIEnv *env, jobject lpObject, struct winsize *lpStruct) +{ + if (!WinSizeFc.cached) cacheWinSizeFields(env, lpObject); + lpStruct->ws_row = (*env)->GetShortField(env, lpObject, WinSizeFc.ws_row); + lpStruct->ws_col = (*env)->GetShortField(env, lpObject, WinSizeFc.ws_col); + lpStruct->ws_xpixel = (*env)->GetShortField(env, lpObject, WinSizeFc.ws_xpixel); + lpStruct->ws_ypixel = (*env)->GetShortField(env, lpObject, WinSizeFc.ws_ypixel); + return lpStruct; +} + +void setWinSizeFields(JNIEnv *env, jobject lpObject, struct winsize *lpStruct) +{ + if (!WinSizeFc.cached) cacheWinSizeFields(env, lpObject); + (*env)->SetShortField(env, lpObject, WinSizeFc.ws_row, (jshort)lpStruct->ws_row); + (*env)->SetShortField(env, lpObject, WinSizeFc.ws_col, (jshort)lpStruct->ws_col); + (*env)->SetShortField(env, lpObject, WinSizeFc.ws_xpixel, (jshort)lpStruct->ws_xpixel); + (*env)->SetShortField(env, lpObject, WinSizeFc.ws_ypixel, (jshort)lpStruct->ws_ypixel); +} + +JNIEXPORT void JNICALL Termios_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(struct termios)); + return; +} + +JNIEXPORT void JNICALL WinSize_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(struct winsize)); + return; +} + +JNIEXPORT void JNICALL CLibrary_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "TCSANOW", "I"), (jint)TCSANOW); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "TCSADRAIN", "I"), (jint)TCSADRAIN); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "TCSAFLUSH", "I"), (jint)TCSAFLUSH); + (*env)->SetStaticLongField(env, that, (*env)->GetStaticFieldID(env, that, "TIOCGWINSZ", "J"), (jlong)TIOCGWINSZ); + (*env)->SetStaticLongField(env, that, (*env)->GetStaticFieldID(env, that, "TIOCSWINSZ", "J"), (jlong)TIOCSWINSZ); + return; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(ioctl__IJLorg_jline_nativ_CLibrary_00024WinSize_2) + (JNIEnv *env, jclass that, jint arg0, jlong arg1, jobject arg2) +{ + struct winsize _arg2, *lparg2=NULL; + jint rc = 0; + + if (arg2) if ((lparg2 = getWinSizeFields(env, arg2, &_arg2)) == NULL) goto fail; + rc = (jint)ioctl(arg0, arg1, (intptr_t)lparg2); +fail: + if (arg2 && lparg2) setWinSizeFields(env, arg2, lparg2); + + return rc; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(ioctl__IJ_3I) + (JNIEnv *env, jclass that, jint arg0, jlong arg1, jintArray arg2) +{ + jint *lparg2=NULL; + jint rc = 0; + + if (arg2) if ((lparg2 = (*env)->GetIntArrayElements(env, arg2, NULL)) == NULL) goto fail; + rc = (jint)ioctl(arg0, arg1, lparg2); +fail: + if (arg2 && lparg2) (*env)->ReleaseIntArrayElements(env, arg2, lparg2, 0); + + return rc; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(openpty) + (JNIEnv *env, jclass that, jintArray arg0, jintArray arg1, jbyteArray arg2, jobject arg3, jobject arg4) +{ + jint *lparg0=NULL; + jint *lparg1=NULL; + jbyte *lparg2=NULL; + struct termios _arg3, *lparg3=NULL; + struct winsize _arg4, *lparg4=NULL; + jint rc = 0; + + if (arg0) if ((lparg0 = (*env)->GetIntArrayElements(env, arg0, NULL)) == NULL) goto fail; + if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail; + if (arg2) if ((lparg2 = (*env)->GetByteArrayElements(env, arg2, NULL)) == NULL) goto fail; + if (arg3) if ((lparg3 = getTermiosFields(env, arg3, &_arg3)) == NULL) goto fail; + if (arg4) if ((lparg4 = getWinSizeFields(env, arg4, &_arg4)) == NULL) goto fail; + rc = (jint)openpty((int *)lparg0, (int *)lparg1, (char *)lparg2, (struct termios *)lparg3, (struct winsize *)lparg4); +fail: + if (arg2 && lparg2) (*env)->ReleaseByteArrayElements(env, arg2, lparg2, 0); + if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0); + if (arg0 && lparg0) (*env)->ReleaseIntArrayElements(env, arg0, lparg0, 0); + + return rc; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(tcgetattr) + (JNIEnv *env, jclass that, jint arg0, jobject arg1) +{ + struct termios _arg1, *lparg1=NULL; + jint rc = 0; + + if (arg1) if ((lparg1 = &_arg1) == NULL) goto fail; + rc = (jint)tcgetattr(arg0, (struct termios *)lparg1); +fail: + if (arg1 && lparg1) setTermiosFields(env, arg1, lparg1); + + return rc; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(tcsetattr) + (JNIEnv *env, jclass that, jint arg0, jint arg1, jobject arg2) +{ + struct termios _arg2, *lparg2=NULL; + jint rc = 0; + + if (arg2) if ((lparg2 = getTermiosFields(env, arg2, &_arg2)) == NULL) goto fail; + rc = (jint)tcsetattr(arg0, arg1, (struct termios *)lparg2); +fail: + + return rc; +} + +JNIEXPORT jint JNICALL CLibrary_NATIVE(isatty) + (JNIEnv *env, jclass that, jint arg0) +{ + jint rc = 0; + + rc = (jint)isatty(arg0); + + return rc; +} + +JNIEXPORT jstring JNICALL CLibrary_NATIVE(ttyname) + (JNIEnv *env, jclass that, jint arg0) +{ + jstring rc = 0; + char s[256] = { 0 }; + int r = 0; + + r = ttyname_r(arg0, s, 256); + if (!r) rc = (*env)->NewStringUTF(env,s); + + return rc; +} + +#endif diff --git a/native/src/main/native/kernel32.c b/native/src/main/native/kernel32.c new file mode 100644 index 000000000..003cdcbaa --- /dev/null +++ b/native/src/main/native/kernel32.c @@ -0,0 +1,974 @@ +/******************************************************************************* + * Copyright (C) 2009-2017 the original author(s). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *******************************************************************************/ +#include "jlinenative.h" + +#if defined(_WIN32) || defined(_WIN64) + +#define isatty _isatty + +#define Kernel32_NATIVE(func) Java_org_jline_nativ_Kernel32_##func +#define CHAR_INFO_NATIVE(func) Java_org_jline_nativ_Kernel32_00024CHAR_1INFO_##func +#define CONSOLE_SCREEN_BUFFER_INFO_NATIVE(func) Java_org_jline_nativ_Kernel32_00024CONSOLE_1SCREEN_1BUFFER_1INFO_##func +#define COORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024COORD_##func +#define FOCUS_EVENT_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024FOCUS_1EVENT_1RECORD_##func +#define INPUT_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024INPUT_1RECORD_##func +#define KEY_EVENT_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024KEY_1EVENT_1RECORD_##func +#define MENU_EVENT_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024MENU_1EVENT_1RECORD_##func +#define MOUSE_EVENT_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024MOUSE_1EVENT_1RECORD_##func +#define SMALL_RECT_NATIVE(func) Java_org_jline_nativ_Kernel32_00024SMALL_1RECT_##func +#define WINDOW_BUFFER_SIZE_RECORD_NATIVE(func) Java_org_jline_nativ_Kernel32_00024WINDOW_1BUFFER_1SIZE_1RECORD_##func + +void cacheCHAR_INFOFields(JNIEnv *env, jobject lpObject); +CHAR_INFO *getCHAR_INFOFields(JNIEnv *env, jobject lpObject, CHAR_INFO *lpStruct); +void setCHAR_INFOFields(JNIEnv *env, jobject lpObject, CHAR_INFO *lpStruct); + +void cacheCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject); +CONSOLE_SCREEN_BUFFER_INFO *getCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject, CONSOLE_SCREEN_BUFFER_INFO *lpStruct); +void setCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject, CONSOLE_SCREEN_BUFFER_INFO *lpStruct); + +void cacheCOORDFields(JNIEnv *env, jobject lpObject); +COORD *getCOORDFields(JNIEnv *env, jobject lpObject, COORD *lpStruct); +void setCOORDFields(JNIEnv *env, jobject lpObject, COORD *lpStruct); + +void cacheFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject); +FOCUS_EVENT_RECORD *getFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, FOCUS_EVENT_RECORD *lpStruct); +void setFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, FOCUS_EVENT_RECORD *lpStruct); + +void cacheINPUT_RECORDFields(JNIEnv *env, jobject lpObject); +INPUT_RECORD *getINPUT_RECORDFields(JNIEnv *env, jobject lpObject, INPUT_RECORD *lpStruct); +void setINPUT_RECORDFields(JNIEnv *env, jobject lpObject, INPUT_RECORD *lpStruct); + +void cacheKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject); +KEY_EVENT_RECORD *getKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, KEY_EVENT_RECORD *lpStruct); +void setKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, KEY_EVENT_RECORD *lpStruct); + +void cacheMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject); +MENU_EVENT_RECORD *getMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MENU_EVENT_RECORD *lpStruct); +void setMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MENU_EVENT_RECORD *lpStruct); + +void cacheMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject); +MOUSE_EVENT_RECORD *getMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MOUSE_EVENT_RECORD *lpStruct); +void setMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MOUSE_EVENT_RECORD *lpStruct); + +void cacheSMALL_RECTFields(JNIEnv *env, jobject lpObject); +SMALL_RECT *getSMALL_RECTFields(JNIEnv *env, jobject lpObject, SMALL_RECT *lpStruct); +void setSMALL_RECTFields(JNIEnv *env, jobject lpObject, SMALL_RECT *lpStruct); + +void cacheWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject); +WINDOW_BUFFER_SIZE_RECORD *getWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject, WINDOW_BUFFER_SIZE_RECORD *lpStruct); +void setWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject, WINDOW_BUFFER_SIZE_RECORD *lpStruct); + +typedef struct CHAR_INFO_FID_CACHE { + int cached; + jclass clazz; + jfieldID attributes, unicodeChar; +} CHAR_INFO_FID_CACHE; + +CHAR_INFO_FID_CACHE CHAR_INFOFc; + +void cacheCHAR_INFOFields(JNIEnv *env, jobject lpObject) +{ + if (CHAR_INFOFc.cached) return; + CHAR_INFOFc.clazz = (*env)->GetObjectClass(env, lpObject); + CHAR_INFOFc.attributes = (*env)->GetFieldID(env, CHAR_INFOFc.clazz, "attributes", "S"); + CHAR_INFOFc.unicodeChar = (*env)->GetFieldID(env, CHAR_INFOFc.clazz, "unicodeChar", "C"); + hawtjni_w_barrier(); + CHAR_INFOFc.cached = 1; +} + +CHAR_INFO *getCHAR_INFOFields(JNIEnv *env, jobject lpObject, CHAR_INFO *lpStruct) +{ + if (!CHAR_INFOFc.cached) cacheCHAR_INFOFields(env, lpObject); + lpStruct->Attributes = (*env)->GetShortField(env, lpObject, CHAR_INFOFc.attributes); + lpStruct->Char.UnicodeChar = (*env)->GetCharField(env, lpObject, CHAR_INFOFc.unicodeChar); + return lpStruct; +} + +void setCHAR_INFOFields(JNIEnv *env, jobject lpObject, CHAR_INFO *lpStruct) +{ + if (!CHAR_INFOFc.cached) cacheCHAR_INFOFields(env, lpObject); + (*env)->SetShortField(env, lpObject, CHAR_INFOFc.attributes, (jshort)lpStruct->Attributes); + (*env)->SetCharField(env, lpObject, CHAR_INFOFc.unicodeChar, (jchar)lpStruct->Char.UnicodeChar); +} + +typedef struct CONSOLE_SCREEN_BUFFER_INFO_FID_CACHE { + int cached; + jclass clazz; + jfieldID size, cursorPosition, attributes, window, maximumWindowSize; +} CONSOLE_SCREEN_BUFFER_INFO_FID_CACHE; + +CONSOLE_SCREEN_BUFFER_INFO_FID_CACHE CONSOLE_SCREEN_BUFFER_INFOFc; + +void cacheCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject) +{ + if (CONSOLE_SCREEN_BUFFER_INFOFc.cached) return; + CONSOLE_SCREEN_BUFFER_INFOFc.clazz = (*env)->GetObjectClass(env, lpObject); + CONSOLE_SCREEN_BUFFER_INFOFc.size = (*env)->GetFieldID(env, CONSOLE_SCREEN_BUFFER_INFOFc.clazz, "size", "Lorg/jline/nativ/Kernel32$COORD;"); + CONSOLE_SCREEN_BUFFER_INFOFc.cursorPosition = (*env)->GetFieldID(env, CONSOLE_SCREEN_BUFFER_INFOFc.clazz, "cursorPosition", "Lorg/jline/nativ/Kernel32$COORD;"); + CONSOLE_SCREEN_BUFFER_INFOFc.attributes = (*env)->GetFieldID(env, CONSOLE_SCREEN_BUFFER_INFOFc.clazz, "attributes", "S"); + CONSOLE_SCREEN_BUFFER_INFOFc.window = (*env)->GetFieldID(env, CONSOLE_SCREEN_BUFFER_INFOFc.clazz, "window", "Lorg/jline/nativ/Kernel32$SMALL_RECT;"); + CONSOLE_SCREEN_BUFFER_INFOFc.maximumWindowSize = (*env)->GetFieldID(env, CONSOLE_SCREEN_BUFFER_INFOFc.clazz, "maximumWindowSize", "Lorg/jline/nativ/Kernel32$COORD;"); + hawtjni_w_barrier(); + CONSOLE_SCREEN_BUFFER_INFOFc.cached = 1; +} + +CONSOLE_SCREEN_BUFFER_INFO *getCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject, CONSOLE_SCREEN_BUFFER_INFO *lpStruct) +{ + if (!CONSOLE_SCREEN_BUFFER_INFOFc.cached) cacheCONSOLE_SCREEN_BUFFER_INFOFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.size); + if (lpObject1 != NULL) getCOORDFields(env, lpObject1, &lpStruct->dwSize); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.cursorPosition); + if (lpObject1 != NULL) getCOORDFields(env, lpObject1, &lpStruct->dwCursorPosition); + } + lpStruct->wAttributes = (*env)->GetShortField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.attributes); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.window); + if (lpObject1 != NULL) getSMALL_RECTFields(env, lpObject1, &lpStruct->srWindow); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.maximumWindowSize); + if (lpObject1 != NULL) getCOORDFields(env, lpObject1, &lpStruct->dwMaximumWindowSize); + } + return lpStruct; +} + +void setCONSOLE_SCREEN_BUFFER_INFOFields(JNIEnv *env, jobject lpObject, CONSOLE_SCREEN_BUFFER_INFO *lpStruct) +{ + if (!CONSOLE_SCREEN_BUFFER_INFOFc.cached) cacheCONSOLE_SCREEN_BUFFER_INFOFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.size); + if (lpObject1 != NULL) setCOORDFields(env, lpObject1, &lpStruct->dwSize); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.cursorPosition); + if (lpObject1 != NULL) setCOORDFields(env, lpObject1, &lpStruct->dwCursorPosition); + } + (*env)->SetShortField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.attributes, (jshort)lpStruct->wAttributes); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.window); + if (lpObject1 != NULL) setSMALL_RECTFields(env, lpObject1, &lpStruct->srWindow); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, CONSOLE_SCREEN_BUFFER_INFOFc.maximumWindowSize); + if (lpObject1 != NULL) setCOORDFields(env, lpObject1, &lpStruct->dwMaximumWindowSize); + } +} + +typedef struct COORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID x, y; +} COORD_FID_CACHE; + +COORD_FID_CACHE COORDFc; + +void cacheCOORDFields(JNIEnv *env, jobject lpObject) +{ + if (COORDFc.cached) return; + COORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + COORDFc.x = (*env)->GetFieldID(env, COORDFc.clazz, "x", "S"); + COORDFc.y = (*env)->GetFieldID(env, COORDFc.clazz, "y", "S"); + hawtjni_w_barrier(); + COORDFc.cached = 1; +} + +COORD *getCOORDFields(JNIEnv *env, jobject lpObject, COORD *lpStruct) +{ + if (!COORDFc.cached) cacheCOORDFields(env, lpObject); + lpStruct->X = (*env)->GetShortField(env, lpObject, COORDFc.x); + lpStruct->Y = (*env)->GetShortField(env, lpObject, COORDFc.y); + return lpStruct; +} + +void setCOORDFields(JNIEnv *env, jobject lpObject, COORD *lpStruct) +{ + if (!COORDFc.cached) cacheCOORDFields(env, lpObject); + (*env)->SetShortField(env, lpObject, COORDFc.x, (jshort)lpStruct->X); + (*env)->SetShortField(env, lpObject, COORDFc.y, (jshort)lpStruct->Y); +} + +typedef struct FOCUS_EVENT_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID setFocus; +} FOCUS_EVENT_RECORD_FID_CACHE; + +FOCUS_EVENT_RECORD_FID_CACHE FOCUS_EVENT_RECORDFc; + +void cacheFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (FOCUS_EVENT_RECORDFc.cached) return; + FOCUS_EVENT_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + FOCUS_EVENT_RECORDFc.setFocus = (*env)->GetFieldID(env, FOCUS_EVENT_RECORDFc.clazz, "setFocus", "Z"); + hawtjni_w_barrier(); + FOCUS_EVENT_RECORDFc.cached = 1; +} + +FOCUS_EVENT_RECORD *getFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, FOCUS_EVENT_RECORD *lpStruct) +{ + if (!FOCUS_EVENT_RECORDFc.cached) cacheFOCUS_EVENT_RECORDFields(env, lpObject); + lpStruct->bSetFocus = (*env)->GetBooleanField(env, lpObject, FOCUS_EVENT_RECORDFc.setFocus); + return lpStruct; +} + +void setFOCUS_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, FOCUS_EVENT_RECORD *lpStruct) +{ + if (!FOCUS_EVENT_RECORDFc.cached) cacheFOCUS_EVENT_RECORDFields(env, lpObject); + (*env)->SetBooleanField(env, lpObject, FOCUS_EVENT_RECORDFc.setFocus, (jboolean)lpStruct->bSetFocus); +} + +typedef struct INPUT_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID eventType, keyEvent, mouseEvent, windowBufferSizeEvent, menuEvent, focusEvent; +} INPUT_RECORD_FID_CACHE; + +INPUT_RECORD_FID_CACHE INPUT_RECORDFc; + +void cacheINPUT_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (INPUT_RECORDFc.cached) return; + INPUT_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + INPUT_RECORDFc.eventType = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "eventType", "S"); + INPUT_RECORDFc.keyEvent = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "keyEvent", "Lorg/jline/nativ/Kernel32$KEY_EVENT_RECORD;"); + INPUT_RECORDFc.mouseEvent = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "mouseEvent", "Lorg/jline/nativ/Kernel32$MOUSE_EVENT_RECORD;"); + INPUT_RECORDFc.windowBufferSizeEvent = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "windowBufferSizeEvent", "Lorg/jline/nativ/Kernel32$WINDOW_BUFFER_SIZE_RECORD;"); + INPUT_RECORDFc.menuEvent = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "menuEvent", "Lorg/jline/nativ/Kernel32$MENU_EVENT_RECORD;"); + INPUT_RECORDFc.focusEvent = (*env)->GetFieldID(env, INPUT_RECORDFc.clazz, "focusEvent", "Lorg/jline/nativ/Kernel32$FOCUS_EVENT_RECORD;"); + hawtjni_w_barrier(); + INPUT_RECORDFc.cached = 1; +} + +INPUT_RECORD *getINPUT_RECORDFields(JNIEnv *env, jobject lpObject, INPUT_RECORD *lpStruct) +{ + if (!INPUT_RECORDFc.cached) cacheINPUT_RECORDFields(env, lpObject); + lpStruct->EventType = (*env)->GetShortField(env, lpObject, INPUT_RECORDFc.eventType); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.keyEvent); + if (lpObject1 != NULL) getKEY_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.KeyEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.mouseEvent); + if (lpObject1 != NULL) getMOUSE_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.MouseEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.windowBufferSizeEvent); + if (lpObject1 != NULL) getWINDOW_BUFFER_SIZE_RECORDFields(env, lpObject1, &lpStruct->Event.WindowBufferSizeEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.menuEvent); + if (lpObject1 != NULL) getMENU_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.MenuEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.focusEvent); + if (lpObject1 != NULL) getFOCUS_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.FocusEvent); + } + return lpStruct; +} + +void setINPUT_RECORDFields(JNIEnv *env, jobject lpObject, INPUT_RECORD *lpStruct) +{ + if (!INPUT_RECORDFc.cached) cacheINPUT_RECORDFields(env, lpObject); + (*env)->SetShortField(env, lpObject, INPUT_RECORDFc.eventType, (jshort)lpStruct->EventType); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.keyEvent); + if (lpObject1 != NULL) setKEY_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.KeyEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.mouseEvent); + if (lpObject1 != NULL) setMOUSE_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.MouseEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.windowBufferSizeEvent); + if (lpObject1 != NULL) setWINDOW_BUFFER_SIZE_RECORDFields(env, lpObject1, &lpStruct->Event.WindowBufferSizeEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.menuEvent); + if (lpObject1 != NULL) setMENU_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.MenuEvent); + } + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, INPUT_RECORDFc.focusEvent); + if (lpObject1 != NULL) setFOCUS_EVENT_RECORDFields(env, lpObject1, &lpStruct->Event.FocusEvent); + } +} + +typedef struct KEY_EVENT_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID keyDown, repeatCount, keyCode, scanCode, uchar, controlKeyState; +} KEY_EVENT_RECORD_FID_CACHE; + +KEY_EVENT_RECORD_FID_CACHE KEY_EVENT_RECORDFc; + +void cacheKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (KEY_EVENT_RECORDFc.cached) return; + KEY_EVENT_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + KEY_EVENT_RECORDFc.keyDown = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "keyDown", "Z"); + KEY_EVENT_RECORDFc.repeatCount = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "repeatCount", "S"); + KEY_EVENT_RECORDFc.keyCode = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "keyCode", "S"); + KEY_EVENT_RECORDFc.scanCode = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "scanCode", "S"); + KEY_EVENT_RECORDFc.uchar = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "uchar", "C"); + KEY_EVENT_RECORDFc.controlKeyState = (*env)->GetFieldID(env, KEY_EVENT_RECORDFc.clazz, "controlKeyState", "I"); + hawtjni_w_barrier(); + KEY_EVENT_RECORDFc.cached = 1; +} + +KEY_EVENT_RECORD *getKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, KEY_EVENT_RECORD *lpStruct) +{ + if (!KEY_EVENT_RECORDFc.cached) cacheKEY_EVENT_RECORDFields(env, lpObject); + lpStruct->bKeyDown = (*env)->GetBooleanField(env, lpObject, KEY_EVENT_RECORDFc.keyDown); + lpStruct->wRepeatCount = (*env)->GetShortField(env, lpObject, KEY_EVENT_RECORDFc.repeatCount); + lpStruct->wVirtualKeyCode = (*env)->GetShortField(env, lpObject, KEY_EVENT_RECORDFc.keyCode); + lpStruct->wVirtualScanCode = (*env)->GetShortField(env, lpObject, KEY_EVENT_RECORDFc.scanCode); + lpStruct->uChar.UnicodeChar = (*env)->GetCharField(env, lpObject, KEY_EVENT_RECORDFc.uchar); + lpStruct->dwControlKeyState = (*env)->GetIntField(env, lpObject, KEY_EVENT_RECORDFc.controlKeyState); + return lpStruct; +} + +void setKEY_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, KEY_EVENT_RECORD *lpStruct) +{ + if (!KEY_EVENT_RECORDFc.cached) cacheKEY_EVENT_RECORDFields(env, lpObject); + (*env)->SetBooleanField(env, lpObject, KEY_EVENT_RECORDFc.keyDown, (jboolean)lpStruct->bKeyDown); + (*env)->SetShortField(env, lpObject, KEY_EVENT_RECORDFc.repeatCount, (jshort)lpStruct->wRepeatCount); + (*env)->SetShortField(env, lpObject, KEY_EVENT_RECORDFc.keyCode, (jshort)lpStruct->wVirtualKeyCode); + (*env)->SetShortField(env, lpObject, KEY_EVENT_RECORDFc.scanCode, (jshort)lpStruct->wVirtualScanCode); + (*env)->SetCharField(env, lpObject, KEY_EVENT_RECORDFc.uchar, (jchar)lpStruct->uChar.UnicodeChar); + (*env)->SetIntField(env, lpObject, KEY_EVENT_RECORDFc.controlKeyState, (jint)lpStruct->dwControlKeyState); +} + +typedef struct MENU_EVENT_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID commandId; +} MENU_EVENT_RECORD_FID_CACHE; + +MENU_EVENT_RECORD_FID_CACHE MENU_EVENT_RECORDFc; + +void cacheMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (MENU_EVENT_RECORDFc.cached) return; + MENU_EVENT_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + MENU_EVENT_RECORDFc.commandId = (*env)->GetFieldID(env, MENU_EVENT_RECORDFc.clazz, "commandId", "I"); + hawtjni_w_barrier(); + MENU_EVENT_RECORDFc.cached = 1; +} + +MENU_EVENT_RECORD *getMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MENU_EVENT_RECORD *lpStruct) +{ + if (!MENU_EVENT_RECORDFc.cached) cacheMENU_EVENT_RECORDFields(env, lpObject); +#if defined(_WIN32) || defined(_WIN64) + lpStruct->dwCommandId = (*env)->GetIntField(env, lpObject, MENU_EVENT_RECORDFc.commandId); +#endif + return lpStruct; +} + +void setMENU_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MENU_EVENT_RECORD *lpStruct) +{ + if (!MENU_EVENT_RECORDFc.cached) cacheMENU_EVENT_RECORDFields(env, lpObject); + (*env)->SetIntField(env, lpObject, MENU_EVENT_RECORDFc.commandId, (jint)lpStruct->dwCommandId); +} + +typedef struct MOUSE_EVENT_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID mousePosition, buttonState, controlKeyState, eventFlags; +} MOUSE_EVENT_RECORD_FID_CACHE; + +MOUSE_EVENT_RECORD_FID_CACHE MOUSE_EVENT_RECORDFc; + +void cacheMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (MOUSE_EVENT_RECORDFc.cached) return; + MOUSE_EVENT_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + MOUSE_EVENT_RECORDFc.mousePosition = (*env)->GetFieldID(env, MOUSE_EVENT_RECORDFc.clazz, "mousePosition", "Lorg/jline/nativ/Kernel32$COORD;"); + MOUSE_EVENT_RECORDFc.buttonState = (*env)->GetFieldID(env, MOUSE_EVENT_RECORDFc.clazz, "buttonState", "I"); + MOUSE_EVENT_RECORDFc.controlKeyState = (*env)->GetFieldID(env, MOUSE_EVENT_RECORDFc.clazz, "controlKeyState", "I"); + MOUSE_EVENT_RECORDFc.eventFlags = (*env)->GetFieldID(env, MOUSE_EVENT_RECORDFc.clazz, "eventFlags", "I"); + hawtjni_w_barrier(); + MOUSE_EVENT_RECORDFc.cached = 1; +} + +MOUSE_EVENT_RECORD *getMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MOUSE_EVENT_RECORD *lpStruct) +{ + if (!MOUSE_EVENT_RECORDFc.cached) cacheMOUSE_EVENT_RECORDFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MOUSE_EVENT_RECORDFc.mousePosition); + if (lpObject1 != NULL) getCOORDFields(env, lpObject1, &lpStruct->dwMousePosition); + } + lpStruct->dwButtonState = (*env)->GetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.buttonState); + lpStruct->dwControlKeyState = (*env)->GetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.controlKeyState); + lpStruct->dwEventFlags = (*env)->GetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.eventFlags); + return lpStruct; +} + +void setMOUSE_EVENT_RECORDFields(JNIEnv *env, jobject lpObject, MOUSE_EVENT_RECORD *lpStruct) +{ + if (!MOUSE_EVENT_RECORDFc.cached) cacheMOUSE_EVENT_RECORDFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, MOUSE_EVENT_RECORDFc.mousePosition); + if (lpObject1 != NULL) setCOORDFields(env, lpObject1, &lpStruct->dwMousePosition); + } + (*env)->SetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.buttonState, (jint)lpStruct->dwButtonState); + (*env)->SetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.controlKeyState, (jint)lpStruct->dwControlKeyState); + (*env)->SetIntField(env, lpObject, MOUSE_EVENT_RECORDFc.eventFlags, (jint)lpStruct->dwEventFlags); +} + +typedef struct SMALL_RECT_FID_CACHE { + int cached; + jclass clazz; + jfieldID left, top, right, bottom; +} SMALL_RECT_FID_CACHE; + +SMALL_RECT_FID_CACHE SMALL_RECTFc; + +void cacheSMALL_RECTFields(JNIEnv *env, jobject lpObject) +{ + if (SMALL_RECTFc.cached) return; + SMALL_RECTFc.clazz = (*env)->GetObjectClass(env, lpObject); + SMALL_RECTFc.left = (*env)->GetFieldID(env, SMALL_RECTFc.clazz, "left", "S"); + SMALL_RECTFc.top = (*env)->GetFieldID(env, SMALL_RECTFc.clazz, "top", "S"); + SMALL_RECTFc.right = (*env)->GetFieldID(env, SMALL_RECTFc.clazz, "right", "S"); + SMALL_RECTFc.bottom = (*env)->GetFieldID(env, SMALL_RECTFc.clazz, "bottom", "S"); + hawtjni_w_barrier(); + SMALL_RECTFc.cached = 1; +} + +SMALL_RECT *getSMALL_RECTFields(JNIEnv *env, jobject lpObject, SMALL_RECT *lpStruct) +{ + if (!SMALL_RECTFc.cached) cacheSMALL_RECTFields(env, lpObject); + lpStruct->Left = (*env)->GetShortField(env, lpObject, SMALL_RECTFc.left); + lpStruct->Top = (*env)->GetShortField(env, lpObject, SMALL_RECTFc.top); + lpStruct->Right = (*env)->GetShortField(env, lpObject, SMALL_RECTFc.right); + lpStruct->Bottom = (*env)->GetShortField(env, lpObject, SMALL_RECTFc.bottom); + return lpStruct; +} + +void setSMALL_RECTFields(JNIEnv *env, jobject lpObject, SMALL_RECT *lpStruct) +{ + if (!SMALL_RECTFc.cached) cacheSMALL_RECTFields(env, lpObject); + (*env)->SetShortField(env, lpObject, SMALL_RECTFc.left, (jshort)lpStruct->Left); + (*env)->SetShortField(env, lpObject, SMALL_RECTFc.top, (jshort)lpStruct->Top); + (*env)->SetShortField(env, lpObject, SMALL_RECTFc.right, (jshort)lpStruct->Right); + (*env)->SetShortField(env, lpObject, SMALL_RECTFc.bottom, (jshort)lpStruct->Bottom); +} + +typedef struct WINDOW_BUFFER_SIZE_RECORD_FID_CACHE { + int cached; + jclass clazz; + jfieldID size; +} WINDOW_BUFFER_SIZE_RECORD_FID_CACHE; + +WINDOW_BUFFER_SIZE_RECORD_FID_CACHE WINDOW_BUFFER_SIZE_RECORDFc; + +void cacheWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject) +{ + if (WINDOW_BUFFER_SIZE_RECORDFc.cached) return; + WINDOW_BUFFER_SIZE_RECORDFc.clazz = (*env)->GetObjectClass(env, lpObject); + WINDOW_BUFFER_SIZE_RECORDFc.size = (*env)->GetFieldID(env, WINDOW_BUFFER_SIZE_RECORDFc.clazz, "size", "Lorg/jline/nativ/Kernel32$COORD;"); + hawtjni_w_barrier(); + WINDOW_BUFFER_SIZE_RECORDFc.cached = 1; +} + +WINDOW_BUFFER_SIZE_RECORD *getWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject, WINDOW_BUFFER_SIZE_RECORD *lpStruct) +{ + if (!WINDOW_BUFFER_SIZE_RECORDFc.cached) cacheWINDOW_BUFFER_SIZE_RECORDFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, WINDOW_BUFFER_SIZE_RECORDFc.size); + if (lpObject1 != NULL) getCOORDFields(env, lpObject1, &lpStruct->dwSize); + } + return lpStruct; +} + +void setWINDOW_BUFFER_SIZE_RECORDFields(JNIEnv *env, jobject lpObject, WINDOW_BUFFER_SIZE_RECORD *lpStruct) +{ + if (!WINDOW_BUFFER_SIZE_RECORDFc.cached) cacheWINDOW_BUFFER_SIZE_RECORDFields(env, lpObject); + { + jobject lpObject1 = (*env)->GetObjectField(env, lpObject, WINDOW_BUFFER_SIZE_RECORDFc.size); + if (lpObject1 != NULL) setCOORDFields(env, lpObject1, &lpStruct->dwSize); + } +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(CloseHandle) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + rc = (jint)CloseHandle((HANDLE)arg0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(FillConsoleOutputAttribute) + (JNIEnv *env, jclass that, jlong arg0, jshort arg1, jint arg2, jobject arg3, jintArray arg4) +{ + COORD _arg3, *lparg3=NULL; + jint *lparg4=NULL; + jint rc = 0; + if (arg3) if ((lparg3 = getCOORDFields(env, arg3, &_arg3)) == NULL) goto fail; + if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail; + rc = (jint)FillConsoleOutputAttribute((HANDLE)(intptr_t)arg0, arg1, arg2, *lparg3, lparg4); +fail: + if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(FillConsoleOutputCharacterW) + (JNIEnv *env, jclass that, jlong arg0, jchar arg1, jint arg2, jobject arg3, jintArray arg4) +{ + COORD _arg3, *lparg3=NULL; + jint *lparg4=NULL; + jint rc = 0; + if (arg3) if ((lparg3 = getCOORDFields(env, arg3, &_arg3)) == NULL) goto fail; + if (arg4) if ((lparg4 = (*env)->GetIntArrayElements(env, arg4, NULL)) == NULL) goto fail; + rc = (jint)FillConsoleOutputCharacterW((HANDLE)(intptr_t)arg0, arg1, arg2, *lparg3, lparg4); +fail: + if (arg4 && lparg4) (*env)->ReleaseIntArrayElements(env, arg4, lparg4, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(FlushConsoleInputBuffer) + (JNIEnv *env, jclass that, jlong arg0) +{ + jint rc = 0; + rc = (jint)FlushConsoleInputBuffer((HANDLE)(intptr_t)arg0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(FormatMessageW) + (JNIEnv *env, jclass that, jint arg0, jlong arg1, jint arg2, jint arg3, jbyteArray arg4, jint arg5, jlongArray arg6) +{ + jbyte *lparg4=NULL; + jlong *lparg6=NULL; + jint rc = 0; + if (arg4) if ((lparg4 = (*env)->GetPrimitiveArrayCritical(env, arg4, NULL)) == NULL) goto fail; + if (arg6) if ((lparg6 = (*env)->GetPrimitiveArrayCritical(env, arg6, NULL)) == NULL) goto fail; + rc = (jint)FormatMessageW(arg0, (void *)(intptr_t)arg1, arg2, arg3, (void *)lparg4, arg5, (void *)NULL); +fail: + if (arg6 && lparg6) (*env)->ReleasePrimitiveArrayCritical(env, arg6, lparg6, 0); + if (arg4 && lparg4) (*env)->ReleasePrimitiveArrayCritical(env, arg4, lparg4, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(GetConsoleMode) + (JNIEnv *env, jclass that, jlong arg0, jintArray arg1) +{ + jint *lparg1=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail; + rc = (jint)GetConsoleMode((HANDLE)(intptr_t)arg0, lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(GetConsoleOutputCP) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + rc = (jint)GetConsoleOutputCP(); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(GetConsoleScreenBufferInfo) + (JNIEnv *env, jclass that, jlong arg0, jobject arg1) +{ + CONSOLE_SCREEN_BUFFER_INFO _arg1, *lparg1=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = &_arg1) == NULL) goto fail; + rc = (jint)GetConsoleScreenBufferInfo((HANDLE)(intptr_t)arg0, lparg1); +fail: + if (arg1 && lparg1) setCONSOLE_SCREEN_BUFFER_INFOFields(env, arg1, lparg1); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(GetLastError) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + rc = (jint)GetLastError(); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(GetNumberOfConsoleInputEvents) + (JNIEnv *env, jclass that, jlong arg0, jintArray arg1) +{ + jint *lparg1=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = (*env)->GetIntArrayElements(env, arg1, NULL)) == NULL) goto fail; + rc = (jint)GetNumberOfConsoleInputEvents((HANDLE)(intptr_t)arg0, lparg1); +fail: + if (arg1 && lparg1) (*env)->ReleaseIntArrayElements(env, arg1, lparg1, 0); + return rc; +} + +JNIEXPORT jlong JNICALL Kernel32_NATIVE(GetStdHandle) + (JNIEnv *env, jclass that, jint arg0) +{ + jlong rc = 0; + rc = (intptr_t)(HANDLE)GetStdHandle(arg0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(PeekConsoleInputW) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jintArray arg3) +{ + jint *lparg3=NULL; + jint rc = 0; + if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jint)PeekConsoleInputW((HANDLE)(intptr_t)arg0, (PINPUT_RECORD)(intptr_t)arg1, arg2, lparg3); +fail: + if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(ReadConsoleInputW) + (JNIEnv *env, jclass that, jlong arg0, jlong arg1, jint arg2, jintArray arg3) +{ + jint *lparg3=NULL; + jint rc = 0; + if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jint)ReadConsoleInputW((HANDLE)(intptr_t)arg0, (PINPUT_RECORD)(intptr_t)arg1, arg2, lparg3); +fail: + if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(ScrollConsoleScreenBuffer) + (JNIEnv *env, jclass that, jlong arg0, jobject arg1, jobject arg2, jobject arg3, jobject arg4) +{ + SMALL_RECT _arg1, *lparg1=NULL; + SMALL_RECT _arg2, *lparg2=NULL; + COORD _arg3, *lparg3=NULL; + CHAR_INFO _arg4, *lparg4=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = getSMALL_RECTFields(env, arg1, &_arg1)) == NULL) goto fail; + if (arg2) if ((lparg2 = getSMALL_RECTFields(env, arg2, &_arg2)) == NULL) goto fail; + if (arg3) if ((lparg3 = getCOORDFields(env, arg3, &_arg3)) == NULL) goto fail; + if (arg4) if ((lparg4 = getCHAR_INFOFields(env, arg4, &_arg4)) == NULL) goto fail; + rc = (jint)ScrollConsoleScreenBuffer((HANDLE)(intptr_t)arg0, lparg1, lparg2, *lparg3, lparg4); +fail: + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(SetConsoleCursorPosition) + (JNIEnv *env, jclass that, jlong arg0, jobject arg1) +{ + COORD _arg1, *lparg1=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = getCOORDFields(env, arg1, &_arg1)) == NULL) goto fail; + rc = (jint)SetConsoleCursorPosition((HANDLE)(intptr_t)arg0, *lparg1); +fail: + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(SetConsoleMode) + (JNIEnv *env, jclass that, jlong arg0, jint arg1) +{ + return (jint)SetConsoleMode((HANDLE)(intptr_t)arg0, arg1); +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(SetConsoleOutputCP) + (JNIEnv *env, jclass that, jint arg0) +{ + return (jint)SetConsoleOutputCP(arg0); +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(SetConsoleTextAttribute) + (JNIEnv *env, jclass that, jlong arg0, jshort arg1) +{ + return (jint)SetConsoleTextAttribute((HANDLE)arg0, arg1); +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(SetConsoleTitle) + (JNIEnv *env, jclass that, jstring arg0) +{ + const jchar *lparg0= NULL; + jint rc = 0; + if (arg0) if ((lparg0 = (*env)->GetStringChars(env, arg0, NULL)) == NULL) goto fail; + rc = (jint)SetConsoleTitle(lparg0); +fail: + if (arg0 && lparg0) (*env)->ReleaseStringChars(env, arg0, lparg0); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(WaitForSingleObject) + (JNIEnv *env, jclass that, jlong arg0, jint arg1) +{ + return (jint)WaitForSingleObject((HANDLE)arg0, arg1); +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(WriteConsoleW) + (JNIEnv *env, jclass that, jlong arg0, jcharArray arg1, jint arg2, jintArray arg3, jlong arg4) +{ + jchar *lparg1=NULL; + jint *lparg3=NULL; + jint rc = 0; + if (arg1) if ((lparg1 = (*env)->GetCharArrayElements(env, arg1, NULL)) == NULL) goto fail; + if (arg3) if ((lparg3 = (*env)->GetIntArrayElements(env, arg3, NULL)) == NULL) goto fail; + rc = (jint)WriteConsoleW((HANDLE)(intptr_t)arg0, lparg1, arg2, lparg3, (LPVOID)(intptr_t)arg4); +fail: + if (arg3 && lparg3) (*env)->ReleaseIntArrayElements(env, arg3, lparg3, 0); + if (arg1 && lparg1) (*env)->ReleaseCharArrayElements(env, arg1, lparg1, JNI_ABORT); + return rc; +} + +JNIEXPORT jint JNICALL Kernel32_NATIVE(_1getch) + (JNIEnv *env, jclass that) +{ + jint rc = 0; + rc = (jint)_getch(); + return rc; +} + +JNIEXPORT void JNICALL Kernel32_NATIVE(free) + (JNIEnv *env, jclass that, jlong arg0) +{ + free((void *)(intptr_t)arg0); +} + +JNIEXPORT void JNICALL Kernel32_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "FOREGROUND_BLUE", "S"), (jshort)FOREGROUND_BLUE); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "FOREGROUND_GREEN", "S"), (jshort)FOREGROUND_GREEN); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "FOREGROUND_RED", "S"), (jshort)FOREGROUND_RED); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "FOREGROUND_INTENSITY", "S"), (jshort)FOREGROUND_INTENSITY); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "BACKGROUND_BLUE", "S"), (jshort)BACKGROUND_BLUE); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "BACKGROUND_GREEN", "S"), (jshort)BACKGROUND_GREEN); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "BACKGROUND_RED", "S"), (jshort)BACKGROUND_RED); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "BACKGROUND_INTENSITY", "S"), (jshort)BACKGROUND_INTENSITY); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_LEADING_BYTE", "S"), (jshort)COMMON_LVB_LEADING_BYTE); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_TRAILING_BYTE", "S"), (jshort)COMMON_LVB_TRAILING_BYTE); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_GRID_HORIZONTAL", "S"), (jshort)COMMON_LVB_GRID_HORIZONTAL); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_GRID_LVERTICAL", "S"), (jshort)COMMON_LVB_GRID_LVERTICAL); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_GRID_RVERTICAL", "S"), (jshort)COMMON_LVB_GRID_RVERTICAL); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_REVERSE_VIDEO", "S"), (jshort)COMMON_LVB_REVERSE_VIDEO); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "COMMON_LVB_UNDERSCORE", "S"), (jshort)COMMON_LVB_UNDERSCORE); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "FORMAT_MESSAGE_FROM_SYSTEM", "I"), (jint)FORMAT_MESSAGE_FROM_SYSTEM); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "STD_INPUT_HANDLE", "I"), (jint)STD_INPUT_HANDLE); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "STD_OUTPUT_HANDLE", "I"), (jint)STD_OUTPUT_HANDLE); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "STD_ERROR_HANDLE", "I"), (jint)STD_ERROR_HANDLE); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "INVALID_HANDLE_VALUE", "I"), (jint)INVALID_HANDLE_VALUE); + return; +} + +JNIEXPORT jlong JNICALL Kernel32_NATIVE(malloc) + (JNIEnv *env, jclass that, jlong arg0) +{ + jlong rc = 0; + rc = (intptr_t)(void *)malloc((size_t)arg0); + return rc; +} + +JNIEXPORT void JNICALL CHAR_INFO_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(CHAR_INFO)); + return; +} + +JNIEXPORT void JNICALL CONSOLE_SCREEN_BUFFER_INFO_NATIVE(init)(JNIEnv *env, jclass that) +{ +#if defined(_WIN32) || defined(_WIN64) + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(CONSOLE_SCREEN_BUFFER_INFO)); +#endif + return; +} + +JNIEXPORT void JNICALL COORD_NATIVE(init)(JNIEnv *env, jclass that) +{ +#if defined(_WIN32) || defined(_WIN64) + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(COORD)); +#endif + return; +} + +JNIEXPORT void JNICALL FOCUS_EVENT_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ +#if defined(_WIN32) || defined(_WIN64) + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(WINDOW_BUFFER_SIZE_RECORD)); +#endif + return; +} + +JNIEXPORT void JNICALL INPUT_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(INPUT_RECORD)); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "KEY_EVENT", "S"), (jshort)KEY_EVENT); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "MOUSE_EVENT", "S"), (jshort)MOUSE_EVENT); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "WINDOW_BUFFER_SIZE_EVENT", "S"), (jshort)WINDOW_BUFFER_SIZE_EVENT); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "FOCUS_EVENT", "S"), (jshort)FOCUS_EVENT); + (*env)->SetStaticShortField(env, that, (*env)->GetStaticFieldID(env, that, "MENU_EVENT", "S"), (jshort)MENU_EVENT); + return; +} +JNIEXPORT void JNICALL INPUT_RECORD_NATIVE(memmove) + (JNIEnv *env, jclass that, jobject arg0, jlong arg1, jlong arg2) +{ + INPUT_RECORD _arg0, *lparg0=NULL; + if (arg0) if ((lparg0 = &_arg0) == NULL) goto fail; + memmove((void *)lparg0, (const void *)(intptr_t)arg1, (size_t)arg2); +fail: + if (arg0 && lparg0) setINPUT_RECORDFields(env, arg0, lparg0); +} + +JNIEXPORT void JNICALL KEY_EVENT_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(KEY_EVENT_RECORD)); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "CAPSLOCK_ON", "I"), (jint)CAPSLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "NUMLOCK_ON", "I"), (jint)NUMLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SCROLLLOCK_ON", "I"), (jint)SCROLLLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "ENHANCED_KEY", "I"), (jint)ENHANCED_KEY); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "LEFT_ALT_PRESSED", "I"), (jint)LEFT_ALT_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "LEFT_CTRL_PRESSED", "I"), (jint)LEFT_CTRL_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "RIGHT_ALT_PRESSED", "I"), (jint)RIGHT_ALT_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "RIGHT_CTRL_PRESSED", "I"), (jint)RIGHT_CTRL_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SHIFT_PRESSED", "I"), (jint)SHIFT_PRESSED); + return; +} + +JNIEXPORT void JNICALL MENU_EVENT_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(MENU_EVENT_RECORD)); + return; +} + +JNIEXPORT void JNICALL MOUSE_EVENT_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(MOUSE_EVENT_RECORD)); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "FROM_LEFT_1ST_BUTTON_PRESSED", "I"), (jint)FROM_LEFT_1ST_BUTTON_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "FROM_LEFT_2ND_BUTTON_PRESSED", "I"), (jint)FROM_LEFT_2ND_BUTTON_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "FROM_LEFT_3RD_BUTTON_PRESSED", "I"), (jint)FROM_LEFT_3RD_BUTTON_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "FROM_LEFT_4TH_BUTTON_PRESSED", "I"), (jint)FROM_LEFT_4TH_BUTTON_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "RIGHTMOST_BUTTON_PRESSED", "I"), (jint)RIGHTMOST_BUTTON_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "CAPSLOCK_ON", "I"), (jint)CAPSLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "NUMLOCK_ON", "I"), (jint)NUMLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SCROLLLOCK_ON", "I"), (jint)SCROLLLOCK_ON); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "ENHANCED_KEY", "I"), (jint)ENHANCED_KEY); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "LEFT_ALT_PRESSED", "I"), (jint)LEFT_ALT_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "LEFT_CTRL_PRESSED", "I"), (jint)LEFT_CTRL_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "RIGHT_ALT_PRESSED", "I"), (jint)RIGHT_ALT_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "RIGHT_CTRL_PRESSED", "I"), (jint)RIGHT_CTRL_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SHIFT_PRESSED", "I"), (jint)SHIFT_PRESSED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "DOUBLE_CLICK", "I"), (jint)DOUBLE_CLICK); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "MOUSE_HWHEELED", "I"), (jint)MOUSE_HWHEELED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "MOUSE_MOVED", "I"), (jint)MOUSE_MOVED); + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "MOUSE_WHEELED", "I"), (jint)MOUSE_WHEELED); + return; +} + +JNIEXPORT void JNICALL SMALL_RECT_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(SMALL_RECT)); + return; +} + +JNIEXPORT void JNICALL WINDOW_BUFFER_SIZE_RECORD_NATIVE(init)(JNIEnv *env, jclass that) +{ + (*env)->SetStaticIntField(env, that, (*env)->GetStaticFieldID(env, that, "SIZEOF", "I"), (jint)sizeof(WINDOW_BUFFER_SIZE_RECORD)); + return; +} + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _OBJECT_NAME_INFORMATION { + UNICODE_STRING Name; + WCHAR NameBuffer[0]; +} OBJECT_NAME_INFORMATION, *POBJECT_NAME_INFORMATION; + +typedef enum { + ObjectBasicInformation, + ObjectNameInformation, + ObjectTypeInformation, + ObjectAllInformation, + ObjectDataInformation +} OBJECT_INFORMATION_CLASS; + +typedef NTSTATUS (NTAPI *TFNNtQueryObject)(HANDLE, OBJECT_INFORMATION_CLASS, PVOID, ULONG, PULONG); +TFNNtQueryObject NtQueryObject = 0; + +HANDLE hModuleNtDll = 0; + +JNIEXPORT jint JNICALL Kernel32_NATIVE(isatty) + (JNIEnv *env, jclass that, jint arg0) +{ + jint rc; + + ULONG result; + BYTE buffer[1024]; + POBJECT_NAME_INFORMATION nameinfo = (POBJECT_NAME_INFORMATION) buffer; + PWSTR name; + DWORD mode; + + /* check if fd is a pipe */ + HANDLE h = (HANDLE) _get_osfhandle(arg0); + DWORD t = h != NULL ? GetFileType(h) : 0; + if (h != NULL && t == FILE_TYPE_CHAR) { + // check that this is a real tty because the /dev/null + // and /dev/zero streams are also of type FILE_TYPE_CHAR + rc = GetConsoleMode(h, &mode) != 0; + } + else { + if (hModuleNtDll == 0) { + hModuleNtDll = LoadLibraryW(L"ntdll.dll"); + } + if (hModuleNtDll == 0) { + rc = 0; + } + else { + if (NtQueryObject == 0) { + NtQueryObject = (TFNNtQueryObject) GetProcAddress(hModuleNtDll, "NtQueryObject"); + } + if (NtQueryObject == 0) { + rc = 0; + } + /* get pipe name */ + else if (NtQueryObject(h, ObjectNameInformation, buffer, sizeof(buffer) - 2, &result) != 0) { + rc = 0; + } + else { + + name = nameinfo->Name.Buffer; + if (name == NULL) { + rc = 0; + } + else { + name[nameinfo->Name.Length / 2] = 0; + + //fprintf( stderr, "Standard stream %d: pipe name: %S\n", arg0, name); + + /* + * Check if this could be a MSYS2 pty pipe ('msys-XXXX-ptyN-XX') + * or a cygwin pty pipe ('cygwin-XXXX-ptyN-XX') + */ + if ((wcsstr(name, L"msys-") || wcsstr(name, L"cygwin-")) && wcsstr(name, L"-pty")) { + rc = 1; + } else { + // This is definitely not a tty + rc = 0; + } + } + } + } + } + + return rc; +} + +#endif diff --git a/native/src/main/resources/org/jline/nativ/FreeBSD/x86/libjlinenative.so b/native/src/main/resources/org/jline/nativ/FreeBSD/x86/libjlinenative.so index 9ad59f06b066563af3f73c6eccf613723053151d..13258b54ec0ff88dbeff89a99fbe7042e614d3f9 100755 GIT binary patch literal 8945 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 Dz}Ifv literal 4612 zcmbVQZ)hCH6`wn)iJCZ;;<}FA2D%BR*dbZzZ23>z5UjtB#7RC&woGj5Wp%fbRyo~X zZ}(KGlt$qiih91H)DT)IG~m)t?k5{++I~%pf!3NjF%qDN7~ z_B!xmU^-3rShtn<4a9LQ`o+F-e8_5gqDnDPX1|}X6KDslKdp-L_gVb<;N@MavPs+v zX*VN3ocPB@c1!!~gg(U|PR+fLbE=8T z)b#_WV2u>)2?yX25A`)`dnc`d2;Gsjec$m#)*T*Ar!C*~Ju@LJCu0XTx)1xlbR{uCHEM0)aGD}K*efn|E^7kYCHs*$Fawn44ARob`UZ=!@ z{EiZUc}gtcBIKiJ{}UzJ|3ZoO((1OA4`65I2N<<8p)~`Sp=igZP!{%c&>bD4Tv|Ff@d&t zcy%`_SAK??(v7CSZLds<(tQ1FiNO#qm8C2?Iu*`cLklM}p7`hNTE$sEf5EEZ>(NbLKcv;qoTEsWcfcC+g> zce`1q)A7>b86ja=J2%>#DtKwf_uGqZ7TLddz{$7;Cmp2R zywfw0&x&Mii{HTFk>FogEm_9b$sA_(aIfPY$UThNbq&nzYz`pqmuq0|wHLuibeZ?u zS8pIsxgRi5m}Qs^xy{X>lI0X6)>5>95$keK_)i#mEvSb}9(_Q@c~3+CHzdU8CY~Xh z-i4th@L$2)i&ojTx4Ymt?Sq}ijDnMOFsUz^2b-}MHmCh!vwQI9;TN3jNOQUnxaOd7 zAaNwoa>zK)l1RMJg8xU1#NlHtM~)pzoHJf?hYjQ@HppYfz7zdt_8YC{0TX-r!_+*q z7rBS?!t|#n0()4Peo#WPB}oxF(& zCl}}y``_}bfG{Q*BaBb-OOXyCydTUu;uz;-#Kn0YY41yGiW3; z&xm8a##t!SSLP}6n9SVML>%cHSmUk$Lq5)ih=?OQV2$Jbk30p|r0u;{h2y?K=3b&n z**iwrpv%p-&<*qbRA54nuxol6-eF27@{przriK<_gaC} zILfN<5El^yd34-^dK1iX`TdO9YI_@v@VBa?wg=d!h`CNuuM(BhN>>J$yGmChFh`ZH zzM8qHbSxT(IY+9KD=K7eDV;ZYl|xEbGtFF4I=@2YgwlB`Zr=Ut499B9{S#{eg^sq+L;T)SH}hYyNLSb=ricwPoc~6UE&+XFCq1O$8f7* z>{RRQJviPi=$dGM8Orw%Hdi3y@yEn2IH2c07QYvM4f+T0mn+Zq=b$q$NwN4& zaRfT^S?Tw}KIlupYkO}%*JPl;*yWy0;#>3Ws`h75_iN~!KN8=L3(&dOlK9rVxut!P z{j1)Zf2JN0?X6eo2J3O-@q^;Xh?&MCu;cW}0V~-vc-pd{bv~eVy<&9_wDoma?Oi8& z`X!*ZqY9nztkJADY-cTb6|n5$l)y2c&pLsVF0kSmfBd+9mOt=bSAQpn9`by=*ZgBZRp%Oi75Fdc CSE%m* diff --git a/native/src/main/resources/org/jline/nativ/FreeBSD/x86_64/libjlinenative.so b/native/src/main/resources/org/jline/nativ/FreeBSD/x86_64/libjlinenative.so index db84a083571354372a09378c9eb01da92a3502c7..fa506463291fce80485fd655ea3deb3583fb666f 100755 GIT binary patch literal 11637 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 literal 6376 zcmcgwU2Ggz6~61W<4qcGoWHgtMVVG9a*!DBy3TJ&wCmro**LE4K>x?%-Lbvy{#Y~P zU>Bhpxj|jI7Dk}TJP{sRl_!t@5%q;tT`EO95LF7Q!~+qeC{Yk{r9KoPSkAd~j(28u z(gq&5_RhKIyXWuzojY@1>CX%_MIt)|m8du;B2b@fc7YV(ryigRkd!zjn&Ej!JS1gX z>P-!`AGW#>Qy~-yppPB!+o1N1Ru^X)Ym#E(X`-x$Eb3KBuS$AMm(eg3rZJZlPkrR% zNQIEkCaf0)G3@#-_~9VktFIUr4jIa0e5n6<{-Piiqj3gtS=!*KxK-a1yR|Pw{t>_* z^GUjl4WwOsT)VPU@wH-1`=Cb~7^J5ZpdKdw3gKG;JKcbX`5gvafnP(>^QF8a^l2bM z*RzWTR*gdbWfRz(X_+&5+c7PD+A@kJ2v3&*4@HMB>0>0_TQF?fv_&C5HIvQiwrZEv zq|nWr;TWJkW!t*#7#8?7OF1#v+p9mJCMdLsXc7_n!`X8SA}>O~5R3QjKYqmKY$l546>m z8VG5t?b_uJ7H)ygkEPCTZSCxfVEguE(0RY*&j3cQZ9?;F*o+RG{o2~`yQsT%wi_j1 z0!a|~eG~dT1cs-v@p9FPgTy<44plau0w$=zsw^47D@y^yKgOh2D~!3}aR zs1JQ^kbeZn5afqQ{;MEyB|s-{coYLcX6iwvILK$}L9SE5c^P-du%#oSz{>ix22-*2 z#lyhtIU;J;wbkBFwUxUuY+2aCmG>OXhg^@p`4`R~EX6tFlF^wjcMjwWW}j(it^B-G zwnWFVuZyo@UO6X*#B@$bv4T;W=^VAnS<|+A7V-tiEl0=9T;4LX&S-w#94gKiL?+zg zli~pM7)#{kF%em8j~w3J8e504MjUhPhY*rCbshx_bK(1dzX??I#M{@JGVzDgaU~t^ zSZVog^Xt*Ucmm~~hhOi%KU)q>V1bn@i_10gj6-O$V9vs_+a=rQ3Z5reINvwBtWZd? zg?PDZq0W7qq;}3Vuag|V20TnWOua0Vlvi-`W6@l)J)V3PK16tx6d6wtAEWklqMW1H z9}Hg^o7zbp21)Wf4qL>3LV^5)c#ezA{@)0{mjoSl(M0qR9V5!;37;S0=zwLKJ>z|6 z6w54_u(VIBPjte0*O|2!I*nrPM0aP_a`Ni9(v>`!OdMCb63OIO67YXgNuD^9IC%7j{FHK3;0bs}=@=ZjcueV5yHr@X_k-MD2&MZALA95Pjxi-v+p%0a%e7g`*tDJ zEMyNGT)1Q|3#Pz|QOsw-MHv*~p-OA6CcH?1Qn^?(OHObm|2O_HsNvq@b;h(pN;|e zj#Ok5e@_Pc8`Q`3jj^!)+ob1CQHyi<6$%k(JCPdQHXdl6pwD_f3LkL zWLVDUe!OM-{mYN<5S)Mgc&n&}bT;h%1NEX}r{Fy3x3g>eUdoR*-eo&e)%@R zdB%^&xATY}-y=9b`0;kZ``(Z5h5ISR3(0yEZeCKf&b^IMv0qGv;s>_x7yR-E1@9L> z&Zll2#p!N_d!Rbv*6=$aA{zU9NaBtC?T~omxIHQH#&OU9Z-QGhK97Kv1;0}wq8>jl zNB2BBAow1I#09=?p`B{r09qzHRT?+WSNH0#oA2Y|N?=}oB<<`G+wa@JV{!9in^>oO z?xI5c5-Jh69SY8S6>!<#9W3e6KL80E|63^Ev`hSg^2D2@_8@d1()4jHxPFcRj`A^* zXE$G#@{Q}{B-shBtMgf9~euY@7H_! z2Zu(az;LfeI#we`|i}X8J$d}BL;p8uw(63>*9ns6yj4oka;`(p~ zL^Am)%dnR8lKD;V6^PLLo*7A>AL5P71 zU|_s|LZ3+YWcu~{a}>Cv3EuU(*TCU7zNr*n(faOg-8*Bt)WwV3(2HS@a>xzwe*j%* BRMG$d diff --git a/native/src/main/resources/org/jline/nativ/Linux/arm/libjlinenative.so b/native/src/main/resources/org/jline/nativ/Linux/arm/libjlinenative.so index f67f1e324d9e5624422afb1afa9ddc1725d63dfc..6791f478d8bae5c470ad5353f7af11e74ad5ad04 100755 GIT binary patch literal 20996 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 YJWMfHBPE9jMT__{aLU;No76}6e~CXwz5oCK literal 7744 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 AyZ`_I literal 8696 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 CHAOxE diff --git a/native/src/main/resources/org/jline/nativ/Linux/armv6/libjlinenative.so b/native/src/main/resources/org/jline/nativ/Linux/armv6/libjlinenative.so index 189d638e48b7d047b254b5f7046bd06829ea2ca8..bfe35207695696e6fbda1fc580d62e60163c305f 100755 GIT binary patch literal 14056 zcmeHOeQ;dWb-!1^;r)8RCN{b|C69*xmX=i*jXU{$NoO|xM=YGETj{anGZ?|PxLMN|i7Nq>OLbL;aX)S(y zqN-ikq8hxL#Z8j0<%!>IP*5ccEmi+U=(y36&<=%pK()*F05^c&06yV7Xae~@7v2We z(1bie^X@3-V<10}SlCe-32?)@R>{>j7TCmL0pr$w%$&=a-)P&Tk)mZ1IcvnLOwwr%;h zgZEwtoGSkDUrlwNUH+xF)_?MAeLp*MYIxOw*^fQ+gZ@j>p3~xMA~3W`Nzxne_lqP zH!84xi&h3~1OBi~epwmagZhma8h4519OyfEzIh zPPudl?d?H(oJ-^j$JslaPC2=JB%5~};q>%xcVh8ud~YI`k7xV0cO}!Qcza6RzjA%L&Pi69>myyax z_r~*)eEvhmpk!-4np>1yA_rxcZ8SfciVVlaaC{hA1uBqqvLcxnj0SS)zB`t_D5o->vHxMz68Q&=EAr z&BSwxdw9Kzxqp!k0{=UZnkpzgbXX8;`9 z4(RBBT&aGrYx-+97G|2EvupW-(|_xqyrjP8pyxDT4`2iI^`c%c^w9=k|Fg8;wSBoC z{%r@}6J&q-&SBV>G}A^g@$;|G&%gc>z_JVHl-;cVcSS$OA_?6#APD^%fLj1(;RgZR z(a#yq$=^V?2p%m?`6r4E!DB_skNTm)j3-=}SqB;656@zXtQG@>bJe0SQ+IZJb`H8l z@ObeMY&tY>tT^V{?E{~_^!dk&>si+h&(6)yFQKf@f1;Rye#%I_C}W>TK6k9RRrh_{^5jZ1pTSSrQmhU!&d=QfUg4nzxAt7pEDJ3<|cexf73*ncn9C46}pkOA}q zIsn%L8UYuuH~u@IVeLfmSMayoAK+K|m;SZ})cU}(TKyHQy|**U*EJdJdG;5JoTs$o z_*yj<9EUoT3))zL=Lb)YO9fs%cpQsL^;p&bKF8r8+G3k}Z7sJSnHBbUk>hSZtavtj zA+S$$a9zQsM%1mOx4o=A8*pDdnseddFl+&3Vn`E>@LelF+x4Zid@`p9;4{d$AX zx-4%%8QZ4+7JT<;$#=E3vMqG%Sdsqw1Nfo6Lfego?v4t4_REG0+mL(c!)MMI(=Mk0?FpT@lB*m7<*V_fuF^#%3bi@pa> zNZEssZN{2tG33<#ydbm3l?h%#W&>n6H>is~W1G~&HO9HYHP(bR#`%%K8IfOZiT7*q zYz_Dk;JbjQ00s1c`xtF+`jBs#Ij1KdJcfJ5lf}8JZ>U#%w!EJ#5t-e}U-%03tuS$q{o?-HQ zI$CUZ&!>a1G4#+eX(RV>&VAZQpJ^Kf^w36qW?f+aP>+1pB~PDiW&&5AT``Nx;bF8EF@D5ambxJ;U znDyH$)c3o4@3ZjZ-SFo}0dFGT4LAc>*)PN);Cf)5UCrSWMUmkiy!)JI0B6D2i6W{j zS!&}B1v{?iz8nhA;!e5R2R^F4RuzID1?B@}Y9X`yw~zskI&fO9#C>oHd8}Upx%JRN zd3`Q$?%4xqH_SSBp5qzNfOfI;aTmlr1!oY~-WzT1o~zr39NVuBDZRS=w=ST4@TiOJ z(|+E4$gjiMMqQj6Rj`5MPMf%X=XT<5dvw=q|Jm)cw8dM%J|8+!9Gg5*#A8g!ma9;| zWXnK!7LQ7+tHaopI-Hf^`*Pw0<>fM5ROQ2%} zLfSggSS|)ELyFUIXflz+dPqli}H`Lj{XGUy$c2?12o&NKB3wpP@g|jcdSSsYdOww&i8)K;HgH*tbp8hjS+gebf_%?Vb?Y z6?dHThPl6S-j2^cMjzt2#u5dKx-9BKeYSTu+M=Ey^sw#Nh56Sq(!PRRKO0}&K6?S< z$F@1A>cseLZD_pMk9xKK@mZ@yJty%Qs262E5vK0toKu{$^y^a?cRuIvyxI8bxI8QQ z49(}~+p*n#3V`dU#C!)p`r|HM=VI6`%Q40h*SnbSM=6g-28o+o%y)?_|2-G;)d6YD zHHk4dCB~$Z7)Yl3@aC#Dk!~$}1=f7)oniyuD}74zh@qH}V#!EqZ)-T4j>dDjjr$Wx zyrye1UxW1wXOg0~vc}uRHW76aL&?Zq;IxaQE>22(??$kqQOe~q@pz1aD$^$($T`{c z14Pkul4vB87>Uc=sLJ*A+_QOSx9IQc>)f&PE{Qko>g?GebKSkW`?iYyo}FD=?&{gm zcaO~WsjT?FHYR#(uHY*kxZ;5;9=PIxD<04u2;v}r5f^O>1^kA9*I9z!H+dg;5#QDL z?U&yR_-z<>5?o5ucY{WkW*J}E|N8y;^jTosKgBdI8@y)(p^x{2?*a3E!n+CYA;RVt z3-!&A_Yi*j<@bjTXqR~(Fz+9H_s;LnFi*TcKc9XXO6P%TE8Y{Qp91|Ju+)jN#Uy@z z*XbzQxg2O&jrpx)OIOz??dE7Uoy+CZ>ExOnTkN%gwoe3tfwuKdY;gV1ZNYW7+H2Pa z)&+v1lW)@_@yK98ShpZswf-~ri0YbJ>ndxBXN9lcT4i19ZLqGhR(l$)o2^Z*c`Xp7 zkCfNpJ2-)NGmZ`Y!Lgz5bt2CrK89aadKhxd{jf|9VFDN7a@Q(rbXoE z=nRT}AJ7X}5V4jE|FyfX^)9=9*~gcy3ey0iy7 zJ6+Xc@R{Y*QfWzPUs3c@x#w%H*3TKIl9K1#Q)ww;r4|z9*`6LRA(jceqb|`FXtv*O z*z;+F*7oi*_{@$Nbf-aU`O^lU?d$Qxsipd7@VR5~>|@gP8`U&LNu9V4zZ`%18DGGq z|MYy~Np%3_nzlew70*+Z>ck0y*827Q#7K#6fUju_H0{;%jS)*PDn;^F`=7BgDyi|@ zV9;zoWYE;-;{hyFowSd!J(?!}6@&g)%>vf#%^7^kx9jr){$YE244V9dYMCOZ_=gOd z{O8oNE%Bc>X!4(u#{e>J{V9Vce-AGaGAaErgC@UDEpz6ieT+R)N%?D!LDPQ5GMW5m z44Qn#9+~`i-EBkbXY7>8--`L7(ke0I=7{LeO6wy=qh(U-L(^OzWa<5lN8=j?ZMplM zs;l(B2ZH{b1Lk~N3RCF6NteC>wBAoWxZyQ{=J+OoDSsO<$Ftd`w*qtgLN0wbuwG9V z*3%GZ_O}W8xjr(W_5Nz1zoVd&;Ikj(KMb1VrR_NmTF-atD}WY|XJY*gID7Q|x(=Lv6|lrNO_tE=UFc-o+!RZT%k$i3^I4BAH7>!6=EV%1jSY&2uz zHoIpf>vLM{E~68m&Dgd)Xfu{>!jQL7|C^xASiJWQKJ~AFKg`&>jiAlgyZhX;8luvk z&zI3(V14Y@G0CqJQ>>5q9d_xTg6975W0!7FR{&5L7C;+lGZt?*Xfqb?^M*X_Jq+56 z&HGjvUtN6CqA4Pxkz~?&ARf8j8A^#Jys6_wDNU5i?;jcpL4av9z-{nI4QJofv}ea!zFbh=`_9GoFvfa3QZK!C1e96Uk;HqfR`P z&yI?rEQ7XU`-g`|QN^HS1l>iVG89lo0>)uz6xTln0wQ~VJe!Iq*R>(*INiHCw{Lbf z@7RQ>#AqbCFYd<1btmGFyn!+k3i%ZYU~HRTIh#$3cjsYo)WLcjv~=UT0@_ci-lIr@wP!?`A|)UKAS{(xGha zmkhPMbU@=}!t~0+E6sPrDz4D5q7=$!lwB@Q92ll4+tB1oiiI|YozDRDL2*gHH zsHrdlR3+y?Jey0TQx_2k91UdSNy@8CCYcuj+1EfmK7u^=F0j(ENIoJ0@qKEyQZj0z zQZhOZO_AY56s@FDTh$uOTx~?ir71TJ27&Lt zbV3!Gw&IuXvdH2yHDNvSx?PqN7$47fU(EAan-D}^zHnv-`h-or{)eOC@hd=8-H^t-e%GTcOcgo6Mr$7fW+ z>C)YQ!On*aIo?$Xv|A_YVtNcfee5rvF$qm1+@$4>g4S}pOA|DYqB{Q-bU2A{s89Ph;Z|DW^7tG6ghAN%z^0PUlky!+Z}4v}PH zn}qKJv>fl?AzPKBSSD@j3!tc%`gphAWPeZ}SmN&i)W^BRM7cFGr+&yIybOS@j4H)= z+d{0>1TbZoehSce(x+@h2{7X(+QjrLfGH<#LM)2ps2|OnFO%zrTvG)(KI7;*WZwt5 z7c0nJ=gR5+w%v>fi!wRt;WH7jmU{$p=9?Gt2>c%}Vx7JUIj%RIG>_Prmf{u2O~M&A p%DM4z-24EpNjV3AnGWNn>kssxg4X)@IBLq>0YmjWW7gAh{{uOu);s_J delta 2784 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 c)K!WMFK-SgZr%)8N2%jj1 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 G<^LBzf7rtS delta 2594 zcma)8YfKbZ6uxJ67WW1F7?xd7VU|tEmZr;U+huJ@L_{kFm0Cj8n9O2D7i$p(pTV+_ z*3_n0@haES#EOZgf13D8r0E~y57S!PVr&zv{UJ7ON?&5qv>1i$xwA8{9r)3+xqIe* z=bU@by>lLO^`e*@5RdvjB#Wq2nP!C8dP}3Wn~wDKrlWUT*g7U?!rp<@#-ivq6F+_F z>%YB_Na39w$^}0q`Sk;OAt;+o#7a(|cnDs4O7OrudO`4sYtfip0FYR#56twk zkPD4mz>*S(eA+pN8ZMGcLPU2K0VEUp<04)XGvJp|=84}wZy&w@fmpO7$=cDmtDN+?C6!hv zLCj45u#~|ZI^XKc7geqFUnoN-i>|W1*js0zl{V4i@9G{sXF7aP7L%(5Qd?2CpElS^ z+}Q$IftGQzInCqLElc#Y&E@4vWBaONT*^mTSMj0{ecrCPlNo5Jt2-8=XYGpBrJ*63 z?I<_PU7LRSg4Q^SAVQnf|HF<~Aw)+Uk|6J;e>)BpoZM3tJ11B=2nmi(rn)Phy!Tct zLY^AECD6X?a@-#sTa1!x6_cqm6~3OcF{y{%&)$?Htio1IzQcB+{1l zz(rtuAQc$*KBlF`Nm>;wp6`E@O6l(!7sa3_cS8Gf3; zg#HZ9iq9d#v*H$#;3dSQm6BTYf9gp3ZoFpMXXGuHn(&sM81gxdXOo13-2gZTGCzwC zLY#ToDFF`DxC~pAqm6*6o;2VqHGIr~#}Nl!dsw3hd<79LZ?!@}4r*ri=CETXST20- zVBeb{EZnm(n+PQ=E`py$L=Za#tUK!r{*Q2L#J3ypKQ(-#0e_4*uiQrscn%f~AWl*@ zk**%98ve~yr+D9H(y3!AuTTwgiC%VeVGZKkp;p5N4H{l=z+cnwxB+iP9Eh95ryP1E zy~Tc2Fta7RjkwyA4A*~A)%OsB_m@e7h|6>VNFu{0wGC|{-{RwJ{pK#>v-K4$jJ!|G z2ser2cniih@r=Idfv3*YycB<<7HEWe+tE&}-eU%N7FiP4r zE0VE9EMxNQ0-{u}U%g~i%~JMT4!mFv*RNR`W-mKo5p`y{*fl24|YEjpK3 zAQ#GPdTALH*@j$*+Vqk#EV6!_yY)J!^9UQ^W*F%zoi?)qFGS~0RTwRN>d7RtJ3c6P z>oE|*OyJ~V0Y8*uaa!+(#ojs%U7YKk)0}7jR_!S#nvP+fnWlY8A!Ie_!wp;WZ20}cIFL& z2fD-|uH$1$L^!Oc{@@&`ORHzK)%s&C6%0$n5{oe2Ae((2w@Autz-is20~rxrHY^Jl4n+WYA7(17(>xcA1gKIORStX5I+_v$MVXHX+=18QBMgPavZk zsjr*_axdh}N5L~wP94mPfw!_BJhLSWeyGMOZUArQcOhf8@QcQ(+jsxdQ@;0~jTKxUP&VGgjsuQd(HCYU>Y|Ogr({Xf`C#ZY%jvDA7k`#CZ8~jZ-&A>UlSq=>=hXK7SKOIM^Bmj(~!@&R*1DGe+u-zDj^n_ zd=>PqsurTz`#>ul_><7*hdgA;mw-Ngxe-I`e;N3v!CU>`2>ed8{~9Re z?|{AtdsLIJM}KcZ-}RC@YhRR9s0#)Wj-fK?}+) ziRGC{W{r}H-`|u-#^=Vf(M+O8O=m{dCKQh)GV!PyO!T0`bM-RE>Y=u_cG`@^@l1Cj zomCR4ggO#@M$fyzWWswNesc|pr?UktU<>UElsEiPiHtyP)cd=Y56C!Xq2 z*IWdpMpwkuh^n4v4s2W1Xm&)nL>9^}+NruG73q!(AW4;sNG6s?YqIH@nPOf`bK@Lk zT1{Qebh})O(3PniD;FR&FNqcSA9 zrh|I8wuAcX4SEv%SX@h=kzye|O^OBgOHu$mz>T9$QY@a8q_}5PkzxU@CPmLa(o4l? z8uh@a2SzVZ)YjCx?y1EU@|j|al}6YkPB2zv)U$0N0tKdtL}-)^;BKak(+zIQ-> ziBGlqGu*2&>Cf<~w2Q^#M*-EJ;m)s%;^PM-&nMq5RvzCic|0_UF8(|IqU7bit3G`f1vpCjlhZ0cKqvoYdqQm6?W>#pQxDnc41&o>H0lil$RZT z@3dN}ZT^xf52}~KO~E$(AQWm#zl2UhTW3F&lsW+F9eA}y2Q6)3_#mp< zdWxGSLtNbECq8ft4MK#jMt}LeK3M*ocBP*42KC&ru)g_aS?$#V$BOaK?!8Z0YFM`w zihBotbgR?4o1pObU|rkqVBPk!tkdrFOAFh>rC0uk6Ld9f#8hZGcm9p_uv$#)`wIVq z#Wz->qo6ic&w1MQ;M$^=r2SWSv<2G>c{)ztOrI1VQ&C^YKa3h}EIiZ^(qE#u-SAoQ zv9(gZQOeH}ZjeGo_PHBxlybiK(8h*}k8J`wT>lmc`TluTJSpW*oU8vremkmR^vS%( zF9!4L!C_2d$XxFK3Vs^=_>YXa^dQo-oG1S#u_EUQAv#Kb0|??MsJZl4=?DhQ7AVq| zcnjs4E5FyHze)$#^{w7QLxm~e;B5gKG`dXzM{Nt(!ea_JRtna#i&n38Wq!})1&@EF zZ>0z#CVhAmB(hq6m7}&*Q1=W|#rENXSr~KSfE~f@rA9YGc;DwY3xVrPj(VLZ|Bvg@ z4xyN%h>nMYuz9PT3l0tgnETP*J(i09L z+Kt!hJ*JS}u!VATuh0*uI-eiv=?BYz8KxR~#8wmV8hy+%h1(rMM1?a9Fw1@a%?swk zsb?;jWx(Tt;rlRLFwY{;&Rj6s)kSS5YK#je28eaRydVRz3pIAkQ*2)_uSj`P%6Y*I z5$=}4p7S&=iOlUr-{Ss5sE&DXyb6vSk%)(tKJa z*WUV%o8&#RqaAlid7s$)4kpC*qUO?GTZ=a`#yz7RrImN`w(>KlrfE{slfSbj_i#<} zMtC!$a&Qr}aW<=sSPJyzWG9;)PxPg*8|xNX6>1F+h{!A=AE z&qJVPL!bbeT8rEM9XPh&q)M&jTI(?y`W|f9^q-Jw{p(=>+7y-?D{kXmB?KE_nbBad z!Viy&t}7SgB61oedtuX1aocIOLZjAWMkDlLwX0-1_6Pj13--_{Ua&K;$H||#Maxxd zt(ASJ)EkO{qlMN(xR2>Mcj;Hy%y1EFJyaO1+uf(7kA`+~Z5rp#VZOs_N6# z%0l2!utT;AVd>KXhael)Wkhzl=MULsb$(s7&=9|^mFnb>Hg2WRbJZPk3@0!wjG?d( z8qn)0+3TrbyXZ)C4*tyZ&dZQ@F-4s07Zra$VD%i1wV-=)n^H|B11%7|bXB=hUM z?79%>*OvO!KL{GVdpq=gc3lW;;jnh+JjY*y?*{{0I0gB2l|r4=Za^z7C`|-%+;L*+ zPUY8C!KyX`R0Ysc>f2Mdo3Q;Dhg!E^T0XfLcpfXh9P!4|-(d?4gx0#T5U2*2V_VR7 zM4c2Y26hC)@XE%Lf_2Hn48SQz)Ty|xAP8$q`=O@|F4$7)$NmvoFxeknTDQOM)JNs` z4}G+%Z$Er>{Yn8ZR>4>O`eS(Mid#TGw93Iby;&&{rZ)|QSE#=Hx-CMzmL5lMh=Jj# zA@g0#Js&QmU{UYDPrlA6|CY9{5;0U>cMAIgMo=Au^o))OI>iXu5p3^Z+--wHw7?F? z92&!=8>F&cscfzmsKS2pn&OgwXrm|HrR3*QTiroaU%{$M_VMJeWo_Xt?3xP)_H%z1 zE*(Z?@4zgn$V=2VRLE`hlDgfm;{~!{s1$ddz*>q8j6`1wbngi-*U+4Mu&)FWcfrV0B8o39~Qg;>IZ!vbUx@D+|yTs&I8>DT4@GZ*#jX_w$@#Cou{JWVc6y4*pO>K z)^%A_yz#Oz4c~JGAF9ZYDSv37VPC^w!;jH9#KiOY<-HN&*(c}YF8G}7nW*Cf zZUC0wJ=k_wK6I50aXNLc2fiCI&+j;FyycU`8AFJD z9@v+GU3)HU<_wm090s-m*ATzA5OlTer2pn(E(2$j zL+nGI1^i0jn^Cs$4S84j+#e4xii!CaFq?q6ei-H+10wrf56mOLBy3FcWn*N&^U!Z- zNWYBp7l9uD-imY9?M2;7jykFuO`{$d^}whHMm;di#c@-_KiVCJbysZb$A!UWNP+vcDeBmviRa;hQoyzC000`RZzG@agES zGpCv*-?Z9kb+vVMwU(x#bTJJ^GENoce+F;tiaAb$r+48#n>Pyd z7n4hjlazjBa!JpjfH5$+aDsu!XY-sLA^L5evt*ooAaxm0Am`uU84XB2`5*ELvcPi$ zOfE4|(gQYcC}!L+x#a8`abxhDWteBnIop_9n>U~4>t!|CUnL8Eo4;D}^)}BaI+I*@ zqhY#QR#u2lb;k9J=6K67K91m|gQw}d4wxwaV^Hd+o-#z~98i9{%T$IaT?xu-hl%)A zpw@WHFkXHgU?ukdjKzSG|KTuxxV^7Kz5{RjnaZq*G+5bw5asQ#pOM1;{{_?wx4dKW zCqdr_&*yH+dDMm1GgCRP?s4F^I_#eW{$DXIe8)gM-}zjEX*ebE9?<|^2hVo|l!rj? zw)J^L7kF!a%EZ+o2Y!7$>d>D4`!4u-4*XW|*8G>@YJUp+GT`|xiuj%2S7TcF9)SJ5 z4&I74{2nXb1wRFNCicfQN7R!ef0g(c{1GF}Wc!W0w(R-7MDSgem3%1dH7+?>MVJqA z=Q)Y_;GO3(9&og0H;*{@$>9IW!BhS^c;`8bz2KeaIzDmWeZYSO-gz!$p}96dB-hC0 z;GO3{HiLJb1Njkn=Q)t0;GO3{ycnIqVhB{8A(2N&;xH?UV*)%ug5tO1 znN&PEeHx02(iCcF4Jd(yb9tOaSv_lJ4GuLZJyAvN%B8+tvm91NqFr(Gs6|sEo{VJ$ zAVVvpq33EJGuxX7O3t(&T7d%+Lo3c{8i?XPxDI8d=EN*CQ37peS zG1zv2vp^R@zGw4$llb z1$E)k*)2zWn8!Za;xzQ)XO_&F9myFa+Z7i(;bR`Qx$p=_cw%b!JP!MDM#j%M&x>8S zcX^)5I6CC;mmO1%x(n+W*_kKvjFPCyuIW}I%R$wQLA$I{Dy_zAR-|$@%lT{4t%;bB zTvsI9C2C@8QfO&V9GsGpRq;$VkxmU^aIUE)6HgLv6nc`XsF7o>L9u2<8mt;$jsILD zfl0?AYDCn;yUbOwD+U!7XEZgIN27&RMhB7ZL=>H;RceN5QqS^iR@7jD?#8-{JHp5k zpCh4<35|2&nH$QmT5jRpEW4r{+qcLWvgG-GxOXepG{cizMPpjXTM-Y44J!c;<#UD zrp=Z<;`yA@jZ9o4GWYS!R=?c+S~%`AX)DCWeg=c{v1}&dn7)H-;kfT-?vWDXA6TiA zzd=|yJ`XU{9xJiT+=p!8xbI|sK|U-RNU$<#_;2C3-()s-^HOfv_o#`R##*0|U2JG3 z7MUM6DgEa>w+vP$OWzN`5l-{T@Ww!ijn?wP#-+)Oo~# z^8@Dx&gv5)yZmn`vw!wmUynUAa50pvK_z2>}Mee|Fky2v(vvB_lQU}0- literal 14892 zcmeHOZ)_CD6`%7NV!(g{RHT@w+w>HmEsN~{g@VEv|G~Bl_#e;;(aHL5Z7-bf+`B!n z)2Ow%kc3_?SW(iXUn(T>0V%4~DyU7Bet;asv}!9it*S_EB~%f~QLO?MZBa|R{rz@t zoVDXt6y-~+edyhrH}B1xncs|enBAGLHMKW~LLs3jEW(0Xv`UE0kd0eC%Vwd8MPj}9 zxOm95D}TyJ*yD04DCb6lWSaa^na2zKb`462pGE<)zkGBP+OW&xNx1$Byb#QI2q#)# zZ-JeB9y*zJ#vu0~p5h2}va)r&XU7wo5Q=xgMppJt*r9%i7@uA0g5BS~i^wChJgRl& zDoDU0_Ut<#UVitFZ9f=Y`ode{pvB=hzI>C%P&@pLbz$xlWN=Zo8N!x zfq(a)5Z{7afl)mGxg9#|rTzruE}vaU z**};{%8YHKZ7GFp?b$2iX4>qxGParS+1rpvCCwhAH(`3V`7JUwY{)(- z=`!P1+Kky9){u!laXwW*HkM>%)YET5UkH$HQ(|)6p~L{)rR1On6d({F5FijB5FijB z5FijB5FijB5Fqe>fIxR{x?<{c=*U>{uh>%Ob9WubId#!4b0%|_D-IW(H@E?E&T-#F za?ag^L*KZkp}^Wmv2Xl?e^b|B8GHM6#43E98_~i^{%*f&Kb${#$BVu4!0GpL)2ljJ zMb(ds1^ZDkUMyUA6nh{OTO_y)Ddb)UN>Jyj#UKV=y7kBJc`4?|9 z#hjY`)3 zFme!MY769*934Zm0th@8#t{2SPhrc9`c&&RGfyXA+ z%xc{_1pEkE*ZE(x?(BzJm){vF3U~f}{~sKm6C2qr%sIjoP=G*yK!8AiK!8AiK!8Ai zK!8AiK!8Aiz(3>4h|(m`}`4ipxL47@Q!Ve{LXyghU4@=UWOco{2BJ*&qMwa@+{<+Z#m8+ z+`?!JCmMf0-Cw&hFg@?o)S&5lpk zMIK>(6x;|O^&W$HtbaS|V|z&ajy?eX4D$GGT+}bCI90ZL>4N%a!yV6*=N6PbQ>?#I zKT-c9R1P!!Uj={j9{pM8RqzAo8_Ne2AP^uBAP^uBAP^uBAP^uBAP^uBAP^w%zk@&x z&PiXx#*SZ)c{qG2#OMlvbMoGK<7!Cm_11uS?wEU3>VN*Hlj3(=p8byC%rW<%uR&i7 zc?G-#%>5$IiF5OcYQ!}B5L$2#y%Nm5?B5(G<@z9fKg9F%ig+G+Pea4!we^i=uVo~) z+8Vu1uidzHLn)=z)zsD2)YjIh60;@G+mpN-1VXTXo{olt*gq2Q7?9X+QrJbr>z}6+ z6%YXcgT9d^(SGFh1ji5WfME^N$ol`;S6$?vfbqI3&-i>_=n5a|??d0> zYo7zX1T)&ZP%J=$qUbOGmKeVpdP1WUsZ!|BM`!9^EH*<|;}H@oL>qMf9f+r(`|m(J zOaBsSkl&c2e`k*VQ|PnqOqAv}L$JJvrR|KJ?d#KH;)AOb(jJsCUY^L{jzv5r`xB{N zBO&9s;gFF=c38wxc&BFCW?ZkC--8z_ENP_E#)veNc6vngrHw&T#fEm|5 zW?bW$lpHXUab5tKr`)h`>z>cn3!B6x8QIiQs=lSMOSrufa!>pI-SzEqe{*wpQ;+Pa z-`(CM@8jl&@2ZKMeF??A$uj?KmH%+Z<$ms~%(+4%^vuYhZS+FgX-^KQR5E3odVeyj z_wpU!4>*Y!q)p!NZ95uemObdlZqR*A#`(~ zG#v)wD5*5Bs5dXX5-N?j#-J5L^(mW?QL7uLHfjecB1$b8qT);ao-xeoG4PCu?Kq|{r61R>#((4Y8tfbk`nh)k;ddTs z6_b+q9R{;~^y6B66MhOaWX;t3ZKRc-h(f6;{r?V0662A-2UdPuyDH(Q>V#<~{X?W# zKkKcEg6H@#2I&%*X_#H2-?~zof;PpzVHexrSA*cIVdvio+fW7OTxOk$1|9>RzJiQJ T;xg;^JF!KGpSTw9NBR8=Bms!! diff --git a/native/src/main/resources/org/jline/nativ/Linux/x86_64/libjlinenative.so b/native/src/main/resources/org/jline/nativ/Linux/x86_64/libjlinenative.so index 918a45b3b94eff499d25915ee00f261f86c5f655..5772a253800158fe7f5f4c8f1d89cd37c065e07b 100755 GIT binary patch literal 13688 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 YPW@V~jBSI88~>MLOV diff --git a/native/src/main/resources/org/jline/nativ/Mac/arm64/libjlinenative.jnilib b/native/src/main/resources/org/jline/nativ/Mac/arm64/libjlinenative.jnilib index b968d5e5a8f516cae335581721597a28e52c82dc..d30f8cbb1c1cd1624bffaf03a0cee0e7fb112ed0 100755 GIT binary patch literal 51666 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 P2bvw5{j$TAy)pF<1;w!d diff --git a/native/src/main/resources/org/jline/nativ/Mac/x86/libjlinenative.jnilib b/native/src/main/resources/org/jline/nativ/Mac/x86/libjlinenative.jnilib index e1c953ffa016327d624bf9c49dc69f4943038ff6..3418272cd6d7c451f1d0b30032a2f7c9e7d0fec3 100755 GIT binary patch literal 13720 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 diff --git a/native/src/main/resources/org/jline/nativ/Mac/x86_64/libjlinenative.jnilib b/native/src/main/resources/org/jline/nativ/Mac/x86_64/libjlinenative.jnilib index d7f243142209bb2d3cb893ebe2c95797444365c0..e82521301b6af5dca8f22325ab092dfae5555672 100755 GIT binary patch literal 14228 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 delta 741 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 literal 0 HcmV?d00001 diff --git a/native/src/main/resources/org/jline/nativ/Windows/x86/jlinenative.dll b/native/src/main/resources/org/jline/nativ/Windows/x86/jlinenative.dll index 10ddc9c4855b721b0384f26ae5b255f18f2161fc..f6bfa9ee6160419934091c9dc28e085ccb686b6f 100755 GIT binary patch delta 37252 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 Z^WEIx>PEFvT>V+aOQ~AtcT3nk{}0sL{A&OJ delta 11642 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 MejJTQ9i_Ja1q|c)z5oCK diff --git a/native/src/main/resources/org/jline/nativ/Windows/x86_64/jlinenative.dll b/native/src/main/resources/org/jline/nativ/Windows/x86_64/jlinenative.dll index 28e6948119b7790639cef8df241410e00c72a737..6b252cf1e02aa0b148742942a1197ef32e7e8f82 100755 GIT binary patch delta 38154 zcmeIb33wD$+Am&J=?+;437A0GLIVM#hLA8}k+nn8Nr!Y6ldyc$^E@mr>eTTy7l|t|9!sa zKF|Hy=kT8Top(9sJ?~lSRHeMHGyIXS2XwR#Z{@imR*pNzO|(S|LNaIPIIa=NviHDM zynXMR(^ES+?$$^khdA!B0ify+Toy=bzg~{3+&gxpwX&AuQudC$%=-3|9Cw#Ab`?Kt zZ@NYLco`oNwQ(-kEMGzuz_1|m7dzw;xe z$yQ;V3r8wP^84AjbbH!HMf5@#3R;mYNK3`J!bmG29ec+P9ns2FcBi=&KDl+BD2YN^ zA?^`I43Zmq2$vB^tHmS2n8WOBW@2v;1> zal3G}S-d4|OjHN15{a7^9}Y{3I)uw)T#n$y*Kyg4OKRs_Ui^1hQsg;YlF0>Pk_C#8 zO~aK-%*9nYuBiQ+yXq}>^5I^NJ6$tNj0zt!5!sCH9dF*UV%wLzvu*Tei#g7b@!7M` z#rYEch*D?Uq_PLa;_&gqpFvsMfNd9q*zNy7@v$-Zr|(ZQIZn(P5HH>zJ~Va}IGk;b z5gGlE`uG9yM0lDobFuh!_@vRVE}|mNxue??Q|Rk^hHC2ao$Bw|W_|Y-aqfU=;kQ7W zWtO;kz}0ETWagL$K~9EKRreL{ApCMWi?~P?qI;5khOTwq4{~8vFXMlDVIu3K9Ppm7`_1rZHO4sHp$@bn#ro zaN*PGVszxB(TAtY3Qyap6}4%xW41#N0?gTFy<(xbFmhb@O=!Z{8RE^6GkBMHBy#*9 z7a95zZgRE9q`AZ|B9jv|DBt&Dew!s3CFo;YR8~|0IhfD)z2*|1jT{~;;#w2lS^(kk zL)U7UF1@V)((z(%l+Bw}PCnZ<=U=D@ob+1D^-$Q~aRFB_Q$)h;)_hsVDW~swr_cH( zIH?x>9p})Y=$YpLfOoRWWPO@(Kynm7#^|#i1RndVb0@9akRgvcw|P(4vX;G|be~d@ z>rqA($@jfe==*((weLFkPHwgDEAmR4btyRdI}$Ncaj_5=F1e&O%jXc3ip8OfE>Y6w z+(ss{mS?Safnr1sk!^FV%!)VP_a~R{1(^Bfl42$&_Sph~IkC<9j~mHWCG;s(ppMCj zJsJ(mAEC(E*17~`WaBzA;_UBL9a@88YDesj $;P93^Hc4|5iua9|k9@q_DO#=Y0 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

Y>jl}S3p)6kP|>!hx+q; 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 delta 13274 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 terminal-jna terminal-jansi + terminal-jni reader builtins console @@ -144,6 +145,12 @@ ${project.version} + + org.jline + jline-terminal-jni + ${project.version} + + org.jline jline-terminal-jna diff --git a/reader/src/test/java/org/jline/terminal/impl/ExternalTerminalTest.java b/reader/src/test/java/org/jline/terminal/impl/ExternalTerminalTest.java index 7d2e28557..76a069a24 100644 --- a/reader/src/test/java/org/jline/terminal/impl/ExternalTerminalTest.java +++ b/reader/src/test/java/org/jline/terminal/impl/ExternalTerminalTest.java @@ -61,19 +61,6 @@ public void testInput() throws IOException, InterruptedException { testConsole(outIn, out, console); } - /* SANDBOX JANSI - @Test - public void testPosix() throws IOException, InterruptedException { - PipedInputStream in = new PipedInputStream(); - PipedOutputStream outIn = new PipedOutputStream(in); - ByteArrayOutputStream out = new ByteArrayOutputStream(); - - Console terminal = new PosixPtyConsole("ansi", new ConsoleReaderBuilder(), NativePty.open(null, null), in, out, "UTF-8"); - - testConsole(outIn, out, terminal); - } - */ - private void testConsole(PipedOutputStream outIn, ByteArrayOutputStream out, Terminal terminal) throws IOException, InterruptedException { Attributes attributes = terminal.getAttributes(); diff --git a/terminal-jni/pom.xml b/terminal-jni/pom.xml new file mode 100644 index 000000000..94183a86e --- /dev/null +++ b/terminal-jni/pom.xml @@ -0,0 +1,62 @@ + + + + + 4.0.0 + + + org.jline + jline-parent + 3.23.1-SNAPSHOT + + + jline-terminal-jni + JLine JNI Terminal + + + org.jline.terminal.jni + + + + + org.jline + jline-native + + + + org.jline + jline-terminal + + + + org.junit.jupiter + junit-jupiter-api + test + + + + + + + org.apache.felix + maven-bundle-plugin + + + *;-noimport:=true + org.jline.terminal + + + + + + + diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniNativePty.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniNativePty.java new file mode 100644 index 000000000..a6faaa89e --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniNativePty.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import org.jline.nativ.CLibrary; +import org.jline.nativ.Kernel32; +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.impl.AbstractPty; +import org.jline.terminal.impl.jni.win.NativeWinSysTerminal; +import org.jline.terminal.spi.Pty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; +import org.jline.utils.OSUtils; + +import static org.jline.nativ.CLibrary.TCSANOW; + +public abstract class JniNativePty extends AbstractPty implements Pty { + + private final int master; + private final int slave; + private final int slaveOut; + private final String name; + private final FileDescriptor masterFD; + private final FileDescriptor slaveFD; + private final FileDescriptor slaveOutFD; + + public JniNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + String name) { + this(provider, systemStream, master, masterFD, slave, slaveFD, slave, slaveFD, name); + } + + public JniNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream); + this.master = master; + this.slave = slave; + this.slaveOut = slaveOut; + this.name = name; + this.masterFD = masterFD; + this.slaveFD = slaveFD; + this.slaveOutFD = slaveOutFD; + } + + protected static String ttyname(int fd) throws IOException { + String name = CLibrary.ttyname(fd); + if (name != null) { + name = name.trim(); + } + if (name == null || name.isEmpty()) { + throw new IOException("Not a tty"); + } + return name; + } + + @Override + public void close() throws IOException { + if (master > 0) { + getMasterInput().close(); + } + if (slave > 0) { + getSlaveInput().close(); + } + } + + public int getMaster() { + return master; + } + + public int getSlave() { + return slave; + } + + public int getSlaveOut() { + return slaveOut; + } + + public String getName() { + return name; + } + + public FileDescriptor getMasterFD() { + return masterFD; + } + + public FileDescriptor getSlaveFD() { + return slaveFD; + } + + public FileDescriptor getSlaveOutFD() { + return slaveOutFD; + } + + public InputStream getMasterInput() { + return new FileInputStream(getMasterFD()); + } + + public OutputStream getMasterOutput() { + return new FileOutputStream(getMasterFD()); + } + + protected InputStream doGetSlaveInput() { + return new FileInputStream(getSlaveFD()); + } + + public OutputStream getSlaveOutput() { + return new FileOutputStream(getSlaveOutFD()); + } + + @Override + public Attributes getAttr() throws IOException { + CLibrary.Termios tios = new CLibrary.Termios(); + CLibrary.tcgetattr(slave, tios); + return toAttributes(tios); + } + + @Override + protected void doSetAttr(Attributes attr) throws IOException { + CLibrary.Termios tios = toTermios(attr); + CLibrary.tcsetattr(slave, TCSANOW, tios); + } + + @Override + public Size getSize() throws IOException { + CLibrary.WinSize sz = new CLibrary.WinSize(); + int res = CLibrary.ioctl(slave, CLibrary.TIOCGWINSZ, sz); + if (res != 0) { + throw new IOException("Error calling ioctl(TIOCGWINSZ): return code is " + res); + } + return new Size(sz.ws_col, sz.ws_row); + } + + @Override + public void setSize(Size size) throws IOException { + CLibrary.WinSize sz = new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()); + int res = CLibrary.ioctl(slave, CLibrary.TIOCSWINSZ, sz); + if (res != 0) { + throw new IOException("Error calling ioctl(TIOCSWINSZ): return code is " + res); + } + } + + protected abstract CLibrary.Termios toTermios(Attributes t); + + protected abstract Attributes toAttributes(CLibrary.Termios tios); + + @Override + public String toString() { + return "NativePty[" + getName() + "]"; + } + + public static boolean isPosixSystemStream(SystemStream stream) { + return CLibrary.isatty(fd(stream)) == 1; + } + + public static String posixSystemStreamName(SystemStream systemStream) { + return CLibrary.ttyname(fd(systemStream)); + } + + public static int systemStreamWidth(SystemStream systemStream) { + try { + if (OSUtils.IS_WINDOWS) { + Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO(); + long outConsole = NativeWinSysTerminal.getConsole(systemStream); + Kernel32.GetConsoleScreenBufferInfo(outConsole, info); + return info.windowWidth(); + } else { + CLibrary.WinSize sz = new CLibrary.WinSize(); + int res = CLibrary.ioctl(fd(systemStream), CLibrary.TIOCGWINSZ, sz); + if (res != 0) { + throw new IOException("Error calling ioctl(TIOCGWINSZ): return code is " + res); + } + return sz.ws_col; + } + } catch (Throwable t) { + return -1; + } + } + + private static int fd(SystemStream systemStream) { + switch (systemStream) { + case Input: + return 0; + case Output: + return 1; + case Error: + return 2; + default: + return -1; + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniTerminalProvider.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniTerminalProvider.java new file mode 100644 index 000000000..a1581ad20 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/JniTerminalProvider.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.charset.Charset; + +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.Terminal; +import org.jline.terminal.TerminalBuilder; +import org.jline.terminal.impl.PosixPtyTerminal; +import org.jline.terminal.impl.PosixSysTerminal; +import org.jline.terminal.impl.jni.freebsd.FreeBsdNativePty; +import org.jline.terminal.impl.jni.linux.LinuxNativePty; +import org.jline.terminal.impl.jni.osx.OsXNativePty; +import org.jline.terminal.impl.jni.solaris.SolarisNativePty; +import org.jline.terminal.impl.jni.win.NativeWinSysTerminal; +import org.jline.terminal.spi.Pty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; +import org.jline.utils.OSUtils; + +public class JniTerminalProvider implements TerminalProvider { + + @Override + public String name() { + return TerminalBuilder.PROP_PROVIDER_JNI; + } + + public Pty current(SystemStream systemStream) throws IOException { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + return LinuxNativePty.current(this, systemStream); + } else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) { + return OsXNativePty.current(this, systemStream); + } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) { + return SolarisNativePty.current(this, systemStream); + } else if (osName.startsWith("FreeBSD")) { + return FreeBsdNativePty.current(this, systemStream); + } + throw new UnsupportedOperationException(); + } + + public Pty open(Attributes attributes, Size size) throws IOException { + String osName = System.getProperty("os.name"); + if (osName.startsWith("Linux")) { + return LinuxNativePty.open(this, attributes, size); + } else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) { + return OsXNativePty.open(this, attributes, size); + } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) { + return SolarisNativePty.open(this, attributes, size); + } else if (osName.startsWith("FreeBSD")) { + return FreeBsdNativePty.open(this, attributes, size); + } + throw new UnsupportedOperationException(); + } + + @Override + public Terminal sysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream) + throws IOException { + if (OSUtils.IS_WINDOWS) { + return winSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream); + } else { + return posixSysTerminal( + name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused, systemStream); + } + } + + public Terminal winSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream) + throws IOException { + return NativeWinSysTerminal.createTerminal( + this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused); + } + + public Terminal posixSysTerminal( + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + Terminal.SignalHandler signalHandler, + boolean paused, + SystemStream systemStream) + throws IOException { + Pty pty = current(systemStream); + return new PosixSysTerminal(name, type, pty, encoding, nativeSignals, signalHandler); + } + + @Override + public Terminal newTerminal( + String name, + String type, + InputStream in, + OutputStream out, + Charset encoding, + Terminal.SignalHandler signalHandler, + boolean paused, + Attributes attributes, + Size size) + throws IOException { + Pty pty = open(attributes, size); + return new PosixPtyTerminal(name, type, pty, in, out, encoding, signalHandler, paused); + } + + @Override + public boolean isSystemStream(SystemStream stream) { + try { + if (OSUtils.IS_WINDOWS) { + return isWindowsSystemStream(stream); + } else { + return isPosixSystemStream(stream); + } + } catch (Throwable t) { + return false; + } + } + + public boolean isWindowsSystemStream(SystemStream stream) { + return NativeWinSysTerminal.isWindowsSystemStream(stream); + } + + public boolean isPosixSystemStream(SystemStream stream) { + return JniNativePty.isPosixSystemStream(stream); + } + + @Override + public String systemStreamName(SystemStream stream) { + return JniNativePty.posixSystemStreamName(stream); + } + + @Override + public int systemStreamWidth(SystemStream stream) { + return JniNativePty.systemStreamWidth(stream); + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/freebsd/FreeBsdNativePty.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/freebsd/FreeBsdNativePty.java new file mode 100644 index 000000000..8708599b1 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/freebsd/FreeBsdNativePty.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.freebsd; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.EnumMap; +import java.util.EnumSet; + +import org.jline.nativ.CLibrary; +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.impl.jni.JniNativePty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; + +public class FreeBsdNativePty extends JniNativePty { + + public static FreeBsdNativePty current(TerminalProvider provider, SystemStream systemStream) throws IOException { + try { + switch (systemStream) { + case Output: + return new FreeBsdNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(1)); + case Error: + return new FreeBsdNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(2)); + default: + throw new IllegalArgumentException("Unsupport stream for console: " + systemStream); + } + } catch (IOException e) { + throw new IOException("Not a tty", e); + } + } + + public static FreeBsdNativePty open(TerminalProvider provider, Attributes attr, Size size) throws IOException { + int[] master = new int[1]; + int[] slave = new int[1]; + byte[] buf = new byte[64]; + CLibrary.openpty( + master, + slave, + buf, + attr != null ? termios(attr) : null, + size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null); + int len = 0; + while (buf[len] != 0) { + len++; + } + String name = new String(buf, 0, len); + return new FreeBsdNativePty( + provider, null, master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name); + } + + public FreeBsdNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, name); + } + + public FreeBsdNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); + } + // CONSTANTS + + private static final int VEOF = 0; + private static final int VEOL = 1; + private static final int VEOL2 = 2; + private static final int VERASE = 3; + private static final int VWERASE = 4; + private static final int VKILL = 5; + private static final int VREPRINT = 6; + private static final int VERASE2 = 7; + private static final int VINTR = 8; + private static final int VQUIT = 9; + private static final int VSUSP = 10; + private static final int VDSUSP = 11; + private static final int VSTART = 12; + private static final int VSTOP = 13; + private static final int VLNEXT = 14; + private static final int VDISCARD = 15; + private static final int VMIN = 16; + private static final int VTIME = 17; + private static final int VSTATUS = 18; + + private static final int IGNBRK = 0x0000001; + private static final int BRKINT = 0x0000002; + private static final int IGNPAR = 0x0000004; + private static final int PARMRK = 0x0000008; + private static final int INPCK = 0x0000010; + private static final int ISTRIP = 0x0000020; + private static final int INLCR = 0x0000040; + private static final int IGNCR = 0x0000080; + private static final int ICRNL = 0x0000100; + private static final int IXON = 0x0000200; + private static final int IXOFF = 0x0000400; + private static final int IXANY = 0x0000800; + private static final int IMAXBEL = 0x0002000; + + private static final int OPOST = 0x0000001; + private static final int ONLCR = 0x0000002; + private static final int TABDLY = 0x0000004; + private static final int TAB0 = 0x0000000; + private static final int TAB3 = 0x0000004; + private static final int ONOEOT = 0x0000008; + private static final int OCRNL = 0x0000010; + private static final int ONLRET = 0x0000040; + + private static final int CIGNORE = 0x0000001; + private static final int CSIZE = 0x0000300; + private static final int CS5 = 0x0000000; + private static final int CS6 = 0x0000100; + private static final int CS7 = 0x0000200; + private static final int CS8 = 0x0000300; + private static final int CSTOPB = 0x0000400; + private static final int CREAD = 0x0000800; + private static final int PARENB = 0x0001000; + private static final int PARODD = 0x0002000; + private static final int HUPCL = 0x0004000; + private static final int CLOCAL = 0x0008000; + + private static final int ECHOKE = 0x0000001; + private static final int ECHOE = 0x0000002; + private static final int ECHOK = 0x0000004; + private static final int ECHO = 0x0000008; + private static final int ECHONL = 0x0000010; + private static final int ECHOPRT = 0x0000020; + private static final int ECHOCTL = 0x0000040; + private static final int ISIG = 0x0000080; + private static final int ICANON = 0x0000100; + private static final int ALTWERASE = 0x000200; + private static final int IEXTEN = 0x0000400; + private static final int EXTPROC = 0x0000800; + private static final int TOSTOP = 0x0400000; + private static final int FLUSHO = 0x0800000; + private static final int PENDIN = 0x2000000; + private static final int NOFLSH = 0x8000000; + + protected CLibrary.Termios toTermios(Attributes t) { + return termios(t); + } + + static CLibrary.Termios termios(Attributes t) { + CLibrary.Termios tio = new CLibrary.Termios(); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNPAR), IGNPAR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.PARMRK), PARMRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INPCK), INPCK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ISTRIP), ISTRIP, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INLCR), INLCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNCR), IGNCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ICRNL), ICRNL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXON), IXON, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXOFF), IXOFF, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXANY), IXANY, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IMAXBEL), IMAXBEL, tio.c_iflag); + // tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IUTF8), IUTF8, tio.c_iflag); + // Output flags + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OPOST), OPOST, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLCR), ONLCR, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OXTABS), OXTABS, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOEOT), ONOEOT, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OCRNL), OCRNL, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOCR), ONOCR, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLRET), ONLRET, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFILL), OFILL, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.NLDLY), NLDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.TABDLY), TABDLY, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.CRDLY), CRDLY, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.FFDLY), FFDLY, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.BSDLY), BSDLY, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.VTDLY), VTDLY, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFDEL), OFDEL, tio.c_oflag); + // Control flags + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CIGNORE), CIGNORE, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS5), CS5, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS6), CS6, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS7), CS7, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS8), CS8, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CSTOPB), CSTOPB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CREAD), CREAD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARENB), PARENB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARODD), PARODD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.HUPCL), HUPCL, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CLOCAL), CLOCAL, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCTS_OFLOW), CCTS_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CRTS_IFLOW), CRTS_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDTR_IFLOW), CDTR_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDSR_OFLOW), CDSR_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCAR_OFLOW), CCAR_OFLOW, tio.c_cflag); + // Local flags + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOKE), ECHOKE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOE), ECHOE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOK), ECHOK, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHO), ECHO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHONL), ECHONL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOPRT), ECHOPRT, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOCTL), ECHOCTL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ISIG), ISIG, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ICANON), ICANON, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ALTWERASE), ALTWERASE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.IEXTEN), IEXTEN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.EXTPROC), EXTPROC, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.TOSTOP), TOSTOP, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.FLUSHO), FLUSHO, tio.c_lflag); + // tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOKERNINFO), NOKERNINFO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.PENDIN), PENDIN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOFLSH), NOFLSH, tio.c_lflag); + // Control chars + tio.c_cc[VEOF] = (byte) t.getControlChar(Attributes.ControlChar.VEOF); + tio.c_cc[VEOL] = (byte) t.getControlChar(Attributes.ControlChar.VEOL); + tio.c_cc[VEOL2] = (byte) t.getControlChar(Attributes.ControlChar.VEOL2); + tio.c_cc[VERASE] = (byte) t.getControlChar(Attributes.ControlChar.VERASE); + tio.c_cc[VWERASE] = (byte) t.getControlChar(Attributes.ControlChar.VWERASE); + tio.c_cc[VKILL] = (byte) t.getControlChar(Attributes.ControlChar.VKILL); + tio.c_cc[VREPRINT] = (byte) t.getControlChar(Attributes.ControlChar.VREPRINT); + tio.c_cc[VINTR] = (byte) t.getControlChar(Attributes.ControlChar.VINTR); + tio.c_cc[VQUIT] = (byte) t.getControlChar(Attributes.ControlChar.VQUIT); + tio.c_cc[VSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VSUSP); + // tio.c_cc[VDSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VDSUSP); + tio.c_cc[VSTART] = (byte) t.getControlChar(Attributes.ControlChar.VSTART); + tio.c_cc[VSTOP] = (byte) t.getControlChar(Attributes.ControlChar.VSTOP); + tio.c_cc[VLNEXT] = (byte) t.getControlChar(Attributes.ControlChar.VLNEXT); + tio.c_cc[VDISCARD] = (byte) t.getControlChar(Attributes.ControlChar.VDISCARD); + tio.c_cc[VMIN] = (byte) t.getControlChar(Attributes.ControlChar.VMIN); + tio.c_cc[VTIME] = (byte) t.getControlChar(Attributes.ControlChar.VTIME); + // tio.c_cc[VSTATUS] = (byte) t.getControlChar(Attributes.ControlChar.VSTATUS); + return tio; + } + + protected Attributes toAttributes(CLibrary.Termios tio) { + Attributes attr = new Attributes(); + // Input flags + EnumSet iflag = attr.getInputFlags(); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.BRKINT, BRKINT); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNPAR, IGNPAR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.PARMRK, PARMRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INPCK, INPCK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ISTRIP, ISTRIP); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INLCR, INLCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNCR, IGNCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ICRNL, ICRNL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXON, IXON); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXOFF, IXOFF); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXANY, IXANY); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IMAXBEL, IMAXBEL); + // addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IUTF8, IUTF8); + // Output flags + EnumSet oflag = attr.getOutputFlags(); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OPOST, OPOST); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLCR, ONLCR); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OXTABS, OXTABS); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOEOT, ONOEOT); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OCRNL, OCRNL); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOCR, ONOCR); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLRET, ONLRET); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFILL, OFILL); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.NLDLY, NLDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.TABDLY, TABDLY); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.CRDLY, CRDLY); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.FFDLY, FFDLY); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.BSDLY, BSDLY); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.VTDLY, VTDLY); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFDEL, OFDEL); + // Control flags + EnumSet cflag = attr.getControlFlags(); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CIGNORE, CIGNORE); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS5, CS5); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS6, CS6); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS7, CS7); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS8, CS8); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CSTOPB, CSTOPB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CREAD, CREAD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARENB, PARENB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARODD, PARODD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.HUPCL, HUPCL); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CLOCAL, CLOCAL); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCTS_OFLOW, CCTS_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CRTS_IFLOW, CRTS_IFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CDSR_OFLOW, CDSR_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCAR_OFLOW, CCAR_OFLOW); + // Local flags + EnumSet lflag = attr.getLocalFlags(); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOKE, ECHOKE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOE, ECHOE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOK, ECHOK); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHO, ECHO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHONL, ECHONL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOPRT, ECHOPRT); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOCTL, ECHOCTL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ISIG, ISIG); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ICANON, ICANON); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ALTWERASE, ALTWERASE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.IEXTEN, IEXTEN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.EXTPROC, EXTPROC); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.TOSTOP, TOSTOP); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.FLUSHO, FLUSHO); + // addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOKERNINFO, NOKERNINFO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.PENDIN, PENDIN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOFLSH, NOFLSH); + // Control chars + EnumMap cc = attr.getControlChars(); + cc.put(Attributes.ControlChar.VEOF, (int) tio.c_cc[VEOF]); + cc.put(Attributes.ControlChar.VEOL, (int) tio.c_cc[VEOL]); + cc.put(Attributes.ControlChar.VEOL2, (int) tio.c_cc[VEOL2]); + cc.put(Attributes.ControlChar.VERASE, (int) tio.c_cc[VERASE]); + cc.put(Attributes.ControlChar.VWERASE, (int) tio.c_cc[VWERASE]); + cc.put(Attributes.ControlChar.VKILL, (int) tio.c_cc[VKILL]); + cc.put(Attributes.ControlChar.VREPRINT, (int) tio.c_cc[VREPRINT]); + cc.put(Attributes.ControlChar.VINTR, (int) tio.c_cc[VINTR]); + cc.put(Attributes.ControlChar.VQUIT, (int) tio.c_cc[VQUIT]); + cc.put(Attributes.ControlChar.VSUSP, (int) tio.c_cc[VSUSP]); + // cc.put(Attributes.ControlChar.VDSUSP, (int) tio.c_cc[VDSUSP]); + cc.put(Attributes.ControlChar.VSTART, (int) tio.c_cc[VSTART]); + cc.put(Attributes.ControlChar.VSTOP, (int) tio.c_cc[VSTOP]); + cc.put(Attributes.ControlChar.VLNEXT, (int) tio.c_cc[VLNEXT]); + cc.put(Attributes.ControlChar.VDISCARD, (int) tio.c_cc[VDISCARD]); + cc.put(Attributes.ControlChar.VMIN, (int) tio.c_cc[VMIN]); + cc.put(Attributes.ControlChar.VTIME, (int) tio.c_cc[VTIME]); + // cc.put(Attributes.ControlChar.VSTATUS, (int) tio.c_cc[VSTATUS]); + // Return + return attr; + } + + private static long setFlag(boolean flag, long value, long org) { + return flag ? org | value : org; + } + + private static > void addFlag(long value, EnumSet flags, T flag, int v) { + if ((value & v) != 0) { + flags.add(flag); + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/linux/LinuxNativePty.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/linux/LinuxNativePty.java new file mode 100644 index 000000000..537fca079 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/linux/LinuxNativePty.java @@ -0,0 +1,393 @@ +/* + * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.linux; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.EnumMap; +import java.util.EnumSet; + +import org.jline.nativ.CLibrary; +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.impl.jni.JniNativePty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; + +public class LinuxNativePty extends JniNativePty { + + public static LinuxNativePty current(TerminalProvider provider, SystemStream systemStream) throws IOException { + try { + switch (systemStream) { + case Output: + return new LinuxNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(1)); + case Error: + return new LinuxNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(2)); + default: + throw new IllegalArgumentException("Unsupport stream for console: " + systemStream); + } + } catch (IOException e) { + throw new IOException("Not a tty", e); + } + } + + public static LinuxNativePty open(TerminalProvider provider, Attributes attr, Size size) throws IOException { + int[] master = new int[1]; + int[] slave = new int[1]; + byte[] buf = new byte[64]; + CLibrary.openpty( + master, + slave, + buf, + attr != null ? termios(attr) : null, + size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null); + int len = 0; + while (buf[len] != 0) { + len++; + } + String name = new String(buf, 0, len); + return new LinuxNativePty( + provider, + null, + master[0], + newDescriptor(master[0]), + slave[0], + newDescriptor(slave[0]), + 2, + FileDescriptor.err, + name); + } + + public LinuxNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); + } + // CONSTANTS + + private static final int VINTR = 0; + private static final int VQUIT = 1; + private static final int VERASE = 2; + private static final int VKILL = 3; + private static final int VEOF = 4; + private static final int VTIME = 5; + private static final int VMIN = 6; + private static final int VSWTC = 7; + private static final int VSTART = 8; + private static final int VSTOP = 9; + private static final int VSUSP = 10; + private static final int VEOL = 11; + private static final int VREPRINT = 12; + private static final int VDISCARD = 13; + private static final int VWERASE = 14; + private static final int VLNEXT = 15; + private static final int VEOL2 = 16; + + private static final int IGNBRK = 0x0000001; + private static final int BRKINT = 0x0000002; + private static final int IGNPAR = 0x0000004; + private static final int PARMRK = 0x0000008; + private static final int INPCK = 0x0000010; + private static final int ISTRIP = 0x0000020; + private static final int INLCR = 0x0000040; + private static final int IGNCR = 0x0000080; + private static final int ICRNL = 0x0000100; + private static final int IUCLC = 0x0000200; + private static final int IXON = 0x0000400; + private static final int IXANY = 0x0000800; + private static final int IXOFF = 0x0001000; + private static final int IMAXBEL = 0x0002000; + private static final int IUTF8 = 0x0004000; + + private static final int OPOST = 0x0000001; + private static final int OLCUC = 0x0000002; + private static final int ONLCR = 0x0000004; + private static final int OCRNL = 0x0000008; + private static final int ONOCR = 0x0000010; + private static final int ONLRET = 0x0000020; + private static final int OFILL = 0x0000040; + private static final int OFDEL = 0x0000080; + private static final int NLDLY = 0x0000100; + private static final int NL0 = 0x0000000; + private static final int NL1 = 0x0000100; + private static final int CRDLY = 0x0000600; + private static final int CR0 = 0x0000000; + private static final int CR1 = 0x0000200; + private static final int CR2 = 0x0000400; + private static final int CR3 = 0x0000600; + private static final int TABDLY = 0x0001800; + private static final int TAB0 = 0x0000000; + private static final int TAB1 = 0x0000800; + private static final int TAB2 = 0x0001000; + private static final int TAB3 = 0x0001800; + private static final int XTABS = 0x0001800; + private static final int BSDLY = 0x0002000; + private static final int BS0 = 0x0000000; + private static final int BS1 = 0x0002000; + private static final int VTDLY = 0x0004000; + private static final int VT0 = 0x0000000; + private static final int VT1 = 0x0004000; + private static final int FFDLY = 0x0008000; + private static final int FF0 = 0x0000000; + private static final int FF1 = 0x0008000; + + private static final int CBAUD = 0x000100f; + private static final int B0 = 0x0000000; + private static final int B50 = 0x0000001; + private static final int B75 = 0x0000002; + private static final int B110 = 0x0000003; + private static final int B134 = 0x0000004; + private static final int B150 = 0x0000005; + private static final int B200 = 0x0000006; + private static final int B300 = 0x0000007; + private static final int B600 = 0x0000008; + private static final int B1200 = 0x0000009; + private static final int B1800 = 0x000000a; + private static final int B2400 = 0x000000b; + private static final int B4800 = 0x000000c; + private static final int B9600 = 0x000000d; + private static final int B19200 = 0x000000e; + private static final int B38400 = 0x000000f; + private static final int EXTA = B19200; + private static final int EXTB = B38400; + private static final int CSIZE = 0x0000030; + private static final int CS5 = 0x0000000; + private static final int CS6 = 0x0000010; + private static final int CS7 = 0x0000020; + private static final int CS8 = 0x0000030; + private static final int CSTOPB = 0x0000040; + private static final int CREAD = 0x0000080; + private static final int PARENB = 0x0000100; + private static final int PARODD = 0x0000200; + private static final int HUPCL = 0x0000400; + private static final int CLOCAL = 0x0000800; + + private static final int ISIG = 0x0000001; + private static final int ICANON = 0x0000002; + private static final int XCASE = 0x0000004; + private static final int ECHO = 0x0000008; + private static final int ECHOE = 0x0000010; + private static final int ECHOK = 0x0000020; + private static final int ECHONL = 0x0000040; + private static final int NOFLSH = 0x0000080; + private static final int TOSTOP = 0x0000100; + private static final int ECHOCTL = 0x0000200; + private static final int ECHOPRT = 0x0000400; + private static final int ECHOKE = 0x0000800; + private static final int FLUSHO = 0x0001000; + private static final int PENDIN = 0x0002000; + private static final int IEXTEN = 0x0008000; + private static final int EXTPROC = 0x0010000; + + protected CLibrary.Termios toTermios(Attributes t) { + return termios(t); + } + + static CLibrary.Termios termios(Attributes t) { + CLibrary.Termios tio = new CLibrary.Termios(); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNPAR), IGNPAR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.PARMRK), PARMRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INPCK), INPCK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ISTRIP), ISTRIP, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INLCR), INLCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNCR), IGNCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ICRNL), ICRNL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXON), IXON, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXOFF), IXOFF, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXANY), IXANY, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IMAXBEL), IMAXBEL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IUTF8), IUTF8, tio.c_iflag); + // Output flags + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OPOST), OPOST, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLCR), ONLCR, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OXTABS), OXTABS, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOEOT), ONOEOT, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OCRNL), OCRNL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOCR), ONOCR, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLRET), ONLRET, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFILL), OFILL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.NLDLY), NLDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.TABDLY), TABDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.CRDLY), CRDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.FFDLY), FFDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.BSDLY), BSDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.VTDLY), VTDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFDEL), OFDEL, tio.c_oflag); + // Control flags + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CIGNORE), CIGNORE, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS5), CS5, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS6), CS6, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS7), CS7, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS8), CS8, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CSTOPB), CSTOPB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CREAD), CREAD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARENB), PARENB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARODD), PARODD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.HUPCL), HUPCL, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CLOCAL), CLOCAL, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCTS_OFLOW), CCTS_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CRTS_IFLOW), CRTS_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDTR_IFLOW), CDTR_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDSR_OFLOW), CDSR_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCAR_OFLOW), CCAR_OFLOW, tio.c_cflag); + // Local flags + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOKE), ECHOKE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOE), ECHOE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOK), ECHOK, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHO), ECHO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHONL), ECHONL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOPRT), ECHOPRT, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOCTL), ECHOCTL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ISIG), ISIG, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ICANON), ICANON, tio.c_lflag); + // tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ALTWERASE), ALTWERASE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.IEXTEN), IEXTEN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.EXTPROC), EXTPROC, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.TOSTOP), TOSTOP, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.FLUSHO), FLUSHO, tio.c_lflag); + // tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOKERNINFO), NOKERNINFO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.PENDIN), PENDIN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOFLSH), NOFLSH, tio.c_lflag); + // Control chars + tio.c_cc[VEOF] = (byte) t.getControlChar(Attributes.ControlChar.VEOF); + tio.c_cc[VEOL] = (byte) t.getControlChar(Attributes.ControlChar.VEOL); + tio.c_cc[VEOL2] = (byte) t.getControlChar(Attributes.ControlChar.VEOL2); + tio.c_cc[VERASE] = (byte) t.getControlChar(Attributes.ControlChar.VERASE); + tio.c_cc[VWERASE] = (byte) t.getControlChar(Attributes.ControlChar.VWERASE); + tio.c_cc[VKILL] = (byte) t.getControlChar(Attributes.ControlChar.VKILL); + tio.c_cc[VREPRINT] = (byte) t.getControlChar(Attributes.ControlChar.VREPRINT); + tio.c_cc[VINTR] = (byte) t.getControlChar(Attributes.ControlChar.VINTR); + tio.c_cc[VQUIT] = (byte) t.getControlChar(Attributes.ControlChar.VQUIT); + tio.c_cc[VSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VSUSP); + tio.c_cc[VSTART] = (byte) t.getControlChar(Attributes.ControlChar.VSTART); + tio.c_cc[VSTOP] = (byte) t.getControlChar(Attributes.ControlChar.VSTOP); + tio.c_cc[VLNEXT] = (byte) t.getControlChar(Attributes.ControlChar.VLNEXT); + tio.c_cc[VDISCARD] = (byte) t.getControlChar(Attributes.ControlChar.VDISCARD); + tio.c_cc[VMIN] = (byte) t.getControlChar(Attributes.ControlChar.VMIN); + tio.c_cc[VTIME] = (byte) t.getControlChar(Attributes.ControlChar.VTIME); + // tio.c_cc[VSTATUS] = (byte) t.getControlChar(Attributes.ControlChar.VSTATUS); + return tio; + } + + protected Attributes toAttributes(CLibrary.Termios tio) { + Attributes attr = new Attributes(); + // Input flags + EnumSet iflag = attr.getInputFlags(); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.BRKINT, BRKINT); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNPAR, IGNPAR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.PARMRK, PARMRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INPCK, INPCK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ISTRIP, ISTRIP); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INLCR, INLCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNCR, IGNCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ICRNL, ICRNL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXON, IXON); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXOFF, IXOFF); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXANY, IXANY); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IMAXBEL, IMAXBEL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IUTF8, IUTF8); + // Output flags + EnumSet oflag = attr.getOutputFlags(); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OPOST, OPOST); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLCR, ONLCR); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OXTABS, OXTABS); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOEOT, ONOEOT); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OCRNL, OCRNL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOCR, ONOCR); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLRET, ONLRET); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFILL, OFILL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.NLDLY, NLDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.TABDLY, TABDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.CRDLY, CRDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.FFDLY, FFDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.BSDLY, BSDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.VTDLY, VTDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFDEL, OFDEL); + // Control flags + EnumSet cflag = attr.getControlFlags(); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CIGNORE, CIGNORE); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS5, CS5); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS6, CS6); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS7, CS7); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS8, CS8); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CSTOPB, CSTOPB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CREAD, CREAD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARENB, PARENB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARODD, PARODD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.HUPCL, HUPCL); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CLOCAL, CLOCAL); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCTS_OFLOW, CCTS_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CRTS_IFLOW, CRTS_IFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CDSR_OFLOW, CDSR_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCAR_OFLOW, CCAR_OFLOW); + // Local flags + EnumSet lflag = attr.getLocalFlags(); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOKE, ECHOKE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOE, ECHOE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOK, ECHOK); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHO, ECHO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHONL, ECHONL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOPRT, ECHOPRT); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOCTL, ECHOCTL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ISIG, ISIG); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ICANON, ICANON); + // addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ALTWERASE, ALTWERASE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.IEXTEN, IEXTEN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.EXTPROC, EXTPROC); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.TOSTOP, TOSTOP); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.FLUSHO, FLUSHO); + // addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOKERNINFO, NOKERNINFO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.PENDIN, PENDIN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOFLSH, NOFLSH); + // Control chars + EnumMap cc = attr.getControlChars(); + cc.put(Attributes.ControlChar.VEOF, (int) tio.c_cc[VEOF]); + cc.put(Attributes.ControlChar.VEOL, (int) tio.c_cc[VEOL]); + cc.put(Attributes.ControlChar.VEOL2, (int) tio.c_cc[VEOL2]); + cc.put(Attributes.ControlChar.VERASE, (int) tio.c_cc[VERASE]); + cc.put(Attributes.ControlChar.VWERASE, (int) tio.c_cc[VWERASE]); + cc.put(Attributes.ControlChar.VKILL, (int) tio.c_cc[VKILL]); + cc.put(Attributes.ControlChar.VREPRINT, (int) tio.c_cc[VREPRINT]); + cc.put(Attributes.ControlChar.VINTR, (int) tio.c_cc[VINTR]); + cc.put(Attributes.ControlChar.VQUIT, (int) tio.c_cc[VQUIT]); + cc.put(Attributes.ControlChar.VSUSP, (int) tio.c_cc[VSUSP]); + cc.put(Attributes.ControlChar.VSTART, (int) tio.c_cc[VSTART]); + cc.put(Attributes.ControlChar.VSTOP, (int) tio.c_cc[VSTOP]); + cc.put(Attributes.ControlChar.VLNEXT, (int) tio.c_cc[VLNEXT]); + cc.put(Attributes.ControlChar.VDISCARD, (int) tio.c_cc[VDISCARD]); + cc.put(Attributes.ControlChar.VMIN, (int) tio.c_cc[VMIN]); + cc.put(Attributes.ControlChar.VTIME, (int) tio.c_cc[VTIME]); + // cc.put(Attributes.ControlChar.VSTATUS, (int) tio.c_cc[VSTATUS]); + // Return + return attr; + } + + private static long setFlag(boolean flag, long value, long org) { + return flag ? org | value : org; + } + + private static > void addFlag(long value, EnumSet flags, T flag, int v) { + if ((value & v) != 0) { + flags.add(flag); + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/osx/OsXNativePty.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/osx/OsXNativePty.java new file mode 100644 index 000000000..8cf4accf0 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/osx/OsXNativePty.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.osx; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.EnumMap; +import java.util.EnumSet; + +import org.jline.nativ.CLibrary; +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.impl.jni.JniNativePty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; + +public class OsXNativePty extends JniNativePty { + + public static OsXNativePty current(TerminalProvider provider, SystemStream systemStream) throws IOException { + try { + switch (systemStream) { + case Output: + return new OsXNativePty( + provider, + SystemStream.Output, + -1, + null, + 0, + FileDescriptor.in, + 1, + FileDescriptor.out, + ttyname(1)); + case Error: + return new OsXNativePty( + provider, + SystemStream.Error, + -1, + null, + 0, + FileDescriptor.in, + 2, + FileDescriptor.err, + ttyname(2)); + default: + throw new IllegalArgumentException("Unsupport stream for console: " + systemStream); + } + } catch (IOException e) { + throw new IOException("Not a tty", e); + } + } + + public static OsXNativePty open(TerminalProvider provider, Attributes attr, Size size) throws IOException { + int[] master = new int[1]; + int[] slave = new int[1]; + byte[] buf = new byte[64]; + CLibrary.openpty( + master, + slave, + buf, + attr != null ? termios(attr) : null, + size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null); + int len = 0; + while (buf[len] != 0) { + len++; + } + String name = new String(buf, 0, len); + return new OsXNativePty( + provider, null, master[0], newDescriptor(master[0]), slave[0], newDescriptor(slave[0]), name); + } + + public OsXNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, name); + } + + public OsXNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); + } + + // CONSTANTS + + private static final int VEOF = 0; + private static final int VEOL = 1; + private static final int VEOL2 = 2; + private static final int VERASE = 3; + private static final int VWERASE = 4; + private static final int VKILL = 5; + private static final int VREPRINT = 6; + private static final int VINTR = 8; + private static final int VQUIT = 9; + private static final int VSUSP = 10; + private static final int VDSUSP = 11; + private static final int VSTART = 12; + private static final int VSTOP = 13; + private static final int VLNEXT = 14; + private static final int VDISCARD = 15; + private static final int VMIN = 16; + private static final int VTIME = 17; + private static final int VSTATUS = 18; + + private static final int IGNBRK = 0x00000001; + private static final int BRKINT = 0x00000002; + private static final int IGNPAR = 0x00000004; + private static final int PARMRK = 0x00000008; + private static final int INPCK = 0x00000010; + private static final int ISTRIP = 0x00000020; + private static final int INLCR = 0x00000040; + private static final int IGNCR = 0x00000080; + private static final int ICRNL = 0x00000100; + private static final int IXON = 0x00000200; + private static final int IXOFF = 0x00000400; + private static final int IXANY = 0x00000800; + private static final int IMAXBEL = 0x00002000; + private static final int IUTF8 = 0x00004000; + + private static final int OPOST = 0x00000001; + private static final int ONLCR = 0x00000002; + private static final int OXTABS = 0x00000004; + private static final int ONOEOT = 0x00000008; + private static final int OCRNL = 0x00000010; + private static final int ONOCR = 0x00000020; + private static final int ONLRET = 0x00000040; + private static final int OFILL = 0x00000080; + private static final int NLDLY = 0x00000300; + private static final int TABDLY = 0x00000c04; + private static final int CRDLY = 0x00003000; + private static final int FFDLY = 0x00004000; + private static final int BSDLY = 0x00008000; + private static final int VTDLY = 0x00010000; + private static final int OFDEL = 0x00020000; + + private static final int CIGNORE = 0x00000001; + private static final int CS5 = 0x00000000; + private static final int CS6 = 0x00000100; + private static final int CS7 = 0x00000200; + private static final int CS8 = 0x00000300; + private static final int CSTOPB = 0x00000400; + private static final int CREAD = 0x00000800; + private static final int PARENB = 0x00001000; + private static final int PARODD = 0x00002000; + private static final int HUPCL = 0x00004000; + private static final int CLOCAL = 0x00008000; + private static final int CCTS_OFLOW = 0x00010000; + private static final int CRTS_IFLOW = 0x00020000; + private static final int CDTR_IFLOW = 0x00040000; + private static final int CDSR_OFLOW = 0x00080000; + private static final int CCAR_OFLOW = 0x00100000; + + private static final int ECHOKE = 0x00000001; + private static final int ECHOE = 0x00000002; + private static final int ECHOK = 0x00000004; + private static final int ECHO = 0x00000008; + private static final int ECHONL = 0x00000010; + private static final int ECHOPRT = 0x00000020; + private static final int ECHOCTL = 0x00000040; + private static final int ISIG = 0x00000080; + private static final int ICANON = 0x00000100; + private static final int ALTWERASE = 0x00000200; + private static final int IEXTEN = 0x00000400; + private static final int EXTPROC = 0x00000800; + private static final int TOSTOP = 0x00400000; + private static final int FLUSHO = 0x00800000; + private static final int NOKERNINFO = 0x02000000; + private static final int PENDIN = 0x20000000; + private static final int NOFLSH = 0x80000000; + + protected CLibrary.Termios toTermios(Attributes t) { + return termios(t); + } + + static CLibrary.Termios termios(Attributes t) { + CLibrary.Termios tio = new CLibrary.Termios(); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNPAR), IGNPAR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.PARMRK), PARMRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INPCK), INPCK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ISTRIP), ISTRIP, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INLCR), INLCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNCR), IGNCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ICRNL), ICRNL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXON), IXON, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXOFF), IXOFF, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXANY), IXANY, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IMAXBEL), IMAXBEL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IUTF8), IUTF8, tio.c_iflag); + // Output flags + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OPOST), OPOST, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLCR), ONLCR, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OXTABS), OXTABS, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOEOT), ONOEOT, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OCRNL), OCRNL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOCR), ONOCR, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLRET), ONLRET, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFILL), OFILL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.NLDLY), NLDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.TABDLY), TABDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.CRDLY), CRDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.FFDLY), FFDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.BSDLY), BSDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.VTDLY), VTDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFDEL), OFDEL, tio.c_oflag); + // Control flags + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CIGNORE), CIGNORE, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS5), CS5, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS6), CS6, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS7), CS7, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS8), CS8, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CSTOPB), CSTOPB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CREAD), CREAD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARENB), PARENB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARODD), PARODD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.HUPCL), HUPCL, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CLOCAL), CLOCAL, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCTS_OFLOW), CCTS_OFLOW, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CRTS_IFLOW), CRTS_IFLOW, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDTR_IFLOW), CDTR_IFLOW, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDSR_OFLOW), CDSR_OFLOW, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCAR_OFLOW), CCAR_OFLOW, tio.c_cflag); + // Local flags + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOKE), ECHOKE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOE), ECHOE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOK), ECHOK, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHO), ECHO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHONL), ECHONL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOPRT), ECHOPRT, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOCTL), ECHOCTL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ISIG), ISIG, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ICANON), ICANON, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ALTWERASE), ALTWERASE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.IEXTEN), IEXTEN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.EXTPROC), EXTPROC, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.TOSTOP), TOSTOP, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.FLUSHO), FLUSHO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOKERNINFO), NOKERNINFO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.PENDIN), PENDIN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOFLSH), NOFLSH, tio.c_lflag); + // Control chars + tio.c_cc[VEOF] = (byte) t.getControlChar(Attributes.ControlChar.VEOF); + tio.c_cc[VEOL] = (byte) t.getControlChar(Attributes.ControlChar.VEOL); + tio.c_cc[VEOL2] = (byte) t.getControlChar(Attributes.ControlChar.VEOL2); + tio.c_cc[VERASE] = (byte) t.getControlChar(Attributes.ControlChar.VERASE); + tio.c_cc[VWERASE] = (byte) t.getControlChar(Attributes.ControlChar.VWERASE); + tio.c_cc[VKILL] = (byte) t.getControlChar(Attributes.ControlChar.VKILL); + tio.c_cc[VREPRINT] = (byte) t.getControlChar(Attributes.ControlChar.VREPRINT); + tio.c_cc[VINTR] = (byte) t.getControlChar(Attributes.ControlChar.VINTR); + tio.c_cc[VQUIT] = (byte) t.getControlChar(Attributes.ControlChar.VQUIT); + tio.c_cc[VSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VSUSP); + tio.c_cc[VDSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VDSUSP); + tio.c_cc[VSTART] = (byte) t.getControlChar(Attributes.ControlChar.VSTART); + tio.c_cc[VSTOP] = (byte) t.getControlChar(Attributes.ControlChar.VSTOP); + tio.c_cc[VLNEXT] = (byte) t.getControlChar(Attributes.ControlChar.VLNEXT); + tio.c_cc[VDISCARD] = (byte) t.getControlChar(Attributes.ControlChar.VDISCARD); + tio.c_cc[VMIN] = (byte) t.getControlChar(Attributes.ControlChar.VMIN); + tio.c_cc[VTIME] = (byte) t.getControlChar(Attributes.ControlChar.VTIME); + tio.c_cc[VSTATUS] = (byte) t.getControlChar(Attributes.ControlChar.VSTATUS); + return tio; + } + + protected Attributes toAttributes(CLibrary.Termios tio) { + Attributes attr = new Attributes(); + // Input flags + EnumSet iflag = attr.getInputFlags(); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.BRKINT, BRKINT); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNPAR, IGNPAR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.PARMRK, PARMRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INPCK, INPCK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ISTRIP, ISTRIP); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INLCR, INLCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNCR, IGNCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ICRNL, ICRNL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXON, IXON); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXOFF, IXOFF); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXANY, IXANY); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IMAXBEL, IMAXBEL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IUTF8, IUTF8); + // Output flags + EnumSet oflag = attr.getOutputFlags(); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OPOST, OPOST); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLCR, ONLCR); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OXTABS, OXTABS); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOEOT, ONOEOT); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OCRNL, OCRNL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOCR, ONOCR); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLRET, ONLRET); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFILL, OFILL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.NLDLY, NLDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.TABDLY, TABDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.CRDLY, CRDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.FFDLY, FFDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.BSDLY, BSDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.VTDLY, VTDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFDEL, OFDEL); + // Control flags + EnumSet cflag = attr.getControlFlags(); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CIGNORE, CIGNORE); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS5, CS5); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS6, CS6); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS7, CS7); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS8, CS8); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CSTOPB, CSTOPB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CREAD, CREAD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARENB, PARENB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARODD, PARODD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.HUPCL, HUPCL); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CLOCAL, CLOCAL); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCTS_OFLOW, CCTS_OFLOW); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CRTS_IFLOW, CRTS_IFLOW); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CDSR_OFLOW, CDSR_OFLOW); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCAR_OFLOW, CCAR_OFLOW); + // Local flags + EnumSet lflag = attr.getLocalFlags(); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOKE, ECHOKE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOE, ECHOE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOK, ECHOK); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHO, ECHO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHONL, ECHONL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOPRT, ECHOPRT); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOCTL, ECHOCTL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ISIG, ISIG); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ICANON, ICANON); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ALTWERASE, ALTWERASE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.IEXTEN, IEXTEN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.EXTPROC, EXTPROC); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.TOSTOP, TOSTOP); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.FLUSHO, FLUSHO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOKERNINFO, NOKERNINFO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.PENDIN, PENDIN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOFLSH, NOFLSH); + // Control chars + EnumMap cc = attr.getControlChars(); + cc.put(Attributes.ControlChar.VEOF, (int) tio.c_cc[VEOF]); + cc.put(Attributes.ControlChar.VEOL, (int) tio.c_cc[VEOL]); + cc.put(Attributes.ControlChar.VEOL2, (int) tio.c_cc[VEOL2]); + cc.put(Attributes.ControlChar.VERASE, (int) tio.c_cc[VERASE]); + cc.put(Attributes.ControlChar.VWERASE, (int) tio.c_cc[VWERASE]); + cc.put(Attributes.ControlChar.VKILL, (int) tio.c_cc[VKILL]); + cc.put(Attributes.ControlChar.VREPRINT, (int) tio.c_cc[VREPRINT]); + cc.put(Attributes.ControlChar.VINTR, (int) tio.c_cc[VINTR]); + cc.put(Attributes.ControlChar.VQUIT, (int) tio.c_cc[VQUIT]); + cc.put(Attributes.ControlChar.VSUSP, (int) tio.c_cc[VSUSP]); + cc.put(Attributes.ControlChar.VDSUSP, (int) tio.c_cc[VDSUSP]); + cc.put(Attributes.ControlChar.VSTART, (int) tio.c_cc[VSTART]); + cc.put(Attributes.ControlChar.VSTOP, (int) tio.c_cc[VSTOP]); + cc.put(Attributes.ControlChar.VLNEXT, (int) tio.c_cc[VLNEXT]); + cc.put(Attributes.ControlChar.VDISCARD, (int) tio.c_cc[VDISCARD]); + cc.put(Attributes.ControlChar.VMIN, (int) tio.c_cc[VMIN]); + cc.put(Attributes.ControlChar.VTIME, (int) tio.c_cc[VTIME]); + cc.put(Attributes.ControlChar.VSTATUS, (int) tio.c_cc[VSTATUS]); + // Return + return attr; + } + + private static long setFlag(boolean flag, long value, long org) { + return flag ? org | value : org; + } + + private static > void addFlag(long value, EnumSet flags, T flag, int v) { + if ((value & v) != 0) { + flags.add(flag); + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/solaris/SolarisNativePty.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/solaris/SolarisNativePty.java new file mode 100644 index 000000000..c34d11b48 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/solaris/SolarisNativePty.java @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.solaris; + +import java.io.FileDescriptor; +import java.io.IOException; +import java.util.EnumMap; +import java.util.EnumSet; + +import org.jline.nativ.CLibrary; +import org.jline.terminal.Attributes; +import org.jline.terminal.Size; +import org.jline.terminal.impl.jni.JniNativePty; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; + +public class SolarisNativePty extends JniNativePty { + + public static SolarisNativePty current(TerminalProvider provider, SystemStream systemStream) throws IOException { + try { + switch (systemStream) { + case Output: + return new SolarisNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 1, FileDescriptor.out, ttyname(1)); + case Error: + return new SolarisNativePty( + provider, systemStream, -1, null, 0, FileDescriptor.in, 2, FileDescriptor.err, ttyname(2)); + default: + throw new IllegalArgumentException("Unsupport stream for console: " + systemStream); + } + } catch (IOException e) { + throw new IOException("Not a tty", e); + } + } + + public static SolarisNativePty open(TerminalProvider provider, Attributes attr, Size size) throws IOException { + int[] master = new int[1]; + int[] slave = new int[1]; + byte[] buf = new byte[64]; + CLibrary.openpty( + master, + slave, + buf, + attr != null ? termios(attr) : null, + size != null ? new CLibrary.WinSize((short) size.getRows(), (short) size.getColumns()) : null); + int len = 0; + while (buf[len] != 0) { + len++; + } + String name = new String(buf, 0, len); + return new SolarisNativePty( + provider, + null, + master[0], + newDescriptor(master[0]), + slave[0], + newDescriptor(slave[0]), + 2, + FileDescriptor.err, + name); + } + + public SolarisNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, name); + } + + public SolarisNativePty( + TerminalProvider provider, + SystemStream systemStream, + int master, + FileDescriptor masterFD, + int slave, + FileDescriptor slaveFD, + int slaveOut, + FileDescriptor slaveOutFD, + String name) { + super(provider, systemStream, master, masterFD, slave, slaveFD, slaveOut, slaveOutFD, name); + } + // CONSTANTS + + private static final int VINTR = 0; + private static final int VQUIT = 1; + private static final int VERASE = 2; + private static final int VKILL = 3; + private static final int VEOF = 4; + private static final int VTIME = 5; + private static final int VMIN = 6; + private static final int VSWTC = 7; + private static final int VSTART = 8; + private static final int VSTOP = 9; + private static final int VSUSP = 10; + private static final int VEOL = 11; + private static final int VREPRINT = 12; + private static final int VDISCARD = 13; + private static final int VWERASE = 14; + private static final int VLNEXT = 15; + private static final int VEOL2 = 16; + + private static final int IGNBRK = 0x0000001; + private static final int BRKINT = 0x0000002; + private static final int IGNPAR = 0x0000004; + private static final int PARMRK = 0x0000010; + private static final int INPCK = 0x0000020; + private static final int ISTRIP = 0x0000040; + private static final int INLCR = 0x0000100; + private static final int IGNCR = 0x0000200; + private static final int ICRNL = 0x0000400; + private static final int IUCLC = 0x0001000; + private static final int IXON = 0x0002000; + private static final int IXANY = 0x0004000; + private static final int IXOFF = 0x0010000; + private static final int IMAXBEL = 0x0020000; + private static final int IUTF8 = 0x0040000; + + private static final int OPOST = 0x0000001; + private static final int OLCUC = 0x0000002; + private static final int ONLCR = 0x0000004; + private static final int OCRNL = 0x0000010; + private static final int ONOCR = 0x0000020; + private static final int ONLRET = 0x0000040; + private static final int OFILL = 0x0000100; + private static final int OFDEL = 0x0000200; + private static final int NLDLY = 0x0000400; + private static final int NL0 = 0x0000000; + private static final int NL1 = 0x0000400; + private static final int CRDLY = 0x0003000; + private static final int CR0 = 0x0000000; + private static final int CR1 = 0x0001000; + private static final int CR2 = 0x0002000; + private static final int CR3 = 0x0003000; + private static final int TABDLY = 0x0014000; + private static final int TAB0 = 0x0000000; + private static final int TAB1 = 0x0004000; + private static final int TAB2 = 0x0010000; + private static final int TAB3 = 0x0014000; + private static final int XTABS = 0x0014000; + private static final int BSDLY = 0x0020000; + private static final int BS0 = 0x0000000; + private static final int BS1 = 0x0020000; + private static final int VTDLY = 0x0040000; + private static final int VT0 = 0x0000000; + private static final int VT1 = 0x0040000; + private static final int FFDLY = 0x0100000; + private static final int FF0 = 0x0000000; + private static final int FF1 = 0x0100000; + + private static final int CBAUD = 0x0010017; + private static final int B0 = 0x0000000; + private static final int B50 = 0x0000001; + private static final int B75 = 0x0000002; + private static final int B110 = 0x0000003; + private static final int B134 = 0x0000004; + private static final int B150 = 0x0000005; + private static final int B200 = 0x0000006; + private static final int B300 = 0x0000007; + private static final int B600 = 0x0000010; + private static final int B1200 = 0x0000011; + private static final int B1800 = 0x0000012; + private static final int B2400 = 0x0000013; + private static final int B4800 = 0x0000014; + private static final int B9600 = 0x0000015; + private static final int B19200 = 0x0000016; + private static final int B38400 = 0x0000017; + private static final int EXTA = 0xB19200; + private static final int EXTB = 0xB38400; + private static final int CSIZE = 0x0000060; + private static final int CS5 = 0x0000000; + private static final int CS6 = 0x0000020; + private static final int CS7 = 0x0000040; + private static final int CS8 = 0x0000060; + private static final int CSTOPB = 0x0000100; + private static final int CREAD = 0x0000200; + private static final int PARENB = 0x0000400; + private static final int PARODD = 0x0001000; + private static final int HUPCL = 0x0002000; + private static final int CLOCAL = 0x0004000; + + private static final int ISIG = 0x0000001; + private static final int ICANON = 0x0000002; + private static final int XCASE = 0x0000004; + private static final int ECHO = 0x0000010; + private static final int ECHOE = 0x0000020; + private static final int ECHOK = 0x0000040; + private static final int ECHONL = 0x0000100; + private static final int NOFLSH = 0x0000200; + private static final int TOSTOP = 0x0000400; + private static final int ECHOCTL = 0x0001000; + private static final int ECHOPRT = 0x0002000; + private static final int ECHOKE = 0x0004000; + private static final int FLUSHO = 0x0010000; + private static final int PENDIN = 0x0040000; + private static final int IEXTEN = 0x0100000; + private static final int EXTPROC = 0x0200000; + + protected CLibrary.Termios toTermios(Attributes t) { + return termios(t); + } + + static CLibrary.Termios termios(Attributes t) { + CLibrary.Termios tio = new CLibrary.Termios(); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNBRK), IGNBRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.BRKINT), BRKINT, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNPAR), IGNPAR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.PARMRK), PARMRK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INPCK), INPCK, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ISTRIP), ISTRIP, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.INLCR), INLCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IGNCR), IGNCR, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.ICRNL), ICRNL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXON), IXON, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXOFF), IXOFF, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IXANY), IXANY, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IMAXBEL), IMAXBEL, tio.c_iflag); + tio.c_iflag = setFlag(t.getInputFlag(Attributes.InputFlag.IUTF8), IUTF8, tio.c_iflag); + // Output flags + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OPOST), OPOST, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLCR), ONLCR, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OXTABS), OXTABS, tio.c_oflag); + // tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOEOT), ONOEOT, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OCRNL), OCRNL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONOCR), ONOCR, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.ONLRET), ONLRET, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFILL), OFILL, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.NLDLY), NLDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.TABDLY), TABDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.CRDLY), CRDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.FFDLY), FFDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.BSDLY), BSDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.VTDLY), VTDLY, tio.c_oflag); + tio.c_oflag = setFlag(t.getOutputFlag(Attributes.OutputFlag.OFDEL), OFDEL, tio.c_oflag); + // Control flags + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CIGNORE), CIGNORE, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS5), CS5, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS6), CS6, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS7), CS7, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CS8), CS8, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CSTOPB), CSTOPB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CREAD), CREAD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARENB), PARENB, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.PARODD), PARODD, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.HUPCL), HUPCL, tio.c_cflag); + tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CLOCAL), CLOCAL, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCTS_OFLOW), CCTS_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CRTS_IFLOW), CRTS_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDTR_IFLOW), CDTR_IFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CDSR_OFLOW), CDSR_OFLOW, tio.c_cflag); + // tio.c_cflag = setFlag(t.getControlFlag(Attributes.ControlFlag.CCAR_OFLOW), CCAR_OFLOW, tio.c_cflag); + // Local flags + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOKE), ECHOKE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOE), ECHOE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOK), ECHOK, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHO), ECHO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHONL), ECHONL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOPRT), ECHOPRT, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ECHOCTL), ECHOCTL, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ISIG), ISIG, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ICANON), ICANON, tio.c_lflag); + // tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.ALTWERASE), ALTWERASE, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.IEXTEN), IEXTEN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.EXTPROC), EXTPROC, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.TOSTOP), TOSTOP, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.FLUSHO), FLUSHO, tio.c_lflag); + // tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOKERNINFO), NOKERNINFO, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.PENDIN), PENDIN, tio.c_lflag); + tio.c_lflag = setFlag(t.getLocalFlag(Attributes.LocalFlag.NOFLSH), NOFLSH, tio.c_lflag); + // Control chars + tio.c_cc[VEOF] = (byte) t.getControlChar(Attributes.ControlChar.VEOF); + tio.c_cc[VEOL] = (byte) t.getControlChar(Attributes.ControlChar.VEOL); + tio.c_cc[VEOL2] = (byte) t.getControlChar(Attributes.ControlChar.VEOL2); + tio.c_cc[VERASE] = (byte) t.getControlChar(Attributes.ControlChar.VERASE); + tio.c_cc[VWERASE] = (byte) t.getControlChar(Attributes.ControlChar.VWERASE); + tio.c_cc[VKILL] = (byte) t.getControlChar(Attributes.ControlChar.VKILL); + tio.c_cc[VREPRINT] = (byte) t.getControlChar(Attributes.ControlChar.VREPRINT); + tio.c_cc[VINTR] = (byte) t.getControlChar(Attributes.ControlChar.VINTR); + tio.c_cc[VQUIT] = (byte) t.getControlChar(Attributes.ControlChar.VQUIT); + tio.c_cc[VSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VSUSP); + // tio.c_cc[VDSUSP] = (byte) t.getControlChar(Attributes.ControlChar.VDSUSP); + tio.c_cc[VSTART] = (byte) t.getControlChar(Attributes.ControlChar.VSTART); + tio.c_cc[VSTOP] = (byte) t.getControlChar(Attributes.ControlChar.VSTOP); + tio.c_cc[VLNEXT] = (byte) t.getControlChar(Attributes.ControlChar.VLNEXT); + tio.c_cc[VDISCARD] = (byte) t.getControlChar(Attributes.ControlChar.VDISCARD); + tio.c_cc[VMIN] = (byte) t.getControlChar(Attributes.ControlChar.VMIN); + tio.c_cc[VTIME] = (byte) t.getControlChar(Attributes.ControlChar.VTIME); + // tio.c_cc[VSTATUS] = (byte) t.getControlChar(Attributes.ControlChar.VSTATUS); + return tio; + } + + protected Attributes toAttributes(CLibrary.Termios tio) { + Attributes attr = new Attributes(); + // Input flags + EnumSet iflag = attr.getInputFlags(); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNBRK, IGNBRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.BRKINT, BRKINT); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNPAR, IGNPAR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.PARMRK, PARMRK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INPCK, INPCK); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ISTRIP, ISTRIP); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.INLCR, INLCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IGNCR, IGNCR); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.ICRNL, ICRNL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXON, IXON); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXOFF, IXOFF); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IXANY, IXANY); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IMAXBEL, IMAXBEL); + addFlag(tio.c_iflag, iflag, Attributes.InputFlag.IUTF8, IUTF8); + // Output flags + EnumSet oflag = attr.getOutputFlags(); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OPOST, OPOST); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLCR, ONLCR); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OXTABS, OXTABS); + // addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOEOT, ONOEOT); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OCRNL, OCRNL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONOCR, ONOCR); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.ONLRET, ONLRET); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFILL, OFILL); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.NLDLY, NLDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.TABDLY, TABDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.CRDLY, CRDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.FFDLY, FFDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.BSDLY, BSDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.VTDLY, VTDLY); + addFlag(tio.c_oflag, oflag, Attributes.OutputFlag.OFDEL, OFDEL); + // Control flags + EnumSet cflag = attr.getControlFlags(); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CIGNORE, CIGNORE); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS5, CS5); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS6, CS6); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS7, CS7); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CS8, CS8); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CSTOPB, CSTOPB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CREAD, CREAD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARENB, PARENB); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.PARODD, PARODD); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.HUPCL, HUPCL); + addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CLOCAL, CLOCAL); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCTS_OFLOW, CCTS_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CRTS_IFLOW, CRTS_IFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CDSR_OFLOW, CDSR_OFLOW); + // addFlag(tio.c_cflag, cflag, Attributes.ControlFlag.CCAR_OFLOW, CCAR_OFLOW); + // Local flags + EnumSet lflag = attr.getLocalFlags(); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOKE, ECHOKE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOE, ECHOE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOK, ECHOK); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHO, ECHO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHONL, ECHONL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOPRT, ECHOPRT); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ECHOCTL, ECHOCTL); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ISIG, ISIG); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ICANON, ICANON); + // addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.ALTWERASE, ALTWERASE); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.IEXTEN, IEXTEN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.EXTPROC, EXTPROC); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.TOSTOP, TOSTOP); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.FLUSHO, FLUSHO); + // addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOKERNINFO, NOKERNINFO); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.PENDIN, PENDIN); + addFlag(tio.c_lflag, lflag, Attributes.LocalFlag.NOFLSH, NOFLSH); + // Control chars + EnumMap cc = attr.getControlChars(); + cc.put(Attributes.ControlChar.VEOF, (int) tio.c_cc[VEOF]); + cc.put(Attributes.ControlChar.VEOL, (int) tio.c_cc[VEOL]); + cc.put(Attributes.ControlChar.VEOL2, (int) tio.c_cc[VEOL2]); + cc.put(Attributes.ControlChar.VERASE, (int) tio.c_cc[VERASE]); + cc.put(Attributes.ControlChar.VWERASE, (int) tio.c_cc[VWERASE]); + cc.put(Attributes.ControlChar.VKILL, (int) tio.c_cc[VKILL]); + cc.put(Attributes.ControlChar.VREPRINT, (int) tio.c_cc[VREPRINT]); + cc.put(Attributes.ControlChar.VINTR, (int) tio.c_cc[VINTR]); + cc.put(Attributes.ControlChar.VQUIT, (int) tio.c_cc[VQUIT]); + cc.put(Attributes.ControlChar.VSUSP, (int) tio.c_cc[VSUSP]); + // cc.put(Attributes.ControlChar.VDSUSP, (int) tio.c_cc[VDSUSP]); + cc.put(Attributes.ControlChar.VSTART, (int) tio.c_cc[VSTART]); + cc.put(Attributes.ControlChar.VSTOP, (int) tio.c_cc[VSTOP]); + cc.put(Attributes.ControlChar.VLNEXT, (int) tio.c_cc[VLNEXT]); + cc.put(Attributes.ControlChar.VDISCARD, (int) tio.c_cc[VDISCARD]); + cc.put(Attributes.ControlChar.VMIN, (int) tio.c_cc[VMIN]); + cc.put(Attributes.ControlChar.VTIME, (int) tio.c_cc[VTIME]); + // cc.put(Attributes.ControlChar.VSTATUS, (int) tio.c_cc[VSTATUS]); + // Return + return attr; + } + + private static long setFlag(boolean flag, long value, long org) { + return flag ? org | value : org; + } + + private static > void addFlag(long value, EnumSet flags, T flag, int v) { + if ((value & v) != 0) { + flags.add(flag); + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinConsoleWriter.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinConsoleWriter.java new file mode 100644 index 000000000..fa4a9f6e2 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinConsoleWriter.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2017, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.win; + +import java.io.IOException; + +import org.jline.nativ.Kernel32; +import org.jline.terminal.impl.AbstractWindowsConsoleWriter; + +class NativeWinConsoleWriter extends AbstractWindowsConsoleWriter { + + private final long console; + private final int[] writtenChars = new int[1]; + + public NativeWinConsoleWriter(long console) { + this.console = console; + } + + @Override + protected void writeConsole(char[] text, int len) throws IOException { + if (Kernel32.WriteConsoleW(console, text, len, writtenChars, 0) == 0) { + throw new IOException("Failed to write to console: " + Kernel32.getLastErrorMessage()); + } + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinSysTerminal.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinSysTerminal.java new file mode 100644 index 000000000..6e8abfad6 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/NativeWinSysTerminal.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2002-2020, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.win; + +import java.io.BufferedWriter; +import java.io.IOError; +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.function.IntConsumer; + +import org.jline.nativ.Kernel32; +import org.jline.nativ.Kernel32.CONSOLE_SCREEN_BUFFER_INFO; +import org.jline.nativ.Kernel32.INPUT_RECORD; +import org.jline.nativ.Kernel32.KEY_EVENT_RECORD; +import org.jline.terminal.Cursor; +import org.jline.terminal.Size; +import org.jline.terminal.impl.AbstractWindowsTerminal; +import org.jline.terminal.spi.SystemStream; +import org.jline.terminal.spi.TerminalProvider; +import org.jline.utils.InfoCmp; +import org.jline.utils.OSUtils; + +import static org.jline.nativ.Kernel32.FORMAT_MESSAGE_FROM_SYSTEM; +import static org.jline.nativ.Kernel32.FormatMessageW; +import static org.jline.nativ.Kernel32.GetConsoleScreenBufferInfo; +import static org.jline.nativ.Kernel32.GetLastError; +import static org.jline.nativ.Kernel32.GetStdHandle; +import static org.jline.nativ.Kernel32.INVALID_HANDLE_VALUE; +import static org.jline.nativ.Kernel32.STD_ERROR_HANDLE; +import static org.jline.nativ.Kernel32.STD_INPUT_HANDLE; +import static org.jline.nativ.Kernel32.STD_OUTPUT_HANDLE; +import static org.jline.nativ.Kernel32.WaitForSingleObject; +import static org.jline.nativ.Kernel32.readConsoleInputHelper; + +public class NativeWinSysTerminal extends AbstractWindowsTerminal { + + private static final long consoleIn = GetStdHandle(STD_INPUT_HANDLE); + private static final long consoleOut = GetStdHandle(STD_OUTPUT_HANDLE); + private static final long consoleErr = GetStdHandle(STD_ERROR_HANDLE); + + public static NativeWinSysTerminal createTerminal( + TerminalProvider provider, + SystemStream systemStream, + String name, + String type, + boolean ansiPassThrough, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + boolean paused) + throws IOException { + // Get input console mode + int[] inMode = new int[1]; + if (Kernel32.GetConsoleMode(consoleIn, inMode) == 0) { + throw new IOException("Failed to get console mode: " + getLastErrorMessage()); + } + // Get output console and mode + long console = getConsole(systemStream); + int[] outMode = new int[1]; + if (Kernel32.GetConsoleMode(console, outMode) == 0) { + throw new IOException("Failed to get console mode: " + getLastErrorMessage()); + } + // Create writer + Writer writer; + if (ansiPassThrough) { + type = type != null ? type : OSUtils.IS_CONEMU ? TYPE_WINDOWS_CONEMU : TYPE_WINDOWS; + writer = newConsoleWriter(console); + } else { + if (enableVtp(console, outMode[0])) { + type = type != null ? type : TYPE_WINDOWS_VTP; + writer = newConsoleWriter(console); + } else if (OSUtils.IS_CONEMU) { + type = type != null ? type : TYPE_WINDOWS_CONEMU; + writer = newConsoleWriter(console); + } else { + type = type != null ? type : TYPE_WINDOWS; + writer = new WindowsAnsiWriter(new BufferedWriter(newConsoleWriter(console))); + } + } + // Create terminal + NativeWinSysTerminal terminal = new NativeWinSysTerminal( + provider, + systemStream, + writer, + name, + type, + encoding, + nativeSignals, + signalHandler, + consoleIn, + inMode[0], + console, + outMode[0]); + // Start input pump thread + if (!paused) { + terminal.resume(); + } + return terminal; + } + + public static long getConsole(SystemStream systemStream) { + long console; + switch (systemStream) { + case Output: + console = consoleOut; + break; + case Error: + console = consoleErr; + break; + default: + throw new IllegalArgumentException("Unsupported stream for console: " + systemStream); + } + return console; + } + + private static boolean enableVtp(long console, int outMode) { + return Kernel32.SetConsoleMode(console, outMode | AbstractWindowsTerminal.ENABLE_VIRTUAL_TERMINAL_PROCESSING) + != 0; + } + + private static Writer newConsoleWriter(long console) { + return new NativeWinConsoleWriter(console); + } + + public static boolean isWindowsSystemStream(SystemStream stream) { + int[] mode = new int[1]; + long console; + switch (stream) { + case Input: + console = consoleIn; + break; + case Output: + console = consoleOut; + break; + case Error: + console = consoleErr; + break; + default: + return false; + } + return Kernel32.GetConsoleMode(console, mode) != 0; + } + + NativeWinSysTerminal( + TerminalProvider provider, + SystemStream systemStream, + Writer writer, + String name, + String type, + Charset encoding, + boolean nativeSignals, + SignalHandler signalHandler, + long inConsole, + int inMode, + long outConsole, + int outMode) + throws IOException { + super( + provider, + systemStream, + writer, + name, + type, + encoding, + nativeSignals, + signalHandler, + inConsole, + inMode, + outConsole, + outMode); + } + + @Override + protected int getConsoleMode(Long console) { + int[] mode = new int[1]; + if (Kernel32.GetConsoleMode(console, mode) == 0) { + return -1; + } + return mode[0]; + } + + @Override + protected void setConsoleMode(Long console, int mode) { + Kernel32.SetConsoleMode(console, mode); + } + + public Size getSize() { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(); + Kernel32.GetConsoleScreenBufferInfo(outConsole, info); + return new Size(info.windowWidth(), info.windowHeight()); + } + + @Override + public Size getBufferSize() { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(); + Kernel32.GetConsoleScreenBufferInfo(outConsole, info); + return new Size(info.size.x, info.size.y); + } + + protected boolean processConsoleInput() throws IOException { + INPUT_RECORD[] events; + if (inConsole != INVALID_HANDLE_VALUE && WaitForSingleObject(inConsole, 100) == 0) { + events = readConsoleInputHelper(inConsole, 1, false); + } else { + return false; + } + + boolean flush = false; + for (INPUT_RECORD event : events) { + if (event.eventType == INPUT_RECORD.KEY_EVENT) { + KEY_EVENT_RECORD keyEvent = event.keyEvent; + processKeyEvent(keyEvent.keyDown, keyEvent.keyCode, keyEvent.uchar, keyEvent.controlKeyState); + flush = true; + } else if (event.eventType == INPUT_RECORD.WINDOW_BUFFER_SIZE_EVENT) { + raise(Signal.WINCH); + } else if (event.eventType == INPUT_RECORD.MOUSE_EVENT) { + processMouseEvent(event.mouseEvent); + flush = true; + } else if (event.eventType == INPUT_RECORD.FOCUS_EVENT) { + processFocusEvent(event.focusEvent.setFocus); + } + } + + return flush; + } + + private char[] focus = new char[] {'\033', '[', ' '}; + + private void processFocusEvent(boolean hasFocus) throws IOException { + if (focusTracking) { + focus[2] = hasFocus ? 'I' : 'O'; + slaveInputPipe.write(focus); + } + } + + private char[] mouse = new char[] {'\033', '[', 'M', ' ', ' ', ' '}; + + private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IOException { + int dwEventFlags = mouseEvent.eventFlags; + int dwButtonState = mouseEvent.buttonState; + if (tracking == MouseTracking.Off + || tracking == MouseTracking.Normal && dwEventFlags == Kernel32.MOUSE_EVENT_RECORD.MOUSE_MOVED + || tracking == MouseTracking.Button + && dwEventFlags == Kernel32.MOUSE_EVENT_RECORD.MOUSE_MOVED + && dwButtonState == 0) { + return; + } + int cb = 0; + dwEventFlags &= ~Kernel32.MOUSE_EVENT_RECORD.DOUBLE_CLICK; // Treat double-clicks as normal + if (dwEventFlags == Kernel32.MOUSE_EVENT_RECORD.MOUSE_WHEELED) { + cb |= 64; + if ((dwButtonState >> 16) < 0) { + cb |= 1; + } + } else if (dwEventFlags == Kernel32.MOUSE_EVENT_RECORD.MOUSE_HWHEELED) { + return; + } else if ((dwButtonState & Kernel32.MOUSE_EVENT_RECORD.FROM_LEFT_1ST_BUTTON_PRESSED) != 0) { + cb |= 0x00; + } else if ((dwButtonState & Kernel32.MOUSE_EVENT_RECORD.RIGHTMOST_BUTTON_PRESSED) != 0) { + cb |= 0x01; + } else if ((dwButtonState & Kernel32.MOUSE_EVENT_RECORD.FROM_LEFT_2ND_BUTTON_PRESSED) != 0) { + cb |= 0x02; + } else { + cb |= 0x03; + } + int cx = mouseEvent.mousePosition.x; + int cy = mouseEvent.mousePosition.y; + mouse[3] = (char) (' ' + cb); + mouse[4] = (char) (' ' + cx + 1); + mouse[5] = (char) (' ' + cy + 1); + slaveInputPipe.write(mouse); + } + + @Override + public Cursor getCursorPosition(IntConsumer discarded) { + CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(); + if (GetConsoleScreenBufferInfo(outConsole, info) == 0) { + throw new IOError(new IOException("Could not get the cursor position: " + getLastErrorMessage())); + } + return new Cursor(info.cursorPosition.x, info.cursorPosition.y); + } + + public void disableScrolling() { + strings.remove(InfoCmp.Capability.insert_line); + strings.remove(InfoCmp.Capability.parm_insert_line); + strings.remove(InfoCmp.Capability.delete_line); + strings.remove(InfoCmp.Capability.parm_delete_line); + } + + static String getLastErrorMessage() { + int errorCode = GetLastError(); + return getErrorMessage(errorCode); + } + + static String getErrorMessage(int errorCode) { + int bufferSize = 160; + byte[] data = new byte[bufferSize]; + FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, bufferSize, null); + return new String(data, StandardCharsets.UTF_16LE).trim(); + } +} diff --git a/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/WindowsAnsiWriter.java b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/WindowsAnsiWriter.java new file mode 100644 index 000000000..32d2a32e3 --- /dev/null +++ b/terminal-jni/src/main/java/org/jline/terminal/impl/jni/win/WindowsAnsiWriter.java @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2009-2018, the original author(s). + * + * This software is distributable under the BSD license. See the terms of the + * BSD license in the documentation provided with this software. + * + * https://opensource.org/licenses/BSD-3-Clause + */ +package org.jline.terminal.impl.jni.win; + +import java.io.IOException; +import java.io.Writer; + +import org.jline.nativ.Kernel32; +import org.jline.utils.AnsiWriter; +import org.jline.utils.Colors; + +import static org.jline.nativ.Kernel32.*; + +/** + * A Windows ANSI escape processor, that uses JNA to access native platform + * API's to change the console attributes. + * + * @since 1.0 + * @author Hiram Chirino + * @author Joris Kuipers + */ +public final class WindowsAnsiWriter extends AnsiWriter { + + private static final long console = GetStdHandle(STD_OUTPUT_HANDLE); + + private static final short FOREGROUND_BLACK = 0; + private static final short FOREGROUND_YELLOW = (short) (FOREGROUND_RED | FOREGROUND_GREEN); + private static final short FOREGROUND_MAGENTA = (short) (FOREGROUND_BLUE | FOREGROUND_RED); + private static final short FOREGROUND_CYAN = (short) (FOREGROUND_BLUE | FOREGROUND_GREEN); + private static final short FOREGROUND_WHITE = (short) (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); + + private static final short BACKGROUND_BLACK = 0; + private static final short BACKGROUND_YELLOW = (short) (BACKGROUND_RED | BACKGROUND_GREEN); + private static final short BACKGROUND_MAGENTA = (short) (BACKGROUND_BLUE | BACKGROUND_RED); + private static final short BACKGROUND_CYAN = (short) (BACKGROUND_BLUE | BACKGROUND_GREEN); + private static final short BACKGROUND_WHITE = (short) (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); + + private static final short[] ANSI_FOREGROUND_COLOR_MAP = { + FOREGROUND_BLACK, + FOREGROUND_RED, + FOREGROUND_GREEN, + FOREGROUND_YELLOW, + FOREGROUND_BLUE, + FOREGROUND_MAGENTA, + FOREGROUND_CYAN, + FOREGROUND_WHITE, + }; + + private static final short[] ANSI_BACKGROUND_COLOR_MAP = { + BACKGROUND_BLACK, + BACKGROUND_RED, + BACKGROUND_GREEN, + BACKGROUND_YELLOW, + BACKGROUND_BLUE, + BACKGROUND_MAGENTA, + BACKGROUND_CYAN, + BACKGROUND_WHITE, + }; + + private final CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO(); + private final short originalColors; + + private boolean negative; + private boolean bold; + private boolean underline; + private short savedX = -1; + private short savedY = -1; + + public WindowsAnsiWriter(Writer out) throws IOException { + super(out); + getConsoleInfo(); + originalColors = info.attributes; + } + + private void getConsoleInfo() throws IOException { + out.flush(); + if (GetConsoleScreenBufferInfo(console, info) == 0) { + throw new IOException("Could not get the screen info: " + Kernel32.getLastErrorMessage()); + } + if (negative) { + info.attributes = invertAttributeColors(info.attributes); + } + } + + private void applyAttribute() throws IOException { + out.flush(); + short attributes = info.attributes; + // bold is simulated by high foreground intensity + if (bold) { + attributes |= FOREGROUND_INTENSITY; + } + // underline is simulated by high foreground intensity + if (underline) { + attributes |= BACKGROUND_INTENSITY; + } + if (negative) { + attributes = invertAttributeColors(attributes); + } + if (SetConsoleTextAttribute(console, attributes) == 0) { + throw new IOException(Kernel32.getLastErrorMessage()); + } + } + + private short invertAttributeColors(short attributes) { + // Swap the the Foreground and Background bits. + int fg = 0x000F & attributes; + fg <<= 4; + int bg = 0X00F0 & attributes; + bg >>= 4; + attributes = (short) ((attributes & 0xFF00) | fg | bg); + return attributes; + } + + private void applyCursorPosition() throws IOException { + info.cursorPosition.x = (short) Math.max(0, Math.min(info.size.x - 1, info.cursorPosition.x)); + info.cursorPosition.y = (short) Math.max(0, Math.min(info.size.y - 1, info.cursorPosition.y)); + if (SetConsoleCursorPosition(console, info.cursorPosition.copy()) == 0) { + throw new IOException(Kernel32.getLastErrorMessage()); + } + } + + @Override + protected void processEraseScreen(int eraseOption) throws IOException { + getConsoleInfo(); + int[] written = new int[1]; + switch (eraseOption) { + case ERASE_SCREEN: + COORD topLeft = new COORD(); + topLeft.x = 0; + topLeft.y = info.window.top; + int screenLength = info.window.height() * info.size.x; + FillConsoleOutputAttribute(console, originalColors, screenLength, topLeft, written); + FillConsoleOutputCharacterW(console, ' ', screenLength, topLeft, written); + break; + case ERASE_SCREEN_TO_BEGINING: + COORD topLeft2 = new COORD(); + topLeft2.x = 0; + topLeft2.y = info.window.top; + int lengthToCursor = (info.cursorPosition.y - info.window.top) * info.size.x + info.cursorPosition.x; + FillConsoleOutputAttribute(console, originalColors, lengthToCursor, topLeft2, written); + FillConsoleOutputCharacterW(console, ' ', lengthToCursor, topLeft2, written); + break; + case ERASE_SCREEN_TO_END: + int lengthToEnd = (info.window.bottom - info.cursorPosition.y) * info.size.x + + (info.size.x - info.cursorPosition.x); + FillConsoleOutputAttribute(console, originalColors, lengthToEnd, info.cursorPosition.copy(), written); + FillConsoleOutputCharacterW(console, ' ', lengthToEnd, info.cursorPosition.copy(), written); + break; + default: + break; + } + } + + @Override + protected void processEraseLine(int eraseOption) throws IOException { + getConsoleInfo(); + int[] written = new int[1]; + switch (eraseOption) { + case ERASE_LINE: + COORD leftColCurrRow = info.cursorPosition.copy(); + leftColCurrRow.x = 0; + FillConsoleOutputAttribute(console, originalColors, info.size.x, leftColCurrRow, written); + FillConsoleOutputCharacterW(console, ' ', info.size.x, leftColCurrRow, written); + break; + case ERASE_LINE_TO_BEGINING: + COORD leftColCurrRow2 = info.cursorPosition.copy(); + leftColCurrRow2.x = 0; + FillConsoleOutputAttribute(console, originalColors, info.cursorPosition.x, leftColCurrRow2, written); + FillConsoleOutputCharacterW(console, ' ', info.cursorPosition.x, leftColCurrRow2, written); + break; + case ERASE_LINE_TO_END: + int lengthToLastCol = info.size.x - info.cursorPosition.x; + FillConsoleOutputAttribute( + console, originalColors, lengthToLastCol, info.cursorPosition.copy(), written); + FillConsoleOutputCharacterW(console, ' ', lengthToLastCol, info.cursorPosition.copy(), written); + break; + default: + break; + } + } + + protected void processCursorUpLine(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition.x = 0; + info.cursorPosition.y -= (short) count; + applyCursorPosition(); + } + + protected void processCursorDownLine(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition.x = 0; + info.cursorPosition.y += (short) count; + applyCursorPosition(); + } + + @Override + protected void processCursorLeft(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition.x -= (short) count; + applyCursorPosition(); + } + + @Override + protected void processCursorRight(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition.x += (short) count; + applyCursorPosition(); + } + + @Override + protected void processCursorDown(int count) throws IOException { + getConsoleInfo(); + int nb = Math.max(0, info.cursorPosition.y + count - info.size.y + 1); + if (nb != count) { + info.cursorPosition.y += (short) count; + applyCursorPosition(); + } + if (nb > 0) { + SMALL_RECT scroll = info.window.copy(); + scroll.top = 0; + COORD org = new COORD(); + org.x = 0; + org.y = (short) (-nb); + CHAR_INFO info = new CHAR_INFO(); + info.unicodeChar = ' '; + info.attributes = originalColors; + ScrollConsoleScreenBuffer(console, scroll, scroll, org, info); + } + } + + @Override + protected void processCursorUp(int count) throws IOException { + getConsoleInfo(); + info.cursorPosition.y -= (short) count; + applyCursorPosition(); + } + + @Override + protected void processCursorTo(int row, int col) throws IOException { + getConsoleInfo(); + info.cursorPosition.y = (short) (info.window.top + row - 1); + info.cursorPosition.x = (short) (col - 1); + applyCursorPosition(); + } + + @Override + protected void processCursorToColumn(int x) throws IOException { + getConsoleInfo(); + info.cursorPosition.x = (short) (x - 1); + applyCursorPosition(); + } + + @Override + protected void processSetForegroundColorExt(int paletteIndex) throws IOException { + int color = Colors.roundColor(paletteIndex, 16); + info.attributes = (short) ((info.attributes & ~0x0007) | ANSI_FOREGROUND_COLOR_MAP[color & 0x07]); + info.attributes = (short) ((info.attributes & ~FOREGROUND_INTENSITY) | (color >= 8 ? FOREGROUND_INTENSITY : 0)); + applyAttribute(); + } + + @Override + protected void processSetBackgroundColorExt(int paletteIndex) throws IOException { + int color = Colors.roundColor(paletteIndex, 16); + info.attributes = (short) ((info.attributes & ~0x0070) | ANSI_BACKGROUND_COLOR_MAP[color & 0x07]); + info.attributes = (short) ((info.attributes & ~BACKGROUND_INTENSITY) | (color >= 8 ? BACKGROUND_INTENSITY : 0)); + applyAttribute(); + } + + @Override + protected void processDefaultTextColor() throws IOException { + info.attributes = (short) ((info.attributes & ~0x000F) | (originalColors & 0xF)); + info.attributes = (short) (info.attributes & ~FOREGROUND_INTENSITY); + applyAttribute(); + } + + @Override + protected void processDefaultBackgroundColor() throws IOException { + info.attributes = (short) ((info.attributes & ~0x00F0) | (originalColors & 0xF0)); + info.attributes = (short) (info.attributes & ~BACKGROUND_INTENSITY); + applyAttribute(); + } + + @Override + protected void processAttributeRest() throws IOException { + info.attributes = (short) ((info.attributes & ~0x00FF) | originalColors); + this.negative = false; + this.bold = false; + this.underline = false; + applyAttribute(); + } + + @Override + protected void processSetAttribute(int attribute) throws IOException { + switch (attribute) { + case ATTRIBUTE_INTENSITY_BOLD: + bold = true; + applyAttribute(); + break; + case ATTRIBUTE_INTENSITY_NORMAL: + bold = false; + applyAttribute(); + break; + + case ATTRIBUTE_UNDERLINE: + underline = true; + applyAttribute(); + break; + case ATTRIBUTE_UNDERLINE_OFF: + underline = false; + applyAttribute(); + break; + + case ATTRIBUTE_NEGATIVE_ON: + negative = true; + applyAttribute(); + break; + case ATTRIBUTE_NEGATIVE_OFF: + negative = false; + applyAttribute(); + break; + default: + break; + } + } + + @Override + protected void processSaveCursorPosition() throws IOException { + getConsoleInfo(); + savedX = info.cursorPosition.x; + savedY = info.cursorPosition.y; + } + + @Override + protected void processRestoreCursorPosition() throws IOException { + // restore only if there was a save operation first + if (savedX != -1 && savedY != -1) { + out.flush(); + info.cursorPosition.x = savedX; + info.cursorPosition.y = savedY; + applyCursorPosition(); + } + } + + @Override + protected void processInsertLine(int optionInt) throws IOException { + getConsoleInfo(); + SMALL_RECT scroll = info.window.copy(); + scroll.top = info.cursorPosition.y; + COORD org = new COORD(); + org.x = 0; + org.y = (short) (info.cursorPosition.y + optionInt); + CHAR_INFO info = new CHAR_INFO(); + info.attributes = originalColors; + info.unicodeChar = ' '; + if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) { + throw new IOException(Kernel32.getLastErrorMessage()); + } + } + + @Override + protected void processDeleteLine(int optionInt) throws IOException { + getConsoleInfo(); + SMALL_RECT scroll = info.window.copy(); + scroll.top = info.cursorPosition.y; + COORD org = new COORD(); + org.x = 0; + org.y = (short) (info.cursorPosition.y - optionInt); + CHAR_INFO info = new CHAR_INFO(); + info.attributes = originalColors; + info.unicodeChar = ' '; + if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) { + throw new IOException(Kernel32.getLastErrorMessage()); + } + } + + @Override + protected void processChangeWindowTitle(String title) { + SetConsoleTitle(title); + } +} diff --git a/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/native-image.properties b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/native-image.properties new file mode 100644 index 000000000..1a4e8e5a5 --- /dev/null +++ b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/native-image.properties @@ -0,0 +1 @@ +Args = -H:ResourceConfigurationResources=${.}/resource-config.json -H:ReflectionConfigurationResources=${.}/reflection-config.json diff --git a/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/reflection-config.json b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/reflection-config.json new file mode 100644 index 000000000..d769687cc --- /dev/null +++ b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/reflection-config.json @@ -0,0 +1,11 @@ +[ + { + "name" : "org.jline.terminal.impl.jni.JniTerminalProvider", + "allDeclaredConstructors" : true, + "allPublicConstructors" : true, + "allDeclaredMethods" : false, + "allPublicMethods" : false, + "allDeclaredFields" : false, + "allPublicFields" : false + } +] \ No newline at end of file diff --git a/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/resource-config.json b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/resource-config.json new file mode 100644 index 000000000..f187ea298 --- /dev/null +++ b/terminal-jni/src/main/resources/META-INF/native-image/org.jline/jline-terminal-jni/resource-config.json @@ -0,0 +1,5 @@ +{ + "resources": [ + {"pattern": "META-INF/services/org/jline/terminal/provider/.*"} + ] +} \ No newline at end of file diff --git a/terminal-jni/src/main/resources/META-INF/services/org/jline/terminal/provider/jni b/terminal-jni/src/main/resources/META-INF/services/org/jline/terminal/provider/jni new file mode 100644 index 000000000..10de0e864 --- /dev/null +++ b/terminal-jni/src/main/resources/META-INF/services/org/jline/terminal/provider/jni @@ -0,0 +1,16 @@ +# +# Copyright (C) 2022 the original author(s). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +class = org.jline.terminal.impl.jni.JniTerminalProvider diff --git a/terminal/src/main/java/org/jline/terminal/TerminalBuilder.java b/terminal/src/main/java/org/jline/terminal/TerminalBuilder.java index 1f7fb8fe1..484809b93 100644 --- a/terminal/src/main/java/org/jline/terminal/TerminalBuilder.java +++ b/terminal/src/main/java/org/jline/terminal/TerminalBuilder.java @@ -49,13 +49,15 @@ public final class TerminalBuilder { public static final String PROP_TYPE = "org.jline.terminal.type"; public static final String PROP_PROVIDERS = "org.jline.terminal.providers"; public static final String PROP_PROVIDER_FFM = "ffm"; + public static final String PROP_PROVIDER_JNI = "jni"; public static final String PROP_PROVIDER_JANSI = "jansi"; public static final String PROP_PROVIDER_JNA = "jna"; public static final String PROP_PROVIDER_EXEC = "exec"; public static final String PROP_PROVIDER_DUMB = "dumb"; - public static final String PROP_PROVIDERS_DEFAULT = - String.join(",", PROP_PROVIDER_FFM, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC); + public static final String PROP_PROVIDERS_DEFAULT = String.join( + ",", PROP_PROVIDER_FFM, PROP_PROVIDER_JNI, PROP_PROVIDER_JANSI, PROP_PROVIDER_JNA, PROP_PROVIDER_EXEC); public static final String PROP_FFM = "org.jline.terminal." + PROP_PROVIDER_FFM; + public static final String PROP_JNI = "org.jline.terminal." + PROP_PROVIDER_JNI; public static final String PROP_JANSI = "org.jline.terminal." + PROP_PROVIDER_JANSI; public static final String PROP_JNA = "org.jline.terminal." + PROP_PROVIDER_JNA; public static final String PROP_EXEC = "org.jline.terminal." + PROP_PROVIDER_EXEC; @@ -145,6 +147,7 @@ public static TerminalBuilder builder() { private String providers; private Boolean jna; private Boolean jansi; + private Boolean jni; private Boolean exec; private Boolean ffm; private Boolean dumb; @@ -202,6 +205,11 @@ public TerminalBuilder jansi(boolean jansi) { return this; } + public TerminalBuilder jni(boolean jni) { + this.jni = jni; + return this; + } + public TerminalBuilder exec(boolean exec) { this.exec = exec; return this; @@ -412,7 +420,7 @@ private Terminal doBuild() throws IOException { } } } - if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && (dumb == null || !dumb)) { + if (terminal == null && OSUtils.IS_WINDOWS && !jna && !jansi && !jni && (dumb == null || !dumb)) { throw new IllegalStateException("Unable to create a system terminal. On windows, either " + "JNA or JANSI library is required. Make sure to add one of those in the classpath."); } @@ -589,6 +597,8 @@ public List getProviders(IllegalStateException exception) { List providers = new ArrayList<>(); // Check ffm provider checkProvider(exception, providers, ffm, PROP_FFM, PROP_PROVIDER_FFM); + // Check jni provider + checkProvider(exception, providers, jni, PROP_JNI, PROP_PROVIDER_JNI); // Check jansi provider checkProvider(exception, providers, jansi, PROP_JANSI, PROP_PROVIDER_JANSI); // Check jna provider diff --git a/terminal/src/main/java/org/jline/terminal/impl/Diag.java b/terminal/src/main/java/org/jline/terminal/impl/Diag.java index b35e62555..ecef6c13f 100644 --- a/terminal/src/main/java/org/jline/terminal/impl/Diag.java +++ b/terminal/src/main/java/org/jline/terminal/impl/Diag.java @@ -82,6 +82,16 @@ static void diag(PrintStream out) { } out.println(); + out.println("JniSupport"); + out.println("================="); + try { + TerminalProvider provider = TerminalProvider.load("jni"); + testProvider(out, provider); + } catch (Throwable t) { + out.println("JNI support not available: " + t); + } + out.println(); + // Exec out.println("Exec Support"); out.println("================="); From bcc083615ca15d43e87692e83fa348098babe0c1 Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 7 Oct 2023 00:16:27 +0800 Subject: [PATCH 2/2] Fix build on linux arm64 and add riscv64 --- native/Makefile | 7 +++++-- native/Makefile.common | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/native/Makefile b/native/Makefile index 46e7eb8c5..4b42b1bbc 100644 --- a/native/Makefile +++ b/native/Makefile @@ -82,8 +82,11 @@ NATIVE_DLL:=$(NATIVE_DIR)/$(LIBNAME) # For cross-compilation, install docker. See also https://github.com/dockcross/dockcross # Disabled linux-armv6 build because of this issue; https://github.com/dockcross/dockcross/issues/190 -native-all: linux-x86 linux-x86_64 linux-arm linux-armv6 linux-armv7 \ - linux-arm64 linux-ppc64 win-x86 win-x86_64 win-arm64 mac-x86 mac-x86_64 mac-arm64 freebsd-x86 freebsd-x86_64 +native-all: \ + linux-x86 linux-x86_64 linux-arm linux-armv6 linux-armv7 linux-arm64 linux-ppc64 linux-riscv64 \ + win-x86 win-x86_64 win-arm64 \ + mac-x86 mac-x86_64 mac-arm64 \ + freebsd-x86 freebsd-x86_64 native: $(NATIVE_DLL) diff --git a/native/Makefile.common b/native/Makefile.common index b4b12e5bd..9c2fc01e3 100644 --- a/native/Makefile.common +++ b/native/Makefile.common @@ -17,7 +17,7 @@ # os=Default is meant to be generic unix/linux -known_targets := Linux-x86 Linux-x86_64 Linux-arm Linux-armv6 Linux-armv7 Linux-android-arm Linux-ppc64 Mac-x86 Mac-x86_64 Mac-arm64 DragonFly-x86_64 FreeBSD-x86_64 OpenBSD-x86_64 Windows-x86 Windows-x86_64 SunOS-sparcv9 HPUX-ia64_32 +known_targets := Linux-x86 Linux-x86_64 Linux-arm Linux-armv6 Linux-armv7 Linux-android-arm Linux-arm64 Linux-ppc64 Linux-riscv64 Mac-x86 Mac-x86_64 Mac-arm64 DragonFly-x86_64 FreeBSD-x86_64 OpenBSD-x86_64 Windows-x86 Windows-x86_64 SunOS-sparcv9 HPUX-ia64_32 target := $(OS_NAME)-$(OS_ARCH) ifeq (,$(findstring $(strip $(target)),$(known_targets))) @@ -65,7 +65,7 @@ Linux-armv7_LIBNAME := libjlinenative.so Linux-arm64_CC := $(CROSS_PREFIX)gcc Linux-arm64_STRIP := $(CROSS_PREFIX)strip -Linux-arm64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -mfloat-abi=hard -mfpu=vfp -fPIC -fvisibility=hidden +Linux-arm64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -march=armv8-a -fPIC -fvisibility=hidden Linux-arm64_LINKFLAGS := -shared -static-libgcc Linux-arm64_LIBNAME := libjlinenative.so @@ -75,6 +75,12 @@ Linux-ppc64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix - Linux-ppc64_LINKFLAGS := -shared -static-libgcc Linux-ppc64_LIBNAME := libjlinenative.so +Linux-riscv64_CC := $(CROSS_PREFIX)gcc +Linux-riscv64_STRIP := $(CROSS_PREFIX)strip +Linux-riscv64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -Os -march=rv64g -fPIC -fvisibility=hidden +Linux-riscv64_LINKFLAGS := -shared -static-libgcc +Linux-riscv64_LIBNAME := libjlinenative.so + DragonFly-x86_64_CC := $(CROSS_PREFIX)cc DragonFly-x86_64_STRIP := $(CROSS_PREFIX)strip DragonFly-x86_64_CCFLAGS := -I$(JAVA_HOME)/include -Itarget/inc -Itarget/inc/unix -O2 -fPIC -fvisibility=hidden