Skip to content

Commit 4cd33f4

Browse files
mpilgremMistuke
authored andcommitted
Add GetConsoleScreenBufferInfoEx
The function retrieves extended information about the specified console screen buffer. See https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfoex. Also adds `getCurrentConsoleScreenBufferInfoEx`, corresponding to `getCurrentConsoleScreenBufferInfo`. For convenience, re-exports `Graphics.Win32.GDI.Types.COLORREF` from module `System.Win32.Console`. Introduces `wincon_compat.h` to patch the incomplete version of `wincon.h` provided with x86 versions of GHC before GHC 7.10.
1 parent 8b77a0e commit 4cd33f4

File tree

4 files changed

+101
-4
lines changed

4 files changed

+101
-4
lines changed

System/Win32/Console.hsc

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,24 +47,30 @@ module System.Win32.Console (
4747
commandLineToArgv,
4848
-- * Screen buffer
4949
CONSOLE_SCREEN_BUFFER_INFO(..),
50+
CONSOLE_SCREEN_BUFFER_INFOEX(..),
5051
COORD(..),
5152
SMALL_RECT(..),
53+
COLORREF,
5254
getConsoleScreenBufferInfo,
53-
getCurrentConsoleScreenBufferInfo
55+
getCurrentConsoleScreenBufferInfo,
56+
getConsoleScreenBufferInfoEx,
57+
getCurrentConsoleScreenBufferInfoEx
5458
) where
5559

5660
#include <windows.h>
5761
#include "alignment.h"
5862
##include "windows_cconv.h"
63+
#include "wincon_compat.h"
5964

6065
import System.Win32.Types
6166
import Graphics.Win32.Misc
67+
import Graphics.Win32.GDI.Types (COLORREF)
6268

6369
import Foreign.C.Types (CInt(..))
6470
import Foreign.C.String (withCWString, CWString)
65-
import Foreign.Ptr (Ptr)
71+
import Foreign.Ptr (Ptr, plusPtr)
6672
import Foreign.Storable (Storable(..))
67-
import Foreign.Marshal.Array (peekArray)
73+
import Foreign.Marshal.Array (peekArray, pokeArray)
6874
import Foreign.Marshal.Alloc (alloca)
6975

