{-# LINE 1 "Basement/Terminal/Size.hsc" #-}
{-# LANGUAGE CApiFFI #-}
module Basement.Terminal.Size
    ( getDimensions
    ) where

import           Foreign
import           Foreign.C
import           Basement.Compat.Base
import           Basement.Types.OffsetSize
import           Basement.Numerical.Subtractive
import           Basement.Numerical.Additive
import           Prelude (fromIntegral)



{-# LINE 22 "Basement/Terminal/Size.hsc" #-}


{-# LINE 26 "Basement/Terminal/Size.hsc" #-}

{-# LINE 27 "Basement/Terminal/Size.hsc" #-}




{-# LINE 33 "Basement/Terminal/Size.hsc" #-}


{-# LINE 35 "Basement/Terminal/Size.hsc" #-}
data Winsize = Winsize
    { ws_row    :: !Word16
    , ws_col    :: !Word16
    , ws_xpixel :: !Word16
    , ws_ypixel :: !Word16
    }

instance Storable Winsize where
    sizeOf _ = (8)
{-# LINE 44 "Basement/Terminal/Size.hsc" #-}
    alignment _ = 2
{-# LINE 45 "Basement/Terminal/Size.hsc" #-}
    peek ptr = do
        r <- (\hsc_ptr -> peekByteOff hsc_ptr 0) ptr
{-# LINE 47 "Basement/Terminal/Size.hsc" #-}
        c <- (\hsc_ptr -> peekByteOff hsc_ptr 2) ptr
{-# LINE 48 "Basement/Terminal/Size.hsc" #-}
        x <- (\hsc_ptr -> peekByteOff hsc_ptr 4) ptr
{-# LINE 49 "Basement/Terminal/Size.hsc" #-}
        y <- (\hsc_ptr -> peekByteOff hsc_ptr 6) ptr
{-# LINE 50 "Basement/Terminal/Size.hsc" #-}
        return (Winsize r c x y)
    poke ptr (Winsize r c x y) = do
        (\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr r
{-# LINE 53 "Basement/Terminal/Size.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 2) ptr c
{-# LINE 54 "Basement/Terminal/Size.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 4) ptr x
{-# LINE 55 "Basement/Terminal/Size.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 6) ptr y
{-# LINE 56 "Basement/Terminal/Size.hsc" #-}


{-# LINE 129 "Basement/Terminal/Size.hsc" #-}
-- defined FOUNDATION_SYSTEM_WINDOWS


{-# LINE 132 "Basement/Terminal/Size.hsc" #-}

foreign import capi "sys/ioctl.h ioctl" c_ioctl :: CInt -> CULong -> Ptr a -> IO CInt

-- | Get the terminal windows size
tiocgwinsz :: CULong
tiocgwinsz = Prelude.fromIntegral (21523 :: Word)
{-# LINE 138 "Basement/Terminal/Size.hsc" #-}


{-# LINE 143 "Basement/Terminal/Size.hsc" #-}


{-# LINE 145 "Basement/Terminal/Size.hsc" #-}
ioctlWinsize :: CInt -> IO (Maybe (CountOf Char, CountOf Char))
ioctlWinsize fd = alloca $ \winsizePtr -> do
    status <- c_ioctl fd tiocgwinsz winsizePtr
    if status == (-1 :: CInt)
        then pure Nothing
        else Just . toDimensions <$> peek winsizePtr
  where
    toDimensions winsize =
        ( CountOf . Prelude.fromIntegral . ws_col $ winsize
        , CountOf . Prelude.fromIntegral . ws_row $ winsize)


{-# LINE 174 "Basement/Terminal/Size.hsc" #-}
-- defined FOUNDATION_SYSTEM_WINDOWS

-- | Return the size of the current terminal
--
-- If the system is not supported or that querying the system result in an error
-- then a default size of (80, 24) will be given back.
getDimensions :: IO (CountOf Char, CountOf Char)
getDimensions =

{-# LINE 185 "Basement/Terminal/Size.hsc" #-}
    maybe defaultSize id <$> ioctlWinsize 0

{-# LINE 189 "Basement/Terminal/Size.hsc" #-}
  where
    defaultSize = (80, 24)