Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Colors STOPPED showing in Windows 10, latest update. #265

Open
Bob12345 opened this issue Jun 23, 2020 · 16 comments
Open

Colors STOPPED showing in Windows 10, latest update. #265

Bob12345 opened this issue Jun 23, 2020 · 16 comments

Comments

@Bob12345
Copy link

Colors STOPPED showing in Windows 10, latest update. Still work in Ubuntu. Same code.
This is my latest windows update https://support.microsoft.com/en-us/help/4549951/windows-10-update-kb4549951

Thank you!

@nickums
Copy link

nickums commented Jul 2, 2020

on windows10 with python35, As colorama has never worled for me, I installed color.
It's in site-packages but 'import color' refuses to load it.

@jpwroberts
Copy link

jpwroberts commented Jul 4, 2020

64 bit Windows 10 Home (20H2)
OS Build 19042.330

Colour changes still work, but effects like reverse and underline no longer work. Also, strangely, the bold version of colours are used. This code:

import colorama

# Some ANSI escape sequences for colours and effects
BLACK = '\u001b[30m'
RED = '\u001b[31m'
GREEN = '\u001b[32m'
YELLOW = '\u001b[33m'
BLUE = '\u001b[34m'
MAGENTA = '\u001b[35m'
CYAN = '\u001b[36m'
WHITE = '\u001b[37m'
RESET = '\u001b[0m'

BOLD = '\u001b[1m'
UNDERLINE = '\u001b[4m'
REVERSE = '\u001b[7m'


def colour_print(text: str, effect: str) -> None:
    output_string = "{0}{1}{2}".format(effect, text, RESET)
    print(output_string)


colorama.init()
colour_print("Hello, Red", RED)
# test that the colour was reset
print("This should be in the default terminal colour")
colour_print("Hello, Blue", BLUE)
colour_print("Hello, Yellow", YELLOW)
colour_print("Hello, Bold", BOLD)
colour_print("Hello, Underline", UNDERLINE)
colour_print("Hello, Reverse", REVERSE)
colour_print("Hello, Black", BLACK)
colorama.deinit()

produced the first 8 lines of output:
ColoramaIssue_265

The second 8 lines were produced by replacing colorama with

import platform

if platform.system() == "Windows":
    import ctypes
    kernel32 = ctypes.windll.kernel32
    kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

That matches what I'd expect those escape sequences to do.

@nickums
Copy link

nickums commented Jul 4, 2020

ah! so it works fine on the windows console. I was naively expecting it to also work on print() output.

@jpwroberts
Copy link

It works, but not quite fine. The "Hello, Red" colour for example should be produced by 41, not 31. 31 should give the colour in the second set of output. Also reverse and underline don't render.
Unfortunately, I didn't take a screenshot before the Windows update - but I'm sure I would have noticed reverse not working, it's pretty noticeable.

@jpwroberts
Copy link

jpwroberts commented Jul 5, 2020

"but I'm sure I would have noticed reverse not working"
It seems I'm less observant than I thought I was! I found a couple of VMs, and tested the code on a (pre update) version of Windows 10, and on Windows 8.1

ColoramaIssue_265_win10Home

Reverse and underline don't render in either of those operating systems. The correct colours are being used though - 31 for Red produces the normal intensity red. Windows 8.1 gave the same results.

The documentation doesn't list underscore and reverse video as supported escape sequences, but the normal colour sequences (eg ESC [ 31 m for red) shouldn't produce high intensity.

It looks like that happened because the Windows 10 console was using a bright colour for the foreground.

@jpwroberts
Copy link

jpwroberts commented Jul 5, 2020

I've been playing around with colorama, and have got behaviour that I believe is more consistent with Linux. This code:

import colorama
# import platform
#
# if platform.system() == "Windows":
#     import ctypes
#     kernel32 = ctypes.windll.kernel32
#     kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)

