qemacs-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemacs-commit] qemacs tests/TestPage.ucs2le.txt buffer.c clang...


From: Charlie Gordon
Subject: [Qemacs-commit] qemacs tests/TestPage.ucs2le.txt buffer.c clang...
Date: Mon, 3 Apr 2017 04:33:58 -0400 (EDT)

CVSROOT:        /sources/qemacs
Module name:    qemacs
Changes by:     Charlie Gordon <chqrlie>        17/04/03 04:33:57

Modified files:
        tests          : TestPage.ucs2le.txt 
        .              : buffer.c clang.c extras.c list.c makemode.c 
                         qe.c qe.h search.c shell.c tty.c util.c 
                         TODO.org 
Added files:
        tests          : 16colors.pl 256colors2.pl color-spaces.pl 
                         truecolors.sh xterm-colortest.sh 
                         xterm-colour-chart.py 

Log message:
        display: full support for 256 color virtual terminal
        - add various utilities for color escape sequence testing:
          tests/16colors.pl
          tests/256colors2.pl
          tests/color-spaces.pl
          tests/truecolors.sh
          tests/xterm-colortest.sh
          tests/xterm-colour-chart.py
        - use colored code-points only for syntax highlighting
        - use QETermStyle and QEStyleDef internally
        - convert to TTYChar attributes only for text terminal output.
        - remove most CHAR_MASK and STYLE_SHIFT handling
        - pass QETermStyle array to get_colorized_line mode handlers
        - pass QETermStyle array to isearch_colorize_matches
        - remove combine_static_colorized_line
        - move color matching functions to util.c
        - rename get_tty_color as qe_map_color
        - improve local variable naming consistency: 
          DisplayState *ds, QEStyleDef *stp, QEStyleDef styledef.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/TestPage.ucs2le.txt?cvsroot=qemacs&rev=1.2
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/16colors.pl?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/256colors2.pl?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/color-spaces.pl?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/truecolors.sh?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/xterm-colortest.sh?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/tests/xterm-colour-chart.py?cvsroot=qemacs&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/qemacs/buffer.c?cvsroot=qemacs&r1=1.108&r2=1.109
http://cvs.savannah.gnu.org/viewcvs/qemacs/clang.c?cvsroot=qemacs&r1=1.121&r2=1.122
http://cvs.savannah.gnu.org/viewcvs/qemacs/extras.c?cvsroot=qemacs&r1=1.65&r2=1.66
http://cvs.savannah.gnu.org/viewcvs/qemacs/list.c?cvsroot=qemacs&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/qemacs/makemode.c?cvsroot=qemacs&r1=1.27&r2=1.28
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.c?cvsroot=qemacs&r1=1.260&r2=1.261
http://cvs.savannah.gnu.org/viewcvs/qemacs/qe.h?cvsroot=qemacs&r1=1.245&r2=1.246
http://cvs.savannah.gnu.org/viewcvs/qemacs/search.c?cvsroot=qemacs&r1=1.12&r2=1.13
http://cvs.savannah.gnu.org/viewcvs/qemacs/shell.c?cvsroot=qemacs&r1=1.121&r2=1.122
http://cvs.savannah.gnu.org/viewcvs/qemacs/tty.c?cvsroot=qemacs&r1=1.75&r2=1.76
http://cvs.savannah.gnu.org/viewcvs/qemacs/util.c?cvsroot=qemacs&r1=1.77&r2=1.78
http://cvs.savannah.gnu.org/viewcvs/qemacs/TODO.org?cvsroot=qemacs&r1=1.32&r2=1.33

Patches:
Index: tests/TestPage.ucs2le.txt
===================================================================
RCS file: /sources/qemacs/qemacs/tests/TestPage.ucs2le.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
Binary files /var/tmp/cvseK7Df6 and /var/tmp/cvsoYHnki differ

Index: buffer.c
===================================================================
RCS file: /sources/qemacs/qemacs/buffer.c,v
retrieving revision 1.108
retrieving revision 1.109
diff -u -b -r1.108 -r1.109
--- buffer.c    31 Mar 2017 07:51:56 -0000      1.108
+++ buffer.c    3 Apr 2017 08:33:57 -0000       1.109
@@ -2393,7 +2393,7 @@
                 break;
             }
             c = eb_nextc(b, offset, &offset);
