Skip to content

Commit

Permalink
Fix restoration of Terminal at close, fixes #819
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Mar 6, 2023
1 parent 0b97167 commit caa2d14
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ private String computeGroupPost(List<Candidate> c, boolean autoGroup, boolean gr
public void testConEmuLineReaderClearScreen() throws IOException {
System.setProperty("org.jline.terminal.conemu.disable-activate", "false");
StringWriter sw = new StringWriter();
AbstractWindowsTerminal terminal = new AbstractWindowsTerminal(new BufferedWriter(sw), "name", TYPE_WINDOWS_CONEMU, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL) {
AbstractWindowsTerminal<?> terminal = new AbstractWindowsTerminal<Object>(new BufferedWriter(sw), "name", TYPE_WINDOWS_CONEMU, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL, null, null) {
@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}

@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,21 +78,21 @@ private void process(TestTerminal terminal, int c) {
}
}

private static class TestTerminal extends AbstractWindowsTerminal {
private static class TestTerminal extends AbstractWindowsTerminal<Object> {
public TestTerminal(StringWriter sw) throws IOException {
super(new AnsiWriter(new BufferedWriter(sw)), "name",
AbstractWindowsTerminal.TYPE_DUMB,
Charset.defaultCharset(),
false, SignalHandler.SIG_DFL);
false, SignalHandler.SIG_DFL, null, null);
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}

@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import static org.fusesource.jansi.internal.Kernel32.WaitForSingleObject;
import static org.fusesource.jansi.internal.Kernel32.readConsoleInputHelper;

public class JansiWinSysTerminal extends AbstractWindowsTerminal {
public class JansiWinSysTerminal extends AbstractWindowsTerminal<Long> {

private static final long consoleIn = GetStdHandle(STD_INPUT_HANDLE);
private static final long consoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -115,18 +115,13 @@ public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
return Kernel32.GetConsoleMode(console, mode) != 0;
}

private long console;
private long outputHandle;

JansiWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
long console, long outputHandle) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler);
this.console = console;
this.outputHandle = outputHandle;
long inConsole, long outConsole) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler, inConsole, outConsole);
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Long console) {
int[] mode = new int[1];
if (Kernel32.GetConsoleMode(console, mode) == 0) {
return -1;
Expand All @@ -135,28 +130,28 @@ protected int getConsoleMode() {
}

@Override
protected void setConsoleMode(int mode) {
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(outputHandle, 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(outputHandle, info);
Kernel32.GetConsoleScreenBufferInfo(outConsole, info);
return new Size(info.size.x, info.size.y);
}

protected boolean processConsoleInput() throws IOException {
INPUT_RECORD[] events;
if (console != INVALID_HANDLE_VALUE
&& WaitForSingleObject(console, 100) == 0) {
events = readConsoleInputHelper(console, 1, false);
if (inConsole != INVALID_HANDLE_VALUE
&& WaitForSingleObject(inConsole, 100) == 0) {
events = readConsoleInputHelper(inConsole, 1, false);
} else {
return false;
}
Expand Down Expand Up @@ -228,7 +223,7 @@ private void processMouseEvent(Kernel32.MOUSE_EVENT_RECORD mouseEvent) throws IO
@Override
public Cursor getCursorPosition(IntConsumer discarded) {
CONSOLE_SCREEN_BUFFER_INFO info = new CONSOLE_SCREEN_BUFFER_INFO();
if (GetConsoleScreenBufferInfo(outputHandle, info) == 0) {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
import org.jline.terminal.Size;
import org.jline.terminal.impl.AbstractWindowsTerminal;
import org.jline.terminal.spi.TerminalProvider;
import org.jline.utils.InfoCmp;
import org.jline.utils.InfoCmp.Capability;
import org.jline.utils.OSUtils;

public class JnaWinSysTerminal extends AbstractWindowsTerminal {
public class JnaWinSysTerminal extends AbstractWindowsTerminal<Pointer> {

private static final Pointer consoleIn = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_INPUT_HANDLE);
private static final Pointer consoleOut = Kernel32.INSTANCE.GetStdHandle(Kernel32.STD_OUTPUT_HANDLE);
Expand Down Expand Up @@ -71,7 +71,7 @@ public static JnaWinSysTerminal createTerminal(String name, String type, boolean
}
}
}
JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler);
JnaWinSysTerminal terminal = new JnaWinSysTerminal(writer, name, type, encoding, nativeSignals, signalHandler, JnaWinSysTerminal.consoleIn, console);
// Start input pump thread
if (!paused) {
terminal.resume();
Expand All @@ -96,26 +96,27 @@ public static boolean isWindowsSystemStream(TerminalProvider.Stream stream) {
}
}

JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler);
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
JnaWinSysTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
Pointer inConsole, Pointer outConsole) throws IOException {
super(writer, name, type, encoding, nativeSignals, signalHandler, inConsole, outConsole);
this.strings.put(Capability.key_mouse, "\\E[M");
}

@Override
protected int getConsoleMode() {
protected int getConsoleMode(Pointer console) {
IntByReference mode = new IntByReference();
Kernel32.INSTANCE.GetConsoleMode(consoleIn, mode);
Kernel32.INSTANCE.GetConsoleMode(console, mode);
return mode.getValue();
}

@Override
protected void setConsoleMode(int mode) {
Kernel32.INSTANCE.SetConsoleMode(consoleIn, mode);
protected void setConsoleMode(Pointer console, int mode) {
Kernel32.INSTANCE.SetConsoleMode(console, mode);
}

public Size getSize() {
Kernel32.CONSOLE_SCREEN_BUFFER_INFO info = new Kernel32.CONSOLE_SCREEN_BUFFER_INFO();
Kernel32.INSTANCE.GetConsoleScreenBufferInfo(consoleOut, info);
Kernel32.INSTANCE.GetConsoleScreenBufferInfo(outConsole, info);
return new Size(info.windowWidth(), info.windowHeight());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import java.io.PrintWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

Expand All @@ -43,7 +42,7 @@
* the writer() becomes the primary output, while the output() is bridged
* to the writer() using a WriterOutputStream wrapper.
*/
public abstract class AbstractWindowsTerminal extends AbstractTerminal {
public abstract class AbstractWindowsTerminal<Console> extends AbstractTerminal {

public static final String TYPE_WINDOWS = "windows";
public static final String TYPE_WINDOWS_256_COLOR = "windows-256color";
Expand All @@ -70,7 +69,10 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected final Map<Signal, Object> nativeHandlers = new HashMap<>();
protected final ShutdownHooks.Task closer;
protected final Attributes attributes = new Attributes();
protected final int originalConsoleMode;
protected final Console inConsole;
protected final Console outConsole;
protected final int originalInConsoleMode;
protected final int originalOutConsoleMode;

protected final Object lock = new Object();
protected boolean paused = true;
Expand All @@ -80,17 +82,21 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected boolean focusTracking = false;
private volatile boolean closing;

public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler) throws IOException {
public AbstractWindowsTerminal(Writer writer, String name, String type, Charset encoding, boolean nativeSignals, SignalHandler signalHandler,
Console inConsole, Console outConsole) throws IOException {
super(name, type, encoding, signalHandler);
NonBlockingPumpReader reader = NonBlocking.nonBlockingPumpReader();
this.slaveInputPipe = reader.getWriter();
this.reader = reader;
this.input = NonBlocking.nonBlockingStream(reader, encoding());
this.writer = new PrintWriter(writer);
this.output = new WriterOutputStream(writer, encoding());
this.inConsole = inConsole;
this.outConsole = outConsole;
parseInfoCmp();
// Attributes
originalConsoleMode = getConsoleMode();
this.originalInConsoleMode = getConsoleMode(inConsole);
this.originalOutConsoleMode = getConsoleMode(outConsole);
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
attributes.setControlChar(Attributes.ControlChar.VINTR, ctrl('C'));
attributes.setControlChar(Attributes.ControlChar.VEOF, ctrl('D'));
Expand Down Expand Up @@ -147,7 +153,7 @@ public OutputStream output() {
}

public Attributes getAttributes() {
int mode = getConsoleMode();
int mode = getConsoleMode(inConsole);
if ((mode & ENABLE_ECHO_INPUT) != 0) {
attributes.setLocalFlag(Attributes.LocalFlag.ECHO, true);
}
Expand All @@ -173,7 +179,7 @@ protected void updateConsoleMode() {
if (tracking != MouseTracking.Off) {
mode |= ENABLE_MOUSE_INPUT;
}
setConsoleMode(mode);
setConsoleMode(inConsole, mode);
}

protected int ctrl(char key) {
Expand All @@ -196,7 +202,8 @@ protected void doClose() throws IOException {
}
reader.close();
writer.close();
setConsoleMode(originalConsoleMode);
setConsoleMode(inConsole, originalInConsoleMode);
setConsoleMode(outConsole, originalOutConsoleMode);
}

static final int SHIFT_FLAG = 0x01;
Expand Down Expand Up @@ -487,9 +494,9 @@ public boolean trackMouse(MouseTracking tracking) {
return true;
}

protected abstract int getConsoleMode();
protected abstract int getConsoleMode(Console console);

protected abstract void setConsoleMode(int mode);
protected abstract void setConsoleMode(Console console, int mode);

/**
* Read a single input event from the input buffer and process it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ public class AbstractWindowsTerminalTest {
public void testWriterBuffering() throws Exception {
System.setProperty("org.jline.terminal.conemu.disable-activate", "true");
StringWriter sw = new StringWriter();
Terminal terminal = new AbstractWindowsTerminal(new AnsiWriter(new BufferedWriter(sw)), "name", TYPE_WINDOWS, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL) {
Terminal terminal = new AbstractWindowsTerminal<Object>(new AnsiWriter(new BufferedWriter(sw)), "name", TYPE_WINDOWS, Charset.defaultCharset(),
false, Terminal.SignalHandler.SIG_DFL, null, null) {
@Override
protected int getConsoleMode() {
protected int getConsoleMode(Object console) {
return 0;
}
@Override
protected void setConsoleMode(int mode) {
protected void setConsoleMode(Object console, int mode) {
}
@Override
protected boolean processConsoleInput() throws IOException {
Expand Down

0 comments on commit caa2d14

Please sign in to comment.