{-# LANGUAGE PatternSynonyms #-}
module Termbox
(
run,
InitError (..),
set,
Cells,
Cell (..),
Cursor (..),
Event (..),
Key (..),
pattern KeyCtrlH,
pattern KeyCtrlLsqBracket,
pattern KeyCtrl2,
pattern KeyCtrl3,
pattern KeyCtrl4,
pattern KeyCtrl5,
pattern KeyCtrl7,
pattern KeyCtrlM,
pattern KeyCtrlI,
pattern KeyCtrlUnderscore,
Mouse (..),
PollError (..),
Attr,
black,
red,
green,
yellow,
blue,
magenta,
cyan,
white,
bold,
underline,
reverse,
)
where
import Control.Exception
import Data.Semigroup (Semigroup (..))
import Termbox.Attr
( Attr,
black,
blue,
bold,
cyan,
green,
magenta,
red,
reverse,
underline,
white,
yellow,
)
import Termbox.Cell (Cell (Cell))
import Termbox.Cells (Cells (Cells), set)
import Termbox.Event (Event (..), PollError (..), poll)
import Termbox.Internal
import Termbox.Key
( Key (..),
pattern KeyCtrl2,
pattern KeyCtrl3,
pattern KeyCtrl4,
pattern KeyCtrl5,
pattern KeyCtrl7,
pattern KeyCtrlH,
pattern KeyCtrlI,
pattern KeyCtrlLsqBracket,
pattern KeyCtrlM,
pattern KeyCtrlUnderscore,
)
import Termbox.Mouse (Mouse (..))
import Prelude hiding (reverse)
data Cursor
=
Cursor !Int !Int
| NoCursor
data InitError
= FailedToOpenTTY
| PipeTrapError
| UnsupportedTerminal
deriving (Show)
instance Exception InitError
run :: (Int -> Int -> (Cells -> Cursor -> IO ()) -> IO Event -> IO a) -> IO a
run action = do
mask $ \unmask -> do
initResult <- tb_init
case () of
_ | initResult == 0 -> do
result <-
unmask
( do
_ <- tb_select_input_mode tB_INPUT_MOUSE
_ <- tb_select_output_mode tB_OUTPUT_256
width <- tb_width
height <- tb_height
action width height render poll
)
`onException` shutdown
shutdown
pure result
_ | initResult == tB_EFAILED_TO_OPEN_TTY -> throwIO FailedToOpenTTY
_ | initResult == tB_EPIPE_TRAP_ERROR -> throwIO PipeTrapError
_ | initResult == tB_EUNSUPPORTED_TERMINAL -> throwIO UnsupportedTerminal
_ -> error ("termbox: unknown tb_init error " ++ show initResult)
render :: Cells -> Cursor -> IO ()
render (Cells cells) cursor = do
tb_set_clear_attributes 0 0
tb_clear
cells
case cursor of
Cursor col row -> tb_set_cursor col row
NoCursor -> tb_set_cursor tB_HIDE_CURSOR tB_HIDE_CURSOR
tb_present
shutdown :: IO ()
shutdown = do
_ <- tb_select_output_mode tB_OUTPUT_NORMAL
tb_shutdown