-            buf[len++] = c & CHAR_MASK;
+            buf[len++] = c;
             if (c == '\n') {
                 /* add null terminator but return offset of newline */
                 buf[len--] = '\0';

Index: clang.c
===================================================================
RCS file: /sources/qemacs/qemacs/clang.c,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -b -r1.121 -r1.122
--- clang.c     2 Apr 2017 01:12:01 -0000       1.121
+++ clang.c     3 Apr 2017 08:33:57 -0000       1.122
@@ -111,7 +111,7 @@
     int i, j;
 
     i = j = 0;
-    c = p[i] & CHAR_MASK;
+    c = p[i];
     if (qe_isalpha_(c)
     ||  c == '$'
     ||  (c == '@' && flavor != CLANG_PIKE)
@@ -120,22 +120,22 @@
             if (j < buf_size - 1)
                 buf[j++] = (c < 0xFF) ? c : 0xFF;
             i++;
-            c = p[i] & CHAR_MASK;
+            c = p[i];
             if (c == '-' && flavor == CLANG_CSS)
                 continue;
             if (qe_isalnum_(c))
                 continue;
             if (flavor == CLANG_RUST && c >= 128)
                 continue;
-            if (c == ':' && (p[i + 1] & CHAR_MASK) == ':'
+            if (c == ':' && p[i + 1] == ':'
             &&  flavor == CLANG_CPP
-            &&  qe_isalpha_(p[i + 2] & CHAR_MASK)) {
+            &&  qe_isalpha_(p[i + 2])) {
                 if (j < buf_size - 2) {
                     buf[j++] = c;
                     buf[j++] = c;
                 }
                 i += 2;
-                c = p[i] & CHAR_MASK;
+                c = p[i];
                 continue;
             }
             break;
@@ -664,7 +664,7 @@
     p = buf;
     pos = 0;
     for (;;) {
-        c = *p++ & CHAR_MASK;
+        c = *p++;
         if (c == '\t')
             pos += tw - (pos % tw);
         else if (c == ' ')
@@ -682,7 +682,7 @@
     tw = s->b->tab_width > 0 ? s->b->tab_width : 8;
     pos = 0;
     for (i = 0; i < size; i++) {
-        c = buf[i] & CHAR_MASK;
+        c = buf[i];
         if (c == '\t') {
             pos += tw - (pos % tw);
         } else {
@@ -762,6 +762,7 @@
     int offset, offset1, offsetl, c, pos, line_num, col_num;
     int i, j, eoi_found, len, pos1, lpos, style, line_num1, state;
     unsigned int buf[COLORED_MAX_LINE_SIZE], *p;
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
     unsigned char stack[MAX_STACK_SIZE];
     char buf1[64], *q;
     int stack_ptr;
@@ -784,7 +785,7 @@
         offsetl = eb_prev_line(s->b, offsetl);
         /* XXX: deal with truncation */
         /* XXX: should only query the syntax colorizer */
-        len = s->get_colorized_line(s, buf, countof(buf),
+        len = s->get_colorized_line(s, buf, countof(buf), sbuf,
                                     offsetl, &offset1, line_num);
         /* store indent position */
         pos1 = find_indent1(s, buf);
@@ -792,14 +793,13 @@
         while (p > buf) {
             p--;
             c = *p;
+            style = sbuf[p - buf];
             /* skip strings or comments */
-            style = (unsigned int)c >> STYLE_SHIFT;
             if (style == C_STYLE_COMMENT
             ||  style == C_STYLE_STRING
             ||  style == C_STYLE_PREPROCESS) {
                 continue;
             }
-            c = c & CHAR_MASK;
             if (state == INDENT_FIND_EQ) {
                 /* special case to search '=' or ; before { to know if
                    we are in data definition */
@@ -878,7 +878,7 @@
                      * are assumed to have no preceding space
                      */
                     if (style == C_STYLE_DEFAULT
-                    &&  (p == buf || !qe_isspace(p[-1] & CHAR_MASK)))
+                    &&  (p == buf || !qe_isspace(p[-1])))
                         goto prev_line;
                     break;
                 default:
@@ -887,13 +887,12 @@
                             unsigned int *p1, *p2;
                             /* special case for if/for/while */
                             p1 = p;
-                            while (p > buf &&
-                                   (p[-1] >> STYLE_SHIFT) == C_STYLE_KEYWORD)
+                            while (p > buf && sbuf[p - buf - 1] == 
C_STYLE_KEYWORD)
                                 p--;
                             p2 = p;
                             q = buf1;
                             while (q < buf1 + countof(buf1) - 1 && p2 <= p1) {
-                                *q++ = *p2++ & CHAR_MASK;
+                                *q++ = *p2++;
                             }
                             *q = '\0';
 
@@ -915,7 +914,7 @@
     /* compute special cases which depend on the chars on the current line */
     /* XXX: deal with truncation */
     /* XXX: should only query the syntax colorizer */
-    len = s->get_colorized_line(s, buf, countof(buf),
+    len = s->get_colorized_line(s, buf, countof(buf), sbuf,
                                 offset, &offset1, line_num1);
 
     if (stack_ptr == 0) {
@@ -929,22 +928,22 @@
 
     for (i = 0; i < len; i++) {
         c = buf[i];
-        style = (unsigned int)c >> STYLE_SHIFT;
-        if (qe_isblank(c & CHAR_MASK))
+        style = sbuf[i];
+        if (qe_isblank(c))
             continue;
         /* if preprocess, no indent */
         if (style == C_STYLE_PREPROCESS) {
             pos = 0;
             break;
         }
-        if (qe_isalpha_(c & CHAR_MASK)) {
+        if (qe_isalpha_(c)) {
             j = get_c_identifier(buf1, countof(buf1), buf + i, CLANG_C);
 
             if (style == C_STYLE_KEYWORD) {
                 if (strfind("case|default", buf1))
                     goto unindent;
             }
-            for (j += i; qe_isblank(buf[j] & CHAR_MASK); j++)
+            for (j += i; qe_isblank(buf[j]); j++)
                 continue;
             if (buf[j] == ':')
                 goto unindent;
@@ -982,10 +981,10 @@
 #if 0
     if (s->mode->auto_indent > 1) {  /* auto format */
         /* recompute colorization of the current line (after re-indentation) */
-        len = s->get_colorized_line(s, buf, countof(buf),
+        len = s->get_colorized_line(s, buf, countof(buf), sbuf,
                                     offset, &offset1, line_num1);
         /* skip indentation */
-        for (pos = 0; qe_isblank(buf[pos] & CHAR_MASK); pos++)
+        for (pos = 0; qe_isblank(buf[pos]); pos++)
             continue;
         /* XXX: keywords "if|for|while|switch -> one space before `(` */
         /* XXX: keyword "return" -> one space before expression */
@@ -1054,19 +1053,11 @@
     }
 }
 
-static int ustr_match_mask(const unsigned int *buf, const char *str)
-{
-    while (*str) {
-        if ((*buf++ & CHAR_MASK) != *str++)
-            return 0;
-    }
-    return 1;
-}
-
 /* forward / backward preprocessor */
 static void do_c_forward_conditional(EditState *s, int dir)
 {
     unsigned int buf[COLORED_MAX_LINE_SIZE], *p;
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
     int line_num, col_num, sharp, level;
     int offset, offset0, offset1;
 
@@ -1075,11 +1066,12 @@
     level = 0;
     for (;;) {
         /* XXX: should only query the syntax colorizer */
-        s->get_colorized_line(s, buf, countof(buf), offset, &offset1, 
line_num);
+        s->get_colorized_line(s, buf, countof(buf), sbuf,
+                              offset, &offset1, line_num);
         sharp = 0;
         for (p = buf; *p; p++) {
-            int c = (*p & CHAR_MASK);
-            int style = (*p >> STYLE_SHIFT);
+            int c = *p;
+            int style = sbuf[p - buf];
             if (qe_isblank(c))
                 continue;
             if (c == '#' && style == C_STYLE_PREPROCESS)
@@ -1088,20 +1080,20 @@
                 break;
         }
         if (sharp == 1) {
-            if (ustr_match_mask(p, dir < 0 ? "endif" : "if")) {
+            if (ustrstart(p, dir < 0 ? "endif" : "if", NULL)) {
                 if (level || offset == offset0)
                     level++;
                 else
                     break;
             } else
-            if (ustr_match_mask(p, "el")) {
+            if (ustrstart(p, "el", NULL)) {
                 if (offset == offset0)
                     level++;
                 else
                 if (level <= 1)
                     break;
             } else
-            if (ustr_match_mask(p, dir > 0 ? "endif" : "if")) {
+            if (ustrstart(p, dir > 0 ? "endif" : "if", NULL)) {
                 if (level)
                     level--;
                 if (!level && offset != offset0)
@@ -1126,6 +1118,7 @@
 static void do_c_list_conditionals(EditState *s)
 {
     unsigned int buf[COLORED_MAX_LINE_SIZE], *p;
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
     int line_num, col_num, sharp, level;
     int offset, offset1;
     EditBuffer *b;
@@ -1141,11 +1134,12 @@
         line_num--;
         offset = eb_prev_line(s->b, offset);
         /* XXX: should only query the syntax colorizer */
-        s->get_colorized_line(s, buf, countof(buf), offset, &offset1, 
line_num);
+        s->get_colorized_line(s, buf, countof(buf), sbuf,
+                              offset, &offset1, line_num);
         sharp = 0;
         for (p = buf; *p; p++) {
-            int c = (*p & CHAR_MASK);
-            int style = (*p >> STYLE_SHIFT);
+            int c = *p;
+            int style = sbuf[p - buf];
             if (qe_isblank(c))
                 continue;
             if (c == '#' && style == C_STYLE_PREPROCESS)
@@ -1154,15 +1148,15 @@
                 break;
         }
         if (sharp == 1) {
-            if (ustr_match_mask(p, "endif")) {
+            if (ustrstart(p, "endif", NULL)) {
                 level++;
             } else
-            if (ustr_match_mask(p, "el")) {
+            if (ustrstart(p, "el", NULL)) {
                 if (level == 0) {
                     eb_insert_buffer_convert(b, 0, s->b, offset, offset1 - 
offset);
                 }
             } else
-            if (ustr_match_mask(p, "if")) {
+            if (ustrstart(p, "if", NULL)) {
                 if (level) {
                     level--;
                 } else {

Index: extras.c
===================================================================
RCS file: /sources/qemacs/qemacs/extras.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -b -r1.65 -r1.66
--- extras.c    2 Apr 2017 01:12:01 -0000       1.65
+++ extras.c    3 Apr 2017 08:33:57 -0000       1.66
@@ -27,6 +27,7 @@
 static int qe_skip_comments(EditState *s, int offset, int *offsetp)
 {
     unsigned int buf[COLORED_MAX_LINE_SIZE];
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
     int line_num, col_num, len, pos;
     int offset0, offset1;
 
@@ -36,14 +37,15 @@
     eb_get_pos(s->b, &line_num, &col_num, offset);
     offset0 = eb_goto_bol2(s->b, offset, &pos);
     /* XXX: should only query the syntax colorizer */
-    len = s->get_colorized_line(s, buf, countof(buf), offset0, &offset1, 
line_num);
+    len = s->get_colorized_line(s, buf, countof(buf), sbuf,
+                                offset0, &offset1, line_num);
     if (len > countof(buf))
         len = countof(buf);
     if (pos >= len)
         return 0;
-    if ((buf[pos] >> STYLE_SHIFT) != QE_STYLE_COMMENT)
+    if (sbuf[pos] != QE_STYLE_COMMENT)
         return 0;
-    while (pos < len && (buf[pos] >> STYLE_SHIFT) == QE_STYLE_COMMENT) {
+    while (pos < len && sbuf[pos] == QE_STYLE_COMMENT) {
         offset = eb_next(s->b, offset);
         pos++;
     }
@@ -81,13 +83,17 @@
     while (qe_isblank(ch2 = eb_nextc(s2->b, pos2 = off2, &off2)))
         continue;
     if (ch1 != ch2) {
-        /* try skipping current words */
+        /* try skipping current words and subsequent blanks */
         off1 = pos1;
         off2 = pos2;
         while (!qe_isspace(ch1 = eb_nextc(s1->b, pos1 = off1, &off1)))
             continue;
         while (!qe_isspace(ch2 = eb_nextc(s2->b, pos2 = off2, &off2)))
             continue;
+        while (qe_isblank(ch1 = eb_nextc(s1->b, pos1 = off1, &off1)))
+            continue;
+        while (qe_isblank(ch2 = eb_nextc(s2->b, pos2 = off2, &off2)))
+            continue;
         if (ch1 != ch2) {
             /* Try to resync from end of line */
             pos1 = eb_goto_eol(s1->b, save1);
@@ -505,6 +511,7 @@
 static void do_forward_block(EditState *s, int dir)
 {
     unsigned int buf[COLORED_MAX_LINE_SIZE];
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
     char balance[MAX_LEVEL];
     int use_colors;
     int line_num, col_num, style, style0, c, level;
@@ -522,14 +529,15 @@
     len = 0;
     if (use_colors) {
         /* XXX: should only query the syntax colorizer */
-        len = s->get_colorized_line(s, buf, countof(buf), offset1, &offset1, 
line_num);
+        len = s->get_colorized_line(s, buf, countof(buf), sbuf,
+                                    offset1, &offset1, line_num);
         if (len < countof(buf) - 2) {
             if (pos > 0
-            &&  ((c = buf[pos - 1] & CHAR_MASK) == ']' || c == '}' || c == 
')')) {
-                style0 = buf[pos - 1] >> STYLE_SHIFT;
+            &&  ((c = buf[pos - 1]) == ']' || c == '}' || c == ')')) {
+                style0 = sbuf[pos - 1];
             } else
             if (pos < len) {
-                style0 = buf[pos] >> STYLE_SHIFT;
+                style0 = sbuf[pos];
             }
         } else {
             /* very long line detected, use fallback version */
@@ -550,7 +558,8 @@
                 len = 0;
                 if (use_colors) {
                     /* XXX: should only query the syntax colorizer */
-                    len = s->get_colorized_line(s, buf, countof(buf), offset1, 
&offset1, line_num);
+                    len = s->get_colorized_line(s, buf, countof(buf), sbuf,
+                                                offset1, &offset1, line_num);
                     if (len >= countof(buf) - 2) {
                         /* very long line detected, use fallback version */
                         use_colors = 0;
@@ -563,7 +572,7 @@
             style = 0;
             --pos;
             if (pos >= 0 && pos < len) {
-                style = buf[pos] >> STYLE_SHIFT;
+                style = sbuf[pos];
             }
             if (style != style0 && style != QE_STYLE_KEYWORD && style != 
QE_STYLE_FUNCTION) {
                 if (style0 == 0)
@@ -626,7 +635,8 @@
                 len = 0;
                 if (use_colors) {
                     /* XXX: should only query the syntax colorizer */
-                    len = s->get_colorized_line(s, buf, countof(buf), offset1, 
&offset1, line_num);
+                    len = s->get_colorized_line(s, buf, countof(buf), sbuf,
+                                                offset1, &offset1, line_num);
                     if (len >= countof(buf) - 2) {
                         /* very long line detected, use fallback version */
                         use_colors = 0;
@@ -639,7 +649,7 @@
             }
             style = 0;
             if (pos < len) {
-                style = buf[pos] >> STYLE_SHIFT;
+                style = sbuf[pos];
             }
             pos++;
             if (style0 != style && style != QE_STYLE_KEYWORD && style != 
QE_STYLE_FUNCTION) {
@@ -1086,7 +1096,7 @@
     return len;
 }
 
-int get_tty_style(const char *str)
+static int qe_term_get_style(const char *str)
 {
     char buf[128];
     QEColor fg_color, bg_color;
@@ -1123,8 +1133,8 @@
                 return -1;
         }
     }
-    fg = get_tty_color(fg_color, xterm_colors, QE_TERM_FG_COLORS);
-    bg = get_tty_color(bg_color, xterm_colors, QE_TERM_BG_COLORS);
+    fg = qe_map_color(fg_color, xterm_colors, QE_TERM_FG_COLORS, NULL);
+    bg = qe_map_color(bg_color, xterm_colors, QE_TERM_BG_COLORS, NULL);
 
     return QE_TERM_COMPOSITE | style | QE_TERM_MAKE_COLOR(fg, bg);
 }
@@ -1136,7 +1146,7 @@
     /* deactivate region hilite */
     s->region_style = 0;
 
-    style = get_tty_style(str);
+    style = qe_term_get_style(str);
     if (style < 0) {
         put_status(s, "Invalid color '%s'", str);
         return;
@@ -1602,12 +1612,15 @@
 
 static void tag_buffer(EditState *s) {
     unsigned int buf[100];
+    QETermStyle sbuf[100];
     int offset, line_num, col_num;
 
+    if (s->colorize_func || s->b->b_styles) {
     /* force complete buffer colorizarion */
     eb_get_pos(s->b, &line_num, &col_num, s->b->total_size);
-    s->get_colorized_line(s, buf, countof(buf), s->b->total_size,
-                          &offset, line_num);
+        s->get_colorized_line(s, buf, countof(buf), sbuf,
+                              s->b->total_size, &offset, line_num);
+    }
 }
 
 static void tag_completion(CompleteState *cp) {

Index: list.c
===================================================================
RCS file: /sources/qemacs/qemacs/list.c,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- list.c      25 Mar 2017 18:15:00 -0000      1.22
+++ list.c      3 Apr 2017 08:33:57 -0000       1.23
@@ -25,28 +25,32 @@
 
 static int list_get_colorized_line(EditState *s,
                                    unsigned int *buf, int buf_size,
-                                   int offset, int *offsetp, 
-                                   qe__unused__ int line_num)
+                                   QETermStyle *sbuf,
+                                   int offset, int *offsetp, int line_num)
 {
     QEmacsState *qs = s->qe_state;
-    int len;
+    int i, len;
 
     /* Get line contents including static buffer styles */
     /* XXX: deal with truncation */
     /* XXX: should just use s->cur_line style */
-    len = generic_get_colorized_line(s, buf, buf_size, offset, offsetp, 
line_num);
+    len = generic_get_colorized_line(s, buf, buf_size, sbuf,
+                                     offset, offsetp, line_num);
 
     if (((qs->active_window == s) || s->force_highlight) &&
           s->offset >= offset && s->offset < *offsetp)
     {
         /* highlight the line if the cursor is inside */
-        clear_color(buf, len);
-        SET_COLOR(buf, 0, len, QE_STYLE_HIGHLIGHT);
+        for (i = 0; i <= len; i++) {
+            sbuf[i] = QE_STYLE_HIGHLIGHT;
+        }
     } else
     if (buf[0] == '*') {
         /* selection */
-        clear_color(buf, len);
-        SET_COLOR(buf, 0, len, QE_STYLE_SELECTION);
+        /* XXX: use QE_STYLE_SEL ? */
+        for (i = 0; i <= len; i++) {
+            sbuf[i] = QE_STYLE_SELECTION;
+        }
     }
     return len;
 }

Index: makemode.c
===================================================================
RCS file: /sources/qemacs/qemacs/makemode.c,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -b -r1.27 -r1.28
--- makemode.c  25 Mar 2017 18:15:01 -0000      1.27
+++ makemode.c  3 Apr 2017 08:33:57 -0000       1.28
@@ -31,13 +31,13 @@
     int i, j;
 
     i = j = 0;
-    c = p[i] & CHAR_MASK;
+    c = p[i];
     if (qe_isalpha_(c)) {
         do {
             if (j < buf_size - 1)
                 buf[j++] = qe_tolower(c);
             i++;
-            c = p[i] & CHAR_MASK;
+            c = p[i];
         } while (qe_isalnum_(c));
     }
     buf[j] = '\0';

Index: qe.c
===================================================================
RCS file: /sources/qemacs/qemacs/qe.c,v
retrieving revision 1.260
retrieving revision 1.261
diff -u -b -r1.260 -r1.261
--- qe.c        2 Apr 2017 01:12:01 -0000       1.260
+++ qe.c        3 Apr 2017 08:33:57 -0000       1.261
@@ -51,7 +51,7 @@
 
 void print_at_byte(QEditScreen *screen,
                    int x, int y, int width, int height,
-                   const char *str, int style_index);
+                   const char *str, int style);
 static EditBuffer *predict_switch_to_buffer(EditState *s);
 static StringArray *get_history(const char *name);
 static void qe_key_process(int key);
@@ -60,7 +60,7 @@
 static int generic_mode_init(EditState *s);
 static void generic_mode_close(EditState *s);
 static void generic_text_display(EditState *s);
-static void display1(DisplayState *s);
+static void display1(DisplayState *ds);
 #ifndef CONFIG_TINY
 static void save_selection(void);
 #endif
@@ -2754,72 +2754,74 @@
 /* Should move all this to display.c */
 
 /* compute style */
-static void apply_style(QEStyleDef *style, int style_index)
+static void apply_style(QEStyleDef *stp, int style)
 {
     QEStyleDef *s;
 
-    if (style_index & QE_TERM_COMPOSITE) {
-        style->fg_color = xterm_colors[QE_TERM_GET_FG(style_index)];
-        style->bg_color = xterm_colors[QE_TERM_GET_BG(style_index)];
-        if (style_index & QE_TERM_UNDERLINE)
-            style->font_style |= QE_STYLE_UNDERLINE;
-        if (style_index & QE_TERM_BOLD)
-            style->font_style |= QE_STYLE_BOLD;
-        if (style_index & QE_TERM_BLINK)
-            style->font_style |= QE_STYLE_BLINK;
+    if (style & QE_TERM_COMPOSITE) {
+        stp->fg_color = xterm_colors[QE_TERM_GET_FG(style)];
+        stp->bg_color = xterm_colors[QE_TERM_GET_BG(style)];
+        if (style & QE_TERM_UNDERLINE)
+            stp->font_style |= QE_STYLE_UNDERLINE;
+        if (style & QE_TERM_BOLD)
+            stp->font_style |= QE_STYLE_BOLD;
+        if (style & QE_TERM_ITALIC)
+            stp->font_style |= QE_STYLE_ITALIC;
+        if (style & QE_TERM_BLINK)
+            stp->font_style |= QE_STYLE_BLINK;
     } else {
-        s = &qe_styles[style_index & QE_STYLE_NUM];
+        s = &qe_styles[style & QE_STYLE_NUM];
         if (s->fg_color != COLOR_TRANSPARENT)
-            style->fg_color = s->fg_color;
+            stp->fg_color = s->fg_color;
         if (s->bg_color != COLOR_TRANSPARENT)
-            style->bg_color = s->bg_color;
+            stp->bg_color = s->bg_color;
         if (s->font_style != 0)
-            style->font_style = s->font_style;
+            stp->font_style = s->font_style;
         if (s->font_size != 0)
-            style->font_size = s->font_size;
+            stp->font_size = s->font_size;
     }
     /* for selection, we need a special handling because only color is
            changed */
-    if (style_index & QE_STYLE_SEL) {
+    if (style & QE_STYLE_SEL) {
         s = &qe_styles[QE_STYLE_SELECTION];
-        style->fg_color = s->fg_color;
-        style->bg_color = s->bg_color;
+        stp->fg_color = s->fg_color;
+        stp->bg_color = s->bg_color;
     }
 }
 
-void get_style(EditState *e, QEStyleDef *style, int style_index)
+void get_style(EditState *e, QEStyleDef *stp, int style)
 {
     /* get root default style */
-    *style = qe_styles[0];
+    *stp = qe_styles[0];
 
     /* apply window default style */
     if (e && e->default_style != 0)
-        apply_style(style, e->default_style);
+        apply_style(stp, e->default_style);
 
     /* apply specific style */
-    if (style_index != 0)
-        apply_style(style, style_index);
+    if (style != 0)
+        apply_style(stp, style);
 }
 
 void style_completion(CompleteState *cp)
 {
     int i;
-    QEStyleDef *style;
+    QEStyleDef *stp;
 
-    style = qe_styles;
-    for (i = 0; i < QE_STYLE_NB; i++, style++) {
-        complete_test(cp, style->name);
+    stp = qe_styles;
+    for (i = 0; i < QE_STYLE_NB; i++, stp++) {
+        complete_test(cp, stp->name);
     }
 }
 
 int find_style_index(const char *name)
 {
     int i;
-    QEStyleDef *style;
+    QEStyleDef *stp;
 
-    style = qe_styles;
-    for (i = 0; i < QE_STYLE_NB; i++, style++) {
-        if (strequal(style->name, name))
+    stp = qe_styles;
+    for (i = 0; i < QE_STYLE_NB; i++, stp++) {
+        if (strequal(stp->name, name))
             return i;
     }
     if (qe_isdigit(*name)) {
@@ -2882,11 +2884,11 @@
 void do_set_style(EditState *e, const char *stylestr,
                   const char *propstr, const char *value)
 {
-    QEStyleDef *style;
+    QEStyleDef *stp;
     int v, prop_index;
 
-    style = find_style(stylestr);
-    if (!style) {
+    stp = find_style(stylestr);
+    if (!stp) {
         put_status(e, "Unknown style '%s'", stylestr);
         return;
     }
@@ -2899,11 +2901,11 @@
 
     switch (prop_index) {
     case CSS_PROP_COLOR:
-        if (css_get_color(&style->fg_color, value))
+        if (css_get_color(&stp->fg_color, value))
             goto bad_color;
         break;
     case CSS_PROP_BACKGROUND_COLOR:
-        if (css_get_color(&style->bg_color, value))
+        if (css_get_color(&stp->bg_color, value))
             goto bad_color;
         break;
     bad_color:
@@ -2911,44 +2913,44 @@
         return;
     case CSS_PROP_FONT_FAMILY:
         v = css_get_font_family(value);
-        style->font_style = (style->font_style & ~QE_FAMILY_MASK) | v;
+        stp->font_style = (stp->font_style & ~QE_FAMILY_MASK) | v;
         break;
     case CSS_PROP_FONT_STYLE:
         /* XXX: cannot handle inherit correctly */
-        v = style->font_style;
+        v = stp->font_style;
         if (strequal(value, "italic")) {
             v |= QE_STYLE_ITALIC;
         } else
         if (strequal(value, "normal")) {
             v &= ~QE_STYLE_ITALIC;
         }
-        style->font_style = v;
+        stp->font_style = v;
         break;
     case CSS_PROP_FONT_WEIGHT:
         /* XXX: cannot handle inherit correctly */
-        v = style->font_style;
+        v = stp->font_style;
         if (strequal(value, "bold")) {
             v |= QE_STYLE_BOLD;
         } else
         if (strequal(value, "normal")) {
             v &= ~QE_STYLE_BOLD;
         }
-        style->font_style = v;
+        stp->font_style = v;
         break;
     case CSS_PROP_FONT_SIZE:
         if (strequal(value, "inherit")) {
-            style->font_size = 0;
+            stp->font_size = 0;
         } else {
-            style->font_size = strtol(value, NULL, 0);
+            stp->font_size = strtol(value, NULL, 0);
         }
         break;
     case CSS_PROP_TEXT_DECORATION:
         /* XXX: cannot handle inherit correctly */
         if (strequal(value, "none")) {
-            style->font_style &= ~QE_STYLE_UNDERLINE;
+            stp->font_style &= ~QE_STYLE_UNDERLINE;
         } else
         if (strequal(value, "underline")) {
-            style->font_style |= QE_STYLE_UNDERLINE;
+            stp->font_style |= QE_STYLE_UNDERLINE;
         }
         break;
     }
@@ -3018,73 +3020,73 @@
             system_fonts);
 }
 
-static void display_bol_bidir(DisplayState *s, DirType base,
+static void display_bol_bidir(DisplayState *ds, DirType base,
                               int embedding_level_max)
 {
-    s->base = base;
-    s->x = s->x_disp = s->edit_state->x_disp[base];
-    if (s->base == DIR_RTL) {
+    ds->base = base;
+    ds->x = ds->x_disp = ds->edit_state->x_disp[base];
+    if (ds->base == DIR_RTL) {
         /* XXX: probably broken. bidir handling needs fixing */
-        s->x_start = s->edit_state->width - s->x;
+        ds->x_start = ds->edit_state->width - ds->x;
     } else {
-        s->x_start = s->x;
+        ds->x_start = ds->x;
     }
-    s->left_gutter = 0;
-    s->x_line = s->x_start;
-    s->style = 0;
-    s->last_style = 0;
-    s->fragment_index = 0;
-    s->line_index = 0;
-    s->nb_fragments = 0;
-    s->word_index = 0;
-    s->embedding_level_max = embedding_level_max;
-    s->last_word_space = 0;
+    ds->left_gutter = 0;
+    ds->x_line = ds->x_start;
+    ds->style = 0;
+    ds->last_style = 0;
+    ds->fragment_index = 0;
+    ds->line_index = 0;
+    ds->nb_fragments = 0;
+    ds->word_index = 0;
+    ds->embedding_level_max = embedding_level_max;
+    ds->last_word_space = 0;
 }
 
-void display_bol(DisplayState *s)
+void display_bol(DisplayState *ds)
 {
-    display_bol_bidir(s, DIR_LTR, 0);
+    display_bol_bidir(ds, DIR_LTR, 0);
 }
 
-void display_close(DisplayState *s)
+void display_close(DisplayState *ds)
 {
 }
 
-void display_init(DisplayState *s, EditState *e, enum DisplayType do_disp,
+void display_init(DisplayState *ds, EditState *e, enum DisplayType do_disp,
                   int (*cursor_func)(DisplayState *ds,
                                      int offset1, int offset2, int line_num,
                                      int x, int y, int w, int h, int hex_mode),
                   void *cursor_opaque)
 {
     QEFont *font;
-    QEStyleDef style;
+    QEStyleDef styledef;
 
-    s->edit_state = e;
-    s->do_disp = do_disp;
-    s->cursor_func = cursor_func;
-    s->cursor_opaque = cursor_opaque;
-    s->wrap = e->wrap;
+    ds->edit_state = e;
+    ds->do_disp = do_disp;
+    ds->cursor_func = cursor_func;
+    ds->cursor_opaque = cursor_opaque;
+    ds->wrap = e->wrap;
     /* select default values */
-    get_style(e, &style, QE_STYLE_DEFAULT);
-    font = select_font(e->screen, style.font_style, style.font_size);
-    s->default_line_height = font->ascent + font->descent;
-    s->eol_width = max3(glyph_width(e->screen, font, '/'),
+    get_style(e, &styledef, QE_STYLE_DEFAULT);
+    font = select_font(e->screen, styledef.font_style, styledef.font_size);
+    ds->default_line_height = font->ascent + font->descent;
+    ds->eol_width = max3(glyph_width(e->screen, font, '/'),
                         glyph_width(e->screen, font, '\\'),
                         glyph_width(e->screen, font, '$'));
-    s->space_width = glyph_width(e->screen, font, ' ');
-    s->tab_width = s->space_width * e->b->tab_width;
-    s->width = e->width - s->eol_width;
-    s->height = e->height;
-    s->hex_mode = e->hex_mode;
-    s->cur_hex_mode = 0;
-    s->y = e->y_disp;
-    s->line_num = 0;
-    s->line_numbers = e->line_numbers * s->space_width * 8;
-    if (s->line_numbers > s->width / 2)
-        s->line_numbers = 0;
-    s->eol_reached = 0;
-    s->eod = 0;
-    display_bol(s);
+    ds->space_width = glyph_width(e->screen, font, ' ');
+    ds->tab_width = ds->space_width * e->b->tab_width;
+    ds->width = e->width - ds->eol_width;
+    ds->height = e->height;
+    ds->hex_mode = e->hex_mode;
+    ds->cur_hex_mode = 0;
+    ds->y = e->y_disp;
+    ds->line_num = 0;
+    ds->line_numbers = e->line_numbers * ds->space_width * 8;
+    if (ds->line_numbers > ds->width / 2)
+        ds->line_numbers = 0;
+    ds->eol_reached = 0;
+    ds->eod = 0;
+    display_bol(ds);
     release_font(e->screen, font);
 }
 
@@ -3135,11 +3137,11 @@
    `offset1..offset2` is the range of offsets for cursor management
    `last` is 0 for a line wrap, 1 for end of line, -1 for continuation
 */
-static void flush_line(DisplayState *s,
+static void flush_line(DisplayState *ds,
                        TextFragment *fragments, int nb_fragments,
                        int offset1, int offset2, int last)
 {
-    EditState *e = s->edit_state;
+    EditState *e = ds->edit_state;
     QEditScreen *screen = e->screen;
     int level, pos, p, i, x, x1, y, baseline, line_height, max_descent;
     TextFragment *frag;
@@ -3157,13 +3159,13 @@
     }
     if (nb_fragments == 0) {
         /* if empty line, still needs a non zero line height */
-        line_height = s->default_line_height;
+        line_height = ds->default_line_height;
     } else {
         line_height = baseline + max_descent;
     }
 
     /* swap according to embedding level (incorrect for very long lines) */
-    for (level = s->embedding_level_max; level > 0; level--) {
+    for (level = ds->embedding_level_max; level > 0; level--) {
         pos = 0;
         while (pos < nb_fragments) {
             if (fragments[pos].embedding_level >= level) {
@@ -3179,17 +3181,17 @@
     }
 
     /* draw everything if line is visible in window */
-    if (s->do_disp == DISP_PRINT 
-    &&  s->y + line_height >= 0
-    &&  s->y < e->ytop + e->height) {
-        QEStyleDef style, default_style;
+    if (ds->do_disp == DISP_PRINT 
+    &&  ds->y + line_height >= 0
+    &&  ds->y < e->ytop + e->height) {
+        QEStyleDef styledef, default_style;
         QELineShadow *ls;
         unsigned int crc;
 
         /* test if display needed */
         crc = compute_crc(fragments, sizeof(*fragments) * nb_fragments, 0);
-        crc = compute_crc(s->line_chars, sizeof(*s->line_chars) * 
s->line_index, crc);
-        if (s->line_num >= e->shadow_nb_lines) {
+        crc = compute_crc(ds->line_chars, sizeof(*ds->line_chars) * 
ds->line_index, crc);
+        if (ds->line_num >= e->shadow_nb_lines) {
             /* realloc shadow */
             int n = e->shadow_nb_lines;
             e->shadow_nb_lines = n + LINE_SHADOW_INCR;
@@ -3202,35 +3204,35 @@
         /* Use checksum based line cache to improve speed in graphics mode.
          * XXX: overlong lines will fail the cache test
          */
-        ls = &e->line_shadow[s->line_num];
-        if (ls->y != s->y || ls->x != s->x_line
+        ls = &e->line_shadow[ds->line_num];
+        if (ls->y != ds->y || ls->x != ds->x_line
         ||  ls->height != line_height || ls->crc != crc) {
             /* update values for the line cache */
-            ls->y = s->y;
-            ls->x = s->x_line;
+            ls->y = ds->y;
+            ls->x = ds->x_line;
             ls->height = line_height;
             ls->crc = crc;
 
             /* display */
             get_style(e, &default_style, QE_STYLE_DEFAULT);
-            x = s->x_start;
-            y = s->y;
+            x = ds->x_start;
+            y = ds->y;
 
             /* first display background rectangles */
             /* XXX: should coalesce rectangles with identical style */
-            if (s->left_gutter > 0) {
+            if (ds->left_gutter > 0) {
                 /* erase space before the line display, aka left gutter */
                 fill_rectangle(screen, e->xleft + x, e->ytop + y,
-                               s->left_gutter, line_height,
+                               ds->left_gutter, line_height,
                                default_style.bg_color);
             }
-            x = s->x_line;
-            x1 = s->width + s->eol_width;
+            x = ds->x_line;
+            x1 = ds->width + ds->eol_width;
             for (i = 0; i < nb_fragments && x < x1; i++) {
                 frag = &fragments[i];
-                get_style(e, &style, frag->style);
+                get_style(e, &styledef, frag->style);
                 fill_rectangle(screen, e->xleft + x, e->ytop + y, 
-                               frag->width, line_height, style.bg_color);
+                               frag->width, line_height, styledef.bg_color);
                 x += frag->width;
             }
             if (x < x1 && last != -1) {
@@ -3239,20 +3241,20 @@
             }
 
             /* then display text */
-            x = s->x_line;
+            x = ds->x_line;
             y += baseline;
 
             for (i = 0; i < nb_fragments && x < x1; i++) {
                 frag = &fragments[i];
                 x += frag->width;
                 if (x > 0) {
-                    get_style(e, &style, frag->style);
+                    get_style(e, &styledef, frag->style);
                     font = select_font(screen,
-                                       style.font_style, style.font_size);
+                                       styledef.font_style, 
styledef.font_size);
                     draw_text(screen, font, 
                               e->xleft + x - frag->width, e->ytop + y,
-                              s->line_chars + frag->line_index,
-                              frag->len, style.fg_color);
+                              ds->line_chars + frag->line_index,
+                              frag->len, styledef.fg_color);
                     release_font(screen, font);
                 }
             }
@@ -3263,9 +3265,9 @@
 
                 markbuf[0] = '/';        /* RTL eol mark */
                 x = 0;                   /* displayed at the left border */
-                if (s->base == DIR_LTR) {
+                if (ds->base == DIR_LTR) {
                     markbuf[0] = '\\';   /* LTR eol mark */
-                    x = s->width;        /* displayed at the right border */
+                    x = ds->width;        /* displayed at the right border */
                 }
                 font = select_font(screen,
                                    default_style.font_style,
@@ -3278,16 +3280,16 @@
     }
 
     /* call cursor callback */
-    if (s->cursor_func) {
-        x = s->x_line;
-        y = s->y;
+    if (ds->cursor_func) {
+        x = ds->x_line;
+        y = ds->y;
 
         /* RTL eol cursor check (probably incorrect) */
         if (offset1 >= 0 && offset2 >= 0 &&
-            s->base == DIR_RTL &&
-            s->cursor_func(s, offset1, offset2, s->line_num,
-                           x, y, -s->eol_width, line_height, e->hex_mode)) {
-            s->eod = 1;
+            ds->base == DIR_RTL &&
+            ds->cursor_func(ds, offset1, offset2, ds->line_num,
+                           x, y, -ds->eol_width, line_height, e->hex_mode)) {
+            ds->eod = 1;
         }
 
         for (i = 0; i < nb_fragments; i++) {
@@ -3296,25 +3298,25 @@
             frag = &fragments[i];
 
             for (j = frag->line_index, k = 0; k < frag->len; k++, j++) {
-                int _offset1 = s->line_offsets[j][0];
-                int _offset2 = s->line_offsets[j][1];
-                int hex_mode = s->line_hex_mode[j];
-                int w = s->line_char_widths[j];
+                int _offset1 = ds->line_offsets[j][0];
+                int _offset2 = ds->line_offsets[j][1];
+                int hex_mode = ds->line_hex_mode[j];
+                int w = ds->line_char_widths[j];
                 x += w;
-                if ((hex_mode == s->hex_mode || s->hex_mode == -1) &&
+                if ((hex_mode == ds->hex_mode || ds->hex_mode == -1) &&
                     _offset1 >= 0 && _offset2 >= 0) {
 #if 0
                     /* probably broken, bidir needs rework */
-                    if (s->base == DIR_RTL) {
-                        if (s->cursor_func(s, _offset1, _offset2, s->line_num,
+                    if (ds->base == DIR_RTL) {
+                        if (ds->cursor_func(ds, _offset1, _offset2, 
ds->line_num,
                                            x, y, -w, line_height, hex_mode))
-                            s->eod = 1;
+                            ds->eod = 1;
                     } else 
 #endif
                     {
-                        if (s->cursor_func(s, _offset1, _offset2, s->line_num,
+                        if (ds->cursor_func(ds, _offset1, _offset2, 
ds->line_num,
                                            x - w, y, w, line_height, hex_mode))
-                            s->eod = 1;
+                            ds->eod = 1;
                     }
                 }
             }
@@ -3322,35 +3324,35 @@
 
         /* LTR eol cursor check */
         if (offset1 >= 0 && offset2 >= 0 &&
-            s->base == DIR_LTR &&
-            s->cursor_func(s, offset1, offset2, s->line_num,
-                           x, y, s->eol_width, line_height, e->hex_mode)) {
-            s->eod = 1;
+            ds->base == DIR_LTR &&
+            ds->cursor_func(ds, offset1, offset2, ds->line_num,
+                           x, y, ds->eol_width, line_height, e->hex_mode)) {
+            ds->eod = 1;
         }
-        s->x_line = x;
+        ds->x_line = x;
     }
 #if 0
     printf("y=%d line_num=%d line_height=%d baseline=%d\n",
-           s->y, s->line_num, line_height, baseline);
+           ds->y, ds->line_num, line_height, baseline);
 #endif
     if (last != -1) {
         /* bump to next line */
-        s->x_line = s->x_start;
-        s->y += line_height;
-        s->line_num++;
+        ds->x_line = ds->x_start;
+        ds->y += line_height;
+        ds->line_num++;
     }
 }
 
 /* keep 'n' line chars at the start of the line */
-static void keep_line_chars(DisplayState *s, int n)
+static void keep_line_chars(DisplayState *ds, int n)
 {
     int index;
 
-    index = s->line_index - n;
-    memmove(s->line_chars, s->line_chars + index, n * sizeof(unsigned int));
-    memmove(s->line_offsets, s->line_offsets + index, n * 2 * sizeof(unsigned 
int));
-    memmove(s->line_char_widths, s->line_char_widths + index, n * 
sizeof(short));
-    s->line_index = n;
+    index = ds->line_index - n;
+    memmove(ds->line_chars, ds->line_chars + index, n * sizeof(unsigned int));
+    memmove(ds->line_offsets, ds->line_offsets + index, n * 2 * 
sizeof(unsigned int));
+    memmove(ds->line_char_widths, ds->line_char_widths + index, n * 
sizeof(short));
+    ds->line_index = n;
 }
 
 #ifndef CONFIG_UNICODE_JOIN
@@ -3376,205 +3378,207 @@
 #endif
 
 /* layout of a word fragment */
-static void flush_fragment(DisplayState *s)
+static void flush_fragment(DisplayState *ds)
 {
-    int w, len, style_index, i, j;
-    QEditScreen *screen = s->edit_state->screen;
+    int w, len, style, i, j;
+    QEditScreen *screen = ds->edit_state->screen;
     TextFragment *frag;
-    QEStyleDef style;
+    QEStyleDef styledef;
     QEFont *font;
     unsigned int char_to_glyph_pos[MAX_WORD_SIZE];
     int nb_glyphs, dst_max_size, ascent, descent;
 
-    if (s->fragment_index == 0)
+    if (ds->fragment_index == 0)
         return;
 
-    if (s->nb_fragments >= MAX_SCREEN_WIDTH ||
-        s->line_index + s->fragment_index > MAX_SCREEN_WIDTH) {
+    if (ds->nb_fragments >= MAX_SCREEN_WIDTH ||
+        ds->line_index + ds->fragment_index > MAX_SCREEN_WIDTH) {
         /* too many fragments on the same line, flush and stay on the line */
-        flush_line(s, s->fragments, s->nb_fragments, -1, -1, -1);
-        s->nb_fragments = 0;
-        s->line_index = 0;
-        s->word_index = 0;
+        flush_line(ds, ds->fragments, ds->nb_fragments, -1, -1, -1);
+        ds->nb_fragments = 0;
+        ds->line_index = 0;
+        ds->word_index = 0;
     }
 
     /* update word start index if needed */
-    if (s->nb_fragments >= 1 && s->last_word_space != s->last_space) {
-        s->last_word_space = s->last_space;
-        s->word_index = s->nb_fragments;
+    if (ds->nb_fragments >= 1 && ds->last_word_space != ds->last_space) {
+        ds->last_word_space = ds->last_space;
+        ds->word_index = ds->nb_fragments;
     }
 
     /* convert fragment to glyphs (currently font independent, but may
        change) */
-    //dst_max_size = MAX_SCREEN_WIDTH - s->line_index;
+    //dst_max_size = MAX_SCREEN_WIDTH - ds->line_index;
     //if (dst_max_size <= 0)
     //    goto the_end;
-    dst_max_size = MAX_WORD_SIZE; // assuming s->fragment_index MAX_WORD_SIZE
-    nb_glyphs = unicode_to_glyphs(s->line_chars + s->line_index,
+    dst_max_size = MAX_WORD_SIZE; // assuming ds->fragment_index MAX_WORD_SIZE
+    nb_glyphs = unicode_to_glyphs(ds->line_chars + ds->line_index,
                                   char_to_glyph_pos, dst_max_size,
-                                  s->fragment_chars, s->fragment_index,
-                                  s->last_embedding_level & 1);
+                                  ds->fragment_chars, ds->fragment_index,
+                                  ds->last_embedding_level & 1);
 
     /* compute new offsets */
-    j = s->line_index;
+    j = ds->line_index;
     for (i = 0; i < nb_glyphs; i++) {
-        s->line_offsets[j][0] = -1;
-        s->line_offsets[j][1] = -1;
+        ds->line_offsets[j][0] = -1;
+        ds->line_offsets[j][1] = -1;
         j++;
     }
-    for (i = 0; i < s->fragment_index; i++) {
+    for (i = 0; i < ds->fragment_index; i++) {
         int offset1, offset2;
-        j = s->line_index + char_to_glyph_pos[i];
-        offset1 = s->fragment_offsets[i][0];
-        offset2 = s->fragment_offsets[i][1];
-        s->line_hex_mode[j] = s->fragment_hex_mode[i];
+        j = ds->line_index + char_to_glyph_pos[i];
+        offset1 = ds->fragment_offsets[i][0];
+        offset2 = ds->fragment_offsets[i][1];
+        ds->line_hex_mode[j] = ds->fragment_hex_mode[i];
         /* we suppose the the chars are contiguous */
-        if (s->line_offsets[j][0] == -1 ||
-            s->line_offsets[j][0] > offset1)
-            s->line_offsets[j][0] = offset1;
-        if (s->line_offsets[j][1] == -1 ||
-            s->line_offsets[j][1] < offset2)
-            s->line_offsets[j][1] = offset2;
+        if (ds->line_offsets[j][0] == -1 ||
+            ds->line_offsets[j][0] > offset1)
+            ds->line_offsets[j][0] = offset1;
+        if (ds->line_offsets[j][1] == -1 ||
+            ds->line_offsets[j][1] < offset2)
+            ds->line_offsets[j][1] = offset2;
     }
 
-    style_index = s->last_style;
-    get_style(s->edit_state, &style, style_index);
+    style = ds->last_style;
+    get_style(ds->edit_state, &styledef, style);
     /* select font according to current style */
-    font = select_font(screen, style.font_style, style.font_size);
-    j = s->line_index;
+    font = select_font(screen, styledef.font_style, styledef.font_size);
+    j = ds->line_index;
     ascent = font->ascent;
     descent = font->descent;
-    if (s->line_chars[j] == '\t') {
+    if (ds->line_chars[j] == '\t') {
         int x1;
         /* special case for TAB */
-        x1 = (s->x - s->x_disp) % s->tab_width;
-        w = s->tab_width - x1;
+        x1 = (ds->x - ds->x_disp) % ds->tab_width;
+        w = ds->tab_width - x1;
         /* display a single space */
-        s->line_chars[j] = ' ';
-        s->line_char_widths[j] = w;
+        ds->line_chars[j] = ' ';
+        ds->line_char_widths[j] = w;
     } else {
         /* XXX: use text metrics for full fragment */
         w = 0;
         /* XXX: is the width negative for a RTL fragment? */
         for (i = 0; i < nb_glyphs; i++) {
             QECharMetrics metrics;
-            text_metrics(screen, font, &metrics, &s->line_chars[j], 1);
+            text_metrics(screen, font, &metrics, &ds->line_chars[j], 1);
             if (metrics.font_ascent > ascent)
                 ascent = metrics.font_ascent;
             if (metrics.font_descent > descent)
                 descent = metrics.font_descent;
-            s->line_char_widths[j] = metrics.width;
-            w += s->line_char_widths[j];
+            ds->line_char_widths[j] = metrics.width;
+            w += ds->line_char_widths[j];
             j++;
         }
     }
     release_font(screen, font);
 
     /* add the fragment */
-    frag = &s->fragments[s->nb_fragments++];
+    frag = &ds->fragments[ds->nb_fragments++];
     frag->width = w;
-    frag->line_index = s->line_index;
+    frag->line_index = ds->line_index;
     frag->len = nb_glyphs;
-    frag->embedding_level = s->last_embedding_level;
-    frag->style = style_index;
+    frag->embedding_level = ds->last_embedding_level;
+    frag->style = style;
     frag->ascent = ascent;
     frag->descent = descent;
-    frag->dummy = 0;
+#if QE_TERM_STYLE_BITS == 16
+    frag->dummy = 0;  /* initialize padding for checksum consistency */
+#endif
 
-    s->line_index += nb_glyphs;
-    s->x += frag->width;
+    ds->line_index += nb_glyphs;
+    ds->x += frag->width;
 
-    switch (s->wrap) {
+    switch (ds->wrap) {
     case WRAP_TRUNCATE:
         break;
     case WRAP_LINE:
-        while (s->x > s->width) {
+        while (ds->x > ds->width) {
             int len1, w1, ww, n;
-            //printf("x=%d maxw=%d len=%d\n", s->x, s->width, frag->len);
-            frag = &s->fragments[s->nb_fragments - 1];
+            //printf("x=%d maxw=%d len=%d\n", ds->x, ds->width, frag->len);
+            frag = &ds->fragments[ds->nb_fragments - 1];
             /* find fragment truncation to fit the line */
             len = len1 = frag->len;
-            w1 = s->x;
-            while (s->x > s->width) {
+            w1 = ds->x;
+            while (ds->x > ds->width) {
                 len--;
-                ww = s->line_char_widths[frag->line_index + len];
-                s->x -= ww;
-                if (len == 0 && s->x == 0) {
+                ww = ds->line_char_widths[frag->line_index + len];
+                ds->x -= ww;
+                if (len == 0 && ds->x == 0) {
                     /* avoid looping by putting at least one char per line */
                     len = 1;
-                    s->x += ww;
+                    ds->x += ww;
                     break;
                 }
             }
             len1 -= len;
-            w1 -= s->x;
+            w1 -= ds->x;
             frag->len = len;
             frag->width -= w1;
-            //printf("after: x=%d w1=%d\n", s->x, w1);
-            n = s->nb_fragments;
+            //printf("after: x=%d w1=%d\n", ds->x, w1);
+            n = ds->nb_fragments;
             if (len == 0)
                 n--;
 
             /* flush fragments with a line continuation mark */
-            flush_line(s, s->fragments, n, -1, -1, 0);
+            flush_line(ds, ds->fragments, n, -1, -1, 0);
 
             /* skip line number column if present */
-            s->left_gutter = s->line_numbers;
-            s->x = s->x_line += s->left_gutter;
+            ds->left_gutter = ds->line_numbers;
+            ds->x = ds->x_line += ds->left_gutter;
 
             /* move the remaining fragment to next line */
-            s->nb_fragments = 0;
+            ds->nb_fragments = 0;
             if (len1 > 0) {
-                memmove(s->fragments, frag, sizeof(TextFragment));
-                frag = s->fragments;
+                memmove(ds->fragments, frag, sizeof(TextFragment));
+                frag = ds->fragments;
                 frag->width = w1;
                 frag->line_index = 0;
                 frag->len = len1;
-                s->nb_fragments = 1;
-                s->x += w1;
+                ds->nb_fragments = 1;
+                ds->x += w1;
             }
-            keep_line_chars(s, len1);
+            keep_line_chars(ds, len1);
         }
         break;
     case WRAP_WORD:
-        if (s->x > s->width) {
+        if (ds->x > ds->width) {
             int index;
 
             /* flush fragments with a line continuation mark */
-            flush_line(s, s->fragments, s->word_index, -1, -1, 0);
+            flush_line(ds, ds->fragments, ds->word_index, -1, -1, 0);
 
             /* skip line number column if present */
-            s->left_gutter = s->line_numbers;
-            s->x = s->x_line += s->left_gutter;
+            ds->left_gutter = ds->line_numbers;
+            ds->x = ds->x_line += ds->left_gutter;
 
             /* put words on next line */
-            index = s->fragments[s->word_index].line_index;
-            memmove(s->fragments, s->fragments + s->word_index,
-                    (s->nb_fragments - s->word_index) * sizeof(TextFragment));
-            s->nb_fragments -= s->word_index;
+            index = ds->fragments[ds->word_index].line_index;
+            memmove(ds->fragments, ds->fragments + ds->word_index,
+                    (ds->nb_fragments - ds->word_index) * 
sizeof(TextFragment));
+            ds->nb_fragments -= ds->word_index;
 
-            for (i = 0; i < s->nb_fragments; i++) {
-                s->fragments[i].line_index -= index;
-                s->x += s->fragments[i].width;
+            for (i = 0; i < ds->nb_fragments; i++) {
+                ds->fragments[i].line_index -= index;
+                ds->x += ds->fragments[i].width;
             }
-            keep_line_chars(s, s->line_index - index);
-            s->word_index = 0;
+            keep_line_chars(ds, ds->line_index - index);
+            ds->word_index = 0;
         }
         break;
     }
-    s->fragment_index = 0;
+    ds->fragment_index = 0;
 }
 
-int display_char_bidir(DisplayState *s, int offset1, int offset2,
+int display_char_bidir(DisplayState *ds, int offset1, int offset2,
                        int embedding_level, int ch)
 {
     int space, style, istab, isaccent;
     EditState *e;
 
-    style = s->style;
+    style = ds->style;
 
     /* special code to colorize block */
-    e = s->edit_state;
+    e = ds->edit_state;
     if (e->show_selection || e->region_style) {
         int mark = e->b->mark;
         int offset = e->offset;
@@ -3598,65 +3602,65 @@
     isaccent = qe_isaccent(ch);
     /* a fragment is a part of word where style/embedding_level do not
        change. For TAB, only one fragment containing it is sent */
-    if (s->fragment_index >= 1) {
-        if (s->fragment_index >= MAX_WORD_SIZE ||
+    if (ds->fragment_index >= 1) {
+        if (ds->fragment_index >= MAX_WORD_SIZE ||
             istab ||
-            space != s->last_space ||
-            style != s->last_style ||
-            embedding_level != s->last_embedding_level) {
+            space != ds->last_space ||
+            style != ds->last_style ||
+            embedding_level != ds->last_embedding_level) {
             /* flush the current fragment if needed */
-            if (isaccent && s->fragment_chars[s->fragment_index - 1] == ' ') {
+            if (isaccent && ds->fragment_chars[ds->fragment_index - 1] == ' ') 
{
                 /* separate last space to make it part of the next word */
                 int off1, off2, cur_hex;
-                --s->fragment_index;
-                off1 = s->fragment_offsets[s->fragment_index][0];
-                off2 = s->fragment_offsets[s->fragment_index][1];
-                cur_hex = s->fragment_hex_mode[s->fragment_index];
-                flush_fragment(s);
-                s->fragment_chars[s->fragment_index] = ' ';
-                s->fragment_offsets[s->fragment_index][0] = off1;
-                s->fragment_offsets[s->fragment_index][1] = off2;
-                s->fragment_hex_mode[s->fragment_index] = cur_hex;
-                s->fragment_index++;
+                --ds->fragment_index;
+                off1 = ds->fragment_offsets[ds->fragment_index][0];
+                off2 = ds->fragment_offsets[ds->fragment_index][1];
+                cur_hex = ds->fragment_hex_mode[ds->fragment_index];
+                flush_fragment(ds);
+                ds->fragment_chars[ds->fragment_index] = ' ';
+                ds->fragment_offsets[ds->fragment_index][0] = off1;
+                ds->fragment_offsets[ds->fragment_index][1] = off2;
+                ds->fragment_hex_mode[ds->fragment_index] = cur_hex;
+                ds->fragment_index++;
             } else {
-                flush_fragment(s);
+                flush_fragment(ds);
             }
         }
     }
 
-    if (isaccent && s->fragment_index == 0) {
+    if (isaccent && ds->fragment_index == 0) {
         /* prepend a space if fragment starts with an accent */
-        s->fragment_chars[s->fragment_index] = ' ';
-        s->fragment_offsets[s->fragment_index][0] = offset1;
-        s->fragment_offsets[s->fragment_index][1] = offset2;
-        s->fragment_hex_mode[s->fragment_index] = s->cur_hex_mode;
-        s->fragment_index++;
+        ds->fragment_chars[ds->fragment_index] = ' ';
+        ds->fragment_offsets[ds->fragment_index][0] = offset1;
+        ds->fragment_offsets[ds->fragment_index][1] = offset2;
+        ds->fragment_hex_mode[ds->fragment_index] = ds->cur_hex_mode;
+        ds->fragment_index++;
         offset1 = offset2 = -1;
     }
     /* store the char and its embedding level */
-    s->fragment_chars[s->fragment_index] = ch;
-    s->fragment_offsets[s->fragment_index][0] = offset1;
-    s->fragment_offsets[s->fragment_index][1] = offset2;
-    s->fragment_hex_mode[s->fragment_index] = s->cur_hex_mode;
-    s->fragment_index++;
-
-    s->last_space = space;
-    s->last_style = style;
-    s->last_embedding_level = embedding_level;
+    ds->fragment_chars[ds->fragment_index] = ch;
+    ds->fragment_offsets[ds->fragment_index][0] = offset1;
+    ds->fragment_offsets[ds->fragment_index][1] = offset2;
+    ds->fragment_hex_mode[ds->fragment_index] = ds->cur_hex_mode;
+    ds->fragment_index++;
+
+    ds->last_space = space;
+    ds->last_style = style;
+    ds->last_embedding_level = embedding_level;
 
     if (istab) {
-        flush_fragment(s);
+        flush_fragment(ds);
     }
     return 0;
 }
 
-void display_printhex(DisplayState *s, int offset1, int offset2,
+void display_printhex(DisplayState *ds, int offset1, int offset2,
                       unsigned int h, int n)
 {
     int i, v;
-    EditState *e = s->edit_state;
+    EditState *e = ds->edit_state;
 
-    s->cur_hex_mode = 1;
+    ds->cur_hex_mode = 1;
     for (i = 0; i < n; i++) {
         v = (h >> ((n - i - 1) * 4)) & 0xf;
         if (v >= 10)
@@ -3665,12 +3669,12 @@
             v += '0';
         /* XXX: simplistic */
         if (e->hex_nibble == i) {
-            display_char(s, offset1, offset2, v);
+            display_char(ds, offset1, offset2, v);
         } else {
-            display_char(s, offset1, offset1, v);
+            display_char(ds, offset1, offset1, v);
         }
     }
-    s->cur_hex_mode = 0;
+    ds->cur_hex_mode = 0;
 }
 
 void display_printf(DisplayState *ds, int offset1, int offset2,
@@ -3694,47 +3698,47 @@
 }
 
 /* end of line */
-void display_eol(DisplayState *s, int offset1, int offset2)
+void display_eol(DisplayState *ds, int offset1, int offset2)
 {
-    flush_fragment(s);
+    flush_fragment(ds);
 
     /* note: the line may be empty */
-    flush_line(s, s->fragments, s->nb_fragments, offset1, offset2, 1);
+    flush_line(ds, ds->fragments, ds->nb_fragments, offset1, offset2, 1);
 }
 
 /* temporary function for backward compatibility */
-static void display1(DisplayState *s)
+static void display1(DisplayState *ds)
 {
-    EditState *e = s->edit_state;
+    EditState *e = ds->edit_state;
     int offset;
 
-    s->eod = 0;
+    ds->eod = 0;
     offset = e->offset_top;
     for (;;) {
         /* XXX: need early bailout from display_line if WRAP_TRUNCATE
            and far beyond the right border after cursor found.
         */
-        offset = e->mode->display_line(e, s, offset);
+        offset = e->mode->display_line(e, ds, offset);
         e->offset_bottom = offset;
 
         /* EOF reached ? */
         if (offset < 0)
             break;
 
-        switch (s->do_disp) {
+        switch (ds->do_disp) {
         case DISP_NONE:
             return;
         case DISP_CURSOR:
-            if (s->eod)
+            if (ds->eod)
                 return;
             break;
         case DISP_CURSOR_SCREEN:
-            if (s->eod || s->y >= s->height)
+            if (ds->eod || ds->y >= ds->height)
                 return;
             break;
         case DISP_PRINT:
         default:
-            if (s->y >= s->height)
+            if (ds->y >= ds->height)
                 return; /* end of screen */
             break;
         }
@@ -3806,6 +3810,7 @@
    buffer */
 
 static int get_staticly_colorized_line(EditState *s, unsigned int *buf, int 
buf_size,
+                                       QETermStyle *sbuf,
                                        int offset, int *offset_ptr, int 
line_num)
 {
     EditBuffer *b = s->b;
@@ -3816,14 +3821,17 @@
     for (;;) {
         int style = eb_get_style(b, offset);
         int c = eb_nextc(b, offset, &offset);
-        if (c == '\n')
+        if (c == '\n') {
+            /* XXX: set style for end of line? */
             break;
+        }
         if (buf_ptr < buf_end) {
-            c = (c & CHAR_MASK) | (style << STYLE_SHIFT);
+            sbuf[buf_ptr - buf] = style;
             *buf_ptr++ = c;
         }
     }
     *buf_ptr = '\0';
+    sbuf[buf_ptr - buf] = 0;  /* end of line style? */
     *offset_ptr = offset;
     return buf_ptr - buf;
 }
@@ -3837,11 +3845,12 @@
 
 static int syntax_get_colorized_line(EditState *s, 
                                      unsigned int *buf, int buf_size, 
+                                     QETermStyle *sbuf,
                                      int offset, int *offsetp, int line_num)
 {
     QEColorizeContext cctx;
     EditBuffer *b = s->b;
-    int len, line, n, col, bom;
+    int i, len, line, n, col, bom;
 
     /* invalidate cache if needed */
     if (s->colorize_max_valid_offset != INT_MAX) {
@@ -3919,6 +3928,7 @@
         SET_COLOR1(buf, 0, QE_STYLE_PREPROCESS);
         cctx.offset = eb_next(b, cctx.offset);
     }
+    cctx.combine_stop = len - bom;
     s->colorize_func(&cctx, buf + bom, len - bom, s->mode);
     /* buf[len] has char '\0' but may hold style, force buf ending */
     buf[len + 1] = 0;
@@ -3930,6 +3940,24 @@
     if (s->colorize_nb_valid_lines < line_num + 2)
         s->colorize_nb_valid_lines = line_num + 2;
 
+    /* Extract styles from colored codepoint array */
+    for (i = 0; i <= len + 1; i++) {
+        sbuf[i] = buf[i] >> STYLE_SHIFT;
+        buf[i] &= CHAR_MASK;
+    }
+
+    /* Combine with buffer styles on restricted range */
+    if (s->b->b_styles) {
+        int i, start = bom + cctx.combine_start, stop = bom + 
cctx.combine_stop;
+        int offset = cctx.offset;
+        for (i = bom; i < stop; i++) {
+            QETermStyle style = eb_get_style(b, offset);
+            if (style && i >= start) {
+                sbuf[i] = style;
+            }
+            offset = eb_next(b, offset);
+        }
+    }
     return len;
 }
 
@@ -3946,24 +3974,6 @@
         e->colorize_max_valid_offset = offset;
 }
 
-int combine_static_colorized_line(EditState *s, unsigned int *buf, 
-                                  int len, int offset)
-{
-    EditBuffer *b = s->b;
-    int i;
-
-    if (b->b_styles) {
-        for (i = 0; i < len; i++) {
-            int style = eb_get_style(b, offset);
-            if (style) {
-                buf[i] = (buf[i] & CHAR_MASK) | (style << STYLE_SHIFT);
-            }
-            offset = eb_next(b, offset);
-        }
-    }
-    return len;
-}
-
 #endif /* CONFIG_TINY */
 
 void set_colorize_func(EditState *s, ColorizeFunc colorize_func)
@@ -3985,21 +3995,20 @@
 }
 
 int generic_get_colorized_line(EditState *s, unsigned int *buf, int buf_size,
+                               QETermStyle *sbuf,
                                int offset, int *offsetp, int line_num)
 {
     int len;
 
 #ifndef CONFIG_TINY
     if (s->colorize_func) {
-        len = syntax_get_colorized_line(s, buf, buf_size, offset, offsetp, 
line_num);
-        if (s->b->b_styles && s->colorize_func != shell_colorize_line) {
-            /* XXX: shell mode should have its own get_colorized_line handler 
*/
-            combine_static_colorized_line(s, buf, buf_size, len);
-        }
+        len = syntax_get_colorized_line(s, buf, buf_size, sbuf,
+                                        offset, offsetp, line_num);
     } else
 #endif
     if (s->b->b_styles) {
-        len = get_staticly_colorized_line(s, buf, buf_size, offset, offsetp, 
line_num);
+        len = get_staticly_colorized_line(s, buf, buf_size, sbuf,
+                                          offset, offsetp, line_num);
     } else {
         len = eb_get_line(s->b, buf, buf_size, offset, offsetp);
         if (buf[len] != '\n') {
@@ -4008,6 +4017,9 @@
             *offsetp = eb_goto_pos(s->b, line_num + 1, 0);
         }
         buf[len] = '\0';
+        if (sbuf) {
+            memset(sbuf, 0, len * sizeof(*sbuf));
+        }
     }
     return len;
 }
@@ -4022,8 +4034,9 @@
     TypeLink embeds[RLE_EMBEDDINGS_SIZE], *bd;
     int embedding_level, embedding_max_level;
     FriBidiCharType base;
-    unsigned int colored_chars[COLORED_MAX_LINE_SIZE];
-    int char_index, colored_nb_chars;
+    unsigned int buf[COLORED_MAX_LINE_SIZE];
+    QETermStyle sbuf[COLORED_MAX_LINE_SIZE];
+    int i, char_index, colored_nb_chars;
 
     line_num = 0;
     /* XXX: should test a flag, to avoid this call in hex/binary */
@@ -4075,17 +4088,14 @@
     /* colorize */
     colored_nb_chars = 0;
     offset0 = offset;
-    if (s->colorize_func
+    if (s->colorize_func || s->b->b_styles
     ||  s->curline_style || s->region_style
-    ||  s->b->b_styles
     ||  s->isearch_state) {
         /* XXX: deal with truncation */
-        colored_nb_chars = s->get_colorized_line(s, colored_chars,
-                                                 countof(colored_chars),
+        colored_nb_chars = s->get_colorized_line(s, buf, countof(buf), sbuf,
                                                  offset, &offset0, line_num);
         if (s->isearch_state) {
-            isearch_colorize_matches(s, colored_chars, colored_nb_chars,
-                                     offset);
+            isearch_colorize_matches(s, buf, colored_nb_chars, sbuf, offset);
         }
     }
 
@@ -4095,7 +4105,7 @@
         /* CG: Should combine styles instead of replacing */
         if (s->region_style && !s->curline_style) {
             int line, start_offset, end_offset;
-            int start_char, end_char;
+            int i, start_char, end_char;
 
             if (s->b->mark < s->offset) {
                 start_offset = max(offset, s->b->mark);
@@ -4111,16 +4121,16 @@
                     end_char = colored_nb_chars;
                 else
                     eb_get_pos(s->b, &line, &end_char, end_offset);
-                clear_color(colored_chars + start_char, end_char - start_char);
-                set_color(colored_chars + start_char, colored_chars + end_char,
-                          s->region_style);
+
+                for (i = start_char; i < end_char; i++) {
+                    sbuf[i] = s->region_style;
+                }
             }
         } else
         if (s->curline_style && s->offset >= offset && s->offset <= offset0) {
             /* XXX: only if qs->active_window == s ? */
-            clear_color(colored_chars, colored_nb_chars);
-            set_color(colored_chars, colored_chars + colored_nb_chars,
-                      s->curline_style);
+            for (i = 0; i < colored_nb_chars; i++)
+                sbuf[i] = s->curline_style;
         }
     }
 #endif
@@ -4137,12 +4147,9 @@
             offset = -1; /* signal end of text */
             break;
         } else {
-            /* Should simplify this if colored line was computed */
             ds->style = 0;
             if (char_index < colored_nb_chars) {
-                /* colored_chars should just be a style array */
-                c = colored_chars[char_index];
-                ds->style = (unsigned int)c >> STYLE_SHIFT;
+                ds->style = sbuf[char_index];
             }
             c = eb_nextc(s->b, offset, &offset);
             if (c == '\n' && !s->minibuf) {
@@ -5300,16 +5307,16 @@
 /* Print a utf-8 encoded buffer as unicode */
 void print_at_byte(QEditScreen *screen,
                    int x, int y, int width, int height,
-                   const char *str, int style_index)
+                   const char *str, int style)
 {
     unsigned int ubuf[MAX_SCREEN_WIDTH];
     int len;
-    QEStyleDef style;
+    QEStyleDef styledef;
     QEFont *font;
     CSSRect rect;
 
     len = utf8_to_unicode(ubuf, countof(ubuf), str);
-    get_style(NULL, &style, style_index);
+    get_style(NULL, &styledef, style);
 
     /* clip rectangle */
     rect.x1 = x;
@@ -5319,9 +5326,9 @@
     set_clip_rectangle(screen, &rect);
 
     /* start rectangle */
-    fill_rectangle(screen, x, y, width, height, style.bg_color);
-    font = select_font(screen, style.font_style, style.font_size);
-    draw_text(screen, font, x, y + font->ascent, ubuf, len, style.fg_color);
+    fill_rectangle(screen, x, y, width, height, styledef.bg_color);
+    font = select_font(screen, styledef.font_style, styledef.font_size);
+    draw_text(screen, font, x, y + font->ascent, ubuf, len, styledef.fg_color);
     release_font(screen, font);
 }
 
@@ -7141,29 +7148,27 @@
     put_status(s, "Hello, how are you?");
 }
 
-int get_glyph_width(QEditScreen *screen, 
-                    EditState *s, int style_index, int c)
+int get_glyph_width(QEditScreen *screen, EditState *s, int style, int c)
 {
+    QEStyleDef styledef;
     QEFont *font;
-    QEStyleDef style;
     int width;
 
-    get_style(s, &style, style_index);
-    font = select_font(screen, style.font_style, style.font_size);
+    get_style(s, &styledef, style);
+    font = select_font(screen, styledef.font_style, styledef.font_size);
     width = glyph_width(screen, font, c);
     release_font(screen, font);
     return width;
 }
 
-int get_line_height(QEditScreen *screen, 
-                    EditState *s, int style_index)
+int get_line_height(QEditScreen *screen, EditState *s, int style)
 {
+    QEStyleDef styledef;
     QEFont *font;
-    QEStyleDef style;
     int height;
 
-    get_style(s, &style, style_index);
-    font = select_font(screen, style.font_style, style.font_size);
+    get_style(s, &styledef, style);
+    font = select_font(screen, styledef.font_style, styledef.font_size);
     height = font->ascent + font->descent;
     release_font(screen, font);
     return height;

Index: qe.h
===================================================================
RCS file: /sources/qemacs/qemacs/qe.h,v
retrieving revision 1.245
retrieving revision 1.246
diff -u -b -r1.245 -r1.246
--- qe.h        2 Apr 2017 01:12:01 -0000       1.245
+++ qe.h        3 Apr 2017 08:33:57 -0000       1.246
@@ -208,6 +208,80 @@
 #define COLOR_TRANSPARENT  0
 #define QECOLOR_XOR        1
 
+#if 1  /* new composite style scheme */
+
+/* A qemacs style is a named set of attributes including:
+ * - colors for foreground and background
+ * - font style bits
+ * - font style size
+ *
+ * Styles are applied to text in successive phases:
+ * - the current syntax mode computes style numbers for each character
+ *   on the line. These nubers are stored into the high bits of the
+ *   32-bit code point.
+ * - these style numbers are then extracted into an array of 32-bit composite
+ *   style values.
+ * - the styles from the optional style buffer are combined into these style
+ *   values.
+ * - search matches and selection styles are applied if relevant.
+ * - the bidirectional algorithm is applied to compute the display order
+ * - sequences of code-point with the same compsite style are formed into
+ *   display units, ligatures are applied.
+ * - the composite style is expanded and converted into display attributes
+ *   to trace the display unit on the device surface
+ */
+
+/* Style numbers are limited to 8 bits, the default set has 27 entries */
+/* Composite styles are 32-bit values that specify
+ * - a style number
+ * - display attributes for underline, bold, blink
+ * - text and background colors as either palette numbers or 4096 rgb values
+ */
+
+#define QE_TERM_STYLE_BITS  32
+typedef uint32_t QETermStyle;
+#define QE_STYLE_NUM        0x00FF
+#define QE_STYLE_SEL        0x0100  /* special selection style (cumulative 
with another style) */
+#define QE_TERM_COMPOSITE   0x0200  /* special bit to indicate qe-term 
composite style */
+#define QE_TERM_UNDERLINE   0x0400
+#define QE_TERM_BOLD        0x0800
+#define QE_TERM_ITALIC      0x1000
+#define QE_TERM_BLINK       0x2000
+#define QE_TERM_BG_BITS     8
+#define QE_TERM_BG_SHIFT    0
+#define QE_TERM_FG_BITS     8
+#define QE_TERM_FG_SHIFT    16
+
+#else
+
+#define QE_TERM_STYLE_BITS  16
+typedef uint16_t QETermStyle;
+#define QE_STYLE_NUM        0x00FF
+#define QE_STYLE_SEL        0x0100  /* special selection style (cumulative 
with another style) */
+#define QE_TERM_COMPOSITE   0x0200  /* special bit to indicate qe-term 
composite style */
+#define QE_TERM_UNDERLINE   0x0400
+#define QE_TERM_BOLD        0x0800
+#define QE_TERM_ITALIC      0x1000
+#define QE_TERM_BLINK       0x2000
+#define QE_TERM_BG_BITS     4
+#define QE_TERM_BG_SHIFT    0
+#define QE_TERM_FG_BITS     4
+#define QE_TERM_FG_SHIFT    4
+
+#endif
+
+#define QE_TERM_DEF_FG      7
+#define QE_TERM_DEF_BG      0
+#define QE_TERM_BG_COLORS   (1 << QE_TERM_BG_BITS)
+#define QE_TERM_FG_COLORS   (1 << QE_TERM_FG_BITS)
+#define QE_TERM_BG_MASK     ((QE_TERM_BG_COLORS - 1) << QE_TERM_BG_SHIFT)
+#define QE_TERM_FG_MASK     ((QE_TERM_FG_COLORS - 1) << QE_TERM_FG_SHIFT)
+#define QE_TERM_MAKE_COLOR(fg, bg)  (((fg) << QE_TERM_FG_SHIFT) | ((bg) << 
QE_TERM_BG_SHIFT))
+#define QE_TERM_SET_FG(col, fg)  ((col) = ((col) & ~QE_TERM_FG_MASK) | ((fg) 
<< QE_TERM_FG_SHIFT))
+#define QE_TERM_SET_BG(col, bg)  ((col) = ((col) & ~QE_TERM_BG_MASK) | ((bg) 
<< QE_TERM_BG_SHIFT))
+#define QE_TERM_GET_FG(color)  (((color) & QE_TERM_FG_MASK) >> 
QE_TERM_FG_SHIFT)
+#define QE_TERM_GET_BG(color)  (((color) & QE_TERM_BG_MASK) >> 
QE_TERM_BG_SHIFT)
+
 typedef struct FindFileState FindFileState;
 
 FindFileState *find_file_open(const char *path, const char *pattern);
@@ -366,6 +440,11 @@
 void get_str(const char **pp, char *buf, int buf_size, const char *stop);
 int css_get_enum(const char *str, const char *enum_str);
 int to_hex(int key);
+
+extern QEColor const xterm_colors[];
+/* XXX: should have a more generic API with precomputed mapping scales */
+int qe_map_color(QEColor color, QEColor const *colors, int count, int *dist);
+
 void color_completion(CompleteState *cp);
 int css_define_color(const char *name, const char *value);
 int css_get_color(QEColor *color_ptr, const char *p);
@@ -787,6 +866,7 @@
  */
 typedef int (*GetColorizedLineFunc)(EditState *s,
                                     unsigned int *buf, int buf_size,
+                                    QETermStyle *sbuf,
                                     int offset, int *offsetp, int line_num);
 
 struct QEColorizeContext {
@@ -795,6 +875,7 @@
     int offset;
     int colorize_state;
     int state_only;
+    int combine_start, combine_stop; /* region for 
combine_static_colorized_line() */
 };
 
 /* colorize a line: this function modifies buf to set the char
@@ -1375,78 +1456,6 @@
     ModeDef *next;
 };
 
-#if 0  /* new composite style scheme */
-
-/* A qemacs style is a named set of attributes including:
- * - colors for foreground and background
- * - font style bits
- * - font style size
- *
- * Styles are applied to text in successive phases:
- * - the current syntax mode computes style numbers for each character
- *   on the line. These nubers are stored into the high bits of the
- *   32-bit code point.
- * - these style numbers are then extracted into an array of 32-bit composite
- *   style values.
- * - the styles from the optional style buffer are combined into these style
- *   values.
- * - search matches and selection styles are applied if relevant.
- * - the bidirectional algorithm is applied to compute the display order
- * - sequences of code-point with the same compsite style are formed into
- *   display units, ligatures are applied.
- * - the composite style is expanded and converted into display attributes
- *   to trace the display unit on the device surface
- */
-
-/* Style numbers are limited to 8 bits, the default set has 27 entries */
-/* Composite styles are 32-bit values that specify
- * - a style number
- * - display attributes for underline, bold, blink
- * - text and background colors as either palette numbers or 4096 rgb values
- */
-
-#define QE_TERM_STYLE_BITS  32
-#define QE_STYLE_NUM        0x00FF
-#define QE_STYLE_SEL        0x0100  /* special selection style (cumulative 
with another style) */
-#define QE_TERM_COMPOSITE   0x0200  /* special bit to indicate qe-term 
composite style */
-#define QE_TERM_UNDERLINE   0x0400
-#define QE_TERM_BOLD        0x0800
-#define QE_TERM_ITALIC      0x1000
-#define QE_TERM_BLINK       0x2000
-#define QE_TERM_BG_BITS     8
-#define QE_TERM_BG_SHIFT    0
-#define QE_TERM_FG_BITS     8
-#define QE_TERM_FG_SHIFT    16
-
-#else
-
-#define QE_TERM_STYLE_BITS  16
-#define QE_STYLE_NUM        0x00FF
-#define QE_STYLE_SEL        0x0100  /* special selection style (cumulative 
with another style) */
-#define QE_TERM_COMPOSITE   0x0200  /* special bit to indicate qe-term 
composite style */
-#define QE_TERM_UNDERLINE   0x0400
-#define QE_TERM_BOLD        0x0800
-#define QE_TERM_ITALIC      0x1000
-#define QE_TERM_BLINK       0x2000
-#define QE_TERM_BG_BITS     4
-#define QE_TERM_BG_SHIFT    0
-#define QE_TERM_FG_BITS     4
-#define QE_TERM_FG_SHIFT    4
-
-#endif
-
-#define QE_TERM_DEF_FG      7
-#define QE_TERM_DEF_BG      0
-#define QE_TERM_BG_COLORS   (1 << QE_TERM_BG_BITS)
-#define QE_TERM_FG_COLORS   (1 << QE_TERM_FG_BITS)
-#define QE_TERM_BG_MASK     ((QE_TERM_BG_COLORS - 1) << QE_TERM_BG_SHIFT)
-#define QE_TERM_FG_MASK     ((QE_TERM_FG_COLORS - 1) << QE_TERM_FG_SHIFT)
-#define QE_TERM_MAKE_COLOR(fg, bg)  (((fg) << QE_TERM_FG_SHIFT) | ((bg) << 
QE_TERM_BG_SHIFT))
-#define QE_TERM_SET_FG(col, fg)  ((col) = ((col) & ~(QE_TERM_FG_MASK)) | ((fg) 
<< QE_TERM_FG_SHIFT))
-#define QE_TERM_SET_BG(col, bg)  ((col) = ((col) & ~(QE_TERM_BG_MASK)) | ((bg) 
<< QE_TERM_BG_SHIFT))
-#define QE_TERM_GET_FG(color)  (((color) & QE_TERM_FG_MASK) >> 
QE_TERM_FG_SHIFT)
-#define QE_TERM_GET_BG(color)  (((color) & QE_TERM_BG_MASK) >> 
QE_TERM_BG_SHIFT)
-
 QEModeData *qe_create_buffer_mode_data(EditBuffer *b, ModeDef *m);
 void *qe_get_buffer_mode_data(EditBuffer *b, ModeDef *m, EditState *e);
 QEModeData *qe_create_window_mode_data(EditState *s, ModeDef *m);
@@ -1456,10 +1465,6 @@
 /* from tty.c */
 /* set from command line option to prevent GUI such as X11 */
 extern int force_tty;
-extern QEColor const xterm_colors[];
-/* XXX: should have a more generic API with precomputed mapping scales */
-int get_tty_color(QEColor color, QEColor const *colors, int count);
-int get_tty_style(const char *style);
 
 enum QEStyle {
 #define STYLE_DEF(constant, name, fg_color, bg_color, \
@@ -1690,10 +1695,12 @@
     short width;      /* fragment width */
     short ascent;
     short descent;
-    short style;      /* style index */
+    QETermStyle style; /* composite style */
     short line_index; /* index into line_buf */
     short len;        /* number of glyphs */
+#if QE_TERM_STYLE_BITS == 16
     short dummy;      /* alignment, must be set for CRC */
+#endif
 } TextFragment;
 
 #ifdef CONFIG_TINY
@@ -1807,13 +1814,6 @@
     *p |= style << STYLE_SHIFT;
 }
 
-static inline void clear_color(unsigned int *p, int count) {
-    int i;
-
-    for (i = 0; i < count; i++)
-        p[i] &= CHAR_MASK;
-}
-
 /* input.c */
 
 #define INPUTMETHOD_NOMATCH   (-1)
@@ -1925,10 +1925,8 @@
 void edit_detach(EditState *s);
 EditBuffer *check_buffer(EditBuffer **sp);
 EditState *check_window(EditState **sp);
-int get_glyph_width(QEditScreen *screen, 
-                    EditState *s, int style_index, int c);
-int get_line_height(QEditScreen *screen,
-                    EditState *s, int style_index);
+int get_glyph_width(QEditScreen *screen, EditState *s, int style, int c);
+int get_line_height(QEditScreen *screen, EditState *s, int style);
 void do_refresh(EditState *s);
 // should take direction argument
 void do_other_window(EditState *s);
@@ -1961,7 +1959,7 @@
 void do_write_file(EditState *s, const char *filename);
 void do_write_region(EditState *s, const char *filename);
 void isearch_colorize_matches(EditState *s, unsigned int *buf, int len,
-                              int offset);
+                              QETermStyle *sbuf, int offset);
 void do_isearch(EditState *s, int dir, int argval);
 void do_query_replace(EditState *s, const char *search_str,
                       const char *replace_str);
@@ -1982,9 +1980,8 @@
 
 void set_colorize_func(EditState *s, ColorizeFunc colorize_func);
 int generic_get_colorized_line(EditState *s, unsigned int *buf, int buf_size,
+                               QETermStyle *sbuf,
                                int offset, int *offsetp, int line_num);
-int combine_static_colorized_line(EditState *s, unsigned int *buf, 
-                                  int len, int offset);
 
 int do_delete_selection(EditState *s);
 void do_char(EditState *s, int key, int argval);
@@ -2085,7 +2082,7 @@
 int find_style_index(const char *name);
 QEStyleDef *find_style(const char *name);
 void style_completion(CompleteState *cp);
-void get_style(EditState *e, QEStyleDef *style, int style_index);
+void get_style(EditState *e, QEStyleDef *stp, int style);
 void style_property_completion(CompleteState *cp);
 int find_style_property(const char *name);
 void do_define_color(EditState *e, const char *name, const char *value);

Index: search.c
===================================================================
RCS file: /sources/qemacs/qemacs/search.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -b -r1.12 -r1.13
--- search.c    2 Jan 2017 11:39:07 -0000       1.12
+++ search.c    3 Apr 2017 08:33:57 -0000       1.13
@@ -557,7 +557,7 @@
 }
 
 void isearch_colorize_matches(EditState *s, unsigned int *buf, int len,
-                              int offset_start)
+                              QETermStyle *sbuf, int offset_start)
 {
     ISearchState *is = s->isearch_state;
     EditBuffer *b = s->b;
@@ -575,7 +575,7 @@
     while (eb_search(b, 1, is->search_flags, offset, offset_end,
                      is->search_u32, is->search_u32_len, NULL, NULL,
                      &found_offset, &found_end) > 0) {
-        int line, start, stop;
+        int line, start, stop, i;
 
         if (found_offset >= offset_end)
             break;
@@ -590,9 +590,8 @@
                 if (stop > len)
                     stop = len;
             }
-            if (start < stop) {
-                clear_color(buf + start, stop - start);
-                set_color(buf + start, buf + stop, QE_STYLE_SEARCH_HILITE);
+            for (i = start; i < stop; i++) {
+                sbuf[i] = QE_STYLE_SEARCH_HILITE;
             }
         }
         offset = found_end;

Index: shell.c
===================================================================
RCS file: /sources/qemacs/qemacs/shell.c,v
retrieving revision 1.121
retrieving revision 1.122
diff -u -b -r1.121 -r1.122
--- shell.c     2 Apr 2017 01:12:01 -0000       1.121
+++ shell.c     3 Apr 2017 08:33:57 -0000       1.122
@@ -631,7 +631,7 @@
             QEColor rgb = xterm_colors[color & 255];
 
             /* map color to qe-term palette */
-            s->fgcolor = get_tty_color(rgb, xterm_colors, QE_TERM_FG_COLORS);
+            s->fgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_FG_COLORS, 
NULL);
             s->nb_esc_params = 1;
         } else
         if (s->esc_params[1] == 2) {
@@ -642,7 +642,7 @@
                                 s->esc_params[4] & 255);
 
             /* map 24-bit colors to qe-term palette */
-            s->fgcolor = get_tty_color(rgb, xterm_colors, QE_TERM_FG_COLORS);
+            s->fgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_FG_COLORS, 
NULL);
             s->nb_esc_params = 1;
         }
         break;
@@ -654,7 +654,7 @@
             QEColor rgb = xterm_colors[color & 255];
 
             /* map color to qe-term palette */
-            s->bgcolor = get_tty_color(rgb, xterm_colors, QE_TERM_BG_COLORS);
+            s->bgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_BG_COLORS, 
NULL);
             s->nb_esc_params = 1;
         } else
         if (s->esc_params[1] == 2) {
@@ -665,7 +665,7 @@
                                 s->esc_params[4] & 255);
 
             /* map 24-bit colors to qe-term palette */
-            s->bgcolor = get_tty_color(rgb, xterm_colors, QE_TERM_BG_COLORS);
+            s->bgcolor = qe_map_color(rgb, xterm_colors, QE_TERM_BG_COLORS, 
NULL);
             s->nb_esc_params = 1;
         }
         break;
@@ -2359,7 +2359,7 @@
     /* detect match lines for known languages and colorize accordingly */
     static char filename[MAX_FILENAME_SIZE];
     ModeDef *m;
-    int i = 0, len, stop = n;
+    int i = 0, len;
 
     if (cp->colorize_state) {
         cp->colorize_state -= 1;
@@ -2402,14 +2402,14 @@
          * if the current directory of the shell process changes and
          * is not possible for remote shells.
          */
+        /* XXX: filename based mode should be stored as a number into 
cp->colorize_state */
         if (i < n && (m = qe_find_mode_filename(filename, MODEF_SYNTAX)) != 
NULL) {
             cp->colorize_state = 0;
             m->colorize_func(cp, str + i, n - i, m);
-            stop = i;
+            cp->combine_stop = i;
         }
         cp->colorize_state = 0;
     }
-    combine_static_colorized_line(cp->s, str, stop, cp->offset);
 }
 
 /* shell mode specific commands */

Index: tty.c
===================================================================
RCS file: /sources/qemacs/qemacs/tty.c,v
retrieving revision 1.75
retrieving revision 1.76
diff -u -b -r1.75 -r1.76
--- tty.c       2 Apr 2017 01:12:01 -0000       1.75
+++ tty.c       3 Apr 2017 08:33:57 -0000       1.76
@@ -37,16 +37,16 @@
 typedef uint64_t TTYChar;
 /* TTY composite style has 8 bit color number for FG and BG plus attribute 
bits */
 #define TTY_STYLE_BITS      32
-#define TTYCHAR(ch,fg,bg)   ((uint32_t)(ch) | ((uint64_t)((fg) | ((bg) << 16)) 
<< 32))
-#define TTYCHAR2(ch,col)    ((uint32_t)(ch) | ((uint64_t)(col) << 32))
-#define TTYCHAR_GETCH(cc)   ((uint32_t)(cc))
-#define TTYCHAR_GETCOL(cc)  ((uint32_t)((cc) >> 32))
-#define TTYCHAR_GETFG(cc)   ((uint32_t)((cc) >> 32) & 0xFF)
-#define TTYCHAR_GETBG(cc)   ((uint32_t)((cc) >> (32 + 16)) & 0xFF)
-#define TTYCHAR_DEFAULT     TTYCHAR(' ', 7, 0)
-#define TTYCHAR_COMB        0x200000
-#define TTYCHAR_BAD         0xFFFD
-#define TTYCHAR_NONE        0xFFFFFFFF
+#define TTY_CHAR(ch,fg,bg)    ((uint32_t)(ch) | ((uint64_t)((fg) | ((bg) << 
16)) << 32))
+#define TTY_CHAR2(ch,col)     ((uint32_t)(ch) | ((uint64_t)(col) << 32))
+#define TTY_CHAR_GET_CH(cc)   ((uint32_t)(cc))
+#define TTY_CHAR_GET_COL(cc)  ((uint32_t)((cc) >> 32))
+#define TTY_CHAR_GET_FG(cc)   ((uint32_t)((cc) >> 32) & 0xFF)
+#define TTY_CHAR_GET_BG(cc)   ((uint32_t)((cc) >> (32 + 16)) & 0xFF)
+#define TTY_CHAR_DEFAULT      TTY_CHAR(' ', 7, 0)
+#define TTY_CHAR_COMB         0x200000
+#define TTY_CHAR_BAD          0xFFFD
+#define TTY_CHAR_NONE         0xFFFFFFFF
 #define TTY_BOLD            0x0100
 #define TTY_UNDERLINE       0x0200
 #define TTY_BLINK           0x0400
@@ -56,15 +56,15 @@
 typedef uint32_t TTYChar;
 /* TTY composite style has 4 bit color number for FG and BG plus attribute 
bits */
 #define TTY_STYLE_BITS      16
-#define TTYCHAR(ch,fg,bg)   ((uint32_t)(ch) | ((uint32_t)((fg) | ((bg) << 12)) 
<< 16))
-#define TTYCHAR2(ch,col)    ((uint32_t)(ch) | ((uint32_t)(col) << 16))
-#define TTYCHAR_GETCH(cc)   ((cc) & 0xFFFF)
-#define TTYCHAR_GETCOL(cc)  (((cc) >> 16) & 0xFFFF)
-#define TTYCHAR_GETFG(cc)   (((cc) >> 16) & 0xFF)
-#define TTYCHAR_GETBG(cc)   (((cc) >> (16 + 8)) & 0xFF)
-#define TTYCHAR_DEFAULT     TTYCHAR(' ', 7, 0)
-#define TTYCHAR_BAD         0xFFFD
-#define TTYCHAR_NONE        0xFFFF
+#define TTY_CHAR(ch,fg,bg)    ((uint32_t)(ch) | ((uint32_t)((fg) | ((bg) << 
12)) << 16))
+#define TTY_CHAR2(ch,col)     ((uint32_t)(ch) | ((uint32_t)(col) << 16))
+#define TTY_CHAR_GET_CH(cc)   ((cc) & 0xFFFF)
+#define TTY_CHAR_GET_COL(cc)  (((cc) >> 16) & 0xFFFF)
+#define TTY_CHAR_GET_FG(cc)   (((cc) >> 16) & 0xFF)
+#define TTY_CHAR_GET_BG(cc)   (((cc) >> (16 + 8)) & 0xFF)
+#define TTY_CHAR_DEFAULT      TTY_CHAR(' ', 7, 0)
+#define TTY_CHAR_BAD          0xFFFD
+#define TTY_CHAR_NONE         0xFFFF
 #define TTY_BOLD            0x0100
 #define TTY_UNDERLINE       0x0200
 #define TTY_BLINK           0x0400
@@ -366,7 +366,7 @@
     /* Erase shadow buffer to impossible value */
     memset(ts->screen + count, 0xFF, size + sizeof(TTYChar));
     /* Fill screen buffer with black spaces */
-    tc = TTYCHAR_DEFAULT;
+    tc = TTY_CHAR_DEFAULT;
     for (i = 0; i < count; i++) {
         ts->screen[i] = tc;
     }
@@ -634,370 +634,6 @@
     }
 }
 
-#if 0
-static QEColor const tty_full_colors[8] = {
-    QERGB(0x00, 0x00, 0x00),
-    QERGB(0xff, 0x00, 0x00),
-    QERGB(0x00, 0xff, 0x00),
-    QERGB(0xff, 0xff, 0x00),
-    QERGB(0x00, 0x00, 0xff),
-    QERGB(0xff, 0x00, 0xff),
-    QERGB(0x00, 0xff, 0xff),
-    QERGB(0xff, 0xff, 0xff),
-};
-#endif
-
-QEColor const xterm_colors[256] = {
-    QERGB(0x00, 0x00, 0x00),
-    QERGB(0xbb, 0x00, 0x00),
-    QERGB(0x00, 0xbb, 0x00),
-    QERGB(0xbb, 0xbb, 0x00),
-    QERGB(0x00, 0x00, 0xbb),
-    QERGB(0xbb, 0x00, 0xbb),
-    QERGB(0x00, 0xbb, 0xbb),
-    QERGB(0xbb, 0xbb, 0xbb),
-
-    QERGB(0x55, 0x55, 0x55),
-    QERGB(0xff, 0x55, 0x55),
-    QERGB(0x55, 0xff, 0x55),
-    QERGB(0xff, 0xff, 0x55),
-    QERGB(0x55, 0x55, 0xff),
-    QERGB(0xff, 0x55, 0xff),
-    QERGB(0x55, 0xff, 0xff),
-    QERGB(0xff, 0xff, 0xff),
-#if 1
-    /* Extended color palette for xterm 256 color mode */
-
-    /* From XFree86: xc/programs/xterm/256colres.h,
-     * v 1.5 2002/10/05 17:57:11 dickey Exp
-     */
-
-    /* 216 entry RGB cube with axes 0,95,135,175,215,255 */
-    /* followed by 24 entry grey scale 8,18..238 */
-    QERGB(0x00, 0x00, 0x00),  /* 16: Grey0 */
-    QERGB(0x00, 0x00, 0x5f),  /* 17: NavyBlue */
-    QERGB(0x00, 0x00, 0x87),  /* 18: DarkBlue */
-    QERGB(0x00, 0x00, 0xaf),  /* 19: Blue3 */
-    QERGB(0x00, 0x00, 0xd7),  /* 20: Blue3 */
-    QERGB(0x00, 0x00, 0xff),  /* 21: Blue1 */
-    QERGB(0x00, 0x5f, 0x00),  /* 22: DarkGreen */
-    QERGB(0x00, 0x5f, 0x5f),  /* 23: DeepSkyBlue4 */
-    QERGB(0x00, 0x5f, 0x87),  /* 24: DeepSkyBlue4 */
-    QERGB(0x00, 0x5f, 0xaf),  /* 25: DeepSkyBlue4 */
-    QERGB(0x00, 0x5f, 0xd7),  /* 26: DodgerBlue3 */
-    QERGB(0x00, 0x5f, 0xff),  /* 27: DodgerBlue2 */
-    QERGB(0x00, 0x87, 0x00),  /* 28: Green4 */
-    QERGB(0x00, 0x87, 0x5f),  /* 29: SpringGreen4 */
-    QERGB(0x00, 0x87, 0x87),  /* 30: Turquoise4 */
-    QERGB(0x00, 0x87, 0xaf),  /* 31: DeepSkyBlue3 */
-    QERGB(0x00, 0x87, 0xd7),  /* 32: DeepSkyBlue3 */
-    QERGB(0x00, 0x87, 0xff),  /* 33: DodgerBlue1 */
-    QERGB(0x00, 0xaf, 0x00),  /* 34: Green3 */
-    QERGB(0x00, 0xaf, 0x5f),  /* 35: SpringGreen3 */
-    QERGB(0x00, 0xaf, 0x87),  /* 36: DarkCyan */
-    QERGB(0x00, 0xaf, 0xaf),  /* 37: LightSeaGreen */
-    QERGB(0x00, 0xaf, 0xd7),  /* 38: DeepSkyBlue2 */
-    QERGB(0x00, 0xaf, 0xff),  /* 39: DeepSkyBlue1 */
-    QERGB(0x00, 0xd7, 0x00),  /* 40: Green3 */
-    QERGB(0x00, 0xd7, 0x5f),  /* 41: SpringGreen3 */
-    QERGB(0x00, 0xd7, 0x87),  /* 42: SpringGreen2 */
-    QERGB(0x00, 0xd7, 0xaf),  /* 43: Cyan3 */
-    QERGB(0x00, 0xd7, 0xd7),  /* 44: DarkTurquoise */
-    QERGB(0x00, 0xd7, 0xff),  /* 45: Turquoise2 */
-    QERGB(0x00, 0xff, 0x00),  /* 46: Green1 */
-    QERGB(0x00, 0xff, 0x5f),  /* 47: SpringGreen2 */
-    QERGB(0x00, 0xff, 0x87),  /* 48: SpringGreen1 */
-    QERGB(0x00, 0xff, 0xaf),  /* 49: MediumSpringGreen */
-    QERGB(0x00, 0xff, 0xd7),  /* 50: Cyan2 */
-    QERGB(0x00, 0xff, 0xff),  /* 51: Cyan1 */
-    QERGB(0x5f, 0x00, 0x00),  /* 52: DarkRed */
-    QERGB(0x5f, 0x00, 0x5f),  /* 53: DeepPink4 */
-    QERGB(0x5f, 0x00, 0x87),  /* 54: Purple4 */
-    QERGB(0x5f, 0x00, 0xaf),  /* 55: Purple4 */
-    QERGB(0x5f, 0x00, 0xd7),  /* 56: Purple3 */
-    QERGB(0x5f, 0x00, 0xff),  /* 57: BlueViolet */
-    QERGB(0x5f, 0x5f, 0x00),  /* 58: Orange4 */
-    QERGB(0x5f, 0x5f, 0x5f),  /* 59: Grey37 */
-    QERGB(0x5f, 0x5f, 0x87),  /* 60: MediumPurple4 */
-    QERGB(0x5f, 0x5f, 0xaf),  /* 61: SlateBlue3 */
-    QERGB(0x5f, 0x5f, 0xd7),  /* 62: SlateBlue3 */
-    QERGB(0x5f, 0x5f, 0xff),  /* 63: RoyalBlue1 */
-    QERGB(0x5f, 0x87, 0x00),  /* 64: Chartreuse4 */
-    QERGB(0x5f, 0x87, 0x5f),  /* 65: DarkSeaGreen4 */
-    QERGB(0x5f, 0x87, 0x87),  /* 66: PaleTurquoise4 */
-    QERGB(0x5f, 0x87, 0xaf),  /* 67: SteelBlue */
-    QERGB(0x5f, 0x87, 0xd7),  /* 68: SteelBlue3 */
-    QERGB(0x5f, 0x87, 0xff),  /* 69: CornflowerBlue */
-    QERGB(0x5f, 0xaf, 0x00),  /* 70: Chartreuse3 */
-    QERGB(0x5f, 0xaf, 0x5f),  /* 71: DarkSeaGreen4 */
-    QERGB(0x5f, 0xaf, 0x87),  /* 72: CadetBlue */
-    QERGB(0x5f, 0xaf, 0xaf),  /* 73: CadetBlue */
-    QERGB(0x5f, 0xaf, 0xd7),  /* 74: SkyBlue3 */
-    QERGB(0x5f, 0xaf, 0xff),  /* 75: SteelBlue1 */
-    QERGB(0x5f, 0xd7, 0x00),  /* 76: Chartreuse3 */
-    QERGB(0x5f, 0xd7, 0x5f),  /* 77: PaleGreen3 */
-    QERGB(0x5f, 0xd7, 0x87),  /* 78: SeaGreen3 */
-    QERGB(0x5f, 0xd7, 0xaf),  /* 79: Aquamarine3 */
-    QERGB(0x5f, 0xd7, 0xd7),  /* 80: MediumTurquoise */
-    QERGB(0x5f, 0xd7, 0xff),  /* 81: SteelBlue1 */
-    QERGB(0x5f, 0xff, 0x00),  /* 82: Chartreuse2 */
-    QERGB(0x5f, 0xff, 0x5f),  /* 83: SeaGreen2 */
-    QERGB(0x5f, 0xff, 0x87),  /* 84: SeaGreen1 */
-    QERGB(0x5f, 0xff, 0xaf),  /* 85: SeaGreen1 */
-    QERGB(0x5f, 0xff, 0xd7),  /* 86: Aquamarine1 */
-    QERGB(0x5f, 0xff, 0xff),  /* 87: DarkSlateGray2 */
-    QERGB(0x87, 0x00, 0x00),  /* 88: DarkRed */
-    QERGB(0x87, 0x00, 0x5f),  /* 89: DeepPink4 */
-    QERGB(0x87, 0x00, 0x87),  /* 90: DarkMagenta */
-    QERGB(0x87, 0x00, 0xaf),  /* 91: DarkMagenta */
-    QERGB(0x87, 0x00, 0xd7),  /* 92: DarkViolet */
-    QERGB(0x87, 0x00, 0xff),  /* 93: Purple */
-    QERGB(0x87, 0x5f, 0x00),  /* 94: Orange4 */
-    QERGB(0x87, 0x5f, 0x5f),  /* 95: LightPink4 */
-    QERGB(0x87, 0x5f, 0x87),  /* 96: Plum4 */
-    QERGB(0x87, 0x5f, 0xaf),  /* 97: MediumPurple3 */
-    QERGB(0x87, 0x5f, 0xd7),  /* 98: MediumPurple3 */
-    QERGB(0x87, 0x5f, 0xff),  /* 99: SlateBlue1 */
-    QERGB(0x87, 0x87, 0x00),  /* 100: Yellow4 */
-    QERGB(0x87, 0x87, 0x5f),  /* 101: Wheat4 */
-    QERGB(0x87, 0x87, 0x87),  /* 102: Grey53 */
-    QERGB(0x87, 0x87, 0xaf),  /* 103: LightSlateGrey */
-    QERGB(0x87, 0x87, 0xd7),  /* 104: MediumPurple */
-    QERGB(0x87, 0x87, 0xff),  /* 105: LightSlateBlue */
-    QERGB(0x87, 0xaf, 0x00),  /* 106: Yellow4 */
-    QERGB(0x87, 0xaf, 0x5f),  /* 107: DarkOliveGreen3 */
-    QERGB(0x87, 0xaf, 0x87),  /* 108: DarkSeaGreen */
-    QERGB(0x87, 0xaf, 0xaf),  /* 109: LightSkyBlue3 */
-    QERGB(0x87, 0xaf, 0xd7),  /* 110: LightSkyBlue3 */
-    QERGB(0x87, 0xaf, 0xff),  /* 111: SkyBlue2 */
-    QERGB(0x87, 0xd7, 0x00),  /* 112: Chartreuse2 */
-    QERGB(0x87, 0xd7, 0x5f),  /* 113: DarkOliveGreen3 */
-    QERGB(0x87, 0xd7, 0x87),  /* 114: PaleGreen3 */
-    QERGB(0x87, 0xd7, 0xaf),  /* 115: DarkSeaGreen3 */
-    QERGB(0x87, 0xd7, 0xd7),  /* 116: DarkSlateGray3 */
-    QERGB(0x87, 0xd7, 0xff),  /* 117: SkyBlue1 */
-    QERGB(0x87, 0xff, 0x00),  /* 118: Chartreuse1 */
-    QERGB(0x87, 0xff, 0x5f),  /* 119: LightGreen */
-    QERGB(0x87, 0xff, 0x87),  /* 120: LightGreen */
-    QERGB(0x87, 0xff, 0xaf),  /* 121: PaleGreen1 */
-    QERGB(0x87, 0xff, 0xd7),  /* 122: Aquamarine1 */
-    QERGB(0x87, 0xff, 0xff),  /* 123: DarkSlateGray1 */
-    QERGB(0xaf, 0x00, 0x00),  /* 124: Red3 */
-    QERGB(0xaf, 0x00, 0x5f),  /* 125: DeepPink4 */
-    QERGB(0xaf, 0x00, 0x87),  /* 126: MediumVioletRed */
-    QERGB(0xaf, 0x00, 0xaf),  /* 127: Magenta3 */
-    QERGB(0xaf, 0x00, 0xd7),  /* 128: DarkViolet */
-    QERGB(0xaf, 0x00, 0xff),  /* 129: Purple */
-    QERGB(0xaf, 0x5f, 0x00),  /* 130: DarkOrange3 */
-    QERGB(0xaf, 0x5f, 0x5f),  /* 131: IndianRed */
-    QERGB(0xaf, 0x5f, 0x87),  /* 132: HotPink3 */
-    QERGB(0xaf, 0x5f, 0xaf),  /* 133: MediumOrchid3 */
-    QERGB(0xaf, 0x5f, 0xd7),  /* 134: MediumOrchid */
-    QERGB(0xaf, 0x5f, 0xff),  /* 135: MediumPurple2 */
-    QERGB(0xaf, 0x87, 0x00),  /* 136: DarkGoldenrod */
-    QERGB(0xaf, 0x87, 0x5f),  /* 137: LightSalmon3 */
-    QERGB(0xaf, 0x87, 0x87),  /* 138: RosyBrown */
-    QERGB(0xaf, 0x87, 0xaf),  /* 139: Grey63 */
-    QERGB(0xaf, 0x87, 0xd7),  /* 140: MediumPurple2 */
-    QERGB(0xaf, 0x87, 0xff),  /* 141: MediumPurple1 */
-    QERGB(0xaf, 0xaf, 0x00),  /* 142: Gold3 */
-    QERGB(0xaf, 0xaf, 0x5f),  /* 143: DarkKhaki */
-    QERGB(0xaf, 0xaf, 0x87),  /* 144: NavajoWhite3 */
-    QERGB(0xaf, 0xaf, 0xaf),  /* 145: Grey69 */
-    QERGB(0xaf, 0xaf, 0xd7),  /* 146: LightSteelBlue3 */
-    QERGB(0xaf, 0xaf, 0xff),  /* 147: LightSteelBlue */
-    QERGB(0xaf, 0xd7, 0x00),  /* 148: Yellow3 */
-    QERGB(0xaf, 0xd7, 0x5f),  /* 149: DarkOliveGreen3 */
-    QERGB(0xaf, 0xd7, 0x87),  /* 150: DarkSeaGreen3 */
-    QERGB(0xaf, 0xd7, 0xaf),  /* 151: DarkSeaGreen2 */
-    QERGB(0xaf, 0xd7, 0xd7),  /* 152: LightCyan3 */
-    QERGB(0xaf, 0xd7, 0xff),  /* 153: LightSkyBlue1 */
-    QERGB(0xaf, 0xff, 0x00),  /* 154: GreenYellow */
-    QERGB(0xaf, 0xff, 0x5f),  /* 155: DarkOliveGreen2 */
-    QERGB(0xaf, 0xff, 0x87),  /* 156: PaleGreen1 */
-    QERGB(0xaf, 0xff, 0xaf),  /* 157: DarkSeaGreen2 */
-    QERGB(0xaf, 0xff, 0xd7),  /* 158: DarkSeaGreen1 */
-    QERGB(0xaf, 0xff, 0xff),  /* 159: PaleTurquoise1 */
-    QERGB(0xd7, 0x00, 0x00),  /* 160: Red3 */
-    QERGB(0xd7, 0x00, 0x5f),  /* 161: DeepPink3 */
-    QERGB(0xd7, 0x00, 0x87),  /* 162: DeepPink3 */
-    QERGB(0xd7, 0x00, 0xaf),  /* 163: Magenta3 */
-    QERGB(0xd7, 0x00, 0xd7),  /* 164: Magenta3 */
-    QERGB(0xd7, 0x00, 0xff),  /* 165: Magenta2 */
-    QERGB(0xd7, 0x5f, 0x00),  /* 166: DarkOrange3 */
-    QERGB(0xd7, 0x5f, 0x5f),  /* 167: IndianRed */
-    QERGB(0xd7, 0x5f, 0x87),  /* 168: HotPink3 */
-    QERGB(0xd7, 0x5f, 0xaf),  /* 169: HotPink2 */
-    QERGB(0xd7, 0x5f, 0xd7),  /* 170: Orchid */
-    QERGB(0xd7, 0x5f, 0xff),  /* 171: MediumOrchid1 */
-    QERGB(0xd7, 0x87, 0x00),  /* 172: Orange3 */
-    QERGB(0xd7, 0x87, 0x5f),  /* 173: LightSalmon3 */
-    QERGB(0xd7, 0x87, 0x87),  /* 174: LightPink3 */
-    QERGB(0xd7, 0x87, 0xaf),  /* 175: Pink3 */
-    QERGB(0xd7, 0x87, 0xd7),  /* 176: Plum3 */
-    QERGB(0xd7, 0x87, 0xff),  /* 177: Violet */
-    QERGB(0xd7, 0xaf, 0x00),  /* 178: Gold3 */
-    QERGB(0xd7, 0xaf, 0x5f),  /* 179: LightGoldenrod3 */
-    QERGB(0xd7, 0xaf, 0x87),  /* 180: Tan */
-    QERGB(0xd7, 0xaf, 0xaf),  /* 181: MistyRose3 */
-    QERGB(0xd7, 0xaf, 0xd7),  /* 182: Thistle3 */
-    QERGB(0xd7, 0xaf, 0xff),  /* 183: Plum2 */
-    QERGB(0xd7, 0xd7, 0x00),  /* 184: Yellow3 */
-    QERGB(0xd7, 0xd7, 0x5f),  /* 185: Khaki3 */
-    QERGB(0xd7, 0xd7, 0x87),  /* 186: LightGoldenrod2 */
-    QERGB(0xd7, 0xd7, 0xaf),  /* 187: LightYellow3 */
-    QERGB(0xd7, 0xd7, 0xd7),  /* 188: Grey84 */
-    QERGB(0xd7, 0xd7, 0xff),  /* 189: LightSteelBlue1 */
-    QERGB(0xd7, 0xff, 0x00),  /* 190: Yellow2 */
-    QERGB(0xd7, 0xff, 0x5f),  /* 191: DarkOliveGreen1 */
-    QERGB(0xd7, 0xff, 0x87),  /* 192: DarkOliveGreen1 */
-    QERGB(0xd7, 0xff, 0xaf),  /* 193: DarkSeaGreen1 */
-    QERGB(0xd7, 0xff, 0xd7),  /* 194: Honeydew2 */
-    QERGB(0xd7, 0xff, 0xff),  /* 195: LightCyan1 */
-    QERGB(0xff, 0x00, 0x00),  /* 196: Red1 */
-    QERGB(0xff, 0x00, 0x5f),  /* 197: DeepPink2 */
-    QERGB(0xff, 0x00, 0x87),  /* 198: DeepPink1 */
-    QERGB(0xff, 0x00, 0xaf),  /* 199: DeepPink1 */
-    QERGB(0xff, 0x00, 0xd7),  /* 200: Magenta2 */
-    QERGB(0xff, 0x00, 0xff),  /* 201: Magenta1 */
-    QERGB(0xff, 0x5f, 0x00),  /* 202: OrangeRed1 */
-    QERGB(0xff, 0x5f, 0x5f),  /* 203: IndianRed1 */
-    QERGB(0xff, 0x5f, 0x87),  /* 204: IndianRed1 */
-    QERGB(0xff, 0x5f, 0xaf),  /* 205: HotPink */
-    QERGB(0xff, 0x5f, 0xd7),  /* 206: HotPink */
-    QERGB(0xff, 0x5f, 0xff),  /* 207: MediumOrchid1 */
-    QERGB(0xff, 0x87, 0x00),  /* 208: DarkOrange */
-    QERGB(0xff, 0x87, 0x5f),  /* 209: Salmon1 */
-    QERGB(0xff, 0x87, 0x87),  /* 210: LightCoral */
-    QERGB(0xff, 0x87, 0xaf),  /* 211: PaleVioletRed1 */
-    QERGB(0xff, 0x87, 0xd7),  /* 212: Orchid2 */
-    QERGB(0xff, 0x87, 0xff),  /* 213: Orchid1 */
-    QERGB(0xff, 0xaf, 0x00),  /* 214: Orange1 */
-    QERGB(0xff, 0xaf, 0x5f),  /* 215: SandyBrown */
-    QERGB(0xff, 0xaf, 0x87),  /* 216: LightSalmon1 */
-    QERGB(0xff, 0xaf, 0xaf),  /* 217: LightPink1 */
-    QERGB(0xff, 0xaf, 0xd7),  /* 218: Pink1 */
-    QERGB(0xff, 0xaf, 0xff),  /* 219: Plum1 */
-    QERGB(0xff, 0xd7, 0x00),  /* 220: Gold1 */
-    QERGB(0xff, 0xd7, 0x5f),  /* 221: LightGoldenrod2 */
-    QERGB(0xff, 0xd7, 0x87),  /* 222: LightGoldenrod2 */
-    QERGB(0xff, 0xd7, 0xaf),  /* 223: NavajoWhite1 */
-    QERGB(0xff, 0xd7, 0xd7),  /* 224: MistyRose1 */
-    QERGB(0xff, 0xd7, 0xff),  /* 225: Thistle1 */
-    QERGB(0xff, 0xff, 0x00),  /* 226: Yellow1 */
-    QERGB(0xff, 0xff, 0x5f),  /* 227: LightGoldenrod1 */
-    QERGB(0xff, 0xff, 0x87),  /* 228: Khaki1 */
-    QERGB(0xff, 0xff, 0xaf),  /* 229: Wheat1 */
-    QERGB(0xff, 0xff, 0xd7),  /* 230: Cornsilk1 */
-    QERGB(0xff, 0xff, 0xff),  /* 231: Grey100 */
-    QERGB(0x08, 0x08, 0x08),  /* 232: Grey3 */
-    QERGB(0x12, 0x12, 0x12),  /* 233: Grey7 */
-    QERGB(0x1c, 0x1c, 0x1c),  /* 234: Grey11 */
-    QERGB(0x26, 0x26, 0x26),  /* 235: Grey15 */
-    QERGB(0x30, 0x30, 0x30),  /* 236: Grey19 */
-    QERGB(0x3a, 0x3a, 0x3a),  /* 237: Grey23 */
-    QERGB(0x44, 0x44, 0x44),  /* 238: Grey27 */
-    QERGB(0x4e, 0x4e, 0x4e),  /* 239: Grey30 */
-    QERGB(0x58, 0x58, 0x58),  /* 240: Grey35 */
-    QERGB(0x62, 0x62, 0x62),  /* 241: Grey39 */
-    QERGB(0x6c, 0x6c, 0x6c),  /* 242: Grey42 */
-    QERGB(0x76, 0x76, 0x76),  /* 243: Grey46 */
-    QERGB(0x80, 0x80, 0x80),  /* 244: Grey50 */
-    QERGB(0x8a, 0x8a, 0x8a),  /* 245: Grey54 */
-    QERGB(0x94, 0x94, 0x94),  /* 246: Grey58 */
-    QERGB(0x9e, 0x9e, 0x9e),  /* 247: Grey62 */
-    QERGB(0xa8, 0xa8, 0xa8),  /* 248: Grey66 */
-    QERGB(0xb2, 0xb2, 0xb2),  /* 249: Grey70 */
-    QERGB(0xbc, 0xbc, 0xbc),  /* 250: Grey74 */
-    QERGB(0xc6, 0xc6, 0xc6),  /* 251: Grey78 */
-    QERGB(0xd0, 0xd0, 0xd0),  /* 252: Grey82 */
-    QERGB(0xda, 0xda, 0xda),  /* 253: Grey85 */
-    QERGB(0xe4, 0xe4, 0xe4),  /* 254: Grey89 */
-    QERGB(0xee, 0xee, 0xee),  /* 255: Grey93 */
-#endif
-};
-
-static unsigned char const scale_cube[256] = {
-    /* This array is used for mapping rgb colors to the standard palette */
-    /* 216 entry RGB cube with axes 0,95,135,175,215,255 */
-#define REP5(x)   (x), (x), (x), (x), (x)
-#define REP10(x)  REP5(x), REP5(x)
-#define REP20(x)  REP10(x), REP10(x)
-#define REP40(x)  REP20(x), REP20(x)
-#define REP25(x)  REP5(x), REP5(x), REP5(x), REP5(x), REP5(x)
-#define REP47(x)  REP10(x), REP10(x), REP10(x), REP10(x), REP5(x), (x), (x)
-    REP47(0), REP47(1), REP20(1), REP40(2), REP40(3), REP40(4), REP20(5), 5
-};
-
-static unsigned char const scale_grey[256] = {
-    /* This array is used for mapping gray levels to the standard palette */
-    /* 232..255: 24 entry grey scale 8,18..238 */
-    16, 16, 16, 16,
-    REP10(232), REP10(233), REP10(234), REP10(235),
-    REP10(236), REP10(237), REP10(238), REP10(239), 
-    REP10(240), REP10(241), REP10(242), REP10(243), 
-    REP10(244), REP10(245), REP10(246), REP10(247),
-    REP10(248), REP10(249), REP10(250), REP10(251),
-    REP10(252), REP10(253), REP10(254), REP10(255),
-    255, 255, 255,
-    231, 231, 231, 231, 231, 231, 231, 231, 231
-};
-
-static inline int color_dist(QEColor c1, QEColor c2) {
-    /* using casts because c1 and c2 are unsigned */
-#if 0
-    /* using a quick approximation to give green extra weight */
-    return      abs((int)((c1 >>  0) & 0xff) - (int)((c2 >>  0) & 0xff)) +
-            2 * abs((int)((c1 >>  8) & 0xff) - (int)((c2 >>  8) & 0xff)) +
-                abs((int)((c1 >> 16) & 0xff) - (int)((c2 >> 16) & 0xff));
-#else
-    /* using different weights to R, G, B according to luminance levels */
-    return  11 * abs((int)((c1 >>  0) & 0xff) - (int)((c2 >>  0) & 0xff)) +
-            59 * abs((int)((c1 >>  8) & 0xff) - (int)((c2 >>  8) & 0xff)) +
-            30 * abs((int)((c1 >> 16) & 0xff) - (int)((c2 >> 16) & 0xff));
-#endif
-}
-
-/* XXX: should have a more generic API with precomputed mapping scales */
-int get_tty_color(QEColor color, QEColor const *colors, int count)
-{
-    int i, cmin, dmin, d;
-
-    dmin = INT_MAX;
-    cmin = 0;
-    for (i = 0; i < count; i++) {
-        d = color_dist(color, colors[i]);
-        if (d < dmin) {
-            cmin = i;
-            dmin = d;
-        }
-    }
-#if 1
-    if (dmin > 0 && count > 16) {
-        unsigned int r = (color >> 16) & 0xff;
-        unsigned int g = (color >>  8) & 0xff;
-        unsigned int b = (color >>  0) & 0xff;
-        if (r == g && g == b) {
-            i = scale_grey[r];
-            d = color_dist(color, colors[i]);
-            if (d < dmin) {
-                cmin = i;
-                dmin = d;
-            }
-        } else {
-            /* XXX: should use more precise projection */
-            i = scale_cube[r] * 36 + scale_cube[g] * 6 + scale_cube[b];
-            d = color_dist(color, colors[i]);
-            if (d < dmin) {
-                cmin = i;
-                dmin = d;
-            }
-        }
-    }
-#endif
-    return cmin;
-}
-
 static void tty_term_fill_rectangle(QEditScreen *s,
                                     int x1, int y1, int w, int h, QEColor 
color)
 {
@@ -1014,17 +650,17 @@
         for (y = y1; y < y2; y++) {
             ts->line_updated[y] = 1;
             for (x = x1; x < x2; x++) {
-                *ptr ^= TTYCHAR(0, 7, 7);
+                *ptr ^= TTY_CHAR(0, 7, 7);
                 ptr++;
             }
             ptr += wrap;
         }
     } else {
-        bgcolor = get_tty_color(color, ts->term_colors, 
ts->term_bg_colors_count);
+        bgcolor = qe_map_color(color, ts->term_colors, 
ts->term_bg_colors_count, NULL);
         for (y = y1; y < y2; y++) {
             ts->line_updated[y] = 1;
             for (x = x1; x < x2; x++) {
-                *ptr = TTYCHAR(' ', 7, bgcolor);
+                *ptr = TTY_CHAR(' ', 7, bgcolor);
                 ptr++;
             }
             ptr += wrap;
@@ -1083,7 +719,7 @@
     unsigned int *ip;
     for (ip = ts->comb_cache; *ip; ip += *ip & 0xFFFF) {
         if (*ip == len + 1U && !memcmp(ip + 1, seq, len * sizeof(*ip))) {
-            return TTYCHAR_COMB + (ip - ts->comb_cache);
+            return TTY_CHAR_COMB + (ip - ts->comb_cache);
         }
     }
     for (ip = ts->comb_cache; *ip; ip += *ip & 0xFFFF) {
@@ -1098,13 +734,13 @@
     }
     if (*ip == 0) {
         if ((ip - ts->comb_cache) + len + 1 >= countof(ts->comb_cache)) {
-            return TTYCHAR_BAD;
+            return TTY_CHAR_BAD;
         }
         ip[len + 1] = 0;
     }
     *ip = len + 1;
     memcpy(ip + 1, seq, len * sizeof(*ip));
-    return TTYCHAR_COMB + (ip - ts->comb_cache);
+    return TTY_CHAR_COMB + (ip - ts->comb_cache);
 }
 
 static void comb_cache_clean(TTYState *ts, const TTYChar *screen, int len) {
@@ -1119,9 +755,9 @@
     }
     ip = ts->comb_cache;
     for (i = 0; i < len; i++) {
-        int ch = TTYCHAR_GETCH(screen[i]);
-        if (ch >= TTYCHAR_COMB && ch < TTYCHAR_COMB + countof(ts->comb_cache) 
- 1) {
-            ip[ch - TTYCHAR_COMB] &= ~0x10000;
+        int ch = TTY_CHAR_GET_CH(screen[i]);
+        if (ch >= TTY_CHAR_COMB && ch < TTY_CHAR_COMB + 
countof(ts->comb_cache) - 1) {
+            ip[ch - TTY_CHAR_COMB] &= ~0x10000;
         }
     }
     for (; *ip != 0; ip += *ip & 0xFFFF) {
@@ -1174,7 +810,7 @@
             eb_printf(b, "   FREE   %d\n", (*ip & 0xFFFF) - 1);
         } else {
             eb_printf(b, "  %06X  %d:",
-                      (unsigned int)(TTYCHAR_COMB + (ip - ts->comb_cache)),
+                      (unsigned int)(TTY_CHAR_COMB + (ip - ts->comb_cache)),
                       (*ip & 0xFFFF) - 1);
             for (i = 1; i < (*ip & 0xFFFF); i++) {
                 eb_printf(b, " %04X", ip[i]);
@@ -1184,7 +820,7 @@
     }
 }
 #else
-#define comb_cache_add(s, p, n)  TTYCHAR_BAD
+#define comb_cache_add(s, p, n)  TTY_CHAR_BAD
 #define comb_cache_clean(s, p, n)
 #define comb_cache_describe(s, b)
 #endif
@@ -1203,7 +839,7 @@
         return;
 
     ts->line_updated[y] = 1;
-    fgcolor = get_tty_color(color, ts->term_colors, ts->term_fg_colors_count);
+    fgcolor = qe_map_color(color, ts->term_colors, ts->term_fg_colors_count, 
NULL);
     if (font->style & QE_STYLE_UNDERLINE)
         fgcolor |= TTY_UNDERLINE;
     if (font->style & QE_STYLE_BOLD)
@@ -1229,7 +865,7 @@
                     n = s->clip_x2;
                 n -= s->clip_x1;
                 for (; n > 0; n--) {
-                    *ptr = TTYCHAR(' ', fgcolor, TTYCHAR_GETBG(*ptr));
+                    *ptr = TTY_CHAR(' ', fgcolor, TTY_CHAR_GET_BG(*ptr));
                     ptr++;
                 }
                 /* skip combining code points if any */
@@ -1249,7 +885,7 @@
         if (x + w > s->clip_x2) {
             /* pad partially clipped wide char with spaces */
             while (x < s->clip_x2) {
-                *ptr = TTYCHAR(' ', fgcolor, TTYCHAR_GETBG(*ptr));
+                *ptr = TTY_CHAR(' ', fgcolor, TTY_CHAR_GET_BG(*ptr));
                 ptr++;
                 x++;
             }
@@ -1265,14 +901,14 @@
             cc = comb_cache_add(ts, str - 1, nacc + 1);
             str += nacc - 1;
             len -= nacc - 1;
-            ptr[-1] = TTYCHAR(cc, fgcolor, TTYCHAR_GETBG(ptr[-1]));
+            ptr[-1] = TTY_CHAR(cc, fgcolor, TTY_CHAR_GET_BG(ptr[-1]));
         } else {
-            *ptr = TTYCHAR(cc, fgcolor, TTYCHAR_GETBG(*ptr));
+            *ptr = TTY_CHAR(cc, fgcolor, TTY_CHAR_GET_BG(*ptr));
             ptr++;
             x += w;
             while (w > 1) {
                 /* put placeholders for wide chars */
-                *ptr = TTYCHAR(TTYCHAR_NONE, fgcolor, TTYCHAR_GETBG(*ptr));
+                *ptr = TTY_CHAR(TTY_CHAR_NONE, fgcolor, TTY_CHAR_GET_BG(*ptr));
                 ptr++;
                 w--;
             }
@@ -1351,12 +987,12 @@
              * background color if emulated as bright.
              */
             if ((ts->term_flags & USE_ERASE_END_OF_LINE)
-            &&  TTYCHAR_GETCH(ptr4[-1]) == ' '
+            &&  TTY_CHAR_GET_CH(ptr4[-1]) == ' '
             &&  (/*!(ts->term_flags & USE_BLINK_AS_BRIGHT_BG) ||*/
-                 TTYCHAR_GETBG(ptr4[-1]) < 8))
+                 TTY_CHAR_GET_BG(ptr4[-1]) < 8))
             {
                 /* find the last non blank char on row */
-                blankcc = TTYCHAR2(' ', TTYCHAR_GETCOL(ptr3[-1]));
+                blankcc = TTY_CHAR2(' ', TTY_CHAR_GET_COL(ptr3[-1]));
                 while (ptr3 > ptr1 && ptr3[-1] == blankcc) {
                     --ptr3;
                 }
@@ -1371,7 +1007,7 @@
                      * space because the color change is non trivial
                      */
                     if (ptr3 == ptr1
-                    ||  TTYCHAR_GETBG(*ptr3) != TTYCHAR_GETBG(ptr3[-1]))
+                    ||  TTY_CHAR_GET_BG(*ptr3) != TTY_CHAR_GET_BG(ptr3[-1]))
                         ptr4++;
                 }
             }
@@ -1388,13 +1024,13 @@
                 cc = *ptr1;
                 ptr1[shadow] = cc;
                 ptr1++;
-                ch = TTYCHAR_GETCH(cc);
-                if ((unsigned int)ch != TTYCHAR_NONE) {
+                ch = TTY_CHAR_GET_CH(cc);
+                if ((unsigned int)ch != TTY_CHAR_NONE) {
                     /* output attributes */
                     again:
-                    if (bgcolor != (int)TTYCHAR_GETBG(cc)) {
+                    if (bgcolor != (int)TTY_CHAR_GET_BG(cc)) {
                         int lastbg = bgcolor;
-                        bgcolor = TTYCHAR_GETBG(cc);
+                        bgcolor = TTY_CHAR_GET_BG(cc);
                         if (ts->term_flags & (USE_256_COLORS | 
USE_24_BIT_COLORS)) {
                             TTY_FPRINTF(s->STDOUT, "\033[48;5;%dm", bgcolor);
                         } else
@@ -1419,9 +1055,9 @@
                     }
                     /* do not special case SPC on fg color change
                     * because of combining marks */
-                    if (fgcolor != (int)TTYCHAR_GETFG(cc)) {
+                    if (fgcolor != (int)TTY_CHAR_GET_FG(cc)) {
                         int lastfg = fgcolor;
-                        fgcolor = TTYCHAR_GETFG(cc);
+                        fgcolor = TTY_CHAR_GET_FG(cc);
                         if (ts->term_flags & (USE_256_COLORS | 
USE_24_BIT_COLORS)) {
                             TTY_FPRINTF(s->STDOUT, "\033[38;5;%dm", fgcolor);
                         } else
@@ -1447,9 +1083,9 @@
                         }
                     }
 #if 1
-                    if (attr != (int)TTYCHAR_GETCOL(cc)) {
+                    if (attr != (int)TTY_CHAR_GET_COL(cc)) {
                         int lastattr = attr;
-                        attr = TTYCHAR_GETCOL(cc);
+                        attr = TTY_CHAR_GET_COL(cc);
 
                         if ((attr ^ lastattr) & TTY_BOLD) {
                             if (attr & TTY_BOLD) {
@@ -1512,9 +1148,9 @@
                         }
                     } else
 #if MAX_UNICODE_DISPLAY > 0xFFFF
-                    if (ch >= TTYCHAR_COMB && ch < TTYCHAR_COMB + 
COMB_CACHE_SIZE - 1) {
+                    if (ch >= TTY_CHAR_COMB && ch < TTY_CHAR_COMB + 
COMB_CACHE_SIZE - 1) {
                         u8 buf[10], *q;
-                        unsigned int *ip = ts->comb_cache + (ch - 
TTYCHAR_COMB);
+                        unsigned int *ip = ts->comb_cache + (ch - 
TTY_CHAR_COMB);
                         int ncc = *ip++;
 
                         if (ncc < 0x300) {

Index: util.c
===================================================================
RCS file: /sources/qemacs/qemacs/util.c,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -b -r1.77 -r1.78
--- util.c      25 Mar 2017 18:07:18 -0000      1.77
+++ util.c      3 Apr 2017 08:33:57 -0000       1.78
@@ -1186,6 +1186,373 @@
 static ColorDef *qe_colors = (ColorDef *)default_colors;
 static int nb_qe_colors = nb_default_colors;
 
+#if 0
+static QEColor const tty_full_colors[8] = {
+    QERGB(0x00, 0x00, 0x00),
+    QERGB(0xff, 0x00, 0x00),
+    QERGB(0x00, 0xff, 0x00),
+    QERGB(0xff, 0xff, 0x00),
+    QERGB(0x00, 0x00, 0xff),
+    QERGB(0xff, 0x00, 0xff),
+    QERGB(0x00, 0xff, 0xff),
+    QERGB(0xff, 0xff, 0xff),
+};
+#endif
+
+QEColor const xterm_colors[256] = {
+    QERGB(0x00, 0x00, 0x00),
+    QERGB(0xbb, 0x00, 0x00),
+    QERGB(0x00, 0xbb, 0x00),
+    QERGB(0xbb, 0xbb, 0x00),
+    QERGB(0x00, 0x00, 0xbb),
+    QERGB(0xbb, 0x00, 0xbb),
+    QERGB(0x00, 0xbb, 0xbb),
+    QERGB(0xbb, 0xbb, 0xbb),
+
+    QERGB(0x55, 0x55, 0x55),
+    QERGB(0xff, 0x55, 0x55),
+    QERGB(0x55, 0xff, 0x55),
+    QERGB(0xff, 0xff, 0x55),
+    QERGB(0x55, 0x55, 0xff),
+    QERGB(0xff, 0x55, 0xff),
+    QERGB(0x55, 0xff, 0xff),
+    QERGB(0xff, 0xff, 0xff),
+#if 1
+    /* Extended color palette for xterm 256 color mode */
+
+    /* From XFree86: xc/programs/xterm/256colres.h,
+     * v 1.5 2002/10/05 17:57:11 dickey Exp
+     */
+
+    /* 216 entry RGB cube with axes 0,95,135,175,215,255 */
+    /* followed by 24 entry grey scale 8,18..238 */
+    QERGB(0x00, 0x00, 0x00),  /* 16: Grey0 */
+    QERGB(0x00, 0x00, 0x5f),  /* 17: NavyBlue */
+    QERGB(0x00, 0x00, 0x87),  /* 18: DarkBlue */
+    QERGB(0x00, 0x00, 0xaf),  /* 19: Blue3 */
+    QERGB(0x00, 0x00, 0xd7),  /* 20: Blue3 */
+    QERGB(0x00, 0x00, 0xff),  /* 21: Blue1 */
+    QERGB(0x00, 0x5f, 0x00),  /* 22: DarkGreen */
+    QERGB(0x00, 0x5f, 0x5f),  /* 23: DeepSkyBlue4 */
+    QERGB(0x00, 0x5f, 0x87),  /* 24: DeepSkyBlue4 */
+    QERGB(0x00, 0x5f, 0xaf),  /* 25: DeepSkyBlue4 */
+    QERGB(0x00, 0x5f, 0xd7),  /* 26: DodgerBlue3 */
+    QERGB(0x00, 0x5f, 0xff),  /* 27: DodgerBlue2 */
+    QERGB(0x00, 0x87, 0x00),  /* 28: Green4 */
+    QERGB(0x00, 0x87, 0x5f),  /* 29: SpringGreen4 */
+    QERGB(0x00, 0x87, 0x87),  /* 30: Turquoise4 */
+    QERGB(0x00, 0x87, 0xaf),  /* 31: DeepSkyBlue3 */
+    QERGB(0x00, 0x87, 0xd7),  /* 32: DeepSkyBlue3 */
+    QERGB(0x00, 0x87, 0xff),  /* 33: DodgerBlue1 */
+    QERGB(0x00, 0xaf, 0x00),  /* 34: Green3 */
+    QERGB(0x00, 0xaf, 0x5f),  /* 35: SpringGreen3 */
+    QERGB(0x00, 0xaf, 0x87),  /* 36: DarkCyan */
+    QERGB(0x00, 0xaf, 0xaf),  /* 37: LightSeaGreen */
+    QERGB(0x00, 0xaf, 0xd7),  /* 38: DeepSkyBlue2 */
+    QERGB(0x00, 0xaf, 0xff),  /* 39: DeepSkyBlue1 */
+    QERGB(0x00, 0xd7, 0x00),  /* 40: Green3 */
+    QERGB(0x00, 0xd7, 0x5f),  /* 41: SpringGreen3 */
+    QERGB(0x00, 0xd7, 0x87),  /* 42: SpringGreen2 */
+    QERGB(0x00, 0xd7, 0xaf),  /* 43: Cyan3 */
+    QERGB(0x00, 0xd7, 0xd7),  /* 44: DarkTurquoise */
+    QERGB(0x00, 0xd7, 0xff),  /* 45: Turquoise2 */
+    QERGB(0x00, 0xff, 0x00),  /* 46: Green1 */
+    QERGB(0x00, 0xff, 0x5f),  /* 47: SpringGreen2 */
+    QERGB(0x00, 0xff, 0x87),  /* 48: SpringGreen1 */
+    QERGB(0x00, 0xff, 0xaf),  /* 49: MediumSpringGreen */
+    QERGB(0x00, 0xff, 0xd7),  /* 50: Cyan2 */
+    QERGB(0x00, 0xff, 0xff),  /* 51: Cyan1 */
+    QERGB(0x5f, 0x00, 0x00),  /* 52: DarkRed */
+    QERGB(0x5f, 0x00, 0x5f),  /* 53: DeepPink4 */
+    QERGB(0x5f, 0x00, 0x87),  /* 54: Purple4 */
+    QERGB(0x5f, 0x00, 0xaf),  /* 55: Purple4 */
+    QERGB(0x5f, 0x00, 0xd7),  /* 56: Purple3 */
+    QERGB(0x5f, 0x00, 0xff),  /* 57: BlueViolet */
+    QERGB(0x5f, 0x5f, 0x00),  /* 58: Orange4 */
+    QERGB(0x5f, 0x5f, 0x5f),  /* 59: Grey37 */
+    QERGB(0x5f, 0x5f, 0x87),  /* 60: MediumPurple4 */
+    QERGB(0x5f, 0x5f, 0xaf),  /* 61: SlateBlue3 */
+    QERGB(0x5f, 0x5f, 0xd7),  /* 62: SlateBlue3 */
+    QERGB(0x5f, 0x5f, 0xff),  /* 63: RoyalBlue1 */
+    QERGB(0x5f, 0x87, 0x00),  /* 64: Chartreuse4 */
+    QERGB(0x5f, 0x87, 0x5f),  /* 65: DarkSeaGreen4 */
+    QERGB(0x5f, 0x87, 0x87),  /* 66: PaleTurquoise4 */
+    QERGB(0x5f, 0x87, 0xaf),  /* 67: SteelBlue */
+    QERGB(0x5f, 0x87, 0xd7),  /* 68: SteelBlue3 */
+    QERGB(0x5f, 0x87, 0xff),  /* 69: CornflowerBlue */
+    QERGB(0x5f, 0xaf, 0x00),  /* 70: Chartreuse3 */
+    QERGB(0x5f, 0xaf, 0x5f),  /* 71: DarkSeaGreen4 */
+    QERGB(0x5f, 0xaf, 0x87),  /* 72: CadetBlue */
+    QERGB(0x5f, 0xaf, 0xaf),  /* 73: CadetBlue */
+    QERGB(0x5f, 0xaf, 0xd7),  /* 74: SkyBlue3 */
+    QERGB(0x5f, 0xaf, 0xff),  /* 75: SteelBlue1 */
+    QERGB(0x5f, 0xd7, 0x00),  /* 76: Chartreuse3 */
+    QERGB(0x5f, 0xd7, 0x5f),  /* 77: PaleGreen3 */
+    QERGB(0x5f, 0xd7, 0x87),  /* 78: SeaGreen3 */
+    QERGB(0x5f, 0xd7, 0xaf),  /* 79: Aquamarine3 */
+    QERGB(0x5f, 0xd7, 0xd7),  /* 80: MediumTurquoise */
+    QERGB(0x5f, 0xd7, 0xff),  /* 81: SteelBlue1 */
+    QERGB(0x5f, 0xff, 0x00),  /* 82: Chartreuse2 */
+    QERGB(0x5f, 0xff, 0x5f),  /* 83: SeaGreen2 */
+    QERGB(0x5f, 0xff, 0x87),  /* 84: SeaGreen1 */
+    QERGB(0x5f, 0xff, 0xaf),  /* 85: SeaGreen1 */
+    QERGB(0x5f, 0xff, 0xd7),  /* 86: Aquamarine1 */
+    QERGB(0x5f, 0xff, 0xff),  /* 87: DarkSlateGray2 */
+    QERGB(0x87, 0x00, 0x00),  /* 88: DarkRed */
+    QERGB(0x87, 0x00, 0x5f),  /* 89: DeepPink4 */
+    QERGB(0x87, 0x00, 0x87),  /* 90: DarkMagenta */
+    QERGB(0x87, 0x00, 0xaf),  /* 91: DarkMagenta */
+    QERGB(0x87, 0x00, 0xd7),  /* 92: DarkViolet */
+    QERGB(0x87, 0x00, 0xff),  /* 93: Purple */
+    QERGB(0x87, 0x5f, 0x00),  /* 94: Orange4 */
+    QERGB(0x87, 0x5f, 0x5f),  /* 95: LightPink4 */
+    QERGB(0x87, 0x5f, 0x87),  /* 96: Plum4 */
+    QERGB(0x87, 0x5f, 0xaf),  /* 97: MediumPurple3 */
+    QERGB(0x87, 0x5f, 0xd7),  /* 98: MediumPurple3 */
+    QERGB(0x87, 0x5f, 0xff),  /* 99: SlateBlue1 */
+    QERGB(0x87, 0x87, 0x00),  /* 100: Yellow4 */
+    QERGB(0x87, 0x87, 0x5f),  /* 101: Wheat4 */
+    QERGB(0x87, 0x87, 0x87),  /* 102: Grey53 */
+    QERGB(0x87, 0x87, 0xaf),  /* 103: LightSlateGrey */
+    QERGB(0x87, 0x87, 0xd7),  /* 104: MediumPurple */
+    QERGB(0x87, 0x87, 0xff),  /* 105: LightSlateBlue */
+    QERGB(0x87, 0xaf, 0x00),  /* 106: Yellow4 */
+    QERGB(0x87, 0xaf, 0x5f),  /* 107: DarkOliveGreen3 */
+    QERGB(0x87, 0xaf, 0x87),  /* 108: DarkSeaGreen */
+    QERGB(0x87, 0xaf, 0xaf),  /* 109: LightSkyBlue3 */
+    QERGB(0x87, 0xaf, 0xd7),  /* 110: LightSkyBlue3 */
+    QERGB(0x87, 0xaf, 0xff),  /* 111: SkyBlue2 */
+    QERGB(0x87, 0xd7, 0x00),  /* 112: Chartreuse2 */
+    QERGB(0x87, 0xd7, 0x5f),  /* 113: DarkOliveGreen3 */
+    QERGB(0x87, 0xd7, 0x87),  /* 114: PaleGreen3 */
+    QERGB(0x87, 0xd7, 0xaf),  /* 115: DarkSeaGreen3 */
+    QERGB(0x87, 0xd7, 0xd7),  /* 116: DarkSlateGray3 */
+    QERGB(0x87, 0xd7, 0xff),  /* 117: SkyBlue1 */
+    QERGB(0x87, 0xff, 0x00),  /* 118: Chartreuse1 */
+    QERGB(0x87, 0xff, 0x5f),  /* 119: LightGreen */
+    QERGB(0x87, 0xff, 0x87),  /* 120: LightGreen */
+    QERGB(0x87, 0xff, 0xaf),  /* 121: PaleGreen1 */
+    QERGB(0x87, 0xff, 0xd7),  /* 122: Aquamarine1 */
+    QERGB(0x87, 0xff, 0xff),  /* 123: DarkSlateGray1 */
+    QERGB(0xaf, 0x00, 0x00),  /* 124: Red3 */
+    QERGB(0xaf, 0x00, 0x5f),  /* 125: DeepPink4 */
+    QERGB(0xaf, 0x00, 0x87),  /* 126: MediumVioletRed */
+    QERGB(0xaf, 0x00, 0xaf),  /* 127: Magenta3 */
+    QERGB(0xaf, 0x00, 0xd7),  /* 128: DarkViolet */
+    QERGB(0xaf, 0x00, 0xff),  /* 129: Purple */
+    QERGB(0xaf, 0x5f, 0x00),  /* 130: DarkOrange3 */
+    QERGB(0xaf, 0x5f, 0x5f),  /* 131: IndianRed */
+    QERGB(0xaf, 0x5f, 0x87),  /* 132: HotPink3 */
+    QERGB(0xaf, 0x5f, 0xaf),  /* 133: MediumOrchid3 */
+    QERGB(0xaf, 0x5f, 0xd7),  /* 134: MediumOrchid */
+    QERGB(0xaf, 0x5f, 0xff),  /* 135: MediumPurple2 */
+    QERGB(0xaf, 0x87, 0x00),  /* 136: DarkGoldenrod */
+    QERGB(0xaf, 0x87, 0x5f),  /* 137: LightSalmon3 */
+    QERGB(0xaf, 0x87, 0x87),  /* 138: RosyBrown */
+    QERGB(0xaf, 0x87, 0xaf),  /* 139: Grey63 */
+    QERGB(0xaf, 0x87, 0xd7),  /* 140: MediumPurple2 */
+    QERGB(0xaf, 0x87, 0xff),  /* 141: MediumPurple1 */
+    QERGB(0xaf, 0xaf, 0x00),  /* 142: Gold3 */
+    QERGB(0xaf, 0xaf, 0x5f),  /* 143: DarkKhaki */
+    QERGB(0xaf, 0xaf, 0x87),  /* 144: NavajoWhite3 */
+    QERGB(0xaf, 0xaf, 0xaf),  /* 145: Grey69 */
+    QERGB(0xaf, 0xaf, 0xd7),  /* 146: LightSteelBlue3 */
+    QERGB(0xaf, 0xaf, 0xff),  /* 147: LightSteelBlue */
+    QERGB(0xaf, 0xd7, 0x00),  /* 148: Yellow3 */
+    QERGB(0xaf, 0xd7, 0x5f),  /* 149: DarkOliveGreen3 */
+    QERGB(0xaf, 0xd7, 0x87),  /* 150: DarkSeaGreen3 */
+    QERGB(0xaf, 0xd7, 0xaf),  /* 151: DarkSeaGreen2 */
+    QERGB(0xaf, 0xd7, 0xd7),  /* 152: LightCyan3 */
+    QERGB(0xaf, 0xd7, 0xff),  /* 153: LightSkyBlue1 */
+    QERGB(0xaf, 0xff, 0x00),  /* 154: GreenYellow */
+    QERGB(0xaf, 0xff, 0x5f),  /* 155: DarkOliveGreen2 */
+    QERGB(0xaf, 0xff, 0x87),  /* 156: PaleGreen1 */
+    QERGB(0xaf, 0xff, 0xaf),  /* 157: DarkSeaGreen2 */
+    QERGB(0xaf, 0xff, 0xd7),  /* 158: DarkSeaGreen1 */
+    QERGB(0xaf, 0xff, 0xff),  /* 159: PaleTurquoise1 */
+    QERGB(0xd7, 0x00, 0x00),  /* 160: Red3 */
+    QERGB(0xd7, 0x00, 0x5f),  /* 161: DeepPink3 */
+    QERGB(0xd7, 0x00, 0x87),  /* 162: DeepPink3 */
+    QERGB(0xd7, 0x00, 0xaf),  /* 163: Magenta3 */
+    QERGB(0xd7, 0x00, 0xd7),  /* 164: Magenta3 */
+    QERGB(0xd7, 0x00, 0xff),  /* 165: Magenta2 */
+    QERGB(0xd7, 0x5f, 0x00),  /* 166: DarkOrange3 */
+    QERGB(0xd7, 0x5f, 0x5f),  /* 167: IndianRed */
+    QERGB(0xd7, 0x5f, 0x87),  /* 168: HotPink3 */
+    QERGB(0xd7, 0x5f, 0xaf),  /* 169: HotPink2 */
+    QERGB(0xd7, 0x5f, 0xd7),  /* 170: Orchid */
+    QERGB(0xd7, 0x5f, 0xff),  /* 171: MediumOrchid1 */
+    QERGB(0xd7, 0x87, 0x00),  /* 172: Orange3 */
+    QERGB(0xd7, 0x87, 0x5f),  /* 173: LightSalmon3 */
+    QERGB(0xd7, 0x87, 0x87),  /* 174: LightPink3 */
+    QERGB(0xd7, 0x87, 0xaf),  /* 175: Pink3 */
+    QERGB(0xd7, 0x87, 0xd7),  /* 176: Plum3 */
+    QERGB(0xd7, 0x87, 0xff),  /* 177: Violet */
+    QERGB(0xd7, 0xaf, 0x00),  /* 178: Gold3 */
+    QERGB(0xd7, 0xaf, 0x5f),  /* 179: LightGoldenrod3 */
+    QERGB(0xd7, 0xaf, 0x87),  /* 180: Tan */
+    QERGB(0xd7, 0xaf, 0xaf),  /* 181: MistyRose3 */
+    QERGB(0xd7, 0xaf, 0xd7),  /* 182: Thistle3 */
+    QERGB(0xd7, 0xaf, 0xff),  /* 183: Plum2 */
+    QERGB(0xd7, 0xd7, 0x00),  /* 184: Yellow3 */
+    QERGB(0xd7, 0xd7, 0x5f),  /* 185: Khaki3 */
+    QERGB(0xd7, 0xd7, 0x87),  /* 186: LightGoldenrod2 */
+    QERGB(0xd7, 0xd7, 0xaf),  /* 187: LightYellow3 */
+    QERGB(0xd7, 0xd7, 0xd7),  /* 188: Grey84 */
+    QERGB(0xd7, 0xd7, 0xff),  /* 189: LightSteelBlue1 */
+    QERGB(0xd7, 0xff, 0x00),  /* 190: Yellow2 */
+    QERGB(0xd7, 0xff, 0x5f),  /* 191: DarkOliveGreen1 */
+    QERGB(0xd7, 0xff, 0x87),  /* 192: DarkOliveGreen1 */
+    QERGB(0xd7, 0xff, 0xaf),  /* 193: DarkSeaGreen1 */
+    QERGB(0xd7, 0xff, 0xd7),  /* 194: Honeydew2 */
+    QERGB(0xd7, 0xff, 0xff),  /* 195: LightCyan1 */
+    QERGB(0xff, 0x00, 0x00),  /* 196: Red1 */
+    QERGB(0xff, 0x00, 0x5f),  /* 197: DeepPink2 */
+    QERGB(0xff, 0x00, 0x87),  /* 198: DeepPink1 */
+    QERGB(0xff, 0x00, 0xaf),  /* 199: DeepPink1 */
+    QERGB(0xff, 0x00, 0xd7),  /* 200: Magenta2 */
+    QERGB(0xff, 0x00, 0xff),  /* 201: Magenta1 */
+    QERGB(0xff, 0x5f, 0x00),  /* 202: OrangeRed1 */
+    QERGB(0xff, 0x5f, 0x5f),  /* 203: IndianRed1 */
+    QERGB(0xff, 0x5f, 0x87),  /* 204: IndianRed1 */
+    QERGB(0xff, 0x5f, 0xaf),  /* 205: HotPink */
+    QERGB(0xff, 0x5f, 0xd7),  /* 206: HotPink */
+    QERGB(0xff, 0x5f, 0xff),  /* 207: MediumOrchid1 */
+    QERGB(0xff, 0x87, 0x00),  /* 208: DarkOrange */
+    QERGB(0xff, 0x87, 0x5f),  /* 209: Salmon1 */
+    QERGB(0xff, 0x87, 0x87),  /* 210: LightCoral */
+    QERGB(0xff, 0x87, 0xaf),  /* 211: PaleVioletRed1 */
+    QERGB(0xff, 0x87, 0xd7),  /* 212: Orchid2 */
+    QERGB(0xff, 0x87, 0xff),  /* 213: Orchid1 */
+    QERGB(0xff, 0xaf, 0x00),  /* 214: Orange1 */
+    QERGB(0xff, 0xaf, 0x5f),  /* 215: SandyBrown */
+    QERGB(0xff, 0xaf, 0x87),  /* 216: LightSalmon1 */
+    QERGB(0xff, 0xaf, 0xaf),  /* 217: LightPink1 */
+    QERGB(0xff, 0xaf, 0xd7),  /* 218: Pink1 */
+    QERGB(0xff, 0xaf, 0xff),  /* 219: Plum1 */
+    QERGB(0xff, 0xd7, 0x00),  /* 220: Gold1 */
+    QERGB(0xff, 0xd7, 0x5f),  /* 221: LightGoldenrod2 */
+    QERGB(0xff, 0xd7, 0x87),  /* 222: LightGoldenrod2 */
+    QERGB(0xff, 0xd7, 0xaf),  /* 223: NavajoWhite1 */
+    QERGB(0xff, 0xd7, 0xd7),  /* 224: MistyRose1 */
+    QERGB(0xff, 0xd7, 0xff),  /* 225: Thistle1 */
+    QERGB(0xff, 0xff, 0x00),  /* 226: Yellow1 */
+    QERGB(0xff, 0xff, 0x5f),  /* 227: LightGoldenrod1 */
+    QERGB(0xff, 0xff, 0x87),  /* 228: Khaki1 */
+    QERGB(0xff, 0xff, 0xaf),  /* 229: Wheat1 */
+    QERGB(0xff, 0xff, 0xd7),  /* 230: Cornsilk1 */
+    QERGB(0xff, 0xff, 0xff),  /* 231: Grey100 */
+    QERGB(0x08, 0x08, 0x08),  /* 232: Grey3 */
+    QERGB(0x12, 0x12, 0x12),  /* 233: Grey7 */
+    QERGB(0x1c, 0x1c, 0x1c),  /* 234: Grey11 */
+    QERGB(0x26, 0x26, 0x26),  /* 235: Grey15 */
+    QERGB(0x30, 0x30, 0x30),  /* 236: Grey19 */
+    QERGB(0x3a, 0x3a, 0x3a),  /* 237: Grey23 */
+    QERGB(0x44, 0x44, 0x44),  /* 238: Grey27 */
+    QERGB(0x4e, 0x4e, 0x4e),  /* 239: Grey30 */
+    QERGB(0x58, 0x58, 0x58),  /* 240: Grey35 */
+    QERGB(0x62, 0x62, 0x62),  /* 241: Grey39 */
+    QERGB(0x6c, 0x6c, 0x6c),  /* 242: Grey42 */
+    QERGB(0x76, 0x76, 0x76),  /* 243: Grey46 */
+    QERGB(0x80, 0x80, 0x80),  /* 244: Grey50 */
+    QERGB(0x8a, 0x8a, 0x8a),  /* 245: Grey54 */
+    QERGB(0x94, 0x94, 0x94),  /* 246: Grey58 */
+    QERGB(0x9e, 0x9e, 0x9e),  /* 247: Grey62 */
+    QERGB(0xa8, 0xa8, 0xa8),  /* 248: Grey66 */
+    QERGB(0xb2, 0xb2, 0xb2),  /* 249: Grey70 */
+    QERGB(0xbc, 0xbc, 0xbc),  /* 250: Grey74 */
+    QERGB(0xc6, 0xc6, 0xc6),  /* 251: Grey78 */
+    QERGB(0xd0, 0xd0, 0xd0),  /* 252: Grey82 */
+    QERGB(0xda, 0xda, 0xda),  /* 253: Grey85 */
+    QERGB(0xe4, 0xe4, 0xe4),  /* 254: Grey89 */
+    QERGB(0xee, 0xee, 0xee),  /* 255: Grey93 */
+#endif
+};
+
+static unsigned char const scale_cube[256] = {
+    /* This array is used for mapping rgb colors to the standard palette */
+    /* 216 entry RGB cube with axes 0,95,135,175,215,255 */
+#define REP5(x)   (x), (x), (x), (x), (x)
+#define REP10(x)  REP5(x), REP5(x)
+#define REP20(x)  REP10(x), REP10(x)
+#define REP40(x)  REP20(x), REP20(x)
+#define REP25(x)  REP5(x), REP5(x), REP5(x), REP5(x), REP5(x)
+#define REP47(x)  REP10(x), REP10(x), REP10(x), REP10(x), REP5(x), (x), (x)
+    REP47(0), REP47(1), REP20(1), REP40(2), REP40(3), REP40(4), REP20(5), 5
+};
+
+static unsigned char const scale_grey[256] = {
+    /* This array is used for mapping gray levels to the standard palette */
+    /* 232..255: 24 entry grey scale 8,18..238 */
+    16, 16, 16, 16,
+    REP10(232), REP10(233), REP10(234), REP10(235),
+    REP10(236), REP10(237), REP10(238), REP10(239), 
+    REP10(240), REP10(241), REP10(242), REP10(243), 
+    REP10(244), REP10(245), REP10(246), REP10(247),
+    REP10(248), REP10(249), REP10(250), REP10(251),
+    REP10(252), REP10(253), REP10(254), REP10(255),
+    255, 255, 255,
+    231, 231, 231, 231, 231, 231, 231, 231, 231
+};
+
+static inline int color_dist(QEColor c1, QEColor c2) {
+    /* using casts because c1 and c2 are unsigned */
+#if 1
+    /* using a quick approximation to give green extra weight */
+    return      abs((int)((c1 >>  0) & 0xff) - (int)((c2 >>  0) & 0xff)) +
+            2 * abs((int)((c1 >>  8) & 0xff) - (int)((c2 >>  8) & 0xff)) +
+                abs((int)((c1 >> 16) & 0xff) - (int)((c2 >> 16) & 0xff));
+#else
+    /* using different weights to R, G, B according to luminance levels */
+    return  11 * abs((int)((c1 >>  0) & 0xff) - (int)((c2 >>  0) & 0xff)) +
+            59 * abs((int)((c1 >>  8) & 0xff) - (int)((c2 >>  8) & 0xff)) +
+            30 * abs((int)((c1 >> 16) & 0xff) - (int)((c2 >> 16) & 0xff));
+#endif
+}
+
+/* XXX: should have a more generic API with precomputed mapping scales */
+int qe_map_color(QEColor color, QEColor const *colors, int count, int *dist)
+{
+    int i, cmin, dmin, d;
+
+    dmin = INT_MAX;
+    cmin = 0;
+    for (i = 0; i < count; i++) {
+        d = color_dist(color, colors[i]);
+        if (d < dmin) {
+            cmin = i;
+            dmin = d;
+        }
+    }
+#if 1
+    if (dmin > 0 && count > 16) {
+        unsigned int r = (color >> 16) & 0xff;
+        unsigned int g = (color >>  8) & 0xff;
+        unsigned int b = (color >>  0) & 0xff;
+        if (r == g && g == b) {
+            i = scale_grey[r];
+            d = color_dist(color, colors[i]);
+            if (d < dmin) {
+                cmin = i;
+                dmin = d;
+            }
+        } else {
+            /* XXX: should use more precise projection */
+            i = scale_cube[r] * 36 + scale_cube[g] * 6 + scale_cube[b];
+            d = color_dist(color, colors[i]);
+            if (d < dmin) {
+                cmin = i;
+                dmin = d;
+            }
+        }
+    }
+#endif
+    if (dist) {
+        *dist = dmin;
+    }
+    return cmin;
+}
+
 void color_completion(CompleteState *cp)
 {
     ColorDef const *def;

Index: TODO.org
===================================================================
RCS file: /sources/qemacs/qemacs/TODO.org,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -b -r1.32 -r1.33
--- TODO.org    2 Apr 2017 01:12:01 -0000       1.32
+++ TODO.org    3 Apr 2017 08:33:57 -0000       1.33
@@ -5,6 +5,8 @@
 
 * Needed for release version 5
 
+** display: fix window split bug
+
 * Priority 0
 
 ** basic: fix current position when changing buffer attached to window
@@ -69,6 +71,7 @@
 ** display: API: remove screen argument in release_font
 ** display: API: remove screen argument in glyph_width
 ** display: API: add create-style(name, properties)
+** display: use true colors on capable terminals
 ** doc: migrate TODO and documentation to markdown or reStructuredText
 ** doc: rewrite TODO file with more sections and explanations
 ** doc: migrate coding-rules.html to markdown
@@ -239,7 +242,6 @@
    qemacs does not take into account combination performed by the terminal.
    Terminal glyph width of 0 should be supported.
 ** deal with accents in filenames (OS/X uses separate utf8 accents)
-** support 256 and true color escapes in tty emulator
 ** auto-fill-mode
 ** auto-revert-mode, global-auto-revert-mode, auto-revert-tail-mode
 ** rectangular regions, cut/paste

Index: tests/16colors.pl
===================================================================
RCS file: tests/16colors.pl
diff -N tests/16colors.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/16colors.pl   3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+#
+# Copyright (c) 2002-2017 Charlie Gordon.
+#
+# use the resources for colors 0-15 - usually more-or-less a
+# reproduction of the standard ANSI colors, but possibly more
+# pleasing shades
+
+# display the colors
+
+# first the system ones:
+print "Background colors:\n";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 100 + $color - 8 : $color + 40;
+    printf("\x1b[%dm %02d ", $n, $color);
+    # print "\x1b[${n}m    ";
+}
+print "\x1b[0m\n\n";
+
+print "Blinking colors:\n";
+print "\x1b[5m";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 100 + $color - 8 : $color + 40;
+    printf("\x1b[%dm %02d ", $n, $color);
+    # print "\x1b[${n}m    ";
+}
+print "\x1b[0m\n\n";
+
+print "Foreground colors:\n";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 90 + $color - 8 : $color + 30;
+    printf("\x1b[%dm %02d ", $n, $color);
+}
+print "\x1b[0m\n\n";
+
+print "Bold colors:\n";
+print "\x1b[1m";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 90 + $color - 8 : $color + 30;
+    printf("\x1b[%dm %02d ", $n, $color);
+}
+print "\x1b[0m\n\n";
+
+print "Italic colors:\n";
+print "\x1b[3m";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 90 + $color - 8 : $color + 30;
+    printf("\x1b[%dm %02d ", $n, $color);
+}
+print "\x1b[0m\n\n";
+
+print "Underline colors:\n";
+print "\x1b[4m";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 90 + $color - 8 : $color + 30;
+    printf("\x1b[%dm %02d ", $n, $color);
+}
+print "\x1b[0m\n\n";
+
+print "Reverse colors:\n";
+print "\x1b[7m";
+for ($color = 0; $color < 16; $color++) {
+    $n = $color > 7 ? 90 + $color - 8 : $color + 30;
+    printf("\x1b[%dm %02d ", $n, $color);
+}
+print "\x1b[0m\n\n";
+
+print "Color combinations:\n";
+for ($bg = 0; $bg < 16; $bg++) {
+    $n = $bg > 7 ? 100 + $bg - 8 : $bg + 40;
+    # printf("\x1b[%dm", ($color > 7) ? 5 : 25);
+    # printf("\x1b[%dm", 40 + ($color & 7));
+    printf("\x1b[%dm", $n);
+    for ($fg = 0; $fg < 16; $fg++) {
+        $n = $fg > 7 ? 90 + $fg - 8 : $fg + 30;
+        # printf("\x1b[%dm", ($fg > 7) ? 1 : 22);
+        # printf("\x1b[%dm %02d ", 30 + ($fg & 7), $fg);
+        printf("\x1b[%dm %02d ", $n, $fg);
+    }
+    print "\x1b[0m\n";
+}
+print "\x1b[0m\n";

Index: tests/256colors2.pl
===================================================================
RCS file: tests/256colors2.pl
diff -N tests/256colors2.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/256colors2.pl 3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+# Author: Todd Larason <address@hidden>
+# $XFree86: xc/programs/xterm/vttests/256colors2.pl,v 1.2 2002/03/26 01:46:43 
dickey Exp $
+
+# use the resources for colors 0-15 - usually more-or-less a
+# reproduction of the standard ANSI colors, but possibly more
+# pleasing shades
+
+# colors 16-231 are a 6x6x6 color cube
+for ($red = 0; $red < 6; $red++) {
+    for ($green = 0; $green < 6; $green++) {
+       for ($blue = 0; $blue < 6; $blue++) {
+           printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\",
+                  16 + ($red * 36) + ($green * 6) + $blue,
+                  ($red ? ($red * 40 + 55) : 0),
+                  ($green ? ($green * 40 + 55) : 0),
+                  ($blue ? ($blue * 40 + 55) : 0));
+       }
+    }
+}
+
+# colors 232-255 are a grayscale ramp, intentionally leaving out
+# black and white
+for ($gray = 0; $gray < 24; $gray++) {
+    $level = ($gray * 10) + 8;
+    printf("\x1b]4;%d;rgb:%2.2x/%2.2x/%2.2x\x1b\\",
+          232 + $gray, $level, $level, $level);
+}
+
+
+# display the colors
+
+# first the system ones:
+print "System colors:\n";
+for ($color = 0; $color < 8; $color++) {
+    print "\x1b[48;5;${color}m  ";
+}
+print "\x1b[0m\n";
+for ($color = 8; $color < 16; $color++) {
+    print "\x1b[48;5;${color}m  ";
+}
+print "\x1b[0m\n\n";
+
+# now the color cube
+print "Color cube, 6x6x6:\n";
+for ($green = 0; $green < 6; $green++) {
+    for ($red = 0; $red < 6; $red++) {
+       for ($blue = 0; $blue < 6; $blue++) {
+           $color = 16 + ($red * 36) + ($green * 6) + $blue;
+           print "\x1b[48;5;${color}m  ";
+       }
+       print "\x1b[0m ";
+    }
+    print "\n";
+}
+
+
+# now the grayscale ramp
+print "Grayscale ramp:\n";
+for ($color = 232; $color < 256; $color++) {
+    print "\x1b[48;5;${color}m  ";
+}
+print "\x1b[0m\n";

Index: tests/color-spaces.pl
===================================================================
RCS file: tests/color-spaces.pl
diff -N tests/color-spaces.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/color-spaces.pl       3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,132 @@
+#!/usr/bin/perl
+# Author: Todd Larason <address@hidden>
+# $XFree86: xc/programs/xterm/vttests/256colors2.pl,v 1.1 1999/07/11 08:49:54 
dawes Exp $
+
+print "256 color mode\n\n";
+
+# display back ground colors
+
+for ($fgbg = 38; $fgbg <= 48; $fgbg +=10) {
+
+    # first the system ones:
+    print "System colors:\n";
+    for ($color = 0; $color < 8; $color++) {
+        print "\x1b[${fgbg};5;${color}m::";
+    }
+    print "\x1b[0m\n";
+    for ($color = 8; $color < 16; $color++) {
+        print "\x1b[${fgbg};5;${color}m::";
+    }
+    print "\x1b[0m\n\n";
+
+    # now the color cube
+    print "Color cube, 6x6x6:\n";
+    for ($green = 0; $green < 6; $green++) {
+        for ($red = 0; $red < 6; $red++) {
+            for ($blue = 0; $blue < 6; $blue++) {
+                $color = 16 + ($red * 36) + ($green * 6) + $blue;
+                print "\x1b[${fgbg};5;${color}m::";
+            }
+            print "\x1b[0m ";
+        }
+        print "\n";
+    }
+
+    # now the grayscale ramp
+    print "Grayscale ramp:\n";
+    print "\x1b[${fgbg};5;16m::";
+    for ($color = 232; $color < 256; $color++) {
+        print "\x1b[${fgbg};5;${color}m::";
+    }
+    print "\x1b[${fgbg};5;231m::";
+    print "\x1b[0m\n\n";
+}
+
+print "Examples for the 3-byte color mode\n\n";
+
+for ($fgbg = 38; $fgbg <= 48; $fgbg +=10) {
+    # now the color cube
+    print "Color cube\n";
+    for ($green = 0; $green < 256; $green += 51) {
+        for ($red = 0; $red < 256; $red += 51) {
+            for ($blue = 0; $blue < 256; $blue += 51) {
+                print "\x1b[${fgbg};2;${red};${green};${blue}m::";
+            }
+            print "\x1b[0m ";
+        }
+        print "\n";
+    }
+    
+    # now the grayscale ramp
+    print "Grayscale ramp:\n";
+    print "\x1b[${fgbg};2;0;0;0m::";
+    for ($gray = 8; $gray < 256; $gray += 10) {
+        print "\x1b[${fgbg};2;${gray};${gray};${gray}m::";
+    }
+    print "\x1b[${fgbg};2;255;255;255m::";
+    print "\x1b[0m\n\n";
+}
+
+print "Combined direct palette and RGB color modes\n\n";
+
+$s = " x ";
+
+for ($fgbg = 38; $fgbg <= 48; $fgbg +=10) {
+    # the color cube
+    print "Color cube\n";
+    for ($green = 0; $green < 256; $green += 51) {
+        for ($red = 0; $red < 256; $red += 51) {
+            for ($blue = 0; $blue < 256; $blue += 51) {
+                print "\x1b[${fgbg};2;${red};${green};${blue}m$s";
+            }
+            print "\x1b[0m ";
+        }
+        print "\n";
+        for ($red = 0; $red < 256; $red += 51) {
+            for ($blue = 0; $blue < 256; $blue += 51) {
+                $color = 16 + ($red / 51) * 36 + ($green / 51) * 6 + ($blue / 
51);
+                print "\x1b[${fgbg};5;${color}m$s";
+            }
+            print "\x1b[0m ";
+        }
+        print "\n";
+    }
+    
+    # the grayscale ramp
+    print "Grayscale ramp:\n";
+    print "\x1b[${fgbg};2;0;0;0m$s";
+    for ($gray = 8; $gray < 256; $gray += 10) {
+        print "\x1b[${fgbg};2;${gray};${gray};${gray}m$s";
+    }
+    print "\x1b[${fgbg};2;255;255;255m$s";
+    print "\x1b[0m\n";
+    print "\x1b[${fgbg};2;0;0;0m$s";
+    for ($gray = 8; $gray < 256; $gray += 10) {
+        print "\x1b[${fgbg};2;${gray};${gray};${gray}m$s";
+    }
+    print "\x1b[${fgbg};2;255;255;255m$s";
+    print "\x1b[0m\n";
+    print "\n";
+}
+
+if (0) {
+    $fgbg = 48;
+    # debug the color cube
+    print "Color cube\n";
+    for ($green = 0; $green < 256; $green += 51) {
+        for ($red = 0; $red < 256; $red += 51) {
+            for ($blue = 0; $blue < 256; $blue += 51) {
+                print "\x1b[0mr:${red}\tg:${green}:\tb:${blue}\t";
+                print "c:${color}\t";
+                print "\x1b[${fgbg};2;${red};${green};${blue}m::";
+                print "  xxXX\x1b[0m";
+                $color = 16 + ($red / 51) * 36 + ($green / 51) * 6 + ($blue / 
51);
+                print " \x1b[${fgbg};5;${color}m::";
+                print "  xxXX\x1b[0m";
+                print "\n";
+            }
+            print "\n";
+        }
+        print "\n";
+    }
+}

Index: tests/truecolors.sh
===================================================================
RCS file: tests/truecolors.sh
diff -N tests/truecolors.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/truecolors.sh 3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,13 @@
+awk 'BEGIN{
+    s="/\\/\\/\\/\\/\\"; s=s s s s s s s s;
+    for (colnum = 0; colnum<77; colnum++) {
+        r = 255-(colnum*255/76);
+        g = (colnum*510/76);
+        b = (colnum*255/76);
+        if (g>255) g = 510-g;
+        printf "\033[48;2;%d;%d;%dm", r,g,b;
+        printf "\033[38;2;%d;%d;%dm", 255-r,255-g,255-b;
+        printf "%s\033[0m", substr(s,colnum+1,1);
+    }
+    printf "\n";
+}'

Index: tests/xterm-colortest.sh
===================================================================
RCS file: tests/xterm-colortest.sh
diff -N tests/xterm-colortest.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/xterm-colortest.sh    3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,365 @@
+#!/usr/bin/perl
+
+# by entheon, do whatever the hell you want with this file
+
+print "\n";
+print "**************************\n";
+print "*XTERM 256Color Test Chart\n";
+print "**************************\n";
+print "* 16  = black\n";
+print "* 255 = white\n";
+print "*\n";
+print "* Usage:\n";
+print "* colortest -w\n";
+print "*    wide display\n";
+print "*\n";
+print "* colortest -w -r\n";
+print "*    wide display reversed\n";
+print "*\n";
+print "* colortest -w -s\n";
+print "*    extra spaces padding\n";
+print "*\n";
+print "* colortest -w -r -s\n";
+print "*    available combination\n";
+print "*\n";
+print "**************************\n";
+
+if( $ARGV[0] eq "-w" || $ARGV[1] eq "-w" || $ARGV[2] eq "-w" ) {
+    push(@arr, [(  " 16:  00/00/00",     " 17:  00/00/5f", 
    " 18:  00/00/87",     " 19:  00/00/af",     " 
20:  00/00/d7",     " 21:  00/00/ff")] );  
+    push(@arr, [(  " 22:  00/5f/00",     " 23:  00/5f/5f", 
    " 24:  00/5f/87",     " 25:  00/5f/af",     " 
26:  00/5f/d7",     " 27:  00/5f/ff")] );  
+    push(@arr, [(  " 28:  00/87/00",     " 29:  00/87/5f", 
    " 30:  00/87/87",     " 31:  00/87/af",     " 
32:  00/87/d7",     " 33:  00/87/ff")] );  
+    push(@arr, [(  " 34:  00/af/00",     " 35:  00/af/5f", 
    " 36:  00/af/87",     " 37:  00/af/af",     " 
38:  00/af/d7",     " 39:  00/af/ff")] );  
+    push(@arr, [(  " 40:  00/d7/00",     " 41:  00/d7/5f", 
    " 42:  00/d7/87",     " 43:  00/d7/af",     " 
44:  00/d7/d7",     " 45:  00/d7/ff")] );  
+    push(@arr, [(  " 46:  00/ff/00",     " 47:  00/ff/5f", 
    " 48:  00/ff/87",     " 49:  00/ff/af",     " 
50:  00/ff/d7",     " 51:  00/ff/ff")] );  
+    push(@arr, [(  " 52:  5f/00/00",     " 53:  5f/00/5f", 
    " 54:  5f/00/87",     " 55:  5f/00/af",     " 
56:  5f/00/d7",     " 57:  5f/00/ff")] );  
+    push(@arr, [(  " 58:  5f/5f/00",     " 59:  5f/5f/5f", 
    " 60:  5f/5f/87",     " 61:  5f/5f/af",     " 
62:  5f/5f/d7",     " 63:  5f/5f/ff")] );  
+    push(@arr, [(  " 64:  5f/87/00",     " 65:  5f/87/5f", 
    " 66:  5f/87/87",     " 67:  5f/87/af",     " 
68:  5f/87/d7",     " 69:  5f/87/ff")] );  
+    push(@arr, [(  " 70:  5f/af/00",     " 71:  5f/af/5f", 
    " 72:  5f/af/87",     " 73:  5f/af/af",     " 
74:  5f/af/d7",     " 75:  5f/af/ff")] );  
+    push(@arr, [(  " 76:  5f/d7/00",     " 77:  5f/d7/5f", 
    " 78:  5f/d7/87",     " 79:  5f/d7/af",     " 
80:  5f/d7/d7",     " 81:  5f/d7/ff")] );  
+    push(@arr, [(  " 82:  5f/ff/00",     " 83:  5f/ff/5f", 
    " 84:  5f/ff/87",     " 85:  5f/ff/af",     " 
86:  5f/ff/d7",     " 87:  5f/ff/ff")] );  
+    push(@arr, [(  " 88:  87/00/00",     " 89:  87/00/5f", 
    " 90:  87/00/87",     " 91:  87/00/af",     " 
92:  87/00/d7",     " 93:  87/00/ff")] );  
+    push(@arr, [(  " 94:  87/5f/00",     " 95:  87/5f/5f", 
    " 96:  87/5f/87",     " 97:  87/5f/af",     " 
98:  87/5f/d7",     " 99:  87/5f/ff")] );  
+    push(@arr, [( " 100: 87/87/00",    " 101: 87/87/5f", 
   " 102: 87/87/87",    " 103: 87/87/af",    " 
104: 87/87/d7",    " 105: 87/87/ff")] );
+    push(@arr, [( " 106: 87/af/00",    " 107: 87/af/5f", 
   " 108: 87/af/87",    " 109: 87/af/af",    " 
110: 87/af/d7",    " 111: 87/af/ff")] );
+    push(@arr, [( " 112: 87/d7/00",    " 113: 87/d7/5f", 
   " 114: 87/d7/87",    " 115: 87/d7/af",    " 
116: 87/d7/d7",    " 117: 87/d7/ff")] );
+    push(@arr, [( " 118: 87/ff/00",    " 119: 87/ff/5f", 
   " 120: 87/ff/87",    " 121: 87/ff/af",    " 
122: 87/ff/d7",    " 123: 87/ff/ff")] );
+    push(@arr, [( " 124: af/00/00",    " 125: af/00/5f", 
   " 126: af/00/87",    " 127: af/00/af",    " 
128: af/00/d7",    " 129: af/00/ff")] );
+    push(@arr, [( " 130: af/5f/00",    " 131: af/5f/5f", 
   " 132: af/5f/87",    " 133: af/5f/af",    " 
134: af/5f/d7",    " 135: af/5f/ff")] );
+    push(@arr, [( " 136: af/87/00",    " 137: af/87/5f", 
   " 138: af/87/87",    " 139: af/87/af",    " 
140: af/87/d7",    " 141: af/87/ff")] );
+    push(@arr, [( " 142: af/af/00",    " 143: af/af/5f", 
   " 144: af/af/87",    " 145: af/af/af",    " 
146: af/af/d7",    " 147: af/af/ff")] );
+    push(@arr, [( " 148: af/d7/00",    " 149: af/d7/5f", 
   " 150: af/d7/87",    " 151: af/d7/af",    " 
152: af/d7/d7",    " 153: af/d7/ff")] );
+    push(@arr, [( " 154: af/ff/00",    " 155: af/ff/5f", 
   " 156: af/ff/87",    " 157: af/ff/af",    " 
158: af/ff/d7",    " 159: af/ff/ff")] );
+    push(@arr, [( " 160: d7/00/00",    " 161: d7/00/5f", 
   " 162: d7/00/87",    " 163: d7/00/af",    " 
164: d7/00/d7",    " 165: d7/00/ff")] );
+    push(@arr, [( " 166: d7/5f/00",    " 167: d7/5f/5f", 
   " 168: d7/5f/87",    " 169: d7/5f/af",    " 
170: d7/5f/d7",    " 171: d7/5f/ff")] );
+    push(@arr, [( " 172: d7/87/00",    " 173: d7/87/5f", 
   " 174: d7/87/87",    " 175: d7/87/af",    " 
176: d7/87/d7",    " 177: d7/87/ff")] );
+    push(@arr, [( " 178: d7/af/00",    " 179: d7/af/5f", 
   " 180: d7/af/87",    " 181: d7/af/af",    " 
182: d7/af/d7",    " 183: d7/af/ff")] );
+    push(@arr, [( " 184: d7/d7/00",    " 185: d7/d7/5f", 
   " 186: d7/d7/87",    " 187: d7/d7/af",    " 
188: d7/d7/d7",    " 189: d7/d7/ff")] );
+    push(@arr, [( " 190: d7/ff/00",    " 191: d7/ff/5f", 
   " 192: d7/ff/87",    " 193: d7/ff/af",    " 
194: d7/ff/d7",    " 195: d7/ff/ff")] );
+    push(@arr, [( " 196: ff/00/00",    " 197: ff/00/5f", 
   " 198: ff/00/87",    " 199: ff/00/af",    " 
200: ff/00/d7",    " 201: ff/00/ff")] );
+    push(@arr, [( " 202: ff/5f/00",    " 203: ff/5f/5f", 
   " 204: ff/5f/87",    " 205: ff/5f/af",    " 
206: ff/5f/d7",    " 207: ff/5f/ff")] );
+    push(@arr, [( " 208: ff/87/00",    " 209: ff/87/5f", 
   " 210: ff/87/87",    " 211: ff/87/af",    " 
212: ff/87/d7",    " 213: ff/87/ff")] );
+    push(@arr, [( " 214: ff/af/00",    " 215: ff/af/5f", 
   " 216: ff/af/87",    " 217: ff/af/af",    " 
218: ff/af/d7",    " 219: ff/af/ff")] );
+    push(@arr, [( " 220: ff/d7/00",    " 221: ff/d7/5f", 
   " 222: ff/d7/87",    " 223: ff/d7/af",    " 
224: ff/d7/d7",    " 225: ff/d7/ff")] );
+    push(@arr, [( " 226: ff/ff/00",    " 227: ff/ff/5f", 
   " 228: ff/ff/87",    " 229: ff/ff/af",    " 
230: ff/ff/d7",    " 231: ff/ff/ff")] );
+    push(@arr, [( " 232: 08/08/08",    " 233: 12/12/12", 
   " 234: 1c/1c/1c",    " 235: 26/26/26",    " 
236: 30/30/30",    " 237: 3a/3a/3a")] );
+    push(@arr, [( " 238: 44/44/44",    " 239: 4e/4e/4e", 
   " 240: 58/58/58",    " 241: 62/62/62",    " 
242: 6c/6c/6c",    " 243: 76/76/76")] );
+    push(@arr, [( " 244: 80/80/80",    " 245: 8a/8a/8a", 
   " 246: 94/94/94",    " 247: 9e/9e/9e",    " 
248: a8/a8/a8",    " 249: b2/b2/b2")] );
+    push(@arr, [( " 250: bc/bc/bc",    " 251: c6/c6/c6", 
   " 252: d0/d0/d0",    " 253: da/da/da",    " 
254: e4/e4/e4",    " 255: ee/ee/ee")] );
+
+    if( $ARGV[0] eq "-s" || $ARGV[1] eq "-s" || $ARGV[2] eq "-s" ){
+        $padding = "    ";
+    }
+    else {
+        
+    }
+
+    # display in reverse order
+    if( $ARGV[0] eq "-r" || $ARGV[1] eq "-r" || $ARGV[2] eq "-r" ){
+        for( $dimone = 0; $dimone < scalar @arr; $dimone++ ) {
+
+            $seed = ($dimone % 6) * -1;
+            for( $dimtwo = 0; $dimtwo < 6; $dimtwo++ ) {
+
+                $movone = $seed;
+                $movtwo = $seed * -1;
+
+                print $arr[$dimone][$dimtwo] . $padding;
+
+                $seed = $seed+1;
+            }
+
+            print "\n";
+        }
+    }
+    else {
+        for( $dimone = 0; $dimone < scalar @arr; $dimone++ ) {
+
+            $seed = ($dimone % 6) * -1;
+            for( $dimtwo = 0; $dimtwo < 6; $dimtwo++ ) {
+
+                $movone = $seed;
+                $movtwo = $seed * -1;
+
+                $newone = $dimone+$movone;
+                $newtwo = $dimtwo+$movtwo;
+
+                if( $newone < scalar @arr ){
+                    print $arr[$newone][$newtwo] . $padding;
+                }
+
+                $seed = $seed+1;
+            }
+
+            print "\n";
+        }
+    }
+    print "\n";
+    print "\n";
+
+}
+else {
+    print " 16:  00/00/00\n";
+    print " 17:  00/00/5f\n";
+    print " 18:  00/00/87\n";
+    print " 19:  00/00/af\n";
+    print " 20:  00/00/d7\n";
+    print " 21:  00/00/ff\n";
+    print " 22:  00/5f/00\n";
+    print " 23:  00/5f/5f\n";
+    print " 24:  00/5f/87\n";
+    print " 25:  00/5f/af\n";
+    print " 26:  00/5f/d7\n";
+    print " 27:  00/5f/ff\n";
+    print " 28:  00/87/00\n";
+    print " 29:  00/87/5f\n";
+    print " 30:  00/87/87\n";
+    print " 31:  00/87/af\n";
+    print " 32:  00/87/d7\n";
+    print " 33:  00/87/ff\n";
+    print " 34:  00/af/00\n";
+    print " 35:  00/af/5f\n";
+    print " 36:  00/af/87\n";
+    print " 37:  00/af/af\n";
+    print " 38:  00/af/d7\n";
+    print " 39:  00/af/ff\n";
+    print " 40:  00/d7/00\n";
+    print " 41:  00/d7/5f\n";
+    print " 42:  00/d7/87\n";
+    print " 43:  00/d7/af\n";
+    print " 44:  00/d7/d7\n";
+    print " 45:  00/d7/ff\n";
+    print " 46:  00/ff/00\n";
+    print " 47:  00/ff/5f\n";
+    print " 48:  00/ff/87\n";
+    print " 49:  00/ff/af\n";
+    print " 50:  00/ff/d7\n";
+    print " 51:  00/ff/ff\n";
+    print " 52:  5f/00/00\n";
+    print " 53:  5f/00/5f\n";
+    print " 54:  5f/00/87\n";
+    print " 55:  5f/00/af\n";
+    print " 56:  5f/00/d7\n";
+    print " 57:  5f/00/ff\n";
+    print " 58:  5f/5f/00\n";
+    print " 59:  5f/5f/5f\n";
+    print " 60:  5f/5f/87\n";
+    print " 61:  5f/5f/af\n";
+    print " 62:  5f/5f/d7\n";
+    print " 63:  5f/5f/ff\n";
+    print " 64:  5f/87/00\n";
+    print " 65:  5f/87/5f\n";
+    print " 66:  5f/87/87\n";
+    print " 67:  5f/87/af\n";
+    print " 68:  5f/87/d7\n";
+    print " 69:  5f/87/ff\n";
+    print " 70:  5f/af/00\n";
+    print " 71:  5f/af/5f\n";
+    print " 72:  5f/af/87\n";
+    print " 73:  5f/af/af\n";
+    print " 74:  5f/af/d7\n";
+    print " 75:  5f/af/ff\n";
+    print " 76:  5f/d7/00\n";
+    print " 77:  5f/d7/5f\n";
+    print " 78:  5f/d7/87\n";
+    print " 79:  5f/d7/af\n";
+    print " 80:  5f/d7/d7\n";
+    print " 81:  5f/d7/ff\n";
+    print " 82:  5f/ff/00\n";
+    print " 83:  5f/ff/5f\n";
+    print " 84:  5f/ff/87\n";
+    print " 85:  5f/ff/af\n";
+    print " 86:  5f/ff/d7\n";
+    print " 87:  5f/ff/ff\n";
+    print " 88:  87/00/00\n";
+    print " 89:  87/00/5f\n";
+    print " 90:  87/00/87\n";
+    print " 91:  87/00/af\n";
+    print " 92:  87/00/d7\n";
+    print " 93:  87/00/ff\n";
+    print " 94:  87/5f/00\n";
+    print " 95:  87/5f/5f\n";
+    print " 96:  87/5f/87\n";
+    print " 97:  87/5f/af\n";
+    print " 98:  87/5f/d7\n";
+    print " 99:  87/5f/ff\n";
+    print " 100 :87/87/00\n";
+    print " 101 :87/87/5f\n";
+    print " 102 :87/87/87\n";
+    print " 103 :87/87/af\n";
+    print " 104 :87/87/d7\n";
+    print " 105 :87/87/ff\n";
+    print " 106 :87/af/00\n";
+    print " 107 :87/af/5f\n";
+    print " 108 :87/af/87\n";
+    print " 109 :87/af/af\n";
+    print " 110 :87/af/d7\n";
+    print " 111 :87/af/ff\n";
+    print " 112 :87/d7/00\n";
+    print " 113 :87/d7/5f\n";
+    print " 114 :87/d7/87\n";
+    print " 115 :87/d7/af\n";
+    print " 116 :87/d7/d7\n";
+    print " 117 :87/d7/ff\n";
+    print " 118 :87/ff/00\n";
+    print " 119 :87/ff/5f\n";
+    print " 120 :87/ff/87\n";
+    print " 121 :87/ff/af\n";
+    print " 122 :87/ff/d7\n";
+    print " 123 :87/ff/ff\n";
+    print " 124 :af/00/00\n";
+    print " 125 :af/00/5f\n";
+    print " 126 :af/00/87\n";
+    print " 127 :af/00/af\n";
+    print " 128 :af/00/d7\n";
+    print " 129 :af/00/ff\n";
+    print " 130 :af/5f/00\n";
+    print " 131 :af/5f/5f\n";
+    print " 132 :af/5f/87\n";
+    print " 133 :af/5f/af\n";
+    print " 134 :af/5f/d7\n";
+    print " 135 :af/5f/ff\n";
+    print " 136 :af/87/00\n";
+    print " 137 :af/87/5f\n";
+    print " 138 :af/87/87\n";
+    print " 139 :af/87/af\n";
+    print " 140 :af/87/d7\n";
+    print " 141 :af/87/ff\n";
+    print " 142 :af/af/00\n";
+    print " 143 :af/af/5f\n";
+    print " 144 :af/af/87\n";
+    print " 145 :af/af/af\n";
+    print " 146 :af/af/d7\n";
+    print " 147 :af/af/ff\n";
+    print " 148 :af/d7/00\n";
+    print " 149 :af/d7/5f\n";
+    print " 150 :af/d7/87\n";
+    print " 151 :af/d7/af\n";
+    print " 152 :af/d7/d7\n";
+    print " 153 :af/d7/ff\n";
+    print " 154 :af/ff/00\n";
+    print " 155 :af/ff/5f\n";
+    print " 156 :af/ff/87\n";
+    print " 157 :af/ff/af\n";
+    print " 158 :af/ff/d7\n";
+    print " 159 :af/ff/ff\n";
+    print " 160 :d7/00/00\n";
+    print " 161 :d7/00/5f\n";
+    print " 162 :d7/00/87\n";
+    print " 163 :d7/00/af\n";
+    print " 164 :d7/00/d7\n";
+    print " 165 :d7/00/ff\n";
+    print " 166 :d7/5f/00\n";
+    print " 167 :d7/5f/5f\n";
+    print " 168 :d7/5f/87\n";
+    print " 169 :d7/5f/af\n";
+    print " 170 :d7/5f/d7\n";
+    print " 171 :d7/5f/ff\n";
+    print " 172 :d7/87/00\n";
+    print " 173 :d7/87/5f\n";
+    print " 174 :d7/87/87\n";
+    print " 175 :d7/87/af\n";
+    print " 176 :d7/87/d7\n";
+    print " 177 :d7/87/ff\n";
+    print " 178 :d7/af/00\n";
+    print " 179 :d7/af/5f\n";
+    print " 180 :d7/af/87\n";
+    print " 181 :d7/af/af\n";
+    print " 182 :d7/af/d7\n";
+    print " 183 :d7/af/ff\n";
+    print " 184 :d7/d7/00\n";
+    print " 185 :d7/d7/5f\n";
+    print " 186 :d7/d7/87\n";
+    print " 187 :d7/d7/af\n";
+    print " 188 :d7/d7/d7\n";
+    print " 189 :d7/d7/ff\n";
+    print " 190 :d7/ff/00\n";
+    print " 191 :d7/ff/5f\n";
+    print " 192 :d7/ff/87\n";
+    print " 193 :d7/ff/af\n";
+    print " 194 :d7/ff/d7\n";
+    print " 195 :d7/ff/ff\n";
+    print " 196 :ff/00/00\n";
+    print " 197 :ff/00/5f\n";
+    print " 198 :ff/00/87\n";
+    print " 199 :ff/00/af\n";
+    print " 200 :ff/00/d7\n";
+    print " 201 :ff/00/ff\n";
+    print " 202 :ff/5f/00\n";
+    print " 203 :ff/5f/5f\n";
+    print " 204 :ff/5f/87\n";
+    print " 205 :ff/5f/af\n";
+    print " 206 :ff/5f/d7\n";
+    print " 207 :ff/5f/ff\n";
+    print " 208 :ff/87/00\n";
+    print " 209 :ff/87/5f\n";
+    print " 210 :ff/87/87\n";
+    print " 211 :ff/87/af\n";
+    print " 212 :ff/87/d7\n";
+    print " 213 :ff/87/ff\n";
+    print " 214 :ff/af/00\n";
+    print " 215 :ff/af/5f\n";
+    print " 216 :ff/af/87\n";
+    print " 217 :ff/af/af\n";
+    print " 218 :ff/af/d7\n";
+    print " 219 :ff/af/ff\n";
+    print " 220 :ff/d7/00\n";
+    print " 221 :ff/d7/5f\n";
+    print " 222 :ff/d7/87\n";
+    print " 223 :ff/d7/af\n";
+    print " 224 :ff/d7/d7\n";
+    print " 225 :ff/d7/ff\n";
+    print " 226 :ff/ff/00\n";
+    print " 227 :ff/ff/5f\n";
+    print " 228 :ff/ff/87\n";
+    print " 229 :ff/ff/af\n";
+    print " 230 :ff/ff/d7\n";
+    print " 231 :ff/ff/ff\n";
+    print " 232 :08/08/08\n";
+    print " 233 :12/12/12\n";
+    print " 234 :1c/1c/1c\n";
+    print " 235 :26/26/26\n";
+    print " 236 :30/30/30\n";
+    print " 237 :3a/3a/3a\n";
+    print " 238 :44/44/44\n";
+    print " 239 :4e/4e/4e\n";
+    print " 240 :58/58/58\n";
+    print " 241 :62/62/62\n";
+    print " 242 :6c/6c/6c\n";
+    print " 243 :76/76/76\n";
+    print " 244 :80/80/80\n";
+    print " 245 :8a/8a/8a\n";
+    print " 246 :94/94/94\n";
+    print " 247 :9e/9e/9e\n";
+    print " 248 :a8/a8/a8\n";
+    print " 249 :b2/b2/b2\n";
+    print " 250 :bc/bc/bc\n";
+    print " 251 :c6/c6/c6\n";
+    print " 252 :d0/d0/d0\n";
+    print " 253 :da/da/da\n";
+    print " 254 :e4/e4/e4\n";
+    print " 255 :ee/ee/ee\n";
+    print "\n";
+    print "\n";
+}
+print "";
+exit;

Index: tests/xterm-colour-chart.py
===================================================================
RCS file: tests/xterm-colour-chart.py
diff -N tests/xterm-colour-chart.py
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/xterm-colour-chart.py 3 Apr 2017 08:33:57 -0000       1.1
@@ -0,0 +1,510 @@
+#!/usr/bin/python
+
+"""
+XTerm Colour Chart 2.0
+
+Ian Ward, 2007
+This file is in the Public Domain, do with it as you wish.
+"""
+
+import sys
+from optparse import OptionParser
+
+__version__ = "2.0"
+
+#  Colour charts
+#  -------------
+#  Anm - colour cube colour where A is a letter between "a" and "f" and 
+#        n and m are numbers between 0 and 5.  eg. "a00" is the one corner
+#        of the cube and "f55" is the opposite corner.  The first coordinate
+#        is given as a letter to help distinguish the boundaries between
+#        colours in the charts.  In 88-colour mode only values "a" through
+#        "d" and 0 through 3 are used.
+#  .nn - basic colour where nn is between 00 and 15.
+#  +nn - gray colour where nn is between 01 and 24 for 256-colour mode
+#        or between 01 and 08 for 88-colour mode.
+
+whale_shape_left = """
+e04d04c04b04
+e03d03c03b03
+e02d02c02b02
+e01d01c01b01
+e00d00c00b00a00a01a02a03a04a05b05c05d05e05f05f04f03f02f01f00
+e10d10c10b10a10a11a12a13a14a15b15c15d15e15f15f14f13f12f11f10
+e20d20c20b20a20a21a22a23a24a25b25c25d25e25f25f24f23f22f21f20
+e30d30c30b30a30a31a32a33a34a35b35c35d35e35f35f34f33f32f31f30
+e40d40c40b40a40a41a42a43a44a45b45c45d45e45f45f44f43f42f41f40
+e50d50c50b50a50a51a52a53a54a55b55c55d55e55f55f54f53f52f51f50
+                              b54c54d54e54
+                              b53c53d53e53
+.00.01.02.03.04.05.06.07      b52c52d52e52
+.08.09.10.11.12.13.14.15      b51c51d51e51
+"""
+
+whale_shape_right = """
+d13c13
+d12c12
+d11c11b11b12b13b14c14d14e14e13e12e11
+d21c21b21b22b23b24c24d24e24e23e22e21
+d31c31b31b32b33b34c34d34e34e33e32e31
+d41c41b41b42b43b44c44d44e44e43e42e41
+                  c43d43            
+                  c42d42
+c22c23d23d22
+c32c33d33d32
+
+
++12+11+10+09+08+07+06+05+04+03+02+01
++13+14+15+16+17+18+19+20+21+22+23+24
+"""
+# join left and right whales
+whale_shape = "\n".join([l.ljust(63)+r for l,r in 
+    zip(whale_shape_left.split("\n"), whale_shape_right.split("\n"))])
+
+whale_shape_88 = """
+c02b02                                    b11b12c12c11  
+c01b01                                    b21b22c22c21
+c00b00a00a01a02a03b03c03d03d02d01d00
+c10b10a10a11a12a13b13c13d13d12d11d10      +08+07+06+05+04+03+02+01
+c20b20a20a21a22a23b23c23d23d22d21d20
+c30b30a30a31a32a33b33c33d33d32d31d30
+                  b32c32                  .00.01.02.03.04.05.06.07
+                  b31c31                  .08.09.10.11.12.13.14.15
+
+"""
+
+cloud_shape = """
+.00.01.02.03.04.05.06.07               c12c13            d13d12      
+.08.09.10.11.12.13.14.15      d11c11b11b12b13b14c14d14e14e13e12e11   
+                              d21c21b21b22b23b24c24d24e24e23e22e21   
+                           e31d31c31b31b32b33b34c34d34e34e33e32         
+         c22c23d23d22      e41d41c41b41b42b43b44c44d44e44e43e42   +01+24
+      d32c32c33d33            d42c42            c43d43            +02+23
+                                                                  +03+22
+                     c02c03                        d03d02         +04+21
+      d01c01      b01b02b03b04      c04d04      e04e03e02e01      +05+20
+   e00d00c00b00a00a01a02a03a04a05b05c05d05e05f05f04f03f02f01f00   +06+19
+   e10d10c10b10a10a11a12a13a14a15b15c15d15e15f15f14f13f12f11f10   +07+18
+   e20d20c20b20a20a21a22a23a24a25b25c25d25e25f25f24f23f22f21f20   +08+17
+f30e30d30c30b30a30a31a32a33a34a35b35c35d35e35f35f34f33f32f31      +09+16
+f40e40d40c40b40a40a41a42a43a44a45b45c45d45e45f45f44f43f42f41      +10+15
+f50e50d50c50b50a50a51a52a53a54a55b55c55d55e55f55f54f53f52f51      +11+14
+   e51d51c51b51      b52b53      b54c54d54e54      e53e52         +12+13 
+      d52c52                        c53d53                        
+"""                                                                      
+
+cloud_shape_88 = """
+                  b11b12c12c11   
+               c21b21b22c22            b01b02            c02c01      
+                              c00b00a00a01a02a03b03c03d03d02d01d00   
++08+07+06+05+04+03+02+01      c10b10a10a11a12a13b13c13d13d12d11d10   
+                           d20c20b20a20a21a22a23b23c23d23d22d21         
+.00.01.02.03.04.05.06.07   d30c30b30a30a31a32a33b33c33d33d32d31
+.08.09.10.11.12.13.14.15      c31b31            b32c32         
+"""
+                                                            
+slices = """
+a00a01a02a03a04a05   c05c04c03c02c01c00   e00e01e02e03e04e05   +01+24   .00.08
+a10a11a12a13a14a15   c15c14c13c12c11c10   e10e11e12e13e14e15   +02+23   .01.09
+a20a21a22a23a24a25   c25c24c23c22c21c20   e20e21e22e23e24e25   +03+22   .02.10
+a30a31a32a33a34a35   c35c34c33c32c31c30   e30e31e32e33e34e35   +04+21   .03.11
+a40a41a42a43a44a45   c45c44c43c42c41c40   e40e41e42e43e44e45   +05+20   .04.12
+a50a51a52a53a54a55   c55c54c53c52c51c50   e50e51e52e53e54e55   +06+19   .05.13
+b50b51b52b53b54b55   d55d54d53d52d51d50   f50f51f52f53f54f55   +07+18   .06.14
+b40b41b42b43b44b45   d45d44d43d42d41d40   f40f41f42f43f44f45   +08+17   .07.15
+b30b31b32b33b34b35   d35d34d33d32d31d30   f30f31f32f33f34f35   +09+16   
+b20b21b22b23b24b25   d25d24d23d22d21d20   f20f21f22f23f24f25   +10+15
+b10b11b12b13b14b15   d15d14d13d12d11d10   f10f11f12f13f14f15   +11+14
+b00b01b02b03b04b05   d05d04d03d02d01d00   f00f01f02f03f04f05   +12+13
+"""
+
+
+slices_88 = """
+a00a01a02a03   c03c02c01c00   +01   .00.08
+a10a11a12a13   c13c12c11c10   +02   .01.09
+a20a21a22a23   c23c22c21c20   +03   .02.10
+a30a31a32a33   c33c32c31c30   +04   .03.11
+b30b31b32b33   d33d32d31d30   +05   .04.12
+b20b21b22b23   d23d22d21d20   +06   .05.13
+b10b11b12b13   d13d12d11d10   +07   .06.14
+b00b01b02b03   d03d02d01d00   +08   .07.15
+"""
+
+
+ribbon_left = """
+a00a01a02a03a04a05b05c05d05e05f05f04f03f02f01f00e00d00c00b00
+a10a11a12a13a14a15b15c15d15e15f15f14f13f12f11f10e10d10c10b10
+a20a21a22a23a24a25b25c25d25e25f25f24f23f22f21f20e20d20c20b20
+a30a31a32a33a34a35b35c35d35e35f35f34f33f32f31f30e30d30c30b30
+a40a41a42a43a44a45b45c45d45e45f45f44f43f42f41f40e40d40c40b40
+a50a51a52a53a54a55b55c55d55e55f55f54f53f52f51f50e50d50c50b50
+
+.00.01.02.03.04.05.06.07   +01+02+03+04+05+06+07+08+09+10+11
+.08.09.10.11.12.13.14.15
+"""
+
+ribbon_right = """
+b01c01d01e01e02e03e04d04c04b04b03c03d03d02c02b02
+b11c11d11e11e12e13e14d14c14b14b13c13d13d12c12b12
+b21c21d21e21e22e23e24d24c24b24b23c23d23d22c22b22
+b31c31d31e31e32e33e34d34c34b34b33c33d33d32c32b32
+b41c41d41e41e42e43e44d44c44b44b43c43d43d42c42b42
+b51c51d51e51e52e53e54d54c54b54b53c53d53d52c52b52
+
++12+13+14+15+16+17+18+19+20+21+22+23+24
+
+"""
+
+ribbon = "\n".join([l+r for l,r in 
+    zip(ribbon_left.split("\n"), ribbon_right.split("\n"))])
+
+ribbon_88 = """
+a00a01a02a03b03c03d03d02d01d00c00c01c02b02b01b00
+a10a11a12a13b13c13d13d12d11d10c10c11c12b12b11b10
+a20a21a22a23b23c23d23d22d21d20c20c21c22b22b21b20
+a30a31a32a33b33c33d33d32d31d30c30c31c32b32b31b30
+                                                            
+.00.01.02.03.04.05.06.07   +01+02+03+04+05+06+07+08
+.08.09.10.11.12.13.14.15
+"""
+
+cow_shape_left = """
++13+14+15+16+17+18+19+20+21+22+23+24         c01   e01
++12+11+10+09+08+07+06+05+04+03+02+01      b02c02d02e02f02
+                                          b03c03d03e03f03f13f23
+               d01   b01                  b04c04d04e04f04f14f24
+      f01f00e00d00c00b00a00a01a02a03a04a05b05c05d05e05f05f15f25
+   f12f11f10e10d10c10b10a10a11a12a13a14a15b15c15d15e15
+f32f22f21f20e20d20c20b20a20a21a22a23a24a25b25c25d25e25
+f42   f31f30e30d30c30b30a30a31a32a33a34a35b35c35d35e35f35
+      f41f40e40d40c40b40a40a41a42a43a44a45b45c45d45e45f45
+      f51f50e50d50c50b50a50a51a52a53a54a55b55c55d55e55f55
+      f52   e51d51c51b51                  b54c54      f54
+      f53   e52d52c52b52                  b53c53      f44
+      f43   e53                              d53      f34
+      f33   e54                              d54         
+"""
+
+cow_shape_right = """
+   c23d23d22
+c32c33d33   
+c22   d32                  c12d12e12
+                           c13d13e13e23
+      e11d11c11b11b12b13b14c14d14e14e24
+   e22e21d21c21b21b22b23b24c24d24
+   e32e31d31c31b31b32b33b34c34d34
+   e33   d41c41b41      b44   d44
+   e34   d42c42b42      c44   d43
+   e44   e42            c43   e43
+         e41            b43
+ 
+.00.01.02.03.04.05.06.07
+.08.09.10.11.12.13.14.15
+"""
+# join left and right cows
+cow_shape = "\n".join([l.ljust(66)+r for l,r in 
+    zip(cow_shape_left.split("\n"), cow_shape_right.split("\n"))])
+
+cow_shape_88 = """
+.00.01.02.03.04.05.06.07      b12c12c11
+.08.09.10.11.12.13.14.15   b21b22c22   
+                           b11   c21
++01+02+03+04+05+06+07+08
+                           b01c01d01
+                           b02c02d02d12
+      d00c00b00a00a01a02a03b03c03d03d13
+   d11d10c10b10a10a11a12a13b13c13
+   d21d20c20b20a20a21a22a23b23c23
+   d22   c30b30a30      a33   c33
+   d23   c31b31a31      b33   c32
+   d33   d31            b32   d32
+         d30            a32
+"""
+
+charts = {
+    88: {
+        'cows': cow_shape_88,
+        'whales': whale_shape_88,
+        'slices': slices_88,
+        'ribbon': ribbon_88,
+        'clouds': cloud_shape_88,},
+    256: {
+        'cows': cow_shape,
+        'whales': whale_shape,
+        'slices': slices,
+        'ribbon': ribbon,
+        'clouds': cloud_shape,}}
+
+# global settings
+
+basic_start = 0 # first index of basic colours
+cube_start = 16 # first index of colour cube
+cube_size = 6 # one side of the colour cube
+gray_start = cube_size ** 3 + cube_start
+colours = 256
+# values copied from xterm 256colres.h:
+cube_steps = 0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff
+gray_steps = (0x08, 0x12, 0x1c, 0x26, 0x30, 0x3a, 0x44, 0x4e, 0x58, 0x62, 
+    0x6c, 0x76, 0x80, 0x84, 0x94, 0x9e, 0xa8, 0xb2, 0xbc, 0xc6, 0xd0,
+    0xda, 0xe4, 0xee)
+# values copied from X11/rgb.txt and XTerm-col.ad:
+basic_colours = ((0,0,0), (205, 0, 0), (0, 205, 0), (205, 205, 0),
+    (0, 0, 238), (205, 0, 205), (0, 205, 205), (229, 229, 229),
+    (127, 127, 127), (255, 0, 0), (0, 255, 0), (255, 255, 0),
+    (0x5c, 0x5c, 0xff), (255, 0, 255), (0, 255, 255), (255, 255, 255))
+
+def set_88_colour_mode():
+    """Switch to 88-colour mode."""
+    global cube_size, gray_start, colours, cube_steps, gray_steps
+    cube_size = 4
+    gray_start = cube_size ** 3 + cube_start
+    colours = 88
+    # values copied from xterm 88colres.h:
+    cube_steps = 0x00, 0x8b, 0xcd, 0xff
+    gray_steps = 0x2e, 0x5c, 0x73, 0x8b, 0xa2, 0xb9, 0xd0, 0xe7 
+
+    
+def error(e):
+    """Report an error to the user."""
+    sys.stderr.write(e+"\n")
+
+def cube_vals(n):
+    """Return the cube coordinates for colour-number n."""
+    assert n>=cube_start and n<gray_start
+    val = n-cube_start
+    c = val % cube_size
+    val = val / cube_size
+    b = val % cube_size
+    a = val / cube_size
+    return a, b, c
+
+def n_to_rgb(n):
+    """Return the red, green and blue components of colour-number n.
+    Components are between 0 and 255."""
+    if n<cube_start:
+        return basic_colours[n-basic_start]
+    if n<gray_start:
+        return [cube_steps[v] for v in cube_vals(n)]
+    return (gray_steps[n-gray_start],) * 3
+
+def n_to_gray(n):
+    """Return an approximate desaturated value for colour-number n.
+    Value is between 0.0 and 255.0."""
+    r, g, b = n_to_rgb(n)
+    return 0.3*r + 0.59*g + 0.11*b
+
+def n_to_prt(n):
+    """Convert a colour number to the format used in the colour charts."""
+    if n >= gray_start:
+        return "+%02d" % (n-gray_start+1)
+    elif n >= cube_start:
+        a, b, c = cube_vals(n)
+        return "%s%s%s" % (chr(ord('a')+a), chr(ord('0')+b), chr(ord('0')+c))
+    else:
+        return ".%02d not found" % (n-basic_start)
+
+def prt_to_n(prt):
+    """Convert a colour chart cell to a colour number."""
+    assert len(prt)==3
+    if prt == '   ':
+        n = -1
+    elif prt[0] == '.':
+        val = int(prt[1:])
+        assert val>=0 and val<cube_start
+        n = basic_start + val
+    elif prt[0] == '+':
+        val = int(prt[1:])-1
+        assert val>=0 and val<colours-gray_start, prt
+        n = gray_start + val
+    else:
+        a = ord(prt[0])-ord('a')
+        assert a>=0 and a<cube_size, prt
+        b = ord(prt[1])-ord('0')
+        assert b>=0 and b<cube_size, prt
+        c = ord(prt[2])-ord('0')
+        assert c>=0 and c<cube_size, prt
+        n = cube_start + (a*cube_size + b)*cube_size + c
+    return n
+
+def distance(n1, n2):
+    """Calculate the distance between colours in the colour cube.
+    Distance is absolute cube coordinates, not actual colour distance.
+    Return -1 if one of the colours is not part of the colour cube."""
+    if n1<cube_start or n1>=gray_start:
+        return -1
+    if n2<cube_start or n2>=gray_start:
+        return -1
+    a1, b1, c1 = cube_vals(n1)
+    a2, b2, c2 = cube_vals(n2)
+    return abs(a1-a2)+abs(b1-b2)+abs(c1-c2)
+
+def parse_chart(chart):
+    """Parse a colour chart passed in as a string."""
+    chart = chart.rstrip()
+    found = set()
+    
+    oall = [] # the complete chart output
+    for ln in chart.split('\n'):
+        oln = [] # the current line of output
+        ln = ln.rstrip()
+        if not oall and not ln:
+            # remove blank lines from top of chart
+            continue
+
+        for loff in range(0, len(ln), 3):
+            prt = ln[loff:loff+3]
+            if not prt:
+                continue
+            n = prt_to_n(prt)
+            if n>=0 and n in found:
+                error("duplicate entry %s found" % prt)
+            found.add(n)
+            if oall and len(oall[-1])>len(oln): # compare distance above
+                nabove = oall[-1][len(oln)]
+                if distance(nabove, n)>1:
+                    error("entry %s found above %s" % (n_to_prt(nabove), prt))
+            if oln: # compare distance to left
+                nleft = oln[-1]
+                if distance(nleft, n)>1:
+                    error("entry %s found left of %s" % (n_to_prt(nleft), prt))
+            oln.append(n)
+        oall.append(oln)
+    
+    # make sure all colours were included in the chart
+    for n in range(colours):
+        if n in found:
+            continue
+        error("entry %s not found" % n_to_prt(n))
+        
+    return oall
+
+
+def draw_chart(chart, origin, angle, numbers, cell_cols, cell_rows):
+    """Draw a colour chart on the screen.
+
+    chart -- chart data parsed by parse_chart()
+    origin -- 0..7 origin of colour cube
+    angle -- 0..5 rotation angle of colour cube
+    numbers -- if True display hex palette numbers on the chart
+    cell_cols -- number of screen columns per cell
+    cell_rows -- number of screen rows per cell
+    """
+    amap = [(0,1,2), (1,2,0), (2,0,1), (0,2,1), (1,0,2), (2,1,0)][angle]
+    omap = [(1,1,1), (1,1,-1), (1,-1,-1), (1,-1,1),
+        (-1,-1,1), (-1,-1,-1), (-1,1,-1), (-1,1,1)][origin]
+
+    if numbers and cell_cols<2:
+        cell_cols=2
+    cell_pad = " "*cell_cols
+    
+    def transform_block(n, row):
+        v = cube_vals(n)
+        v = [(int(om/2) + om * n) % cube_size for n, om in zip(v, omap)]
+        r, g, b = v[amap[0]], v[amap[1]], v[amap[2]]
+        vtrans = (r*cube_size + g)*cube_size + b + cube_start
+        return block(vtrans, row)
+
+    def block(n, row):
+        if not numbers or row!=cell_rows-1:
+            return "\x1b[48;5;%dm%s" % (n, cell_pad)
+        y = n_to_gray(n)
+        if y>0x30:
+            # use black text
+            return "\x1b[48;5;%d;30m%02x%s" % (n, n, cell_pad[2:])
+        # else use gray text
+        return "\x1b[48;5;%d;37m%02x%s" % (n, n, cell_pad[2:])
+
+    def blank():
+        return "\x1b[0m%s" % (cell_pad,)
+
+    for ln in chart:
+        for row in range(cell_rows):
+            out = []
+            for n in ln:
+                if n<0:
+                    out.append(blank())
+                elif n<cube_start:
+                    out.append(block(n, row))
+                elif n<gray_start:
+                    out.append(transform_block(n, row))
+                else:
+                    out.append(block(n, row))
+            print "".join(out) + "\x1b[0m"
+
+def reset_palette():
+    """Reset the terminal palette."""
+    reset = ["%d;rgb:%02x/%02x/%02x" % ((n,) + tuple(n_to_rgb(n)))
+        for n in range(colours)]
+    sys.stdout.write("\x1b]4;"+";".join(reset)+"\x1b\\")
+
+def main(): 
+    parser = OptionParser(usage="%prog [options] [chart names]",
+        version="%prog "+__version__)
+    parser.add_option("-8", "--88-colours", action="store_true", 
+        dest="colours_88", default=False, 
+        help="use 88-colour mode [default: 256-colour mode]")
+    parser.add_option("-l", "--list-charts", action="store_true", 
+        dest="list_charts", default=False,
+        help="list available charts")
+    parser.add_option("-o", "--origin", dest="origin", type="int",
+        default=0, metavar="NUM",
+        help="set the origin of the colour cube: 0-7 [default: %default]")
+    parser.add_option("-a", "--angle", dest="angle", type="int",
+        default=0, metavar="NUM",
+        help="set the angle of the colour cube: 0-5 [default: %default]")
+    parser.add_option("-n", "--numbers", action="store_true",
+        dest="numbers", default=False,
+        help="display hex colour numbers on chart")
+    parser.add_option("-x", "--cell-columns", dest="columns", type="int",
+        default=2, metavar="COLS",
+        help="set the number of columns for drawing each colour cell "
+        "[default: %default]")
+    parser.add_option("-y", "--cell-rows", dest="rows", type="int",
+        default=1, metavar="ROWS",
+        help="set the number of rows for drawing each colour cell "
+        "[default: %default]")
+    parser.add_option("-r", "--reset-palette", action="store_true",
+        dest="reset_palette", default=False,
+        help="reset the colour palette before displaying chart, "
+        "this option may be used to switch between 88 and 256-colour "
+        "modes in xterm")
+
+    options, args = parser.parse_args()
+    if options.origin<0 or options.origin>7:
+        error("Invalid origin value specified!")
+        sys.exit(2)
+    if options.angle<0 or options.angle>5:
+        error("Invalid angle value specified!")
+        sys.exit(2)
+    if options.columns < 1:
+        error("Invalid number of columns specified!")
+    if options.rows < 1:
+        error("Invalid number of rows specified!")
+    if options.colours_88:
+        set_88_colour_mode()
+    if options.list_charts:
+        print "Charts available in %d-colour mode:" % colours
+        for cname in charts[colours].keys():
+            print "  "+cname
+        sys.exit(0)
+    if options.reset_palette:
+        reset_palette()
+    
+    if not args:
+        args = ["whales"] # default chart
+    first = True
+    for cname in args:
+        if not first:
+            print
+        first = False
+        if cname not in charts[colours]:
+            error("Chart %r not found!" % cname)
+            continue
+        chart = parse_chart(charts[colours][cname])
+        draw_chart(chart, options.origin, options.angle, options.numbers,
+            options.columns, options.rows)
+
+
+
+if __name__ == '__main__':
+    main()



reply via email to

[Prev in Thread] Current Thread [Next in Thread]