diff options
author | ktamp <ktamp@users.noreply.github.com> | 2020-06-23 23:31:41 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-23 23:31:41 +0300 |
commit | a3b95162499833c17699e0d22c44d3dd09a1ef54 (patch) | |
tree | aa1097c47684ab581e3097a57a6a83e143b232c3 /lib/system | |
parent | 9ebbe000a81b735f0bb8350b0897c9d1b0d1f43f (diff) | |
download | Nim-a3b95162499833c17699e0d22c44d3dd09a1ef54.tar.gz |
readLine: Unicode support for Windows console
When input is read from the Windows console, input encoding is UTF16. This is translated internally to UTF8.
Diffstat (limited to 'lib/system')
-rw-r--r-- | lib/system/io.nim | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/lib/system/io.nim b/lib/system/io.nim index 482057214..330b67dff 100644 --- a/lib/system/io.nim +++ b/lib/system/io.nim @@ -14,6 +14,11 @@ include inclrtl import std/private/since import formatfloat +when defined(windows) and not defined(useWinAnsi): + import os + import system/widestrs + import terminal + # ----------------- IO Part ------------------------------------------------ type CFile {.importc: "FILE", header: "<stdio.h>", @@ -352,6 +357,37 @@ proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect], proc c_memchr(s: pointer, c: cint, n: csize_t): pointer {. importc: "memchr", header: "<string.h>".} + when defined(windows) and not defined(useWinAnsi): + proc readConsole(hConsoleInput: FileHandle, lpBuffer: pointer, + nNumberOfCharsToRead: uint32, + lpNumberOfCharsRead: ptr uint32, + pInputControl: pointer): int32 {. + stdcall, dynlib: "kernel32", importc: "ReadConsoleW".} + + if f.isatty: + if c_feof(f) < 0: + return false + const numberOfCharsToRead = 2048 + var numberOfCharsRead = 0'u32 + var buffer = newWideCString("", numberOfCharsToRead) + if readConsole(getOsFileHandle(f), addr(buffer[0]), + numberOfCharsToRead, addr(numberOfCharsRead), nil) == 0: + var error = osLastError() + raiseEIO("error: " & $error & " `" & osErrorMsg(error) & "`") + # input always ends with "\r\n" + numberOfCharsRead -= 2 + # handle Ctrl+Z as EOF + for i in 0'u32..<numberOfCharsRead: + if buffer[i].uint16 == 26: #Ctrl+Z + close(f) #has the same effect as setting EOF + if i == 0: + return false + numberOfCharsRead = i + break + buffer[numberOfCharsRead] = 0.Utf16Char + line = TaintedString($buffer) + return(true) + var pos = 0 # Use the currently reserved space for a first try |