Skip to content

Commit

Permalink
Fix console output code page and add a BufferedWriter, #133
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Jun 16, 2017
1 parent 8b2de8c commit cc688bd
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ public JansiWinSysTerminal(String name, boolean nativeSignals, SignalHandler sig
name, nativeSignals, signalHandler);
}

@Override
protected int getConsoleOutputCP() {
return Kernel32.GetConsoleOutputCP();
}

@Override
protected void setConsoleOutputCP(int cp) {
Kernel32.SetConsoleOutputCP(cp);
}

@Override
protected int getConsoleMode() {
return WindowsSupport.getConsoleMode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,16 @@ public JnaWinSysTerminal(String name, boolean nativeSignals, SignalHandler signa
strings.put(InfoCmp.Capability.key_mouse, "\\E[M");
}

@Override
protected int getConsoleOutputCP() {
return Kernel32.INSTANCE.GetConsoleOutputCP();
}

@Override
protected void setConsoleOutputCP(int cp) {
Kernel32.INSTANCE.SetConsoleCP(cp);

This comment has been minimized.

Copy link
@stephan-gh

stephan-gh Jun 16, 2017

Contributor

SetConsoleCP sets the input code page, not the output code page. It worked after I added SetConsoleOutputCP to the Kernel32 interface, although I had to omit throws LastErrorException because it always throws an exception for some reason (even though it sets the code page correctly!)

}

@Override
protected int getConsoleMode() {
IntByReference mode = new IntByReference();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.jline.utils.ShutdownHooks;
import org.jline.utils.Signals;

import java.io.BufferedWriter;
import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOError;
Expand All @@ -35,7 +36,8 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {

private static final int PIPE_SIZE = 1024;

private static final Charset INPUT_CHARSET = Charset.forName("UTF-8");
private static final Charset CHARSET = Charset.forName("UTF-8");
private static final int CODE_PAGE = 65001;

protected static final int ENABLE_PROCESSED_INPUT = 0x0001;
protected static final int ENABLE_LINE_INPUT = 0x0002;
Expand All @@ -54,6 +56,7 @@ public abstract class AbstractWindowsTerminal extends AbstractTerminal {
protected final ShutdownHooks.Task closer;
protected final Attributes attributes = new Attributes();
protected final Thread pump;
protected final int consoleOutputCP;

protected MouseTracking tracking = MouseTracking.Off;
private volatile boolean closing;
Expand All @@ -64,12 +67,10 @@ public AbstractWindowsTerminal(OutputStream output, String name, boolean nativeS
this.slaveInputPipe = new PipedOutputStream(input);
this.input = new FilterInputStream(input) {};
this.output = output;
String encoding = getConsoleEncoding();
if (encoding == null) {
encoding = Charset.defaultCharset().name();
}
this.reader = new NonBlockingReader(getName(), new org.jline.utils.InputStreamReader(input, INPUT_CHARSET));
this.writer = new PrintWriter(new OutputStreamWriter(output, encoding));
this.consoleOutputCP = getConsoleOutputCP();
setConsoleOutputCP(CODE_PAGE);
this.reader = new NonBlockingReader(getName(), new org.jline.utils.InputStreamReader(input, CHARSET));
this.writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output, CHARSET)));

This comment has been minimized.

Copy link
@stephan-gh

stephan-gh Jun 16, 2017

Contributor

The BufferedWriter doesn't fix the output problems because the issue is in the AnsiOutputStream (or rather: the FilterOutputStream) which splits up the bytes to filter them. The buffering must be between AnsiOutputStream and FileOutputStream, otherwise it won't work.

This comment has been minimized.

Copy link
@gnodet

gnodet Jun 16, 2017

Author Member

This way ?

this.writer = new PrintWriter(new OutputStreamWriter(new BufferedOutputStream(output), CHARSET));

This comment has been minimized.

Copy link
@stephan-gh

stephan-gh Jun 16, 2017

Contributor

No, you need to do it manually in JnaWinSysTerminal and the JANSI implementation (haven't looked at that but I guess it's the same). It must come after the ANSI output stream:

new WindowsAnsiOutputStream(new BufferedOutputStream(new FileOutputStream(FileDescriptor.out))
parseInfoCmp();
// Attributes
attributes.setLocalFlag(Attributes.LocalFlag.ISIG, true);
Expand Down Expand Up @@ -106,22 +107,6 @@ public SignalHandler handle(Signal signal, SignalHandler handler) {
return prev;
}

protected String getConsoleEncoding() {
int codepage = getConsoleOutputCP();
//http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
String charsetMS = "ms" + codepage;
if (java.nio.charset.Charset.isSupported(charsetMS)) {
return charsetMS;
}
String charsetCP = "cp" + codepage;
if (java.nio.charset.Charset.isSupported(charsetCP)) {
return charsetCP;
}
return null;
}

protected abstract int getConsoleOutputCP();

public NonBlockingReader reader() {
return reader;
}
Expand Down Expand Up @@ -174,10 +159,6 @@ protected int ctrl(char key) {
return (Character.toUpperCase(key) & 0x1f);
}

protected abstract int getConsoleMode();

protected abstract void setConsoleMode(int mode);

public void setSize(Size size) {
throw new UnsupportedOperationException("Can not resize windows terminal");
}
Expand All @@ -191,10 +172,9 @@ public void close() throws IOException {
}
reader.close();
writer.close();
setConsoleOutputCP(consoleOutputCP);
}

protected abstract String readConsoleInput() throws IOException;

protected String getEscapeSequence(short keyCode) {
// virtual keycodes: http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
// TODO: numpad keys, modifiers
Expand Down Expand Up @@ -293,7 +273,7 @@ protected void pump() {
try {
while (!closing) {
String buf = readConsoleInput();
for (byte b : buf.getBytes(INPUT_CHARSET)) {
for (byte b : buf.getBytes(CHARSET)) {
processInputByte(b);
}
}
Expand Down Expand Up @@ -344,5 +324,15 @@ public boolean trackMouse(MouseTracking tracking) {
return true;
}

protected abstract int getConsoleOutputCP();

protected abstract void setConsoleOutputCP(int cp);

protected abstract int getConsoleMode();

protected abstract void setConsoleMode(int mode);

protected abstract String readConsoleInput() throws IOException;

}

0 comments on commit cc688bd

Please sign in to comment.