...

Source file src/github.com/gdamore/tcell/v2/termbox/compat.go

Documentation: github.com/gdamore/tcell/v2/termbox

     1  // Copyright 2020 The TCell Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use file except in compliance with the License.
     5  // You may obtain a copy of the license at
     6  //
     7  //    http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package termbox is a compatibility layer to allow tcell to emulate
    16  // the github.com/nsf/termbox package.
    17  package termbox
    18  
    19  import (
    20  	"errors"
    21  
    22  	"github.com/gdamore/tcell/v2"
    23  )
    24  
    25  var screen tcell.Screen
    26  var outMode OutputMode
    27  
    28  // Init initializes the screen for use.
    29  func Init() error {
    30  	outMode = OutputNormal
    31  	if s, e := tcell.NewScreen(); e != nil {
    32  		return e
    33  	} else if e = s.Init(); e != nil {
    34  		return e
    35  	} else {
    36  		screen = s
    37  		return nil
    38  	}
    39  }
    40  
    41  // Close cleans up the terminal, restoring terminal modes, etc.
    42  func Close() {
    43  	screen.Fini()
    44  }
    45  
    46  // Flush updates the screen.
    47  func Flush() error {
    48  	screen.Show()
    49  	return nil
    50  }
    51  
    52  // SetCursor displays the terminal cursor at the given location.
    53  func SetCursor(x, y int) {
    54  	screen.ShowCursor(x, y)
    55  }
    56  
    57  // HideCursor hides the terminal cursor.
    58  func HideCursor() {
    59  	SetCursor(-1, -1)
    60  }
    61  
    62  // Size returns the screen size as width, height in character cells.
    63  func Size() (int, int) {
    64  	return screen.Size()
    65  }
    66  
    67  // Attribute affects the presentation of characters, such as color, boldness,
    68  // and so forth.
    69  type Attribute uint16
    70  
    71  // Colors first.  The order here is significant.
    72  const (
    73  	ColorDefault Attribute = iota
    74  	ColorBlack
    75  	ColorRed
    76  	ColorGreen
    77  	ColorYellow
    78  	ColorBlue
    79  	ColorMagenta
    80  	ColorCyan
    81  	ColorWhite
    82  )
    83  
    84  // Other attributes.
    85  const (
    86  	AttrBold Attribute = 1 << (9 + iota)
    87  	AttrUnderline
    88  	AttrReverse
    89  )
    90  
    91  func fixColor(c tcell.Color) tcell.Color {
    92  	if c == tcell.ColorDefault {
    93  		return c
    94  	}
    95  	switch outMode {
    96  	case OutputNormal:
    97  		c = tcell.PaletteColor(int(c) & 0xf)
    98  	case Output256:
    99  		c = tcell.PaletteColor(int(c) & 0xff)
   100  	case Output216:
   101  		c = tcell.PaletteColor(int(c)%216 + 16)
   102  	case OutputGrayscale:
   103  		c %= tcell.PaletteColor(int(c)%24 + 232)
   104  	default:
   105  		c = tcell.ColorDefault
   106  	}
   107  	return c
   108  }
   109  
   110  func mkStyle(fg, bg Attribute) tcell.Style {
   111  	st := tcell.StyleDefault
   112  
   113  	f := tcell.PaletteColor(int(fg)&0x1ff - 1)
   114  	b := tcell.PaletteColor(int(bg)&0x1ff - 1)
   115  
   116  	f = fixColor(f)
   117  	b = fixColor(b)
   118  	st = st.Foreground(f).Background(b)
   119  	if (fg|bg)&AttrBold != 0 {
   120  		st = st.Bold(true)
   121  	}
   122  	if (fg|bg)&AttrUnderline != 0 {
   123  		st = st.Underline(true)
   124  	}
   125  	if (fg|bg)&AttrReverse != 0 {
   126  		st = st.Reverse(true)
   127  	}
   128  	return st
   129  }
   130  
   131  // Clear clears the screen with the given attributes.
   132  func Clear(fg, bg Attribute) {
   133  	st := mkStyle(fg, bg)
   134  	w, h := screen.Size()
   135  	for row := 0; row < h; row++ {
   136  		for col := 0; col < w; col++ {
   137  			screen.SetContent(col, row, ' ', nil, st)
   138  		}
   139  	}
   140  }
   141  
   142  // InputMode is not used.
   143  type InputMode int
   144  
   145  // Unused input modes; here for compatibility.
   146  const (
   147  	InputCurrent InputMode = iota
   148  	InputEsc
   149  	InputAlt
   150  	InputMouse
   151  )
   152  
   153  // SetInputMode does not do anything in this version.
   154  func SetInputMode(mode InputMode) InputMode {
   155  	// We don't do anything else right now
   156  	return InputEsc
   157  }
   158  
   159  // OutputMode represents an output mode, which determines how colors
   160  // are used.  See the termbox documentation for an explanation.
   161  type OutputMode int
   162  
   163  // OutputMode values.
   164  const (
   165  	OutputCurrent OutputMode = iota
   166  	OutputNormal
   167  	Output256
   168  	Output216
   169  	OutputGrayscale
   170  )
   171  
   172  // SetOutputMode is used to set the color palette used.
   173  func SetOutputMode(mode OutputMode) OutputMode {
   174  	if screen.Colors() < 256 {
   175  		mode = OutputNormal
   176  	}
   177  	switch mode {
   178  	case OutputCurrent:
   179  		return outMode
   180  	case OutputNormal, Output256, Output216, OutputGrayscale:
   181  		outMode = mode
   182  		return mode
   183  	default:
   184  		return outMode
   185  	}
   186  }
   187  
   188  // Sync forces a resync of the screen.
   189  func Sync() error {
   190  	screen.Sync()
   191  	return nil
   192  }
   193  
   194  // SetCell sets the character cell at a given location to the given
   195  // content (rune) and attributes.
   196  func SetCell(x, y int, ch rune, fg, bg Attribute) {
   197  	st := mkStyle(fg, bg)
   198  	screen.SetContent(x, y, ch, nil, st)
   199  }
   200  
   201  // EventType represents the type of event.
   202  type EventType uint8
   203  
   204  // Modifier represents the possible modifier keys.
   205  type Modifier tcell.ModMask
   206  
   207  // Key is a key press.
   208  type Key tcell.Key
   209  
   210  // Event represents an event like a key press, mouse action, or window resize.
   211  type Event struct {
   212  	Type   EventType
   213  	Mod    Modifier
   214  	Key    Key
   215  	Ch     rune
   216  	Width  int
   217  	Height int
   218  	Err    error
   219  	MouseX int
   220  	MouseY int
   221  	N      int
   222  }
   223  
   224  // Event types.
   225  const (
   226  	EventNone EventType = iota
   227  	EventKey
   228  	EventResize
   229  	EventMouse
   230  	EventInterrupt
   231  	EventError
   232  	EventRaw
   233  )
   234  
   235  // Keys codes.
   236  const (
   237  	KeyF1             = Key(tcell.KeyF1)
   238  	KeyF2             = Key(tcell.KeyF2)
   239  	KeyF3             = Key(tcell.KeyF3)
   240  	KeyF4             = Key(tcell.KeyF4)
   241  	KeyF5             = Key(tcell.KeyF5)
   242  	KeyF6             = Key(tcell.KeyF6)
   243  	KeyF7             = Key(tcell.KeyF7)
   244  	KeyF8             = Key(tcell.KeyF8)
   245  	KeyF9             = Key(tcell.KeyF9)
   246  	KeyF10            = Key(tcell.KeyF10)
   247  	KeyF11            = Key(tcell.KeyF11)
   248  	KeyF12            = Key(tcell.KeyF12)
   249  	KeyInsert         = Key(tcell.KeyInsert)
   250  	KeyDelete         = Key(tcell.KeyDelete)
   251  	KeyHome           = Key(tcell.KeyHome)
   252  	KeyEnd            = Key(tcell.KeyEnd)
   253  	KeyArrowUp        = Key(tcell.KeyUp)
   254  	KeyArrowDown      = Key(tcell.KeyDown)
   255  	KeyArrowRight     = Key(tcell.KeyRight)
   256  	KeyArrowLeft      = Key(tcell.KeyLeft)
   257  	KeyCtrlA          = Key(tcell.KeyCtrlA)
   258  	KeyCtrlB          = Key(tcell.KeyCtrlB)
   259  	KeyCtrlC          = Key(tcell.KeyCtrlC)
   260  	KeyCtrlD          = Key(tcell.KeyCtrlD)
   261  	KeyCtrlE          = Key(tcell.KeyCtrlE)
   262  	KeyCtrlF          = Key(tcell.KeyCtrlF)
   263  	KeyCtrlG          = Key(tcell.KeyCtrlG)
   264  	KeyCtrlH          = Key(tcell.KeyCtrlH)
   265  	KeyCtrlI          = Key(tcell.KeyCtrlI)
   266  	KeyCtrlJ          = Key(tcell.KeyCtrlJ)
   267  	KeyCtrlK          = Key(tcell.KeyCtrlK)
   268  	KeyCtrlL          = Key(tcell.KeyCtrlL)
   269  	KeyCtrlM          = Key(tcell.KeyCtrlM)
   270  	KeyCtrlN          = Key(tcell.KeyCtrlN)
   271  	KeyCtrlO          = Key(tcell.KeyCtrlO)
   272  	KeyCtrlP          = Key(tcell.KeyCtrlP)
   273  	KeyCtrlQ          = Key(tcell.KeyCtrlQ)
   274  	KeyCtrlR          = Key(tcell.KeyCtrlR)
   275  	KeyCtrlS          = Key(tcell.KeyCtrlS)
   276  	KeyCtrlT          = Key(tcell.KeyCtrlT)
   277  	KeyCtrlU          = Key(tcell.KeyCtrlU)
   278  	KeyCtrlV          = Key(tcell.KeyCtrlV)
   279  	KeyCtrlW          = Key(tcell.KeyCtrlW)
   280  	KeyCtrlX          = Key(tcell.KeyCtrlX)
   281  	KeyCtrlY          = Key(tcell.KeyCtrlY)
   282  	KeyCtrlZ          = Key(tcell.KeyCtrlZ)
   283  	KeyCtrlUnderscore = Key(tcell.KeyCtrlUnderscore)
   284  	KeyBackspace      = Key(tcell.KeyBackspace)
   285  	KeyBackspace2     = Key(tcell.KeyBackspace2)
   286  	KeyTab            = Key(tcell.KeyTab)
   287  	KeyEnter          = Key(tcell.KeyEnter)
   288  	KeyEsc            = Key(tcell.KeyEscape)
   289  	KeyPgdn           = Key(tcell.KeyPgDn)
   290  	KeyPgup           = Key(tcell.KeyPgUp)
   291  	KeySpace          = Key(tcell.Key(' '))
   292  	KeyTilde          = Key(tcell.Key('~'))
   293  	KeyCtrlSpace      = Key(tcell.KeyCtrlSpace)
   294  
   295  	// The following assignments are provided for termbox
   296  	// compatibility.  Their use in applications is discouraged.
   297  	// The mouse keys are completely not supported as tcell uses
   298  	// a separate mouse event instead of key strokes.
   299  	MouseLeft         = Key(tcell.KeyF63) // arbitrary assignments
   300  	MouseRight        = Key(tcell.KeyF62)
   301  	MouseMiddle       = Key(tcell.KeyF61)
   302  	MouseRelease      = Key(tcell.KeyF60)
   303  	MouseWheelUp      = Key(tcell.KeyF59)
   304  	MouseWheelDown    = Key(tcell.KeyF58)
   305  	KeyCtrlTilde      = Key(tcell.KeyCtrlSpace) // termbox defines a bunch of weird ones, don't use them
   306  	KeyCtrl2          = Key(tcell.KeyNUL)
   307  	KeyCtrl3          = Key(tcell.KeyEscape)
   308  	KeyCtrl4          = Key(tcell.KeyCtrlBackslash)
   309  	KeyCtrl5          = Key(tcell.KeyCtrlRightSq)
   310  	KeyCtrl6          = Key(tcell.KeyCtrlCarat)
   311  	KeyCtrl7          = Key(tcell.KeyCtrlUnderscore)
   312  	KeyCtrl8          = Key(tcell.KeyDEL)
   313  	KeyCtrlSlash      = Key(tcell.KeyCtrlUnderscore)
   314  	KeyCtrlRsqBracket = Key(tcell.KeyCtrlRightSq)
   315  	KeyCtrlBackslash  = Key(tcell.KeyCtrlBackslash)
   316  	KeyCtrlLsqBracket = Key(tcell.KeyCtrlLeftSq)
   317  )
   318  
   319  // Modifiers.
   320  const (
   321  	ModAlt = Modifier(tcell.ModAlt)
   322  )
   323  
   324  func makeEvent(tev tcell.Event) Event {
   325  	switch tev := tev.(type) {
   326  	case *tcell.EventInterrupt:
   327  		return Event{Type: EventInterrupt}
   328  	case *tcell.EventResize:
   329  		w, h := tev.Size()
   330  		return Event{Type: EventResize, Width: w, Height: h}
   331  	case *tcell.EventKey:
   332  		k := tev.Key()
   333  		ch := rune(0)
   334  		if k == tcell.KeyRune {
   335  			ch = tev.Rune()
   336  			if ch == ' ' {
   337  				k = tcell.Key(' ')
   338  			} else {
   339  				k = tcell.Key(0)
   340  			}
   341  		}
   342  		mod := tev.Modifiers()
   343  		return Event{
   344  			Type: EventKey,
   345  			Key:  Key(k),
   346  			Ch:   ch,
   347  			Mod:  Modifier(mod),
   348  		}
   349  	default:
   350  		return Event{Type: EventNone}
   351  	}
   352  }
   353  
   354  // ParseEvent is not supported.
   355  func ParseEvent(data []byte) Event {
   356  	// Not supported
   357  	return Event{Type: EventError, Err: errors.New("no raw events")}
   358  }
   359  
   360  // PollRawEvent is not supported.
   361  func PollRawEvent(data []byte) Event {
   362  	// Not supported
   363  	return Event{Type: EventError, Err: errors.New("no raw events")}
   364  }
   365  
   366  // PollEvent blocks until an event is ready, and then returns it.
   367  func PollEvent() Event {
   368  	ev := screen.PollEvent()
   369  	return makeEvent(ev)
   370  }
   371  
   372  // Interrupt posts an interrupt event.
   373  func Interrupt() {
   374  	screen.PostEvent(tcell.NewEventInterrupt(nil))
   375  }
   376  
   377  // Cell represents a single character cell on screen.
   378  type Cell struct {
   379  	Ch rune
   380  	Fg Attribute
   381  	Bg Attribute
   382  }
   383  

View as plain text