# Source code for colorama.win32

    # Copyright Jonathan Hartley 2013. BSD 3-Clause license, see LICENSE file.

    # from winbase.h
    STDOUT = -11
    STDERR = -12

    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

        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)