summary refs log tree commit diff
path: root/vendor/github.com/chzyer/readline/windows_api.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/chzyer/readline/windows_api.go')
-rw-r--r--vendor/github.com/chzyer/readline/windows_api.go152
1 files changed, 152 insertions, 0 deletions
diff --git a/vendor/github.com/chzyer/readline/windows_api.go b/vendor/github.com/chzyer/readline/windows_api.go
new file mode 100644
index 0000000..63f4f7b
--- /dev/null
+++ b/vendor/github.com/chzyer/readline/windows_api.go
@@ -0,0 +1,152 @@
+// +build windows
+
+package readline
+
+import (
+	"reflect"
+	"syscall"
+	"unsafe"
+)
+
+var (
+	kernel = NewKernel()
+	stdout = uintptr(syscall.Stdout)
+	stdin  = uintptr(syscall.Stdin)
+)
+
+type Kernel struct {
+	SetConsoleCursorPosition,
+	SetConsoleTextAttribute,
+	FillConsoleOutputCharacterW,
+	FillConsoleOutputAttribute,
+	ReadConsoleInputW,
+	GetConsoleScreenBufferInfo,
+	GetConsoleCursorInfo,
+	GetStdHandle CallFunc
+}
+
+type short int16
+type word uint16
+type dword uint32
+type wchar uint16
+
+type _COORD struct {
+	x short
+	y short
+}
+
+func (c *_COORD) ptr() uintptr {
+	return uintptr(*(*int32)(unsafe.Pointer(c)))
+}
+
+const (
+	EVENT_KEY                = 0x0001
+	EVENT_MOUSE              = 0x0002
+	EVENT_WINDOW_BUFFER_SIZE = 0x0004
+	EVENT_MENU               = 0x0008
+	EVENT_FOCUS              = 0x0010
+)
+
+type _KEY_EVENT_RECORD struct {
+	bKeyDown          int32
+	wRepeatCount      word
+	wVirtualKeyCode   word
+	wVirtualScanCode  word
+	unicodeChar       wchar
+	dwControlKeyState dword
+}
+
+// KEY_EVENT_RECORD          KeyEvent;
+// MOUSE_EVENT_RECORD        MouseEvent;
+// WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+// MENU_EVENT_RECORD         MenuEvent;
+// FOCUS_EVENT_RECORD        FocusEvent;
+type _INPUT_RECORD struct {
+	EventType word
+	Padding   uint16
+	Event     [16]byte
+}
+
+type _CONSOLE_SCREEN_BUFFER_INFO struct {
+	dwSize              _COORD
+	dwCursorPosition    _COORD
+	wAttributes         word
+	srWindow            _SMALL_RECT
+	dwMaximumWindowSize _COORD
+}
+
+type _SMALL_RECT struct {
+	left   short
+	top    short
+	right  short
+	bottom short
+}
+
+type _CONSOLE_CURSOR_INFO struct {
+	dwSize   dword
+	bVisible bool
+}
+
+type CallFunc func(u ...uintptr) error
+
+func NewKernel() *Kernel {
+	k := &Kernel{}
+	kernel32 := syscall.NewLazyDLL("kernel32.dll")
+	v := reflect.ValueOf(k).Elem()
+	t := v.Type()
+	for i := 0; i < t.NumField(); i++ {
+		name := t.Field(i).Name
+		f := kernel32.NewProc(name)
+		v.Field(i).Set(reflect.ValueOf(k.Wrap(f)))
+	}
+	return k
+}
+
+func (k *Kernel) Wrap(p *syscall.LazyProc) CallFunc {
+	return func(args ...uintptr) error {
+		var r0 uintptr
+		var e1 syscall.Errno
+		size := uintptr(len(args))
+		if len(args) <= 3 {
+			buf := make([]uintptr, 3)
+			copy(buf, args)
+			r0, _, e1 = syscall.Syscall(p.Addr(), size,
+				buf[0], buf[1], buf[2])
+		} else {
+			buf := make([]uintptr, 6)
+			copy(buf, args)
+			r0, _, e1 = syscall.Syscall6(p.Addr(), size,
+				buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
+			)
+		}
+
+		if int(r0) == 0 {
+			if e1 != 0 {
+				return error(e1)
+			} else {
+				return syscall.EINVAL
+			}
+		}
+		return nil
+	}
+
+}
+
+func GetConsoleScreenBufferInfo() (*_CONSOLE_SCREEN_BUFFER_INFO, error) {
+	t := new(_CONSOLE_SCREEN_BUFFER_INFO)
+	err := kernel.GetConsoleScreenBufferInfo(
+		stdout,
+		uintptr(unsafe.Pointer(t)),
+	)
+	return t, err
+}
+
+func GetConsoleCursorInfo() (*_CONSOLE_CURSOR_INFO, error) {
+	t := new(_CONSOLE_CURSOR_INFO)
+	err := kernel.GetConsoleCursorInfo(stdout, uintptr(unsafe.Pointer(t)))
+	return t, err
+}
+
+func SetConsoleCursorPosition(c *_COORD) error {
+	return kernel.SetConsoleCursorPosition(stdout, c.ptr())
+}