1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 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())
}
|