termbox-1.0.0: src/Termbox/Internal/Cell.hs
module Termbox.Internal.Cell
( -- * Cell
Cell,
drawCell,
char,
-- ** Color
fg,
bg,
-- ** Style
bold,
underline,
blink,
)
where
import qualified Data.Char as Char
import Data.String (IsString (..))
import Foreign.C.Types (CInt (CInt), CWchar (CWchar))
import qualified Termbox.Bindings.Hs
import Termbox.Internal.Color (Color (Color))
-- | A single cell.
--
-- * Create a cell with 'char', or with a string literal.
-- * Set a cell's color with 'fg', 'bg'.
-- * Style a cell with 'bold', 'underline', 'blink'.
data Cell
= CellEmpty
| CellFg
{-# UNPACK #-} !Char -- invariant: char is width 1
{-# UNPACK #-} !Termbox.Bindings.Hs.Tb_color -- fg
| CellFgBlink
{-# UNPACK #-} !Char -- invariant: char is width 1
{-# UNPACK #-} !Termbox.Bindings.Hs.Tb_color -- fg
| CellFgBg
{-# UNPACK #-} !Char -- invariant: char is width 1
{-# UNPACK #-} !Termbox.Bindings.Hs.Tb_color -- fg
{-# UNPACK #-} !Termbox.Bindings.Hs.Tb_color -- bg
instance {-# OVERLAPS #-} IsString [Cell] where
fromString =
map char
drawCell :: Termbox.Bindings.Hs.Tb_color -> Int -> Int -> Cell -> IO ()
drawCell bg0 col row = \case
CellEmpty -> pure ()
CellFg ch fg_ -> Termbox.Bindings.Hs.tb_change_cell col row ch fg_ bg0
CellFgBlink ch fg_ -> Termbox.Bindings.Hs.tb_change_cell col row ch fg_ (makeBold bg0) -- bold background = blink
CellFgBg ch fg_ bg_ -> Termbox.Bindings.Hs.tb_change_cell col row ch fg_ bg_
-- | Create a cell from a character.
--
-- If the character is not 1 character wide, it will not be displayed.
char :: Char -> Cell
char ch =
case wcwidth (charToCWchar ch) of
1 -> CellFg ch Termbox.Bindings.Hs.TB_DEFAULT
_ -> CellEmpty
-- | Set the foreground color of a cell.
fg :: Color -> Cell -> Cell
fg (Color color) = \case
CellEmpty -> CellEmpty
CellFg ch _ -> CellFg ch color
CellFgBlink ch _ -> CellFgBlink ch color
CellFgBg ch _ bg_ -> CellFgBg ch color bg_
-- | Set the background color of a cell.
bg :: Color -> Cell -> Cell
bg (Color color) = \case
CellEmpty -> CellEmpty
CellFg ch fg_ -> CellFgBg ch fg_ color
CellFgBlink ch fg_ -> CellFgBg ch fg_ (makeBold color) -- bold background = blink
CellFgBg ch fg_ _ -> CellFgBg ch fg_ color
-- | Make a cell bold.
bold :: Cell -> Cell
bold = \case
CellEmpty -> CellEmpty
CellFg ch fg_ -> CellFg ch (makeBold fg_)
CellFgBlink ch fg_ -> CellFgBlink ch (makeBold fg_)
CellFgBg ch fg_ bg_ -> CellFgBg ch (makeBold fg_) bg_
-- | Make a cell underlined.
underline :: Cell -> Cell
underline = \case
CellEmpty -> CellEmpty
CellFg ch fg_ -> CellFg ch (makeUnderline fg_)
CellFgBlink ch fg_ -> CellFgBlink ch (makeUnderline fg_)
CellFgBg ch fg_ bg_ -> CellFgBg ch (makeUnderline fg_) bg_
-- | Make a cell blink.
blink :: Cell -> Cell
blink = \case
CellEmpty -> CellEmpty
CellFg ch fg_ -> CellFgBlink ch fg_
CellFgBlink ch fg_ -> CellFgBlink ch fg_
CellFgBg ch fg_ bg_ -> CellFgBg ch fg_ (makeBold bg_) -- bold background = blink
makeBold :: Termbox.Bindings.Hs.Tb_color -> Termbox.Bindings.Hs.Tb_color
makeBold =
Termbox.Bindings.Hs.tb_attr Termbox.Bindings.Hs.TB_BOLD
makeUnderline :: Termbox.Bindings.Hs.Tb_color -> Termbox.Bindings.Hs.Tb_color
makeUnderline =
Termbox.Bindings.Hs.tb_attr Termbox.Bindings.Hs.TB_UNDERLINE
charToCWchar :: Char -> CWchar
charToCWchar =
fromIntegral @Int @CWchar . Char.ord
foreign import capi unsafe "wchar.h wcwidth"
wcwidth :: CWchar -> CInt