Skip to content

Commit

Permalink
more work
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellwrosen committed Nov 12, 2023
1 parent 8149bf0 commit a2f6f42
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ foreign import capi unsafe "termbox2.h tb_print_ex"

-- | Send raw bytes to the terminal.
foreign import capi unsafe "termbox2.h tb_send"
tb_send :: CString -> CSize -> IO CInt
tb_send :: Ptr CChar -> CSize -> IO CInt

-- | Set a cell value in the back buffer.
foreign import capi unsafe "termbox2.h tb_set_cell"
Expand Down
50 changes: 14 additions & 36 deletions termbox2-bindings-hs/src/Termbox2/Bindings/Hs.hs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,6 @@ module Termbox2.Bindings.Hs
tb_present,
tb_invalidate,

-- ** Custom escape sequences
tb_set_func,

-- ** Error utils
tb_last_errno,
tb_strerror,
Expand All @@ -67,6 +64,19 @@ module Termbox2.Bindings.Hs
TB_UNDERLINE,
TB_UNDERLINE_2
),
Tb_color
( Tb_color,
TB_DEFAULT,
TB_BLACK,
TB_BLUE,
TB_CYAN,
TB_GREEN,
TB_HI_BLACK,
TB_MAGENTA,
TB_RED,
TB_WHITE,
TB_YELLOW
),
Tb_error
( Tb_error,
TB_ERR,
Expand Down Expand Up @@ -191,42 +201,11 @@ module Termbox2.Bindings.Hs
TB_OUTPUT_NORMAL,
TB_OUTPUT_TRUECOLOR
),

-- ** Colors

-- _TB_DEFAULT,
-- _TB_BLACK,
-- _TB_HI_BLACK,
-- _TB_BLUE,
-- _TB_CYAN,
-- _TB_GREEN,
-- _TB_MAGENTA,
-- _TB_RED,
-- _TB_WHITE,
-- _TB_YELLOW,

-- ** Attributes

-- _TB_BLINK,
-- _TB_BOLD,
-- _TB_BRIGHT,
-- _TB_DIM,
-- _TB_INVISIBLE,
-- _TB_ITALIC,
-- _TB_OVERLINE,
-- _TB_REVERSE,
-- _TB_STRIKEOUT,
-- _TB_UNDERLINE,
-- _TB_UNDERLINE_2,

-- ** Function types
)
where

-- _TB_FUNC_EXTRACT_PRE,
-- _TB_FUNC_EXTRACT_POST,

import Termbox2.Bindings.Hs.Internal.Attr (Tb_attr (..))
import Termbox2.Bindings.Hs.Internal.Color (Tb_color (..))
import Termbox2.Bindings.Hs.Internal.Error (Tb_error (..))
import Termbox2.Bindings.Hs.Internal.Event (Tb_event (..))
import Termbox2.Bindings.Hs.Internal.EventMod (Tb_event_mod (..), _TB_MOD_ALT, _TB_MOD_CTRL, _TB_MOD_MOTION, _TB_MOD_SHIFT)
Expand Down Expand Up @@ -255,7 +234,6 @@ import Termbox2.Bindings.Hs.Internal.Functions
tb_set_cell_ex,
tb_set_clear_attrs,
tb_set_cursor,
tb_set_func,
tb_set_input_mode,
tb_set_output_mode,
tb_shutdown,
Expand Down
85 changes: 85 additions & 0 deletions termbox2-bindings-hs/src/Termbox2/Bindings/Hs/Internal/Color.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
module Termbox2.Bindings.Hs.Internal.Color
( Tb_color
( Tb_color,
TB_DEFAULT,
TB_BLACK,
TB_BLUE,
TB_CYAN,
TB_GREEN,
TB_HI_BLACK,
TB_MAGENTA,
TB_RED,
TB_WHITE,
TB_YELLOW
),
)
where

import Data.Word (Word64)
import Termbox2.Bindings.C

-- | A color.
newtype Tb_color
= Tb_color Word64
deriving stock (Eq, Ord)
deriving newtype (Num, Show)

pattern TB_DEFAULT :: Tb_color
pattern TB_DEFAULT <-
((== Tb_color _TB_DEFAULT) -> True)
where
TB_DEFAULT = Tb_color _TB_DEFAULT

pattern TB_BLACK :: Tb_color
pattern TB_BLACK <-
((== Tb_color _TB_BLACK) -> True)
where
TB_BLACK = Tb_color _TB_BLACK

pattern TB_BLUE :: Tb_color
pattern TB_BLUE <-
((== Tb_color _TB_BLUE) -> True)
where
TB_BLUE = Tb_color _TB_BLUE

pattern TB_CYAN :: Tb_color
pattern TB_CYAN <-
((== Tb_color _TB_CYAN) -> True)
where
TB_CYAN = Tb_color _TB_CYAN

