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

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

    {-# LINE 6 "libraries\\Win32\\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(..),
            COORD(..),
            SMALL_RECT(..),
            getConsoleScreenBufferInfo,
            getCurrentConsoleScreenBufferInfo
      ) where

    #include "windows_cconv.h"

    import System.Win32.Types
    import Graphics.Win32.Misc

    import Foreign.C.Types (CInt(..))
    import Foreign.C.String (withCWString, CWString)
    import Foreign.Ptr (Ptr)
    import Foreign.Storable (Storable(..))
    import Foreign.Marshal.Array (peekArray)
    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
    CtrlEvent
    eNABLE_EXTENDED_FLAGS = 128
    eNABLE_INSERT_MODE = 32
    eNABLE_LINE_INPUT = 2
    eNABLE_MOUSE_INPUT = 16
    eNABLE_PROCESSED_INPUT = 1
    eNABLE_PROCESSED_INPUT :: CtrlEvent
    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 121 "libraries\\Win32\\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 commandline 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 157 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        alignment _ = 2
    {-# LINE 158 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        peek buf = do
            dwSize'              <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
    {-# LINE 160 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            dwCursorPosition'    <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
    {-# LINE 161 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            wAttributes'         <- ((\hsc_ptr -> peekByteOff hsc_ptr 8)) buf
    {-# LINE 162 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            srWindow'            <- ((\hsc_ptr -> peekByteOff hsc_ptr 10)) buf
    {-# LINE 163 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            dwMaximumWindowSize' <- ((\hsc_ptr -> peekByteOff hsc_ptr 18)) buf
    {-# LINE 164 "libraries\\Win32\\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 167 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (dwCursorPosition info)
    {-# LINE 168 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 8)) buf (wAttributes info)
    {-# LINE 169 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 10)) buf (srWindow info)
    {-# LINE 170 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 18)) buf (dwMaximumWindowSize info)
    {-# LINE 171 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}

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

    instance Storable COORD where
        sizeOf = const (4)
    {-# LINE 179 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        alignment _ = 2
    {-# LINE 180 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        peek buf = do
            x' <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
    {-# LINE 182 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            y' <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) buf
    {-# LINE 183 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            return $ COORD x' y'
        poke buf coord = do
            ((\hsc_ptr -> pokeByteOff hsc_ptr 0)) buf (xPos coord)
    {-# LINE 186 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) buf (yPos coord)
    {-# LINE 187 "libraries\\Win32\\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 197 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        alignment _ = 2
    {-# LINE 198 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
        peek buf = do
            left'   <- ((\hsc_ptr -> peekByteOff hsc_ptr 0)) buf
    {-# LINE 200 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            top'    <- ((\hsc_ptr -> peekByteOff hsc_ptr 2)) buf
    {-# LINE 201 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            right'  <- ((\hsc_ptr -> peekByteOff hsc_ptr 4)) buf
    {-# LINE 202 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            bottom' <- ((\hsc_ptr -> peekByteOff hsc_ptr 6)) buf
    {-# LINE 203 "libraries\\Win32\\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 206 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 2)) buf (topPos small_rect)
    {-# LINE 207 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 4)) buf (rightPos small_rect)
    {-# LINE 208 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}
            ((\hsc_ptr -> pokeByteOff hsc_ptr 6)) buf (bottomPos small_rect)
    {-# LINE 209 "libraries\\Win32\\System\\Win32\\Console.hsc" #-}

    foreign import WINDOWS_CCONV safe "windows.h GetConsoleScreenBufferInfo"
        c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> 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