summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2016-06-28 18:55:59 +0200
committerGitHub <noreply@github.com>2016-06-28 18:55:59 +0200
commitf7f0cff8b3544694593d36f880d24f7e9f87593f (patch)
treeb0f5e1adad463c7732737a682053fd3b1e2c62e0 /lib
parent38de553b86fd5f42c726da9bceb6828fb835eff5 (diff)
parent8314412b99fbb101d44cee62a091c0a8e5f84089 (diff)
downloadNim-f7f0cff8b3544694593d36f880d24f7e9f87593f.tar.gz
Merge pull request #4403 from miere43/win-getch
Implemented terminal.getch() for Windows
Diffstat (limited to 'lib')
-rw-r--r--lib/pure/terminal.nim26
-rw-r--r--lib/windows/winlean.nim21
2 files changed, 35 insertions, 12 deletions
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index 60f064e7c..c135f6a00 100644
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -493,17 +493,21 @@ template styledEcho*(args: varargs[expr]): expr =
   ## Echoes styles arguments to stdout using ``styledWriteLine``.
   callStyledEcho(args)
 
-when defined(nimdoc):
-  proc getch*(): char =
-    ## Read a single character from the terminal, blocking until it is entered.
-    ## The character is not printed to the terminal. This is not available for
-    ## Windows.
-    discard
-elif not defined(windows):
-  proc getch*(): char =
-    ## Read a single character from the terminal, blocking until it is entered.
-    ## The character is not printed to the terminal. This is not available for
-    ## Windows.
+proc getch*(): char =
+  ## Read a single character from the terminal, blocking until it is entered.
+  ## The character is not printed to the terminal.
+  when defined(windows):
+    let fd = getStdHandle(STD_INPUT_HANDLE)
+    var keyEvent = KEY_EVENT_RECORD()
+    var numRead: cint 
+    while true:
+      # Block until character is entered
+      doAssert(waitForSingleObject(fd, INFINITE) == WAIT_OBJECT_0)
+      doAssert(readConsoleInput(fd, addr(keyEvent), 1, addr(numRead)) != 0)
+      if numRead == 0 or keyEvent.eventType != 1 or keyEvent.bKeyDown == 0:
+        continue
+      return char(keyEvent.uChar)
+  else:
     let fd = getFileHandle(stdin)
     var oldMode: Termios
     discard fd.tcgetattr(addr oldMode)
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 04edeb2cb..c9b4b610c 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -1016,4 +1016,23 @@ proc wsaCloseEvent*(hEvent: Handle): bool
      {.stdcall, importc: "WSACloseEvent", dynlib: "ws2_32.dll".}
 
 proc wsaResetEvent*(hEvent: Handle): bool
-     {.stdcall, importc: "WSAResetEvent", dynlib: "ws2_32.dll".}
\ No newline at end of file
+     {.stdcall, importc: "WSAResetEvent", dynlib: "ws2_32.dll".}
+
+type
+  KEY_EVENT_RECORD* {.final, pure.} = object
+    eventType*: int16
+    bKeyDown*: WINBOOL
+    wRepeatCount*: int16
+    wVirtualKeyCode*: int16
+    wVirtualScanCode*: int16
+    uChar*: int16
+    dwControlKeyState*: DWORD
+
+when defined(useWinAnsi):
+  proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
+                        lpNumberOfEventsRead: ptr cint): cint
+       {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputA".}
+else:
+  proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
+                        lpNumberOfEventsRead: ptr cint): cint
+       {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
\ No newline at end of file