Signed-off-by: John Gossman <johngos@microsoft.com>
| 1 | 1 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,87 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package term |
|
| 3 |
+ |
|
| 4 |
+import ( |
|
| 5 |
+ "syscall" |
|
| 6 |
+ "unsafe" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+const ( |
|
| 10 |
+ // Consts for Get/SetConsoleMode function |
|
| 11 |
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683167(v=vs.85).aspx |
|
| 12 |
+ ENABLE_ECHO_INPUT = 0x0004 |
|
| 13 |
+ ENABLE_INSERT_MODE = 0x0020 |
|
| 14 |
+ ENABLE_LINE_INPUT = 0x0002 |
|
| 15 |
+ ENABLE_MOUSE_INPUT = 0x0010 |
|
| 16 |
+ ENABLE_PROCESSED_INPUT = 0x0001 |
|
| 17 |
+ ENABLE_QUICK_EDIT_MODE = 0x0040 |
|
| 18 |
+ ENABLE_WINDOW_INPUT = 0x0008 |
|
| 19 |
+ // If parameter is a screen buffer handle, additional values |
|
| 20 |
+ ENABLE_PROCESSED_OUTPUT = 0x0001 |
|
| 21 |
+ ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002 |
|
| 22 |
+) |
|
| 23 |
+ |
|
| 24 |
+var kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
|
|
| 25 |
+ |
|
| 26 |
+var ( |
|
| 27 |
+ setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
|
|
| 28 |
+ getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
|
|
| 29 |
+) |
|
| 30 |
+ |
|
| 31 |
+func GetConsoleMode(fileDesc uintptr) (uint32, error) {
|
|
| 32 |
+ var mode uint32 |
|
| 33 |
+ err := syscall.GetConsoleMode(syscall.Handle(fileDesc), &mode) |
|
| 34 |
+ return mode, err |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func SetConsoleMode(fileDesc uintptr, mode uint32) error {
|
|
| 38 |
+ r, _, err := setConsoleModeProc.Call(fileDesc, uintptr(mode), 0) |
|
| 39 |
+ if r == 0 {
|
|
| 40 |
+ if err != nil {
|
|
| 41 |
+ return err |
|
| 42 |
+ } |
|
| 43 |
+ return syscall.EINVAL |
|
| 44 |
+ } |
|
| 45 |
+ return nil |
|
| 46 |
+} |
|
| 47 |
+ |
|
| 48 |
+// types for calling GetConsoleScreenBufferInfo |
|
| 49 |
+// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms682093(v=vs.85).aspx |
|
| 50 |
+type ( |
|
| 51 |
+ SHORT int16 |
|
| 52 |
+ |
|
| 53 |
+ SMALL_RECT struct {
|
|
| 54 |
+ Left SHORT |
|
| 55 |
+ Top SHORT |
|
| 56 |
+ Right SHORT |
|
| 57 |
+ Bottom SHORT |
|
| 58 |
+ } |
|
| 59 |
+ |
|
| 60 |
+ COORD struct {
|
|
| 61 |
+ X SHORT |
|
| 62 |
+ Y SHORT |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ WORD uint16 |
|
| 66 |
+ |
|
| 67 |
+ CONSOLE_SCREEN_BUFFER_INFO struct {
|
|
| 68 |
+ dwSize COORD |
|
| 69 |
+ dwCursorPosition COORD |
|
| 70 |
+ wAttributes WORD |
|
| 71 |
+ srWindow SMALL_RECT |
|
| 72 |
+ dwMaximumWindowSize COORD |
|
| 73 |
+ } |
|
| 74 |
+) |
|
| 75 |
+ |
|
| 76 |
+func GetConsoleScreenBufferInfo(fileDesc uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
|
|
| 77 |
+ var info CONSOLE_SCREEN_BUFFER_INFO |
|
| 78 |
+ r, _, err := getConsoleScreenBufferInfoProc.Call(uintptr(fileDesc), uintptr(unsafe.Pointer(&info)), 0) |
|
| 79 |
+ if r == 0 {
|
|
| 80 |
+ if err != nil {
|
|
| 81 |
+ return nil, err |
|
| 82 |
+ } |
|
| 83 |
+ return nil, syscall.EINVAL |
|
| 84 |
+ } |
|
| 85 |
+ return &info, nil |
|
| 86 |
+} |
| 4 | 6 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,89 @@ |
| 0 |
+// +build windows |
|
| 1 |
+ |
|
| 2 |
+package term |
|
| 3 |
+ |
|
| 4 |
+type State struct {
|
|
| 5 |
+ mode uint32 |
|
| 6 |
+} |
|
| 7 |
+ |
|
| 8 |
+type Winsize struct {
|
|
| 9 |
+ Height uint16 |
|
| 10 |
+ Width uint16 |
|
| 11 |
+ x uint16 |
|
| 12 |
+ y uint16 |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+func GetWinsize(fd uintptr) (*Winsize, error) {
|
|
| 16 |
+ ws := &Winsize{}
|
|
| 17 |
+ var info *CONSOLE_SCREEN_BUFFER_INFO |
|
| 18 |
+ info, err := GetConsoleScreenBufferInfo(fd) |
|
| 19 |
+ if err != nil {
|
|
| 20 |
+ return nil, err |
|
| 21 |
+ } |
|
| 22 |
+ ws.Height = uint16(info.srWindow.Right - info.srWindow.Left + 1) |
|
| 23 |
+ ws.Width = uint16(info.srWindow.Bottom - info.srWindow.Top + 1) |
|
| 24 |
+ |
|
| 25 |
+ ws.x = 0 // todo azlinux -- this is the pixel size of the Window, and not currently used by any caller |
|
| 26 |
+ ws.y = 0 |
|
| 27 |
+ |
|
| 28 |
+ return ws, nil |
|
| 29 |
+} |
|
| 30 |
+ |
|
| 31 |
+func SetWinsize(fd uintptr, ws *Winsize) error {
|
|
| 32 |
+ return nil |
|
| 33 |
+} |
|
| 34 |
+ |
|
| 35 |
+// IsTerminal returns true if the given file descriptor is a terminal. |
|
| 36 |
+func IsTerminal(fd uintptr) bool {
|
|
| 37 |
+ _, e := GetConsoleMode(fd) |
|
| 38 |
+ return e == nil |
|
| 39 |
+} |
|
| 40 |
+ |
|
| 41 |
+// Restore restores the terminal connected to the given file descriptor to a |
|
| 42 |
+// previous state. |
|
| 43 |
+func RestoreTerminal(fd uintptr, state *State) error {
|
|
| 44 |
+ return SetConsoleMode(fd, state.mode) |
|
| 45 |
+} |
|
| 46 |
+ |
|
| 47 |
+func SaveState(fd uintptr) (*State, error) {
|
|
| 48 |
+ mode, e := GetConsoleMode(fd) |
|
| 49 |
+ if e != nil {
|
|
| 50 |
+ return nil, e |
|
| 51 |
+ } |
|
| 52 |
+ return &State{mode}, nil
|
|
| 53 |
+} |
|
| 54 |
+ |
|
| 55 |
+// see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings |
|
| 56 |
+func DisableEcho(fd uintptr, state *State) error {
|
|
| 57 |
+ state.mode &^= (ENABLE_ECHO_INPUT) |
|
| 58 |
+ state.mode |= (ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) |
|
| 59 |
+ return SetConsoleMode(fd, state.mode) |
|
| 60 |
+} |
|
| 61 |
+ |
|
| 62 |
+func SetRawTerminal(fd uintptr) (*State, error) {
|
|
| 63 |
+ oldState, err := MakeRaw(fd) |
|
| 64 |
+ if err != nil {
|
|
| 65 |
+ return nil, err |
|
| 66 |
+ } |
|
| 67 |
+ // TODO (azlinux): implement handling interrupt and restore state of terminal |
|
| 68 |
+ return oldState, err |
|
| 69 |
+} |
|
| 70 |
+ |
|
| 71 |
+// MakeRaw puts the terminal connected to the given file descriptor into raw |
|
| 72 |
+// mode and returns the previous state of the terminal so that it can be |
|
| 73 |
+// restored. |
|
| 74 |
+func MakeRaw(fd uintptr) (*State, error) {
|
|
| 75 |
+ var state *State |
|
| 76 |
+ state, err := SaveState(fd) |
|
| 77 |
+ if err != nil {
|
|
| 78 |
+ return nil, err |
|
| 79 |
+ } |
|
| 80 |
+ |
|
| 81 |
+ // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms683462(v=vs.85).aspx for these flag settings |
|
| 82 |
+ state.mode &^= (ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT) |
|
| 83 |
+ err = SetConsoleMode(fd, state.mode) |
|
| 84 |
+ if err != nil {
|
|
| 85 |
+ return nil, err |
|
| 86 |
+ } |
|
| 87 |
+ return state, nil |
|
| 88 |
+} |