# Some ANSI escape sequences for colours and effects
BLACK = '\u001b[30m'
RED = '\u001b[31m'
GREEN = '\u001b[32m'
YELLOW = '\u001b[33m'
BLUE = '\u001b[34m'
MAGENTA = '\u001b[35m'
CYAN = '\u001b[36m'
WHITE = '\u001b[37m'
RESET = '\u001b[0m'

LIGHT_GREEN = '\u001b[92m'

BOLD = '\u001b[1m'
BOLD_OFF = '\u001b[21m'
NORMAL = '\u001b[22m'
UNDERLINE = '\u001b[4m'
UNDERLINE_OFF = '\u001b[24m'
REVERSE = '\u001b[7m'
REVERSE_OFF = '\u001b[27m'


def colour_print(text: str, *effects: str) -> None:
    """
    Print `text` using the ANSI sequences to change colour, etc.

    :param text: The text to print.
    :param effects: The effects we want.  Zero or more of the constants
        defined at the start of this module.
    """
    effect_string = "".join(effects)
    output_string = "{0}{1}{2}".format(effect_string, text, RESET)
    print(output_string)


colorama.init(strip=False)
colour_print("Hello, Red", RED)
colour_print("Hello, Red in bold", RED, BOLD)
# test that the colour was reset
print("This should be in the default terminal colour")
colour_print("Hello, Green", GREEN)
colour_print("Hello, Green reversed", GREEN, REVERSE)
print()
colour_print("Hello, Green bold and underlined", BOLD, UNDERLINE, GREEN)
print()
colour_print("Hello, Yellow", YELLOW)
colour_print("Hello, Yellow bold", YELLOW, BOLD)
colour_print("Hello, green", GREEN)
colour_print("Hello, light green", LIGHT_GREEN)
colour_print("Hello, bold green", GREEN, BOLD)
colour_print("Hello, bold green reversed", GREEN, BOLD, REVERSE)
colour_print("Hello, green reversed", GREEN, REVERSE)
colour_print("Hello, Bold", BOLD)
colour_print("Hello, Underline", UNDERLINE)
colour_print("Hello, Reverse", REVERSE)
colour_print("Hello, Reverse and Underline", REVERSE, UNDERLINE)
colour_print("Hello, Reverse", REVERSE)
colour_print("Hello, Black", BLACK)

print("{}Reversed{}NotReversed".format(REVERSE, REVERSE_OFF))
print("{}bold{}Reversed{}Not Reversed{}underlined{}not bold{}not underlined".format(BOLD, REVERSE, REVERSE_OFF, UNDERLINE, BOLD_OFF, UNDERLINE_OFF))
colorama.deinit()

Produces this output, on a console with a bright foreground and background. It also works fine with normal fore/background.

ColoramaIssue_265_fixes

I also added support for reverse video and underlining (not under Windows 8 though).

Edited to remove silly question. This is my first time contributing to an open-source project.

@Bob12345
Copy link
Author

Bob12345 commented Jul 8, 2020

Even without Colorama, I get the handle but kernel32.GetConsoleMode() returns 0. Latest Windows 10 and all the packages. Similar code in C/C++ renders as it should (https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences)

@jpwroberts
Copy link

What Python code are you running?

@Bob12345
Copy link
Author

Bob12345 commented Jul 9, 2020

What Python code are you running?
this used to work:

from colorama import init, Fore, Back, Style 

if os.name == 'nt':
    init(convert=True)

print (Style.BRIGHT + Fore.YELLOW + Back.BLUE + str("stuff...") + Style.RESET_ALL)

this works in Python Interactive window in Visual Studio 2019 but not in Python Console:

BLACK = '\u001b[30m'
RED = '\u001b[31m'
GREEN = '\u001b[32m'
YELLOW = '\u001b[33m'
BLUE = '\u001b[34m'
MAGENTA = '\u001b[35m'
CYAN = '\u001b[36m'
WHITE = '\u001b[37m'
RESET = '\u001b[0m'

LIGHT_GREEN = '\u001b[92m'

