@@ -21,7 +21,7 @@
22-- - <http://www.unixwiz.net/techtips/termios-vmin-vtime.html>
22-- - <http://www.unixwiz.net/techtips/termios-vmin-vtime.html>
24−-- - <<http://vt100.net/docs/vt100-ug/chapter3.html vt100 control sequences>
24+-- - <http://vt100.net/docs/vt100-ug/chapter3.html vt100 control sequences>
25module Graphics.Vty ( Vty(..)
25module Graphics.Vty ( Vty(..)
27 , mkVtyEscDelay
27 , mkVtyEscDelay
@@ -46,34 +46,31 @@ import Data.IORef
46import qualified System.Console.Terminfo as Terminfo
46import qualified System.Console.Terminfo as Terminfo
48-- | The main object. At most one should be created.
48-- | The main object. At most one should be created.
49−-- An alternative is to use unsafePerformIO to automatically create a singleton Vty instance when
49+--
50−-- required.
50+-- The use of Vty typically follows this process:
54+-- 1. use the update equation of Vty to display a picture
60+-- An alternative to tracking the Vty instance is to use 'withVty' in "Graphics.Vty.Inline.Unsafe".
52-- This does not assure any thread safety. In theory, as long as an update action is not executed
62-- This does not assure any thread safety. In theory, as long as an update action is not executed
53-- when another update action is already then it's safe to call this on multiple threads.
63-- when another update action is already then it's safe to call this on multiple threads.
65+-- \todo Remove explicit `shutdown` requirement.
54data Vty = Vty
66data Vty = Vty
55 { -- | Outputs the given Picture. Equivalent to output_picture applied to a display context
67 { -- | Outputs the given Picture. Equivalent to output_picture applied to a display context
56 -- implicitly managed by Vty.
68 -- implicitly managed by Vty.
57 update :: Picture -> IO ()
69 update :: Picture -> IO ()
58 -- | Get one Event object, blocking if necessary.
70 -- | Get one Event object, blocking if necessary.
59 , next_event :: IO Event
71 , next_event :: IO Event
60− -- | The terminal device interface. See `Interface`
72+ -- | The output interface. See `Output`
61− --
73+ , output_iface :: Output
62− -- The use of Vty typically follows this process:
66− -- 1. use the update equation of Vty to display a picture
72− -- todo: provide a similar abstraction to Graphics.Vty.Output for input. Use haskeline's
73− -- input backend for implementation.
75− -- todo: remove explicit `shutdown` requirement.
77 -- | Refresh the display. Normally the library takes care of refreshing. Nonetheless, some
74 -- | Refresh the display. Normally the library takes care of refreshing. Nonetheless, some
78 -- other program might output to the terminal and mess the display. In that case the user
75 -- other program might output to the terminal and mess the display. In that case the user
79 -- might want to force a refresh.
76 -- might want to force a refresh.
@@ -95,42 +92,42 @@ mkVty = mkVtyEscDelay defaultEscDelay
95mkVtyEscDelay :: Int -> IO Vty
92mkVtyEscDelay :: Int -> IO Vty
96mkVtyEscDelay escDelay = do
93mkVtyEscDelay escDelay = do
97 term_info <- Terminfo.setupTermFromEnv
94 term_info <- Terminfo.setupTermFromEnv
98− t <- current_terminal
95+ t <- output_for_current_terminal
99 reserve_display t
96 reserve_display t
100 (kvar, endi) <- initTermInput escDelay term_info
97 (kvar, endi) <- initTermInput escDelay term_info
101 intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
98 intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
103intMkVty :: IO Event -> IO () -> Output -> IO Vty
100intMkVty :: IO Event -> IO () -> Output -> IO Vty
104−intMkVty kvar fend t = do
101+intMkVty kvar fend out = do
105 last_pic_ref <- newIORef Nothing
102 last_pic_ref <- newIORef Nothing
106 last_update_ref <- newIORef Nothing
103 last_update_ref <- newIORef Nothing
108 let inner_update in_pic = do
105 let inner_update in_pic = do
109− b@(w,h) <- display_bounds t
106+ b@(w,h) <- display_bounds out
110 let cursor = pic_cursor in_pic
107 let cursor = pic_cursor in_pic
111 in_pic' = case cursor of
108 in_pic' = case cursor of
112 Cursor x y ->
109 Cursor x y ->
114 x' = case x of
111 x' = case x of
115− _ | x >= 0x80000000 -> 0
112+ _ | x < 0 -> 0
116− | x >= w -> w - 1
113+ | x >= w -> w - 1
117− | otherwise -> x
114+ | otherwise -> x
118 y' = case y of
115 y' = case y of
119− _ | y >= 0x80000000 -> 0
116+ _ | y < 0 -> 0
120− | y >= h -> h - 1
117+ | y >= h -> h - 1
121− | otherwise -> y
118+ | otherwise -> y
122 in in_pic { pic_cursor = Cursor x' y' }
119 in in_pic { pic_cursor = Cursor x' y' }
123 _ -> in_pic
120 _ -> in_pic
124 mlast_update <- readIORef last_update_ref
121 mlast_update <- readIORef last_update_ref
125 update_data <- case mlast_update of
122 update_data <- case mlast_update of
126 Nothing -> do
123 Nothing -> do
127− dc <- display_context t b
124+ dc <- display_context out b
128 output_picture dc in_pic'
125 output_picture dc in_pic'
129 return (b, dc)
126 return (b, dc)
130 Just (last_bounds, last_context) -> do
127 Just (last_bounds, last_context) -> do
131 if b /= last_bounds
128 if b /= last_bounds
133− dc <- display_context t b
130+ dc <- display_context out b
134 output_picture dc in_pic'
131 output_picture dc in_pic'
135 return (b, dc)
132 return (b, dc)
@@ -146,14 +143,14 @@ intMkVty kvar fend t = do
147 let gkey = do k <- kvar
144 let gkey = do k <- kvar
148 case k of
145 case k of
149− (EvResize _ _) -> inner_refresh
146+ (EvResize _ _) -> inner_refresh
150− >> display_bounds t
147+ >> display_bounds out
151 >>= return . (\(w,h)-> EvResize w h)
148 >>= return . (\(w,h)-> EvResize w h)
152 _ -> return k
149 _ -> return k
154 return $ Vty { update = inner_update
151 return $ Vty { update = inner_update
155 , next_event = gkey
152 , next_event = gkey
156− , terminal = t
153+ , output_iface = out
157 , refresh = inner_refresh
154 , refresh = inner_refresh
158 , shutdown = fend
155 , shutdown = fend