|
|
// +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()) }
|