BOLD = '\u001b[1m'
BOLD_OFF = '\u001b[21m'
NORMAL = '\u001b[22m'
UNDERLINE = '\u001b[4m'
UNDERLINE_OFF = '\u001b[24m'
REVERSE = '\u001b[7m'
REVERSE_OFF = '\u001b[27m'

ESC = '\x1b'
CSI = '\x1b['

import platform
import ctypes
from ctypes import byref, POINTER, windll, WINFUNCTYPE
from ctypes.wintypes import BOOL, DWORD, HANDLE, LPWSTR, LPVOID

if platform.system() == "Windows":
    print("Windows")

    kernel32 = ctypes.windll.kernel32
    h = kernel32.GetStdHandle(-11)
    mode = DWORD()
    if not kernel32.GetConsoleMode(h, byref(mode)):
        print("not console mode " + str(kernel32.GetConsoleMode(h, byref(mode))))

    print("console mode: " + str(kernel32.GetConsoleMode()))

    kernel32.SetConsoleMode(h, 7)

    print("console mode: " + str(kernel32.GetConsoleMode()))
#if os.name == 'nt':
#    print("NT")
#    init(convert=True)

print (ESC + GREEN + "TESTESTTEST" + RED + "TEST TEST TEST" +CSI+ "TEST TEST TEST")

@Bob12345
Copy link
Author

Bob12345 commented Jul 9, 2020

