// Copyright 2020 The gocui Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gocui import "github.com/gdamore/tcell/v2" // Attribute affects the presentation of characters, such as color, boldness, etc. type Attribute uint64 const ( // ColorDefault is used to leave the Color unchanged from whatever system or teminal default may exist. ColorDefault = Attribute(tcell.ColorDefault) // AttrIsValidColor is used to indicate the color value is actually // valid (initialized). This is useful to permit the zero value // to be treated as the default. AttrIsValidColor = Attribute(tcell.ColorValid) // AttrIsRGBColor is used to indicate that the Attribute value is RGB value of color. // The lower order 3 bytes are RGB. // (It's not a color in basic ANSI range 256). AttrIsRGBColor = Attribute(tcell.ColorIsRGB) // AttrColorBits is a mask where color is located in Attribute AttrColorBits = 0xffffffffff // roughly 5 bytes, tcell uses 4 bytes and half-byte as a special flags for color (rest is reserved for future) // AttrStyleBits is a mask where character attributes (e.g.: bold, italic, underline) are located in Attribute AttrStyleBits = 0xffffff0000000000 // remaining 3 bytes in the 8 bytes Attribute (tcell is not using it, so we should be fine) ) // Color attributes. These colors are compatible with tcell.Color type and can be expanded like: // g.FgColor := gocui.Attribute(tcell.ColorLime) const ( ColorBlack Attribute = AttrIsValidColor + iota ColorRed ColorGreen ColorYellow ColorBlue ColorMagenta ColorCyan ColorWhite ) // grayscale indexes (for backward compatibility with termbox-go original grayscale) var grayscale = []tcell.Color{ 16, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 231, } // Attributes are not colors, but effects (e.g.: bold, dim) which affect the display of text. // They can be combined. const ( AttrBold Attribute = 1 << (40 + iota) AttrBlink AttrReverse AttrUnderline AttrDim AttrItalic AttrStrikeThrough AttrNone Attribute = 0 // Just normal text. ) // AttrAll represents all the text effect attributes turned on const AttrAll = AttrBold | AttrBlink | AttrReverse | AttrUnderline | AttrDim | AttrItalic // IsValidColor indicates if the Attribute is a valid color value (has been set). func (a Attribute) IsValidColor() bool { return a&AttrIsValidColor != 0 } // 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. // // This function produce the same output as `tcell.Hex()` with additional // support for `termbox-go` colors (to 256). func (a Attribute) Hex() int32 { if !a.IsValidColor() { return -1 } tc := getTcellColor(a, OutputTrue) return tc.Hex() } // RGB returns the red, green, and blue components of the color, with // each component represented as a value 0-255. If the color // is unknown or unset, -1 is returned for each component. // // This function produce the same output as `tcell.RGB()` with additional // support for `termbox-go` colors (to 256). func (a Attribute) RGB() (int32, int32, int32) { v := a.Hex() if v < 0 { return -1, -1, -1 } return (v >> 16) & 0xff, (v >> 8) & 0xff, v & 0xff } // 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(color string) Attribute { return Attribute(tcell.GetColor(color)) } // Get256Color creates Attribute which stores ANSI color (0-255) func Get256Color(color int32) Attribute { return Attribute(color) | AttrIsValidColor } // GetRGBColor creates Attribute which stores RGB color. // Color is passed as 24bit RGB value, where R << 16 | G << 8 | B func GetRGBColor(color int32) Attribute { return Attribute(color) | AttrIsValidColor | AttrIsRGBColor } // NewRGBColor creates Attribute which stores RGB color. func NewRGBColor(r, g, b int32) Attribute { return Attribute(tcell.NewRGBColor(r, g, b)) } // getTcellColor transform Attribute into tcell.Color func getTcellColor(c Attribute, omode OutputMode) tcell.Color { c = c & AttrColorBits // Default color is 0 in tcell/v2 and was 0 in termbox-go, so we are good here if c == ColorDefault { return tcell.ColorDefault } tc := tcell.ColorDefault // Check if we have valid color if c.IsValidColor() { tc = tcell.Color(c) } else if c > 0 && c <= 256 { // It's not valid color, but it has value in range 1-256 // This is old Attribute style of color from termbox-go (black=1, etc.) // convert to tcell color (black=0|ColorValid) tc = tcell.Color(c-1) | tcell.ColorValid } switch omode { case OutputTrue: return tc case OutputNormal: tc &= tcell.Color(0xf) | tcell.ColorValid case Output256: tc &= tcell.Color(0xff) | tcell.ColorValid case Output216: tc &= tcell.Color(0xff) if tc > 215 { return tcell.ColorDefault } tc += tcell.Color(16) | tcell.ColorValid case OutputGrayscale: tc &= tcell.Color(0x1f) if tc > 26 { return tcell.ColorDefault } tc = grayscale[tc] | tcell.ColorValid default: return tcell.ColorDefault } return tc }