Skip to content
Browse files

support auf UTF-8 in Windows

  • Loading branch information...
1 parent d66fb67 commit e3b38a789a5aad0cb5082d948bbe4bd5fe5806d6 avedusav committed Jan 22, 2008
Showing with 102 additions and 8 deletions.
  1. +6 −4 src/main/java/jline/ConsoleReader.java
  2. +96 −4 src/main/java/jline/WindowsTerminal.java
View
10 src/main/java/jline/ConsoleReader.java
@@ -149,6 +149,7 @@
private Map triggeredActions = new HashMap();
+
/**
* Adding a triggered Action allows to give another curse of action
* if a character passed the preprocessing.
@@ -169,9 +170,11 @@ public void addTriggeredAction(char c, ActionListener listener){
* {@link System#out} for output. {@link FileDescriptor#in} is used because
* it has a better chance of being unbuffered.
*/
- public ConsoleReader() throws IOException {
- this(new FileInputStream(FileDescriptor.in),
- new PrintWriter(System.out));
+ public ConsoleReader() throws IOException {
+ this(new FileInputStream(FileDescriptor.in),
+ new PrintWriter(
+ new OutputStreamWriter(System.out,
+ System.getProperty("jline.WindowsTerminal.output.encoding",System.getProperty("file.encoding")))));
}
/**
@@ -205,7 +208,6 @@ public ConsoleReader(InputStream in, Writer out, InputStream bindings,
this.terminal = term;
setInput(in);
this.out = out;
-
if (bindings == null) {
try {
String bindingFile = System.getProperty("jline.keybindings",
View
100 src/main/java/jline/WindowsTerminal.java
@@ -8,6 +8,8 @@
import java.io.*;
+import jline.UnixTerminal.ReplayPrefixOneCharInputStream;
+
/**
* <p>
* Terminal implementation for Microsoft Windows. Terminal initialization in
@@ -186,7 +188,11 @@
private Boolean directConsole;
private boolean echoEnabled;
-
+
+ String encoding = System.getProperty("jline.WindowsTerminal.input.encoding", System.getProperty("file.encoding"));
+ ReplayPrefixOneCharInputStream replayStream = new ReplayPrefixOneCharInputStream(encoding);
+ InputStreamReader replayReader;
+
public WindowsTerminal() {
String dir = System.getProperty("jline.WindowsTerminal.directConsole");
@@ -195,6 +201,13 @@ public WindowsTerminal() {
} else if ("false".equals(dir)) {
directConsole = Boolean.FALSE;
}
+
+ try {
+ replayReader = new InputStreamReader(replayStream, encoding);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
}
private native int getConsoleMode();
@@ -338,10 +351,18 @@ public int readVirtualKey(InputStream in) throws IOException {
default:
return 0;
}
- } else {
- return indicator;
+ } else if (indicator > 128) {
+ // handle unicode characters longer than 2 bytes,
+ // thanks to Marc.Herbert@continuent.com
+ replayStream.setInput(indicator, in);
+ // replayReader = new InputStreamReader(replayStream, encoding);
+ indicator = replayReader.read();
+
}
- }
+
+ return indicator;
+
+ }
public boolean isSupported() {
return true;
@@ -418,4 +439,75 @@ public synchronized void disableEcho() {
public InputStream getDefaultBindings() {
return getClass().getResourceAsStream("windowsbindings.properties");
}
+
+ /**
+ * This is awkward and inefficient, but probably the minimal way to add
+ * UTF-8 support to JLine
+ *
+ * @author <a href="mailto:Marc.Herbert@continuent.com">Marc Herbert</a>
+ */
+ static class ReplayPrefixOneCharInputStream extends InputStream {
+ byte firstByte;
+ int byteLength;
+ InputStream wrappedStream;
+ int byteRead;
+
+ final String encoding;
+
+ public ReplayPrefixOneCharInputStream(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public void setInput(int recorded, InputStream wrapped) throws IOException {
+ this.byteRead = 0;
+ this.firstByte = (byte) recorded;
+ this.wrappedStream = wrapped;
+
+ byteLength = 1;
+ if (encoding.equalsIgnoreCase("UTF-8"))
+ setInputUTF8(recorded, wrapped);
+ else if (encoding.equalsIgnoreCase("UTF-16"))
+ byteLength = 2;
+ else if (encoding.equalsIgnoreCase("UTF-32"))
+ byteLength = 4;
+ }
+
+
+ public void setInputUTF8(int recorded, InputStream wrapped) throws IOException {
+ // 110yyyyy 10zzzzzz
+ if ((firstByte & (byte) 0xE0) == (byte) 0xC0)
+ this.byteLength = 2;
+ // 1110xxxx 10yyyyyy 10zzzzzz
+ else if ((firstByte & (byte) 0xF0) == (byte) 0xE0)
+ this.byteLength = 3;
+ // 11110www 10xxxxxx 10yyyyyy 10zzzzzz
+ else if ((firstByte & (byte) 0xF8) == (byte) 0xF0)
+ this.byteLength = 4;
+ else
+ throw new IOException("invalid UTF-8 first byte: " + firstByte);
+ }
+
+ public int read() throws IOException {
+ if (available() == 0)
+ return -1;
+
+ byteRead++;
+
+ if (byteRead == 1)
+ return firstByte;
+
+ return wrappedStream.read();
+ }
+
+ /**
+ * InputStreamReader is greedy and will try to read bytes in advance. We
+ * do NOT want this to happen since we use a temporary/"losing bytes"
+ * InputStreamReader above, that's why we hide the real
+ * wrappedStream.available() here.
+ */
+ public int available() {
+ return byteLength - byteRead;
+ }
+ }
+
}

0 comments on commit e3b38a7

Please sign in to comment.
Something went wrong with that request. Please try again.