golang-github-nsf-termbox-go-0.0~git20160914/000077500000000000000000000000001277573306300205135ustar00rootroot00000000000000golang-github-nsf-termbox-go-0.0~git20160914/AUTHORS000066400000000000000000000001451277573306300215630ustar00rootroot00000000000000# Please keep this file sorted. Georg Reinke nsf golang-github-nsf-termbox-go-0.0~git20160914/LICENSE000066400000000000000000000020461277573306300215220ustar00rootroot00000000000000Copyright (C) 2012 termbox-go authors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. golang-github-nsf-termbox-go-0.0~git20160914/README.md000066400000000000000000000046131277573306300217760ustar00rootroot00000000000000## Termbox Termbox is a library that provides a minimalistic API which allows the programmer to write text-based user interfaces. The library is crossplatform and has both terminal-based implementations on *nix operating systems and a winapi console based implementation for windows operating systems. The basic idea is an abstraction of the greatest common subset of features available on all major terminals and other terminal-like APIs in a minimalistic fashion. Small API means it is easy to implement, test, maintain and learn it, that's what makes the termbox a distinct library in its area. ### Installation Install and update this go package with `go get -u github.com/nsf/termbox-go` ### Examples For examples of what can be done take a look at demos in the _demos directory. You can try them with go run: `go run _demos/keyboard.go` There are also some interesting projects using termbox-go: - [godit](https://github.com/nsf/godit) is an emacsish lightweight text editor written using termbox. - [gomatrix](https://github.com/GeertJohan/gomatrix) connects to The Matrix and displays its data streams in your terminal. - [gotetris](https://github.com/jjinux/gotetris) is an implementation of Tetris. - [sokoban-go](https://github.com/rn2dy/sokoban-go) is an implementation of sokoban game. - [hecate](https://github.com/evanmiller/hecate) is a hex editor designed by Satan. - [httopd](https://github.com/verdverm/httopd) is top for httpd logs. - [mop](https://github.com/michaeldv/mop) is stock market tracker for hackers. - [termui](https://github.com/gizak/termui) is a terminal dashboard. - [termloop](https://github.com/JoelOtter/termloop) is a terminal game engine. - [xterm-color-chart](https://github.com/kutuluk/xterm-color-chart) is a XTerm 256 color chart. - [gocui](https://github.com/jroimartin/gocui) is a minimalist Go library aimed at creating console user interfaces. - [dry](https://github.com/moncho/dry) is an interactive cli to manage Docker containers. - [pxl](https://github.com/ichinaski/pxl) displays images in the terminal. - [snake-game](https://github.com/DyegoCosta/snake-game) is an implementation of the Snake game. - [gone](https://github.com/guillaumebreton/gone) is a CLI pomodoro® timer. - [Spoof.go](https://github.com/sabey/spoofgo) controllable movement spoofing from the cli ### API reference [godoc.org/github.com/nsf/termbox-go](http://godoc.org/github.com/nsf/termbox-go) golang-github-nsf-termbox-go-0.0~git20160914/_demos/000077500000000000000000000000001277573306300217615ustar00rootroot00000000000000golang-github-nsf-termbox-go-0.0~git20160914/_demos/editbox.go000066400000000000000000000157141277573306300237560ustar00rootroot00000000000000package main import ( "github.com/mattn/go-runewidth" "github.com/nsf/termbox-go" "unicode/utf8" ) func tbprint(x, y int, fg, bg termbox.Attribute, msg string) { for _, c := range msg { termbox.SetCell(x, y, c, fg, bg) x += runewidth.RuneWidth(c) } } func fill(x, y, w, h int, cell termbox.Cell) { for ly := 0; ly < h; ly++ { for lx := 0; lx < w; lx++ { termbox.SetCell(x+lx, y+ly, cell.Ch, cell.Fg, cell.Bg) } } } func rune_advance_len(r rune, pos int) int { if r == '\t' { return tabstop_length - pos%tabstop_length } return runewidth.RuneWidth(r) } func voffset_coffset(text []byte, boffset int) (voffset, coffset int) { text = text[:boffset] for len(text) > 0 { r, size := utf8.DecodeRune(text) text = text[size:] coffset += 1 voffset += rune_advance_len(r, voffset) } return } func byte_slice_grow(s []byte, desired_cap int) []byte { if cap(s) < desired_cap { ns := make([]byte, len(s), desired_cap) copy(ns, s) return ns } return s } func byte_slice_remove(text []byte, from, to int) []byte { size := to - from copy(text[from:], text[to:]) text = text[:len(text)-size] return text } func byte_slice_insert(text []byte, offset int, what []byte) []byte { n := len(text) + len(what) text = byte_slice_grow(text, n) text = text[:n] copy(text[offset+len(what):], text[offset:]) copy(text[offset:], what) return text } const preferred_horizontal_threshold = 5 const tabstop_length = 8 type EditBox struct { text []byte line_voffset int cursor_boffset int // cursor offset in bytes cursor_voffset int // visual cursor offset in termbox cells cursor_coffset int // cursor offset in unicode code points } // Draws the EditBox in the given location, 'h' is not used at the moment func (eb *EditBox) Draw(x, y, w, h int) { eb.AdjustVOffset(w) const coldef = termbox.ColorDefault fill(x, y, w, h, termbox.Cell{Ch: ' '}) t := eb.text lx := 0 tabstop := 0 for { rx := lx - eb.line_voffset if len(t) == 0 { break } if lx == tabstop { tabstop += tabstop_length } if rx >= w { termbox.SetCell(x+w-1, y, '→', coldef, coldef) break } r, size := utf8.DecodeRune(t) if r == '\t' { for ; lx < tabstop; lx++ { rx = lx - eb.line_voffset if rx >= w { goto next } if rx >= 0 { termbox.SetCell(x+rx, y, ' ', coldef, coldef) } } } else { if rx >= 0 { termbox.SetCell(x+rx, y, r, coldef, coldef) } lx += runewidth.RuneWidth(r) } next: t = t[size:] } if eb.line_voffset != 0 { termbox.SetCell(x, y, '←', coldef, coldef) } } // Adjusts line visual offset to a proper value depending on width func (eb *EditBox) AdjustVOffset(width int) { ht := preferred_horizontal_threshold max_h_threshold := (width - 1) / 2 if ht > max_h_threshold { ht = max_h_threshold } threshold := width - 1 if eb.line_voffset != 0 { threshold = width - ht } if eb.cursor_voffset-eb.line_voffset >= threshold { eb.line_voffset = eb.cursor_voffset + (ht - width + 1) } if eb.line_voffset != 0 && eb.cursor_voffset-eb.line_voffset < ht { eb.line_voffset = eb.cursor_voffset - ht if eb.line_voffset < 0 { eb.line_voffset = 0 } } } func (eb *EditBox) MoveCursorTo(boffset int) { eb.cursor_boffset = boffset eb.cursor_voffset, eb.cursor_coffset = voffset_coffset(eb.text, boffset) } func (eb *EditBox) RuneUnderCursor() (rune, int) { return utf8.DecodeRune(eb.text[eb.cursor_boffset:]) } func (eb *EditBox) RuneBeforeCursor() (rune, int) { return utf8.DecodeLastRune(eb.text[:eb.cursor_boffset]) } func (eb *EditBox) MoveCursorOneRuneBackward() { if eb.cursor_boffset == 0 { return } _, size := eb.RuneBeforeCursor() eb.MoveCursorTo(eb.cursor_boffset - size) } func (eb *EditBox) MoveCursorOneRuneForward() { if eb.cursor_boffset == len(eb.text) { return } _, size := eb.RuneUnderCursor() eb.MoveCursorTo(eb.cursor_boffset + size) } func (eb *EditBox) MoveCursorToBeginningOfTheLine() { eb.MoveCursorTo(0) } func (eb *EditBox) MoveCursorToEndOfTheLine() { eb.MoveCursorTo(len(eb.text)) } func (eb *EditBox) DeleteRuneBackward() { if eb.cursor_boffset == 0 { return } eb.MoveCursorOneRuneBackward() _, size := eb.RuneUnderCursor() eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size) } func (eb *EditBox) DeleteRuneForward() { if eb.cursor_boffset == len(eb.text) { return } _, size := eb.RuneUnderCursor() eb.text = byte_slice_remove(eb.text, eb.cursor_boffset, eb.cursor_boffset+size) } func (eb *EditBox) DeleteTheRestOfTheLine() { eb.text = eb.text[:eb.cursor_boffset] } func (eb *EditBox) InsertRune(r rune) { var buf [utf8.UTFMax]byte n := utf8.EncodeRune(buf[:], r) eb.text = byte_slice_insert(eb.text, eb.cursor_boffset, buf[:n]) eb.MoveCursorOneRuneForward() } // Please, keep in mind that cursor depends on the value of line_voffset, which // is being set on Draw() call, so.. call this method after Draw() one. func (eb *EditBox) CursorX() int { return eb.cursor_voffset - eb.line_voffset } var edit_box EditBox const edit_box_width = 30 func redraw_all() { const coldef = termbox.ColorDefault termbox.Clear(coldef, coldef) w, h := termbox.Size() midy := h / 2 midx := (w - edit_box_width) / 2 // unicode box drawing chars around the edit box termbox.SetCell(midx-1, midy, '│', coldef, coldef) termbox.SetCell(midx+edit_box_width, midy, '│', coldef, coldef) termbox.SetCell(midx-1, midy-1, '┌', coldef, coldef) termbox.SetCell(midx-1, midy+1, '└', coldef, coldef) termbox.SetCell(midx+edit_box_width, midy-1, '┐', coldef, coldef) termbox.SetCell(midx+edit_box_width, midy+1, '┘', coldef, coldef) fill(midx, midy-1, edit_box_width, 1, termbox.Cell{Ch: '─'}) fill(midx, midy+1, edit_box_width, 1, termbox.Cell{Ch: '─'}) edit_box.Draw(midx, midy, edit_box_width, 1) termbox.SetCursor(midx+edit_box.CursorX(), midy) tbprint(midx+6, midy+3, coldef, coldef, "Press ESC to quit") termbox.Flush() } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() termbox.SetInputMode(termbox.InputEsc) redraw_all() mainloop: for { switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: switch ev.Key { case termbox.KeyEsc: break mainloop case termbox.KeyArrowLeft, termbox.KeyCtrlB: edit_box.MoveCursorOneRuneBackward() case termbox.KeyArrowRight, termbox.KeyCtrlF: edit_box.MoveCursorOneRuneForward() case termbox.KeyBackspace, termbox.KeyBackspace2: edit_box.DeleteRuneBackward() case termbox.KeyDelete, termbox.KeyCtrlD: edit_box.DeleteRuneForward() case termbox.KeyTab: edit_box.InsertRune('\t') case termbox.KeySpace: edit_box.InsertRune(' ') case termbox.KeyCtrlK: edit_box.DeleteTheRestOfTheLine() case termbox.KeyHome, termbox.KeyCtrlA: edit_box.MoveCursorToBeginningOfTheLine() case termbox.KeyEnd, termbox.KeyCtrlE: edit_box.MoveCursorToEndOfTheLine() default: if ev.Ch != 0 { edit_box.InsertRune(ev.Ch) } } case termbox.EventError: panic(ev.Err) } redraw_all() } } golang-github-nsf-termbox-go-0.0~git20160914/_demos/interrupt.go000066400000000000000000000023521277573306300243460ustar00rootroot00000000000000package main import ( "fmt" "github.com/nsf/termbox-go" "time" ) func tbPrint(x, y int, fg, bg termbox.Attribute, msg string) { for _, c := range msg { termbox.SetCell(x, y, c, fg, bg) x++ } } func draw(i int) { termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) defer termbox.Flush() w, h := termbox.Size() s := fmt.Sprintf("count = %d", i) tbPrint((w/2)-(len(s)/2), h/2, termbox.ColorRed, termbox.ColorDefault, s) } func main() { err := termbox.Init() if err != nil { panic(err) } termbox.SetInputMode(termbox.InputEsc) go func() { time.Sleep(5 * time.Second) termbox.Interrupt() // This should never run - the Interrupt(), above, should cause the event // loop below to exit, which then exits the process. If something goes // wrong, this panic will trigger and show what happened. time.Sleep(1 * time.Second) panic("this should never run") }() var count int draw(count) mainloop: for { switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: if ev.Ch == '+' { count++ } else if ev.Ch == '-' { count-- } case termbox.EventError: panic(ev.Err) case termbox.EventInterrupt: break mainloop } draw(count) } termbox.Close() fmt.Println("Finished") } golang-github-nsf-termbox-go-0.0~git20160914/_demos/keyboard.go000066400000000000000000000603721277573306300241200ustar00rootroot00000000000000package main import "github.com/nsf/termbox-go" import "fmt" type key struct { x int y int ch rune } var K_ESC = []key{{1, 1, 'E'}, {2, 1, 'S'}, {3, 1, 'C'}} var K_F1 = []key{{6, 1, 'F'}, {7, 1, '1'}} var K_F2 = []key{{9, 1, 'F'}, {10, 1, '2'}} var K_F3 = []key{{12, 1, 'F'}, {13, 1, '3'}} var K_F4 = []key{{15, 1, 'F'}, {16, 1, '4'}} var K_F5 = []key{{19, 1, 'F'}, {20, 1, '5'}} var K_F6 = []key{{22, 1, 'F'}, {23, 1, '6'}} var K_F7 = []key{{25, 1, 'F'}, {26, 1, '7'}} var K_F8 = []key{{28, 1, 'F'}, {29, 1, '8'}} var K_F9 = []key{{33, 1, 'F'}, {34, 1, '9'}} var K_F10 = []key{{36, 1, 'F'}, {37, 1, '1'}, {38, 1, '0'}} var K_F11 = []key{{40, 1, 'F'}, {41, 1, '1'}, {42, 1, '1'}} var K_F12 = []key{{44, 1, 'F'}, {45, 1, '1'}, {46, 1, '2'}} var K_PRN = []key{{50, 1, 'P'}, {51, 1, 'R'}, {52, 1, 'N'}} var K_SCR = []key{{54, 1, 'S'}, {55, 1, 'C'}, {56, 1, 'R'}} var K_BRK = []key{{58, 1, 'B'}, {59, 1, 'R'}, {60, 1, 'K'}} var K_LED1 = []key{{66, 1, '-'}} var K_LED2 = []key{{70, 1, '-'}} var K_LED3 = []key{{74, 1, '-'}} var K_TILDE = []key{{1, 4, '`'}} var K_TILDE_SHIFT = []key{{1, 4, '~'}} var K_1 = []key{{4, 4, '1'}} var K_1_SHIFT = []key{{4, 4, '!'}} var K_2 = []key{{7, 4, '2'}} var K_2_SHIFT = []key{{7, 4, '@'}} var K_3 = []key{{10, 4, '3'}} var K_3_SHIFT = []key{{10, 4, '#'}} var K_4 = []key{{13, 4, '4'}} var K_4_SHIFT = []key{{13, 4, '$'}} var K_5 = []key{{16, 4, '5'}} var K_5_SHIFT = []key{{16, 4, '%'}} var K_6 = []key{{19, 4, '6'}} var K_6_SHIFT = []key{{19, 4, '^'}} var K_7 = []key{{22, 4, '7'}} var K_7_SHIFT = []key{{22, 4, '&'}} var K_8 = []key{{25, 4, '8'}} var K_8_SHIFT = []key{{25, 4, '*'}} var K_9 = []key{{28, 4, '9'}} var K_9_SHIFT = []key{{28, 4, '('}} var K_0 = []key{{31, 4, '0'}} var K_0_SHIFT = []key{{31, 4, ')'}} var K_MINUS = []key{{34, 4, '-'}} var K_MINUS_SHIFT = []key{{34, 4, '_'}} var K_EQUALS = []key{{37, 4, '='}} var K_EQUALS_SHIFT = []key{{37, 4, '+'}} var K_BACKSLASH = []key{{40, 4, '\\'}} var K_BACKSLASH_SHIFT = []key{{40, 4, '|'}} var K_BACKSPACE = []key{{44, 4, 0x2190}, {45, 4, 0x2500}, {46, 4, 0x2500}} var K_INS = []key{{50, 4, 'I'}, {51, 4, 'N'}, {52, 4, 'S'}} var K_HOM = []key{{54, 4, 'H'}, {55, 4, 'O'}, {56, 4, 'M'}} var K_PGU = []key{{58, 4, 'P'}, {59, 4, 'G'}, {60, 4, 'U'}} var K_K_NUMLOCK = []key{{65, 4, 'N'}} var K_K_SLASH = []key{{68, 4, '/'}} var K_K_STAR = []key{{71, 4, '*'}} var K_K_MINUS = []key{{74, 4, '-'}} var K_TAB = []key{{1, 6, 'T'}, {2, 6, 'A'}, {3, 6, 'B'}} var K_q = []key{{6, 6, 'q'}} var K_Q = []key{{6, 6, 'Q'}} var K_w = []key{{9, 6, 'w'}} var K_W = []key{{9, 6, 'W'}} var K_e = []key{{12, 6, 'e'}} var K_E = []key{{12, 6, 'E'}} var K_r = []key{{15, 6, 'r'}} var K_R = []key{{15, 6, 'R'}} var K_t = []key{{18, 6, 't'}} var K_T = []key{{18, 6, 'T'}} var K_y = []key{{21, 6, 'y'}} var K_Y = []key{{21, 6, 'Y'}} var K_u = []key{{24, 6, 'u'}} var K_U = []key{{24, 6, 'U'}} var K_i = []key{{27, 6, 'i'}} var K_I = []key{{27, 6, 'I'}} var K_o = []key{{30, 6, 'o'}} var K_O = []key{{30, 6, 'O'}} var K_p = []key{{33, 6, 'p'}} var K_P = []key{{33, 6, 'P'}} var K_LSQB = []key{{36, 6, '['}} var K_LCUB = []key{{36, 6, '{'}} var K_RSQB = []key{{39, 6, ']'}} var K_RCUB = []key{{39, 6, '}'}} var K_ENTER = []key{ {43, 6, 0x2591}, {44, 6, 0x2591}, {45, 6, 0x2591}, {46, 6, 0x2591}, {43, 7, 0x2591}, {44, 7, 0x2591}, {45, 7, 0x21B5}, {46, 7, 0x2591}, {41, 8, 0x2591}, {42, 8, 0x2591}, {43, 8, 0x2591}, {44, 8, 0x2591}, {45, 8, 0x2591}, {46, 8, 0x2591}, } var K_DEL = []key{{50, 6, 'D'}, {51, 6, 'E'}, {52, 6, 'L'}} var K_END = []key{{54, 6, 'E'}, {55, 6, 'N'}, {56, 6, 'D'}} var K_PGD = []key{{58, 6, 'P'}, {59, 6, 'G'}, {60, 6, 'D'}} var K_K_7 = []key{{65, 6, '7'}} var K_K_8 = []key{{68, 6, '8'}} var K_K_9 = []key{{71, 6, '9'}} var K_K_PLUS = []key{{74, 6, ' '}, {74, 7, '+'}, {74, 8, ' '}} var K_CAPS = []key{{1, 8, 'C'}, {2, 8, 'A'}, {3, 8, 'P'}, {4, 8, 'S'}} var K_a = []key{{7, 8, 'a'}} var K_A = []key{{7, 8, 'A'}} var K_s = []key{{10, 8, 's'}} var K_S = []key{{10, 8, 'S'}} var K_d = []key{{13, 8, 'd'}} var K_D = []key{{13, 8, 'D'}} var K_f = []key{{16, 8, 'f'}} var K_F = []key{{16, 8, 'F'}} var K_g = []key{{19, 8, 'g'}} var K_G = []key{{19, 8, 'G'}} var K_h = []key{{22, 8, 'h'}} var K_H = []key{{22, 8, 'H'}} var K_j = []key{{25, 8, 'j'}} var K_J = []key{{25, 8, 'J'}} var K_k = []key{{28, 8, 'k'}} var K_K = []key{{28, 8, 'K'}} var K_l = []key{{31, 8, 'l'}} var K_L = []key{{31, 8, 'L'}} var K_SEMICOLON = []key{{34, 8, ';'}} var K_PARENTHESIS = []key{{34, 8, ':'}} var K_QUOTE = []key{{37, 8, '\''}} var K_DOUBLEQUOTE = []key{{37, 8, '"'}} var K_K_4 = []key{{65, 8, '4'}} var K_K_5 = []key{{68, 8, '5'}} var K_K_6 = []key{{71, 8, '6'}} var K_LSHIFT = []key{{1, 10, 'S'}, {2, 10, 'H'}, {3, 10, 'I'}, {4, 10, 'F'}, {5, 10, 'T'}} var K_z = []key{{9, 10, 'z'}} var K_Z = []key{{9, 10, 'Z'}} var K_x = []key{{12, 10, 'x'}} var K_X = []key{{12, 10, 'X'}} var K_c = []key{{15, 10, 'c'}} var K_C = []key{{15, 10, 'C'}} var K_v = []key{{18, 10, 'v'}} var K_V = []key{{18, 10, 'V'}} var K_b = []key{{21, 10, 'b'}} var K_B = []key{{21, 10, 'B'}} var K_n = []key{{24, 10, 'n'}} var K_N = []key{{24, 10, 'N'}} var K_m = []key{{27, 10, 'm'}} var K_M = []key{{27, 10, 'M'}} var K_COMMA = []key{{30, 10, ','}} var K_LANB = []key{{30, 10, '<'}} var K_PERIOD = []key{{33, 10, '.'}} var K_RANB = []key{{33, 10, '>'}} var K_SLASH = []key{{36, 10, '/'}} var K_QUESTION = []key{{36, 10, '?'}} var K_RSHIFT = []key{{42, 10, 'S'}, {43, 10, 'H'}, {44, 10, 'I'}, {45, 10, 'F'}, {46, 10, 'T'}} var K_ARROW_UP = []key{{54, 10, '('}, {55, 10, 0x2191}, {56, 10, ')'}} var K_K_1 = []key{{65, 10, '1'}} var K_K_2 = []key{{68, 10, '2'}} var K_K_3 = []key{{71, 10, '3'}} var K_K_ENTER = []key{{74, 10, 0x2591}, {74, 11, 0x2591}, {74, 12, 0x2591}} var K_LCTRL = []key{{1, 12, 'C'}, {2, 12, 'T'}, {3, 12, 'R'}, {4, 12, 'L'}} var K_LWIN = []key{{6, 12, 'W'}, {7, 12, 'I'}, {8, 12, 'N'}} var K_LALT = []key{{10, 12, 'A'}, {11, 12, 'L'}, {12, 12, 'T'}} var K_SPACE = []key{ {14, 12, ' '}, {15, 12, ' '}, {16, 12, ' '}, {17, 12, ' '}, {18, 12, ' '}, {19, 12, 'S'}, {20, 12, 'P'}, {21, 12, 'A'}, {22, 12, 'C'}, {23, 12, 'E'}, {24, 12, ' '}, {25, 12, ' '}, {26, 12, ' '}, {27, 12, ' '}, {28, 12, ' '}, } var K_RALT = []key{{30, 12, 'A'}, {31, 12, 'L'}, {32, 12, 'T'}} var K_RWIN = []key{{34, 12, 'W'}, {35, 12, 'I'}, {36, 12, 'N'}} var K_RPROP = []key{{38, 12, 'P'}, {39, 12, 'R'}, {40, 12, 'O'}, {41, 12, 'P'}} var K_RCTRL = []key{{43, 12, 'C'}, {44, 12, 'T'}, {45, 12, 'R'}, {46, 12, 'L'}} var K_ARROW_LEFT = []key{{50, 12, '('}, {51, 12, 0x2190}, {52, 12, ')'}} var K_ARROW_DOWN = []key{{54, 12, '('}, {55, 12, 0x2193}, {56, 12, ')'}} var K_ARROW_RIGHT = []key{{58, 12, '('}, {59, 12, 0x2192}, {60, 12, ')'}} var K_K_0 = []key{{65, 12, ' '}, {66, 12, '0'}, {67, 12, ' '}, {68, 12, ' '}} var K_K_PERIOD = []key{{71, 12, '.'}} type combo struct { keys [][]key } var combos = []combo{ {[][]key{K_TILDE, K_2, K_SPACE, K_LCTRL, K_RCTRL}}, {[][]key{K_A, K_LCTRL, K_RCTRL}}, {[][]key{K_B, K_LCTRL, K_RCTRL}}, {[][]key{K_C, K_LCTRL, K_RCTRL}}, {[][]key{K_D, K_LCTRL, K_RCTRL}}, {[][]key{K_E, K_LCTRL, K_RCTRL}}, {[][]key{K_F, K_LCTRL, K_RCTRL}}, {[][]key{K_G, K_LCTRL, K_RCTRL}}, {[][]key{K_H, K_BACKSPACE, K_LCTRL, K_RCTRL}}, {[][]key{K_I, K_TAB, K_LCTRL, K_RCTRL}}, {[][]key{K_J, K_LCTRL, K_RCTRL}}, {[][]key{K_K, K_LCTRL, K_RCTRL}}, {[][]key{K_L, K_LCTRL, K_RCTRL}}, {[][]key{K_M, K_ENTER, K_K_ENTER, K_LCTRL, K_RCTRL}}, {[][]key{K_N, K_LCTRL, K_RCTRL}}, {[][]key{K_O, K_LCTRL, K_RCTRL}}, {[][]key{K_P, K_LCTRL, K_RCTRL}}, {[][]key{K_Q, K_LCTRL, K_RCTRL}}, {[][]key{K_R, K_LCTRL, K_RCTRL}}, {[][]key{K_S, K_LCTRL, K_RCTRL}}, {[][]key{K_T, K_LCTRL, K_RCTRL}}, {[][]key{K_U, K_LCTRL, K_RCTRL}}, {[][]key{K_V, K_LCTRL, K_RCTRL}}, {[][]key{K_W, K_LCTRL, K_RCTRL}}, {[][]key{K_X, K_LCTRL, K_RCTRL}}, {[][]key{K_Y, K_LCTRL, K_RCTRL}}, {[][]key{K_Z, K_LCTRL, K_RCTRL}}, {[][]key{K_LSQB, K_ESC, K_3, K_LCTRL, K_RCTRL}}, {[][]key{K_4, K_BACKSLASH, K_LCTRL, K_RCTRL}}, {[][]key{K_RSQB, K_5, K_LCTRL, K_RCTRL}}, {[][]key{K_6, K_LCTRL, K_RCTRL}}, {[][]key{K_7, K_SLASH, K_MINUS_SHIFT, K_LCTRL, K_RCTRL}}, {[][]key{K_SPACE}}, {[][]key{K_1_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_DOUBLEQUOTE, K_LSHIFT, K_RSHIFT}}, {[][]key{K_3_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_4_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_5_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_7_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_QUOTE}}, {[][]key{K_9_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_0_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_8_SHIFT, K_K_STAR, K_LSHIFT, K_RSHIFT}}, {[][]key{K_EQUALS_SHIFT, K_K_PLUS, K_LSHIFT, K_RSHIFT}}, {[][]key{K_COMMA}}, {[][]key{K_MINUS, K_K_MINUS}}, {[][]key{K_PERIOD, K_K_PERIOD}}, {[][]key{K_SLASH, K_K_SLASH}}, {[][]key{K_0, K_K_0}}, {[][]key{K_1, K_K_1}}, {[][]key{K_2, K_K_2}}, {[][]key{K_3, K_K_3}}, {[][]key{K_4, K_K_4}}, {[][]key{K_5, K_K_5}}, {[][]key{K_6, K_K_6}}, {[][]key{K_7, K_K_7}}, {[][]key{K_8, K_K_8}}, {[][]key{K_9, K_K_9}}, {[][]key{K_PARENTHESIS, K_LSHIFT, K_RSHIFT}}, {[][]key{K_SEMICOLON}}, {[][]key{K_LANB, K_LSHIFT, K_RSHIFT}}, {[][]key{K_EQUALS}}, {[][]key{K_RANB, K_LSHIFT, K_RSHIFT}}, {[][]key{K_QUESTION, K_LSHIFT, K_RSHIFT}}, {[][]key{K_2_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_A, K_LSHIFT, K_RSHIFT}}, {[][]key{K_B, K_LSHIFT, K_RSHIFT}}, {[][]key{K_C, K_LSHIFT, K_RSHIFT}}, {[][]key{K_D, K_LSHIFT, K_RSHIFT}}, {[][]key{K_E, K_LSHIFT, K_RSHIFT}}, {[][]key{K_F, K_LSHIFT, K_RSHIFT}}, {[][]key{K_G, K_LSHIFT, K_RSHIFT}}, {[][]key{K_H, K_LSHIFT, K_RSHIFT}}, {[][]key{K_I, K_LSHIFT, K_RSHIFT}}, {[][]key{K_J, K_LSHIFT, K_RSHIFT}}, {[][]key{K_K, K_LSHIFT, K_RSHIFT}}, {[][]key{K_L, K_LSHIFT, K_RSHIFT}}, {[][]key{K_M, K_LSHIFT, K_RSHIFT}}, {[][]key{K_N, K_LSHIFT, K_RSHIFT}}, {[][]key{K_O, K_LSHIFT, K_RSHIFT}}, {[][]key{K_P, K_LSHIFT, K_RSHIFT}}, {[][]key{K_Q, K_LSHIFT, K_RSHIFT}}, {[][]key{K_R, K_LSHIFT, K_RSHIFT}}, {[][]key{K_S, K_LSHIFT, K_RSHIFT}}, {[][]key{K_T, K_LSHIFT, K_RSHIFT}}, {[][]key{K_U, K_LSHIFT, K_RSHIFT}}, {[][]key{K_V, K_LSHIFT, K_RSHIFT}}, {[][]key{K_W, K_LSHIFT, K_RSHIFT}}, {[][]key{K_X, K_LSHIFT, K_RSHIFT}}, {[][]key{K_Y, K_LSHIFT, K_RSHIFT}}, {[][]key{K_Z, K_LSHIFT, K_RSHIFT}}, {[][]key{K_LSQB}}, {[][]key{K_BACKSLASH}}, {[][]key{K_RSQB}}, {[][]key{K_6_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_MINUS_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_TILDE}}, {[][]key{K_a}}, {[][]key{K_b}}, {[][]key{K_c}}, {[][]key{K_d}}, {[][]key{K_e}}, {[][]key{K_f}}, {[][]key{K_g}}, {[][]key{K_h}}, {[][]key{K_i}}, {[][]key{K_j}}, {[][]key{K_k}}, {[][]key{K_l}}, {[][]key{K_m}}, {[][]key{K_n}}, {[][]key{K_o}}, {[][]key{K_p}}, {[][]key{K_q}}, {[][]key{K_r}}, {[][]key{K_s}}, {[][]key{K_t}}, {[][]key{K_u}}, {[][]key{K_v}}, {[][]key{K_w}}, {[][]key{K_x}}, {[][]key{K_y}}, {[][]key{K_z}}, {[][]key{K_LCUB, K_LSHIFT, K_RSHIFT}}, {[][]key{K_BACKSLASH_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_RCUB, K_LSHIFT, K_RSHIFT}}, {[][]key{K_TILDE_SHIFT, K_LSHIFT, K_RSHIFT}}, {[][]key{K_8, K_BACKSPACE, K_LCTRL, K_RCTRL}}, } var func_combos = []combo{ {[][]key{K_F1}}, {[][]key{K_F2}}, {[][]key{K_F3}}, {[][]key{K_F4}}, {[][]key{K_F5}}, {[][]key{K_F6}}, {[][]key{K_F7}}, {[][]key{K_F8}}, {[][]key{K_F9}}, {[][]key{K_F10}}, {[][]key{K_F11}}, {[][]key{K_F12}}, {[][]key{K_INS}}, {[][]key{K_DEL}}, {[][]key{K_HOM}}, {[][]key{K_END}}, {[][]key{K_PGU}}, {[][]key{K_PGD}}, {[][]key{K_ARROW_UP}}, {[][]key{K_ARROW_DOWN}}, {[][]key{K_ARROW_LEFT}}, {[][]key{K_ARROW_RIGHT}}, } func print_tb(x, y int, fg, bg termbox.Attribute, msg string) { for _, c := range msg { termbox.SetCell(x, y, c, fg, bg) x++ } } func printf_tb(x, y int, fg, bg termbox.Attribute, format string, args ...interface{}) { s := fmt.Sprintf(format, args...) print_tb(x, y, fg, bg, s) } func draw_key(k []key, fg, bg termbox.Attribute) { for _, k := range k { termbox.SetCell(k.x+2, k.y+4, k.ch, fg, bg) } } func draw_keyboard() { termbox.SetCell(0, 0, 0x250C, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(79, 0, 0x2510, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(0, 23, 0x2514, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(79, 23, 0x2518, termbox.ColorWhite, termbox.ColorBlack) for i := 1; i < 79; i++ { termbox.SetCell(i, 0, 0x2500, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(i, 23, 0x2500, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(i, 17, 0x2500, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(i, 4, 0x2500, termbox.ColorWhite, termbox.ColorBlack) } for i := 1; i < 23; i++ { termbox.SetCell(0, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(79, i, 0x2502, termbox.ColorWhite, termbox.ColorBlack) } termbox.SetCell(0, 17, 0x251C, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(79, 17, 0x2524, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(0, 4, 0x251C, termbox.ColorWhite, termbox.ColorBlack) termbox.SetCell(79, 4, 0x2524, termbox.ColorWhite, termbox.ColorBlack) for i := 5; i < 17; i++ { termbox.SetCell(1, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow) termbox.SetCell(78, i, 0x2588, termbox.ColorYellow, termbox.ColorYellow) } draw_key(K_ESC, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F1, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F2, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F3, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F4, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F5, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F6, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F7, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F8, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F9, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F10, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F11, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_F12, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_PRN, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_SCR, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_BRK, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LED1, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LED2, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LED3, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_TILDE, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_1, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_2, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_3, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_4, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_5, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_6, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_7, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_8, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_9, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_0, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_MINUS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_EQUALS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_BACKSLASH, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_BACKSPACE, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_INS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_HOM, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_PGU, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_NUMLOCK, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_SLASH, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_STAR, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_MINUS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_TAB, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_q, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_w, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_e, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_r, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_t, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_y, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_u, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_i, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_o, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_p, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LSQB, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RSQB, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_ENTER, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_DEL, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_END, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_PGD, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_7, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_8, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_9, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_PLUS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_CAPS, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_a, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_s, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_d, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_f, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_g, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_h, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_j, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_k, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_l, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_SEMICOLON, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_QUOTE, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_4, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_5, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_6, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LSHIFT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_z, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_x, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_c, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_v, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_b, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_n, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_m, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_COMMA, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_PERIOD, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_SLASH, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RSHIFT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_ARROW_UP, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_1, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_2, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_3, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_ENTER, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LCTRL, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LWIN, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_LALT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_SPACE, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RCTRL, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RPROP, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RWIN, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_RALT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_ARROW_LEFT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_ARROW_DOWN, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_ARROW_RIGHT, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_0, termbox.ColorWhite, termbox.ColorBlue) draw_key(K_K_PERIOD, termbox.ColorWhite, termbox.ColorBlue) printf_tb(33, 1, termbox.ColorMagenta|termbox.AttrBold, termbox.ColorBlack, "Keyboard demo!") printf_tb(21, 2, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+Q to exit)") printf_tb(15, 3, termbox.ColorMagenta, termbox.ColorBlack, "(press CTRL+X and then CTRL+C to change input mode)") inputmode := termbox.SetInputMode(termbox.InputCurrent) inputmode_str := "" switch { case inputmode&termbox.InputEsc != 0: inputmode_str = "termbox.InputEsc" case inputmode&termbox.InputAlt != 0: inputmode_str = "termbox.InputAlt" } if inputmode&termbox.InputMouse != 0 { inputmode_str += " | termbox.InputMouse" } printf_tb(3, 18, termbox.ColorWhite, termbox.ColorBlack, "Input mode: %s", inputmode_str) } var fcmap = []string{ "CTRL+2, CTRL+~", "CTRL+A", "CTRL+B", "CTRL+C", "CTRL+D", "CTRL+E", "CTRL+F", "CTRL+G", "CTRL+H, BACKSPACE", "CTRL+I, TAB", "CTRL+J", "CTRL+K", "CTRL+L", "CTRL+M, ENTER", "CTRL+N", "CTRL+O", "CTRL+P", "CTRL+Q", "CTRL+R", "CTRL+S", "CTRL+T", "CTRL+U", "CTRL+V", "CTRL+W", "CTRL+X", "CTRL+Y", "CTRL+Z", "CTRL+3, ESC, CTRL+[", "CTRL+4, CTRL+\\", "CTRL+5, CTRL+]", "CTRL+6", "CTRL+7, CTRL+/, CTRL+_", "SPACE", } var fkmap = []string{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "INSERT", "DELETE", "HOME", "END", "PGUP", "PGDN", "ARROW UP", "ARROW DOWN", "ARROW LEFT", "ARROW RIGHT", } func funckeymap(k termbox.Key) string { if k == termbox.KeyCtrl8 { return "CTRL+8, BACKSPACE 2" /* 0x7F */ } else if k >= termbox.KeyArrowRight && k <= 0xFFFF { return fkmap[0xFFFF-k] } else if k <= termbox.KeySpace { return fcmap[k] } return "UNKNOWN" } func pretty_print_press(ev *termbox.Event) { printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ") printf_tb(8, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Key) printf_tb(8, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Key) printf_tb(8, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Key) printf_tb(8, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", funckeymap(ev.Key)) printf_tb(54, 19, termbox.ColorWhite, termbox.ColorBlack, "Char: ") printf_tb(60, 19, termbox.ColorYellow, termbox.ColorBlack, "decimal: %d", ev.Ch) printf_tb(60, 20, termbox.ColorGreen, termbox.ColorBlack, "hex: 0x%X", ev.Ch) printf_tb(60, 21, termbox.ColorCyan, termbox.ColorBlack, "octal: 0%o", ev.Ch) printf_tb(60, 22, termbox.ColorRed, termbox.ColorBlack, "string: %s", string(ev.Ch)) modifier := "none" if ev.Mod != 0 { modifier = "termbox.ModAlt" } printf_tb(54, 18, termbox.ColorWhite, termbox.ColorBlack, "Modifier: %s", modifier) } func pretty_print_resize(ev *termbox.Event) { printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Resize event: %d x %d", ev.Width, ev.Height) } var counter = 0 func pretty_print_mouse(ev *termbox.Event) { printf_tb(3, 19, termbox.ColorWhite, termbox.ColorBlack, "Mouse event: %d x %d", ev.MouseX, ev.MouseY) button := "" switch ev.Key { case termbox.MouseLeft: button = "MouseLeft: %d" case termbox.MouseMiddle: button = "MouseMiddle: %d" case termbox.MouseRight: button = "MouseRight: %d" case termbox.MouseWheelUp: button = "MouseWheelUp: %d" case termbox.MouseWheelDown: button = "MouseWheelDown: %d" case termbox.MouseRelease: button = "MouseRelease: %d" } if ev.Mod&termbox.ModMotion != 0 { button += "*" } counter++ printf_tb(43, 19, termbox.ColorWhite, termbox.ColorBlack, "Key: ") printf_tb(48, 19, termbox.ColorYellow, termbox.ColorBlack, button, counter) } func dispatch_press(ev *termbox.Event) { if ev.Mod&termbox.ModAlt != 0 { draw_key(K_LALT, termbox.ColorWhite, termbox.ColorRed) draw_key(K_RALT, termbox.ColorWhite, termbox.ColorRed) } var k *combo if ev.Key >= termbox.KeyArrowRight { k = &func_combos[0xFFFF-ev.Key] } else if ev.Ch < 128 { if ev.Ch == 0 && ev.Key < 128 { k = &combos[ev.Key] } else { k = &combos[ev.Ch] } } if k == nil { return } keys := k.keys for _, k := range keys { draw_key(k, termbox.ColorWhite, termbox.ColorRed) } } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse) termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) draw_keyboard() termbox.Flush() inputmode := 0 ctrlxpressed := false loop: for { switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: if ev.Key == termbox.KeyCtrlS && ctrlxpressed { termbox.Sync() } if ev.Key == termbox.KeyCtrlQ && ctrlxpressed { break loop } if ev.Key == termbox.KeyCtrlC && ctrlxpressed { chmap := []termbox.InputMode{ termbox.InputEsc | termbox.InputMouse, termbox.InputAlt | termbox.InputMouse, termbox.InputEsc, termbox.InputAlt, } inputmode++ if inputmode >= len(chmap) { inputmode = 0 } termbox.SetInputMode(chmap[inputmode]) } if ev.Key == termbox.KeyCtrlX { ctrlxpressed = true } else { ctrlxpressed = false } termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) draw_keyboard() dispatch_press(&ev) pretty_print_press(&ev) termbox.Flush() case termbox.EventResize: termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) draw_keyboard() pretty_print_resize(&ev) termbox.Flush() case termbox.EventMouse: termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) draw_keyboard() pretty_print_mouse(&ev) termbox.Flush() case termbox.EventError: panic(ev.Err) } } } golang-github-nsf-termbox-go-0.0~git20160914/_demos/output.go000066400000000000000000000133351277573306300236550ustar00rootroot00000000000000package main import "github.com/mattn/go-runewidth" import "github.com/nsf/termbox-go" const chars = "nnnnnnnnnbbbbbbbbbuuuuuuuuuBBBBBBBBB" var output_mode = termbox.OutputNormal func next_char(current int) int { current++ if current >= len(chars) { return 0 } return current } func print_combinations_table(sx, sy int, attrs []termbox.Attribute) { var bg termbox.Attribute current_char := 0 y := sy all_attrs := []termbox.Attribute{ 0, termbox.AttrBold, termbox.AttrUnderline, termbox.AttrBold | termbox.AttrUnderline, } draw_line := func() { x := sx for _, a := range all_attrs { for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ { fg := a | c termbox.SetCell(x, y, rune(chars[current_char]), fg, bg) current_char = next_char(current_char) x++ } } } for _, a := range attrs { for c := termbox.ColorDefault; c <= termbox.ColorWhite; c++ { bg = a | c draw_line() y++ } } } func print_wide(x, y int, s string) { red := false for _, r := range s { c := termbox.ColorDefault if red { c = termbox.ColorRed } termbox.SetCell(x, y, r, termbox.ColorDefault, c) w := runewidth.RuneWidth(r) if w == 0 || (w == 2 && runewidth.IsAmbiguousWidth(r)) { w = 1 } x += w red = !red } } const hello_world = "こんにちは世界" func draw_all() { termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) switch output_mode { case termbox.OutputNormal: print_combinations_table(1, 1, []termbox.Attribute{ 0, termbox.AttrBold, }) print_combinations_table(2+len(chars), 1, []termbox.Attribute{ termbox.AttrReverse, }) print_wide(2+len(chars), 11, hello_world) case termbox.OutputGrayscale: for y := 0; y < 26; y++ { for x := 0; x < 26; x++ { termbox.SetCell(x, y, 'n', termbox.Attribute(x+1), termbox.Attribute(y+1)) termbox.SetCell(x+27, y, 'b', termbox.Attribute(x+1)|termbox.AttrBold, termbox.Attribute(26-y)) termbox.SetCell(x+54, y, 'u', termbox.Attribute(x+1)|termbox.AttrUnderline, termbox.Attribute(y+1)) } termbox.SetCell(82, y, 'd', termbox.Attribute(y+1), termbox.ColorDefault) termbox.SetCell(83, y, 'd', termbox.ColorDefault, termbox.Attribute(26-y)) } case termbox.Output216: for r := 0; r < 6; r++ { for g := 0; g < 6; g++ { for b := 0; b < 6; b++ { y := r x := g + 6*b c1 := termbox.Attribute(1 + r*36 + g*6 + b) bg := termbox.Attribute(1 + g*36 + b*6 + r) c2 := termbox.Attribute(1 + b*36 + r*6 + g) bc1 := c1 | termbox.AttrBold uc1 := c1 | termbox.AttrUnderline bc2 := c2 | termbox.AttrBold uc2 := c2 | termbox.AttrUnderline termbox.SetCell(x, y, 'n', c1, bg) termbox.SetCell(x, y+6, 'b', bc1, bg) termbox.SetCell(x, y+12, 'u', uc1, bg) termbox.SetCell(x, y+18, 'B', bc1|uc1, bg) termbox.SetCell(x+37, y, 'n', c2, bg) termbox.SetCell(x+37, y+6, 'b', bc2, bg) termbox.SetCell(x+37, y+12, 'u', uc2, bg) termbox.SetCell(x+37, y+18, 'B', bc2|uc2, bg) } c1 := termbox.Attribute(1 + g*6 + r*36) c2 := termbox.Attribute(6 + g*6 + r*36) termbox.SetCell(74+g, r, 'd', c1, termbox.ColorDefault) termbox.SetCell(74+g, r+6, 'd', c2, termbox.ColorDefault) termbox.SetCell(74+g, r+12, 'd', termbox.ColorDefault, c1) termbox.SetCell(74+g, r+18, 'd', termbox.ColorDefault, c2) } } case termbox.Output256: for y := 0; y < 4; y++ { for x := 0; x < 8; x++ { for z := 0; z < 8; z++ { bg := termbox.Attribute(1 + y*64 + x*8 + z) c1 := termbox.Attribute(256 - y*64 - x*8 - z) c2 := termbox.Attribute(1 + y*64 + z*8 + x) c3 := termbox.Attribute(256 - y*64 - z*8 - x) c4 := termbox.Attribute(1 + y*64 + x*4 + z*4) bold := c2 | termbox.AttrBold under := c3 | termbox.AttrUnderline both := c1 | termbox.AttrBold | termbox.AttrUnderline termbox.SetCell(z+8*x, y, ' ', 0, bg) termbox.SetCell(z+8*x, y+5, 'n', c4, bg) termbox.SetCell(z+8*x, y+10, 'b', bold, bg) termbox.SetCell(z+8*x, y+15, 'u', under, bg) termbox.SetCell(z+8*x, y+20, 'B', both, bg) } } } for x := 0; x < 12; x++ { for y := 0; y < 2; y++ { c1 := termbox.Attribute(233 + y*12 + x) termbox.SetCell(66+x, y, 'd', c1, termbox.ColorDefault) termbox.SetCell(66+x, 2+y, 'd', termbox.ColorDefault, c1) } } for x := 0; x < 6; x++ { for y := 0; y < 6; y++ { c1 := termbox.Attribute(17 + x*6 + y*36) c2 := termbox.Attribute(17 + 5 + x*6 + y*36) termbox.SetCell(66+x, 6+y, 'd', c1, termbox.ColorDefault) termbox.SetCell(66+x, 12+y, 'd', c2, termbox.ColorDefault) termbox.SetCell(72+x, 6+y, 'd', termbox.ColorDefault, c1) termbox.SetCell(72+x, 12+y, 'd', termbox.ColorDefault, c2) } } } termbox.Flush() } var available_modes = []termbox.OutputMode{ termbox.OutputNormal, termbox.OutputGrayscale, termbox.Output216, termbox.Output256, } var output_mode_index = 0 func switch_output_mode(direction int) { output_mode_index += direction if output_mode_index < 0 { output_mode_index = len(available_modes) - 1 } else if output_mode_index >= len(available_modes) { output_mode_index = 0 } output_mode = termbox.SetOutputMode(available_modes[output_mode_index]) termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) termbox.Sync() } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() draw_all() loop: for { switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: switch ev.Key { case termbox.KeyEsc: break loop case termbox.KeyArrowUp, termbox.KeyArrowRight: switch_output_mode(1) draw_all() case termbox.KeyArrowDown, termbox.KeyArrowLeft: switch_output_mode(-1) draw_all() } case termbox.EventResize: draw_all() } } } golang-github-nsf-termbox-go-0.0~git20160914/_demos/paint.go000066400000000000000000000052011277573306300234210ustar00rootroot00000000000000package main import ( "github.com/nsf/termbox-go" ) var curCol = 0 var curRune = 0 var backbuf []termbox.Cell var bbw, bbh int var runes = []rune{' ', '░', '▒', '▓', '█'} var colors = []termbox.Attribute{ termbox.ColorBlack, termbox.ColorRed, termbox.ColorGreen, termbox.ColorYellow, termbox.ColorBlue, termbox.ColorMagenta, termbox.ColorCyan, termbox.ColorWhite, } type attrFunc func(int) (rune, termbox.Attribute, termbox.Attribute) func updateAndDrawButtons(current *int, x, y int, mx, my int, n int, attrf attrFunc) { lx, ly := x, y for i := 0; i < n; i++ { if lx <= mx && mx <= lx+3 && ly <= my && my <= ly+1 { *current = i } r, fg, bg := attrf(i) termbox.SetCell(lx+0, ly+0, r, fg, bg) termbox.SetCell(lx+1, ly+0, r, fg, bg) termbox.SetCell(lx+2, ly+0, r, fg, bg) termbox.SetCell(lx+3, ly+0, r, fg, bg) termbox.SetCell(lx+0, ly+1, r, fg, bg) termbox.SetCell(lx+1, ly+1, r, fg, bg) termbox.SetCell(lx+2, ly+1, r, fg, bg) termbox.SetCell(lx+3, ly+1, r, fg, bg) lx += 4 } lx, ly = x, y for i := 0; i < n; i++ { if *current == i { fg := termbox.ColorRed | termbox.AttrBold bg := termbox.ColorDefault termbox.SetCell(lx+0, ly+2, '^', fg, bg) termbox.SetCell(lx+1, ly+2, '^', fg, bg) termbox.SetCell(lx+2, ly+2, '^', fg, bg) termbox.SetCell(lx+3, ly+2, '^', fg, bg) } lx += 4 } } func update_and_redraw_all(mx, my int) { termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) if mx != -1 && my != -1 { backbuf[bbw*my+mx] = termbox.Cell{Ch: runes[curRune], Fg: colors[curCol]} } copy(termbox.CellBuffer(), backbuf) _, h := termbox.Size() updateAndDrawButtons(&curRune, 0, 0, mx, my, len(runes), func(i int) (rune, termbox.Attribute, termbox.Attribute) { return runes[i], termbox.ColorDefault, termbox.ColorDefault }) updateAndDrawButtons(&curCol, 0, h-3, mx, my, len(colors), func(i int) (rune, termbox.Attribute, termbox.Attribute) { return ' ', termbox.ColorDefault, colors[i] }) termbox.Flush() } func reallocBackBuffer(w, h int) { bbw, bbh = w, h backbuf = make([]termbox.Cell, w*h) } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() termbox.SetInputMode(termbox.InputEsc | termbox.InputMouse) reallocBackBuffer(termbox.Size()) update_and_redraw_all(-1, -1) mainloop: for { mx, my := -1, -1 switch ev := termbox.PollEvent(); ev.Type { case termbox.EventKey: if ev.Key == termbox.KeyEsc { break mainloop } case termbox.EventMouse: if ev.Key == termbox.MouseLeft { mx, my = ev.MouseX, ev.MouseY } case termbox.EventResize: reallocBackBuffer(ev.Width, ev.Height) } update_and_redraw_all(mx, my) } } golang-github-nsf-termbox-go-0.0~git20160914/_demos/random_output.go000066400000000000000000000013761277573306300252170ustar00rootroot00000000000000package main import "github.com/nsf/termbox-go" import "math/rand" import "time" func draw() { w, h := termbox.Size() termbox.Clear(termbox.ColorDefault, termbox.ColorDefault) for y := 0; y < h; y++ { for x := 0; x < w; x++ { termbox.SetCell(x, y, ' ', termbox.ColorDefault, termbox.Attribute(rand.Int()%8)+1) } } termbox.Flush() } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() event_queue := make(chan termbox.Event) go func() { for { event_queue <- termbox.PollEvent() } }() draw() loop: for { select { case ev := <-event_queue: if ev.Type == termbox.EventKey && ev.Key == termbox.KeyEsc { break loop } default: draw() time.Sleep(10 * time.Millisecond) } } } golang-github-nsf-termbox-go-0.0~git20160914/_demos/raw_input.go000066400000000000000000000045201277573306300243210ustar00rootroot00000000000000package main import ( "fmt" "github.com/nsf/termbox-go" "strings" ) func tbprint(x, y int, fg, bg termbox.Attribute, msg string) { for _, c := range msg { termbox.SetCell(x, y, c, fg, bg) x++ } } var current string var curev termbox.Event func mouse_button_str(k termbox.Key) string { switch k { case termbox.MouseLeft: return "MouseLeft" case termbox.MouseMiddle: return "MouseMiddle" case termbox.MouseRight: return "MouseRight" case termbox.MouseRelease: return "MouseRelease" case termbox.MouseWheelUp: return "MouseWheelUp" case termbox.MouseWheelDown: return "MouseWheelDown" } return "Key" } func mod_str(m termbox.Modifier) string { var out []string if m&termbox.ModAlt != 0 { out = append(out, "ModAlt") } if m&termbox.ModMotion != 0 { out = append(out, "ModMotion") } return strings.Join(out, " | ") } func redraw_all() { const coldef = termbox.ColorDefault termbox.Clear(coldef, coldef) tbprint(0, 0, termbox.ColorMagenta, coldef, "Press 'q' to quit") tbprint(0, 1, coldef, coldef, current) switch curev.Type { case termbox.EventKey: tbprint(0, 2, coldef, coldef, fmt.Sprintf("EventKey: k: %d, c: %c, mod: %s", curev.Key, curev.Ch, mod_str(curev.Mod))) case termbox.EventMouse: tbprint(0, 2, coldef, coldef, fmt.Sprintf("EventMouse: x: %d, y: %d, b: %s, mod: %s", curev.MouseX, curev.MouseY, mouse_button_str(curev.Key), mod_str(curev.Mod))) case termbox.EventNone: tbprint(0, 2, coldef, coldef, "EventNone") } tbprint(0, 3, coldef, coldef, fmt.Sprintf("%d", curev.N)) termbox.Flush() } func main() { err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() termbox.SetInputMode(termbox.InputAlt | termbox.InputMouse) redraw_all() data := make([]byte, 0, 64) mainloop: for { if cap(data)-len(data) < 32 { newdata := make([]byte, len(data), len(data)+32) copy(newdata, data) data = newdata } beg := len(data) d := data[beg : beg+32] switch ev := termbox.PollRawEvent(d); ev.Type { case termbox.EventRaw: data = data[:beg+ev.N] current = fmt.Sprintf("%q", data) if current == `"q"` { break mainloop } for { ev := termbox.ParseEvent(data) if ev.N == 0 { break } curev = ev copy(data, data[curev.N:]) data = data[:len(data)-curev.N] } case termbox.EventError: panic(ev.Err) } redraw_all() } } golang-github-nsf-termbox-go-0.0~git20160914/api.go000066400000000000000000000273451277573306300216260ustar00rootroot00000000000000// +build !windows package termbox import "github.com/mattn/go-runewidth" import "fmt" import "os" import "os/signal" import "syscall" import "runtime" // public API // Initializes termbox library. This function should be called before any other functions. // After successful initialization, the library must be finalized using 'Close' function. // // Example usage: // err := termbox.Init() // if err != nil { // panic(err) // } // defer termbox.Close() func Init() error { var err error out, err = os.OpenFile("/dev/tty", syscall.O_WRONLY, 0) if err != nil { return err } in, err = syscall.Open("/dev/tty", syscall.O_RDONLY, 0) if err != nil { return err } err = setup_term() if err != nil { return fmt.Errorf("termbox: error while reading terminfo data: %v", err) } signal.Notify(sigwinch, syscall.SIGWINCH) signal.Notify(sigio, syscall.SIGIO) _, err = fcntl(in, syscall.F_SETFL, syscall.O_ASYNC|syscall.O_NONBLOCK) if err != nil { return err } _, err = fcntl(in, syscall.F_SETOWN, syscall.Getpid()) if runtime.GOOS != "darwin" && err != nil { return err } err = tcgetattr(out.Fd(), &orig_tios) if err != nil { return err } tios := orig_tios tios.Iflag &^= syscall_IGNBRK | syscall_BRKINT | syscall_PARMRK | syscall_ISTRIP | syscall_INLCR | syscall_IGNCR | syscall_ICRNL | syscall_IXON tios.Lflag &^= syscall_ECHO | syscall_ECHONL | syscall_ICANON | syscall_ISIG | syscall_IEXTEN tios.Cflag &^= syscall_CSIZE | syscall_PARENB tios.Cflag |= syscall_CS8 tios.Cc[syscall_VMIN] = 1 tios.Cc[syscall_VTIME] = 0 err = tcsetattr(out.Fd(), &tios) if err != nil { return err } out.WriteString(funcs[t_enter_ca]) out.WriteString(funcs[t_enter_keypad]) out.WriteString(funcs[t_hide_cursor]) out.WriteString(funcs[t_clear_screen]) termw, termh = get_term_size(out.Fd()) back_buffer.init(termw, termh) front_buffer.init(termw, termh) back_buffer.clear() front_buffer.clear() go func() { buf := make([]byte, 128) for { select { case <-sigio: for { n, err := syscall.Read(in, buf) if err == syscall.EAGAIN || err == syscall.EWOULDBLOCK { break } select { case input_comm <- input_event{buf[:n], err}: ie := <-input_comm buf = ie.data[:128] case <-quit: return } } case <-quit: return } } }() IsInit = true return nil } // Interrupt an in-progress call to PollEvent by causing it to return // EventInterrupt. Note that this function will block until the PollEvent // function has successfully been interrupted. func Interrupt() { interrupt_comm <- struct{}{} } // Finalizes termbox library, should be called after successful initialization // when termbox's functionality isn't required anymore. func Close() { quit <- 1 out.WriteString(funcs[t_show_cursor]) out.WriteString(funcs[t_sgr0]) out.WriteString(funcs[t_clear_screen]) out.WriteString(funcs[t_exit_ca]) out.WriteString(funcs[t_exit_keypad]) out.WriteString(funcs[t_exit_mouse]) tcsetattr(out.Fd(), &orig_tios) out.Close() syscall.Close(in) // reset the state, so that on next Init() it will work again termw = 0 termh = 0 input_mode = InputEsc out = nil in = 0 lastfg = attr_invalid lastbg = attr_invalid lastx = coord_invalid lasty = coord_invalid cursor_x = cursor_hidden cursor_y = cursor_hidden foreground = ColorDefault background = ColorDefault IsInit = false } // Synchronizes the internal back buffer with the terminal. func Flush() error { // invalidate cursor position lastx = coord_invalid lasty = coord_invalid update_size_maybe() for y := 0; y < front_buffer.height; y++ { line_offset := y * front_buffer.width for x := 0; x < front_buffer.width; { cell_offset := line_offset + x back := &back_buffer.cells[cell_offset] front := &front_buffer.cells[cell_offset] if back.Ch < ' ' { back.Ch = ' ' } w := runewidth.RuneWidth(back.Ch) if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) { w = 1 } if *back == *front { x += w continue } *front = *back send_attr(back.Fg, back.Bg) if w == 2 && x == front_buffer.width-1 { // there's not enough space for 2-cells rune, // let's just put a space in there send_char(x, y, ' ') } else { send_char(x, y, back.Ch) if w == 2 { next := cell_offset + 1 front_buffer.cells[next] = Cell{ Ch: 0, Fg: back.Fg, Bg: back.Bg, } } } x += w } } if !is_cursor_hidden(cursor_x, cursor_y) { write_cursor(cursor_x, cursor_y) } return flush() } // Sets the position of the cursor. See also HideCursor(). func SetCursor(x, y int) { if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) { outbuf.WriteString(funcs[t_show_cursor]) } if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) { outbuf.WriteString(funcs[t_hide_cursor]) } cursor_x, cursor_y = x, y if !is_cursor_hidden(cursor_x, cursor_y) { write_cursor(cursor_x, cursor_y) } } // The shortcut for SetCursor(-1, -1). func HideCursor() { SetCursor(cursor_hidden, cursor_hidden) } // Changes cell's parameters in the internal back buffer at the specified // position. func SetCell(x, y int, ch rune, fg, bg Attribute) { if x < 0 || x >= back_buffer.width { return } if y < 0 || y >= back_buffer.height { return } back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg} } // Returns a slice into the termbox's back buffer. You can get its dimensions // using 'Size' function. The slice remains valid as long as no 'Clear' or // 'Flush' function calls were made after call to this function. func CellBuffer() []Cell { return back_buffer.cells } // After getting a raw event from PollRawEvent function call, you can parse it // again into an ordinary one using termbox logic. That is parse an event as // termbox would do it. Returned event in addition to usual Event struct fields // sets N field to the amount of bytes used within 'data' slice. If the length // of 'data' slice is zero or event cannot be parsed for some other reason, the // function will return a special event type: EventNone. // // IMPORTANT: EventNone may contain a non-zero N, which means you should skip // these bytes, because termbox cannot recognize them. // // NOTE: This API is experimental and may change in future. func ParseEvent(data []byte) Event { event := Event{Type: EventKey} ok := extract_event(data, &event) if !ok { return Event{Type: EventNone, N: event.N} } return event } // Wait for an event and return it. This is a blocking function call. Instead // of EventKey and EventMouse it returns EventRaw events. Raw event is written // into `data` slice and Event's N field is set to the amount of bytes written. // The minimum required length of the 'data' slice is 1. This requirement may // vary on different platforms. // // NOTE: This API is experimental and may change in future. func PollRawEvent(data []byte) Event { if len(data) == 0 { panic("len(data) >= 1 is a requirement") } var event Event if extract_raw_event(data, &event) { return event } for { select { case ev := <-input_comm: if ev.err != nil { return Event{Type: EventError, Err: ev.err} } inbuf = append(inbuf, ev.data...) input_comm <- ev if extract_raw_event(data, &event) { return event } case <-interrupt_comm: event.Type = EventInterrupt return event case <-sigwinch: event.Type = EventResize event.Width, event.Height = get_term_size(out.Fd()) return event } } } // Wait for an event and return it. This is a blocking function call. func PollEvent() Event { var event Event // try to extract event from input buffer, return on success event.Type = EventKey ok := extract_event(inbuf, &event) if event.N != 0 { copy(inbuf, inbuf[event.N:]) inbuf = inbuf[:len(inbuf)-event.N] } if ok { return event } for { select { case ev := <-input_comm: if ev.err != nil { return Event{Type: EventError, Err: ev.err} } inbuf = append(inbuf, ev.data...) input_comm <- ev ok := extract_event(inbuf, &event) if event.N != 0 { copy(inbuf, inbuf[event.N:]) inbuf = inbuf[:len(inbuf)-event.N] } if ok { return event } case <-interrupt_comm: event.Type = EventInterrupt return event case <-sigwinch: event.Type = EventResize event.Width, event.Height = get_term_size(out.Fd()) return event } } panic("unreachable") } // Returns the size of the internal back buffer (which is mostly the same as // terminal's window size in characters). But it doesn't always match the size // of the terminal window, after the terminal size has changed, the internal // back buffer will get in sync only after Clear or Flush function calls. func Size() (width int, height int) { return termw, termh } // Clears the internal back buffer. func Clear(fg, bg Attribute) error { foreground, background = fg, bg err := update_size_maybe() back_buffer.clear() return err } // Sets termbox input mode. Termbox has two input modes: // // 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match // any known sequence. ESC means KeyEsc. This is the default input mode. // // 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match // any known sequence. ESC enables ModAlt modifier for the next keyboard event. // // Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will // enable mouse button press/release and drag events. // // If 'mode' is InputCurrent, returns the current input mode. See also Input* // constants. func SetInputMode(mode InputMode) InputMode { if mode == InputCurrent { return input_mode } if mode&(InputEsc|InputAlt) == 0 { mode |= InputEsc } if mode&(InputEsc|InputAlt) == InputEsc|InputAlt { mode &^= InputAlt } if mode&InputMouse != 0 { out.WriteString(funcs[t_enter_mouse]) } else { out.WriteString(funcs[t_exit_mouse]) } input_mode = mode return input_mode } // Sets the termbox output mode. Termbox has four output options: // // 1. OutputNormal => [1..8] // This mode provides 8 different colors: // black, red, green, yellow, blue, magenta, cyan, white // Shortcut: ColorBlack, ColorRed, ... // Attributes: AttrBold, AttrUnderline, AttrReverse // // Example usage: // SetCell(x, y, '@', ColorBlack | AttrBold, ColorRed); // // 2. Output256 => [1..256] // In this mode you can leverage the 256 terminal mode: // 0x01 - 0x08: the 8 colors as in OutputNormal // 0x09 - 0x10: Color* | AttrBold // 0x11 - 0xe8: 216 different colors // 0xe9 - 0x1ff: 24 different shades of grey // // Example usage: // SetCell(x, y, '@', 184, 240); // SetCell(x, y, '@', 0xb8, 0xf0); // // 3. Output216 => [1..216] // This mode supports the 3rd range of the 256 mode only. // But you dont need to provide an offset. // // 4. OutputGrayscale => [1..26] // This mode supports the 4th range of the 256 mode // and black and white colors from 3th range of the 256 mode // But you dont need to provide an offset. // // In all modes, 0x00 represents the default color. // // `go run _demos/output.go` to see its impact on your terminal. // // If 'mode' is OutputCurrent, it returns the current output mode. // // Note that this may return a different OutputMode than the one requested, // as the requested mode may not be available on the target platform. func SetOutputMode(mode OutputMode) OutputMode { if mode == OutputCurrent { return output_mode } output_mode = mode return output_mode } // Sync comes handy when something causes desync between termbox's understanding // of a terminal buffer and the reality. Such as a third party process. Sync // forces a complete resync between the termbox and a terminal, it may not be // visually pretty though. func Sync() error { front_buffer.clear() err := send_clear() if err != nil { return err } return Flush() } golang-github-nsf-termbox-go-0.0~git20160914/api_common.go000066400000000000000000000105231277573306300231640ustar00rootroot00000000000000// termbox is a library for creating cross-platform text-based interfaces package termbox // public API, common OS agnostic part type ( InputMode int OutputMode int EventType uint8 Modifier uint8 Key uint16 Attribute uint16 ) // This type represents a termbox event. The 'Mod', 'Key' and 'Ch' fields are // valid if 'Type' is EventKey. The 'Width' and 'Height' fields are valid if // 'Type' is EventResize. The 'Err' field is valid if 'Type' is EventError. type Event struct { Type EventType // one of Event* constants Mod Modifier // one of Mod* constants or 0 Key Key // one of Key* constants, invalid if 'Ch' is not 0 Ch rune // a unicode character Width int // width of the screen Height int // height of the screen Err error // error in case if input failed MouseX int // x coord of mouse MouseY int // y coord of mouse N int // number of bytes written when getting a raw event } // A cell, single conceptual entity on the screen. The screen is basically a 2d // array of cells. 'Ch' is a unicode character, 'Fg' and 'Bg' are foreground // and background attributes respectively. type Cell struct { Ch rune Fg Attribute Bg Attribute } // To know if termbox has been initialized or not var ( IsInit bool = false ) // Key constants, see Event.Key field. const ( KeyF1 Key = 0xFFFF - iota KeyF2 KeyF3 KeyF4 KeyF5 KeyF6 KeyF7 KeyF8 KeyF9 KeyF10 KeyF11 KeyF12 KeyInsert KeyDelete KeyHome KeyEnd KeyPgup KeyPgdn KeyArrowUp KeyArrowDown KeyArrowLeft KeyArrowRight key_min // see terminfo MouseLeft MouseMiddle MouseRight MouseRelease MouseWheelUp MouseWheelDown ) const ( KeyCtrlTilde Key = 0x00 KeyCtrl2 Key = 0x00 KeyCtrlSpace Key = 0x00 KeyCtrlA Key = 0x01 KeyCtrlB Key = 0x02 KeyCtrlC Key = 0x03 KeyCtrlD Key = 0x04 KeyCtrlE Key = 0x05 KeyCtrlF Key = 0x06 KeyCtrlG Key = 0x07 KeyBackspace Key = 0x08 KeyCtrlH Key = 0x08 KeyTab Key = 0x09 KeyCtrlI Key = 0x09 KeyCtrlJ Key = 0x0A KeyCtrlK Key = 0x0B KeyCtrlL Key = 0x0C KeyEnter Key = 0x0D KeyCtrlM Key = 0x0D KeyCtrlN Key = 0x0E KeyCtrlO Key = 0x0F KeyCtrlP Key = 0x10 KeyCtrlQ Key = 0x11 KeyCtrlR Key = 0x12 KeyCtrlS Key = 0x13 KeyCtrlT Key = 0x14 KeyCtrlU Key = 0x15 KeyCtrlV Key = 0x16 KeyCtrlW Key = 0x17 KeyCtrlX Key = 0x18 KeyCtrlY Key = 0x19 KeyCtrlZ Key = 0x1A KeyEsc Key = 0x1B KeyCtrlLsqBracket Key = 0x1B KeyCtrl3 Key = 0x1B KeyCtrl4 Key = 0x1C KeyCtrlBackslash Key = 0x1C KeyCtrl5 Key = 0x1D KeyCtrlRsqBracket Key = 0x1D KeyCtrl6 Key = 0x1E KeyCtrl7 Key = 0x1F KeyCtrlSlash Key = 0x1F KeyCtrlUnderscore Key = 0x1F KeySpace Key = 0x20 KeyBackspace2 Key = 0x7F KeyCtrl8 Key = 0x7F ) // Alt modifier constant, see Event.Mod field and SetInputMode function. const ( ModAlt Modifier = 1 << iota ModMotion ) // Cell colors, you can combine a color with multiple attributes using bitwise // OR ('|'). const ( ColorDefault Attribute = iota ColorBlack ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite ) // Cell attributes, it is possible to use multiple attributes by combining them // using bitwise OR ('|'). Although, colors cannot be combined. But you can // combine attributes and a single color. // // It's worth mentioning that some platforms don't support certain attibutes. // For example windows console doesn't support AttrUnderline. And on some // terminals applying AttrBold to background may result in blinking text. Use // them with caution and test your code on various terminals. const ( AttrBold Attribute = 1 << (iota + 9) AttrUnderline AttrReverse ) // Input mode. See SetInputMode function. const ( InputEsc InputMode = 1 << iota InputAlt InputMouse InputCurrent InputMode = 0 ) // Output mode. See SetOutputMode function. const ( OutputCurrent OutputMode = iota OutputNormal Output256 Output216 OutputGrayscale ) // Event type. See Event.Type field. const ( EventKey EventType = iota EventResize EventMouse EventError EventInterrupt EventRaw EventNone ) golang-github-nsf-termbox-go-0.0~git20160914/api_windows.go000066400000000000000000000136221277573306300233710ustar00rootroot00000000000000package termbox import ( "syscall" ) // public API // Initializes termbox library. This function should be called before any other functions. // After successful initialization, the library must be finalized using 'Close' function. // // Example usage: // err := termbox.Init() // if err != nil { // panic(err) // } // defer termbox.Close() func Init() error { var err error interrupt, err = create_event() if err != nil { return err } in, err = syscall.Open("CONIN$", syscall.O_RDWR, 0) if err != nil { return err } out, err = syscall.Open("CONOUT$", syscall.O_RDWR, 0) if err != nil { return err } err = get_console_mode(in, &orig_mode) if err != nil { return err } err = set_console_mode(in, enable_window_input) if err != nil { return err } orig_size = get_term_size(out) win_size := get_win_size(out) err = set_console_screen_buffer_size(out, win_size) if err != nil { return err } err = get_console_cursor_info(out, &orig_cursor_info) if err != nil { return err } show_cursor(false) term_size = get_term_size(out) back_buffer.init(int(term_size.x), int(term_size.y)) front_buffer.init(int(term_size.x), int(term_size.y)) back_buffer.clear() front_buffer.clear() clear() diffbuf = make([]diff_msg, 0, 32) go input_event_producer() IsInit = true return nil } // Finalizes termbox library, should be called after successful initialization // when termbox's functionality isn't required anymore. func Close() { // we ignore errors here, because we can't really do anything about them Clear(0, 0) Flush() // stop event producer cancel_comm <- true set_event(interrupt) select { case <-input_comm: default: } <-cancel_done_comm set_console_cursor_info(out, &orig_cursor_info) set_console_cursor_position(out, coord{}) set_console_screen_buffer_size(out, orig_size) set_console_mode(in, orig_mode) syscall.Close(in) syscall.Close(out) syscall.Close(interrupt) IsInit = false } // Interrupt an in-progress call to PollEvent by causing it to return // EventInterrupt. Note that this function will block until the PollEvent // function has successfully been interrupted. func Interrupt() { interrupt_comm <- struct{}{} } // Synchronizes the internal back buffer with the terminal. func Flush() error { update_size_maybe() prepare_diff_messages() for _, diff := range diffbuf { r := small_rect{ left: 0, top: diff.pos, right: term_size.x - 1, bottom: diff.pos + diff.lines - 1, } write_console_output(out, diff.chars, r) } if !is_cursor_hidden(cursor_x, cursor_y) { move_cursor(cursor_x, cursor_y) } return nil } // Sets the position of the cursor. See also HideCursor(). func SetCursor(x, y int) { if is_cursor_hidden(cursor_x, cursor_y) && !is_cursor_hidden(x, y) { show_cursor(true) } if !is_cursor_hidden(cursor_x, cursor_y) && is_cursor_hidden(x, y) { show_cursor(false) } cursor_x, cursor_y = x, y if !is_cursor_hidden(cursor_x, cursor_y) { move_cursor(cursor_x, cursor_y) } } // The shortcut for SetCursor(-1, -1). func HideCursor() { SetCursor(cursor_hidden, cursor_hidden) } // Changes cell's parameters in the internal back buffer at the specified // position. func SetCell(x, y int, ch rune, fg, bg Attribute) { if x < 0 || x >= back_buffer.width { return } if y < 0 || y >= back_buffer.height { return } back_buffer.cells[y*back_buffer.width+x] = Cell{ch, fg, bg} } // Returns a slice into the termbox's back buffer. You can get its dimensions // using 'Size' function. The slice remains valid as long as no 'Clear' or // 'Flush' function calls were made after call to this function. func CellBuffer() []Cell { return back_buffer.cells } // Wait for an event and return it. This is a blocking function call. func PollEvent() Event { select { case ev := <-input_comm: return ev case <-interrupt_comm: return Event{Type: EventInterrupt} } } // Returns the size of the internal back buffer (which is mostly the same as // console's window size in characters). But it doesn't always match the size // of the console window, after the console size has changed, the internal back // buffer will get in sync only after Clear or Flush function calls. func Size() (int, int) { return int(term_size.x), int(term_size.y) } // Clears the internal back buffer. func Clear(fg, bg Attribute) error { foreground, background = fg, bg update_size_maybe() back_buffer.clear() return nil } // Sets termbox input mode. Termbox has two input modes: // // 1. Esc input mode. When ESC sequence is in the buffer and it doesn't match // any known sequence. ESC means KeyEsc. This is the default input mode. // // 2. Alt input mode. When ESC sequence is in the buffer and it doesn't match // any known sequence. ESC enables ModAlt modifier for the next keyboard event. // // Both input modes can be OR'ed with Mouse mode. Setting Mouse mode bit up will // enable mouse button press/release and drag events. // // If 'mode' is InputCurrent, returns the current input mode. See also Input* // constants. func SetInputMode(mode InputMode) InputMode { if mode == InputCurrent { return input_mode } if mode&InputMouse != 0 { err := set_console_mode(in, enable_window_input|enable_mouse_input|enable_extended_flags) if err != nil { panic(err) } } else { err := set_console_mode(in, enable_window_input) if err != nil { panic(err) } } input_mode = mode return input_mode } // Sets the termbox output mode. // // Windows console does not support extra colour modes, // so this will always set and return OutputNormal. func SetOutputMode(mode OutputMode) OutputMode { return OutputNormal } // Sync comes handy when something causes desync between termbox's understanding // of a terminal buffer and the reality. Such as a third party process. Sync // forces a complete resync between the termbox and a terminal, it may not be // visually pretty though. At the moment on Windows it does nothing. func Sync() error { return nil } golang-github-nsf-termbox-go-0.0~git20160914/collect_terminfo.py000077500000000000000000000037711277573306300244300ustar00rootroot00000000000000#!/usr/bin/env python import sys, os, subprocess def escaped(s): return repr(s)[1:-1] def tput(term, name): try: return subprocess.check_output(['tput', '-T%s' % term, name]).decode() except subprocess.CalledProcessError as e: return e.output.decode() def w(s): if s == None: return sys.stdout.write(s) terminals = { 'xterm' : 'xterm', 'rxvt-256color' : 'rxvt_256color', 'rxvt-unicode' : 'rxvt_unicode', 'linux' : 'linux', 'Eterm' : 'eterm', 'screen' : 'screen' } keys = [ "F1", "kf1", "F2", "kf2", "F3", "kf3", "F4", "kf4", "F5", "kf5", "F6", "kf6", "F7", "kf7", "F8", "kf8", "F9", "kf9", "F10", "kf10", "F11", "kf11", "F12", "kf12", "INSERT", "kich1", "DELETE", "kdch1", "HOME", "khome", "END", "kend", "PGUP", "kpp", "PGDN", "knp", "KEY_UP", "kcuu1", "KEY_DOWN", "kcud1", "KEY_LEFT", "kcub1", "KEY_RIGHT", "kcuf1" ] funcs = [ "T_ENTER_CA", "smcup", "T_EXIT_CA", "rmcup", "T_SHOW_CURSOR", "cnorm", "T_HIDE_CURSOR", "civis", "T_CLEAR_SCREEN", "clear", "T_SGR0", "sgr0", "T_UNDERLINE", "smul", "T_BOLD", "bold", "T_BLINK", "blink", "T_REVERSE", "rev", "T_ENTER_KEYPAD", "smkx", "T_EXIT_KEYPAD", "rmkx" ] def iter_pairs(iterable): iterable = iter(iterable) while True: yield (next(iterable), next(iterable)) def do_term(term, nick): w("// %s\n" % term) w("var %s_keys = []string{\n\t" % nick) for k, v in iter_pairs(keys): w('"') w(escaped(tput(term, v))) w('",') w("\n}\n") w("var %s_funcs = []string{\n\t" % nick) for k,v in iter_pairs(funcs): w('"') if v == "sgr": w("\\033[3%d;4%dm") elif v == "cup": w("\\033[%d;%dH") else: w(escaped(tput(term, v))) w('", ') w("\n}\n\n") def do_terms(d): w("var terms = []struct {\n") w("\tname string\n") w("\tkeys []string\n") w("\tfuncs []string\n") w("}{\n") for k, v in d.items(): w('\t{"%s", %s_keys, %s_funcs},\n' % (k, v, v)) w("}\n\n") w("// +build !windows\n\npackage termbox\n\n") for k,v in terminals.items(): do_term(k, v) do_terms(terminals) golang-github-nsf-termbox-go-0.0~git20160914/syscalls.go000066400000000000000000000014051277573306300226770ustar00rootroot00000000000000// +build ignore package termbox /* #include #include */ import "C" type syscall_Termios C.struct_termios const ( syscall_IGNBRK = C.IGNBRK syscall_BRKINT = C.BRKINT syscall_PARMRK = C.PARMRK syscall_ISTRIP = C.ISTRIP syscall_INLCR = C.INLCR syscall_IGNCR = C.IGNCR syscall_ICRNL = C.ICRNL syscall_IXON = C.IXON syscall_OPOST = C.OPOST syscall_ECHO = C.ECHO syscall_ECHONL = C.ECHONL syscall_ICANON = C.ICANON syscall_ISIG = C.ISIG syscall_IEXTEN = C.IEXTEN syscall_CSIZE = C.CSIZE syscall_PARENB = C.PARENB syscall_CS8 = C.CS8 syscall_VMIN = C.VMIN syscall_VTIME = C.VTIME // on darwin change these to (on *bsd too?): // C.TIOCGETA // C.TIOCSETA syscall_TCGETS = C.TCGETS syscall_TCSETS = C.TCSETS ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_darwin.go000066400000000000000000000013611277573306300242440ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go // +build !amd64 package termbox type syscall_Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 Ispeed uint32 Ospeed uint32 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x402c7413 syscall_TCSETS = 0x802c7414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_darwin_amd64.go000066400000000000000000000014071277573306300252400ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox type syscall_Termios struct { Iflag uint64 Oflag uint64 Cflag uint64 Lflag uint64 Cc [20]uint8 Pad_cgo_0 [4]byte Ispeed uint64 Ospeed uint64 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x40487413 syscall_TCSETS = 0x80487414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_dragonfly.go000066400000000000000000000013371277573306300247500ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox type syscall_Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 Ispeed uint32 Ospeed uint32 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x402c7413 syscall_TCSETS = 0x802c7414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_freebsd.go000066400000000000000000000013371277573306300243750ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox type syscall_Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 Ispeed uint32 Ospeed uint32 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x402c7413 syscall_TCSETS = 0x802c7414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_linux.go000066400000000000000000000014741277573306300241240ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox import "syscall" type syscall_Termios syscall.Termios const ( syscall_IGNBRK = syscall.IGNBRK syscall_BRKINT = syscall.BRKINT syscall_PARMRK = syscall.PARMRK syscall_ISTRIP = syscall.ISTRIP syscall_INLCR = syscall.INLCR syscall_IGNCR = syscall.IGNCR syscall_ICRNL = syscall.ICRNL syscall_IXON = syscall.IXON syscall_OPOST = syscall.OPOST syscall_ECHO = syscall.ECHO syscall_ECHONL = syscall.ECHONL syscall_ICANON = syscall.ICANON syscall_ISIG = syscall.ISIG syscall_IEXTEN = syscall.IEXTEN syscall_CSIZE = syscall.CSIZE syscall_PARENB = syscall.PARENB syscall_CS8 = syscall.CS8 syscall_VMIN = syscall.VMIN syscall_VTIME = syscall.VTIME syscall_TCGETS = syscall.TCGETS syscall_TCSETS = syscall.TCSETS ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_netbsd.go000066400000000000000000000013351277573306300242400ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox type syscall_Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 Ispeed int32 Ospeed int32 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x402c7413 syscall_TCSETS = 0x802c7414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_openbsd.go000066400000000000000000000013351277573306300244130ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs syscalls.go package termbox type syscall_Termios struct { Iflag uint32 Oflag uint32 Cflag uint32 Lflag uint32 Cc [20]uint8 Ispeed int32 Ospeed int32 } const ( syscall_IGNBRK = 0x1 syscall_BRKINT = 0x2 syscall_PARMRK = 0x8 syscall_ISTRIP = 0x20 syscall_INLCR = 0x40 syscall_IGNCR = 0x80 syscall_ICRNL = 0x100 syscall_IXON = 0x200 syscall_OPOST = 0x1 syscall_ECHO = 0x8 syscall_ECHONL = 0x10 syscall_ICANON = 0x100 syscall_ISIG = 0x80 syscall_IEXTEN = 0x400 syscall_CSIZE = 0x300 syscall_PARENB = 0x1000 syscall_CS8 = 0x300 syscall_VMIN = 0x10 syscall_VTIME = 0x11 syscall_TCGETS = 0x402c7413 syscall_TCSETS = 0x802c7414 ) golang-github-nsf-termbox-go-0.0~git20160914/syscalls_windows.go000066400000000000000000000027171277573306300244600ustar00rootroot00000000000000// Created by cgo -godefs - DO NOT EDIT // cgo -godefs -- -DUNICODE syscalls.go package termbox const ( foreground_blue = 0x1 foreground_green = 0x2 foreground_red = 0x4 foreground_intensity = 0x8 background_blue = 0x10 background_green = 0x20 background_red = 0x40 background_intensity = 0x80 std_input_handle = -0xa std_output_handle = -0xb key_event = 0x1 mouse_event = 0x2 window_buffer_size_event = 0x4 enable_window_input = 0x8 enable_mouse_input = 0x10 enable_extended_flags = 0x80 vk_f1 = 0x70 vk_f2 = 0x71 vk_f3 = 0x72 vk_f4 = 0x73 vk_f5 = 0x74 vk_f6 = 0x75 vk_f7 = 0x76 vk_f8 = 0x77 vk_f9 = 0x78 vk_f10 = 0x79 vk_f11 = 0x7a vk_f12 = 0x7b vk_insert = 0x2d vk_delete = 0x2e vk_home = 0x24 vk_end = 0x23 vk_pgup = 0x21 vk_pgdn = 0x22 vk_arrow_up = 0x26 vk_arrow_down = 0x28 vk_arrow_left = 0x25 vk_arrow_right = 0x27 vk_backspace = 0x8 vk_tab = 0x9 vk_enter = 0xd vk_esc = 0x1b vk_space = 0x20 left_alt_pressed = 0x2 left_ctrl_pressed = 0x8 right_alt_pressed = 0x1 right_ctrl_pressed = 0x4 shift_pressed = 0x10 generic_read = 0x80000000 generic_write = 0x40000000 console_textmode_buffer = 0x1 ) golang-github-nsf-termbox-go-0.0~git20160914/termbox.go000066400000000000000000000255041277573306300225300ustar00rootroot00000000000000// +build !windows package termbox import "unicode/utf8" import "bytes" import "syscall" import "unsafe" import "strings" import "strconv" import "os" import "io" // private API const ( t_enter_ca = iota t_exit_ca t_show_cursor t_hide_cursor t_clear_screen t_sgr0 t_underline t_bold t_blink t_reverse t_enter_keypad t_exit_keypad t_enter_mouse t_exit_mouse t_max_funcs ) const ( coord_invalid = -2 attr_invalid = Attribute(0xFFFF) ) type input_event struct { data []byte err error } var ( // term specific sequences keys []string funcs []string // termbox inner state orig_tios syscall_Termios back_buffer cellbuf front_buffer cellbuf termw int termh int input_mode = InputEsc output_mode = OutputNormal out *os.File in int lastfg = attr_invalid lastbg = attr_invalid lastx = coord_invalid lasty = coord_invalid cursor_x = cursor_hidden cursor_y = cursor_hidden foreground = ColorDefault background = ColorDefault inbuf = make([]byte, 0, 64) outbuf bytes.Buffer sigwinch = make(chan os.Signal, 1) sigio = make(chan os.Signal, 1) quit = make(chan int) input_comm = make(chan input_event) interrupt_comm = make(chan struct{}) intbuf = make([]byte, 0, 16) // grayscale indexes grayscale = []Attribute{ 0, 17, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 232, } ) func write_cursor(x, y int) { outbuf.WriteString("\033[") outbuf.Write(strconv.AppendUint(intbuf, uint64(y+1), 10)) outbuf.WriteString(";") outbuf.Write(strconv.AppendUint(intbuf, uint64(x+1), 10)) outbuf.WriteString("H") } func write_sgr_fg(a Attribute) { switch output_mode { case Output256, Output216, OutputGrayscale: outbuf.WriteString("\033[38;5;") outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10)) outbuf.WriteString("m") default: outbuf.WriteString("\033[3") outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10)) outbuf.WriteString("m") } } func write_sgr_bg(a Attribute) { switch output_mode { case Output256, Output216, OutputGrayscale: outbuf.WriteString("\033[48;5;") outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10)) outbuf.WriteString("m") default: outbuf.WriteString("\033[4") outbuf.Write(strconv.AppendUint(intbuf, uint64(a-1), 10)) outbuf.WriteString("m") } } func write_sgr(fg, bg Attribute) { switch output_mode { case Output256, Output216, OutputGrayscale: outbuf.WriteString("\033[38;5;") outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10)) outbuf.WriteString("m") outbuf.WriteString("\033[48;5;") outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10)) outbuf.WriteString("m") default: outbuf.WriteString("\033[3") outbuf.Write(strconv.AppendUint(intbuf, uint64(fg-1), 10)) outbuf.WriteString(";4") outbuf.Write(strconv.AppendUint(intbuf, uint64(bg-1), 10)) outbuf.WriteString("m") } } type winsize struct { rows uint16 cols uint16 xpixels uint16 ypixels uint16 } func get_term_size(fd uintptr) (int, int) { var sz winsize _, _, _ = syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall.TIOCGWINSZ), uintptr(unsafe.Pointer(&sz))) return int(sz.cols), int(sz.rows) } func send_attr(fg, bg Attribute) { if fg == lastfg && bg == lastbg { return } outbuf.WriteString(funcs[t_sgr0]) var fgcol, bgcol Attribute switch output_mode { case Output256: fgcol = fg & 0x1FF bgcol = bg & 0x1FF case Output216: fgcol = fg & 0xFF bgcol = bg & 0xFF if fgcol > 216 { fgcol = ColorDefault } if bgcol > 216 { bgcol = ColorDefault } if fgcol != ColorDefault { fgcol += 0x10 } if bgcol != ColorDefault { bgcol += 0x10 } case OutputGrayscale: fgcol = fg & 0x1F bgcol = bg & 0x1F if fgcol > 26 { fgcol = ColorDefault } if bgcol > 26 { bgcol = ColorDefault } if fgcol != ColorDefault { fgcol = grayscale[fgcol] } if bgcol != ColorDefault { bgcol = grayscale[bgcol] } default: fgcol = fg & 0x0F bgcol = bg & 0x0F } if fgcol != ColorDefault { if bgcol != ColorDefault { write_sgr(fgcol, bgcol) } else { write_sgr_fg(fgcol) } } else if bgcol != ColorDefault { write_sgr_bg(bgcol) } if fg&AttrBold != 0 { outbuf.WriteString(funcs[t_bold]) } if bg&AttrBold != 0 { outbuf.WriteString(funcs[t_blink]) } if fg&AttrUnderline != 0 { outbuf.WriteString(funcs[t_underline]) } if fg&AttrReverse|bg&AttrReverse != 0 { outbuf.WriteString(funcs[t_reverse]) } lastfg, lastbg = fg, bg } func send_char(x, y int, ch rune) { var buf [8]byte n := utf8.EncodeRune(buf[:], ch) if x-1 != lastx || y != lasty { write_cursor(x, y) } lastx, lasty = x, y outbuf.Write(buf[:n]) } func flush() error { _, err := io.Copy(out, &outbuf) outbuf.Reset() if err != nil { return err } return nil } func send_clear() error { send_attr(foreground, background) outbuf.WriteString(funcs[t_clear_screen]) if !is_cursor_hidden(cursor_x, cursor_y) { write_cursor(cursor_x, cursor_y) } // we need to invalidate cursor position too and these two vars are // used only for simple cursor positioning optimization, cursor // actually may be in the correct place, but we simply discard // optimization once and it gives us simple solution for the case when // cursor moved lastx = coord_invalid lasty = coord_invalid return flush() } func update_size_maybe() error { w, h := get_term_size(out.Fd()) if w != termw || h != termh { termw, termh = w, h back_buffer.resize(termw, termh) front_buffer.resize(termw, termh) front_buffer.clear() return send_clear() } return nil } func tcsetattr(fd uintptr, termios *syscall_Termios) error { r, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall_TCSETS), uintptr(unsafe.Pointer(termios))) if r != 0 { return os.NewSyscallError("SYS_IOCTL", e) } return nil } func tcgetattr(fd uintptr, termios *syscall_Termios) error { r, _, e := syscall.Syscall(syscall.SYS_IOCTL, fd, uintptr(syscall_TCGETS), uintptr(unsafe.Pointer(termios))) if r != 0 { return os.NewSyscallError("SYS_IOCTL", e) } return nil } func parse_mouse_event(event *Event, buf string) (int, bool) { if strings.HasPrefix(buf, "\033[M") && len(buf) >= 6 { // X10 mouse encoding, the simplest one // \033 [ M Cb Cx Cy b := buf[3] - 32 switch b & 3 { case 0: if b&64 != 0 { event.Key = MouseWheelUp } else { event.Key = MouseLeft } case 1: if b&64 != 0 { event.Key = MouseWheelDown } else { event.Key = MouseMiddle } case 2: event.Key = MouseRight case 3: event.Key = MouseRelease default: return 6, false } event.Type = EventMouse // KeyEvent by default if b&32 != 0 { event.Mod |= ModMotion } // the coord is 1,1 for upper left event.MouseX = int(buf[4]) - 1 - 32 event.MouseY = int(buf[5]) - 1 - 32 return 6, true } else if strings.HasPrefix(buf, "\033[<") || strings.HasPrefix(buf, "\033[") { // xterm 1006 extended mode or urxvt 1015 extended mode // xterm: \033 [ < Cb ; Cx ; Cy (M or m) // urxvt: \033 [ Cb ; Cx ; Cy M // find the first M or m, that's where we stop mi := strings.IndexAny(buf, "Mm") if mi == -1 { return 0, false } // whether it's a capital M or not isM := buf[mi] == 'M' // whether it's urxvt or not isU := false // buf[2] is safe here, because having M or m found means we have at // least 3 bytes in a string if buf[2] == '<' { buf = buf[3:mi] } else { isU = true buf = buf[2:mi] } s1 := strings.Index(buf, ";") s2 := strings.LastIndex(buf, ";") // not found or only one ';' if s1 == -1 || s2 == -1 || s1 == s2 { return 0, false } n1, err := strconv.ParseInt(buf[0:s1], 10, 64) if err != nil { return 0, false } n2, err := strconv.ParseInt(buf[s1+1:s2], 10, 64) if err != nil { return 0, false } n3, err := strconv.ParseInt(buf[s2+1:], 10, 64) if err != nil { return 0, false } // on urxvt, first number is encoded exactly as in X10, but we need to // make it zero-based, on xterm it is zero-based already if isU { n1 -= 32 } switch n1 & 3 { case 0: if n1&64 != 0 { event.Key = MouseWheelUp } else { event.Key = MouseLeft } case 1: if n1&64 != 0 { event.Key = MouseWheelDown } else { event.Key = MouseMiddle } case 2: event.Key = MouseRight case 3: event.Key = MouseRelease default: return mi + 1, false } if !isM { // on xterm mouse release is signaled by lowercase m event.Key = MouseRelease } event.Type = EventMouse // KeyEvent by default if n1&32 != 0 { event.Mod |= ModMotion } event.MouseX = int(n2) - 1 event.MouseY = int(n3) - 1 return mi + 1, true } return 0, false } func parse_escape_sequence(event *Event, buf []byte) (int, bool) { bufstr := string(buf) for i, key := range keys { if strings.HasPrefix(bufstr, key) { event.Ch = 0 event.Key = Key(0xFFFF - i) return len(key), true } } // if none of the keys match, let's try mouse seqences return parse_mouse_event(event, bufstr) } func extract_raw_event(data []byte, event *Event) bool { if len(inbuf) == 0 { return false } n := len(data) if n == 0 { return false } n = copy(data, inbuf) copy(inbuf, inbuf[n:]) inbuf = inbuf[:len(inbuf)-n] event.N = n event.Type = EventRaw return true } func extract_event(inbuf []byte, event *Event) bool { if len(inbuf) == 0 { event.N = 0 return false } if inbuf[0] == '\033' { // possible escape sequence if n, ok := parse_escape_sequence(event, inbuf); n != 0 { event.N = n return ok } // it's not escape sequence, then it's Alt or Esc, check input_mode switch { case input_mode&InputEsc != 0: // if we're in escape mode, fill Esc event, pop buffer, return success event.Ch = 0 event.Key = KeyEsc event.Mod = 0 event.N = 1 return true case input_mode&InputAlt != 0: // if we're in alt mode, set Alt modifier to event and redo parsing event.Mod = ModAlt ok := extract_event(inbuf[1:], event) if ok { event.N++ } else { event.N = 0 } return ok default: panic("unreachable") } } // if we're here, this is not an escape sequence and not an alt sequence // so, it's a FUNCTIONAL KEY or a UNICODE character // first of all check if it's a functional key if Key(inbuf[0]) <= KeySpace || Key(inbuf[0]) == KeyBackspace2 { // fill event, pop buffer, return success event.Ch = 0 event.Key = Key(inbuf[0]) event.N = 1 return true } // the only possible option is utf8 rune if r, n := utf8.DecodeRune(inbuf); r != utf8.RuneError { event.Ch = r event.Key = 0 event.N = n return true } return false } func fcntl(fd int, cmd int, arg int) (val int, err error) { r, _, e := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), uintptr(cmd), uintptr(arg)) val = int(r) if e != 0 { err = e } return } golang-github-nsf-termbox-go-0.0~git20160914/termbox_common.go000066400000000000000000000017421277573306300240760ustar00rootroot00000000000000package termbox // private API, common OS agnostic part type cellbuf struct { width int height int cells []Cell } func (this *cellbuf) init(width, height int) { this.width = width this.height = height this.cells = make([]Cell, width*height) } func (this *cellbuf) resize(width, height int) { if this.width == width && this.height == height { return } oldw := this.width oldh := this.height oldcells := this.cells this.init(width, height) this.clear() minw, minh := oldw, oldh if width < minw { minw = width } if height < minh { minh = height } for i := 0; i < minh; i++ { srco, dsto := i*oldw, i*width src := oldcells[srco : srco+minw] dst := this.cells[dsto : dsto+minw] copy(dst, src) } } func (this *cellbuf) clear() { for i := range this.cells { c := &this.cells[i] c.Ch = ' ' c.Fg = foreground c.Bg = background } } const cursor_hidden = -1 func is_cursor_hidden(x, y int) bool { return x == cursor_hidden || y == cursor_hidden } golang-github-nsf-termbox-go-0.0~git20160914/termbox_windows.go000066400000000000000000000476011277573306300243040ustar00rootroot00000000000000package termbox import "syscall" import "unsafe" import "unicode/utf16" import "github.com/mattn/go-runewidth" type ( wchar uint16 short int16 dword uint32 word uint16 char_info struct { char wchar attr word } coord struct { x short y short } small_rect struct { left short top short right short bottom short } console_screen_buffer_info struct { size coord cursor_position coord attributes word window small_rect maximum_window_size coord } console_cursor_info struct { size dword visible int32 } input_record struct { event_type word _ [2]byte event [16]byte } key_event_record struct { key_down int32 repeat_count word virtual_key_code word virtual_scan_code word unicode_char wchar control_key_state dword } window_buffer_size_record struct { size coord } mouse_event_record struct { mouse_pos coord button_state dword control_key_state dword event_flags dword } ) const ( mouse_lmb = 0x1 mouse_rmb = 0x2 mouse_mmb = 0x4 | 0x8 | 0x10 ) func (this coord) uintptr() uintptr { return uintptr(*(*int32)(unsafe.Pointer(&this))) } var kernel32 = syscall.NewLazyDLL("kernel32.dll") var is_cjk = runewidth.IsEastAsian() var ( proc_set_console_active_screen_buffer = kernel32.NewProc("SetConsoleActiveScreenBuffer") proc_set_console_screen_buffer_size = kernel32.NewProc("SetConsoleScreenBufferSize") proc_create_console_screen_buffer = kernel32.NewProc("CreateConsoleScreenBuffer") proc_get_console_screen_buffer_info = kernel32.NewProc("GetConsoleScreenBufferInfo") proc_write_console_output = kernel32.NewProc("WriteConsoleOutputW") proc_write_console_output_character = kernel32.NewProc("WriteConsoleOutputCharacterW") proc_write_console_output_attribute = kernel32.NewProc("WriteConsoleOutputAttribute") proc_set_console_cursor_info = kernel32.NewProc("SetConsoleCursorInfo") proc_set_console_cursor_position = kernel32.NewProc("SetConsoleCursorPosition") proc_get_console_cursor_info = kernel32.NewProc("GetConsoleCursorInfo") proc_read_console_input = kernel32.NewProc("ReadConsoleInputW") proc_get_console_mode = kernel32.NewProc("GetConsoleMode") proc_set_console_mode = kernel32.NewProc("SetConsoleMode") proc_fill_console_output_character = kernel32.NewProc("FillConsoleOutputCharacterW") proc_fill_console_output_attribute = kernel32.NewProc("FillConsoleOutputAttribute") proc_create_event = kernel32.NewProc("CreateEventW") proc_wait_for_multiple_objects = kernel32.NewProc("WaitForMultipleObjects") proc_set_event = kernel32.NewProc("SetEvent") ) func set_console_active_screen_buffer(h syscall.Handle) (err error) { r0, _, e1 := syscall.Syscall(proc_set_console_active_screen_buffer.Addr(), 1, uintptr(h), 0, 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func set_console_screen_buffer_size(h syscall.Handle, size coord) (err error) { r0, _, e1 := syscall.Syscall(proc_set_console_screen_buffer_size.Addr(), 2, uintptr(h), size.uintptr(), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func create_console_screen_buffer() (h syscall.Handle, err error) { r0, _, e1 := syscall.Syscall6(proc_create_console_screen_buffer.Addr(), 5, uintptr(generic_read|generic_write), 0, 0, console_textmode_buffer, 0, 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return syscall.Handle(r0), err } func get_console_screen_buffer_info(h syscall.Handle, info *console_screen_buffer_info) (err error) { r0, _, e1 := syscall.Syscall(proc_get_console_screen_buffer_info.Addr(), 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func write_console_output(h syscall.Handle, chars []char_info, dst small_rect) (err error) { tmp_coord = coord{dst.right - dst.left + 1, dst.bottom - dst.top + 1} tmp_rect = dst r0, _, e1 := syscall.Syscall6(proc_write_console_output.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), tmp_coord.uintptr(), tmp_coord0.uintptr(), uintptr(unsafe.Pointer(&tmp_rect)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func write_console_output_character(h syscall.Handle, chars []wchar, pos coord) (err error) { r0, _, e1 := syscall.Syscall6(proc_write_console_output_character.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(&chars[0])), uintptr(len(chars)), pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func write_console_output_attribute(h syscall.Handle, attrs []word, pos coord) (err error) { r0, _, e1 := syscall.Syscall6(proc_write_console_output_attribute.Addr(), 5, uintptr(h), uintptr(unsafe.Pointer(&attrs[0])), uintptr(len(attrs)), pos.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func set_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) { r0, _, e1 := syscall.Syscall(proc_set_console_cursor_info.Addr(), 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func get_console_cursor_info(h syscall.Handle, info *console_cursor_info) (err error) { r0, _, e1 := syscall.Syscall(proc_get_console_cursor_info.Addr(), 2, uintptr(h), uintptr(unsafe.Pointer(info)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func set_console_cursor_position(h syscall.Handle, pos coord) (err error) { r0, _, e1 := syscall.Syscall(proc_set_console_cursor_position.Addr(), 2, uintptr(h), pos.uintptr(), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func read_console_input(h syscall.Handle, record *input_record) (err error) { r0, _, e1 := syscall.Syscall6(proc_read_console_input.Addr(), 4, uintptr(h), uintptr(unsafe.Pointer(record)), 1, uintptr(unsafe.Pointer(&tmp_arg)), 0, 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func get_console_mode(h syscall.Handle, mode *dword) (err error) { r0, _, e1 := syscall.Syscall(proc_get_console_mode.Addr(), 2, uintptr(h), uintptr(unsafe.Pointer(mode)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func set_console_mode(h syscall.Handle, mode dword) (err error) { r0, _, e1 := syscall.Syscall(proc_set_console_mode.Addr(), 2, uintptr(h), uintptr(mode), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func fill_console_output_character(h syscall.Handle, char wchar, n int) (err error) { r0, _, e1 := syscall.Syscall6(proc_fill_console_output_character.Addr(), 5, uintptr(h), uintptr(char), uintptr(n), tmp_coord.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func fill_console_output_attribute(h syscall.Handle, attr word, n int) (err error) { r0, _, e1 := syscall.Syscall6(proc_fill_console_output_attribute.Addr(), 5, uintptr(h), uintptr(attr), uintptr(n), tmp_coord.uintptr(), uintptr(unsafe.Pointer(&tmp_arg)), 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func create_event() (out syscall.Handle, err error) { r0, _, e1 := syscall.Syscall6(proc_create_event.Addr(), 4, 0, 0, 0, 0, 0, 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return syscall.Handle(r0), err } func wait_for_multiple_objects(objects []syscall.Handle) (err error) { r0, _, e1 := syscall.Syscall6(proc_wait_for_multiple_objects.Addr(), 4, uintptr(len(objects)), uintptr(unsafe.Pointer(&objects[0])), 0, 0xFFFFFFFF, 0, 0) if uint32(r0) == 0xFFFFFFFF { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } func set_event(ev syscall.Handle) (err error) { r0, _, e1 := syscall.Syscall(proc_set_event.Addr(), 1, uintptr(ev), 0, 0) if int(r0) == 0 { if e1 != 0 { err = error(e1) } else { err = syscall.EINVAL } } return } type diff_msg struct { pos short lines short chars []char_info } type input_event struct { event Event err error } var ( orig_cursor_info console_cursor_info orig_size coord orig_mode dword orig_screen syscall.Handle back_buffer cellbuf front_buffer cellbuf term_size coord input_mode = InputEsc cursor_x = cursor_hidden cursor_y = cursor_hidden foreground = ColorDefault background = ColorDefault in syscall.Handle out syscall.Handle interrupt syscall.Handle charbuf []char_info diffbuf []diff_msg beg_x = -1 beg_y = -1 beg_i = -1 input_comm = make(chan Event) interrupt_comm = make(chan struct{}) cancel_comm = make(chan bool, 1) cancel_done_comm = make(chan bool) alt_mode_esc = false // these ones just to prevent heap allocs at all costs tmp_info console_screen_buffer_info tmp_arg dword tmp_coord0 = coord{0, 0} tmp_coord = coord{0, 0} tmp_rect = small_rect{0, 0, 0, 0} ) func get_cursor_position(out syscall.Handle) coord { err := get_console_screen_buffer_info(out, &tmp_info) if err != nil { panic(err) } return tmp_info.cursor_position } func get_term_size(out syscall.Handle) coord { err := get_console_screen_buffer_info(out, &tmp_info) if err != nil { panic(err) } return tmp_info.size } func get_win_size(out syscall.Handle) coord { err := get_console_screen_buffer_info(out, &tmp_info) if err != nil { panic(err) } return coord{ x: tmp_info.window.right - tmp_info.window.left + 1, y: tmp_info.window.bottom - tmp_info.window.top + 1, } } func update_size_maybe() { size := get_term_size(out) if size.x != term_size.x || size.y != term_size.y { term_size = size back_buffer.resize(int(size.x), int(size.y)) front_buffer.resize(int(size.x), int(size.y)) front_buffer.clear() clear() area := int(size.x) * int(size.y) if cap(charbuf) < area { charbuf = make([]char_info, 0, area) } } } var color_table_bg = []word{ 0, // default (black) 0, // black background_red, background_green, background_red | background_green, // yellow background_blue, background_red | background_blue, // magenta background_green | background_blue, // cyan background_red | background_blue | background_green, // white } var color_table_fg = []word{ foreground_red | foreground_blue | foreground_green, // default (white) 0, foreground_red, foreground_green, foreground_red | foreground_green, // yellow foreground_blue, foreground_red | foreground_blue, // magenta foreground_green | foreground_blue, // cyan foreground_red | foreground_blue | foreground_green, // white } const ( replacement_char = '\uFFFD' max_rune = '\U0010FFFF' surr1 = 0xd800 surr2 = 0xdc00 surr3 = 0xe000 surr_self = 0x10000 ) func append_diff_line(y int) int { n := 0 for x := 0; x < front_buffer.width; { cell_offset := y*front_buffer.width + x back := &back_buffer.cells[cell_offset] front := &front_buffer.cells[cell_offset] attr, char := cell_to_char_info(*back) charbuf = append(charbuf, char_info{attr: attr, char: char[0]}) *front = *back n++ w := runewidth.RuneWidth(back.Ch) if w == 0 || w == 2 && runewidth.IsAmbiguousWidth(back.Ch) { w = 1 } x += w // If not CJK, fill trailing space with whitespace if !is_cjk && w == 2 { charbuf = append(charbuf, char_info{attr: attr, char: ' '}) } } return n } // compares 'back_buffer' with 'front_buffer' and prepares all changes in the form of // 'diff_msg's in the 'diff_buf' func prepare_diff_messages() { // clear buffers diffbuf = diffbuf[:0] charbuf = charbuf[:0] var diff diff_msg gbeg := 0 for y := 0; y < front_buffer.height; y++ { same := true line_offset := y * front_buffer.width for x := 0; x < front_buffer.width; x++ { cell_offset := line_offset + x back := &back_buffer.cells[cell_offset] front := &front_buffer.cells[cell_offset] if *back != *front { same = false break } } if same && diff.lines > 0 { diffbuf = append(diffbuf, diff) diff = diff_msg{} } if !same { beg := len(charbuf) end := beg + append_diff_line(y) if diff.lines == 0 { diff.pos = short(y) gbeg = beg } diff.lines++ diff.chars = charbuf[gbeg:end] } } if diff.lines > 0 { diffbuf = append(diffbuf, diff) diff = diff_msg{} } } func get_ct(table []word, idx int) word { idx = idx & 0x0F if idx >= len(table) { idx = len(table) - 1 } return table[idx] } func cell_to_char_info(c Cell) (attr word, wc [2]wchar) { attr = get_ct(color_table_fg, int(c.Fg)) | get_ct(color_table_bg, int(c.Bg)) if c.Fg&AttrReverse|c.Bg&AttrReverse != 0 { attr = (attr&0xF0)>>4 | (attr&0x0F)<<4 } if c.Fg&AttrBold != 0 { attr |= foreground_intensity } if c.Bg&AttrBold != 0 { attr |= background_intensity } r0, r1 := utf16.EncodeRune(c.Ch) if r0 == 0xFFFD { wc[0] = wchar(c.Ch) wc[1] = ' ' } else { wc[0] = wchar(r0) wc[1] = wchar(r1) } return } func move_cursor(x, y int) { err := set_console_cursor_position(out, coord{short(x), short(y)}) if err != nil { panic(err) } } func show_cursor(visible bool) { var v int32 if visible { v = 1 } var info console_cursor_info info.size = 100 info.visible = v err := set_console_cursor_info(out, &info) if err != nil { panic(err) } } func clear() { var err error attr, char := cell_to_char_info(Cell{ ' ', foreground, background, }) area := int(term_size.x) * int(term_size.y) err = fill_console_output_attribute(out, attr, area) if err != nil { panic(err) } err = fill_console_output_character(out, char[0], area) if err != nil { panic(err) } if !is_cursor_hidden(cursor_x, cursor_y) { move_cursor(cursor_x, cursor_y) } } func key_event_record_to_event(r *key_event_record) (Event, bool) { if r.key_down == 0 { return Event{}, false } e := Event{Type: EventKey} if input_mode&InputAlt != 0 { if alt_mode_esc { e.Mod = ModAlt alt_mode_esc = false } if r.control_key_state&(left_alt_pressed|right_alt_pressed) != 0 { e.Mod = ModAlt } } ctrlpressed := r.control_key_state&(left_ctrl_pressed|right_ctrl_pressed) != 0 if r.virtual_key_code >= vk_f1 && r.virtual_key_code <= vk_f12 { switch r.virtual_key_code { case vk_f1: e.Key = KeyF1 case vk_f2: e.Key = KeyF2 case vk_f3: e.Key = KeyF3 case vk_f4: e.Key = KeyF4 case vk_f5: e.Key = KeyF5 case vk_f6: e.Key = KeyF6 case vk_f7: e.Key = KeyF7 case vk_f8: e.Key = KeyF8 case vk_f9: e.Key = KeyF9 case vk_f10: e.Key = KeyF10 case vk_f11: e.Key = KeyF11 case vk_f12: e.Key = KeyF12 default: panic("unreachable") } return e, true } if r.virtual_key_code <= vk_delete { switch r.virtual_key_code { case vk_insert: e.Key = KeyInsert case vk_delete: e.Key = KeyDelete case vk_home: e.Key = KeyHome case vk_end: e.Key = KeyEnd case vk_pgup: e.Key = KeyPgup case vk_pgdn: e.Key = KeyPgdn case vk_arrow_up: e.Key = KeyArrowUp case vk_arrow_down: e.Key = KeyArrowDown case vk_arrow_left: e.Key = KeyArrowLeft case vk_arrow_right: e.Key = KeyArrowRight case vk_backspace: if ctrlpressed { e.Key = KeyBackspace2 } else { e.Key = KeyBackspace } case vk_tab: e.Key = KeyTab case vk_enter: e.Key = KeyEnter case vk_esc: switch { case input_mode&InputEsc != 0: e.Key = KeyEsc case input_mode&InputAlt != 0: alt_mode_esc = true return Event{}, false } case vk_space: if ctrlpressed { // manual return here, because KeyCtrlSpace is zero e.Key = KeyCtrlSpace return e, true } else { e.Key = KeySpace } } if e.Key != 0 { return e, true } } if ctrlpressed { if Key(r.unicode_char) >= KeyCtrlA && Key(r.unicode_char) <= KeyCtrlRsqBracket { e.Key = Key(r.unicode_char) if input_mode&InputAlt != 0 && e.Key == KeyEsc { alt_mode_esc = true return Event{}, false } return e, true } switch r.virtual_key_code { case 192, 50: // manual return here, because KeyCtrl2 is zero e.Key = KeyCtrl2 return e, true case 51: if input_mode&InputAlt != 0 { alt_mode_esc = true return Event{}, false } e.Key = KeyCtrl3 case 52: e.Key = KeyCtrl4 case 53: e.Key = KeyCtrl5 case 54: e.Key = KeyCtrl6 case 189, 191, 55: e.Key = KeyCtrl7 case 8, 56: e.Key = KeyCtrl8 } if e.Key != 0 { return e, true } } if r.unicode_char != 0 { e.Ch = rune(r.unicode_char) return e, true } return Event{}, false } func input_event_producer() { var r input_record var err error var last_button Key var last_button_pressed Key var last_state = dword(0) var last_x, last_y = -1, -1 handles := []syscall.Handle{in, interrupt} for { err = wait_for_multiple_objects(handles) if err != nil { input_comm <- Event{Type: EventError, Err: err} } select { case <-cancel_comm: cancel_done_comm <- true return default: } err = read_console_input(in, &r) if err != nil { input_comm <- Event{Type: EventError, Err: err} } switch r.event_type { case key_event: kr := (*key_event_record)(unsafe.Pointer(&r.event)) ev, ok := key_event_record_to_event(kr) if ok { for i := 0; i < int(kr.repeat_count); i++ { input_comm <- ev } } case window_buffer_size_event: sr := *(*window_buffer_size_record)(unsafe.Pointer(&r.event)) input_comm <- Event{ Type: EventResize, Width: int(sr.size.x), Height: int(sr.size.y), } case mouse_event: mr := *(*mouse_event_record)(unsafe.Pointer(&r.event)) ev := Event{Type: EventMouse} switch mr.event_flags { case 0, 2: // single or double click cur_state := mr.button_state switch { case last_state&mouse_lmb == 0 && cur_state&mouse_lmb != 0: last_button = MouseLeft last_button_pressed = last_button case last_state&mouse_rmb == 0 && cur_state&mouse_rmb != 0: last_button = MouseRight last_button_pressed = last_button case last_state&mouse_mmb == 0 && cur_state&mouse_mmb != 0: last_button = MouseMiddle last_button_pressed = last_button case last_state&mouse_lmb != 0 && cur_state&mouse_lmb == 0: last_button = MouseRelease case last_state&mouse_rmb != 0 && cur_state&mouse_rmb == 0: last_button = MouseRelease case last_state&mouse_mmb != 0 && cur_state&mouse_mmb == 0: last_button = MouseRelease default: last_state = cur_state continue } last_state = cur_state ev.Key = last_button last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y) ev.MouseX = last_x ev.MouseY = last_y case 1: // mouse motion x, y := int(mr.mouse_pos.x), int(mr.mouse_pos.y) if last_state != 0 && (last_x != x || last_y != y) { ev.Key = last_button_pressed ev.Mod = ModMotion ev.MouseX = x ev.MouseY = y last_x, last_y = x, y } else { ev.Type = EventNone } case 4: // mouse wheel n := int16(mr.button_state >> 16) if n > 0 { ev.Key = MouseWheelUp } else { ev.Key = MouseWheelDown } last_x, last_y = int(mr.mouse_pos.x), int(mr.mouse_pos.y) ev.MouseX = last_x ev.MouseY = last_y default: ev.Type = EventNone } if ev.Type != EventNone { input_comm <- ev } } } } golang-github-nsf-termbox-go-0.0~git20160914/terminfo.go000066400000000000000000000124751277573306300226760ustar00rootroot00000000000000// +build !windows // This file contains a simple and incomplete implementation of the terminfo // database. Information was taken from the ncurses manpages term(5) and // terminfo(5). Currently, only the string capabilities for special keys and for // functions without parameters are actually used. Colors are still done with // ANSI escape sequences. Other special features that are not (yet?) supported // are reading from ~/.terminfo, the TERMINFO_DIRS variable, Berkeley database // format and extended capabilities. package termbox import ( "bytes" "encoding/binary" "encoding/hex" "errors" "fmt" "io/ioutil" "os" "strings" ) const ( ti_magic = 0432 ti_header_length = 12 ti_mouse_enter = "\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h" ti_mouse_leave = "\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l" ) func load_terminfo() ([]byte, error) { var data []byte var err error term := os.Getenv("TERM") if term == "" { return nil, fmt.Errorf("termbox: TERM not set") } // The following behaviour follows the one described in terminfo(5) as // distributed by ncurses. terminfo := os.Getenv("TERMINFO") if terminfo != "" { // if TERMINFO is set, no other directory should be searched return ti_try_path(terminfo) } // next, consider ~/.terminfo home := os.Getenv("HOME") if home != "" { data, err = ti_try_path(home + "/.terminfo") if err == nil { return data, nil } } // next, TERMINFO_DIRS dirs := os.Getenv("TERMINFO_DIRS") if dirs != "" { for _, dir := range strings.Split(dirs, ":") { if dir == "" { // "" -> "/usr/share/terminfo" dir = "/usr/share/terminfo" } data, err = ti_try_path(dir) if err == nil { return data, nil } } } // fall back to /usr/share/terminfo return ti_try_path("/usr/share/terminfo") } func ti_try_path(path string) (data []byte, err error) { // load_terminfo already made sure it is set term := os.Getenv("TERM") // first try, the typical *nix path terminfo := path + "/" + term[0:1] + "/" + term data, err = ioutil.ReadFile(terminfo) if err == nil { return } // fallback to darwin specific dirs structure terminfo = path + "/" + hex.EncodeToString([]byte(term[:1])) + "/" + term data, err = ioutil.ReadFile(terminfo) return } func setup_term_builtin() error { name := os.Getenv("TERM") if name == "" { return errors.New("termbox: TERM environment variable not set") } for _, t := range terms { if t.name == name { keys = t.keys funcs = t.funcs return nil } } compat_table := []struct { partial string keys []string funcs []string }{ {"xterm", xterm_keys, xterm_funcs}, {"rxvt", rxvt_unicode_keys, rxvt_unicode_funcs}, {"linux", linux_keys, linux_funcs}, {"Eterm", eterm_keys, eterm_funcs}, {"screen", screen_keys, screen_funcs}, // let's assume that 'cygwin' is xterm compatible {"cygwin", xterm_keys, xterm_funcs}, {"st", xterm_keys, xterm_funcs}, } // try compatibility variants for _, it := range compat_table { if strings.Contains(name, it.partial) { keys = it.keys funcs = it.funcs return nil } } return errors.New("termbox: unsupported terminal") } func setup_term() (err error) { var data []byte var header [6]int16 var str_offset, table_offset int16 data, err = load_terminfo() if err != nil { return setup_term_builtin() } rd := bytes.NewReader(data) // 0: magic number, 1: size of names section, 2: size of boolean section, 3: // size of numbers section (in integers), 4: size of the strings section (in // integers), 5: size of the string table err = binary.Read(rd, binary.LittleEndian, header[:]) if err != nil { return } if (header[1]+header[2])%2 != 0 { // old quirk to align everything on word boundaries header[2] += 1 } str_offset = ti_header_length + header[1] + header[2] + 2*header[3] table_offset = str_offset + 2*header[4] keys = make([]string, 0xFFFF-key_min) for i, _ := range keys { keys[i], err = ti_read_string(rd, str_offset+2*ti_keys[i], table_offset) if err != nil { return } } funcs = make([]string, t_max_funcs) // the last two entries are reserved for mouse. because the table offset is // not there, the two entries have to fill in manually for i, _ := range funcs[:len(funcs)-2] { funcs[i], err = ti_read_string(rd, str_offset+2*ti_funcs[i], table_offset) if err != nil { return } } funcs[t_max_funcs-2] = ti_mouse_enter funcs[t_max_funcs-1] = ti_mouse_leave return nil } func ti_read_string(rd *bytes.Reader, str_off, table int16) (string, error) { var off int16 _, err := rd.Seek(int64(str_off), 0) if err != nil { return "", err } err = binary.Read(rd, binary.LittleEndian, &off) if err != nil { return "", err } _, err = rd.Seek(int64(table+off), 0) if err != nil { return "", err } var bs []byte for { b, err := rd.ReadByte() if err != nil { return "", err } if b == byte(0x00) { break } bs = append(bs, b) } return string(bs), nil } // "Maps" the function constants from termbox.go to the number of the respective // string capability in the terminfo file. Taken from (ncurses) term.h. var ti_funcs = []int16{ 28, 40, 16, 13, 5, 39, 36, 27, 26, 34, 89, 88, } // Same as above for the special keys. var ti_keys = []int16{ 66, 68 /* apparently not a typo; 67 is F10 for whatever reason */, 69, 70, 71, 72, 73, 74, 75, 67, 216, 217, 77, 59, 76, 164, 82, 81, 87, 61, 79, 83, } golang-github-nsf-termbox-go-0.0~git20160914/terminfo_builtin.go000066400000000000000000000065431277573306300244230ustar00rootroot00000000000000// +build !windows package termbox // Eterm var eterm_keys = []string{ "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", } var eterm_funcs = []string{ "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", } // screen var screen_keys = []string{ "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", } var screen_funcs = []string{ "\x1b[?1049h", "\x1b[?1049l", "\x1b[34h\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, } // xterm var xterm_keys = []string{ "\x1bOP", "\x1bOQ", "\x1bOR", "\x1bOS", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1bOH", "\x1bOF", "\x1b[5~", "\x1b[6~", "\x1bOA", "\x1bOB", "\x1bOD", "\x1bOC", } var xterm_funcs = []string{ "\x1b[?1049h", "\x1b[?1049l", "\x1b[?12l\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b(B\x1b[m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b[?1h\x1b=", "\x1b[?1l\x1b>", ti_mouse_enter, ti_mouse_leave, } // rxvt-unicode var rxvt_unicode_keys = []string{ "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", } var rxvt_unicode_funcs = []string{ "\x1b[?1049h", "\x1b[r\x1b[?1049l", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x1b(B", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, } // linux var linux_keys = []string{ "\x1b[[A", "\x1b[[B", "\x1b[[C", "\x1b[[D", "\x1b[[E", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[1~", "\x1b[4~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", } var linux_funcs = []string{ "", "", "\x1b[?25h\x1b[?0c", "\x1b[?25l\x1b[?1c", "\x1b[H\x1b[J", "\x1b[0;10m", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "", "", "", "", } // rxvt-256color var rxvt_256color_keys = []string{ "\x1b[11~", "\x1b[12~", "\x1b[13~", "\x1b[14~", "\x1b[15~", "\x1b[17~", "\x1b[18~", "\x1b[19~", "\x1b[20~", "\x1b[21~", "\x1b[23~", "\x1b[24~", "\x1b[2~", "\x1b[3~", "\x1b[7~", "\x1b[8~", "\x1b[5~", "\x1b[6~", "\x1b[A", "\x1b[B", "\x1b[D", "\x1b[C", } var rxvt_256color_funcs = []string{ "\x1b7\x1b[?47h", "\x1b[2J\x1b[?47l\x1b8", "\x1b[?25h", "\x1b[?25l", "\x1b[H\x1b[2J", "\x1b[m\x0f", "\x1b[4m", "\x1b[1m", "\x1b[5m", "\x1b[7m", "\x1b=", "\x1b>", ti_mouse_enter, ti_mouse_leave, } var terms = []struct { name string keys []string funcs []string }{ {"Eterm", eterm_keys, eterm_funcs}, {"screen", screen_keys, screen_funcs}, {"xterm", xterm_keys, xterm_funcs}, {"rxvt-unicode", rxvt_unicode_keys, rxvt_unicode_funcs}, {"linux", linux_keys, linux_funcs}, {"rxvt-256color", rxvt_256color_keys, rxvt_256color_funcs}, }