Now something like this, works just fine in Windows 10. This is C++ and no Colorama:
(It's a Microsoft Sample, slightly modified)

//

#include "stdafx.h"
//
//    Copyright (C) Microsoft.  All rights reserved.
//
#define DEFINE_CONSOLEV2_PROPERTIES
//#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
//#endif
// System headers
#include <windows.h>

// Standard library C-style
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>

#define ESC "\x1b"
#define CSI "\x1b["

bool EnableVTMode()
{
	// Set output mode to handle virtual terminal sequences
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	if (hOut == INVALID_HANDLE_VALUE)
	{
		return false;
	}

	DWORD dwMode = 0;
	if (!GetConsoleMode(hOut, &dwMode))
	{
		return false;
	}

	dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
	if (!SetConsoleMode(hOut, dwMode))
	{
		return false;
	}
	return true;
}

void PrintVerticalBorder()
{
	printf(ESC "(0");       // Enter Line drawing mode
	printf(CSI "104;93m");   // bright yellow on bright blue
	printf("x");            // in line drawing mode, \x78 -> \u2502 "Vertical Bar"
	printf(CSI "0m");       // restore color
	printf(ESC "(B");       // exit line drawing mode
}

void PrintHorizontalBorder(COORD const Size, bool fIsTop)
{
	printf(ESC "(0");       // Enter Line drawing mode
	printf(CSI "104;93m");  // Make the border bright yellow on bright blue
	printf(fIsTop ? "l" : "m"); // print left corner 

	for (int i = 1; i < Size.X - 1; i++)
		printf("q"); // in line drawing mode, \x71 -> \u2500 "HORIZONTAL SCAN LINE-5"

	printf(fIsTop ? "k" : "j"); // print right corner
	printf(CSI "0m");
	printf(ESC "(B");       // exit line drawing mode
}

void PrintStatusLine(char* const pszMessage, COORD const Size)
{
	printf(CSI "%d;1H", Size.Y);
	printf(CSI "K"); // clear the line
	printf(pszMessage);
}

int __cdecl wmain(int argc, WCHAR* argv[])
{
	argc; // unused
	argv; // unused
		  //First, enable VT mode
	bool fSuccess = EnableVTMode();
	if (!fSuccess)
	{
		printf("Unable to enter VT processing mode. Quitting.\n");
		return -1;
	}
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	if (hOut == INVALID_HANDLE_VALUE)
	{
		printf("Couldn't get the console handle. Quitting.\n");
		return -1;
	}

	CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
	GetConsoleScreenBufferInfo(hOut, &ScreenBufferInfo);
	COORD Size;
	Size.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1;
	Size.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1;

	// Enter the alternate buffer
	printf(CSI "?1049h");

	// Clear screen, tab stops, set, stop at columns 16, 32
	printf(CSI "1;1H");
	printf(CSI "2J"); // Clear screen

	int iNumTabStops = 4; // (0, 20, 40, width)
	printf(CSI "3g"); // clear all tab stops
	printf(CSI "1;20H"); // Move to column 20
	printf(ESC "H"); // set a tab stop

	printf(CSI "1;40H"); // Move to column 40
	printf(ESC "H"); // set a tab stop

					 // Set scrolling margins to 3, h-2
	printf(CSI "3;%dr", Size.Y - 2);
	int iNumLines = Size.Y - 4;

	printf(CSI "1;1H");
	printf(CSI "102;30m");
	printf("Windows 10 Anniversary Update - VT Example");
	printf(CSI "0m");

	// Print a top border - Yellow
	printf(CSI "2;1H");
	PrintHorizontalBorder(Size, true);

	// // Print a bottom border
	printf(CSI "%d;1H", Size.Y - 1);
	PrintHorizontalBorder(Size, false);

	wchar_t wch;

	// draw columns
	printf(CSI "3;1H");
	int line = 0;
	for (line = 0; line < iNumLines * iNumTabStops; line++)
	{
		PrintVerticalBorder();
		if (line + 1 != iNumLines * iNumTabStops) // don't advance to next line if this is the last line
			printf("\t"); // advance to next tab stop

	}

	PrintStatusLine("Press any key to see text printed between tab stops.", Size);
	wch = _getwch();

	// Fill columns with output
	printf(CSI "3;1H");
	for (line = 0; line < iNumLines; line++)
	{
		int tab = 0;
		for (tab = 0; tab < iNumTabStops - 1; tab++)
		{
			PrintVerticalBorder();
			printf("line=%d", line);
			printf("\t"); // advance to next tab stop
		}
		PrintVerticalBorder();// print border at right side
		if (line + 1 != iNumLines)
			printf("\t"); // advance to next tab stop, (on the next line)
	}

	PrintStatusLine("Press any key to demonstrate scroll margins", Size);
	wch = _getwch();

	printf(CSI "3;1H");
	for (line = 0; line < iNumLines * 2; line++)
	{
		printf(CSI "K"); // clear the line
		int tab = 0;
		for (tab = 0; tab < iNumTabStops - 1; tab++)
		{
			PrintVerticalBorder();
			printf("line=%d", line);
			printf("\t"); // advance to next tab stop
		}
		PrintVerticalBorder(); // print border at right side
		if (line + 1 != iNumLines * 2)
		{
			printf("\n"); //Advance to next line. If we're at the bottom of the margins, the text will scroll.
			printf("\r"); //return to first col in buffer
		}
	}

	PrintStatusLine("Press any key to exit", Size);
	wch = _getwch();

	// Exit the alternate buffer
	printf(CSI "?1049l");

}```

@Bob12345
Copy link
Author

Bob12345 commented Jul 9, 2020

I may have figured it out (Maybe). I have Python 2.7, 3.4, 3.6 on my Windows10 machine.

@jpwroberts
Copy link

Just in case it's causing confusion, in my comment that "I've been playing around with colorama" from 9 days ago, I meant that I'd been modifying the colorama source code. The current version of colorama doesn't produce reverse video and underlining on Windows.
Check out Pull Request 267

@Xyndra
Copy link

Xyndra commented Oct 14, 2020

The solution only needs one line of code:
init(convert=True)

@jpwroberts
Copy link

Hi, Xyndra
I've tested passing convert=True and didn't get reverse video or underlining on Windows 10. Colours also appeared bright if the default terminal text colour is bright.

@Xyndra
Copy link

Xyndra commented Oct 14, 2020

Yeah, but I think that´s the most you can get in cmd.😔

@jpwroberts
Copy link

If my PR makes it into the next release, you'll be able to get the effects in the screenshot above (my last post on 5th July).
Please don't make any important decisions based on that, though. If they find a bug in my code, it probably won't make it into the next release. There's also no date for another release; these are strange times and the project maintainers are very busy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants