1 # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.
9 from ctypes import LibraryLoader
11 windll = LibraryLoader(ctypes.WinDLL)
12 from ctypes import wintypes
13 except (AttributeError, ImportError):
15 SetConsoleTextAttribute = lambda *_: None
16 winapi_test = lambda *_: None
18 from ctypes import byref, Structure, c_char, POINTER
20 COORD = wintypes._COORD
22 class CONSOLE_SCREEN_BUFFER_INFO(Structure):
23 """struct in wincon.h."""
27 ("dwCursorPosition", COORD),
28 ("wAttributes", wintypes.WORD),
29 ("srWindow", wintypes.SMALL_RECT),
30 ("dwMaximumWindowSize", COORD),
34 return "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)" % (
37 self.dwCursorPosition.Y,
38 self.dwCursorPosition.X,
44 self.dwMaximumWindowSize.Y,
45 self.dwMaximumWindowSize.X,
48 _GetStdHandle = windll.kernel32.GetStdHandle
49 _GetStdHandle.argtypes = [
52 _GetStdHandle.restype = wintypes.HANDLE
54 _GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo
55 _GetConsoleScreenBufferInfo.argtypes = [
57 POINTER(CONSOLE_SCREEN_BUFFER_INFO),
59 _GetConsoleScreenBufferInfo.restype = wintypes.BOOL
61 _SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute
62 _SetConsoleTextAttribute.argtypes = [
66 _SetConsoleTextAttribute.restype = wintypes.BOOL
68 _SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition
69 _SetConsoleCursorPosition.argtypes = [
73 _SetConsoleCursorPosition.restype = wintypes.BOOL
75 _FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA
76 _FillConsoleOutputCharacterA.argtypes = [
81 POINTER(wintypes.DWORD),
83 _FillConsoleOutputCharacterA.restype = wintypes.BOOL
85 _FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute
86 _FillConsoleOutputAttribute.argtypes = [
91 POINTER(wintypes.DWORD),
93 _FillConsoleOutputAttribute.restype = wintypes.BOOL
95 _SetConsoleTitleW = windll.kernel32.SetConsoleTitleA
96 _SetConsoleTitleW.argtypes = [wintypes.LPCSTR]
97 _SetConsoleTitleW.restype = wintypes.BOOL
100 STDOUT: _GetStdHandle(STDOUT),
101 STDERR: _GetStdHandle(STDERR),
105 handle = handles[STDOUT]
106 csbi = CONSOLE_SCREEN_BUFFER_INFO()
107 success = _GetConsoleScreenBufferInfo(handle, byref(csbi))
110 def GetConsoleScreenBufferInfo(stream_id=STDOUT):
111 handle = handles[stream_id]
112 csbi = CONSOLE_SCREEN_BUFFER_INFO()
113 success = _GetConsoleScreenBufferInfo(handle, byref(csbi))
116 def SetConsoleTextAttribute(stream_id, attrs):
117 handle = handles[stream_id]
118 return _SetConsoleTextAttribute(handle, attrs)
120 def SetConsoleCursorPosition(stream_id, position, adjust=True):
121 position = COORD(*position)
122 # If the position is out of range, do nothing.
123 if position.Y <= 0 or position.X <= 0:
125 # Adjust for Windows' SetConsoleCursorPosition:
126 # 1. being 0-based, while ANSI is 1-based.
127 # 2. expecting (x,y), while ANSI uses (y,x).
128 adjusted_position = COORD(position.Y - 1, position.X - 1)
130 # Adjust for viewport's scroll position
131 sr = GetConsoleScreenBufferInfo(STDOUT).srWindow
132 adjusted_position.Y += sr.Top
133 adjusted_position.X += sr.Left
134 # Resume normal processing
135 handle = handles[stream_id]
136 return _SetConsoleCursorPosition(handle, adjusted_position)
138 def FillConsoleOutputCharacter(stream_id, char, length, start):
139 handle = handles[stream_id]
140 char = c_char(char.encode())
141 length = wintypes.DWORD(length)
142 num_written = wintypes.DWORD(0)
143 # Note that this is hard-coded for ANSI (vs wide) bytes.
144 success = _FillConsoleOutputCharacterA(
145 handle, char, length, start, byref(num_written)
147 return num_written.value
149 def FillConsoleOutputAttribute(stream_id, attr, length, start):
150 """FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )"""
151 handle = handles[stream_id]
152 attribute = wintypes.WORD(attr)
153 length = wintypes.DWORD(length)
154 num_written = wintypes.DWORD(0)
155 # Note that this is hard-coded for ANSI (vs wide) bytes.
156 return _FillConsoleOutputAttribute(
157 handle, attribute, length, start, byref(num_written)
160 def SetConsoleTitle(title):
161 return _SetConsoleTitleW(title)