on de65cb2 help sign in
vty/src/Graphics/Vty/Attributes.hs
225 lines 7.6 kB history raw
1-- Copyright 2009-2010 Corey O'Connor
2-- Display attributes
3--
4-- For efficiency this can be, in the future, encoded into a single 32 bit word. The 32 bit word is
5-- first divided into 4 groups of 8 bits where:
6-- The first group codes what action should be taken with regards to the other groups.
7-- XXYYZZ__
8-- XX - style action
9-- 00 => reset to default
10-- 01 => unchanged
11-- 10 => set
12-- YY - foreground color action
13-- 00 => reset to default
14-- 01 => unchanged
15-- 10 => set
16-- ZZ - background color action
17-- 00 => reset to default
18-- 01 => unchanged
19-- 10 => set
20-- __ - unused
21--
22-- Next is the style flags
23-- SURBDO__
24-- S - standout
25-- U - underline
26-- R - reverse video
27-- B - blink
28-- D - dim
29-- O - bold
30-- __ - unused
31--
32-- Then the foreground color encoded into 8 bits.
33-- Then the background color encoded into 8 bits.
34--
35module Graphics.Vty.Attributes
36 where
38import Data.Bits
39import Data.Monoid
40import Data.Word
42-- | A display attribute defines the Color and Style of all the characters rendered after the
43-- attribute is applied.
44--
45-- At most 256 colors, picked from a 240 and 16 color palette, are possible for the background and
46-- foreground. The 240 colors and 16 colors are points in different palettes. See Color for more
47-- information.
48data Attr = Attr
49 { attr_style :: !(MaybeDefault Style)
50 , attr_fore_color :: !(MaybeDefault Color)
51 , attr_back_color :: !(MaybeDefault Color)
52 } deriving ( Eq, Show )
54instance Monoid Attr where
55 mempty = Attr mempty mempty mempty
56 mappend attr_0 attr_1 =
57 Attr ( attr_style attr_0 `mappend` attr_style attr_1 )
58 ( attr_fore_color attr_0 `mappend` attr_fore_color attr_1 )
59 ( attr_back_color attr_0 `mappend` attr_back_color attr_1 )
61-- | Specifies the display attributes such that the final style and color values do not depend on
62-- the previously applied display attribute. The display attributes can still depend on the
63-- terminal's default colors (unfortunately).
64data FixedAttr = FixedAttr
65 { fixed_style :: !Style
66 , fixed_fore_color :: !(Maybe Color)
67 , fixed_back_color :: !(Maybe Color)
68 } deriving ( Eq, Show )
70-- | The style and color attributes can either be the terminal defaults. Or be equivalent to the
71-- previously applied style. Or be a specific value.
72data Eq v => MaybeDefault v = Default | KeepCurrent | SetTo !v
73 deriving ( Eq, Show )
75instance Eq v => Monoid ( MaybeDefault v ) where
76 mempty = KeepCurrent
77 mappend Default Default = Default
78 mappend Default KeepCurrent = Default
79 mappend Default ( SetTo v ) = SetTo v
80 mappend KeepCurrent Default = Default
81 mappend KeepCurrent KeepCurrent = KeepCurrent
82 mappend KeepCurrent ( SetTo v ) = SetTo v
83 mappend ( SetTo _v ) Default = Default
84 mappend ( SetTo v ) KeepCurrent = SetTo v
85 mappend ( SetTo _ ) ( SetTo v ) = SetTo v
87-- | Abstract data type representing a color.
88--
89-- Currently the foreground and background color are specified as points in either a:
90--
91-- * 16 color palette. Where the first 8 colors are equal to the 8 colors of the ISO 6429 (ANSI) 8
92-- color palette and the second 8 colors are bright/vivid versions of the first 8 colors.
93--
94-- * 240 color palette. This palette is a regular sampling of the full RGB colorspace.
95--
96-- The 8 ISO 6429 (ANSI) colors are as follows:
97--
98-- 0. black
99--
100-- 1. red
101--
102-- 2. green
103--
104-- 3. yellow
105--
106-- 4. blue
107--
108-- 5. magenta
109--
110-- 6. cyan
111--
112-- 7. white
113--
114-- The mapping from points in the 240 color palette to colors actually displayable by the terminal
115-- depends on the number of colors the terminal claims to support. Which is usually determined by
116-- the terminfo "colors" property. If this property is not being accurately reported then the color
117-- reproduction will be incorrect.
118--
119-- If the terminal reports <= 16 colors then the 240 color palette points are only mapped to the 8
120-- color pallete. I'm not sure of the RGB points for the "bright" colors which is why they are not
121-- addressable via the 240 color palette.
122--
123-- If the terminal reports > 16 colors then the 240 color palette points are mapped to the nearest
124-- points in a ("color count" - 16) subsampling of the 240 color palette.
125--
126-- All of this assumes the terminals are behaving similarly to xterm and rxvt when handling colors.
127-- And that the individual colors have not been remapped by the user. There may be a way to verify
128-- this through terminfo but I don't know it.
129--
130-- Seriously, terminal color support is INSANE.
131data Color = ISOColor !Word8 | Color240 !Word8
132 deriving ( Eq, Show )
134-- | Standard 8-color ANSI terminal color codes.
135black, red, green, yellow, blue, magenta, cyan, white :: Color
136black = ISOColor 0
137red = ISOColor 1
138green = ISOColor 2
139yellow = ISOColor 3
140blue = ISOColor 4
141magenta= ISOColor 5
142cyan = ISOColor 6
143white = ISOColor 7
145-- | Bright/Vivid variants of the standard 8-color ANSI
146bright_black, bright_red, bright_green, bright_yellow :: Color
147bright_blue, bright_magenta, bright_cyan, bright_white :: Color
148bright_black = ISOColor 8
149bright_red = ISOColor 9
150bright_green = ISOColor 10
151bright_yellow = ISOColor 11
152bright_blue = ISOColor 12
153bright_magenta= ISOColor 13
154bright_cyan = ISOColor 14
155bright_white = ISOColor 15
157-- | Styles are represented as an 8 bit word. Each bit in the word is 1 if the style attribute
158-- assigned to that bit should be applied and 0 if the style attribute should not be applied.
159type Style = Word8
161-- | The 6 possible style attributes:
162--
163-- * standout
164--
165-- * underline
166--
167-- * reverse_video
168--
169-- * blink
170--
171-- * dim
172--
173-- * bold/bright
174--
175-- ( The invisible, protect, and altcharset display attributes some terminals support are not
176-- supported via VTY.)
177standout, underline, reverse_video, blink, dim, bold :: Style
178standout = 0x01
179underline = 0x02
180reverse_video = 0x04
181blink = 0x08
182dim = 0x10
183bold = 0x20
185default_style_mask :: Style
186default_style_mask = 0x00
188style_mask :: Attr -> Word8
189style_mask attr
190 = case attr_style attr of
191 Default -> 0
192 KeepCurrent -> 0
193 SetTo v -> v
195-- | true if the given Style value has the specified Style set.
196has_style :: Style -> Style -> Bool
197has_style s bit_mask = ( s .&. bit_mask ) /= 0
199-- | Set the foreground color of an `Attr'.
200with_fore_color :: Attr -> Color -> Attr
201with_fore_color attr c = attr { attr_fore_color = SetTo c }
203-- | Set the background color of an `Attr'.
204with_back_color :: Attr -> Color -> Attr
205with_back_color attr c = attr { attr_back_color = SetTo c }
207-- | Add the given style attribute
208with_style :: Attr -> Style -> Attr
209with_style attr style_flag = attr { attr_style = SetTo $ style_mask attr .|. style_flag }
211-- | Sets the style, background color and foreground color to the default values for the terminal.
212-- There is no easy way to determine what the default background and foreground colors are.
213def_attr :: Attr
214def_attr = Attr Default Default Default
216-- | Keeps the style, background color and foreground color that was previously set. Used to
217-- override some part of the previous style.
218--
219-- EG: current_style `with_fore_color` bright_magenta
220--
221-- Would be the currently applied style (be it underline, bold, etc) but with the foreground color
222-- set to bright_magenta.
223current_attr :: Attr
224current_attr = Attr KeepCurrent KeepCurrent KeepCurrent