Skip to content

Commit

Permalink
Adding an extra library for native integration with Windows, which is…
Browse files Browse the repository at this point in the history
… required to make it work with cmd.exe
  • Loading branch information
mabe02 committed Mar 27, 2016
1 parent f809681 commit a5506b6
Show file tree
Hide file tree
Showing 6 changed files with 247 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
.idea/
nb-configuration.xml
target/
/lanterna.iml
*.iml
27 changes: 27 additions & 0 deletions native-integration/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.lanterna</groupId>
<artifactId>lanterna-native-integration</artifactId>
<version>3.0.0-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>com.googlecode.lanterna</groupId>
<artifactId>lanterna</artifactId>
<version>3.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.2.2</version>
</dependency>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna-platform</artifactId>
<version>4.2.2</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.googlecode.lanterna.terminal;

import com.sun.jna.Structure;
import com.sun.jna.platform.win32.WinDef;

import java.util.Arrays;
import java.util.List;

/**
* Created by Martin on 2016-03-27.
*/
public class WinDefEx {
public static class COORD extends Structure {
public short X;
public short Y;

@Override
protected List getFieldOrder() {
return Arrays.asList("X", "Y");
}

@Override
public String toString() {
return "COORD{" +
"X=" + X +
", Y=" + Y +
'}';
}
}

public static class SMALL_RECT extends Structure {
public short Left;
public short Top;
public short Right;
public short Bottom;

@Override
protected List getFieldOrder() {
return Arrays.asList("Left", "Top", "Right", "Bottom");
}

@Override
public String toString() {
return "SMALL_RECT{" +
"Left=" + Left +
", Top=" + Top +
", Right=" + Right +
", Bottom=" + Bottom +
'}';
}
}

public static class CONSOLE_SCREEN_BUFFER_INFO extends Structure {
public COORD dwSize;
public COORD dwCursorPosition;
public WinDef.WORD wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;

protected List getFieldOrder() {
return Arrays.asList(new String[] {
"dwSize", "dwCursorPosition", "wAttributes", "srWindow", "dwMaximumWindowSize"
});
}

@Override
public String toString() {
return "CONSOLE_SCREEN_BUFFER_INFO{" +
"dwSize=" + dwSize +
", dwCursorPosition=" + dwCursorPosition +
", wAttributes=" + wAttributes +
", srWindow=" + srWindow +
", dwMaximumWindowSize=" + dwMaximumWindowSize +
'}';
}
}

private WinDefEx() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.googlecode.lanterna.terminal;

import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.StdCallLibrary;

/**
* Created by Martin on 2016-03-27.
*/
interface WinconEx extends StdCallLibrary {
boolean GetConsoleScreenBufferInfo(WinNT.HANDLE hConsoleOutput, WinDefEx.CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.googlecode.lanterna.terminal;

import com.googlecode.lanterna.terminal.ansi.TerminalDeviceControlStrategy;
import com.googlecode.lanterna.terminal.ansi.UnixLikeTerminal;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;

/**
* Created by Martin on 2016-03-27.
*/
public class WindowsTerminal extends UnixLikeTerminal {

public WindowsTerminal() throws IOException {
this(System.in, System.out, Charset.defaultCharset(), CtrlCBehaviour.CTRL_C_KILLS_APPLICATION);
}

public WindowsTerminal(
InputStream terminalInput,
OutputStream terminalOutput,
Charset terminalCharset,
CtrlCBehaviour terminalCtrlCBehaviour) throws IOException {

super(new WindowsTerminalDeviceController(),
terminalInput,
terminalOutput,
terminalCharset,
terminalCtrlCBehaviour);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package com.googlecode.lanterna.terminal;

import com.googlecode.lanterna.TerminalSize;
import com.googlecode.lanterna.terminal.ansi.TerminalDeviceControlStrategy;
import com.sun.jna.Native;
import com.sun.jna.platform.win32.Kernel32;
import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.platform.win32.Wincon;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.win32.W32APIOptions;

import java.io.IOException;

/**
* Created by Martin on 2016-03-27.
*/
public class WindowsTerminalDeviceController implements TerminalDeviceControlStrategy {

private final Wincon windowsConsole;
private final WinconEx extendedConsole;
private final WinNT.HANDLE consoleInputHandle;
private final WinNT.HANDLE consoleOutputHandle;

private Integer savedTerminalMode;

public WindowsTerminalDeviceController() {
this.windowsConsole = Kernel32.INSTANCE;
this.extendedConsole = (WinconEx)Native.loadLibrary("kernel32", WinconEx.class, W32APIOptions.UNICODE_OPTIONS);
this.consoleInputHandle = windowsConsole.GetStdHandle(Wincon.STD_INPUT_HANDLE);
this.consoleOutputHandle = windowsConsole.GetStdHandle(Wincon.STD_OUTPUT_HANDLE);
this.savedTerminalMode = null;
}

@Override
public synchronized void saveTerminalSettings() throws IOException {
this.savedTerminalMode = getConsoleMode();
}

@Override
public synchronized void restoreTerminalSettings() throws IOException {
if(savedTerminalMode != null) {
windowsConsole.SetConsoleMode(consoleInputHandle, savedTerminalMode);
}
}

@Override
public synchronized void keyEchoEnabled(boolean enabled) throws IOException {
int mode = getConsoleMode();
if(enabled) {
mode |= Wincon.ENABLE_ECHO_INPUT;
}
else {
mode &= ~Wincon.ENABLE_ECHO_INPUT;
}
windowsConsole.SetConsoleMode(consoleInputHandle, mode);
}

@Override
public synchronized void canonicalMode(boolean enabled) throws IOException {
int mode = getConsoleMode();
if(enabled) {
mode |= Wincon.ENABLE_LINE_INPUT;
}
else {
mode &= ~Wincon.ENABLE_LINE_INPUT;
}
windowsConsole.SetConsoleMode(consoleInputHandle, mode);
}

@Override
public synchronized void keyStrokeSignalsEnabled(boolean enabled) throws IOException {
int mode = getConsoleMode();
if(enabled) {
mode |= Wincon.ENABLE_PROCESSED_INPUT;
}
else {
mode &= ~Wincon.ENABLE_PROCESSED_INPUT;
}
windowsConsole.SetConsoleMode(consoleInputHandle, mode);
}

@Override
public synchronized TerminalSize getTerminalSize() throws IOException {
WinDefEx.CONSOLE_SCREEN_BUFFER_INFO screenBufferInfo = new WinDefEx.CONSOLE_SCREEN_BUFFER_INFO();
extendedConsole.GetConsoleScreenBufferInfo(consoleOutputHandle, screenBufferInfo);
int columns = screenBufferInfo.srWindow.Right - screenBufferInfo.srWindow.Left + 1;
int rows = screenBufferInfo.srWindow.Bottom - screenBufferInfo.srWindow.Top + 1;
return new TerminalSize(columns, rows);
}

private int getConsoleMode() {
IntByReference lpMode = new IntByReference();
windowsConsole.GetConsoleMode(consoleInputHandle, lpMode);
return lpMode.getValue();
}
}

0 comments on commit a5506b6

Please sign in to comment.