7076
foreign import WINDOWS_CCONV unsafe "windows.h GetConsoleMode"
@@ -169,6 +175,50 @@ instance Storable CONSOLE_SCREEN_BUFFER_INFO where
169175
(#poke CONSOLE_SCREEN_BUFFER_INFO, srWindow) buf (srWindow info)
170176
(#poke CONSOLE_SCREEN_BUFFER_INFO, dwMaximumWindowSize) buf (dwMaximumWindowSize info)
171177

178+
data CONSOLE_SCREEN_BUFFER_INFOEX = CONSOLE_SCREEN_BUFFER_INFOEX
179+
{ dwSizeEx :: COORD
180+
, dwCursorPositionEx :: COORD
181+
, wAttributesEx :: WORD
182+
, srWindowEx :: SMALL_RECT
183+
, dwMaximumWindowSizeEx :: COORD
184+
, wPopupAttributes :: WORD
185+
, bFullscreenSupported :: BOOL
186+
, colorTable :: [COLORREF]
187+
-- ^ Only the first 16 'COLORREF' values passed to the Windows Console
188+
-- API. If fewer than 16 values, the remainder are padded with @0@ when
189+
-- passed to the API.
190+
} deriving (Show, Eq)
191+
192+
instance Storable CONSOLE_SCREEN_BUFFER_INFOEX where
193+
sizeOf = const #{size CONSOLE_SCREEN_BUFFER_INFOEX}
194+
alignment = const #{alignment CONSOLE_SCREEN_BUFFER_INFOEX}
195+
peek buf = do
196+
dwSize' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, dwSize) buf
197+
dwCursorPosition' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, dwCursorPosition) buf
198+
wAttributes' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, wAttributes) buf
199+
srWindow' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, srWindow) buf
200+
dwMaximumWindowSize' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, dwMaximumWindowSize) buf
201+
wPopupAttributes' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, wPopupAttributes) buf
202+
bFullscreenSupported' <- (#peek CONSOLE_SCREEN_BUFFER_INFOEX, bFullscreenSupported) buf
203+
colorTable' <- peekArray 16 ((#ptr CONSOLE_SCREEN_BUFFER_INFOEX, ColorTable) buf)
204+
return $ CONSOLE_SCREEN_BUFFER_INFOEX dwSize' dwCursorPosition'
205+
wAttributes' srWindow' dwMaximumWindowSize' wPopupAttributes'
206+
bFullscreenSupported' colorTable'
207+
poke buf info = do
208+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, cbSize) buf cbSize
209+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, dwSize) buf (dwSizeEx info)
210+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, dwCursorPosition) buf (dwCursorPositionEx info)
211+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, wAttributes) buf (wAttributesEx info)
212+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, srWindow) buf (srWindowEx info)
213+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, dwMaximumWindowSize) buf (dwMaximumWindowSizeEx info)
214+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, wPopupAttributes) buf (wPopupAttributes info)
215+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, bFullscreenSupported) buf (bFullscreenSupported info)
216+
pokeArray ((#ptr CONSOLE_SCREEN_BUFFER_INFOEX, ColorTable) buf) colorTable'
217+
where
218+
cbSize :: ULONG
219+
cbSize = #{size CONSOLE_SCREEN_BUFFER_INFOEX}
220+
colorTable' = take 16 $ colorTable info ++ repeat 0
221+
172222
data COORD = COORD
173223
{ xPos :: SHORT
174224
, yPos :: SHORT
@@ -210,6 +260,9 @@ instance Storable SMALL_RECT where
210260
foreign import WINDOWS_CCONV safe "windows.h GetConsoleScreenBufferInfo"
211261
c_GetConsoleScreenBufferInfo :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFO -> IO BOOL
212262

263+
foreign import WINDOWS_CCONV safe "windows.h GetConsoleScreenBufferInfoEx"
264+
c_GetConsoleScreenBufferInfoEx :: HANDLE -> Ptr CONSOLE_SCREEN_BUFFER_INFOEX -> IO BOOL
265+
213266
getConsoleScreenBufferInfo :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFO
214267
getConsoleScreenBufferInfo h = alloca $ \ptr -> do
215268
failIfFalse_ "GetConsoleScreenBufferInfo" $ c_GetConsoleScreenBufferInfo h ptr
@@ -219,3 +272,19 @@ getCurrentConsoleScreenBufferInfo :: IO CONSOLE_SCREEN_BUFFER_INFO
219272
getCurrentConsoleScreenBufferInfo = do
220273
h <- failIf (== nullHANDLE) "getStdHandle" $ getStdHandle sTD_OUTPUT_HANDLE
221274
getConsoleScreenBufferInfo h
275+
276+
getConsoleScreenBufferInfoEx :: HANDLE -> IO CONSOLE_SCREEN_BUFFER_INFOEX
277+
getConsoleScreenBufferInfoEx h = alloca $ \ptr -> do
278+
-- The cbSize member must be set or GetConsoleScreenBufferInfoEx fails with
279+
-- ERROR_INVALID_PARAMETER (87).
280+
(#poke CONSOLE_SCREEN_BUFFER_INFOEX, cbSize) ptr cbSize
281+
failIfFalse_ "GetConsoleScreenBufferInfoEx" $ c_GetConsoleScreenBufferInfoEx h ptr
282+
peek ptr
283+
where
284+
cbSize :: ULONG
285+
cbSize = #{size CONSOLE_SCREEN_BUFFER_INFOEX}
286+
287+
getCurrentConsoleScreenBufferInfoEx :: IO CONSOLE_SCREEN_BUFFER_INFOEX
288+
getCurrentConsoleScreenBufferInfoEx = do
289+
h <- failIf (== nullHANDLE) "getStdHandle" $ getStdHandle sTD_OUTPUT_HANDLE
290+
getConsoleScreenBufferInfoEx h

Win32.cabal

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ Library
108108
ghc-options: -Wall
109109
include-dirs: include
110110
includes: "alphablend.h", "diatemp.h", "dumpBMP.h", "ellipse.h", "errors.h", "HsGDI.h", "HsWin32.h", "Win32Aux.h", "win32debug.h", "windows_cconv.h", "WndProc.h", "alignment.h"
111-
install-includes: "HsWin32.h", "HsGDI.h", "WndProc.h", "windows_cconv.h", "alphablend.h", "winternl_compat.h", "winuser_compat.h", "winreg_compat.h", "tlhelp32_compat.h", "winnls_compat.h", "winnt_compat.h"
111+
install-includes: "HsWin32.h", "HsGDI.h", "WndProc.h", "windows_cconv.h", "alphablend.h", "wincon_compat.h", "winternl_compat.h", "winuser_compat.h", "winreg_compat.h", "tlhelp32_compat.h", "winnls_compat.h", "winnt_compat.h"
112112
c-sources:
113113
cbits/HsGDI.c
114114
cbits/HsWin32.c

changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Add function `createIcon` (see #194)
66
* Add `WindowMessage` value `wM_SETICON` (see #194)
77
* Add `WPARAM` values `iCON_SMALL`, `iCON_BIG` (see #194)
8+
* Add functions `getConsoleScreenBufferInfoEx` and
9+
`getCurrentConsoleScreenBufferInfoEx`
810

911
## 2.13.2.0 November 2021
1012

include/wincon_compat.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/* The version of wincon.h provided by the version of MSYS2 included with x86
2+
* versions of GHC before GHC 7.10 excludes certain components introduced with
3+
* Windows Vista.
4+
*/
5+
6+
#ifndef WINCON_COMPAT_H
7+
#define WINCON_COMPAT_H
8+
9+
#if defined(x86_64_HOST_ARCH) || __GLASGOW_HASKELL__ > 708
10+
#
11+
#else
12+
13+
typedef struct _CONSOLE_SCREEN_BUFFER_INFOEX {
14+
ULONG cbSize;
15+
COORD dwSize;
16+
COORD dwCursorPosition;
17+
WORD wAttributes;
18+
SMALL_RECT srWindow;
19+
COORD dwMaximumWindowSize;
20+
WORD wPopupAttributes;
21+
WINBOOL bFullscreenSupported;
22+
COLORREF ColorTable[16];
23+
} CONSOLE_SCREEN_BUFFER_INFOEX, *PCONSOLE_SCREEN_BUFFER_INFOEX;
24+
25+
#endif /* GHC version check */
26+
#endif /* WINCON_COMPAT_H */

0 commit comments

Comments
 (0)