Skip to content

Commit 1a85d58

Browse files
committed
fix: Restore Windows console codepage auto-detection (fixes #1366)
Unicode box-drawing characters have been rendering as garbage on Windows cmd.exe and PowerShell since JLine 3.22.0 (October 2020). Root cause: In commit 5739bab, the getConsoleOutputCP() method was removed, eliminating automatic Windows console codepage detection. JLine defaulted to UTF-8, but Windows consoles often use CP437, CP850, CP936, etc. This fix restores codepage auto-detection: - Added getConsoleCodepage() method that uses reflection to call Kernel32.GetConsoleOutputCP() from JNI or FFM providers - Modified computeEncoding() to auto-detect Windows codepage when: * Running on native Windows (not Cygwin/MSYS) * No explicit codepage is set * Falls back gracefully if native providers aren't available Encoding detection priority (after fix): 1. Explicitly set encoding field 2. System property org.jline.terminal.encoding 3. Explicitly set codepage field 4. System property org.jline.terminal.codepage 5. Auto-detected Windows codepage (NEW) 6. UTF-8 (default fallback)
1 parent 3580251 commit 1a85d58

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

terminal/src/main/java/org/jline/terminal/TerminalBuilder.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,10 @@ public Charset computeEncoding() {
10041004
codepage = Integer.parseInt(str);
10051005
}
10061006
}
1007+
// Auto-detect Windows console codepage if not explicitly set
1008+
if (codepage <= 0 && OSUtils.IS_WINDOWS && !OSUtils.IS_CYGWIN && !OSUtils.IS_MSYSTEM) {
1009+
codepage = getConsoleCodepage();
1010+
}
10071011
if (codepage >= 0) {
10081012
encoding = getCodepageCharset(codepage);
10091013
} else {
@@ -1166,6 +1170,34 @@ private static <S> S load(Class<S> clazz) {
11661170

11671171
private static final int UTF8_CODE_PAGE = 65001;
11681172

1173+
/**
1174+
* Auto-detect the Windows console output codepage using GetConsoleOutputCP().
1175+
* Uses reflection to avoid hard dependency on native provider modules.
1176+
*
1177+
* @return the detected codepage, or -1 if detection fails
1178+
*/
1179+
private static int getConsoleCodepage() {
1180+
try {
1181+
// Try JNI provider's Kernel32 first
1182+
Class<?> kernel32Class = Class.forName("org.jline.nativ.Kernel32");
1183+
java.lang.reflect.Method method = kernel32Class.getMethod("GetConsoleOutputCP");
1184+
return (Integer) method.invoke(null);
1185+
} catch (ClassNotFoundException | NoSuchMethodException e) {
1186+
// JNI provider not available, try FFM provider
1187+
try {
1188+
Class<?> kernel32Class = Class.forName("org.jline.terminal.impl.ffm.Kernel32");
1189+
java.lang.reflect.Method method = kernel32Class.getMethod("GetConsoleOutputCP");
1190+
return (Integer) method.invoke(null);
1191+
} catch (Exception ex) {
1192+
// FFM provider not available either, return -1
1193+
return -1;
1194+
}
1195+
} catch (Exception e) {
1196+
// Reflection failed, return -1
1197+
return -1;
1198+
}
1199+
}
1200+
11691201
private static Charset getCodepageCharset(int codepage) {
11701202
// http://docs.oracle.com/javase/6/docs/technotes/guides/intl/encoding.doc.html
11711203
if (codepage == UTF8_CODE_PAGE) {

0 commit comments

Comments
 (0)