1// +build windows 2 3package readline 4 5import ( 6 "reflect" 7 "syscall" 8 "unsafe" 9) 10 11var ( 12 kernel = NewKernel() 13 stdout = uintptr(syscall.Stdout) 14 stdin = uintptr(syscall.Stdin) 15) 16 17type Kernel struct { 18 SetConsoleCursorPosition, 19 SetConsoleTextAttribute, 20 FillConsoleOutputCharacterW, 21 FillConsoleOutputAttribute, 22 ReadConsoleInputW, 23 GetConsoleScreenBufferInfo, 24 GetConsoleCursorInfo, 25 GetStdHandle CallFunc 26} 27 28type short int16 29type word uint16 30type dword uint32 31type wchar uint16 32 33type _COORD struct { 34 x short 35 y short 36} 37 38func (c *_COORD) ptr() uintptr { 39 return uintptr(*(*int32)(unsafe.Pointer(c))) 40} 41 42const ( 43 EVENT_KEY = 0x0001 44 EVENT_MOUSE = 0x0002 45 EVENT_WINDOW_BUFFER_SIZE = 0x0004 46 EVENT_MENU = 0x0008 47 EVENT_FOCUS = 0x0010 48) 49 50type _KEY_EVENT_RECORD struct { 51 bKeyDown int32 52 wRepeatCount word 53 wVirtualKeyCode word 54 wVirtualScanCode word 55 unicodeChar wchar 56 dwControlKeyState dword 57} 58 59// KEY_EVENT_RECORD KeyEvent; 60// MOUSE_EVENT_RECORD MouseEvent; 61// WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent; 62// MENU_EVENT_RECORD MenuEvent; 63// FOCUS_EVENT_RECORD FocusEvent; 64type _INPUT_RECORD struct { 65 EventType word 66 Padding uint16 67 Event [16]byte 68} 69 70type _CONSOLE_SCREEN_BUFFER_INFO struct { 71 dwSize _COORD 72 dwCursorPosition _COORD 73 wAttributes word 74 srWindow _SMALL_RECT 75 dwMaximumWindowSize _COORD 76} 77 78type _SMALL_RECT struct { 79 left short 80 top short 81 right short 82 bottom short 83} 84 85type _CONSOLE_CURSOR_INFO struct { 86 dwSize dword 87 bVisible bool 88} 89 90type CallFunc func(u ...uintptr) error 91 92func NewKernel() *Kernel { 93 k := &Kernel{} 94 kernel32 := syscall.NewLazyDLL("kernel32.dll") 95 v := reflect.ValueOf(k).Elem() 96 t := v.Type() 97 for i := 0; i < t.NumField(); i++ { 98 name := t.Field(i).Name 99 f := kernel32.NewProc(name) 100 v.Field(i).Set(reflect.ValueOf(k.Wrap(f))) 101 } 102 return k 103} 104 105func (k *Kernel) Wrap(p *syscall.LazyProc) CallFunc { 106 return func(args ...uintptr) error { 107 var r0 uintptr 108 var e1 syscall.Errno 109 size := uintptr(len(args)) 110 if len(args) <= 3 { 111 buf := make([]uintptr, 3) 112 copy(buf, args) 113 r0, _, e1 = syscall.Syscall(p.Addr(), size, 114 buf[0], buf[1], buf[2]) 115 } else { 116 buf := make([]uintptr, 6) 117 copy(buf, args) 118 r0, _, e1 = syscall.Syscall6(p.Addr(), size, 119 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], 120 ) 121 } 122 123 if int(r0) == 0 { 124 if e1 != 0 { 125 return error(e1) 126 } else { 127 return syscall.EINVAL 128 } 129 } 130 return nil 131 } 132 133} 134 135func GetConsoleScreenBufferInfo() (*_CONSOLE_SCREEN_BUFFER_INFO, error) { 136 t := new(_CONSOLE_SCREEN_BUFFER_INFO) 137 err := kernel.GetConsoleScreenBufferInfo( 138 stdout, 139 uintptr(unsafe.Pointer(t)), 140 ) 141 return t, err 142} 143 144func GetConsoleCursorInfo() (*_CONSOLE_CURSOR_INFO, error) { 145 t := new(_CONSOLE_CURSOR_INFO) 146 err := kernel.GetConsoleCursorInfo(stdout, uintptr(unsafe.Pointer(t))) 147 return t, err 148} 149 150func SetConsoleCursorPosition(c *_COORD) error { 151 return kernel.SetConsoleCursorPosition(stdout, c.ptr()) 152} 153