color: add win32 support for non-black background

This complicates the code a bit, since attributes need to be masked together
correctly before they are applied. Perhaps the code should be redesigned at
some point, but this works well for now.
This commit is contained in:
Sune Foldager 2010-09-13 16:12:25 +02:00
parent 1833e73f70
commit cd1204adbe

View File

@ -221,7 +221,7 @@ try:
# http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
w32effects = {
'none': 0,
'none': -1,
'black': 0,
'red': FOREGROUND_RED,
'green': FOREGROUND_GREEN,
@ -231,7 +231,7 @@ try:
'cyan': FOREGROUND_BLUE | FOREGROUND_GREEN,
'white': FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
'bold': FOREGROUND_INTENSITY,
'black_background': 0,
'black_background': 0x100, # unused value > 0x0f
'red_background': BACKGROUND_RED,
'green_background': BACKGROUND_GREEN,
'yellow_background': BACKGROUND_RED | BACKGROUND_GREEN,
@ -244,6 +244,9 @@ try:
'inverse': COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
}
passthrough = set([FOREGROUND_INTENSITY, BACKGROUND_INTENSITY,
COMMON_LVB_UNDERSCORE, COMMON_LVB_REVERSE_VIDEO])
stdout = GetStdHandle(STD_OUTPUT_HANDLE)
try:
origattr = stdout.GetConsoleScreenBufferInfo()['Attributes']
@ -256,13 +259,23 @@ try:
def win32print(text, orig, **opts):
label = opts.get('label', '')
attr = 0
attr = origattr
def mapcolor(val, attr):
if val == -1:
return origattr
elif val in passthrough:
return attr | val
elif val > 0x0f:
return (val & 0x70) | (attr & 0x8f)
else:
return (val & 0x07) | (attr & 0xf8)
# determine console attributes based on labels
for l in label.split():
style = _styles.get(l, '')
for effect in style.split():
attr |= w32effects[effect]
attr = mapcolor(w32effects[effect], attr)
# hack to ensure regexp finds data
if not text.startswith('\033['):
@ -273,9 +286,8 @@ try:
while m:
for sattr in m.group(1).split(';'):
if sattr:
val = int(sattr)
attr = val and attr|val or 0
stdout.SetConsoleTextAttribute(attr or origattr)
attr = mapcolor(int(sattr), attr)
stdout.SetConsoleTextAttribute(attr)
orig(m.group(2), **opts)
m = re.match(ansire, m.group(3))