[BACK]Return to colour.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/colour.c, Revision 1.5

1.5     ! nicm        1: /* $OpenBSD: colour.c,v 1.4 2011/08/22 10:14:15 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20:
1.3       nicm       21: #include <ctype.h>
1.2       nicm       22: #include <stdlib.h>
1.1       nicm       23: #include <string.h>
                     24:
                     25: #include "tmux.h"
                     26:
1.2       nicm       27: /*
                     28:  * Colour to string conversion functions. Bit 8 of the colour means it is one
                     29:  * of the 256 colour palette.
                     30:  */
                     31:
1.3       nicm       32: /* An RGB colour. */
                     33: struct colour_rgb {
                     34:        u_char  r;
                     35:        u_char  g;
                     36:        u_char  b;
                     37: };
                     38:
                     39: /* 256 colour RGB table, generated on first use. */
                     40: struct colour_rgb *colour_rgb_256;
                     41:
                     42: void   colour_rgb_generate256(void);
1.4       nicm       43: u_int  colour_rgb_distance(struct colour_rgb *, struct colour_rgb *);
1.3       nicm       44: int    colour_rgb_find(struct colour_rgb *);
                     45:
                     46: /* Generate 256 colour RGB table. */
                     47: void
                     48: colour_rgb_generate256(void)
                     49: {
                     50:        struct colour_rgb       *rgb;
                     51:        u_int                    i, r, g, b;
                     52:
                     53:        /*
                     54:         * Allocate the table. The first 16 colours are often changed by users
                     55:         * and terminals so don't include them.
                     56:         */
                     57:        colour_rgb_256 = xcalloc(240, sizeof *colour_rgb_256);
                     58:
                     59:        /* Add the colours first. */
                     60:        r = g = b = 0;
                     61:        for (i = 240; i > 24; i--) {
                     62:                rgb = &colour_rgb_256[240 - i];
                     63:
                     64:                if (r != 0)
                     65:                        rgb->r = (r * 40) + 55;
                     66:                if (g != 0)
                     67:                        rgb->g = (g * 40) + 55;
                     68:                if (b != 0)
                     69:                        rgb->b = (b * 40) + 55;
                     70:
                     71:                b++;
                     72:                if (b > 5) {
                     73:                        b = 0;
                     74:                        g++;
                     75:                }
                     76:                if (g > 5) {
                     77:                        g = 0;
                     78:                        r++;
                     79:                }
                     80:        }
                     81:
                     82:        /* Then add the greys. */
                     83:        for (i = 24; i > 0; i--) {
                     84:                rgb = &colour_rgb_256[240 - i];
                     85:
                     86:                rgb->r = 8 + (24 - i) * 10;
                     87:                rgb->g = 8 + (24 - i) * 10;
                     88:                rgb->b = 8 + (24 - i) * 10;
                     89:        }
                     90: }
                     91:
                     92: /* Get colour RGB distance. */
1.4       nicm       93: u_int
1.3       nicm       94: colour_rgb_distance(struct colour_rgb *rgb1, struct colour_rgb *rgb2)
                     95: {
                     96:        int     r, g, b;
                     97:
                     98:        r = rgb1->r - rgb2->r;
                     99:        g = rgb1->g - rgb2->g;
                    100:        b = rgb1->b - rgb2->b;
1.4       nicm      101:        return (r * r + g * g + b * b);
1.3       nicm      102: }
                    103:
                    104: /* Work out the nearest colour from the 256 colour set. */
                    105: int
                    106: colour_rgb_find(struct colour_rgb *rgb)
                    107: {
1.4       nicm      108:        u_int   distance, lowest, colour, i;
1.3       nicm      109:
                    110:        if (colour_rgb_256 == NULL)
                    111:                colour_rgb_generate256();
                    112:
                    113:        colour = 16;
1.4       nicm      114:        lowest = UINT_MAX;
1.3       nicm      115:        for (i = 0; i < 240; i++) {
                    116:                distance = colour_rgb_distance(&colour_rgb_256[i], rgb);
                    117:                if (distance < lowest) {
                    118:                        lowest = distance;
                    119:                        colour = 16 + i;
                    120:                }
                    121:        }
                    122:        return (colour);
                    123: }
                    124:
                    125: /* Set grid cell foreground colour. */
1.2       nicm      126: void
                    127: colour_set_fg(struct grid_cell *gc, int c)
                    128: {
                    129:        if (c & 0x100)
                    130:                gc->flags |= GRID_FLAG_FG256;
                    131:        gc->fg = c;
                    132: }
                    133:
1.3       nicm      134: /* Set grid cell background colour. */
1.2       nicm      135: void
                    136: colour_set_bg(struct grid_cell *gc, int c)
                    137: {
                    138:        if (c & 0x100)
                    139:                gc->flags |= GRID_FLAG_BG256;
                    140:        gc->bg = c;
                    141: }
                    142:
