changeset 12277:a7d3147bd4b3 stable

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.
author Sune Foldager <cryo@cyanite.org>
date Mon, 13 Sep 2010 16:12:25 +0200
parents 4481f8a93c7a
children c4c2ba553401 7cf258b2d0cc 0852da25a31b
files hgext/color.py
diffstat 1 files changed, 19 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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))