@@ -25,7 +25,7 @@ import Graphics.Vty.Image (DisplayRegion)
25import Graphics.Vty.DisplayAttributes
25import Graphics.Vty.DisplayAttributes
26import Graphics.Vty.Output.Interface
26import Graphics.Vty.Output.Interface
28−import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable)
28+import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable, writeWord8)
30import Data.IORef
30import Data.IORef
31import Data.Maybe (isJust, isNothing, fromJust)
31import Data.Maybe (isJust, isNothing, fromJust)
@@ -49,7 +49,6 @@ data TerminfoCaps = TerminfoCaps
49 , cup :: CapExpression
49 , cup :: CapExpression
50 , cnorm :: Maybe CapExpression
50 , cnorm :: Maybe CapExpression
51 , civis :: Maybe CapExpression
51 , civis :: Maybe CapExpression
52− , supportsNoColors :: Bool
53 , useAltColorMap :: Bool
52 , useAltColorMap :: Bool
54 , setForeColor :: CapExpression
53 , setForeColor :: CapExpression
55 , setBackColor :: CapExpression
54 , setBackColor :: CapExpression
@@ -104,28 +103,28 @@ sendCapToTerminal t cap capParams = do
105-- * Providing independent string capabilities for all display
104-- * Providing independent string capabilities for all display
106-- attributes.
105-- attributes.
107−reserveTerminal :: String -> Fd -> IO Output
106+reserveTerminal :: String -> Fd -> ColorMode -> IO Output
108−reserveTerminal termName outFd = do
107+reserveTerminal termName outFd colorMode = do
109 ti <- Terminfo.setupTerm termName
108 ti <- Terminfo.setupTerm termName
110 -- assumes set foreground always implies set background exists.
109 -- assumes set foreground always implies set background exists.
111 -- if set foreground is not set then all color changing style
110 -- if set foreground is not set then all color changing style
112 -- attributes are filtered.
111 -- attributes are filtered.
113 msetaf <- probeCap ti "setaf"
112 msetaf <- probeCap ti "setaf"
114 msetf <- probeCap ti "setf"
113 msetf <- probeCap ti "setf"
115− let (noColors, useAlt, setForeCap)
114+ let (useAlt, setForeCap)
116 = case msetaf of
115 = case msetaf of
117− Just setaf -> (False, False, setaf)
116+ Just setaf -> (False, setaf)
118 Nothing -> case msetf of
117 Nothing -> case msetf of
119− Just setf -> (False, True, setf)
118+ Just setf -> (True, setf)
120− Nothing -> (True, True, error $ "no fore color support for terminal " ++ termName)
119+ Nothing -> (True, error $ "no fore color support for terminal " ++ termName)
121 msetab <- probeCap ti "setab"
120 msetab <- probeCap ti "setab"
122 msetb <- probeCap ti "setb"
121 msetb <- probeCap ti "setb"
123− let set_back_cap
122+ let setBackCap
124 = case msetab of
123 = case msetab of
125 Nothing -> case msetb of
125 Nothing -> case msetb of
126 Just setb -> setb
126 Just setb -> setb
127 Nothing -> error $ "no back color support for terminal " ++ termName
127 Nothing -> error $ "no back color support for terminal " ++ termName
130 hyperlinkModeStatus <- newIORef False
129 hyperlinkModeStatus <- newIORef False
131 newAssumedStateRef <- newIORef initialAssumedState
130 newAssumedStateRef <- newIORef initialAssumedState
@@ -151,10 +150,9 @@ reserveTerminal termName outFd = do
151 <*> requireCap ti "cup"
150 <*> requireCap ti "cup"
152 <*> probeCap ti "cnorm"
151 <*> probeCap ti "cnorm"
153 <*> probeCap ti "civis"
152 <*> probeCap ti "civis"
155 <*> pure useAlt
153 <*> pure useAlt
156 <*> pure setForeCap
154 <*> pure setForeCap
157− <*> pure set_back_cap
155+ <*> pure setBackCap
158 <*> requireCap ti "sgr0"
156 <*> requireCap ti "sgr0"
159 <*> requireCap ti "clear"
157 <*> requireCap ti "clear"
160 <*> requireCap ti "el"
158 <*> requireCap ti "el"
@@ -194,17 +192,12 @@ reserveTerminal termName outFd = do
194 when (toEnum len /= actualLen) $ fail $ "Graphics.Vty.Output: outputByteBuffer "
192 when (toEnum len /= actualLen) $ fail $ "Graphics.Vty.Output: outputByteBuffer "
195 ++ "length mismatch. " ++ show len ++ " /= " ++ show actualLen
193 ++ "length mismatch. " ++ show len ++ " /= " ++ show actualLen
196 ++ " Please report this bug to vty project."
194 ++ " Please report this bug to vty project."
198− = case supportsNoColors terminfoCaps of
199− False -> case Terminfo.getCapability ti (Terminfo.tiGetNum "colors" ) of
203 , supportsCursorVisibility = isJust $ civis terminfoCaps
195 , supportsCursorVisibility = isJust $ civis terminfoCaps
204 , supportsMode = terminfoModeSupported
196 , supportsMode = terminfoModeSupported
205 , setMode = terminfoSetMode
197 , setMode = terminfoSetMode
206 , getModeStatus = terminfoModeStatus
198 , getModeStatus = terminfoModeStatus
207 , assumedStateRef = newAssumedStateRef
199 , assumedStateRef = newAssumedStateRef
200+ , outputColorMode = colorMode
208 -- I think fix would help assure tActual is the only
201 -- I think fix would help assure tActual is the only
209 -- reference. I was having issues tho.
202 -- reference. I was having issues tho.
210 , mkDisplayContext = (`terminfoDisplayContext` terminfoCaps)
203 , mkDisplayContext = (`terminfoDisplayContext` terminfoCaps)
@@ -302,7 +295,7 @@ writeURLEscapes NoLinkChange =
302-- | Portably setting the display attributes is a giant pain in the ass.
295-- | Portably setting the display attributes is a giant pain in the ass.
304-- If the terminal supports the sgr capability (which sets the on/off
297-- If the terminal supports the sgr capability (which sets the on/off
305−-- state of each style directly ; and, for no good reason, resets the
298+-- state of each style directly; and, for no good reason, resets the
306-- colors to the default) this procedure is used:
299-- colors to the default) this procedure is used:
308-- 0. set the style attributes. This resets the fore and back color.
301-- 0. set the style attributes. This resets the fore and back color.
@@ -341,9 +334,9 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
341 -- The only way to reset either color, portably, to the default
334 -- The only way to reset either color, portably, to the default
342 -- is to use either the set state capability or the set default
335 -- is to use either the set state capability or the set default
343 -- capability.
336 -- capability.
344− True -> do
337+ True -> do
345 case reqDisplayCapSeqFor (displayAttrCaps terminfoCaps)
338 case reqDisplayCapSeqFor (displayAttrCaps terminfoCaps)
346− (fixedStyle attr )
339+ (fixedStyle attr)
347 (styleToApplySeq $ fixedStyle attr) of
340 (styleToApplySeq $ fixedStyle attr) of
348 -- only way to reset a color to the defaults
341 -- only way to reset a color to the defaults
349 EnterExitSeq caps -> writeDefaultAttr dc urlsEnabled
342 EnterExitSeq caps -> writeDefaultAttr dc urlsEnabled
@@ -376,9 +369,9 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
376 -- applied states.
369 -- applied states.
377 EnterExitSeq caps -> foldMap (\cap -> writeCapExpr cap []) caps
370 EnterExitSeq caps -> foldMap (\cap -> writeCapExpr cap []) caps
378 `mappend`
371 `mappend`
379− writeColorDiff setForeColor (foreColorDiff diffs)
372+ writeColorDiff Foreground (foreColorDiff diffs)
380 `mappend`
373 `mappend`
381− writeColorDiff setBackColor (backColorDiff diffs)
374+ writeColorDiff Background (backColorDiff diffs)
382 -- implicitly resets the colors to the defaults
375 -- implicitly resets the colors to the defaults
383 SetState state -> writeCapExpr (fromJust $ setAttrStates
376 SetState state -> writeCapExpr (fromJust $ setAttrStates
384 $ displayAttrCaps terminfoCaps
377 $ displayAttrCaps terminfoCaps
@@ -410,20 +403,52 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
410 | otherwise = mempty
403 | otherwise = mempty
411 setColors =
404 setColors =
412 (case fixedForeColor attr of
405 (case fixedForeColor attr of
413− Just c -> writeCapExpr (setForeColor terminfoCaps)
406+ Just c -> writeColor Foreground c
414− [toEnum $ colorMap c]
415 Nothing -> mempty)
407 Nothing -> mempty)
416 `mappend`
408 `mappend`
417 (case fixedBackColor attr of
409 (case fixedBackColor attr of
418− Just c -> writeCapExpr (setBackColor terminfoCaps)
410+ Just c -> writeColor Background c
419− [toEnum $ colorMap c]
420 Nothing -> mempty)
411 Nothing -> mempty)
421− writeColorDiff _f NoColorChange
412+ writeColorDiff _side NoColorChange
423− writeColorDiff _f ColorToDefault
414+ writeColorDiff _side ColorToDefault
424 = error "ColorToDefault is not a possible case for applyColorDiffs"
415 = error "ColorToDefault is not a possible case for applyColorDiffs"
425− writeColorDiff f (SetColor c)
416+ writeColorDiff side (SetColor c)
419+ writeColor side (RGBColor r g b) =
420+ case outputColorMode (contextDevice dc) of
422+ hardcodeColor side (r, g, b)
424+ error "clampColor should remove rgb colors in standard mode"
426− = writeCapExpr (f terminfoCaps) [toEnum $ colorMap c]
426+ writeCapExpr (setSideColor side terminfoCaps) [toEnum $ colorMap c]
428+-- a color can either be in the foreground or the background
429+data ColorSide = Foreground | Background
431+-- get the capability for drawing a color on a specific side
432+setSideColor :: ColorSide -> TerminfoCaps -> CapExpression
433+setSideColor Foreground = setForeColor
434+setSideColor Background = setBackColor
436+hardcodeColor :: ColorSide -> (Word8, Word8, Word8) -> Write
437+hardcodeColor side (r, g, b) =
438+ -- hardcoded color codes are formatted as "\x1b[{side};2;{r};{g};{b}m"
439+ mconcat [ writeStr "\x1b[", sideCode, delimiter, writeChar '2', delimiter
440+ , writeColor r, delimiter, writeColor g, delimiter, writeColor b
443+ writeChar = writeWord8 . fromIntegral . fromEnum
444+ writeStr = mconcat . map writeChar
445+ writeColor = writeStr . show
446+ delimiter = writeChar ';'
447+ -- 38/48 are used to set whether we should write to the
448+ -- foreground/background. I really don't want to know why.
449+ sideCode = case side of
450+ Foreground -> writeStr "38"
451+ Background -> writeStr "48"
428-- | The color table used by a terminal is a 16 color set followed by a
453-- | The color table used by a terminal is a 16 color set followed by a
429-- 240 color set that might not be supported by the terminal.
454-- 240 color set that might not be supported by the terminal.
@@ -433,6 +458,10 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
433ansiColorIndex :: Color -> Int
458ansiColorIndex :: Color -> Int
434ansiColorIndex (ISOColor v) = fromEnum v
459ansiColorIndex (ISOColor v) = fromEnum v
435ansiColorIndex (Color240 v) = 16 + fromEnum v
460ansiColorIndex (Color240 v) = 16 + fromEnum v
461+ansiColorIndex (RGBColor _ _ _) =
462+ error $ unlines [ "Attempted to create color index from rgb color."
463+ , "This is currently unsupported, and shouldn't ever happen"
437-- | For terminals without setaf/setab
466-- | For terminals without setaf/setab
@@ -449,6 +478,10 @@ altColorIndex (ISOColor 6) = 3
449altColorIndex (ISOColor 7) = 7
478altColorIndex (ISOColor 7) = 7
450altColorIndex (ISOColor v) = fromEnum v
479altColorIndex (ISOColor v) = fromEnum v
451altColorIndex (Color240 v) = 16 + fromEnum v
480altColorIndex (Color240 v) = 16 + fromEnum v
481+altColorIndex (RGBColor _ _ _) =
482+ error $ unlines [ "Attempted to create color index from rgb color."
483+ , "This is currently unsupported, and shouldn't ever happen"
453{- | The sequence of terminfo caps to apply a given style are determined
486{- | The sequence of terminfo caps to apply a given style are determined
454 - according to these rules.
487 - according to these rules.