pattern TB_GREEN :: Tb_color
pattern TB_GREEN <-
((== Tb_color _TB_GREEN) -> True)
where
TB_GREEN = Tb_color _TB_GREEN

pattern TB_HI_BLACK :: Tb_color
pattern TB_HI_BLACK <-
((== Tb_color _TB_HI_BLACK) -> True)
where
TB_HI_BLACK = Tb_color _TB_HI_BLACK

pattern TB_MAGENTA :: Tb_color
pattern TB_MAGENTA <-
((== Tb_color _TB_MAGENTA) -> True)
where
TB_MAGENTA = Tb_color _TB_MAGENTA

pattern TB_RED :: Tb_color
pattern TB_RED <-
((== Tb_color _TB_RED) -> True)
where
TB_RED = Tb_color _TB_RED

pattern TB_WHITE :: Tb_color
pattern TB_WHITE <-
((== Tb_color _TB_WHITE) -> True)
where
TB_WHITE = Tb_color _TB_WHITE

pattern TB_YELLOW :: Tb_color
pattern TB_YELLOW <-
((== Tb_color _TB_YELLOW) -> True)
where
TB_YELLOW = Tb_color _TB_YELLOW
108 changes: 79 additions & 29 deletions termbox2-bindings-hs/src/Termbox2/Bindings/Hs/Internal/Functions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ module Termbox2.Bindings.Hs.Internal.Functions
tb_set_cell_ex,
tb_set_clear_attrs,
tb_set_cursor,
tb_set_func,
tb_set_input_mode,
tb_set_output_mode,
tb_shutdown,
Expand All @@ -31,18 +30,20 @@ module Termbox2.Bindings.Hs.Internal.Functions
)
where

import Data.ByteString (ByteString)
import Data.ByteString.Unsafe qualified as ByteString
import Data.Coerce (coerce)
import Data.Text (Text)
import Data.Text.Foreign qualified as Text (peekCStringLen)
import Data.Text.Foreign qualified as Text (peekCStringLen, withCString)
import Foreign.C (CInt, Errno (..), withCString)
import Foreign.C.ConstPtr (ConstPtr (..))
import Foreign.Marshal (alloca)
import Foreign.Marshal.Array (lengthArray0)
import Foreign.Marshal (alloca, lengthArray0, withArrayLen)
import Foreign.Storable qualified as Storable
import System.Posix.Types (Fd (Fd))
import Termbox2.Bindings.C qualified as Termbox
import Termbox2.Bindings.Hs.Internal.Attr (Tb_attr (Tb_attr))
import Termbox2.Bindings.Hs.Internal.Error (Tb_error (Tb_error))
import Termbox2.Bindings.Hs.Internal.Event (Tb_event, makeEvent)
import Termbox2.Bindings.Hs.Internal.InputMode (Tb_input_mode (Tb_input_mode))
import Termbox2.Bindings.Hs.Internal.OutputMode (Tb_output_mode (Tb_output_mode))
import Termbox2.Bindings.Hs.Internal.Prelude
Expand Down Expand Up @@ -147,14 +148,26 @@ tb_last_errno =
coerce Termbox.tb_last_errno

-- | Wait up to a number of milliseconds for an event.
-- tb_peek_event :: Ptr Tb_event -> CInt -> IO CInt
tb_peek_event :: ()
tb_peek_event = ()
tb_peek_event :: Int -> IO (Either Tb_error Tb_event)
tb_peek_event ms =
alloca \eventPtr -> do
code <- Termbox.tb_peek_event eventPtr (intToCInt ms)
if code == Termbox._TB_OK
then do
event <- Storable.peek eventPtr
pure (Right (makeEvent event))
else pure (Left (Tb_error code))

-- | Wait for an event.
-- tb_poll_event :: Ptr Tb_event -> IO CInt
tb_poll_event :: ()
tb_poll_event = ()
tb_poll_event :: IO (Either Tb_error Tb_event)
tb_poll_event =
alloca \eventPtr -> do
code <- Termbox.tb_poll_event eventPtr
if code == Termbox._TB_OK
then do
event <- Storable.peek eventPtr
pure (Right (makeEvent event))
else pure (Left (Tb_error code))

-- | Synchronize the back buffer with the terminal.
tb_present :: IO (Either Tb_error ())
Expand All @@ -163,21 +176,53 @@ tb_present =

-- | Print a string to the back buffer.
-- tb_print :: CInt -> CInt -> Word64 -> Word64 -> CString -> IO CInt
tb_print :: ()
tb_print = ()
tb_print ::
-- | x
Int ->
-- | y
Int ->
-- | fg
Tb_attr ->
-- | fg
Tb_attr ->
-- | str
Text ->
IO (Either Tb_error ())
tb_print x y (Tb_attr fg) (Tb_attr bg) str =
Text.withCString str \cstr ->
check (Termbox.tb_print (intToCInt x) (intToCInt y) fg bg cstr)

