diff options
author | Michael Muré <batolettre@gmail.com> | 2019-11-03 20:47:29 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2019-11-03 20:47:29 +0100 |
commit | cb8236c9c22007eb622b7219c58d3342f1f53d50 (patch) | |
tree | e232e5362486065d9b28bb55b9791690efb50c08 /vendor/github.com/nsf/termbox-go/api.go | |
parent | 163ea9c93306c387f84ff0b85c2d8fca4c01e449 (diff) | |
download | git-bug-cb8236c9c22007eb622b7219c58d3342f1f53d50.tar.gz |
termui: migrate to awesome-gocui instead of the old fork I had
Diffstat (limited to 'vendor/github.com/nsf/termbox-go/api.go')
-rw-r--r-- | vendor/github.com/nsf/termbox-go/api.go | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/vendor/github.com/nsf/termbox-go/api.go b/vendor/github.com/nsf/termbox-go/api.go deleted file mode 100644 index d530ab5c..00000000 --- a/vendor/github.com/nsf/termbox-go/api.go +++ /dev/null @@ -1,489 +0,0 @@ -// +build !windows - -package termbox - -import "github.com/mattn/go-runewidth" -import "fmt" -import "os" -import "os/signal" -import "syscall" -import "runtime" -import "time" - -// 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} - status := extract_event(data, &event, false) - if status != event_extracted { - 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 { - // Constant governing macOS specific behavior. See https://github.com/nsf/termbox-go/issues/132 - // This is an arbitrary delay which hopefully will be enough time for any lagging - // partial escape sequences to come through. - const esc_wait_delay = 100 * time.Millisecond - - var event Event - var esc_wait_timer *time.Timer - var esc_timeout <-chan time.Time - - // try to extract event from input buffer, return on success - event.Type = EventKey - status := extract_event(inbuf, &event, true) - if event.N != 0 { - copy(inbuf, inbuf[event.N:]) - inbuf = inbuf[:len(inbuf)-event.N] - } - if status == event_extracted { - return event - } else if status == esc_wait { - esc_wait_timer = time.NewTimer(esc_wait_delay) - esc_timeout = esc_wait_timer.C - } - - for { - select { - case ev := <-input_comm: - if esc_wait_timer != nil { - if !esc_wait_timer.Stop() { - <-esc_wait_timer.C - } - esc_wait_timer = nil - } - - if ev.err != nil { - return Event{Type: EventError, Err: ev.err} - } - - inbuf = append(inbuf, ev.data...) - input_comm <- ev - status := extract_event(inbuf, &event, true) - if event.N != 0 { - copy(inbuf, inbuf[event.N:]) - inbuf = inbuf[:len(inbuf)-event.N] - } - if status == event_extracted { - return event - } else if status == esc_wait { - esc_wait_timer = time.NewTimer(esc_wait_delay) - esc_timeout = esc_wait_timer.C - } - case <-esc_timeout: - esc_wait_timer = nil - - status := extract_event(inbuf, &event, false) - if event.N != 0 { - copy(inbuf, inbuf[event.N:]) - inbuf = inbuf[:len(inbuf)-event.N] - } - if status == event_extracted { - 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 - } - } -} - -// 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 don't 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 don't 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() -} |