Spaces:
Runtime error
Runtime error
# Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file. | |
# from winbase.h | |
STDOUT = -11 | |
STDERR = -12 | |
ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004 | |
try: | |
import ctypes | |
from ctypes import LibraryLoader | |
windll = LibraryLoader(ctypes.WinDLL) | |
from ctypes import wintypes | |
except (AttributeError, ImportError): | |
windll = None | |
SetConsoleTextAttribute = lambda *_: None | |
winapi_test = lambda *_: None | |
else: | |
from ctypes import byref, Structure, c_char, POINTER | |
COORD = wintypes._COORD | |
class CONSOLE_SCREEN_BUFFER_INFO(Structure): | |
"""struct in wincon.h.""" | |
_fields_ = [ | |
("dwSize", COORD), | |
("dwCursorPosition", COORD), | |
("wAttributes", wintypes.WORD), | |
("srWindow", wintypes.SMALL_RECT), | |
("dwMaximumWindowSize", COORD), | |
] | |
def __str__(self): | |
return '(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)' % ( | |
self.dwSize.Y, self.dwSize.X | |
, self.dwCursorPosition.Y, self.dwCursorPosition.X | |
, self.wAttributes | |
, self.srWindow.Top, self.srWindow.Left, self.srWindow.Bottom, self.srWindow.Right | |
, self.dwMaximumWindowSize.Y, self.dwMaximumWindowSize.X | |
) | |
_GetStdHandle = windll.kernel32.GetStdHandle | |
_GetStdHandle.argtypes = [ | |
wintypes.DWORD, | |
] | |
_GetStdHandle.restype = wintypes.HANDLE | |
_GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo | |
_GetConsoleScreenBufferInfo.argtypes = [ | |
wintypes.HANDLE, | |
POINTER(CONSOLE_SCREEN_BUFFER_INFO), | |
] | |
_GetConsoleScreenBufferInfo.restype = wintypes.BOOL | |
_SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute | |
_SetConsoleTextAttribute.argtypes = [ | |
wintypes.HANDLE, | |
wintypes.WORD, | |
] | |
_SetConsoleTextAttribute.restype = wintypes.BOOL | |
_SetConsoleCursorPosition = windll.kernel32.SetConsoleCursorPosition | |
_SetConsoleCursorPosition.argtypes = [ | |
wintypes.HANDLE, | |
COORD, | |
] | |
_SetConsoleCursorPosition.restype = wintypes.BOOL | |
_FillConsoleOutputCharacterA = windll.kernel32.FillConsoleOutputCharacterA | |
_FillConsoleOutputCharacterA.argtypes = [ | |
wintypes.HANDLE, | |
c_char, | |
wintypes.DWORD, | |
COORD, | |
POINTER(wintypes.DWORD), | |
] | |
_FillConsoleOutputCharacterA.restype = wintypes.BOOL | |
_FillConsoleOutputAttribute = windll.kernel32.FillConsoleOutputAttribute | |
_FillConsoleOutputAttribute.argtypes = [ | |
wintypes.HANDLE, | |
wintypes.WORD, | |
wintypes.DWORD, | |
COORD, | |
POINTER(wintypes.DWORD), | |
] | |
_FillConsoleOutputAttribute.restype = wintypes.BOOL | |
_SetConsoleTitleW = windll.kernel32.SetConsoleTitleW | |
_SetConsoleTitleW.argtypes = [ | |
wintypes.LPCWSTR | |
] | |
_SetConsoleTitleW.restype = wintypes.BOOL | |
_GetConsoleMode = windll.kernel32.GetConsoleMode | |
_GetConsoleMode.argtypes = [ | |
wintypes.HANDLE, | |
POINTER(wintypes.DWORD) | |
] | |
_GetConsoleMode.restype = wintypes.BOOL | |
_SetConsoleMode = windll.kernel32.SetConsoleMode | |
_SetConsoleMode.argtypes = [ | |
wintypes.HANDLE, | |
wintypes.DWORD | |
] | |
_SetConsoleMode.restype = wintypes.BOOL | |
def _winapi_test(handle): | |
csbi = CONSOLE_SCREEN_BUFFER_INFO() | |
success = _GetConsoleScreenBufferInfo( | |
handle, byref(csbi)) | |
return bool(success) | |
def winapi_test(): | |
return any(_winapi_test(h) for h in | |
(_GetStdHandle(STDOUT), _GetStdHandle(STDERR))) | |
def GetConsoleScreenBufferInfo(stream_id=STDOUT): | |
handle = _GetStdHandle(stream_id) | |
csbi = CONSOLE_SCREEN_BUFFER_INFO() | |
success = _GetConsoleScreenBufferInfo( | |
handle, byref(csbi)) | |
return csbi | |
def SetConsoleTextAttribute(stream_id, attrs): | |
handle = _GetStdHandle(stream_id) | |
return _SetConsoleTextAttribute(handle, attrs) | |
def SetConsoleCursorPosition(stream_id, position, adjust=True): | |
position = COORD(*position) | |
# If the position is out of range, do nothing. | |
if position.Y <= 0 or position.X <= 0: | |
return | |
# Adjust for Windows' SetConsoleCursorPosition: | |
# 1. being 0-based, while ANSI is 1-based. | |
# 2. expecting (x,y), while ANSI uses (y,x). | |
adjusted_position = COORD(position.Y - 1, position.X - 1) | |
if adjust: | |
# Adjust for viewport's scroll position | |
sr = GetConsoleScreenBufferInfo(STDOUT).srWindow | |
adjusted_position.Y += sr.Top | |
adjusted_position.X += sr.Left | |
# Resume normal processing | |
handle = _GetStdHandle(stream_id) | |
return _SetConsoleCursorPosition(handle, adjusted_position) | |
def FillConsoleOutputCharacter(stream_id, char, length, start): | |
handle = _GetStdHandle(stream_id) | |
char = c_char(char.encode()) | |
length = wintypes.DWORD(length) | |
num_written = wintypes.DWORD(0) | |
# Note that this is hard-coded for ANSI (vs wide) bytes. | |
success = _FillConsoleOutputCharacterA( | |
handle, char, length, start, byref(num_written)) | |
return num_written.value | |
def FillConsoleOutputAttribute(stream_id, attr, length, start): | |
''' FillConsoleOutputAttribute( hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten )''' | |
handle = _GetStdHandle(stream_id) | |
attribute = wintypes.WORD(attr) | |
length = wintypes.DWORD(length) | |
num_written = wintypes.DWORD(0) | |
# Note that this is hard-coded for ANSI (vs wide) bytes. | |
return _FillConsoleOutputAttribute( | |
handle, attribute, length, start, byref(num_written)) | |
def SetConsoleTitle(title): | |
return _SetConsoleTitleW(title) | |
def GetConsoleMode(handle): | |
mode = wintypes.DWORD() | |
success = _GetConsoleMode(handle, byref(mode)) | |
if not success: | |
raise ctypes.WinError() | |
return mode.value | |
def SetConsoleMode(handle, mode): | |
success = _SetConsoleMode(handle, mode) | |
if not success: | |
raise ctypes.WinError() | |