@@ -25,7 +25,7 @@ import Graphics.Vty.Image (DisplayRegion)
2525import Graphics.Vty.DisplayAttributes
2626import Graphics.Vty.Output.Interface
2727
28−import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable)
28+import Blaze.ByteString.Builder (Write, writeToByteString, writeStorable, writeWord8)
2929
3030import Data.IORef
3131import Data.Maybe (isJust, isNothing, fromJust)
@@ -49,7 +49,6 @@ data TerminfoCaps = TerminfoCaps
4949 , cup :: CapExpression
5050 , cnorm :: Maybe CapExpression
5151 , civis :: Maybe CapExpression
52− , supportsNoColors :: Bool
5352 , useAltColorMap :: Bool
5453 , setForeColor :: CapExpression
5554 , setBackColor :: CapExpression
@@ -104,20 +103,20 @@ sendCapToTerminal t cap capParams = do
104103--
105104-- * Providing independent string capabilities for all display
106105-- attributes.
107−reserveTerminal :: String -> Fd -> IO Output
108−reserveTerminal termName outFd = do
106+reserveTerminal :: String -> Fd -> ColorMode -> IO Output
107+reserveTerminal termName outFd colorMode = do
109108 ti <- Terminfo.setupTerm termName
110109 -- assumes set foreground always implies set background exists.
111110 -- if set foreground is not set then all color changing style
112111 -- attributes are filtered.
113112 msetaf <- probeCap ti "setaf"
114113 msetf <- probeCap ti "setf"
115− let (noColors, useAlt, setForeCap)
114+ let (useAlt, setForeCap)
116115 = case msetaf of
117− Just setaf -> (False, False, setaf)
116+ Just setaf -> (False, setaf)
118117 Nothing -> case msetf of
119− Just setf -> (False, True, setf)
120− Nothing -> (True, True, error $ "no fore color support for terminal " ++ termName)
118+ Just setf -> (True, setf)
119+ Nothing -> (True, error $ "no fore color support for terminal " ++ termName)
121120 msetab <- probeCap ti "setab"
122121 msetb <- probeCap ti "setb"
123122 let setBackCap
@@ -151,7 +150,6 @@ reserveTerminal termName outFd = do
151150 <*> requireCap ti "cup"
152151 <*> probeCap ti "cnorm"
153152 <*> probeCap ti "civis"
154− <*> pure noColors
155153 <*> pure useAlt
156154 <*> pure setForeCap
157155 <*> pure setBackCap
@@ -194,17 +192,12 @@ reserveTerminal termName outFd = do
194192 when (toEnum len /= actualLen) $ fail $ "Graphics.Vty.Output: outputByteBuffer "
195193 ++ "length mismatch. " ++ show len ++ " /= " ++ show actualLen
196194 ++ " Please report this bug to vty project."
197− , contextColorCount
198− = case supportsNoColors terminfoCaps of
199− False -> case Terminfo.getCapability ti (Terminfo.tiGetNum "colors" ) of
200− Nothing -> 8
201− Just v -> toEnum v
202− True -> 1
203195 , supportsCursorVisibility = isJust $ civis terminfoCaps
204196 , supportsMode = terminfoModeSupported
205197 , setMode = terminfoSetMode
206198 , getModeStatus = terminfoModeStatus
207199 , assumedStateRef = newAssumedStateRef
200+ , outputColorMode = colorMode
208201 -- I think fix would help assure tActual is the only
209202 -- reference. I was having issues tho.
210203 , mkDisplayContext = (`terminfoDisplayContext` terminfoCaps)
@@ -376,9 +369,9 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
376369 -- applied states.
377370 EnterExitSeq caps -> foldMap (\cap -> writeCapExpr cap []) caps
378371 `mappend`
379− writeColorDiff setForeColor (foreColorDiff diffs)
372+ writeColorDiff Foreground (foreColorDiff diffs)
380373 `mappend`
381− writeColorDiff setBackColor (backColorDiff diffs)
374+ writeColorDiff Background (backColorDiff diffs)
382375 -- implicitly resets the colors to the defaults
383376 SetState state -> writeCapExpr (fromJust $ setAttrStates
384377 $ displayAttrCaps terminfoCaps
@@ -410,29 +403,65 @@ terminfoWriteSetAttr dc terminfoCaps urlsEnabled prevAttr reqAttr diffs =
410403 | otherwise = mempty
411404 setColors =
412405 (case fixedForeColor attr of
413− Just c -> writeCapExpr (setForeColor terminfoCaps)
414− [toEnum $ colorMap c]
406+ Just c -> writeColor Foreground c
415407 Nothing -> mempty)
416408 `mappend`
417409 (case fixedBackColor attr of
418− Just c -> writeCapExpr (setBackColor terminfoCaps)
419− [toEnum $ colorMap c]
410+ Just c -> writeColor Background c
420411 Nothing -> mempty)
421− writeColorDiff _f NoColorChange
412+ writeColorDiff _side NoColorChange
422413 = mempty
423− writeColorDiff _f ColorToDefault
414+ writeColorDiff _side ColorToDefault
424415 = error "ColorToDefault is not a possible case for applyColorDiffs"
425− writeColorDiff f (SetColor c)
426− = writeCapExpr (f terminfoCaps) [toEnum $ colorMap c]
416+ writeColorDiff side (SetColor c)
417+ = writeColor side c
418+
419+ writeColor side (RGBColor r g b) =
420+ case outputColorMode (contextDevice dc) of
421+ FullColor ->
422+ hardcodeColor side (r, g, b)
423+ _ ->
424+ error "clampColor should remove rgb colors in standard mode"
425+ writeColor side c =
426+ writeCapExpr (setSideColor side terminfoCaps) [toEnum $ colorMap c]
427+
428+-- a color can either be in the foreground or the background
429+data ColorSide = Foreground | Background
430+
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
435+
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
441+ , writeChar 'm']
442+ where
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"
427452
428453-- | The color table used by a terminal is a 16 color set followed by a
429454-- 240 color set that might not be supported by the terminal.
430455--
431−-- This takes a Color which clearly identifies which pallete to use and
432−-- computes the index into the full 256 color pallete.
456+-- This takes a Color which clearly identifies which palette to use and
457+-- computes the index into the full 256 color palette.
433458ansiColorIndex :: Color -> Int
434459ansiColorIndex (ISOColor v) = fromEnum v
435460ansiColorIndex (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"
464+ ]
436465
437466-- | For terminals without setaf/setab
438467--
@@ -449,6 +478,10 @@ altColorIndex (ISOColor 6) = 3
449478altColorIndex (ISOColor 7) = 7
450479altColorIndex (ISOColor v) = fromEnum v
451480altColorIndex (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"
484+ ]
452485
453486{- | The sequence of terminfo caps to apply a given style are determined
454487 - according to these rules.