summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2019-08-18 22:57:56 +0200
committerGitHub <noreply@github.com>2019-08-18 22:57:56 +0200
commit742862b847646dff4562992cd502d3077b2c9474 (patch)
tree8ffdf07aa85b7d593a2450c20425bf91c210ef93
parentac7a3651379f0601f9bbf5b1d613c8d6eb89cf4c (diff)
downloadNim-742862b847646dff4562992cd502d3077b2c9474.tar.gz
more enhancements for #11618 (#11976)
* finish the Windows IO layer changes; refs #11618
* added system.getOsFileHandle which is less error-prone on Windows
* make tests green again
-rw-r--r--changelog.md3
-rw-r--r--lib/system.nim6
-rw-r--r--lib/system/io.nim27
-rw-r--r--tests/system/techo_unicode.nim27
4 files changed, 55 insertions, 8 deletions
diff --git a/changelog.md b/changelog.md
index 3780c270b..41d371b60 100644
--- a/changelog.md
+++ b/changelog.md
@@ -21,6 +21,9 @@
 - `encodings.getCurrentEncoding` now distinguishes between the console's
   encoding and the OS's encoding. This distinction is only meaningful on
   Windows.
+- Added `system.getOsFileHandle` which is usually more useful
+  than `system.getFileHandle`. This distinction is only meaningful on
+  Windows.
 
 ## Library changes
 
diff --git a/lib/system.nim b/lib/system.nim
index d582411d8..7e23b5188 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -4496,12 +4496,6 @@ proc substr*(s: string, first = 0): string =
 when defined(nimconfig):
   include "system/nimscript"
 
-when defined(windows) and appType == "console" and
-    not defined(nimDontSetUtf8CodePage) and not defined(nimscript):
-  proc setConsoleOutputCP(codepage: cint): cint {.stdcall, dynlib: "kernel32",
-    importc: "SetConsoleOutputCP".}
-  discard setConsoleOutputCP(65001) # 65001 - utf-8 codepage
-
 when not defined(js):
   proc toOpenArray*[T](x: ptr UncheckedArray[T]; first, last: int): openArray[T] {.
     magic: "Slice".}
diff --git a/lib/system/io.nim b/lib/system/io.nim
index 7f7df74ba..977e8539a 100644
--- a/lib/system/io.nim
+++ b/lib/system/io.nim
@@ -202,7 +202,7 @@ when defined(windows):
     # But we cannot call printf directly as the string might contain \0.
     # So we have to loop over all the sections separated by potential \0s.
     var i = c_fprintf(f, "%s", s)
-    while i < s.len and false:
+    while i < s.len:
       if s[i] == '\0':
         inc i
       else:
@@ -257,10 +257,23 @@ proc flushFile*(f: File) {.tags: [WriteIOEffect].} =
   discard c_fflush(f)
 
 proc getFileHandle*(f: File): FileHandle =
-  ## returns the OS file handle of the file ``f``. This is only useful for
+  ## returns the file handle of the file ``f``. This is only useful for
   ## platform specific programming.
+  ## Note that on Windows this doesn't return the Windows-specific handle,
+  ## but the C library's notion of a handle, whatever that means.
+  ## Use `getOsFileHandle` instead.
   c_fileno(f)
 
+proc getOsFileHandle*(f: File): FileHandle =
+  ## returns the OS file handle of the file ``f``. This is only useful for
+  ## platform specific programming.
+  when defined(windows):
+    proc getOsfhandle(fd: cint): FileHandle {.
+      importc: "_get_osfhandle", header: "<io.h>".}
+    result = getOsfhandle(getFileHandle(f))
+  else:
+    result = c_fileno(f)
+
 proc readLine*(f: File, line: var TaintedString): bool {.tags: [ReadIOEffect],
               benign.} =
   ## reads a line of text from the file `f` into `line`. May throw an IO
@@ -607,6 +620,16 @@ when defined(windows) and not defined(nimscript):
   c_setmode(c_fileno(stdout), O_BINARY)
   c_setmode(c_fileno(stderr), O_BINARY)
 
+when defined(windows) and appType == "console" and
+    not defined(nimDontSetUtf8CodePage) and not defined(nimscript):
+  proc setConsoleOutputCP(codepage: cuint): int32 {.stdcall, dynlib: "kernel32",
+    importc: "SetConsoleOutputCP".}
+  proc setConsoleCP(wCodePageID: cuint): int32 {.stdcall, dynlib: "kernel32",
+    importc: "SetConsoleCP".}
+
+  const Utf8codepage = 65001
+  discard setConsoleOutputCP(Utf8codepage)
+  discard setConsoleCP(Utf8codepage)
 
 proc readFile*(filename: string): TaintedString {.tags: [ReadIOEffect], benign.} =
   ## Opens a file named `filename` for reading, calls `readAll
diff --git a/tests/system/techo_unicode.nim b/tests/system/techo_unicode.nim
new file mode 100644
index 000000000..d0395224b
--- /dev/null
+++ b/tests/system/techo_unicode.nim
@@ -0,0 +1,27 @@
+discard """
+  output: '''ÄhmÖÜ
+abasdfdsmÄhmaИ
+Иnastystring
+A你好
+ИnastystringA你好
+ÖÜhmabasdfdsmÄhmaИ'''
+  disabled: "posix"
+  joinable: "false"
+"""
+
+import winlean
+
+echo "ÄhmÖÜ"
+echo "abasdfdsmÄhmaИ"
+echo "И\0nasty\0\0\0\0string\0"
+echo "A你好"
+
+write stdout, "И\0nasty\0\0\0\0string\0"
+writeLine stdout, "A你好"
+stdout.flushFile()
+
+let handle = getOsFileHandle(stdout)
+var a = "ÖÜhmabasdfdsmÄhmaИ"
+var ac = 0'i32
+discard writeFile(handle, addr a[0], int32(len(a)), addr ac, nil)
+stdout.flushFile()