1 # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
7 ENABLE_VIRTUAL_TERMINAL_PROCESSING
= 0x0004
11 from ctypes
import LibraryLoader
12 windll
= LibraryLoader(ctypes
.WinDLL
)
13 from ctypes
import wintypes
14 except (AttributeError, ImportError):
16 SetConsoleTextAttribute
= lambda *_
: None
17 winapi_test
= lambda *_
: None
19 from ctypes
import byref
, Structure
, c_char
, POINTER
21 COORD
= wintypes
._COORD
23 class CONSOLE_SCREEN_BUFFER_INFO(Structure
):
24 """struct in wincon.h."""
27 ("dwCursorPosition", COORD
),
28 ("wAttributes", wintypes
.WORD
),
29 ("srWindow", wintypes
.SMALL_RECT
),
30 ("dwMaximumWindowSize", COORD
),
33 return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % (
34 self
.dwSize
.Y
, self
.dwSize
.X
35 , self
.dwCursorPosition
.Y
, self
.dwCursorPosition
.X
37 , self
.srWindow
.Top
, self
.srWindow
.Left
, self
.srWindow
.Bottom
, self
.srWindow
.Right
38 , self
.dwMaximumWindowSize
.Y
, self
.dwMaximumWindowSize
.X
41 _GetStdHandle
= windll
.kernel32
.GetStdHandle
42 _GetStdHandle
.argtypes
= [
45 _GetStdHandle
.restype
= wintypes
.HANDLE
47 _GetConsoleScreenBufferInfo
= windll
.kernel32
.GetConsoleScreenBufferInfo
48 _GetConsoleScreenBufferInfo
.argtypes
= [
50 POINTER(CONSOLE_SCREEN_BUFFER_INFO
),
52 _GetConsoleScreenBufferInfo
.restype
= wintypes
.BOOL
54 _SetConsoleTextAttribute
= windll
.kernel32
.SetConsoleTextAttribute
55 _SetConsoleTextAttribute
.argtypes
= [
59 _SetConsoleTextAttribute
.restype
= wintypes
.BOOL
61 _SetConsoleCursorPosition
= windll
.kernel32
.SetConsoleCursorPosition
62 _SetConsoleCursorPosition
.argtypes
= [
66 _SetConsoleCursorPosition
.restype
= wintypes
.BOOL
68 _FillConsoleOutputCharacterA
= windll
.kernel32
.FillConsoleOutputCharacterA
69 _FillConsoleOutputCharacterA
.argtypes
= [
74 POINTER(wintypes
.DWORD
),
76 _FillConsoleOutputCharacterA
.restype
= wintypes
.BOOL
78 _FillConsoleOutputAttribute
= windll
.kernel32
.FillConsoleOutputAttribute
79 _FillConsoleOutputAttribute
.argtypes
= [
84 POINTER(wintypes
.DWORD
),
86 _FillConsoleOutputAttribute
.restype
= wintypes
.BOOL
88 _SetConsoleTitleW
= windll
.kernel32
.SetConsoleTitleW
89 _SetConsoleTitleW
.argtypes
= [
92 _SetConsoleTitleW
.restype
= wintypes
.BOOL
94 _GetConsoleMode
= windll
.kernel32
.GetConsoleMode
95 _GetConsoleMode
.argtypes
= [
97 POINTER(wintypes
.DWORD
)
99 _GetConsoleMode
.restype
= wintypes
.BOOL
101 _SetConsoleMode
= windll
.kernel32
.SetConsoleMode
102 _SetConsoleMode
.argtypes
= [
106 _SetConsoleMode
.restype
= wintypes
.BOOL
108 def _winapi_test(handle
):
109 csbi
= CONSOLE_SCREEN_BUFFER_INFO()
110 success
= _GetConsoleScreenBufferInfo(
115 return any(_winapi_test(h
) for h
in
116 (_GetStdHandle(STDOUT
), _GetStdHandle(STDERR
)))
118 def GetConsoleScreenBufferInfo(stream_id
=STDOUT
):
119 handle
= _GetStdHandle(stream_id
)
120 csbi
= CONSOLE_SCREEN_BUFFER_INFO()
121 success
= _GetConsoleScreenBufferInfo(
125 def SetConsoleTextAttribute(stream_id
, attrs
):
126 handle
= _GetStdHandle(stream_id
)
127 return _SetConsoleTextAttribute(handle
, attrs
)
129 def SetConsoleCursorPosition(stream_id
, position
, adjust
=True):
130 position
= COORD(*position
)
131 # If the position is out of range, do nothing.
132 if position
.Y
<= 0 or position
.X
<= 0:
134 # Adjust for Windows' SetConsoleCursorPosition:
135 # 1. being 0-based, while ANSI is 1-based.
136 # 2. expecting (x,y), while ANSI uses (y,x).
137 adjusted_position
= COORD(position
.Y
- 1, position
.X
- 1)
139 # Adjust for viewport's scroll position
140 sr
= GetConsoleScreenBufferInfo(STDOUT
).srWindow
141 adjusted_position
.Y
+= sr
.Top
142 adjusted_position
.X
+= sr
.Left
143 # Resume normal processing
144 handle
= _GetStdHandle(stream_id
)
145 return _SetConsoleCursorPosition(handle
, adjusted_position
)
147 def FillConsoleOutputCharacter(stream_id
, char
, length
, start
):
148 handle
= _GetStdHandle(stream_id
)
149 char
= c_char(char
.encode())
150 length
= wintypes
.DWORD(length
)
151 num_written
= wintypes
.DWORD(0)
152 # Note that this is hard-coded for ANSI (vs wide) bytes.
153 success
= _FillConsoleOutputCharacterA(
154 handle
, char
, length
, start
, byref(num_written
))
155 return num_written
.value
157 def FillConsoleOutputAttribute(stream_id
, attr
, length
, start
):
158 ''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )'''
159 handle
= _GetStdHandle(stream_id
)
160 attribute
= wintypes
.WORD(attr
)
161 length
= wintypes
.DWORD(length
)
162 num_written
= wintypes
.DWORD(0)
163 # Note that this is hard-coded for ANSI (vs wide) bytes.
164 return _FillConsoleOutputAttribute(
165 handle
, attribute
, length
, start
, byref(num_written
))
167 def SetConsoleTitle(title
):
168 return _SetConsoleTitleW(title
)
170 def GetConsoleMode(handle
):
171 mode
= wintypes
.DWORD()
172 success
= _GetConsoleMode(handle
, byref(mode
))
174 raise ctypes
.WinError()
177 def SetConsoleMode(handle
, mode
):
178 success
= _SetConsoleMode(handle
, mode
)
180 raise ctypes
.WinError()