1.3       nicm      143: /* Convert colour to a string. */
1.1       nicm      144: const char *
1.2       nicm      145: colour_tostring(int c)
1.1       nicm      146: {
1.2       nicm      147:        static char     s[32];
                    148:
                    149:        if (c & 0x100) {
                    150:                xsnprintf(s, sizeof s, "colour%u", c & ~0x100);
                    151:                return (s);
                    152:        }
                    153:
1.1       nicm      154:        switch (c) {
                    155:        case 0:
                    156:                return ("black");
                    157:        case 1:
                    158:                return ("red");
                    159:        case 2:
                    160:                return ("green");
                    161:        case 3:
                    162:                return ("yellow");
                    163:        case 4:
                    164:                return ("blue");
                    165:        case 5:
                    166:                return ("magenta");
                    167:        case 6:
                    168:                return ("cyan");
                    169:        case 7:
                    170:                return ("white");
                    171:        case 8:
                    172:                return ("default");
1.5     ! nicm      173:        case 90:
        !           174:                return ("brightblack");
        !           175:        case 91:
        !           176:                return ("brightred");
        !           177:        case 92:
        !           178:                return ("brightgreen");
        !           179:        case 93:
        !           180:                return ("brightyellow");
        !           181:        case 94:
        !           182:                return ("brightblue");
        !           183:        case 95:
        !           184:                return ("brightmagenta");
        !           185:        case 96:
        !           186:                return ("brightcyan");
        !           187:        case 97:
        !           188:                return ("brightwhite");
1.1       nicm      189:        }
                    190:        return (NULL);
                    191: }
                    192:
1.3       nicm      193: /* Convert colour from string. */
1.1       nicm      194: int
                    195: colour_fromstring(const char *s)
                    196: {
1.3       nicm      197:        const char              *errstr;
                    198:        const char              *cp;
                    199:        struct colour_rgb        rgb;
                    200:        int                      n;
                    201:
                    202:        if (*s == '#' && strlen(s) == 7) {
                    203:                for (cp = s + 1; isxdigit((u_char) *cp); cp++)
                    204:                        ;
                    205:                if (*cp != '\0')
                    206:                        return (-1);
                    207:                n = sscanf(s + 1, "%2hhx%2hhx%2hhx", &rgb.r, &rgb.g, &rgb.b);
                    208:                if (n != 3)
                    209:                        return (-1);
                    210:                return (colour_rgb_find(&rgb) | 0x100);
                    211:        }
1.2       nicm      212:
                    213:        if (strncasecmp(s, "colour", (sizeof "colour") - 1) == 0) {
                    214:                n = strtonum(s + (sizeof "colour") - 1, 0, 255, &errstr);
                    215:                if (errstr != NULL)
                    216:                        return (-1);
                    217:                return (n | 0x100);
                    218:        }
                    219:
1.1       nicm      220:        if (strcasecmp(s, "black") == 0 || (s[0] == '0' && s[1] == '\0'))
                    221:                return (0);
                    222:        if (strcasecmp(s, "red") == 0 || (s[0] == '1' && s[1] == '\0'))
                    223:                return (1);
                    224:        if (strcasecmp(s, "green") == 0 || (s[0] == '2' && s[1] == '\0'))
                    225:                return (2);
                    226:        if (strcasecmp(s, "yellow") == 0 || (s[0] == '3' && s[1] == '\0'))
                    227:                return (3);
                    228:        if (strcasecmp(s, "blue") == 0 || (s[0] == '4' && s[1] == '\0'))
                    229:                return (4);
                    230:        if (strcasecmp(s, "magenta") == 0 || (s[0] == '5' && s[1] == '\0'))
                    231:                return (5);
                    232:        if (strcasecmp(s, "cyan") == 0 || (s[0] == '6' && s[1] == '\0'))
                    233:                return (6);
                    234:        if (strcasecmp(s, "white") == 0 || (s[0] == '7' && s[1] == '\0'))
                    235:                return (7);
                    236:        if (strcasecmp(s, "default") == 0 || (s[0] == '8' && s[1] == '\0'))
                    237:                return (8);
1.5     ! nicm      238:        if (strcasecmp(s, "brightblack") == 0 ||
        !           239:            (s[0] == '9' && s[1] == '0' && s[1] == '\0'))
        !           240:                return (90);
        !           241:        if (strcasecmp(s, "brightred") == 0 ||
        !           242:            (s[0] == '9' && s[1] == '1' && s[1] == '\0'))
        !           243:                return (91);
        !           244:        if (strcasecmp(s, "brightgreen") == 0 ||
        !           245:            (s[0] == '9' && s[1] == '2' && s[1] == '\0'))
        !           246:                return (92);
        !           247:        if (strcasecmp(s, "brightyellow") == 0 ||
        !           248:            (s[0] == '9' && s[1] == '3' && s[1] == '\0'))
        !           249:                return (93);
        !           250:        if (strcasecmp(s, "brightblue") == 0 ||
        !           251:            (s[0] == '9' && s[1] == '4' && s[1] == '\0'))
        !           252:                return (94);
        !           253:        if (strcasecmp(s, "brightmagenta") == 0 ||
        !           254:            (s[0] == '9' && s[1] == '5' && s[1] == '\0'))
        !           255:                return (95);
        !           256:        if (strcasecmp(s, "brightcyan") == 0 ||
        !           257:            (s[0] == '9' && s[1] == '6' && s[1] == '\0'))
        !           258:                return (96);
        !           259:        if (strcasecmp(s, "brightwhite") == 0 ||
        !           260:            (s[0] == '9' && s[1] == '7' && s[1] == '\0'))
        !           261:                return (97);
1.1       nicm      262:        return (-1);
                    263: }
                    264:
