@@ -1,4 +1,5 @@
11-- Copyright Corey O'Connor
2+-- General philosophy is: MonadIO is for equations exposed to clients.
23{-# LANGUAGE BangPatterns #-}
34{-# LANGUAGE RankNTypes #-}
45{-# LANGUAGE ScopedTypeVariables #-}
@@ -18,41 +19,17 @@ import Graphics.Vty.DisplayRegion
1819
1920import Graphics.Vty.DisplayAttributes
2021
21−import Control.Monad ( liftM )
22+import Control.Monad.Fix
2223import Control.Monad.Trans
2324
2425import qualified Data.ByteString.Internal as BS
2526import Data.IORef
2627import qualified Data.Vector as Vector
2728
28−import System.IO
29−
30−-- | An handle to a terminal that hides the implementation.
31−data TerminalHandle where
32− TerminalHandle :: Terminal t => t -> IORef TerminalState -> TerminalHandle
33−
34−state_ref :: TerminalHandle -> IORef TerminalState
35−state_ref (TerminalHandle _ s_ref) = s_ref
36−
37−new_terminal_handle :: forall m t. ( MonadIO m, Terminal t ) => t -> m TerminalHandle
38−new_terminal_handle t = do
39− s_ref <- liftIO $ newIORef initial_terminal_state
40− return $ TerminalHandle t s_ref
41−
42−-- | The current terminal state. This may not exactly be known.
43−data TerminalState = TerminalState
44− { known_fattr :: Maybe FixedAttr
45− }
46−
47−-- | Initially we know nothing about a terminal's state.
48−initial_terminal_state :: TerminalState
49−initial_terminal_state = TerminalState Nothing
50−
51−class Terminal t where
52− -- | Text identifier for the terminal. Used for debugging.
53− terminal_ID :: t -> String
54− -- |
55− release_terminal :: MonadIO m => t -> m ()
29+data Terminal = Terminal
30+ { -- | Text identifier for the terminal. Used for debugging.
31+ terminal_ID :: String
32+ , release_device :: MonadIO m => m ()
5633 -- | Clear the display and initialize the terminal to some initial display state.
5734 --
5835 -- The expectation of a program is that the display starts in some initial state.
@@ -63,77 +40,67 @@ class Terminal t where
6340 -- The abstract operation I think all these behaviors are instances of is reserving exclusive
6441 -- access to a display such that:
6542 -- - The previous state cannot be determined
66− -- - When exclusive access to a display is release the display returns to the previous state.
67− reserve_display :: MonadIO m => t -> m ()
68−
43+ -- - When exclusive access to a display is released the display returns to the previous state.
44+ , reserve_display :: MonadIO m => m ()
6945 -- | Return the display to the state before reserve_display
7046 -- If no previous state then set the display state to the initial state.
71− release_display :: MonadIO m => t -> m ()
72−
47+ , release_display :: MonadIO m => m ()
7348 -- | Returns the current display bounds.
74− display_bounds :: MonadIO m => t -> m DisplayRegion
75−
76− -- Internal method used to provide the DisplayTerminal instance to the DisplayHandle
77− -- constructor.
78− display_terminal_instance :: MonadIO m
79− => t
80− -> DisplayRegion
81− -> (forall d. DisplayTerminal d => d -> DisplayHandle)
82− -> m DisplayHandle
83−
49+ , display_bounds :: MonadIO m => m DisplayRegion
8450 -- | Output the byte buffer of the specified size to the terminal device. The size is equal to
8551 -- end_ptr - start_ptr
86− output_byte_buffer :: t -> OutputBuffer -> Int -> IO ()
87−
88− -- | Handle of output device
89− output_handle :: t -> IO Handle
52+ , output_byte_buffer :: OutputBuffer -> Int -> IO ()
53+ -- | Maximum number of colors supported by the context.
54+ , context_color_count :: Int
55+ , assumed_state_ref :: IORef AssumedState
56+ , mk_display_context :: DisplayContext -> IO DisplayContext
57+ }
9058
91−instance Terminal TerminalHandle where
92− terminal_ID (TerminalHandle t _) = terminal_ID t
93− release_terminal (TerminalHandle t _) = release_terminal t
94− reserve_display (TerminalHandle t _) = reserve_display t
95− release_display (TerminalHandle t _) = release_display t
96− display_bounds (TerminalHandle t _) = display_bounds t
97− display_terminal_instance (TerminalHandle t _) = display_terminal_instance t
98− output_byte_buffer (TerminalHandle t _) = output_byte_buffer t
99− output_handle (TerminalHandle t _) = output_handle t
59+data AssumedState = AssumedState
60+ { prev_fattr :: Maybe FixedAttr
61+ , prev_output_ops :: Maybe DisplayOps
62+ }
10063
101−data DisplayHandle where
102− DisplayHandle :: forall d . DisplayTerminal d => d -> TerminalHandle -> DisplayState -> DisplayHandle
64+initial_assumed_state :: AssumedState
65+initial_assumed_state = AssumedState Nothing Nothing
10366
10467-- | Acquire display access to the given region of the display.
10568-- Currently all regions have the upper left corner of (0,0) and the lower right corner at
10669-- (max display_width provided_width, max display_height provided_height)
107−display_context :: MonadIO m => TerminalHandle -> DisplayRegion -> m DisplayHandle
108−display_context t b = do
109− s <- initial_display_state
110− display_terminal_instance t b (\ d -> DisplayHandle d t s)
111−
112−data DisplayState = DisplayState
113− { previous_output_ref :: IORef (Maybe DisplayOps)
114− }
115−
116−initial_display_state :: MonadIO m => m DisplayState
117−initial_display_state = liftM DisplayState $ liftIO $ newIORef Nothing
118−
119−class DisplayTerminal d where
120− -- | Provide the bounds of the display context.
121− context_region :: d -> DisplayRegion
122−
123− -- | Maximum number of colors supported by the context.
124− context_color_count :: d -> Int
125−
70+display_context :: MonadIO m
71+ => Terminal
72+ -> DisplayRegion
73+ -> m DisplayContext
74+display_context t r = liftIO $ do
75+ let def_context self = DisplayContext
76+ { context_region = r
77+ , context_device = t
78+ , move_cursor_required_bytes = move_cursor_required_bytes self
79+ , serialize_move_cursor = serialize_move_cursor self
80+ , show_cursor_required_bytes = show_cursor_required_bytes self
81+ , serialize_show_cursor = serialize_show_cursor self
82+ , hide_cursor_required_bytes = hide_cursor_required_bytes self
83+ , serialize_hide_cursor = serialize_hide_cursor self
84+ , attr_required_bytes = attr_required_bytes self
85+ , serialize_set_attr = serialize_set_attr self
86+ , default_attr_required_bytes = default_attr_required_bytes self
87+ , serialize_default_attr = serialize_default_attr self
88+ , inline_hack = return ()
89+ }
90+ mfix (mk_display_context t . def_context)
91+
92+data DisplayContext = DisplayContext
93+ { -- | Provide the bounds of the display context.
94+ context_region :: DisplayRegion
95+ , context_device :: Terminal
12696 -- | sets the output position to the specified row and column. Where the number of bytes
12797 -- required for the control codes can be specified seperate from the actual byte sequence.
128− move_cursor_required_bytes :: d -> Int -> Int -> Int
129− serialize_move_cursor :: MonadIO m => d -> Int -> Int -> OutputBuffer -> m OutputBuffer
130−
131− show_cursor_required_bytes :: d -> Int
132− serialize_show_cursor :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
133−
134− hide_cursor_required_bytes :: d -> Int
135− serialize_hide_cursor :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
136−
98+ , move_cursor_required_bytes :: Int -> Int -> Int
99+ , serialize_move_cursor :: Int -> Int -> OutputBuffer -> IO OutputBuffer
100+ , show_cursor_required_bytes :: Int
101+ , serialize_show_cursor :: OutputBuffer -> IO OutputBuffer
102+ , hide_cursor_required_bytes :: Int
103+ , serialize_hide_cursor :: OutputBuffer -> IO OutputBuffer
137104 -- | Assure the specified output attributes will be applied to all the following text until the
138105 -- next output attribute change. Where the number of bytes required for the control codes can
139106 -- be specified seperate from the actual byte sequence. The required number of bytes must be
@@ -145,33 +112,15 @@ class DisplayTerminal d where
145112 -- attributes. In order to support this the currently applied display attributes are required.
146113 -- In addition it may be possible to optimize the state changes based off the currently applied
147114 -- display attributes.
148− attr_required_bytes :: d -> FixedAttr -> Attr -> DisplayAttrDiff -> Int
149− serialize_set_attr :: MonadIO m => d -> FixedAttr -> Attr -> DisplayAttrDiff -> OutputBuffer -> m OutputBuffer
150−
115+ , attr_required_bytes :: FixedAttr -> Attr -> DisplayAttrDiff -> Int
116+ , serialize_set_attr :: FixedAttr -> Attr -> DisplayAttrDiff -> OutputBuffer -> IO OutputBuffer
151117 -- | Reset the display attributes to the default display attributes
152− default_attr_required_bytes :: d -> Int
153− serialize_default_attr :: MonadIO m => d -> OutputBuffer -> m OutputBuffer
154−
118+ , default_attr_required_bytes :: Int
119+ , serialize_default_attr :: OutputBuffer -> IO OutputBuffer
155120 -- | See Graphics.Vty.Terminal.XTermColor.inline_hack
156− inline_hack :: MonadIO m => d -> m ()
157− inline_hack _d = return ()
158−
121+ , inline_hack :: IO ()
122+ }
159123
160−instance DisplayTerminal DisplayHandle where
161− context_region (DisplayHandle d _ _) = context_region d
162− context_color_count (DisplayHandle d _ _) = context_color_count d
163− move_cursor_required_bytes (DisplayHandle d _ _) = move_cursor_required_bytes d
164− serialize_move_cursor (DisplayHandle d _ _) = serialize_move_cursor d
165− show_cursor_required_bytes (DisplayHandle d _ _) = show_cursor_required_bytes d
166− serialize_show_cursor (DisplayHandle d _ _) = serialize_show_cursor d
167− hide_cursor_required_bytes (DisplayHandle d _ _) = hide_cursor_required_bytes d
168− serialize_hide_cursor (DisplayHandle d _ _) = serialize_hide_cursor d
169− attr_required_bytes (DisplayHandle d _ _) = attr_required_bytes d
170− serialize_set_attr (DisplayHandle d _ _) = serialize_set_attr d
171− default_attr_required_bytes (DisplayHandle d _ _) = default_attr_required_bytes d
172− serialize_default_attr (DisplayHandle d _ _) = serialize_default_attr d
173− inline_hack (DisplayHandle d _ _) = inline_hack d
174−
175124-- | All terminals serialize UTF8 text to the terminal device exactly as serialized in memory.
176125utf8_text_required_bytes :: BS.ByteString -> Int
177126utf8_text_required_bytes str =
@@ -179,15 +128,14 @@ utf8_text_required_bytes str =
179128 in src_bytes_length
180129
181130-- | All terminals serialize UTF8 text to the terminal device exactly as serialized in memory.
182−serialize_utf8_text :: MonadIO m => BS.ByteString -> OutputBuffer -> m OutputBuffer
131+serialize_utf8_text :: BS.ByteString -> OutputBuffer -> IO OutputBuffer
183132serialize_utf8_text str dest_ptr =
184133 let (src_fptr, src_ptr_offset, src_bytes_length) = BS.toForeignPtr str
185− in liftIO $ withForeignPtr src_fptr $ \src_ptr -> do
134+ in withForeignPtr src_fptr $ \src_ptr -> do
186135 let src_ptr' = src_ptr `plusPtr` src_ptr_offset
187136 BS.memcpy dest_ptr src_ptr' (toEnum src_bytes_length)
188137 return (dest_ptr `plusPtr` src_bytes_length)
189138
190−
191139-- | Displays the given `Picture`.
192140--
193141-- 0. The image is cropped to the display size.
@@ -199,159 +147,142 @@ serialize_utf8_text str dest_ptr =
199147-- 3. Serialized to the display.
200148--
201149-- 4. The cursor is then shown and positioned or kept hidden.
202−--
203150--
204151-- todo: specify possible IO exceptions.
205152-- abstract from IO monad to a MonadIO instance.
206−output_picture :: MonadIO m => DisplayHandle -> Picture -> m ()
207−output_picture (DisplayHandle d t s) pic = do
208− let !r = context_region d
209− let !ops = spans_for_pic pic r
210− let !initial_attr = FixedAttr default_style_mask Nothing Nothing
211− -- Diff the previous output against the requested output. Differences are currently on a per-row
212− -- basis.
213− diffs :: [Bool]
214− <- liftIO ( readIORef (previous_output_ref s) )
215− >>= \mprevious_ops -> case mprevious_ops of
216− Nothing
217− -> return $ replicate ( fromEnum $ region_height $ effected_region ops )
218− True
219− Just previous_ops
220− -> if effected_region previous_ops /= effected_region ops
221− then return $ replicate ( fromEnum $ region_height $ effected_region ops )
222− True
223− else return $ zipWith (/=) ( Vector.toList $ display_ops previous_ops )
224− ( Vector.toList $ display_ops ops )
225−
226− -- determine the number of bytes required to completely serialize the output ops.
227− let total = hide_cursor_required_bytes d
228− + default_attr_required_bytes d
229− + required_bytes d initial_attr diffs ops
153+output_picture :: MonadIO m => DisplayContext -> Picture -> m ()
154+output_picture dc pic = liftIO $ do
155+ as <- readIORef (assumed_state_ref $ context_device dc)
156+ let !r = context_region dc
157+ !ops = spans_for_pic pic r
158+ !initial_attr = FixedAttr default_style_mask Nothing Nothing
159+ -- Diff the previous output against the requested output. Differences are currently on a per-row
160+ -- basis.
161+ -- \todo handle resizes that crop the dominate directions better.
162+ diffs :: [Bool] = case prev_output_ops as of
163+ Nothing -> replicate (fromEnum $ region_height $ effected_region ops) True
164+ Just previous_ops -> if effected_region previous_ops /= effected_region ops
165+ then replicate (fromEnum $ region_height $ effected_region ops) True
166+ else zipWith (/=) (Vector.toList $ display_ops previous_ops)
167+ (Vector.toList $ display_ops ops)
168+ -- determine the number of bytes required to completely serialize the output ops.
169+ total = hide_cursor_required_bytes dc
170+ + default_attr_required_bytes dc
171+ + required_bytes dc initial_attr diffs ops
230172 + case pic_cursor pic of
231173 NoCursor -> 0
232174 Cursor x y -> let m = cursor_output_map ops $ pic_cursor pic
233175 ( ox, oy ) = char_to_output_pos m ( x, y )
234− in show_cursor_required_bytes d
235− + move_cursor_required_bytes d ox oy
236−
176+ in show_cursor_required_bytes dc + move_cursor_required_bytes dc ox oy
237177 -- ... then serialize
238− liftIO $ allocaBytes (fromEnum total) $ \start_ptr -> do
239− ptr <- serialize_hide_cursor d start_ptr
240− ptr' <- serialize_default_attr d ptr
241− ptr'' <- serialize_output_ops d ptr' initial_attr diffs ops
178+ allocaBytes (fromEnum total) $ \start_ptr -> do
179+ ptr <- serialize_hide_cursor dc start_ptr
180+ ptr' <- serialize_default_attr dc ptr
181+ ptr'' <- serialize_output_ops dc ptr' initial_attr diffs ops
242182 end_ptr <- case pic_cursor pic of
243183 NoCursor -> return ptr''
244184 Cursor x y -> do
245185 let m = cursor_output_map ops $ pic_cursor pic
246186 (ox, oy) = char_to_output_pos m (x,y)
247− serialize_show_cursor d ptr'' >>= serialize_move_cursor d ox oy
187+ serialize_show_cursor dc ptr'' >>= serialize_move_cursor dc ox oy
248188 -- todo: How to handle exceptions?
249189 case end_ptr `minusPtr` start_ptr of
250190 count | count < 0 -> fail "End pointer before start of buffer."
251191 | toEnum count > total -> fail $ "End pointer past end of buffer by " ++ show (toEnum count - total)
252− | otherwise -> output_byte_buffer t start_ptr (toEnum count)
192+ | otherwise -> output_byte_buffer (context_device dc) start_ptr (toEnum count)
253193 -- Cache the output spans.
254− liftIO $ writeIORef (previous_output_ref s) (Just ops)
255− return ()
194+ let as' = as { prev_output_ops = Just ops }
195+ writeIORef (assumed_state_ref $ context_device dc) as'
256196
257−required_bytes :: DisplayTerminal d => d -> FixedAttr -> [Bool] -> DisplayOps -> Int
258−required_bytes d in_fattr diffs ops =
197+required_bytes :: DisplayContext -> FixedAttr -> [Bool] -> DisplayOps -> Int
198+required_bytes dc in_fattr diffs ops =
259199 let (_, n, _, _) = Vector.foldl' required_bytes' (0, 0, in_fattr, diffs) ( display_ops ops )
260200 in n
261201 where
262202 required_bytes' (y, current_sum, fattr, True : diffs') span_ops
263− = let (s, fattr') = span_ops_required_bytes d y fattr span_ops
203+ = let (s, fattr') = span_ops_required_bytes dc y fattr span_ops
264204 in ( y + 1, s + current_sum, fattr', diffs' )
265205 required_bytes' (y, current_sum, fattr, False : diffs') _span_ops
266206 = ( y + 1, current_sum, fattr, diffs' )
267207 required_bytes' (_y, _current_sum, _fattr, [] ) _span_ops
268208 = error "shouldn't be possible"
269209
270−span_ops_required_bytes :: DisplayTerminal d => d -> Int -> FixedAttr -> SpanOps -> (Int, FixedAttr)
271−span_ops_required_bytes d y in_fattr span_ops =
210+span_ops_required_bytes :: DisplayContext -> Int -> FixedAttr -> SpanOps -> (Int, FixedAttr)
211+span_ops_required_bytes dc y in_fattr span_ops =
272212 -- The first operation is to set the cursor to the start of the row
273− let header_required_bytes = move_cursor_required_bytes d 0 y
213+ let header_required_bytes = move_cursor_required_bytes dc 0 y
274214 -- then the span ops are serialized in the order specified
275− in Vector.foldl' ( \(current_sum, fattr) op -> let (c, fattr') = span_op_required_bytes d fattr op
215+ in Vector.foldl' ( \(current_sum, fattr) op -> let (c, fattr') = span_op_required_bytes dc fattr op
276216 in (c + current_sum, fattr')
277217 )
278218 (header_required_bytes, in_fattr)
279219 span_ops
280220
281−span_op_required_bytes :: DisplayTerminal d => d -> FixedAttr -> SpanOp -> (Int, FixedAttr)
282−span_op_required_bytes d fattr (AttributeChange attr) =
283− let attr' = limit_attr_for_display d attr
221+span_op_required_bytes :: DisplayContext -> FixedAttr -> SpanOp -> (Int, FixedAttr)
222+span_op_required_bytes dc fattr (AttributeChange attr) =
223+ let attr' = limit_attr_for_display (context_device dc) attr
284224 diffs = display_attr_diffs fattr fattr'
285− c = attr_required_bytes d fattr attr' diffs
225+ c = attr_required_bytes dc fattr attr' diffs
286226 fattr' = fix_display_attr fattr attr'
287227 in (c, fattr')
288−span_op_required_bytes _d fattr (TextSpan _ _ str) = (utf8_text_required_bytes str, fattr)
228+span_op_required_bytes _dc fattr (TextSpan _ _ str) = (utf8_text_required_bytes str, fattr)
289229
290−serialize_output_ops :: ( MonadIO m, DisplayTerminal d )
291− => d
230+serialize_output_ops :: DisplayContext
292231 -> OutputBuffer
293232 -> FixedAttr
294233 -> [Bool]
295234 -> DisplayOps
296− -> m OutputBuffer
297−serialize_output_ops d start_ptr in_fattr diffs ops = do
235+ -> IO OutputBuffer
236+serialize_output_ops dc start_ptr in_fattr diffs ops = do
298237 (_, end_ptr, _, _) <- Vector.foldM' serialize_output_ops'
299238 ( 0, start_ptr, in_fattr, diffs )
300239 ( display_ops ops )
301240 return end_ptr
302241 where
303242 serialize_output_ops' ( y, out_ptr, fattr, True : diffs' ) span_ops
304− = serialize_span_ops d y out_ptr fattr span_ops
243+ = serialize_span_ops dc y out_ptr fattr span_ops
305244 >>= return . ( \(out_ptr', fattr') -> ( y + 1, out_ptr', fattr', diffs' ) )
306245 serialize_output_ops' ( y, out_ptr, fattr, False : diffs' ) _span_ops
307246 = return ( y + 1, out_ptr, fattr, diffs' )
308247 serialize_output_ops' (_y, _out_ptr, _fattr, [] ) _span_ops
309248 = error "shouldn't be possible"
310249
311−serialize_span_ops :: ( MonadIO m, DisplayTerminal d )
312− => d
250+serialize_span_ops :: DisplayContext
313251 -> Int
314252 -> OutputBuffer
315253 -> FixedAttr
316254 -> SpanOps
317− -> m (OutputBuffer, FixedAttr)
318−serialize_span_ops d y out_ptr in_fattr span_ops = do
255+ -> IO (OutputBuffer, FixedAttr)
256+serialize_span_ops dc y out_ptr in_fattr span_ops = do
319257 -- The first operation is to set the cursor to the start of the row
320− out_ptr' <- serialize_move_cursor d 0 y out_ptr
258+ out_ptr' <- serialize_move_cursor dc 0 y out_ptr
321259 -- then the span ops are serialized in the order specified
322− Vector.foldM ( \(out_ptr'', fattr) op -> serialize_span_op d op out_ptr'' fattr )
260+ Vector.foldM ( \(out_ptr'', fattr) op -> serialize_span_op dc op out_ptr'' fattr )
323261 (out_ptr', in_fattr)
324262 span_ops
325263
326−serialize_span_op :: ( MonadIO m, DisplayTerminal d )
327− => d
264+serialize_span_op :: DisplayContext
328265 -> SpanOp
329266 -> OutputBuffer
330267 -> FixedAttr
331− -> m (OutputBuffer, FixedAttr)
332−serialize_span_op d (AttributeChange attr) out_ptr fattr = do
333− let attr' = limit_attr_for_display d attr
268+ -> IO (OutputBuffer, FixedAttr)
269+serialize_span_op dc (AttributeChange attr) out_ptr fattr = do
270+ let attr' = limit_attr_for_display (context_device dc) attr
334271 fattr' = fix_display_attr fattr attr'
335272 diffs = display_attr_diffs fattr fattr'
336− out_ptr' <- serialize_set_attr d fattr attr' diffs out_ptr
273+ out_ptr' <- serialize_set_attr dc fattr attr' diffs out_ptr
337274 return (out_ptr', fattr')
338−serialize_span_op _d (TextSpan _ _ str) out_ptr fattr = do
275+serialize_span_op _dc (TextSpan _ _ str) out_ptr fattr = do
339276 out_ptr' <- serialize_utf8_text str out_ptr
340277 return (out_ptr', fattr)
341278
342−marshall_to_terminal :: ( Terminal t )
343− => t -> Int -> (Ptr Word8 -> IO (Ptr Word8)) -> IO ()
344−marshall_to_terminal t c f = do
345− start_ptr <- mallocBytes (fromEnum c)
346− --
347− -- todo: capture exceptions?
279+send_to_terminal :: Terminal -> Int -> (Ptr Word8 -> IO (Ptr Word8)) -> IO ()
280+send_to_terminal t c f = allocaBytes (fromEnum c) $ \start_ptr -> do
348281 end_ptr <- f start_ptr
349282 case end_ptr `minusPtr` start_ptr of
350283 count | count < 0 -> fail "End pointer before start pointer."
351284 | toEnum count > c -> fail $ "End pointer past end of buffer by " ++ show (toEnum count - c)
352285 | otherwise -> output_byte_buffer t start_ptr (toEnum count)
353− free start_ptr
354− return ()
355286
356287-- | The cursor position is given in X,Y character offsets. Due to multi-column characters this
357288-- needs to be translated to column, row positions.
@@ -391,8 +322,8 @@ cursor_column_offset span_ops cx cy =
391322
392323-- | Not all terminals support all display attributes. This filters a display attribute to what the
393324-- given terminal can display.
394−limit_attr_for_display :: DisplayTerminal d => d -> Attr -> Attr
395−limit_attr_for_display d attr
325+limit_attr_for_display :: Terminal -> Attr -> Attr
326+limit_attr_for_display t attr
396327 = attr { attr_fore_color = clamp_color $ attr_fore_color attr
397328 , attr_back_color = clamp_color $ attr_back_color attr
398329 }
@@ -401,16 +332,16 @@ limit_attr_for_display d attr
401332 clamp_color KeepCurrent = KeepCurrent
402333 clamp_color (SetTo c) = clamp_color' c
403334 clamp_color' (ISOColor v)
404− | context_color_count d < 8 = Default
405− | context_color_count d < 16 && v >= 8 = SetTo $ ISOColor (v - 8)
335+ | context_color_count t < 8 = Default
336+ | context_color_count t < 16 && v >= 8 = SetTo $ ISOColor (v - 8)
406337 | otherwise = SetTo $ ISOColor v
407338 clamp_color' (Color240 v)
408339 -- TODO: Choose closes ISO color?
409− | context_color_count d < 8 = Default
410− | context_color_count d < 16 = Default
411− | context_color_count d == 240 = SetTo $ Color240 v
340+ | context_color_count t < 8 = Default
341+ | context_color_count t < 16 = Default
342+ | context_color_count t == 240 = SetTo $ Color240 v
412343 | otherwise
413344 = let p :: Double = fromIntegral v / 240.0
414− v' = floor $ p * (fromIntegral $ context_color_count d)
345+ v' = floor $ p * (fromIntegral $ context_color_count t)
415346 in SetTo $ Color240 v'
416347