-- | Print a string to the back buffer.
-- | Print a string to the back buffer and return its width.
-- tb_print_ex :: CInt -> CInt -> Word64 -> Word64 -> Ptr CSize -> CString -> IO CInt
tb_print_ex :: ()
tb_print_ex = ()
tb_print_ex ::
-- | x
Int ->
-- | y
Int ->
-- | fg
Tb_attr ->
-- | fg
Tb_attr ->
-- | str
Text ->
IO (Either Tb_error Int)
tb_print_ex x y (Tb_attr fg) (Tb_attr bg) str =
alloca \sizePtr ->
Text.withCString str \cstr -> do
code <- Termbox.tb_print_ex (intToCInt x) (intToCInt y) fg bg sizePtr cstr
if code == Termbox._TB_OK
then do
size <- Storable.peek sizePtr
pure (Right (csizeToInt size))
else pure (Left (Tb_error code))

-- | Send raw bytes to the terminal.
-- tb_send :: CString -> CSize -> IO CInt
tb_send :: ()
tb_send = ()
tb_send :: ByteString -> IO (Either Tb_error ())
tb_send bytes =
ByteString.unsafeUseAsCStringLen bytes \(cstr, len) ->
check (Termbox.tb_send cstr (intToCSize len))

-- | Set a cell value in the back buffer.
-- tb_set_cell :: CInt -> CInt -> Word32 -> Word64 -> Word64 -> IO CInt
tb_set_cell ::
-- | x
Int ->
Expand All @@ -194,12 +239,23 @@ tb_set_cell x y ch (Tb_attr fg) (Tb_attr bg) =
check (Termbox.tb_set_cell (intToCInt x) (intToCInt y) (charToWord32 ch) fg bg)

-- | Set a cell value in the back buffer.
-- tb_set_cell_ex :: CInt -> CInt -> Ptr Word32 -> CSize -> Word64 -> Word64 -> IO CInt
tb_set_cell_ex :: ()
tb_set_cell_ex = ()
tb_set_cell_ex ::
-- | x
Int ->
-- | y
Int ->
-- | chs
[Char] ->
-- | fg
Tb_attr ->
-- | bg
Tb_attr ->
IO (Either Tb_error ())
tb_set_cell_ex x y chs (Tb_attr fg) (Tb_attr bg) =
withArrayLen (map charToWord32 chs) \len cchs ->
check (Termbox.tb_set_cell_ex (intToCInt x) (intToCInt y) cchs (intToCSize len) fg bg)

-- | Set the foreground and background attributes that @tb_clear@ clears the back buffer with.
-- tb_set_clear_attrs :: Word64 -> Word64 -> IO CInt
tb_set_clear_attrs ::
-- | fg
Tb_attr ->
Expand All @@ -210,7 +266,6 @@ tb_set_clear_attrs (Tb_attr fg) (Tb_attr bg) =
check (Termbox.tb_set_clear_attrs fg bg)

-- | Set the cursor in the back buffer.
-- tb_set_cursor :: CInt -> CInt -> IO CInt
tb_set_cursor ::
-- | x
Int ->
Expand All @@ -220,11 +275,6 @@ tb_set_cursor ::
tb_set_cursor x y =
check (Termbox.tb_set_cursor (intToCInt x) (intToCInt y))

-- | Set or clear custom escape sequence functions.
-- tb_set_func :: CInt -> FunPtr (Ptr Tb_event -> Ptr CSize -> IO CInt) -> IO CInt
tb_set_func :: ()
tb_set_func = ()

-- | Set the input mode.
tb_set_input_mode :: Tb_input_mode -> IO (Either Tb_error ())
tb_set_input_mode (Tb_input_mode mode) =
Expand Down
18 changes: 15 additions & 3 deletions termbox2-bindings-hs/src/Termbox2/Bindings/Hs/Internal/Prelude.hs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
module Termbox2.Bindings.Hs.Internal.Prelude
( charToWord32,
word32ToChar,
cintToInt,
intToCInt,
word32ToChar,
csizeToInt,
intToCSize,
)
where

import qualified Data.Char as Char
import Data.Char qualified as Char
import Data.Word (Word32)
import Foreign.C.Types (CInt)
import Foreign.C.Types (CInt, CSize)

charToWord32 :: Char -> Word32
charToWord32 =
Expand All @@ -29,3 +31,13 @@ intToCInt :: Int -> CInt
intToCInt =
fromIntegral
{-# INLINE intToCInt #-}

csizeToInt :: CSize -> Int
csizeToInt =
fromIntegral
{-# INLINE csizeToInt #-}

intToCSize :: Int -> CSize
intToCSize =
fromIntegral
{-# INLINE intToCSize #-}
Loading

0 comments on commit a2f6f42

Please sign in to comment.