1
2
3 package winterm
4
5 import (
6 "fmt"
7 "syscall"
8 "unsafe"
9 )
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 var (
32 kernel32DLL = syscall.NewLazyDLL("kernel32.dll")
33
34 getConsoleCursorInfoProc = kernel32DLL.NewProc("GetConsoleCursorInfo")
35 setConsoleCursorInfoProc = kernel32DLL.NewProc("SetConsoleCursorInfo")
36 setConsoleCursorPositionProc = kernel32DLL.NewProc("SetConsoleCursorPosition")
37 setConsoleModeProc = kernel32DLL.NewProc("SetConsoleMode")
38 getConsoleScreenBufferInfoProc = kernel32DLL.NewProc("GetConsoleScreenBufferInfo")
39 setConsoleScreenBufferSizeProc = kernel32DLL.NewProc("SetConsoleScreenBufferSize")
40 scrollConsoleScreenBufferProc = kernel32DLL.NewProc("ScrollConsoleScreenBufferA")
41 setConsoleTextAttributeProc = kernel32DLL.NewProc("SetConsoleTextAttribute")
42 setConsoleWindowInfoProc = kernel32DLL.NewProc("SetConsoleWindowInfo")
43 writeConsoleOutputProc = kernel32DLL.NewProc("WriteConsoleOutputW")
44 readConsoleInputProc = kernel32DLL.NewProc("ReadConsoleInputW")
45 waitForSingleObjectProc = kernel32DLL.NewProc("WaitForSingleObject")
46 )
47
48
49 const (
50
51
52 ENABLE_PROCESSED_INPUT = 0x0001
53 ENABLE_LINE_INPUT = 0x0002
54 ENABLE_ECHO_INPUT = 0x0004
55 ENABLE_WINDOW_INPUT = 0x0008
56 ENABLE_MOUSE_INPUT = 0x0010
57 ENABLE_INSERT_MODE = 0x0020
58 ENABLE_QUICK_EDIT_MODE = 0x0040
59 ENABLE_EXTENDED_FLAGS = 0x0080
60 ENABLE_AUTO_POSITION = 0x0100
61 ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200
62
63 ENABLE_PROCESSED_OUTPUT = 0x0001
64 ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002
65 ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004
66 DISABLE_NEWLINE_AUTO_RETURN = 0x0008
67 ENABLE_LVB_GRID_WORLDWIDE = 0x0010
68
69
70
71
72
73
74 FOREGROUND_BLUE uint16 = 0x0001
75 FOREGROUND_GREEN uint16 = 0x0002
76 FOREGROUND_RED uint16 = 0x0004
77 FOREGROUND_INTENSITY uint16 = 0x0008
78 FOREGROUND_MASK uint16 = 0x000F
79
80 BACKGROUND_BLUE uint16 = 0x0010
81 BACKGROUND_GREEN uint16 = 0x0020
82 BACKGROUND_RED uint16 = 0x0040
83 BACKGROUND_INTENSITY uint16 = 0x0080
84 BACKGROUND_MASK uint16 = 0x00F0
85
86 COMMON_LVB_MASK uint16 = 0xFF00
87 COMMON_LVB_REVERSE_VIDEO uint16 = 0x4000
88 COMMON_LVB_UNDERSCORE uint16 = 0x8000
89
90
91
92 KEY_EVENT = 0x0001
93 MOUSE_EVENT = 0x0002
94 WINDOW_BUFFER_SIZE_EVENT = 0x0004
95 MENU_EVENT = 0x0008
96 FOCUS_EVENT = 0x0010
97
98
99 WAIT_ABANDONED = 0x00000080
100 WAIT_FAILED = 0xFFFFFFFF
101 WAIT_SIGNALED = 0x0000000
102 WAIT_TIMEOUT = 0x00000102
103
104
105 WAIT_INFINITE = 0xFFFFFFFF
106 WAIT_ONE_SECOND = 1000
107 WAIT_HALF_SECOND = 500
108 WAIT_QUARTER_SECOND = 250
109 )
110
111
112
113
114 type (
115 CHAR_INFO struct {
116 UnicodeChar uint16
117 Attributes uint16
118 }
119
120 CONSOLE_CURSOR_INFO struct {
121 Size uint32
122 Visible int32
123 }
124
125 CONSOLE_SCREEN_BUFFER_INFO struct {
126 Size COORD
127 CursorPosition COORD
128 Attributes uint16
129 Window SMALL_RECT
130 MaximumWindowSize COORD
131 }
132
133 COORD struct {
134 X int16
135 Y int16
136 }
137
138 SMALL_RECT struct {
139 Left int16
140 Top int16
141 Right int16
142 Bottom int16
143 }
144
145
146
147 INPUT_RECORD struct {
148 EventType uint16
149 KeyEvent KEY_EVENT_RECORD
150 }
151
152 KEY_EVENT_RECORD struct {
153 KeyDown int32
154 RepeatCount uint16
155 VirtualKeyCode uint16
156 VirtualScanCode uint16
157 UnicodeChar uint16
158 ControlKeyState uint32
159 }
160
161 WINDOW_BUFFER_SIZE struct {
162 Size COORD
163 }
164 )
165
166
167 func boolToBOOL(f bool) int32 {
168 if f {
169 return int32(1)
170 } else {
171 return int32(0)
172 }
173 }
174
175
176
177 func GetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
178 r1, r2, err := getConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
179 return checkError(r1, r2, err)
180 }
181
182
183
184 func SetConsoleCursorInfo(handle uintptr, cursorInfo *CONSOLE_CURSOR_INFO) error {
185 r1, r2, err := setConsoleCursorInfoProc.Call(handle, uintptr(unsafe.Pointer(cursorInfo)), 0)
186 return checkError(r1, r2, err)
187 }
188
189
190
191 func SetConsoleCursorPosition(handle uintptr, coord COORD) error {
192 r1, r2, err := setConsoleCursorPositionProc.Call(handle, coordToPointer(coord))
193 use(coord)
194 return checkError(r1, r2, err)
195 }
196
197
198
199 func GetConsoleMode(handle uintptr) (mode uint32, err error) {
200 err = syscall.GetConsoleMode(syscall.Handle(handle), &mode)
201 return mode, err
202 }
203
204
205
206 func SetConsoleMode(handle uintptr, mode uint32) error {
207 r1, r2, err := setConsoleModeProc.Call(handle, uintptr(mode), 0)
208 use(mode)
209 return checkError(r1, r2, err)
210 }
211
212
213
214 func GetConsoleScreenBufferInfo(handle uintptr) (*CONSOLE_SCREEN_BUFFER_INFO, error) {
215 info := CONSOLE_SCREEN_BUFFER_INFO{}
216 err := checkError(getConsoleScreenBufferInfoProc.Call(handle, uintptr(unsafe.Pointer(&info)), 0))
217 if err != nil {
218 return nil, err
219 }
220 return &info, nil
221 }
222
223 func ScrollConsoleScreenBuffer(handle uintptr, scrollRect SMALL_RECT, clipRect SMALL_RECT, destOrigin COORD, char CHAR_INFO) error {
224 r1, r2, err := scrollConsoleScreenBufferProc.Call(handle, uintptr(unsafe.Pointer(&scrollRect)), uintptr(unsafe.Pointer(&clipRect)), coordToPointer(destOrigin), uintptr(unsafe.Pointer(&char)))
225 use(scrollRect)
226 use(clipRect)
227 use(destOrigin)
228 use(char)
229 return checkError(r1, r2, err)
230 }
231
232
233
234 func SetConsoleScreenBufferSize(handle uintptr, coord COORD) error {
235 r1, r2, err := setConsoleScreenBufferSizeProc.Call(handle, coordToPointer(coord))
236 use(coord)
237 return checkError(r1, r2, err)
238 }
239
240
241
242
243 func SetConsoleTextAttribute(handle uintptr, attribute uint16) error {
244 r1, r2, err := setConsoleTextAttributeProc.Call(handle, uintptr(attribute), 0)
245 use(attribute)
246 return checkError(r1, r2, err)
247 }
248
249
250
251
252 func SetConsoleWindowInfo(handle uintptr, isAbsolute bool, rect SMALL_RECT) error {
253 r1, r2, err := setConsoleWindowInfoProc.Call(handle, uintptr(boolToBOOL(isAbsolute)), uintptr(unsafe.Pointer(&rect)))
254 use(isAbsolute)
255 use(rect)
256 return checkError(r1, r2, err)
257 }
258
259
260
261 func WriteConsoleOutput(handle uintptr, buffer []CHAR_INFO, bufferSize COORD, bufferCoord COORD, writeRegion *SMALL_RECT) error {
262 r1, r2, err := writeConsoleOutputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), coordToPointer(bufferSize), coordToPointer(bufferCoord), uintptr(unsafe.Pointer(writeRegion)))
263 use(buffer)
264 use(bufferSize)
265 use(bufferCoord)
266 return checkError(r1, r2, err)
267 }
268
269
270
271 func ReadConsoleInput(handle uintptr, buffer []INPUT_RECORD, count *uint32) error {
272 r1, r2, err := readConsoleInputProc.Call(handle, uintptr(unsafe.Pointer(&buffer[0])), uintptr(len(buffer)), uintptr(unsafe.Pointer(count)))
273 use(buffer)
274 return checkError(r1, r2, err)
275 }
276
277
278
279
280 func WaitForSingleObject(handle uintptr, msWait uint32) (bool, error) {
281 r1, _, err := waitForSingleObjectProc.Call(handle, uintptr(uint32(msWait)))
282 switch r1 {
283 case WAIT_ABANDONED, WAIT_TIMEOUT:
284 return false, nil
285 case WAIT_SIGNALED:
286 return true, nil
287 }
288 use(msWait)
289 return false, err
290 }
291
292
293 func (info CONSOLE_SCREEN_BUFFER_INFO) String() string {
294 return fmt.Sprintf("Size(%v) Cursor(%v) Window(%v) Max(%v)", info.Size, info.CursorPosition, info.Window, info.MaximumWindowSize)
295 }
296
297 func (coord COORD) String() string {
298 return fmt.Sprintf("%v,%v", coord.X, coord.Y)
299 }
300
301 func (rect SMALL_RECT) String() string {
302 return fmt.Sprintf("(%v,%v),(%v,%v)", rect.Left, rect.Top, rect.Right, rect.Bottom)
303 }
304
305
306 func checkError(r1, r2 uintptr, err error) error {
307
308 if r1 != 0 {
309 return nil
310 }
311
312
313 if err != nil {
314 return err
315 }
316 return syscall.EINVAL
317 }
318
319
320 func coordToPointer(c COORD) uintptr {
321
322 return uintptr(*((*uint32)(unsafe.Pointer(&c))))
323 }
324
325
326
327 func use(p interface{}) {}
328
View as plain text