mirror of
https://github.com/gdamore/tcell.git
synced 2025-04-24 13:48:51 +08:00
fixes #75 Add goreport and fix related issues
This commit is contained in:
parent
b727b9f424
commit
43f9cc0d07
@ -5,6 +5,7 @@
|
||||
[](https://github.com/gdamore/tcell/blob/master/LICENSE)
|
||||
[](https://gitter.im/gdamore/tcell)
|
||||
[](https://godoc.org/github.com/gdamore/tcell)
|
||||
[](http://goreportcard.com/report/gdamore/tcell)
|
||||
|
||||
> _Tcell is a work in progress (Gamma).
|
||||
> Please use with caution; interfaces may change in before final release.
|
||||
|
2
attr.go
2
attr.go
@ -31,4 +31,4 @@ const (
|
||||
AttrNone AttrMask = 0
|
||||
)
|
||||
|
||||
const AttrMaskAll = AttrBold | AttrBlink | AttrReverse | AttrUnderline | AttrDim
|
||||
const attrAll = AttrBold | AttrBlink | AttrReverse | AttrUnderline | AttrDim
|
||||
|
@ -16,6 +16,6 @@
|
||||
|
||||
package tcell
|
||||
|
||||
func GetCharset() string {
|
||||
func getCharset() string {
|
||||
return ""
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func GetCharset() string {
|
||||
func getCharset() string {
|
||||
// Determine the character set. This can help us later.
|
||||
// Per POSIX, we search for LC_ALL first, then LC_CTYPE, and
|
||||
// finally LANG. First one set wins.
|
||||
|
@ -16,6 +16,6 @@
|
||||
|
||||
package tcell
|
||||
|
||||
func GetCharset() string {
|
||||
func getCharset() string {
|
||||
return "UTF-16"
|
||||
}
|
||||
|
11
color.go
11
color.go
@ -964,6 +964,9 @@ var colorNames = map[string]Color{
|
||||
"slategrey": ColorSlateGray,
|
||||
}
|
||||
|
||||
// Hex returns the color's hexadecimal RGB 24-bit value with each component
|
||||
// consisting of a single byte, ala R << 16 | G << 8 | B. If the color
|
||||
// is unknown or unset, -1 is returned.
|
||||
func (c Color) Hex() int32 {
|
||||
if c&ColorIsRGB != 0 {
|
||||
return (int32(c) & 0xffffff)
|
||||
@ -974,6 +977,9 @@ func (c Color) Hex() int32 {
|
||||
return -1
|
||||
}
|
||||
|
||||
// RGB returns the red, green, and blue components of the color, with
|
||||
// each component represented as a value 0-255. In the event that the
|
||||
// color cannot be broken up (not set usually), -1 is returned for each value.
|
||||
func (c Color) RGB() (int32, int32, int32) {
|
||||
v := c.Hex()
|
||||
if v < 0 {
|
||||
@ -982,15 +988,18 @@ func (c Color) RGB() (int32, int32, int32) {
|
||||
return (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff
|
||||
}
|
||||
|
||||
// NewRGBColor returns a new color with the given red, green, and blue values.
|
||||
// Each value must be represented in the range 0-255.
|
||||
func NewRGBColor(r, g, b int32) Color {
|
||||
return NewHexColor(((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff))
|
||||
}
|
||||
|
||||
// NewHexColor returns a color using the given 24-bit RGB value.
|
||||
func NewHexColor(v int32) Color {
|
||||
return ColorIsRGB | Color(v)
|
||||
}
|
||||
|
||||
// Given a color name (W3C name), return the actual color. A hex value may
|
||||
// GetColor creates a Color from a color name (W3C name). A hex value may
|
||||
// be supplied as a string in the format "#ffffff".
|
||||
func GetColor(name string) Color {
|
||||
if c, ok := colorNames[name]; ok {
|
||||
|
280
console_win.go
280
console_win.go
@ -26,7 +26,6 @@ import (
|
||||
type cScreen struct {
|
||||
in syscall.Handle
|
||||
out syscall.Handle
|
||||
mbtns uint32 // debounce mouse buttons
|
||||
evch chan Event
|
||||
quit chan struct{}
|
||||
curx int
|
||||
@ -372,6 +371,52 @@ const (
|
||||
vkF24 = 0x87
|
||||
)
|
||||
|
||||
var vkKeys = map[uint16]Key{
|
||||
vkCancel: KeyCancel,
|
||||
vkBack: KeyBackspace,
|
||||
vkTab: KeyTab,
|
||||
vkClear: KeyClear,
|
||||
vkPause: KeyPause,
|
||||
vkPrint: KeyPrint,
|
||||
vkPrtScr: KeyPrint,
|
||||
vkPrior: KeyPgUp,
|
||||
vkNext: KeyPgDn,
|
||||
vkReturn: KeyEnter,
|
||||
vkEnd: KeyEnd,
|
||||
vkHome: KeyHome,
|
||||
vkLeft: KeyLeft,
|
||||
vkUp: KeyUp,
|
||||
vkRight: KeyRight,
|
||||
vkDown: KeyDown,
|
||||
vkInsert: KeyInsert,
|
||||
vkDelete: KeyDelete,
|
||||
vkHelp: KeyHelp,
|
||||
vkF1: KeyF1,
|
||||
vkF2: KeyF2,
|
||||
vkF3: KeyF3,
|
||||
vkF4: KeyF4,
|
||||
vkF5: KeyF5,
|
||||
vkF6: KeyF6,
|
||||
vkF7: KeyF7,
|
||||
vkF8: KeyF8,
|
||||
vkF9: KeyF9,
|
||||
vkF10: KeyF10,
|
||||
vkF11: KeyF11,
|
||||
vkF12: KeyF12,
|
||||
vkF13: KeyF13,
|
||||
vkF14: KeyF14,
|
||||
vkF15: KeyF15,
|
||||
vkF16: KeyF16,
|
||||
vkF17: KeyF17,
|
||||
vkF18: KeyF18,
|
||||
vkF19: KeyF19,
|
||||
vkF20: KeyF20,
|
||||
vkF21: KeyF21,
|
||||
vkF22: KeyF22,
|
||||
vkF23: KeyF23,
|
||||
vkF24: KeyF24,
|
||||
}
|
||||
|
||||
// NB: All Windows platforms are little endian. We assume this
|
||||
// never, ever change. The following code is endian safe. and does
|
||||
// not use unsafe pointers.
|
||||
@ -406,6 +451,50 @@ func mod2mask(cks uint32) ModMask {
|
||||
return mm
|
||||
}
|
||||
|
||||
func mrec2btns(mbtns, flags uint32) ButtonMask {
|
||||
btns := ButtonNone
|
||||
if mbtns&0x1 != 0 {
|
||||
btns |= Button1
|
||||
}
|
||||
if mbtns&0x2 != 0 {
|
||||
btns |= Button2
|
||||
}
|
||||
if mbtns&0x4 != 0 {
|
||||
btns |= Button3
|
||||
}
|
||||
if mbtns&0x8 != 0 {
|
||||
btns |= Button4
|
||||
}
|
||||
if mbtns&0x10 != 0 {
|
||||
btns |= Button5
|
||||
}
|
||||
if mbtns&0x20 != 0 {
|
||||
btns |= Button6
|
||||
}
|
||||
if mbtns&0x40 != 0 {
|
||||
btns |= Button7
|
||||
}
|
||||
if mbtns&0x80 != 0 {
|
||||
btns |= Button8
|
||||
}
|
||||
|
||||
if flags&mouseVWheeled != 0 {
|
||||
if mbtns&0x80000000 == 0 {
|
||||
btns |= WheelUp
|
||||
} else {
|
||||
btns |= WheelDown
|
||||
}
|
||||
}
|
||||
if flags&mouseHWheeled != 0 {
|
||||
if mbtns&0x80000000 == 0 {
|
||||
btns |= WheelRight
|
||||
} else {
|
||||
btns |= WheelLeft
|
||||
}
|
||||
}
|
||||
return btns
|
||||
}
|
||||
|
||||
func (s *cScreen) getConsoleInput() error {
|
||||
rec := &inputRecord{}
|
||||
var nrec int32
|
||||
@ -444,92 +533,8 @@ func (s *cScreen) getConsoleInput() error {
|
||||
return nil
|
||||
}
|
||||
key := KeyNUL // impossible on Windows
|
||||
switch krec.kcode {
|
||||
case vkCancel:
|
||||
key = KeyCancel
|
||||
case vkBack:
|
||||
key = KeyBackspace
|
||||
case vkTab:
|
||||
key = KeyTab
|
||||
case vkClear:
|
||||
key = KeyClear
|
||||
case vkPause:
|
||||
key = KeyPause
|
||||
case vkPrint, vkPrtScr:
|
||||
key = KeyPrint
|
||||
case vkPrior:
|
||||
key = KeyPgUp
|
||||
case vkNext:
|
||||
key = KeyPgDn
|
||||
case vkReturn:
|
||||
key = KeyEnter
|
||||
case vkEnd:
|
||||
key = KeyEnd
|
||||
case vkHome:
|
||||
key = KeyHome
|
||||
case vkLeft:
|
||||
key = KeyLeft
|
||||
case vkUp:
|
||||
key = KeyUp
|
||||
case vkRight:
|
||||
key = KeyRight
|
||||
case vkDown:
|
||||
key = KeyDown
|
||||
case vkInsert:
|
||||
key = KeyInsert
|
||||
case vkDelete:
|
||||
key = KeyDelete
|
||||
case vkHelp:
|
||||
key = KeyHelp
|
||||
case vkF1:
|
||||
key = KeyF1
|
||||
case vkF2:
|
||||
key = KeyF2
|
||||
case vkF3:
|
||||
key = KeyF3
|
||||
case vkF4:
|
||||
key = KeyF4
|
||||
case vkF5:
|
||||
key = KeyF5
|
||||
case vkF6:
|
||||
key = KeyF6
|
||||
case vkF7:
|
||||
key = KeyF7
|
||||
case vkF8:
|
||||
key = KeyF8
|
||||
case vkF9:
|
||||
key = KeyF9
|
||||
case vkF10:
|
||||
key = KeyF10
|
||||
case vkF11:
|
||||
key = KeyF11
|
||||
case vkF12:
|
||||
key = KeyF12
|
||||
case vkF13:
|
||||
key = KeyF13
|
||||
case vkF14:
|
||||
key = KeyF14
|
||||
case vkF15:
|
||||
key = KeyF15
|
||||
case vkF16:
|
||||
key = KeyF16
|
||||
case vkF17:
|
||||
key = KeyF17
|
||||
case vkF18:
|
||||
key = KeyF18
|
||||
case vkF19:
|
||||
key = KeyF19
|
||||
case vkF20:
|
||||
key = KeyF20
|
||||
case vkF21:
|
||||
key = KeyF21
|
||||
case vkF22:
|
||||
key = KeyF22
|
||||
case vkF23:
|
||||
key = KeyF23
|
||||
case vkF24:
|
||||
key = KeyF24
|
||||
default:
|
||||
ok := false
|
||||
if key, ok = vkKeys[krec.kcode]; !ok {
|
||||
return nil
|
||||
}
|
||||
for krec.repeat > 0 {
|
||||
@ -544,49 +549,8 @@ func (s *cScreen) getConsoleInput() error {
|
||||
mrec.y = geti16(rec.data[2:])
|
||||
mrec.btns = getu32(rec.data[4:])
|
||||
mrec.mod = getu32(rec.data[8:])
|
||||
mrec.flags = getu32(rec.data[12:]) // not using yet
|
||||
btns := ButtonNone
|
||||
|
||||
s.mbtns = mrec.btns
|
||||
if mrec.btns&0x1 != 0 {
|
||||
btns |= Button1
|
||||
}
|
||||
if mrec.btns&0x2 != 0 {
|
||||
btns |= Button2
|
||||
}
|
||||
if mrec.btns&0x4 != 0 {
|
||||
btns |= Button3
|
||||
}
|
||||
if mrec.btns&0x8 != 0 {
|
||||
btns |= Button4
|
||||
}
|
||||
if mrec.btns&0x10 != 0 {
|
||||
btns |= Button5
|
||||
}
|
||||
if mrec.btns&0x20 != 0 {
|
||||
btns |= Button6
|
||||
}
|
||||
if mrec.btns&0x40 != 0 {
|
||||
btns |= Button7
|
||||
}
|
||||
if mrec.btns&0x80 != 0 {
|
||||
btns |= Button8
|
||||
}
|
||||
|
||||
if mrec.flags&mouseVWheeled != 0 {
|
||||
if mrec.btns&0x80000000 == 0 {
|
||||
btns |= WheelUp
|
||||
} else {
|
||||
btns |= WheelDown
|
||||
}
|
||||
}
|
||||
if mrec.flags&mouseHWheeled != 0 {
|
||||
if mrec.btns&0x80000000 == 0 {
|
||||
btns |= WheelRight
|
||||
} else {
|
||||
btns |= WheelLeft
|
||||
}
|
||||
}
|
||||
mrec.flags = getu32(rec.data[12:])
|
||||
btns := mrec2btns(mrec.btns, mrec.flags)
|
||||
// we ignore double click, events are delivered normally
|
||||
s.PostEvent(NewEventMouse(int(mrec.x), int(mrec.y), btns,
|
||||
mod2mask(mrec.mod)))
|
||||
@ -615,6 +579,25 @@ func (s *cScreen) Colors() int {
|
||||
return 16
|
||||
}
|
||||
|
||||
var vgaColors = map[Color]uint16{
|
||||
ColorBlack: 0,
|
||||
ColorMaroon: 0x4,
|
||||
ColorGreen: 0x2,
|
||||
ColorNavy: 0x1,
|
||||
ColorOlive: 0x6,
|
||||
ColorPurple: 0x5,
|
||||
ColorTeal: 0x3,
|
||||
ColorSilver: 0x7,
|
||||
ColorGrey: 0x8,
|
||||
ColorRed: 0xc,
|
||||
ColorLime: 0xa,
|
||||
ColorBlue: 0x9,
|
||||
ColorYellow: 0xe,
|
||||
ColorFuchsia: 0xd,
|
||||
ColorAqua: 0xb,
|
||||
ColorWhite: 0xf,
|
||||
}
|
||||
|
||||
// Windows uses RGB signals
|
||||
func mapColor2RGB(c Color) uint16 {
|
||||
|
||||
@ -628,41 +611,8 @@ func mapColor2RGB(c Color) uint16 {
|
||||
}
|
||||
winLock.Unlock()
|
||||
|
||||
switch c {
|
||||
case ColorBlack:
|
||||
return 0
|
||||
// primaries
|
||||
case ColorMaroon:
|
||||
return 0x4
|
||||
case ColorGreen:
|
||||
return 0x2
|
||||
case ColorNavy:
|
||||
return 0x1
|
||||
case ColorOlive:
|
||||
return 0x6
|
||||
case ColorPurple:
|
||||
return 0x5
|
||||
case ColorTeal:
|
||||
return 0x3
|
||||
case ColorSilver:
|
||||
return 0x7
|
||||
// bright variants
|
||||
case ColorGrey:
|
||||
return 0x8
|
||||
case ColorRed:
|
||||
return 0xc
|
||||
case ColorLime:
|
||||
return 0xa
|
||||
case ColorBlue:
|
||||
return 0x9
|
||||
case ColorYellow:
|
||||
return 0xe
|
||||
case ColorFuchsia:
|
||||
return 0xd
|
||||
case ColorAqua:
|
||||
return 0xb
|
||||
case ColorWhite:
|
||||
return 0xf
|
||||
if vc, ok := vgaColors[c]; ok {
|
||||
return vc
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
3
event.go
3
event.go
@ -31,14 +31,17 @@ type EventTime struct {
|
||||
when time.Time
|
||||
}
|
||||
|
||||
// When returns the time stamp when the event occurred.
|
||||
func (e *EventTime) When() time.Time {
|
||||
return e.when
|
||||
}
|
||||
|
||||
// SetEventTime sets the time of occurrence for the event.
|
||||
func (e *EventTime) SetEventTime(t time.Time) {
|
||||
e.when = t
|
||||
}
|
||||
|
||||
// SetEventNow sets the time of occurrence for the event to the current time.
|
||||
func (e *EventTime) SetEventNow() {
|
||||
e.SetEventTime(time.Now())
|
||||
}
|
||||
|
198
key.go
198
key.go
@ -78,6 +78,128 @@ func (ev *EventKey) Modifiers() ModMask {
|
||||
return ev.mod
|
||||
}
|
||||
|
||||
var keyNames = map[Key]string{
|
||||
KeySpace: "Space",
|
||||
KeyEnter: "Enter",
|
||||
KeyBackspace: "Backspace",
|
||||
KeyTab: "Tab",
|
||||
KeyBacktab: "Backtab",
|
||||
KeyEsc: "Esc",
|
||||
KeyBackspace2: "Backspace2",
|
||||
KeyDelete: "Delete",
|
||||
KeyInsert: "Insert",
|
||||
KeyUp: "Up",
|
||||
KeyDown: "Down",
|
||||
KeyLeft: "Left",
|
||||
KeyRight: "Right",
|
||||
KeyHome: "Home",
|
||||
KeyEnd: "End",
|
||||
KeyUpLeft: "UpLeft",
|
||||
KeyUpRight: "UpRight",
|
||||
KeyDownLeft: "DownLeft",
|
||||
KeyDownRight: "DownRight",
|
||||
KeyCenter: "Center",
|
||||
KeyPgDn: "PgDn",
|
||||
KeyPgUp: "PgUp",
|
||||
KeyClear: "Clear",
|
||||
KeyExit: "Exit",
|
||||
KeyCancel: "Cancel",
|
||||
KeyPause: "Pause",
|
||||
KeyPrint: "Print",
|
||||
KeyF1: "F1",
|
||||
KeyF2: "F2",
|
||||
KeyF3: "F3",
|
||||
KeyF4: "F4",
|
||||
KeyF5: "F5",
|
||||
KeyF6: "F6",
|
||||
KeyF7: "F7",
|
||||
KeyF8: "F8",
|
||||
KeyF9: "F9",
|
||||
KeyF10: "F10",
|
||||
KeyF11: "F11",
|
||||
KeyF12: "F12",
|
||||
KeyF13: "F13",
|
||||
KeyF14: "F14",
|
||||
KeyF15: "F15",
|
||||
KeyF16: "F16",
|
||||
KeyF17: "F17",
|
||||
KeyF18: "F18",
|
||||
KeyF19: "F19",
|
||||
KeyF20: "F20",
|
||||
KeyF21: "F21",
|
||||
KeyF22: "F22",
|
||||
KeyF23: "F23",
|
||||
KeyF24: "F24",
|
||||
KeyF25: "F25",
|
||||
KeyF26: "F26",
|
||||
KeyF27: "F27",
|
||||
KeyF28: "F28",
|
||||
KeyF29: "F29",
|
||||
KeyF30: "F30",
|
||||
KeyF31: "F31",
|
||||
KeyF32: "F32",
|
||||
KeyF33: "F33",
|
||||
KeyF34: "F34",
|
||||
KeyF35: "F35",
|
||||
KeyF36: "F36",
|
||||
KeyF37: "F37",
|
||||
KeyF38: "F38",
|
||||
KeyF39: "F39",
|
||||
KeyF40: "F40",
|
||||
KeyF41: "F41",
|
||||
KeyF42: "F42",
|
||||
KeyF43: "F43",
|
||||
KeyF44: "F44",
|
||||
KeyF45: "F45",
|
||||
KeyF46: "F46",
|
||||
KeyF47: "F47",
|
||||
KeyF48: "F48",
|
||||
KeyF49: "F49",
|
||||
KeyF50: "F50",
|
||||
KeyF51: "F51",
|
||||
KeyF52: "F52",
|
||||
KeyF53: "F53",
|
||||
KeyF54: "F54",
|
||||
KeyF55: "F55",
|
||||
KeyF56: "F56",
|
||||
KeyF57: "F57",
|
||||
KeyF58: "F58",
|
||||
KeyF59: "F59",
|
||||
KeyF60: "F60",
|
||||
KeyF61: "F61",
|
||||
KeyF62: "F62",
|
||||
KeyF63: "F63",
|
||||
KeyF64: "F64",
|
||||
KeyCtrlA: "Ctrl-A",
|
||||
KeyCtrlB: "Ctrl-B",
|
||||
KeyCtrlC: "Ctrl-C",
|
||||
KeyCtrlD: "Ctrl-D",
|
||||
KeyCtrlE: "Ctrl-E",
|
||||
KeyCtrlF: "Ctrl-F",
|
||||
KeyCtrlG: "Ctrl-G",
|
||||
KeyCtrlJ: "Ctrl-J",
|
||||
KeyCtrlK: "Ctrl-K",
|
||||
KeyCtrlL: "Ctrl-L",
|
||||
KeyCtrlN: "Ctrl-N",
|
||||
KeyCtrlO: "Ctrl-O",
|
||||
KeyCtrlP: "Ctrl-P",
|
||||
KeyCtrlQ: "Ctrl-Q",
|
||||
KeyCtrlR: "Ctrl-R",
|
||||
KeyCtrlS: "Ctrl-S",
|
||||
KeyCtrlT: "Ctrl-T",
|
||||
KeyCtrlU: "Ctrl-U",
|
||||
KeyCtrlV: "Ctrl-V",
|
||||
KeyCtrlW: "Ctrl-W",
|
||||
KeyCtrlX: "Ctrl-X",
|
||||
KeyCtrlY: "Ctrl-Y",
|
||||
KeyCtrlZ: "Ctrl-Z",
|
||||
KeyCtrlSpace: "Ctrl-Space",
|
||||
KeyCtrlUnderscore: "Ctrl-_",
|
||||
KeyCtrlRightSq: "Ctrl-]",
|
||||
KeyCtrlBackslash: "Ctrl-\\",
|
||||
KeyCtrlCarat: "Ctrl-^",
|
||||
}
|
||||
|
||||
// Name returns a printable value or the key stroke. This can be used
|
||||
// when printing the event, for example.
|
||||
func (ev *EventKey) Name() string {
|
||||
@ -96,84 +218,14 @@ func (ev *EventKey) Name() string {
|
||||
m = append(m, "Ctrl")
|
||||
}
|
||||
|
||||
switch ev.key {
|
||||
case KeyRune:
|
||||
ok := false
|
||||
if s, ok = keyNames[ev.key]; !ok {
|
||||
if ev.key == KeyRune {
|
||||
s = "Rune[" + string(ev.ch) + "]"
|
||||
case KeySpace:
|
||||
s = "Space"
|
||||
case KeyEnter:
|
||||
s = "Enter"
|
||||
case KeyBackspace:
|
||||
s = "Backspace"
|
||||
case KeyTab:
|
||||
s = "Tab"
|
||||
case KeyBacktab:
|
||||
s = "Backtab"
|
||||
case KeyEsc:
|
||||
s = "Esc"
|
||||
case KeyBackspace2:
|
||||
s = "Backspace2"
|
||||
case KeyDelete:
|
||||
s = "Delete"
|
||||
case KeyInsert:
|
||||
s = "Insert"
|
||||
case KeyUp:
|
||||
s = "Up"
|
||||
case KeyDown:
|
||||
s = "Down"
|
||||
case KeyLeft:
|
||||
s = "Left"
|
||||
case KeyRight:
|
||||
s = "Right"
|
||||
case KeyHome:
|
||||
s = "Home"
|
||||
case KeyEnd:
|
||||
s = "End"
|
||||
case KeyUpLeft:
|
||||
s = "UpLeft"
|
||||
case KeyUpRight:
|
||||
s = "UpRight"
|
||||
case KeyDownLeft:
|
||||
s = "DownLeft"
|
||||
case KeyDownRight:
|
||||
s = "DownRight"
|
||||
case KeyCenter:
|
||||
s = "Center"
|
||||
case KeyPgDn:
|
||||
s = "PgDn"
|
||||
case KeyPgUp:
|
||||
s = "PgUp"
|
||||
case KeyClear:
|
||||
s = "Clear"
|
||||
case KeyExit:
|
||||
s = "Exit"
|
||||
case KeyCancel:
|
||||
s = "Cancel"
|
||||
case KeyPause:
|
||||
s = "Pause"
|
||||
case KeyPrint:
|
||||
s = "Print"
|
||||
case KeyCtrlSpace:
|
||||
s = "Ctrl-Space"
|
||||
case KeyCtrlUnderscore:
|
||||
s = "Ctrl-_"
|
||||
case KeyCtrlRightSq:
|
||||
s = "Ctrl-]"
|
||||
case KeyCtrlBackslash:
|
||||
s = "Ctrl-\\"
|
||||
case KeyCtrlCarat:
|
||||
s = "Ctrl-^"
|
||||
default:
|
||||
if ev.key >= KeyF1 && ev.key <= KeyF64 {
|
||||
s = fmt.Sprintf("F%d", int(ev.key-KeyF1)+1)
|
||||
} else if ev.key >= KeyCtrlA && ev.key <= KeyCtrlZ {
|
||||
s = fmt.Sprintf("Ctrl-%c",
|
||||
rune(ev.key-KeyCtrlA)+'A')
|
||||
} else {
|
||||
s = fmt.Sprintf("Key[%d,%d]", ev.key, int(ev.ch))
|
||||
}
|
||||
}
|
||||
|
||||
if len(m) != 0 {
|
||||
if ev.mod&ModCtrl != 0 && strings.HasPrefix(s, "Ctrl-") {
|
||||
s = s[5:]
|
||||
|
@ -226,11 +226,7 @@ func (s *simscreen) drawCell(x, y int) int {
|
||||
|
||||
l := utf8.EncodeRune(ubuf, r)
|
||||
|
||||
if enc := s.encoder; enc != nil {
|
||||
nout, _, _ = enc.Transform(lbuf, ubuf[:l], true)
|
||||
} else {
|
||||
nout = 0
|
||||
}
|
||||
nout, _, _ = s.encoder.Transform(lbuf, ubuf[:l], true)
|
||||
|
||||
if nout == 0 || lbuf[0] == '\x1a' {
|
||||
|
||||
@ -398,46 +394,17 @@ outer:
|
||||
continue
|
||||
}
|
||||
|
||||
switch s.charset {
|
||||
case "UTF-8":
|
||||
r, l := utf8.DecodeRune(b)
|
||||
if r == utf8.RuneError && (l == 0 || l == 1) {
|
||||
failed = true
|
||||
// yank off one byte
|
||||
b = b[1:]
|
||||
} else {
|
||||
b = b[l:]
|
||||
ev := NewEventKey(KeyRune, r, ModNone)
|
||||
s.PostEvent(ev)
|
||||
continue
|
||||
}
|
||||
|
||||
case "US-ASCII":
|
||||
// ASCII cannot generate this, so most likely it was
|
||||
// entered as an Alt sequence
|
||||
ev := NewEventKey(KeyRune, rune(b[0]-128), ModAlt)
|
||||
s.PostEvent(ev)
|
||||
b = b[1:]
|
||||
continue
|
||||
|
||||
default:
|
||||
utfb := make([]byte, len(b)*4) // worst case
|
||||
dec := s.decoder
|
||||
if dec == nil {
|
||||
failed = true
|
||||
b = b[1:]
|
||||
continue
|
||||
}
|
||||
|
||||
// take care to consume at *most* a single rune
|
||||
for l := 1; l < len(b); l++ {
|
||||
dec.Reset()
|
||||
nout, nin, _ := dec.Transform(utfb, b[:l], true)
|
||||
s.decoder.Reset()
|
||||
nout, nin, _ := s.decoder.Transform(utfb, b[:l], true)
|
||||
|
||||
if nout != 0 {
|
||||
r, _ := utf8.DecodeRune(utfb[:nout])
|
||||
if r != utf8.RuneError {
|
||||
ev := NewEventKey(KeyRune, r, ModNone)
|
||||
s.PostEvent(ev)
|
||||
}
|
||||
b = b[nin:]
|
||||
continue outer
|
||||
}
|
||||
@ -446,7 +413,6 @@ outer:
|
||||
b = b[1:]
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return failed == false
|
||||
}
|
||||
|
4
style.go
4
style.go
@ -77,7 +77,7 @@ func (s Style) Decompose() (fg Color, bg Color, attr AttrMask) {
|
||||
} else {
|
||||
bg = ColorDefault
|
||||
}
|
||||
attr = AttrMask(s) & AttrMaskAll
|
||||
attr = AttrMask(s) & attrAll
|
||||
|
||||
return fg, bg, attr
|
||||
}
|
||||
@ -91,7 +91,7 @@ func (s Style) setAttrs(attrs Style, on bool) Style {
|
||||
|
||||
// Normal returns the style with all attributes disabled.
|
||||
func (s Style) Normal() Style {
|
||||
return s &^ Style(AttrMaskAll)
|
||||
return s &^ Style(attrAll)
|
||||
}
|
||||
|
||||
// Bold returns a new style based on s, with the bold attribute set
|
||||
|
@ -25,6 +25,7 @@ import (
|
||||
var screen tcell.Screen
|
||||
var outMode OutputMode
|
||||
|
||||
// Init initializes the screen for use.
|
||||
func Init() error {
|
||||
outMode = OutputNormal
|
||||
if s, e := tcell.NewScreen(); e != nil {
|
||||
@ -37,23 +38,28 @@ func Init() error {
|
||||
}
|
||||
}
|
||||
|
||||
// Close cleans up the terminal, restoring terminal modes, etc.
|
||||
func Close() {
|
||||
screen.Fini()
|
||||
}
|
||||
|
||||
// Flush updates the screen.
|
||||
func Flush() error {
|
||||
screen.Show()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCursor displays the terminal cursor at the given location.
|
||||
func SetCursor(x, y int) {
|
||||
screen.ShowCursor(x, y)
|
||||
}
|
||||
|
||||
// HideCursor hides the terminal cursor.
|
||||
func HideCursor() {
|
||||
SetCursor(-1, -1)
|
||||
}
|
||||
|
||||
// Size returns the screen size as width, height in character cells.
|
||||
func Size() (int, int) {
|
||||
return screen.Size()
|
||||
}
|
||||
@ -122,18 +128,19 @@ func mkStyle(fg, bg Attribute) tcell.Style {
|
||||
b = tcell.ColorDefault
|
||||
}
|
||||
st = st.Foreground(f).Background(b)
|
||||
if (fg&AttrBold != 0) || (bg&AttrBold != 0) {
|
||||
if (fg|bg)&AttrBold != 0 {
|
||||
st = st.Bold(true)
|
||||
}
|
||||
if (fg&AttrUnderline != 0) || (bg&AttrUnderline != 0) {
|
||||
if (fg|bg)&AttrUnderline != 0 {
|
||||
st = st.Underline(true)
|
||||
}
|
||||
if (fg&AttrReverse != 0) || (bg&AttrReverse != 0) {
|
||||
if (fg|bg)&AttrReverse != 0 {
|
||||
st = st.Reverse(true)
|
||||
}
|
||||
return st
|
||||
}
|
||||
|
||||
// Clear clears the screen with the given attributes.
|
||||
func Clear(fg, bg Attribute) {
|
||||
st := mkStyle(fg, bg)
|
||||
w, h := screen.Size()
|
||||
@ -144,6 +151,7 @@ func Clear(fg, bg Attribute) {
|
||||
}
|
||||
}
|
||||
|
||||
// InputMode is not used.
|
||||
type InputMode int
|
||||
|
||||
const (
|
||||
@ -153,11 +161,14 @@ const (
|
||||
InputMouse
|
||||
)
|
||||
|
||||
// SetInputMode does not do anything in this version.
|
||||
func SetInputMode(mode InputMode) InputMode {
|
||||
// We don't do anything else right now
|
||||
return InputEsc
|
||||
}
|
||||
|
||||
// OutputMode represents an output mode, which determines how colors
|
||||
// are used. See the termbox documentation for an explanation.
|
||||
type OutputMode int
|
||||
|
||||
const (
|
||||
@ -168,6 +179,7 @@ const (
|
||||
OutputGrayscale
|
||||
)
|
||||
|
||||
// SetOutputMode is used to set the color palette used.
|
||||
func SetOutputMode(mode OutputMode) OutputMode {
|
||||
if screen.Colors() < 256 {
|
||||
mode = OutputNormal
|
||||
@ -183,20 +195,29 @@ func SetOutputMode(mode OutputMode) OutputMode {
|
||||
}
|
||||
}
|
||||
|
||||
// Sync forces a resync of the screen.
|
||||
func Sync() error {
|
||||
screen.Sync()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCell sets the character cell at a given location to the given
|
||||
// content (rune) and attributes.
|
||||
func SetCell(x, y int, ch rune, fg, bg Attribute) {
|
||||
st := mkStyle(fg, bg)
|
||||
screen.SetContent(x, y, ch, nil, st)
|
||||
}
|
||||
|
||||
// EventType represents the type of event.
|
||||
type EventType uint8
|
||||
|
||||
// Modifier represents the possible modifier keys.
|
||||
type Modifier tcell.ModMask
|
||||
|
||||
// Key is a key press.
|
||||
type Key tcell.Key
|
||||
|
||||
// Event represents an event like a key press, mouse action, or window resize.
|
||||
type Event struct {
|
||||
Type EventType
|
||||
Mod Modifier
|
||||
@ -309,25 +330,30 @@ func makeEvent(tev tcell.Event) Event {
|
||||
}
|
||||
}
|
||||
|
||||
// ParseEvent is not supported.
|
||||
func ParseEvent(data []byte) Event {
|
||||
// Not supported
|
||||
return Event{Type: EventError, Err: errors.New("no raw events")}
|
||||
}
|
||||
|
||||
// PollRawEvent is not supported.
|
||||
func PollRawEvent(data []byte) Event {
|
||||
// Not supported
|
||||
return Event{Type: EventError, Err: errors.New("no raw events")}
|
||||
}
|
||||
|
||||
// PollEvent blocks until an event is ready, and then returns it.
|
||||
func PollEvent() Event {
|
||||
ev := screen.PollEvent()
|
||||
return makeEvent(ev)
|
||||
}
|
||||
|
||||
// Interrupt posts an interrupt event.
|
||||
func Interrupt() {
|
||||
screen.PostEvent(tcell.NewEventInterrupt(nil))
|
||||
}
|
||||
|
||||
// Cell represents a single character cell on screen.
|
||||
type Cell struct {
|
||||
Ch rune
|
||||
Fg Attribute
|
||||
|
34
tscreen.go
34
tscreen.go
@ -97,7 +97,7 @@ func (t *tScreen) Init() error {
|
||||
t.indoneq = make(chan struct{})
|
||||
t.charset = "UTF-8"
|
||||
|
||||
t.charset = GetCharset()
|
||||
t.charset = getCharset()
|
||||
if enc := GetEncoding(t.charset); enc != nil {
|
||||
t.encoder = enc.NewEncoder()
|
||||
t.decoder = enc.NewDecoder()
|
||||
@ -679,6 +679,23 @@ func (t *tScreen) PostEvent(ev Event) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *tScreen) clip(x, y int) (int, int) {
|
||||
w, h := t.cells.Size()
|
||||
if x < 0 {
|
||||
x = 0
|
||||
}
|
||||
if y < 0 {
|
||||
y = 0
|
||||
}
|
||||
if x > w-1 {
|
||||
x = w - 1
|
||||
}
|
||||
if y > h-1 {
|
||||
y = h - 1
|
||||
}
|
||||
return x, y
|
||||
}
|
||||
|
||||
func (t *tScreen) postMouseEvent(x, y, btn int) {
|
||||
|
||||
// XTerm mouse events only report at most one button at a time,
|
||||
@ -733,19 +750,8 @@ func (t *tScreen) postMouseEvent(x, y, btn int) {
|
||||
// Some terminals will report mouse coordinates outside the
|
||||
// screen, especially with click-drag events. Clip the coordinates
|
||||
// to the screen in that case.
|
||||
if x < 0 {
|
||||
x = 0
|
||||
}
|
||||
if y < 0 {
|
||||
y = 0
|
||||
}
|
||||
w, h := t.cells.Size()
|
||||
if x > w-1 {
|
||||
x = w - 1
|
||||
}
|
||||
if y > h-1 {
|
||||
y = h - 1
|
||||
}
|
||||
x, y = t.clip(x, y)
|
||||
|
||||
ev := NewEventMouse(x, y, button, mod)
|
||||
t.PostEvent(ev)
|
||||
}
|
||||
|
@ -40,37 +40,22 @@ type boxLayoutCell struct {
|
||||
view *ViewPort
|
||||
}
|
||||
|
||||
func (b *BoxLayout) layout() {
|
||||
if b.view == nil {
|
||||
return
|
||||
}
|
||||
func (b *BoxLayout) hLayout() {
|
||||
w, h := b.view.Size()
|
||||
|
||||
minx, miny, totx, toty := 0, 0, 0, 0
|
||||
totf := 0.0
|
||||
for _, c := range b.cells {
|
||||
x, y := c.widget.Size()
|
||||
totx += x
|
||||
toty += y
|
||||
totf += c.fill
|
||||
if x > minx {
|
||||
minx = x
|
||||
}
|
||||
if y > miny {
|
||||
miny = y
|
||||
b.width += x
|
||||
if y > b.height {
|
||||
b.height = y
|
||||
}
|
||||
c.pad = 0
|
||||
c.frac = 0
|
||||
}
|
||||
|
||||
extra := 0
|
||||
if b.orient == Horizontal {
|
||||
extra = w - totx
|
||||
b.width = totx
|
||||
b.height = miny
|
||||
} else {
|
||||
extra = h - toty
|
||||
b.width = minx
|
||||
b.height = toty
|
||||
}
|
||||
extra := w - b.width
|
||||
if extra < 0 {
|
||||
extra = 0
|
||||
}
|
||||
@ -85,9 +70,6 @@ func (b *BoxLayout) layout() {
|
||||
c.pad = int(c.frac)
|
||||
c.frac -= float64(c.pad)
|
||||
resid -= c.pad
|
||||
} else {
|
||||
c.pad = 0
|
||||
c.frac = 0
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,28 +91,93 @@ func (b *BoxLayout) layout() {
|
||||
resid--
|
||||
}
|
||||
|
||||
x, y, xinc, yinc := 0, 0, 0, 0
|
||||
x, y, xinc := 0, 0, 0
|
||||
for _, c := range b.cells {
|
||||
cw, ch := c.widget.Size()
|
||||
cw, _ := c.widget.Size()
|
||||
|
||||
switch b.orient {
|
||||
case Horizontal:
|
||||
xinc = cw + c.pad
|
||||
cw += c.pad
|
||||
ch = h
|
||||
|
||||
case Vertical:
|
||||
c.view.Resize(x, y, cw, h)
|
||||
x += xinc
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BoxLayout) vLayout() {
|
||||
w, h := b.view.Size()
|
||||
|
||||
totf := 0.0
|
||||
for _, c := range b.cells {
|
||||
x, y := c.widget.Size()
|
||||
b.height += y
|
||||
totf += c.fill
|
||||
if x > b.width {
|
||||
b.width = x
|
||||
}
|
||||
c.pad = 0
|
||||
c.frac = 0
|
||||
}
|
||||
|
||||
extra := h - b.height
|
||||
if extra < 0 {
|
||||
extra = 0
|
||||
}
|
||||
|
||||
resid := extra
|
||||
if totf == 0 {
|
||||
resid = 0
|
||||
}
|
||||
|
||||
for _, c := range b.cells {
|
||||
if c.fill > 0 {
|
||||
c.frac = float64(extra) * c.fill / totf
|
||||
c.pad = int(c.frac)
|
||||
c.frac -= float64(c.pad)
|
||||
resid -= c.pad
|
||||
}
|
||||
}
|
||||
|
||||
// Distribute any left over padding. We try to give it to the
|
||||
// the cells with the highest residual fraction. It should be
|
||||
// the case that no single cell gets more than one more cell.
|
||||
for resid > 0 {
|
||||
var best *boxLayoutCell
|
||||
for _, c := range b.cells {
|
||||
if c.fill == 0 {
|
||||
continue
|
||||
}
|
||||
if best == nil || c.frac > best.frac {
|
||||
best = c
|
||||
}
|
||||
}
|
||||
best.pad++
|
||||
best.frac = 0
|
||||
resid--
|
||||
}
|
||||
|
||||
x, y, yinc := 0, 0, 0
|
||||
for _, c := range b.cells {
|
||||
_, ch := c.widget.Size()
|
||||
|
||||
yinc = ch + c.pad
|
||||
ch += c.pad
|
||||
cw = w
|
||||
c.view.Resize(x, y, w, ch)
|
||||
y += yinc
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BoxLayout) layout() {
|
||||
if b.view == nil {
|
||||
return
|
||||
}
|
||||
b.width, b.height = 0, 0
|
||||
switch b.orient {
|
||||
case Horizontal:
|
||||
b.hLayout()
|
||||
case Vertical:
|
||||
b.vLayout()
|
||||
default:
|
||||
panic("Bad orientation")
|
||||
|
||||
}
|
||||
c.view.Resize(x, y, cw, ch)
|
||||
x += xinc
|
||||
y += yinc
|
||||
}
|
||||
b.changed = false
|
||||
}
|
||||
|
@ -36,40 +36,63 @@ type Text struct {
|
||||
WidgetWatchers
|
||||
}
|
||||
|
||||
func (t *Text) clear() {
|
||||
v := t.view
|
||||
w, h := v.Size()
|
||||
v.Clear()
|
||||
for y := 0; y < h; y++ {
|
||||
for x := 0; x < w; x++ {
|
||||
v.SetContent(x, y, ' ', nil, t.style)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calcY figures the initial Y offset. Alignment is top by default.
|
||||
func (t *Text) calcY(height int) int {
|
||||
if t.align&VAlignCenter != 0 {
|
||||
return (height - len(t.lengths)) / 2
|
||||
}
|
||||
if t.align&VAlignBottom != 0 {
|
||||
return height - len(t.lengths)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// calcX figures the initial X offset for the given line.
|
||||
// Alignment is left by default.
|
||||
func (t *Text) calcX(width, line int) int {
|
||||
if t.align&HAlignCenter != 0 {
|
||||
return (width - t.lengths[line]) / 2
|
||||
}
|
||||
if t.align&HAlignRight != 0 {
|
||||
return width - t.lengths[line]
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Draw draws the Text.
|
||||
func (t *Text) Draw() {
|
||||
v := t.view
|
||||
if v == nil {
|
||||
return
|
||||
}
|
||||
var x, y int
|
||||
|
||||
width, height := v.Size()
|
||||
if width == 0 || height == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
v.Clear()
|
||||
for y := 0; y < height; y++ {
|
||||
for x := 0; x < width; x++ {
|
||||
v.SetContent(x, y, ' ', nil, t.style)
|
||||
}
|
||||
}
|
||||
t.clear()
|
||||
|
||||
// Note that we might wind up with a negative X if the width
|
||||
// is larger than the length. That's OK, and correct even.
|
||||
// The view will clip it properly in that case.
|
||||
|
||||
// We align to the left & top by default.
|
||||
if t.align&VAlignCenter != 0 {
|
||||
y = (height - 1) / 2
|
||||
} else if t.align&VAlignBottom != 0 {
|
||||
y = height - 1
|
||||
} else {
|
||||
y = 0
|
||||
}
|
||||
y := t.calcY(height)
|
||||
r := rune(0)
|
||||
w := 0
|
||||
x := 0
|
||||
var styl tcell.Style
|
||||
var comb []rune
|
||||
line := 0
|
||||
@ -77,13 +100,7 @@ func (t *Text) Draw() {
|
||||
for i, l := range t.text {
|
||||
|
||||
if newline {
|
||||
if t.align&HAlignCenter != 0 {
|
||||
x = (width - t.lengths[line]) / 2
|
||||
} else if t.align&HAlignRight != 0 {
|
||||
x = width - t.lengths[line]
|
||||
} else {
|
||||
x = 0
|
||||
}
|
||||
x = t.calcX(width, line)
|
||||
newline = false
|
||||
}
|
||||
if l == '\n' {
|
||||
|
Loading…
x
Reference in New Issue
Block a user