{-# LINE 1 "src/System/Console/Terminal/Posix.hsc" #-}

module System.Console.Terminal.Posix
  ( size, fdSize, hSize
  ) where

import System.Console.Terminal.Common
import Control.Exception (catch)
import Data.Typeable (cast)
import Foreign
import Foreign.C.Error
import Foreign.C.Types
import GHC.IO.FD (FD(FD, fdFD))
import GHC.IO.Handle.Internals (withHandle_)
import GHC.IO.Handle.Types (Handle, Handle__(Handle__, haDevice))

{-# LINE 18 "src/System/Console/Terminal/Posix.hsc" #-}
import System.Posix.Types (Fd(Fd))








-- Interesting part of @struct winsize@
data CWin = CWin CUShort CUShort

instance Storable CWin where
  sizeOf _ = ((8))
{-# LINE 32 "src/System/Console/Terminal/Posix.hsc" #-}
  alignment _ = (2)
{-# LINE 33 "src/System/Console/Terminal/Posix.hsc" #-}
  peek ptr = do
    row <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) ptr
{-# LINE 35 "src/System/Console/Terminal/Posix.hsc" #-}
    col <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) ptr
{-# LINE 36 "src/System/Console/Terminal/Posix.hsc" #-}
    return $ CWin row col
  poke ptr (CWin row col) = do
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr row
{-# LINE 39 "src/System/Console/Terminal/Posix.hsc" #-}
    ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) ptr col
{-# LINE 40 "src/System/Console/Terminal/Posix.hsc" #-}


fdSize :: Integral n => Fd -> IO (Maybe (Window n))
fdSize (Fd fd) = with (CWin 0 0) $ \ws -> do
  throwErrnoIfMinus1 "ioctl" $
    ioctl fd (1074295912) ws
{-# LINE 46 "src/System/Console/Terminal/Posix.hsc" #-}
  CWin row col <- peek ws
  return . Just $ Window (fromIntegral row) (fromIntegral col)
 `catch`
  handler
 where
  handler :: IOError -> IO (Maybe (Window h))
  handler _ = return Nothing

foreign import ccall "sys/ioctl.h ioctl"
  ioctl :: CInt -> CInt -> Ptr CWin -> IO CInt

size :: Integral n => IO (Maybe (Window n))
size = fdSize (Fd (1))
{-# LINE 59 "src/System/Console/Terminal/Posix.hsc" #-}

hSize :: Integral n => Handle -> IO (Maybe (Window n))
hSize h = withHandle_ "hSize" h $ \Handle__ { haDevice = dev } ->
  case cast dev of
    Nothing -> return Nothing
    Just FD { fdFD = fd } -> fdSize (Fd fd)