{-# LINE 1 "System\\Win32\\Console.hsc" #-}

{-# LINE 2 "System\\Win32\\Console.hsc" #-}
{-# LANGUAGE Safe #-}

{-# LINE 6 "System\\Win32\\Console.hsc" #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  System.Win32.Console
-- Copyright   :  (c) University of Glasgow 2006
-- License     :  BSD-style (see the file LICENSE)
--
-- Maintainer  :  Esa Ilari Vuokko <ei@vuokko.info>
-- Stability   :  provisional
-- Portability :  portable
--
-- A collection of FFI declarations for interfacing with Win32 Console API
--
-----------------------------------------------------------------------------

module System.Win32.Console (
        -- * Console mode
        getConsoleMode,
        setConsoleMode,
        eNABLE_ECHO_INPUT,
        eNABLE_EXTENDED_FLAGS,
        eNABLE_INSERT_MODE,
        eNABLE_LINE_INPUT,
        eNABLE_MOUSE_INPUT,
        eNABLE_PROCESSED_INPUT,
        eNABLE_QUICK_EDIT_MODE,
        eNABLE_WINDOW_INPUT,
        eNABLE_VIRTUAL_TERMINAL_INPUT,
        eNABLE_PROCESSED_OUTPUT,
        eNABLE_WRAP_AT_EOL_OUTPUT,
        eNABLE_VIRTUAL_TERMINAL_PROCESSING,
        dISABLE_NEWLINE_AUTO_RETURN,
        eNABLE_LVB_GRID_WORLDWIDE,
        -- * Console code pages
        getConsoleCP,
        setConsoleCP,
        getConsoleOutputCP,
        setConsoleOutputCP,
        -- * Ctrl events
        CtrlEvent, cTRL_C_EVENT, cTRL_BREAK_EVENT,
        generateConsoleCtrlEvent,
        -- * Command line
        commandLineToArgv,
        -- * Screen buffer
        CONSOLE_SCREEN_BUFFER_INFO(..),
        CONSOLE_SCREEN_BUFFER_INFOEX(..),
        COORD(..),
        SMALL_RECT(..),
        COLORREF,
        getConsoleScreenBufferInfo,
        getCurrentConsoleScreenBufferInfo,
        getConsoleScreenBufferInfoEx,
        getCurrentConsoleScreenBufferInfoEx
  ) where



#include "windows_cconv.h"


import System.Win32.Types
import Graphics.Win32.Misc
import Graphics.Win32.GDI.Types (COLORREF)

import Foreign.C.Types (CInt(..))
import Foreign.C.String (withCWString, CWString)
import Foreign.Ptr (Ptr, plusPtr)
import Foreign.Storable (Storable(..))
import Foreign.Marshal.Array (peekArray, pokeArray)
import Foreign.Marshal.Alloc (alloca)

foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleMode"
        c_GetConsoleMode :: HANDLE -> LPDWORD -> IO BOOL

foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleMode"
        c_SetConsoleMode :: HANDLE -> DWORD -> IO BOOL

getConsoleMode :: HANDLE -> IO DWORD
getConsoleMode h = alloca $ \ptr -> do
    failIfFalse_ "GetConsoleMode" $ c_GetConsoleMode h ptr
    peek ptr

setConsoleMode :: HANDLE -> DWORD -> IO ()
setConsoleMode h mode = failIfFalse_ "SetConsoleMode" $ c_SetConsoleMode h mode

eNABLE_ECHO_INPUT, eNABLE_EXTENDED_FLAGS, eNABLE_INSERT_MODE, eNABLE_LINE_INPUT,
    eNABLE_MOUSE_INPUT, eNABLE_PROCESSED_INPUT, eNABLE_QUICK_EDIT_MODE,
    eNABLE_WINDOW_INPUT, eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_PROCESSED_OUTPUT,
    eNABLE_WRAP_AT_EOL_OUTPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING,
    dISABLE_NEWLINE_AUTO_RETURN, eNABLE_LVB_GRID_WORLDWIDE :: DWORD
eNABLE_ECHO_INPUT = 4
eNABLE_EXTENDED_FLAGS = 128
eNABLE_INSERT_MODE = 32
eNABLE_LINE_INPUT = 2
eNABLE_MOUSE_INPUT = 16
eNABLE_PROCESSED_INPUT = 1
eNABLE_QUICK_EDIT_MODE = 64
eNABLE_WINDOW_INPUT = 8
eNABLE_VIRTUAL_TERMINAL_INPUT = 512
eNABLE_PROCESSED_OUTPUT = 1
eNABLE_WRAP_AT_EOL_OUTPUT = 2
eNABLE_VIRTUAL_TERMINAL_PROCESSING = 4
dISABLE_NEWLINE_AUTO_RETURN = 8
eNABLE_LVB_GRID_WORLDWIDE = 16

foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleCP"
        getConsoleCP :: IO UINT

foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCP"
        setConsoleCP :: UINT -> IO ()

foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleOutputCP"
        getConsoleOutputCP :: IO UINT

foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleOutputCP"
        setConsoleOutputCP :: UINT -> IO ()

type CtrlEvent = DWORD
cTRL_C_EVENT       :: CtrlEvent
cTRL_C_EVENT       =  0
cTRL_BREAK_EVENT   :: CtrlEvent
cTRL_BREAK_EVENT   =  1

{-# LINE 127 "System\\Win32\\Console.hsc" #-}

generateConsoleCtrlEvent :: CtrlEvent -> DWORD -> IO ()
generateConsoleCtrlEvent e p
    = failIfFalse_
        "generateConsoleCtrlEvent"
        $ c_GenerateConsoleCtrlEvent e p

foreign import WINDOWS_CCONV safe "windows.h GenerateConsoleCtrlEvent"
    c_GenerateConsoleCtrlEvent :: CtrlEvent -> DWORD -> IO BOOL

foreign import WINDOWS_CCONV unsafe "Shellapi.h CommandLineToArgvW"
     c_CommandLineToArgvW :: CWString -> Ptr CInt -> IO (Ptr CWString)

-- | This function can be used to parse command line arguments and return
--   the split up arguments as elements in a list.
commandLineToArgv :: String -> IO [String]
commandLineToArgv []  = return []
commandLineToArgv arg =
  do withCWString arg $ \c_arg -> do
       alloca $ \c_size -> do
         res <- c_CommandLineToArgvW c_arg c_size
         size <- peek c_size
         args <- peekArray (fromIntegral size) res
         _ <- localFree res
         mapM peekTString args

data CONSOLE_SCREEN_BUFFER_INFO = CONSOLE_SCREEN_BUFFER_INFO
    { dwSize              :: COORD
    , dwCursorPosition    :: COORD
    , wAttributes         :: WORD
    , srWindow            :: SMALL_RECT
    , dwMaximumWindowSize :: COORD
    } deriving (Show, Eq)

instance Storable CONSOLE_SCREEN_BUFFER_INFO where
    sizeOf = const (22)
{-# LINE 163 "System\\Win32\\Console.hsc" #-}
    alignment _ = 2
{-# LINE 164 "System\\Win32\\Console.hsc" #-}
    peek buf = do
        dwSize'              <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
{-# LINE 166 "System\\Win32\\Console.hsc" #-}
        dwCursorPosition'    <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
{-# LINE 167 "System\\Win32\\Console.hsc" #-}
        wAttributes'         <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf
{-# LINE 168 "System\\Win32\\Console.hsc" #-}
        srWindow'            <- ((\hsc_ptr -> peekByteOff hsc_ptr 10)) buf
{-# LINE 169 "System\\Win32\\Console.hsc" #-}
        dwMaximumWindowSize' <- ((\hsc_ptr -> peekByteOff hsc_ptr 18)) buf
{-# LINE 170 "System\\Win32\\Console.hsc" #-}
        return $ CONSOLE_SCREEN_BUFFER_INFO dwSize' dwCursorPosition' wAttributes' srWindow' dwMaximumWindowSize'
    poke buf info = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (dwSize info)
{-# LINE 173 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (dwCursorPosition info)
{-# LINE 174 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (wAttributes info)
{-# LINE 175 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 10)) buf (srWindow info)
{-# LINE 176 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 18)) buf (dwMaximumWindowSize info)
{-# LINE 177 "System\\Win32\\Console.hsc" #-}

data CONSOLE_SCREEN_BUFFER_INFOEX = CONSOLE_SCREEN_BUFFER_INFOEX
    { dwSizeEx              :: COORD
    , dwCursorPositionEx    :: COORD
    , wAttributesEx         :: WORD
    , srWindowEx            :: SMALL_RECT
    , dwMaximumWindowSizeEx :: COORD
    , wPopupAttributes      :: WORD
    , bFullscreenSupported  :: BOOL
    , colorTable            :: [COLORREF]
      -- ^ Only the first 16 'COLORREF' values passed to the Windows Console
      -- API. If fewer than 16 values, the remainder are padded with @0@ when
      -- passed to the API.
    } deriving (Show, Eq)

instance Storable CONSOLE_SCREEN_BUFFER_INFOEX where
    sizeOf = const (96)
{-# LINE 194 "System\\Win32\\Console.hsc" #-}
    alignment = const 4
{-# LINE 195 "System\\Win32\\Console.hsc" #-}
    peek buf = do
        dwSize'               <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
{-# LINE 197 "System\\Win32\\Console.hsc" #-}
        dwCursorPosition'     <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf
{-# LINE 198 "System\\Win32\\Console.hsc" #-}
        wAttributes'          <- ((\hsc_ptr -> peekByteOff hsc_ptr 12)) buf
{-# LINE 199 "System\\Win32\\Console.hsc" #-}
        srWindow'             <- ((\hsc_ptr -> peekByteOff hsc_ptr 14)) buf
{-# LINE 200 "System\\Win32\\Console.hsc" #-}
        dwMaximumWindowSize'  <- ((\hsc_ptr -> peekByteOff hsc_ptr 22)) buf
{-# LINE 201 "System\\Win32\\Console.hsc" #-}
        wPopupAttributes'     <- ((\hsc_ptr -> peekByteOff hsc_ptr 26)) buf
{-# LINE 202 "System\\Win32\\Console.hsc" #-}
        bFullscreenSupported' <- ((\hsc_ptr -> peekByteOff hsc_ptr 28)) buf
{-# LINE 203 "System\\Win32\\Console.hsc" #-}
        colorTable'           <- peekArray 16 (((\hsc_ptr -> hsc_ptr `plusPtr` 32)) buf)
{-# LINE 204 "System\\Win32\\Console.hsc" #-}
        return $ CONSOLE_SCREEN_BUFFER_INFOEX dwSize' dwCursorPosition'
          wAttributes' srWindow' dwMaximumWindowSize' wPopupAttributes'
          bFullscreenSupported' colorTable'
    poke buf info = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf cbSize
{-# LINE 209 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (dwSizeEx info)
{-# LINE 210 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (dwCursorPositionEx info)
{-# LINE 211 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 12)) buf (wAttributesEx info)
{-# LINE 212 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 14)) buf (srWindowEx info)
{-# LINE 213 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 22)) buf (dwMaximumWindowSizeEx info)
{-# LINE 214 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 26)) buf (wPopupAttributes info)
{-# LINE 215 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 28)) buf (bFullscreenSupported info)
{-# LINE 216 "System\\Win32\\Console.hsc" #-}
        pokeArray (((\hsc_ptr -> hsc_ptr `plusPtr` 32)) buf) colorTable'
{-# LINE 217 "System\\Win32\\Console.hsc" #-}
      where
        cbSize :: ULONG
        cbSize = (96)
{-# LINE 220 "System\\Win32\\Console.hsc" #-}
        colorTable' = take 16 $ colorTable info ++ repeat 0

data COORD = COORD
    { xPos :: SHORT
    , yPos :: SHORT
    } deriving (Show, Eq)

instance Storable COORD where
    sizeOf = const (4)
{-# LINE 229 "System\\Win32\\Console.hsc" #-}
    alignment _ = 2
{-# LINE 230 "System\\Win32\\Console.hsc" #-}
    peek buf = do
        x' <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
{-# LINE 232 "System\\Win32\\Console.hsc" #-}
        y' <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) buf
{-# LINE 233 "System\\Win32\\Console.hsc" #-}
        return $ COORD x' y'
    poke buf coord = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (xPos coord)
{-# LINE 236 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) buf (yPos coord)
{-# LINE 237 "System\\Win32\\Console.hsc" #-}

data SMALL_RECT = SMALL_RECT
    { leftPos   :: SHORT
    , topPos    :: SHORT
    , rightPos  :: SHORT
    , bottomPos :: SHORT
    } deriving (Show, Eq)

instance Storable SMALL_RECT where
    sizeOf _ = (8)
{-# LINE 247 "System\\Win32\\Console.hsc" #-}
    alignment _ = 2
{-# LINE 248 "System\\Win32\\Console.hsc" #-}
    peek buf = do
        left'   <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
{-# LINE 250 "System\\Win32\\Console.hsc" #-}
        top'    <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) buf
{-# LINE 251 "System\\Win32\\Console.hsc" #-}
        right'  <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
{-# LINE 252 "System\\Win32\\Console.hsc" #-}
        bottom' <- ((\hsc_ptr -> peekByteOff hsc_ptr 6)) buf
{-# LINE 253 "System\\Win32\\Console.hsc" #-}
        return $ SMALL_RECT left' top' right' bottom'
    poke buf small_rect = do
        ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (leftPos small_rect)
{-# LINE 256 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) buf (topPos small_rect)
{-# LINE 257 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (rightPos small_rect)
{-# LINE 258 "System\\Win32\\Console.hsc" #-}
        ((\hsc_ptr -> pokeByteOff hsc_ptr 6)) buf (bottomPos small_rect)
{-# LINE 259 "System\\Win32\\Console.hsc" #-}

foreign import WINDOWS_CCONV safe "windows.h GetConsoleScreenBufferInfo"
    c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO BOOL

foreign import WINDOWS_CCONV safe "windows.h GetConsoleScreenBufferInfoEx"
    c_GetConsoleScreenBufferInfoEx :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFOEX -> IO BOOL

getConsoleScreenBufferInfo :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFO
getConsoleScreenBufferInfo h = alloca $ \ptr -> do
    failIfFalse_ "GetConsoleScreenBufferInfo" $ c_GetConsoleScreenBufferInfo h ptr
    peek ptr

getCurrentConsoleScreenBufferInfo :: IO CONSOLE_SCREEN_BUFFER_INFO
getCurrentConsoleScreenBufferInfo = do
    h <- failIf (== nullHANDLE) "getStdHandle" $ getStdHandle sTD_OUTPUT_HANDLE
    getConsoleScreenBufferInfo h

getConsoleScreenBufferInfoEx :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFOEX
getConsoleScreenBufferInfoEx h = alloca $ \ptr -> do
    -- The cbSize member must be set or GetConsoleScreenBufferInfoEx fails with
    -- ERROR_INVALID_PARAMETER (87).
    ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) ptr cbSize
{-# LINE 281 "System\\Win32\\Console.hsc" #-}
    failIfFalse_ "GetConsoleScreenBufferInfoEx" $ c_GetConsoleScreenBufferInfoEx h ptr
    peek ptr
  where
    cbSize :: ULONG
    cbSize = (96)
{-# LINE 286 "System\\Win32\\Console.hsc" #-}

getCurrentConsoleScreenBufferInfoEx :: IO CONSOLE_SCREEN_BUFFER_INFOEX
getCurrentConsoleScreenBufferInfoEx = do
    h <- failIf (== nullHANDLE) "getStdHandle" $ getStdHandle sTD_OUTPUT_HANDLE
    getConsoleScreenBufferInfoEx h