termbox_windows.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857
  1. package termbox
  2. import "syscall"
  3. import "unsafe"
  4. import "unicode/utf16"
  5. import "github.com/mattn/go-runewidth"
  6. type (
  7. wchar uint16
  8. short int16
  9. dword uint32
  10. word uint16
  11. char_info struct {
  12. char wchar
  13. attr word
  14. }
  15. coord struct {
  16. x short
  17. y short
  18. }
  19. small_rect struct {
  20. left short
  21. top short
  22. right short
  23. bottom short
  24. }
  25. console_screen_buffer_info struct {
  26. size coord
  27. cursor_position coord
  28. attributes word
  29. window small_rect
  30. maximum_window_size coord
  31. }
  32. console_cursor_info struct {
  33. size dword
  34. visible int32
  35. }
  36. input_record struct {
  37. event_type word
  38. _ [2]byte
  39. event [16]byte
  40. }
  41. key_event_record struct {
  42. key_down int32
  43. repeat_count word
  44. virtual_key_code word
  45. virtual_scan_code word
  46. unicode_char wchar
  47. control_key_state dword
  48. }
  49. window_buffer_size_record struct {
  50. size coord
  51. }
  52. mouse_event_record struct {
  53. mouse_pos coord
  54. button_state dword
  55. control_key_state dword
  56. event_flags dword
  57. }
  58. )
  59. const (
  60. mouse_lmb = 0x1
  61. mouse_rmb = 0x2
  62. mouse_mmb = 0x4 | 0x8 | 0x10
  63. )
  64. func (this coord) uintptr() uintptr {
  65. return uintptr(*(*int32)(unsafe.Pointer(&this)))
  66. }
  67. var kernel32 = syscall.NewLazyDLL("kernel32.dll")
  68. var is_cjk = runewidth.IsEastAsian()
  69. var (
  70. proc_set_console_active_screen_buffer = kernel32.NewProc("SetConsoleActiveScreenBuffer")
  71. proc_set_console_screen_buffer_size = kernel32.NewProc("SetConsoleScreenBufferSize")
  72. proc_create_console_screen_buffer = kernel32.NewProc("CreateConsoleScreenBuffer")
  73. proc_get_console_screen_buffer_info = kernel32.NewProc("GetConsoleScreenBufferInfo")
  74. proc_write_console_output = kernel32.NewProc("WriteConsoleOutputW")
  75. proc_write_console_output_character = kernel32.NewProc("WriteConsoleOutputCharacterW")
  76. proc_write_console_output_attribute = kernel32.NewProc("WriteConsoleOutputAttribute")
  77. proc_set_console_cursor_info = kernel32.NewProc("SetConsoleCursorInfo")
  78. proc_set_console_cursor_position = kernel32.NewProc("SetConsoleCursorPosition")
  79. proc_get_console_cursor_info = kernel32.NewProc("GetConsoleCursorInfo")
  80. proc_read_console_input = kernel32.NewProc("ReadConsoleInputW")
  81. proc_get_console_mode = kernel32.NewProc("GetConsoleMode")
  82. proc_set_console_mode = kernel32.NewProc("SetConsoleMode")
  83. proc_fill_console_output_character = kernel32.NewProc("FillConsoleOutputCharacterW")
  84. proc_fill_console_output_attribute = kernel32.NewProc("FillConsoleOutputAttribute")
  85. proc_create_event = kernel32.NewProc("CreateEventW")
  86. proc_wait_for_multiple_objects = kernel32.NewProc("WaitForMultipleObjects")
  87. proc_set_event = kernel32.NewProc("SetEvent")
  88. )
  89. func set_console_active_screen_buffer(h syscall.Handle) (err error) {
  90. r0, _, e1 := syscall.Syscall(proc_set_console_active_screen_buffer.Addr(),
  91. 1, uintptr(h), 0, 0)
  92. if int(r0) == 0 {
  93. if e1 != 0 {
  94. err = error(e1)
  95. } else {
  96. err = syscall.EINVAL
  97. }
  98. }
  99. return
  100. }
  101. func set_console_screen_buffer_size(h syscall.Handle, size coord) (err error) {
  102. r0, _, e1 := syscall.Syscall(proc_set_console_screen_buffer_size.Addr(),
  103. 2, uintptr(h), size.uintptr(), 0)
  104. if int(r0) == 0 {
  105. if e1 != 0 {
  106. err = error(e1)
  107. } else {
  108. err = syscall.EINVAL
  109. }
  110. }
  111. return
  112. }
  113. func create_console_screen_buffer() (h syscall.Handle, err error) {
  114. r0, _, e1 := syscall.Syscall6(proc_create_console_screen_buffer.Addr(),
  115. 5, uintptr(generic_read|generic_write), 0, 0, console_textmode_buffer, 0, 0)
  116. if int(r0) == 0 {
  117. if e1 != 0 {
  118. err = error(e1)
  119. } else {
  120. err = syscall.EINVAL
  121. }
  122. }
  123. return syscall.Handle(r0), err
  124. }
  125. func get_console_screen_buffer_info(h syscall.Handle, info *console_screen_buffer_info) (err error) {
  126. r0, _, e1 := syscall.Syscall(proc_get_console_screen_buffer_info.Addr(),
  127. 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
  128. if int(r0) == 0 {
  129. if e1 != 0 {
  130. err = error(e1)
  131. } else {
  132. err = syscall.EINVAL
  133. }
  134. }
  135. return
  136. }
  137. func write_console_output(h syscall.Handle, chars []char_info, dst small_rect) (err error) {
  138. tmp_coord = coord{dst.right - dst.left + 1, dst.bottom - dst.top + 1}
  139. tmp_rect = dst
  140. r0, _, e1 := syscall.Syscall6(proc_write_console_output.Addr(),
  141. 5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), tmp_coord.uintptr(),
  142. tmp_coord0.uintptr(), uintptr(unsafe.Pointer(&tmp_rect)), 0)
  143. if int(r0) == 0 {
  144. if e1 != 0 {
  145. err = error(e1)
  146. } else {
  147. err = syscall.EINVAL
  148. }
  149. }
  150. return
  151. }
  152. func write_console_output_character(h syscall.Handle, chars []wchar, pos coord) (err error) {
  153. r0, _, e1 := syscall.Syscall6(proc_write_console_output_character.Addr(),
  154. 5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), uintptr(len(chars)),
  155. pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
  156. if int(r0) == 0 {
  157. if e1 != 0 {
  158. err = error(e1)
  159. } else {
  160. err = syscall.EINVAL
  161. }
  162. }
  163. return
  164. }
  165. func write_console_output_attribute(h syscall.Handle, attrs []word, pos coord) (err error) {
  166. r0, _, e1 := syscall.Syscall6(proc_write_console_output_attribute.Addr(),
  167. 5, uintptr(h), uintptr(unsafe.Pointer(&attrs[0])), uintptr(len(attrs)),
  168. pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0)
  169. if int(r0) == 0 {
  170. if e1 != 0 {
  171. err = error(e1)
  172. } else {
  173. err = syscall.EINVAL
  174. }
  175. }
  176. return
  177. }
  178. func set_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
  179. r0, _, e1 := syscall.Syscall(proc_set_console_cursor_info.Addr(),
  180. 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
  181. if int(r0) == 0 {
  182. if e1 != 0 {
  183. err = error(e1)
  184. } else {
  185. err = syscall.EINVAL
  186. }
  187. }
  188. return
  189. }
  190. func get_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) {
  191. r0, _, e1 := syscall.Syscall(proc_get_console_cursor_info.Addr(),
  192. 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0)
  193. if int(r0) == 0 {
  194. if e1 != 0 {
  195. err = error(e1)
  196. } else {
  197. err = syscall.EINVAL
  198. }
  199. }
  200. return
  201. }
  202. func set_console_cursor_position(h syscall.Handle, pos coord) (err error) {
  203. r0, _, e1 := syscall.Syscall(proc_set_console_cursor_position.Addr(),
  204. 2, uintptr(h), pos.uintptr(), 0)
  205. if int(r0) == 0 {
  206. if e1 != 0 {
  207. err = error(e1)
  208. } else {
  209. err = syscall.EINVAL
  210. }
  211. }
  212. return
  213. }
  214. func read_console_input(h syscall.Handle, record *input_record) (err error) {
  215. r0, _, e1 := syscall.Syscall6(proc_read_console_input.Addr(),
  216. 4, uintptr(h), uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&tmp_arg)), 0, 0)
  217. if int(r0) == 0 {
  218. if e1 != 0 {
  219. err = error(e1)
  220. } else {
  221. err = syscall.EINVAL
  222. }
  223. }
  224. return
  225. }
  226. func get_console_mode(h syscall.Handle, mode *dword) (err error) {
  227. r0, _, e1 := syscall.Syscall(proc_get_console_mode.Addr(),
  228. 2, uintptr(h), uintptr(unsafe.Pointer(mode)), 0)
  229. if int(r0) == 0 {
  230. if e1 != 0 {
  231. err = error(e1)
  232. } else {
  233. err = syscall.EINVAL
  234. }
  235. }
  236. return
  237. }
  238. func set_console_mode(h syscall.Handle, mode dword) (err error) {
  239. r0, _, e1 := syscall.Syscall(proc_set_console_mode.Addr(),
  240. 2, uintptr(h), uintptr(mode), 0)
  241. if int(r0) == 0 {
  242. if e1 != 0 {
  243. err = error(e1)
  244. } else {
  245. err = syscall.EINVAL
  246. }
  247. }
  248. return
  249. }
  250. func fill_console_output_character(h syscall.Handle, char wchar, n int) (err error) {
  251. r0, _, e1 := syscall.Syscall6(proc_fill_console_output_character.Addr(),
  252. 5, uintptr(h), uintptr(char), uintptr(n), tmp_coord.uintptr(),
  253. uintptr(unsafe.Pointer(&tmp_arg)), 0)
  254. if int(r0) == 0 {
  255. if e1 != 0 {
  256. err = error(e1)
  257. } else {
  258. err = syscall.EINVAL
  259. }
  260. }
  261. return
  262. }
  263. func fill_console_output_attribute(h syscall.Handle, attr word, n int) (err error) {
  264. r0, _, e1 := syscall.Syscall6(proc_fill_console_output_attribute.Addr(),
  265. 5, uintptr(h), uintptr(attr), uintptr(n), tmp_coord.uintptr(),
  266. uintptr(unsafe.Pointer(&tmp_arg)), 0)
  267. if int(r0) == 0 {
  268. if e1 != 0 {
  269. err = error(e1)
  270. } else {
  271. err = syscall.EINVAL
  272. }
  273. }
  274. return
  275. }
  276. func create_event() (out syscall.Handle, err error) {
  277. r0, _, e1 := syscall.Syscall6(proc_create_event.Addr(),
  278. 4, 0, 0, 0, 0, 0, 0)
  279. if int(r0) == 0 {
  280. if e1 != 0 {
  281. err = error(e1)
  282. } else {
  283. err = syscall.EINVAL
  284. }
  285. }
  286. return syscall.Handle(r0), err
  287. }
  288. func wait_for_multiple_objects(objects []syscall.Handle) (err error) {
  289. r0, _, e1 := syscall.Syscall6(proc_wait_for_multiple_objects.Addr(),
  290. 4, uintptr(len(objects)), uintptr(unsafe.Pointer(&objects[0])),
  291. 0, 0xFFFFFFFF, 0, 0)
  292. if uint32(r0) == 0xFFFFFFFF {
  293. if e1 != 0 {
  294. err = error(e1)
  295. } else {
  296. err = syscall.EINVAL
  297. }
  298. }
  299. return
  300. }
  301. func set_event(ev syscall.Handle) (err error) {
  302. r0, _, e1 := syscall.Syscall(proc_set_event.Addr(),
  303. 1, uintptr(ev), 0, 0)
  304. if int(r0) == 0 {
  305. if e1 != 0 {
  306. err = error(e1)
  307. } else {
  308. err = syscall.EINVAL
  309. }
  310. }
  311. return
  312. }
  313. type diff_msg struct {
  314. pos short
  315. lines short
  316. chars []char_info
  317. }
  318. type input_event struct {
  319. event Event
  320. err error
  321. }
  322. var (
  323. orig_cursor_info console_cursor_info
  324. orig_size coord
  325. orig_mode dword
  326. orig_screen syscall.Handle
  327. back_buffer cellbuf
  328. front_buffer cellbuf
  329. term_size coord
  330. input_mode = InputEsc
  331. cursor_x = cursor_hidden
  332. cursor_y = cursor_hidden
  333. foreground = ColorDefault
  334. background = ColorDefault
  335. in syscall.Handle
  336. out syscall.Handle
  337. interrupt syscall.Handle
  338. charbuf []char_info
  339. diffbuf []diff_msg
  340. beg_x = -1
  341. beg_y = -1
  342. beg_i = -1
  343. input_comm = make(chan Event)
  344. interrupt_comm = make(chan struct{})
  345. cancel_comm = make(chan bool, 1)
  346. cancel_done_comm = make(chan bool)
  347. alt_mode_esc = false
  348. // these ones just to prevent heap allocs at all costs
  349. tmp_info console_screen_buffer_info
  350. tmp_arg dword
  351. tmp_coord0 = coord{0, 0}
  352. tmp_coord = coord{0, 0}
  353. tmp_rect = small_rect{0, 0, 0, 0}
  354. )
  355. func get_cursor_position(out syscall.Handle) coord {
  356. err := get_console_screen_buffer_info(out, &tmp_info)
  357. if err != nil {
  358. panic(err)
  359. }
  360. return tmp_info.cursor_position
  361. }
  362. func get_term_size(out syscall.Handle) coord {
  363. err := get_console_screen_buffer_info(out, &tmp_info)
  364. if err != nil {
  365. panic(err)
  366. }
  367. return tmp_info.size
  368. }
  369. func get_win_size(out syscall.Handle) coord {
  370. err := get_console_screen_buffer_info(out, &tmp_info)
  371. if err != nil {
  372. panic(err)
  373. }
  374. return coord{
  375. x: tmp_info.window.right - tmp_info.window.left + 1,
  376. y: tmp_info.window.bottom - tmp_info.window.top + 1,
  377. }
  378. }
  379. func update_size_maybe() {
  380. size := get_term_size(out)
  381. if size.x != term_size.x || size.y != term_size.y {
  382. term_size = size
  383. back_buffer.resize(int(size.x), int(size.y))
  384. front_buffer.resize(int(size.x), int(size.y))
  385. front_buffer.clear()
  386. clear()
  387. area := int(size.x) * int(size.y)
  388. if cap(charbuf) < area {
  389. charbuf = make([]char_info, 0, area)
  390. }
  391. }
  392. }
  393. var color_table_bg = []word{
  394. 0, // default (black)
  395. 0, // black
  396. background_red,
  397. background_green,
  398. background_red | background_green, // yellow
  399. background_blue,
  400. background_red | background_blue, // magenta
  401. background_green | background_blue, // cyan
  402. background_red | background_blue | background_green, // white
  403. }
  404. var color_table_fg = []word{
  405. foreground_red | foreground_blue | foreground_green, // default (white)
  406. 0,
  407. foreground_red,
  408. foreground_green,
  409. foreground_red | foreground_green, // yellow
  410. foreground_blue,
  411. foreground_red | foreground_blue, // magenta
  412. foreground_green | foreground_blue, // cyan
  413. foreground_red | foreground_blue | foreground_green, // white
  414. }
  415. const (
  416. replacement_char = '\uFFFD'
  417. max_rune = '\U0010FFFF'
  418. surr1 = 0xd800
  419. surr2 = 0xdc00
  420. surr3 = 0xe000
  421. surr_self = 0x10000
  422. )
  423. func append_diff_line(y int) int {
  424. n := 0
  425. for x := 0; x < front_buffer.width; {
  426. cell_offset := y*front_buffer.width + x
  427. back := &back_buffer.cells[cell_offset]
  428. front := &front_buffer.cells[cell_offset]
  429. attr, char := cell_to_char_info(*back)
  430. charbuf = append(charbuf, char_info{attr: attr, char: char[0]})
  431. *front = *back
  432. n++
  433. w := runewidth.RuneWidth(back.Ch)
  434. if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) {
  435. w = 1
  436. }
  437. x += w
  438. // If not CJK, fill trailing space with whitespace
  439. if !is_cjk && w == 2 {
  440. charbuf = append(charbuf, char_info{attr: attr, char: ' '})
  441. }
  442. }
  443. return n
  444. }
  445. // compares 'back_buffer' with 'front_buffer' and prepares all changes in the form of
  446. // 'diff_msg's in the 'diff_buf'
  447. func prepare_diff_messages() {
  448. // clear buffers
  449. diffbuf = diffbuf[:0]
  450. charbuf = charbuf[:0]
  451. var diff diff_msg
  452. gbeg := 0
  453. for y := 0; y < front_buffer.height; y++ {
  454. same := true
  455. line_offset := y * front_buffer.width
  456. for x := 0; x < front_buffer.width; x++ {
  457. cell_offset := line_offset + x
  458. back := &back_buffer.cells[cell_offset]
  459. front := &front_buffer.cells[cell_offset]
  460. if *back != *front {
  461. same = false
  462. break
  463. }
  464. }
  465. if same && diff.lines > 0 {
  466. diffbuf = append(diffbuf, diff)
  467. diff = diff_msg{}
  468. }
  469. if !same {
  470. beg := len(charbuf)
  471. end := beg + append_diff_line(y)
  472. if diff.lines == 0 {
  473. diff.pos = short(y)
  474. gbeg = beg
  475. }
  476. diff.lines++
  477. diff.chars = charbuf[gbeg:end]
  478. }
  479. }
  480. if diff.lines > 0 {
  481. diffbuf = append(diffbuf, diff)
  482. diff = diff_msg{}
  483. }
  484. }
  485. func get_ct(table []word, idx int) word {
  486. idx = idx & 0x0F
  487. if idx >= len(table) {
  488. idx = len(table) - 1
  489. }
  490. return table[idx]
  491. }
  492. func cell_to_char_info(c Cell) (attr word, wc [2]wchar) {
  493. attr = get_ct(color_table_fg, int(c.Fg)) | get_ct(color_table_bg, int(c.Bg))
  494. if c.Fg&AttrReverse|c.Bg&AttrReverse != 0 {
  495. attr = (attr&0xF0)>>4 | (attr&0x0F)<<4
  496. }
  497. if c.Fg&AttrBold != 0 {
  498. attr |= foreground_intensity
  499. }
  500. if c.Bg&AttrBold != 0 {
  501. attr |= background_intensity
  502. }
  503. r0, r1 := utf16.EncodeRune(c.Ch)
  504. if r0 == 0xFFFD {
  505. wc[0] = wchar(c.Ch)
  506. wc[1] = ' '
  507. } else {
  508. wc[0] = wchar(r0)
  509. wc[1] = wchar(r1)
  510. }
  511. return
  512. }
  513. func move_cursor(x, y int) {
  514. err := set_console_cursor_position(out, coord{short(x), short(y)})
  515. if err != nil {
  516. panic(err)
  517. }
  518. }
  519. func show_cursor(visible bool) {
  520. var v int32
  521. if visible {
  522. v = 1
  523. }
  524. var info console_cursor_info
  525. info.size = 100
  526. info.visible = v
  527. err := set_console_cursor_info(out, &info)
  528. if err != nil {
  529. panic(err)
  530. }
  531. }
  532. func clear() {
  533. var err error
  534. attr, char := cell_to_char_info(Cell{
  535. ' ',
  536. foreground,
  537. background,
  538. })
  539. area := int(term_size.x) * int(term_size.y)
  540. err = fill_console_output_attribute(out, attr, area)
  541. if err != nil {
  542. panic(err)
  543. }
  544. err = fill_console_output_character(out, char[0], area)
  545. if err != nil {
  546. panic(err)
  547. }
  548. if !is_cursor_hidden(cursor_x, cursor_y) {
  549. move_cursor(cursor_x, cursor_y)
  550. }
  551. }
  552. func key_event_record_to_event(r *key_event_record) (Event, bool) {
  553. if r.key_down == 0 {
  554. return Event{}, false
  555. }
  556. e := Event{Type: EventKey}
  557. if input_mode&InputAlt != 0 {
  558. if alt_mode_esc {
  559. e.Mod = ModAlt
  560. alt_mode_esc = false
  561. }
  562. if r.control_key_state&(left_alt_pressed|right_alt_pressed) != 0 {
  563. e.Mod = ModAlt
  564. }
  565. }
  566. ctrlpressed := r.control_key_state&(left_ctrl_pressed|right_ctrl_pressed) != 0
  567. if r.virtual_key_code >= vk_f1 && r.virtual_key_code <= vk_f12 {
  568. switch r.virtual_key_code {
  569. case vk_f1:
  570. e.Key = KeyF1
  571. case vk_f2:
  572. e.Key = KeyF2
  573. case vk_f3:
  574. e.Key = KeyF3
  575. case vk_f4:
  576. e.Key = KeyF4
  577. case vk_f5:
  578. e.Key = KeyF5
  579. case vk_f6:
  580. e.Key = KeyF6
  581. case vk_f7:
  582. e.Key = KeyF7
  583. case vk_f8:
  584. e.Key = KeyF8
  585. case vk_f9:
  586. e.Key = KeyF9
  587. case vk_f10:
  588. e.Key = KeyF10
  589. case vk_f11:
  590. e.Key = KeyF11
  591. case vk_f12:
  592. e.Key = KeyF12
  593. default:
  594. panic("unreachable")
  595. }
  596. return e, true
  597. }
  598. if r.virtual_key_code <= vk_delete {
  599. switch r.virtual_key_code {
  600. case vk_insert:
  601. e.Key = KeyInsert
  602. case vk_delete:
  603. e.Key = KeyDelete
  604. case vk_home:
  605. e.Key = KeyHome
  606. case vk_end:
  607. e.Key = KeyEnd
  608. case vk_pgup:
  609. e.Key = KeyPgup
  610. case vk_pgdn:
  611. e.Key = KeyPgdn
  612. case vk_arrow_up:
  613. e.Key = KeyArrowUp
  614. case vk_arrow_down:
  615. e.Key = KeyArrowDown
  616. case vk_arrow_left:
  617. e.Key = KeyArrowLeft
  618. case vk_arrow_right:
  619. e.Key = KeyArrowRight
  620. case vk_backspace:
  621. if ctrlpressed {
  622. e.Key = KeyBackspace2
  623. } else {
  624. e.Key = KeyBackspace
  625. }
  626. case vk_tab:
  627. e.Key = KeyTab
  628. case vk_enter:
  629. e.Key = KeyEnter
  630. case vk_esc:
  631. switch {
  632. case input_mode&InputEsc != 0:
  633. e.Key = KeyEsc
  634. case input_mode&InputAlt != 0:
  635. alt_mode_esc = true
  636. return Event{}, false
  637. }
  638. case vk_space:
  639. if ctrlpressed {
  640. // manual return here, because KeyCtrlSpace is zero
  641. e.Key = KeyCtrlSpace
  642. return e, true
  643. } else {
  644. e.Key = KeySpace
  645. }
  646. }
  647. if e.Key != 0 {
  648. return e, true
  649. }
  650. }
  651. if ctrlpressed {
  652. if Key(r.unicode_char) >= KeyCtrlA && Key(r.unicode_char) <= KeyCtrlRsqBracket {
  653. e.Key = Key(r.unicode_char)
  654. if input_mode&InputAlt != 0 && e.Key == KeyEsc {
  655. alt_mode_esc = true
  656. return Event{}, false
  657. }
  658. return e, true
  659. }
  660. switch r.virtual_key_code {
  661. case 192, 50:
  662. // manual return here, because KeyCtrl2 is zero
  663. e.Key = KeyCtrl2
  664. return e, true
  665. case 51:
  666. if input_mode&InputAlt != 0 {
  667. alt_mode_esc = true
  668. return Event{}, false
  669. }
  670. e.Key = KeyCtrl3
  671. case 52:
  672. e.Key = KeyCtrl4
  673. case 53:
  674. e.Key = KeyCtrl5
  675. case 54:
  676. e.Key = KeyCtrl6
  677. case 189, 191, 55:
  678. e.Key = KeyCtrl7
  679. case 8, 56:
  680. e.Key = KeyCtrl8
  681. }
  682. if e.Key != 0 {
  683. return e, true
  684. }
  685. }
  686. if r.unicode_char != 0 {
  687. e.Ch = rune(r.unicode_char)
  688. return e, true
  689. }
  690. return Event{}, false
  691. }
  692. func input_event_producer() {
  693. var r input_record
  694. var err error
  695. var last_button Key
  696. var last_button_pressed Key
  697. var last_state = dword(0)
  698. var last_x, last_y = -1, -1
  699. handles := []syscall.Handle{in, interrupt}
  700. for {
  701. err = wait_for_multiple_objects(handles)
  702. if err != nil {
  703. input_comm <- Event{Type: EventError, Err: err}
  704. }
  705. select {
  706. case <-cancel_comm:
  707. cancel_done_comm <- true
  708. return
  709. default:
  710. }
  711. err = read_console_input(in, &r)
  712. if err != nil {
  713. input_comm <- Event{Type: EventError, Err: err}
  714. }
  715. switch r.event_type {
  716. case key_event:
  717. kr := (*key_event_record)(unsafe.Pointer(&r.event))
  718. ev, ok := key_event_record_to_event(kr)
  719. if ok {
  720. for i := 0; i < int(kr.repeat_count); i++ {
  721. input_comm <- ev
  722. }
  723. }
  724. case window_buffer_size_event:
  725. sr := *(*window_buffer_size_record)(unsafe.Pointer(&r.event))
  726. input_comm <- Event{
  727. Type: EventResize,
  728. Width: int(sr.size.x),
  729. Height: int(sr.size.y),
  730. }
  731. case mouse_event:
  732. mr := *(*mouse_event_record)(unsafe.Pointer(&r.event))
  733. ev := Event{Type: EventMouse}
  734. switch mr.event_flags {
  735. case 0, 2:
  736. // single or double click
  737. cur_state := mr.button_state
  738. switch {
  739. case last_state&mouse_lmb == 0 && cur_state&mouse_lmb != 0:
  740. last_button = MouseLeft
  741. last_button_pressed = last_button
  742. case last_state&mouse_rmb == 0 && cur_state&mouse_rmb != 0:
  743. last_button = MouseRight
  744. last_button_pressed = last_button
  745. case last_state&mouse_mmb == 0 && cur_state&mouse_mmb != 0:
  746. last_button = MouseMiddle
  747. last_button_pressed = last_button
  748. case last_state&mouse_lmb != 0 && cur_state&mouse_lmb == 0:
  749. last_button = MouseRelease
  750. case last_state&mouse_rmb != 0 && cur_state&mouse_rmb == 0:
  751. last_button = MouseRelease
  752. case last_state&mouse_mmb != 0 && cur_state&mouse_mmb == 0:
  753. last_button = MouseRelease
  754. default:
  755. last_state = cur_state
  756. continue
  757. }
  758. last_state = cur_state
  759. ev.Key = last_button
  760. last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
  761. ev.MouseX = last_x
  762. ev.MouseY = last_y
  763. case 1:
  764. // mouse motion
  765. x, y := int(mr.mouse_pos.x), int(mr.mouse_pos.y)
  766. if last_state != 0 && (last_x != x || last_y != y) {
  767. ev.Key = last_button_pressed
  768. ev.Mod = ModMotion
  769. ev.MouseX = x
  770. ev.MouseY = y
  771. last_x, last_y = x, y
  772. } else {
  773. ev.Type = EventNone
  774. }
  775. case 4:
  776. // mouse wheel
  777. n := int16(mr.button_state >> 16)
  778. if n > 0 {
  779. ev.Key = MouseWheelUp
  780. } else {
  781. ev.Key = MouseWheelDown
  782. }
  783. last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y)
  784. ev.MouseX = last_x
  785. ev.MouseY = last_y
  786. default:
  787. ev.Type = EventNone
  788. }
  789. if ev.Type != EventNone {
  790. input_comm <- ev
  791. }
  792. }
  793. }
  794. }