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.
--- a/hgext/color.py Fri Sep 10 09:30:50 2010 -0500
+++ b/hgext/color.py Mon Sep 13 16:12:25 2010 +0200
@@ -221,7 +221,7 @@
# 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 @@
'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 @@
'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 @@
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 @@
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))