зеркало из https://github.com/Azure/ARO-RP.git
153 строки
3.0 KiB
Go
153 строки
3.0 KiB
Go
// +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())
|
|
}
|