1.3       nicm      265: /* Convert 256 colour palette to 16. */
1.1       nicm      266: u_char
                    267: colour_256to16(u_char c)
                    268: {
                    269:        static const u_char table[256] = {
                    270:                 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
                    271:                 0,  4,  4,  4, 12, 12,  2,  6,  4,  4, 12, 12,  2,  2,  6,  4,
                    272:                12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10,
                    273:                10, 10, 10, 14,  1,  5,  4,  4, 12, 12,  3,  8,  4,  4, 12, 12,
                    274:                 2,  2,  6,  4, 12, 12,  2,  2,  2,  6, 12, 12, 10, 10, 10, 10,
                    275:                14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  5,  4, 12, 12,  1,  1,
                    276:                 5,  4, 12, 12,  3,  3,  8,  4, 12, 12,  2,  2,  2,  6, 12, 12,
                    277:                10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,  1,  1,  1,  5,
                    278:                12, 12,  1,  1,  1,  5, 12, 12,  1,  1,  1,  5, 12, 12,  3,  3,
                    279:                 3,  7, 12, 12, 10, 10, 10, 10, 14, 12, 10, 10, 10, 10, 10, 14,
                    280:                 9,  9,  9,  9, 13, 12,  9,  9,  9,  9, 13, 12,  9,  9,  9,  9,
                    281:                13, 12,  9,  9,  9,  9, 13, 12, 11, 11, 11, 11,  7, 12, 10, 10,
                    282:                10, 10, 10, 14,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,
                    283:                 9,  9,  9,  9,  9, 13,  9,  9,  9,  9,  9, 13,  9,  9,  9,  9,
                    284:                 9, 13, 11, 11, 11, 11, 11, 15,  0,  0,  0,  0,  0,  0,  8,  8,
                    285:                 8,  8,  8,  8,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15
                    286:        };
                    287:
                    288:        return (table[c]);
                    289: }
                    290:
1.3       nicm      291: /* Convert 256 colour palette to 88. */
1.1       nicm      292: u_char
                    293: colour_256to88(u_char c)
                    294: {
                    295:        static const u_char table[256] = {
                    296:                 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
                    297:                16, 17, 17, 18, 18, 19, 20, 21, 21, 22, 22, 23, 20, 21, 21, 22,
                    298:                22, 23, 24, 25, 25, 26, 26, 27, 24, 25, 25, 26, 26, 27, 28, 29,
                    299:                29, 30, 30, 31, 32, 33, 33, 34, 34, 35, 36, 37, 37, 38, 38, 39,
                    300:                36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43, 40, 41, 41, 42,
                    301:                42, 43, 44, 45, 45, 46, 46, 47, 32, 33, 33, 34, 34, 35, 36, 37,
                    302:                37, 38, 38, 39, 36, 37, 37, 38, 38, 39, 40, 41, 41, 42, 42, 43,
                    303:                40, 41, 41, 42, 42, 43, 44, 45, 45, 46, 46, 47, 48, 49, 49, 50,
                    304:                50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54, 54, 55, 56, 57,
                    305:                57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61, 61, 62, 62, 63,
                    306:                48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 55, 52, 53, 53, 54,
                    307:                54, 55, 56, 57, 57, 58, 58, 59, 56, 57, 57, 58, 58, 59, 60, 61,
                    308:                61, 62, 62, 63, 64, 65, 65, 66, 66, 67, 68, 69, 69, 70, 70, 71,
                    309:                68, 69, 69, 70, 70, 71, 72, 73, 73, 74, 74, 75, 72, 73, 73, 74,
                    310:                74, 75, 76, 77, 77, 78, 78, 79,  0,  0, 80, 80, 80, 81, 81, 81,
                    311:                82, 82, 82, 83, 83, 83, 84, 84, 84, 85, 85, 85, 86, 86, 86, 87
                    312:        };
                    313:
                    314:        return (table[c]);
                    315: }