diff --git a/jansi/src/main/java/org/fusesource/jansi/AnsiConsole.java b/jansi/src/main/java/org/fusesource/jansi/AnsiConsole.java index 2e25f3b4..e1baf826 100644 --- a/jansi/src/main/java/org/fusesource/jansi/AnsiConsole.java +++ b/jansi/src/main/java/org/fusesource/jansi/AnsiConsole.java @@ -127,7 +127,7 @@ private static PrintStream ansiSystem(boolean stdout) { // the ansi escapes. if (getBoolean(JANSI_STRIP)) { jansiOutputType = JansiOutputType.STRIP_ANSI; - return new PrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), true); + return new PrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), true); } if (IS_WINDOWS) { @@ -146,7 +146,7 @@ && SetConsoleMode(console, mode[0] | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) { // codes but we can use jansi-native Kernel32 API for console try { jansiOutputType = JansiOutputType.WINDOWS; - return newPrintStream(new AnsiNoSyncOutputStream(out, new WindowsAnsiProcessor(out, stdout)), enc); + return newPrintStream(new AnsiNoSyncOutputStream(out, new WindowsAnsiProcessor(out, stdout), enc), enc); } catch (Throwable ignore) { // this happens when JNA is not in the path.. or // this happens when the stdout is being redirected to a file. @@ -154,7 +154,7 @@ && SetConsoleMode(console, mode[0] | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) { // Use the ANSIOutputStream to strip out the ANSI escape sequences. jansiOutputType = JansiOutputType.STRIP_ANSI; - return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), enc); + return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), enc); } // We must be on some Unix variant or ANSI-enabled ConEmu, Cygwin or MSYS(2) on Windows... @@ -166,7 +166,7 @@ && SetConsoleMode(console, mode[0] | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) { // to strip the ANSI sequences.. if (!forceColored && isatty(stdout ? 1 : 2) == 0) { jansiOutputType = JansiOutputType.STRIP_ANSI; - return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), enc); + return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), enc); } } catch (Throwable ignore) { // These errors happen if the JNI lib is not available for your platform. diff --git a/jansi/src/main/java/org/fusesource/jansi/AnsiNoSyncOutputStream.java b/jansi/src/main/java/org/fusesource/jansi/AnsiNoSyncOutputStream.java index de80ae2e..49584648 100644 --- a/jansi/src/main/java/org/fusesource/jansi/AnsiNoSyncOutputStream.java +++ b/jansi/src/main/java/org/fusesource/jansi/AnsiNoSyncOutputStream.java @@ -18,6 +18,7 @@ import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.charset.Charset; import java.util.ArrayList; /** @@ -62,10 +63,22 @@ public class AnsiNoSyncOutputStream extends FilterOutputStream { private int startOfValue; private final ArrayList options = new ArrayList(); private int state = LOOKING_FOR_FIRST_ESC_CHAR; + private final Charset cs; public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap) { + this(os, ap, Charset.defaultCharset()); + } + + public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap, Charset cs) { + super(os); + this.ap = ap; + this.cs = cs; + } + + public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap, String encoding) { super(os); this.ap = ap; + this.cs = encoding != null ? Charset.forName(encoding) : Charset.defaultCharset(); } /** @@ -138,7 +151,7 @@ public void write(int data) throws IOException { case LOOKING_FOR_STR_ARG_END: buffer[pos++] = (byte) data; if ('"' != data) { - String value = new String(buffer, startOfValue, (pos - 1) - startOfValue); + String value = new String(buffer, startOfValue, (pos - 1) - startOfValue, cs); options.add(value); if (data == ';') { state = LOOKING_FOR_NEXT_ARG; @@ -177,7 +190,7 @@ public void write(int data) throws IOException { case LOOKING_FOR_OSC_PARAM: buffer[pos++] = (byte) data; if (BEL == data) { - String value = new String(buffer, startOfValue, (pos - 1) - startOfValue); + String value = new String(buffer, startOfValue, (pos - 1) - startOfValue, cs); options.add(value); reset(ap.processOperatingSystemCommand(options)); } else if (FIRST_ESC_CHAR == data) { @@ -190,7 +203,7 @@ public void write(int data) throws IOException { case LOOKING_FOR_ST: buffer[pos++] = (byte) data; if (SECOND_ST_CHAR == data) { - String value = new String(buffer, startOfValue, (pos - 2) - startOfValue); + String value = new String(buffer, startOfValue, (pos - 2) - startOfValue, cs); options.add(value); reset(ap.processOperatingSystemCommand(options)); } else { diff --git a/jansi/src/test/java/org/fusesource/jansi/EncodingTest.java b/jansi/src/test/java/org/fusesource/jansi/EncodingTest.java new file mode 100644 index 00000000..92c1cfb8 --- /dev/null +++ b/jansi/src/test/java/org/fusesource/jansi/EncodingTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009-2020 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. + */package org.fusesource.jansi; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.util.concurrent.atomic.AtomicReference; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class EncodingTest { + + @Test + public void testEncoding8859() throws UnsupportedEncodingException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final AtomicReference newLabel = new AtomicReference(); + PrintStream ansi = new PrintStream(new AnsiNoSyncOutputStream(baos, new AnsiProcessor(baos) { + @Override + protected void processChangeWindowTitle(String label) { + newLabel.set(label); + } + }, "ISO-8859-1"), true, "ISO-8859-1"); + + ansi.print("\033]0;un bon café\007"); + ansi.flush(); + assertEquals("un bon café", newLabel.get()); + } + + @Test + public void testEncodingUtf8() throws UnsupportedEncodingException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final AtomicReference newLabel = new AtomicReference(); + PrintStream ansi = new PrintStream(new AnsiNoSyncOutputStream(baos, new AnsiProcessor(baos) { + @Override + protected void processChangeWindowTitle(String label) { + newLabel.set(label); + } + }, "UTF-8"), true, "UTF-8"); + + ansi.print("\033]0;ひらがな\007"); + ansi.flush(); + assertEquals("ひらがな", newLabel.get()); + } + +}