|
Packit |
fc89b4 |
{-# OPTIONS_HADDOCK hide #-}
|
|
Packit |
fc89b4 |
{-# LANGUAGE RankNTypes #-}
|
|
Packit |
fc89b4 |
{-# LANGUAGE DeriveDataTypeable #-}
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- | "System.Win32.Console" is really very impoverished, so I have had to do all the FFI myself.
|
|
Packit |
fc89b4 |
module System.Console.ANSI.Windows.Foreign (
|
|
Packit |
fc89b4 |
-- Re-exports from Win32.Types
|
|
Packit |
fc89b4 |
BOOL, WORD, DWORD, WCHAR, HANDLE, iNVALID_HANDLE_VALUE, nullHANDLE,
|
|
Packit |
fc89b4 |
SHORT,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- 'Re-exports from System.Win32.Console.Extra'
|
|
Packit |
fc89b4 |
INPUT_RECORD(..), INPUT_RECORD_EVENT(..), kEY_EVENT,
|
|
Packit |
fc89b4 |
KEY_EVENT_RECORD(..), UNICODE_ASCII_CHAR (..), writeConsoleInput,
|
|
Packit |
fc89b4 |
getNumberOfConsoleInputEvents, readConsoleInput,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
charToWCHAR, cWcharsToChars,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
COORD(..), SMALL_RECT(..), rect_top, rect_bottom, rect_left, rect_right, rect_width, rect_height,
|
|
Packit |
fc89b4 |
CONSOLE_CURSOR_INFO(..), CONSOLE_SCREEN_BUFFER_INFO(..), CHAR_INFO(..),
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
eNABLE_VIRTUAL_TERMINAL_INPUT,
|
|
Packit |
fc89b4 |
eNABLE_VIRTUAL_TERMINAL_PROCESSING,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY, fOREGROUND_WHITE, fOREGROUND_INTENSE_WHITE,
|
|
Packit |
fc89b4 |
bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY, bACKGROUND_WHITE, bACKGROUND_INTENSE_WHITE,
|
|
Packit |
fc89b4 |
cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
getStdHandle,
|
|
Packit |
fc89b4 |
getConsoleScreenBufferInfo,
|
|
Packit |
fc89b4 |
getConsoleCursorInfo,
|
|
Packit |
fc89b4 |
getConsoleMode,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleTextAttribute,
|
|
Packit |
fc89b4 |
setConsoleCursorPosition,
|
|
Packit |
fc89b4 |
setConsoleCursorInfo,
|
|
Packit |
fc89b4 |
setConsoleTitle,
|
|
Packit |
fc89b4 |
setConsoleMode,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fillConsoleOutputAttribute,
|
|
Packit |
fc89b4 |
fillConsoleOutputCharacter,
|
|
Packit |
fc89b4 |
scrollConsoleScreenBuffer,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
withTString, withHandleToHANDLE,
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
ConsoleException(..)
|
|
Packit |
fc89b4 |
) where
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
import Foreign.C.Types
|
|
Packit |
fc89b4 |
import Foreign.Marshal
|
|
Packit |
fc89b4 |
import Foreign.Ptr
|
|
Packit |
fc89b4 |
import Foreign.Storable
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
import Data.Bits
|
|
Packit |
fc89b4 |
import Data.Char
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
import System.Win32.Types
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
import Control.Exception (Exception, throw)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
#if __GLASGOW_HASKELL__ >= 612
|
|
Packit |
fc89b4 |
import Data.Typeable
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
#if !MIN_VERSION_Win32(2,5,1)
|
|
Packit |
fc89b4 |
import Control.Concurrent.MVar
|
|
Packit |
fc89b4 |
import Foreign.StablePtr
|
|
Packit |
fc89b4 |
import Control.Exception (bracket)
|
|
Packit |
fc89b4 |
#if __GLASGOW_HASKELL__ >= 612
|
|
Packit |
fc89b4 |
import GHC.IO.Handle.Types (Handle(..), Handle__(..))
|
|
Packit |
fc89b4 |
import GHC.IO.FD (FD(..)) -- A wrapper around an Int32
|
|
Packit |
fc89b4 |
import Data.Typeable
|
|
Packit |
fc89b4 |
#else
|
|
Packit |
fc89b4 |
import GHC.IOBase (Handle(..), Handle__(..))
|
|
Packit |
fc89b4 |
import qualified GHC.IOBase as IOBase (FD) -- Just an Int32
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
#if defined(i386_HOST_ARCH)
|
|
Packit |
fc89b4 |
# define WINDOWS_CCONV stdcall
|
|
Packit |
fc89b4 |
#elif defined(x86_64_HOST_ARCH)
|
|
Packit |
fc89b4 |
# define WINDOWS_CCONV ccall
|
|
Packit |
fc89b4 |
#else
|
|
Packit |
fc89b4 |
# error Unknown mingw32 arch
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
--import System.Console.ANSI.Windows.Foreign.Compat
|
|
Packit |
fc89b4 |
#if !MIN_VERSION_Win32(2,5,0)
|
|
Packit |
fc89b4 |
-- Some Windows types missing from System.Win32 prior version 2.5.0.0
|
|
Packit |
fc89b4 |
type SHORT = CShort
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
type WCHAR = CWchar
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
charToWCHAR :: Char -> WCHAR
|
|
Packit |
fc89b4 |
charToWCHAR char = fromIntegral (ord char)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- This is a FFI hack. Some of the API calls take a Coord, but that isn't a built-in FFI type so I can't
|
|
Packit |
fc89b4 |
-- use it directly. Instead, I use UNPACKED_COORD and marshal COORDs into this manually. Note that we CAN'T
|
|
Packit |
fc89b4 |
-- just use two SHORTs directly because they get expanded to 4 bytes each instead of just boing 2 lots of 2
|
|
Packit |
fc89b4 |
-- bytes by the stdcall convention, so linking fails.
|
|
Packit |
fc89b4 |
type UNPACKED_COORD = CInt
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- Field packing order determined experimentally: I couldn't immediately find a specification for Windows
|
|
Packit |
fc89b4 |
-- struct layout anywhere.
|
|
Packit |
fc89b4 |
unpackCOORD :: COORD -> UNPACKED_COORD
|
|
Packit |
fc89b4 |
unpackCOORD (COORD x y) = (fromIntegral y) `shiftL` (sizeOf x * 8) .|. (fromIntegral x)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
peekAndOffset :: Storable a => Ptr a -> IO (a, Ptr b)
|
|
Packit |
fc89b4 |
peekAndOffset ptr = do
|
|
Packit |
fc89b4 |
item <- peek ptr
|
|
Packit |
fc89b4 |
return (item, ptr `plusPtr` sizeOf item)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
pokeAndOffset :: Storable a => Ptr a -> a -> IO (Ptr b)
|
|
Packit |
fc89b4 |
pokeAndOffset ptr item = do
|
|
Packit |
fc89b4 |
poke ptr item
|
|
Packit |
fc89b4 |
return (ptr `plusPtr` sizeOf item)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data COORD = COORD {
|
|
Packit |
fc89b4 |
coord_x :: SHORT,
|
|
Packit |
fc89b4 |
coord_y :: SHORT
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
deriving (Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Show COORD where
|
|
Packit |
fc89b4 |
show (COORD x y) = "(" ++ show x ++ ", " ++ show y ++ ")"
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable COORD where
|
|
Packit |
fc89b4 |
sizeOf ~(COORD x y) = sizeOf x + sizeOf y
|
|
Packit |
fc89b4 |
alignment ~(COORD x _) = alignment x
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
let ptr' = castPtr ptr :: Ptr SHORT
|
|
Packit |
fc89b4 |
x <- peekElemOff ptr' 0
|
|
Packit |
fc89b4 |
y <- peekElemOff ptr' 1
|
|
Packit |
fc89b4 |
return (COORD x y)
|
|
Packit |
fc89b4 |
poke ptr (COORD x y) = do
|
|
Packit |
fc89b4 |
let ptr' = castPtr ptr :: Ptr SHORT
|
|
Packit |
fc89b4 |
pokeElemOff ptr' 0 x
|
|
Packit |
fc89b4 |
pokeElemOff ptr' 1 y
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data SMALL_RECT = SMALL_RECT {
|
|
Packit |
fc89b4 |
rect_top_left :: COORD,
|
|
Packit |
fc89b4 |
rect_bottom_right :: COORD
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
rect_top, rect_left, rect_bottom, rect_right :: SMALL_RECT -> SHORT
|
|
Packit |
fc89b4 |
rect_top = coord_y . rect_top_left
|
|
Packit |
fc89b4 |
rect_left = coord_x . rect_top_left
|
|
Packit |
fc89b4 |
rect_bottom = coord_y . rect_bottom_right
|
|
Packit |
fc89b4 |
rect_right = coord_x . rect_bottom_right
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
rect_width, rect_height :: SMALL_RECT -> SHORT
|
|
Packit |
fc89b4 |
rect_width rect = rect_right rect - rect_left rect + 1
|
|
Packit |
fc89b4 |
rect_height rect = rect_bottom rect - rect_top rect + 1
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Show SMALL_RECT where
|
|
Packit |
fc89b4 |
show (SMALL_RECT tl br) = show tl ++ "-" ++ show br
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable SMALL_RECT where
|
|
Packit |
fc89b4 |
sizeOf ~(SMALL_RECT tl br) = sizeOf tl + sizeOf br
|
|
Packit |
fc89b4 |
alignment ~(SMALL_RECT tl _) = alignment tl
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
let ptr' = castPtr ptr :: Ptr COORD
|
|
Packit |
fc89b4 |
tl <- peekElemOff ptr' 0
|
|
Packit |
fc89b4 |
br <- peekElemOff ptr' 1
|
|
Packit |
fc89b4 |
return (SMALL_RECT tl br)
|
|
Packit |
fc89b4 |
poke ptr (SMALL_RECT tl br) = do
|
|
Packit |
fc89b4 |
let ptr' = castPtr ptr :: Ptr COORD
|
|
Packit |
fc89b4 |
pokeElemOff ptr' 0 tl
|
|
Packit |
fc89b4 |
pokeElemOff ptr' 1 br
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data CONSOLE_CURSOR_INFO = CONSOLE_CURSOR_INFO {
|
|
Packit |
fc89b4 |
cci_cursor_size :: DWORD,
|
|
Packit |
fc89b4 |
cci_cursor_visible :: BOOL
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
deriving (Show)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable CONSOLE_CURSOR_INFO where
|
|
Packit |
fc89b4 |
sizeOf ~(CONSOLE_CURSOR_INFO size visible) = sizeOf size + sizeOf visible
|
|
Packit |
fc89b4 |
alignment ~(CONSOLE_CURSOR_INFO size _) = alignment size
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
(size, ptr') <- peekAndOffset (castPtr ptr)
|
|
Packit |
fc89b4 |
visible <- peek ptr'
|
|
Packit |
fc89b4 |
return (CONSOLE_CURSOR_INFO size visible)
|
|
Packit |
fc89b4 |
poke ptr (CONSOLE_CURSOR_INFO size visible) = do
|
|
Packit |
fc89b4 |
ptr' <- pokeAndOffset (castPtr ptr) size
|
|
Packit |
fc89b4 |
poke ptr' visible
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data CONSOLE_SCREEN_BUFFER_INFO = CONSOLE_SCREEN_BUFFER_INFO {
|
|
Packit |
fc89b4 |
csbi_size :: COORD,
|
|
Packit |
fc89b4 |
csbi_cursor_position :: COORD,
|
|
Packit |
fc89b4 |
csbi_attributes :: WORD,
|
|
Packit |
fc89b4 |
csbi_window :: SMALL_RECT,
|
|
Packit |
fc89b4 |
csbi_maximum_window_size :: COORD
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
deriving (Show)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable CONSOLE_SCREEN_BUFFER_INFO where
|
|
Packit |
fc89b4 |
sizeOf ~(CONSOLE_SCREEN_BUFFER_INFO size cursor_position attributes window maximum_window_size)
|
|
Packit |
fc89b4 |
= sizeOf size + sizeOf cursor_position + sizeOf attributes + sizeOf window + sizeOf maximum_window_size
|
|
Packit |
fc89b4 |
alignment ~(CONSOLE_SCREEN_BUFFER_INFO size _ _ _ _) = alignment size
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
(size, ptr1) <- peekAndOffset (castPtr ptr)
|
|
Packit |
fc89b4 |
(cursor_position, ptr2) <- peekAndOffset ptr1
|
|
Packit |
fc89b4 |
(attributes, ptr3) <- peekAndOffset ptr2
|
|
Packit |
fc89b4 |
(window, ptr4) <- peekAndOffset ptr3
|
|
Packit |
fc89b4 |
maximum_window_size <- peek ptr4
|
|
Packit |
fc89b4 |
return (CONSOLE_SCREEN_BUFFER_INFO size cursor_position attributes window maximum_window_size)
|
|
Packit |
fc89b4 |
poke ptr (CONSOLE_SCREEN_BUFFER_INFO size cursor_position attributes window maximum_window_size) = do
|
|
Packit |
fc89b4 |
ptr1 <- pokeAndOffset (castPtr ptr) size
|
|
Packit |
fc89b4 |
ptr2 <- pokeAndOffset ptr1 cursor_position
|
|
Packit |
fc89b4 |
ptr3 <- pokeAndOffset ptr2 attributes
|
|
Packit |
fc89b4 |
ptr4 <- pokeAndOffset ptr3 window
|
|
Packit |
fc89b4 |
poke ptr4 maximum_window_size
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data CHAR_INFO = CHAR_INFO {
|
|
Packit |
fc89b4 |
ci_char :: WCHAR,
|
|
Packit |
fc89b4 |
ci_attributes :: WORD
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
deriving (Show)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable CHAR_INFO where
|
|
Packit |
fc89b4 |
sizeOf ~(CHAR_INFO char attributes) = sizeOf char + sizeOf attributes
|
|
Packit |
fc89b4 |
alignment ~(CHAR_INFO char _) = alignment char
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
(char, ptr') <- peekAndOffset (castPtr ptr)
|
|
Packit |
fc89b4 |
attributes <- peek ptr'
|
|
Packit |
fc89b4 |
return (CHAR_INFO char attributes)
|
|
Packit |
fc89b4 |
poke ptr (CHAR_INFO char attributes) = do
|
|
Packit |
fc89b4 |
ptr' <- pokeAndOffset (castPtr ptr) char
|
|
Packit |
fc89b4 |
poke ptr' attributes
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
eNABLE_VIRTUAL_TERMINAL_INPUT, eNABLE_VIRTUAL_TERMINAL_PROCESSING :: DWORD
|
|
Packit |
fc89b4 |
sTD_INPUT_HANDLE, sTD_OUTPUT_HANDLE, sTD_ERROR_HANDLE :: DWORD
|
|
Packit |
fc89b4 |
eNABLE_VIRTUAL_TERMINAL_INPUT = 512
|
|
Packit |
fc89b4 |
eNABLE_VIRTUAL_TERMINAL_PROCESSING = 4
|
|
Packit |
fc89b4 |
sTD_INPUT_HANDLE = -10
|
|
Packit |
fc89b4 |
sTD_OUTPUT_HANDLE = -11
|
|
Packit |
fc89b4 |
sTD_ERROR_HANDLE = -12
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fOREGROUND_BLUE, fOREGROUND_GREEN, fOREGROUND_RED, fOREGROUND_INTENSITY,
|
|
Packit |
fc89b4 |
bACKGROUND_BLUE, bACKGROUND_GREEN, bACKGROUND_RED, bACKGROUND_INTENSITY,
|
|
Packit |
fc89b4 |
cOMMON_LVB_REVERSE_VIDEO, cOMMON_LVB_UNDERSCORE :: WORD
|
|
Packit |
fc89b4 |
fOREGROUND_BLUE = 0x1
|
|
Packit |
fc89b4 |
fOREGROUND_GREEN = 0x2
|
|
Packit |
fc89b4 |
fOREGROUND_RED = 0x4
|
|
Packit |
fc89b4 |
fOREGROUND_INTENSITY = 0x8
|
|
Packit |
fc89b4 |
bACKGROUND_BLUE = 0x10
|
|
Packit |
fc89b4 |
bACKGROUND_GREEN = 0x20
|
|
Packit |
fc89b4 |
bACKGROUND_RED= 0x40
|
|
Packit |
fc89b4 |
bACKGROUND_INTENSITY = 0x80
|
|
Packit |
fc89b4 |
cOMMON_LVB_REVERSE_VIDEO = 0x4000
|
|
Packit |
fc89b4 |
cOMMON_LVB_UNDERSCORE = 0x8000
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fOREGROUND_WHITE, bACKGROUND_WHITE, fOREGROUND_INTENSE_WHITE, bACKGROUND_INTENSE_WHITE :: WORD
|
|
Packit |
fc89b4 |
fOREGROUND_WHITE = fOREGROUND_RED .|. fOREGROUND_GREEN .|. fOREGROUND_BLUE
|
|
Packit |
fc89b4 |
bACKGROUND_WHITE = bACKGROUND_RED .|. bACKGROUND_GREEN .|. bACKGROUND_BLUE
|
|
Packit |
fc89b4 |
fOREGROUND_INTENSE_WHITE = fOREGROUND_WHITE .|. fOREGROUND_INTENSITY
|
|
Packit |
fc89b4 |
bACKGROUND_INTENSE_WHITE = bACKGROUND_WHITE .|. bACKGROUND_INTENSITY
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
kEY_EVENT, mOUSE_EVENT, wINDOW_BUFFER_SIZE_EVENT, mENU_EVENT, fOCUS_EVENT :: WORD
|
|
Packit |
fc89b4 |
kEY_EVENT = 1
|
|
Packit |
fc89b4 |
mOUSE_EVENT = 2
|
|
Packit |
fc89b4 |
wINDOW_BUFFER_SIZE_EVENT = 4
|
|
Packit |
fc89b4 |
mENU_EVENT = 8
|
|
Packit |
fc89b4 |
fOCUS_EVENT = 16
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h GetStdHandle" getStdHandle :: DWORD -> IO HANDLE
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleScreenBufferInfo" cGetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleCursorInfo" cGetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleMode" cGetConsoleMode :: HANDLE -> Ptr DWORD -> IO BOOL
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTextAttribute" cSetConsoleTextAttribute :: HANDLE -> WORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorPosition" cSetConsoleCursorPosition :: HANDLE -> UNPACKED_COORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleCursorInfo" cSetConsoleCursorInfo :: HANDLE -> Ptr CONSOLE_CURSOR_INFO -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleTitleW" cSetConsoleTitle :: LPCTSTR -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h SetConsoleMode" cSetConsoleMode :: HANDLE -> DWORD -> IO BOOL
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputAttribute" cFillConsoleOutputAttribute :: HANDLE -> WORD -> DWORD -> UNPACKED_COORD -> Ptr DWORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h FillConsoleOutputCharacterW" cFillConsoleOutputCharacter :: HANDLE -> TCHAR -> DWORD -> UNPACKED_COORD -> Ptr DWORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h ScrollConsoleScreenBufferW" cScrollConsoleScreenBuffer :: HANDLE -> Ptr SMALL_RECT -> Ptr SMALL_RECT -> UNPACKED_COORD -> Ptr CHAR_INFO -> IO BOOL
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h WriteConsoleInputW" cWriteConsoleInput :: HANDLE -> Ptr INPUT_RECORD -> DWORD -> LPDWORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h GetNumberOfConsoleInputEvents" cGetNumberOfConsoleInputEvents :: HANDLE -> Ptr DWORD -> IO BOOL
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "windows.h ReadConsoleInputW" cReadConsoleInput :: HANDLE -> Ptr INPUT_RECORD -> DWORD -> LPDWORD -> IO BOOL
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data ConsoleException = ConsoleException !ErrCode deriving (Show, Eq, Typeable)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Exception ConsoleException
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
throwIfFalse :: IO Bool -> IO ()
|
|
Packit |
fc89b4 |
throwIfFalse action = do
|
|
Packit |
fc89b4 |
succeeded <- action
|
|
Packit |
fc89b4 |
if not succeeded
|
|
Packit |
fc89b4 |
then getLastError >>= throw . ConsoleException -- TODO: Check if last error is zero for some instructable reason (?)
|
|
Packit |
fc89b4 |
else return ()
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
getConsoleScreenBufferInfo :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFO
|
|
Packit |
fc89b4 |
getConsoleScreenBufferInfo handle = alloca $ \ptr_console_screen_buffer_info -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cGetConsoleScreenBufferInfo handle ptr_console_screen_buffer_info
|
|
Packit |
fc89b4 |
peek ptr_console_screen_buffer_info
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
getConsoleCursorInfo :: HANDLE -> IO CONSOLE_CURSOR_INFO
|
|
Packit |
fc89b4 |
getConsoleCursorInfo handle = alloca $ \ptr_console_cursor_info -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cGetConsoleCursorInfo handle ptr_console_cursor_info
|
|
Packit |
fc89b4 |
peek ptr_console_cursor_info
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
getConsoleMode :: HANDLE -> IO DWORD
|
|
Packit |
fc89b4 |
getConsoleMode handle = alloca $ \ptr_mode -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cGetConsoleMode handle ptr_mode
|
|
Packit |
fc89b4 |
peek ptr_mode
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleTextAttribute :: HANDLE -> WORD -> IO ()
|
|
Packit |
fc89b4 |
setConsoleTextAttribute handle attributes = throwIfFalse $ cSetConsoleTextAttribute handle attributes
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleCursorPosition :: HANDLE -> COORD -> IO ()
|
|
Packit |
fc89b4 |
setConsoleCursorPosition handle cursor_position = throwIfFalse $ cSetConsoleCursorPosition handle (unpackCOORD cursor_position)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleCursorInfo :: HANDLE -> CONSOLE_CURSOR_INFO -> IO ()
|
|
Packit |
fc89b4 |
setConsoleCursorInfo handle console_cursor_info = with console_cursor_info $ \ptr_console_cursor_info -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cSetConsoleCursorInfo handle ptr_console_cursor_info
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleTitle :: LPCTSTR -> IO ()
|
|
Packit |
fc89b4 |
setConsoleTitle title = throwIfFalse $ cSetConsoleTitle title
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
setConsoleMode :: HANDLE -> DWORD -> IO ()
|
|
Packit |
fc89b4 |
setConsoleMode handle attributes = throwIfFalse $ cSetConsoleMode handle attributes
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fillConsoleOutputAttribute :: HANDLE -> WORD -> DWORD -> COORD -> IO DWORD
|
|
Packit |
fc89b4 |
fillConsoleOutputAttribute handle attribute fill_length write_origin = alloca $ \ptr_chars_written -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cFillConsoleOutputAttribute handle attribute fill_length (unpackCOORD write_origin) ptr_chars_written
|
|
Packit |
fc89b4 |
peek ptr_chars_written
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
fillConsoleOutputCharacter :: HANDLE -> TCHAR -> DWORD -> COORD -> IO DWORD
|
|
Packit |
fc89b4 |
fillConsoleOutputCharacter handle char fill_length write_origin = alloca $ \ptr_chars_written -> do
|
|
Packit |
fc89b4 |
throwIfFalse $ cFillConsoleOutputCharacter handle char fill_length (unpackCOORD write_origin) ptr_chars_written
|
|
Packit |
fc89b4 |
peek ptr_chars_written
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
scrollConsoleScreenBuffer :: HANDLE -> SMALL_RECT -> Maybe SMALL_RECT -> COORD -> CHAR_INFO -> IO ()
|
|
Packit |
fc89b4 |
scrollConsoleScreenBuffer handle scroll_rectangle mb_clip_rectangle destination_origin fill
|
|
Packit |
fc89b4 |
= with scroll_rectangle $ \ptr_scroll_rectangle ->
|
|
Packit |
fc89b4 |
maybeWith with mb_clip_rectangle $ \ptr_clip_rectangle ->
|
|
Packit |
fc89b4 |
with fill $ \ptr_fill ->
|
|
Packit |
fc89b4 |
throwIfFalse $ cScrollConsoleScreenBuffer handle ptr_scroll_rectangle ptr_clip_rectangle (unpackCOORD destination_origin) ptr_fill
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
#if !MIN_VERSION_Win32(2,5,1)
|
|
Packit |
fc89b4 |
-- | This bit is all highly dubious. The problem is that we want to output ANSI to arbitrary Handles rather than forcing
|
|
Packit |
fc89b4 |
-- people to use stdout. However, the Windows ANSI emulator needs a Windows HANDLE to work it's magic, so we need to be able
|
|
Packit |
fc89b4 |
-- to extract one of those from the Haskell Handle.
|
|
Packit |
fc89b4 |
--
|
|
Packit |
fc89b4 |
-- This code accomplishes this, albeit at the cost of only being compatible with GHC.
|
|
Packit |
fc89b4 |
-- withHandleToHANDLE was added in Win32-2.5.1.0
|
|
Packit |
fc89b4 |
withHandleToHANDLE :: Handle -> (HANDLE -> IO a) -> IO a
|
|
Packit |
fc89b4 |
withHandleToHANDLE haskell_handle action =
|
|
Packit |
fc89b4 |
-- Create a stable pointer to the Handle. This prevents the garbage collector
|
|
Packit |
fc89b4 |
-- getting to it while we are doing horrible manipulations with it, and hence
|
|
Packit |
fc89b4 |
-- stops it being finalized (and closed).
|
|
Packit |
fc89b4 |
withStablePtr haskell_handle $ const $ do
|
|
Packit |
fc89b4 |
-- Grab the write handle variable from the Handle
|
|
Packit |
fc89b4 |
let write_handle_mvar = case haskell_handle of
|
|
Packit |
fc89b4 |
FileHandle _ handle_mvar -> handle_mvar
|
|
Packit |
fc89b4 |
DuplexHandle _ _ handle_mvar -> handle_mvar -- This is "write" MVar, we could also take the "read" one
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- Get the FD from the algebraic data type
|
|
Packit |
fc89b4 |
#if __GLASGOW_HASKELL__ < 612
|
|
Packit |
fc89b4 |
fd <- fmap haFD $ readMVar write_handle_mvar
|
|
Packit |
fc89b4 |
#else
|
|
Packit |
fc89b4 |
--readMVar write_handle_mvar >>= \(Handle__ { haDevice = dev }) -> print (typeOf dev)
|
|
Packit |
fc89b4 |
Just fd <- fmap (\(Handle__ { haDevice = dev }) -> fmap fdFD (cast dev)) $ readMVar write_handle_mvar
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- Finally, turn that (C-land) FD into a HANDLE using msvcrt
|
|
Packit |
fc89b4 |
windows_handle <- cget_osfhandle fd
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- Do what the user originally wanted
|
|
Packit |
fc89b4 |
action windows_handle
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- This essential function comes from the C runtime system. It is certainly provided by msvcrt, and also seems to be provided by the mingw C library - hurrah!
|
|
Packit |
fc89b4 |
#if __GLASGOW_HASKELL__ >= 612
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "_get_osfhandle" cget_osfhandle :: CInt -> IO HANDLE
|
|
Packit |
fc89b4 |
#else
|
|
Packit |
fc89b4 |
foreign import WINDOWS_CCONV unsafe "_get_osfhandle" cget_osfhandle :: IOBase.FD -> IO HANDLE
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- withStablePtr was added in Win32-2.5.1.0
|
|
Packit |
fc89b4 |
withStablePtr :: a -> (StablePtr a -> IO b) -> IO b
|
|
Packit |
fc89b4 |
withStablePtr value = bracket (newStablePtr value) freeStablePtr
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- The following is based on module System.Win32.Console.Extra from package
|
|
Packit |
fc89b4 |
-- Win32-console, cut down for the WCHAR version of writeConsoleInput.
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
writeConsoleInput :: HANDLE -> [INPUT_RECORD] -> IO DWORD
|
|
Packit |
fc89b4 |
writeConsoleInput hdl evs =
|
|
Packit |
fc89b4 |
writeConsoleInputWith hdl $ \act -> withArrayLen evs $ \len ptr -> act (ptr, toEnum len)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
writeConsoleInputWith :: HANDLE -> InputHandler (Ptr INPUT_RECORD, DWORD) -> IO DWORD
|
|
Packit |
fc89b4 |
writeConsoleInputWith hdl withBuffer =
|
|
Packit |
fc89b4 |
returnWith_ $ \ptrN ->
|
|
Packit |
fc89b4 |
withBuffer $ \(ptrBuf, len) ->
|
|
Packit |
fc89b4 |
failIfFalse_ "WriteConsoleInputW" $ cWriteConsoleInput hdl ptrBuf len ptrN
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
returnWith_ :: Storable a => (Ptr a -> IO b) -> IO a
|
|
Packit |
fc89b4 |
returnWith_ act = alloca $ \ptr -> act ptr >> peek ptr
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
type InputHandler i = forall a. (i -> IO a) -> IO a
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef union _UNICODE_ASCII_CHAR {
|
|
Packit |
fc89b4 |
WCHAR UnicodeChar;
|
|
Packit |
fc89b4 |
CHAR AsciiChar;
|
|
Packit |
fc89b4 |
} UNICODE_ASCII_CHAR;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
newtype UNICODE_ASCII_CHAR = UnicodeAsciiChar { unicodeAsciiChar :: WCHAR }
|
|
Packit |
fc89b4 |
deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable UNICODE_ASCII_CHAR where
|
|
Packit |
fc89b4 |
sizeOf _ = 2
|
|
Packit |
fc89b4 |
alignment _ = 2
|
|
Packit |
fc89b4 |
peek ptr = UnicodeAsciiChar <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
poke ptr val = case val of
|
|
Packit |
fc89b4 |
UnicodeAsciiChar c -> (`pokeByteOff` 0) ptr c
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _KEY_EVENT_RECORD {
|
|
Packit |
fc89b4 |
BOOL bKeyDown;
|
|
Packit |
fc89b4 |
WORD wRepeatCount;
|
|
Packit |
fc89b4 |
WORD wVirtualKeyCode;
|
|
Packit |
fc89b4 |
WORD wVirtualScanCode;
|
|
Packit |
fc89b4 |
union {
|
|
Packit |
fc89b4 |
WCHAR UnicodeChar;
|
|
Packit |
fc89b4 |
CHAR AsciiChar;
|
|
Packit |
fc89b4 |
} uChar;
|
|
Packit |
fc89b4 |
DWORD dwControlKeyState;
|
|
Packit |
fc89b4 |
}
|
|
Packit |
fc89b4 |
#ifdef __GNUC__
|
|
Packit |
fc89b4 |
/* gcc's alignment is not what win32 expects */
|
|
Packit |
fc89b4 |
PACKED
|
|
Packit |
fc89b4 |
#endif
|
|
Packit |
fc89b4 |
KEY_EVENT_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data KEY_EVENT_RECORD = KEY_EVENT_RECORD {
|
|
Packit |
fc89b4 |
keyEventKeyDown :: BOOL,
|
|
Packit |
fc89b4 |
keyEventRepeatCount :: WORD,
|
|
Packit |
fc89b4 |
keyEventVirtualKeyCode :: WORD,
|
|
Packit |
fc89b4 |
keyEventVirtualScanCode :: WORD,
|
|
Packit |
fc89b4 |
keyEventChar :: UNICODE_ASCII_CHAR,
|
|
Packit |
fc89b4 |
keyEventControlKeystate :: DWORD
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable KEY_EVENT_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 16
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr = KEY_EVENT_RECORD <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 6) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 8) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 10) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 12) ptr
|
|
Packit |
fc89b4 |
poke ptr val = do
|
|
Packit |
fc89b4 |
(`pokeByteOff` 0) ptr $ keyEventKeyDown val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 4) ptr $ keyEventRepeatCount val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 6) ptr $ keyEventVirtualKeyCode val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 8) ptr $ keyEventVirtualScanCode val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 10) ptr $ keyEventChar val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 12) ptr $ keyEventControlKeystate val
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _MOUSE_EVENT_RECORD {
|
|
Packit |
fc89b4 |
COORD dwMousePosition;
|
|
Packit |
fc89b4 |
DWORD dwButtonState;
|
|
Packit |
fc89b4 |
DWORD dwControlKeyState;
|
|
Packit |
fc89b4 |
DWORD dwEventFlags;
|
|
Packit |
fc89b4 |
} MOUSE_EVENT_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data MOUSE_EVENT_RECORD = MOUSE_EVENT_RECORD {
|
|
Packit |
fc89b4 |
mousePosition :: COORD,
|
|
Packit |
fc89b4 |
mouseButtonState :: DWORD,
|
|
Packit |
fc89b4 |
mouseControlKeyState :: DWORD,
|
|
Packit |
fc89b4 |
mouseEventFlags :: DWORD
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable MOUSE_EVENT_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 16
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr =
|
|
Packit |
fc89b4 |
MOUSE_EVENT_RECORD <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 8) ptr
|
|
Packit |
fc89b4 |
<*> (`peekByteOff` 12) ptr
|
|
Packit |
fc89b4 |
poke ptr val = do
|
|
Packit |
fc89b4 |
(`pokeByteOff` 0) ptr $ mousePosition val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 4) ptr $ mouseButtonState val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 8) ptr $ mouseControlKeyState val
|
|
Packit |
fc89b4 |
(`pokeByteOff` 12) ptr $ mouseEventFlags val
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _WINDOW_BUFFER_SIZE_RECORD {
|
|
Packit |
fc89b4 |
COORD dwSize;
|
|
Packit |
fc89b4 |
} WINDOW_BUFFER_SIZE_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data WINDOW_BUFFER_SIZE_RECORD = WINDOW_BUFFER_SIZE_RECORD {
|
|
Packit |
fc89b4 |
bufSizeNew :: COORD
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable WINDOW_BUFFER_SIZE_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 4
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr = WINDOW_BUFFER_SIZE_RECORD <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
poke ptr val = (`pokeByteOff` 0) ptr $ bufSizeNew val
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _MENU_EVENT_RECORD {
|
|
Packit |
fc89b4 |
UINT dwCommandId;
|
|
Packit |
fc89b4 |
} MENU_EVENT_RECORD,*PMENU_EVENT_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data MENU_EVENT_RECORD = MENU_EVENT_RECORD {
|
|
Packit |
fc89b4 |
menuCommandId :: UINT
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable MENU_EVENT_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 4
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr = MENU_EVENT_RECORD <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
poke ptr val = (`pokeByteOff` 0) ptr $ menuCommandId val
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _FOCUS_EVENT_RECORD { BOOL bSetFocus; } FOCUS_EVENT_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data FOCUS_EVENT_RECORD = FOCUS_EVENT_RECORD {
|
|
Packit |
fc89b4 |
focusSetFocus :: BOOL
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable FOCUS_EVENT_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 4
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr = FOCUS_EVENT_RECORD <$> (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
poke ptr val = (`pokeByteOff` 0) ptr $ focusSetFocus val
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
data INPUT_RECORD_EVENT
|
|
Packit |
fc89b4 |
= InputKeyEvent KEY_EVENT_RECORD
|
|
Packit |
fc89b4 |
| InputMouseEvent MOUSE_EVENT_RECORD
|
|
Packit |
fc89b4 |
| InputWindowBufferSizeEvent WINDOW_BUFFER_SIZE_RECORD
|
|
Packit |
fc89b4 |
| InputMenuEvent MENU_EVENT_RECORD
|
|
Packit |
fc89b4 |
| InputFocusEvent FOCUS_EVENT_RECORD
|
|
Packit |
fc89b4 |
deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
{-
|
|
Packit |
fc89b4 |
typedef struct _INPUT_RECORD {
|
|
Packit |
fc89b4 |
WORD EventType;
|
|
Packit |
fc89b4 |
union {
|
|
Packit |
fc89b4 |
KEY_EVENT_RECORD KeyEvent;
|
|
Packit |
fc89b4 |
MOUSE_EVENT_RECORD MouseEvent;
|
|
Packit |
fc89b4 |
WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
|
|
Packit |
fc89b4 |
MENU_EVENT_RECORD MenuEvent;
|
|
Packit |
fc89b4 |
FOCUS_EVENT_RECORD FocusEvent;
|
|
Packit |
fc89b4 |
} Event;
|
|
Packit |
fc89b4 |
} INPUT_RECORD,*PINPUT_RECORD;
|
|
Packit |
fc89b4 |
-}
|
|
Packit |
fc89b4 |
data INPUT_RECORD = INPUT_RECORD {
|
|
Packit |
fc89b4 |
inputEventType :: WORD,
|
|
Packit |
fc89b4 |
inputEvent :: INPUT_RECORD_EVENT
|
|
Packit |
fc89b4 |
} deriving (Show, Read, Eq)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
instance Storable INPUT_RECORD where
|
|
Packit |
fc89b4 |
sizeOf _ = 20
|
|
Packit |
fc89b4 |
alignment _ = 4
|
|
Packit |
fc89b4 |
peek ptr = do
|
|
Packit |
fc89b4 |
evType <- (`peekByteOff` 0) ptr
|
|
Packit |
fc89b4 |
event <- case evType of
|
|
Packit |
fc89b4 |
_ | evType == kEY_EVENT
|
|
Packit |
fc89b4 |
-> InputKeyEvent <$> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
_ | evType == mOUSE_EVENT
|
|
Packit |
fc89b4 |
-> InputMouseEvent <$> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
_ | evType == wINDOW_BUFFER_SIZE_EVENT
|
|
Packit |
fc89b4 |
-> InputWindowBufferSizeEvent <$> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
_ | evType == mENU_EVENT
|
|
Packit |
fc89b4 |
-> InputMenuEvent <$> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
_ | evType == fOCUS_EVENT
|
|
Packit |
fc89b4 |
-> InputFocusEvent <$> (`peekByteOff` 4) ptr
|
|
Packit |
fc89b4 |
_ -> error $ "peek (INPUT_RECORD): Unknown event type " ++ show evType
|
|
Packit |
fc89b4 |
return $ INPUT_RECORD evType event
|
|
Packit |
fc89b4 |
poke ptr val = do
|
|
Packit |
fc89b4 |
(`pokeByteOff` 0) ptr $ inputEventType val
|
|
Packit |
fc89b4 |
case inputEvent val of
|
|
Packit |
fc89b4 |
InputKeyEvent ev -> (`pokeByteOff` 4) ptr ev
|
|
Packit |
fc89b4 |
InputMouseEvent ev -> (`pokeByteOff` 4) ptr ev
|
|
Packit |
fc89b4 |
InputWindowBufferSizeEvent ev -> (`pokeByteOff` 4) ptr ev
|
|
Packit |
fc89b4 |
InputMenuEvent ev -> (`pokeByteOff` 4) ptr ev
|
|
Packit |
fc89b4 |
InputFocusEvent ev -> (`pokeByteOff` 4) ptr ev
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- The following is based on module System.Win32.Console.Extra from package
|
|
Packit |
fc89b4 |
-- Win32-console.
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
getNumberOfConsoleInputEvents :: HANDLE -> IO DWORD
|
|
Packit |
fc89b4 |
getNumberOfConsoleInputEvents hdl =
|
|
Packit |
fc89b4 |
returnWith_ $ \ptrN ->
|
|
Packit |
fc89b4 |
failIfFalse_ "GetNumberOfConsoleInputEvents" $ cGetNumberOfConsoleInputEvents hdl ptrN
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- The following is based on module System.Win32.Console.Extra from package
|
|
Packit |
fc89b4 |
-- Win32-console, cut down for the WCHAR version of readConsoleInput.
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
readConsoleInput :: HANDLE -> DWORD -> IO [INPUT_RECORD]
|
|
Packit |
fc89b4 |
readConsoleInput hdl len = readConsoleInputWith hdl len $ \(ptr, n) -> peekArray (fromEnum n) ptr
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
readConsoleInputWith :: HANDLE -> DWORD -> OutputHandler (Ptr INPUT_RECORD, DWORD)
|
|
Packit |
fc89b4 |
readConsoleInputWith hdl len handler =
|
|
Packit |
fc89b4 |
allocaArray (fromEnum len) $ \ptrBuf ->
|
|
Packit |
fc89b4 |
alloca $ \ptrN -> do
|
|
Packit |
fc89b4 |
failIfFalse_ "ReadConsoleInputW" $ cReadConsoleInput hdl ptrBuf len ptrN
|
|
Packit |
fc89b4 |
n <- peek ptrN
|
|
Packit |
fc89b4 |
handler (ptrBuf, n)
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
type OutputHandler o = forall a. (o -> IO a) -> IO a
|
|
Packit |
fc89b4 |
|
|
Packit |
fc89b4 |
-- Replicated from module Foreign.C.String in package base because that module
|
|
Packit |
fc89b4 |
-- does not export the function.
|
|
Packit |
fc89b4 |
cWcharsToChars :: [CWchar] -> [Char]
|
|
Packit |
fc89b4 |
cWcharsToChars = map chr . fromUTF16 . map fromIntegral
|
|
Packit |
fc89b4 |
where
|
|
Packit |
fc89b4 |
fromUTF16 (c1:c2:wcs)
|
|
Packit |
fc89b4 |
| 0xd800 <= c1 && c1 <= 0xdbff && 0xdc00 <= c2 && c2 <= 0xdfff =
|
|
Packit |
fc89b4 |
((c1 - 0xd800)*0x400 + (c2 - 0xdc00) + 0x10000) : fromUTF16 wcs
|
|
Packit |
fc89b4 |
fromUTF16 (c:wcs) = c : fromUTF16 wcs
|
|
Packit |
fc89b4 |
fromUTF16 [] = []
|