/*
xterm 256 color code parser by Igor van den Hoven
v1.0 02/11/2009
v1.4 06/24/2011 v1.4.2 06/30/2011
This code is placed in the public domain.
*/
/*
For xterm 256 color foreground colors use:
<aaa> to <fff> for RGB foreground colors
<g00> to <g23> for grayscale foreground colors
For xterm 256 color background colors use:
<AAA> to <FFF> for RGB background colors
<G00> to <G23> for grayscale background colors
Background color support is commented out by default
With 256 colors disabled colors are converted to 16 color ANSI.
*/
/*
For 32 color codes use:
^a - dark azure ^A - azure
^b - dark blue ^B - blue
^c - dark cyan ^C - cyan
^e - dark ebony ^E - ebony
^g - dark green ^G - green
^j - dark jade ^J - jade
^l - dark lime ^L - lime
^m - dark magenta ^M - magenta
^o - dark orange ^O - orange
^p - dark pink ^P - pink
^r - dark red ^R - red
^s - dark silver ^S - silver
^t - dark tan ^T - tan
^v - dark violet ^V - violet
^w - dark white ^W - white
^y - dark yellow ^Y - yellow
With 256 colors disabled colors are converted to 16 color ANSI.
*/
#include <stdio.h>
#include <string.h>
/*
256 to 16 color conversion table
*/
char *ansi_colors[256] =
{
"\e[22;30m", "\e[22;31m", "\e[22;32m", "\e[22;33m", "\e[22;34m", "\e[22;35m", "\e[22;36m", "\e[22;37m",
"\e[1;30m", "\e[1;31m", "\e[1;32m", "\e[1;33m", "\e[1;34m", "\e[1;35m", "\e[1;36m", "\e[1;37m",
"\e[22;30m", "\e[22;34m", "\e[22;34m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m", "\e[1;36m",
"\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[1;30m", "\e[22;34m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[1;34m", "\e[1;34m",
"\e[22;32m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[22;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m", "\e[1;36m",
"\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;37m", "\e[22;34m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;32m", "\e[22;36m", "\e[22;36m", "\e[1;34m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[22;36m", "\e[1;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m",
"\e[22;31m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;35m",
"\e[22;31m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[22;35m", "\e[1;35m",
"\e[22;33m", "\e[22;33m", "\e[22;31m", "\e[22;35m", "\e[22;35m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[22;37m", "\e[1;34m", "\e[1;34m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[1;32m", "\e[1;36m", "\e[1;36m",
"\e[1;33m", "\e[1;33m", "\e[1;32m", "\e[1;32m", "\e[1;36m", "\e[1;36m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[22;35m", "\e[1;35m", "\e[1;35m",
"\e[22;33m", "\e[22;33m", "\e[22;33m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;31m", "\e[1;31m", "\e[1;35m", "\e[1;35m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;33m", "\e[1;37m", "\e[1;37m",
"\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m",
"\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m", "\e[1;30m",
"\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m", "\e[22;37m",
"\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m", "\e[1;37m"
};
/*
32 to 256 color conversion table
*/
char *alphabet_colors_dark[26] =
{
"<abd>", "<aad>", "<add>", "", "<g04>", "", "<ada>", "", "", "<adb>", "", "<bda>", "<dad>",
"", "<dba>", "<dab>", "", "<daa>", "<ccc>", "<cba>", "", "<bad>", "<ddd>", "", "<dda>", ""
};
char *alphabet_colors_bold[26] =
{
"<acf>", "<aaf>", "<aff>", "", "<bbb>", "", "<afa>", "", "", "<afc>", "", "<cfa>", "<faf>",
"", "<fca>", "<fac>", "", "<faa>", "<eee>", "<eda>", "", "<caf>", "<fff>", "", "<ffa>", ""
};
// Make sure that the output buffer remains at least 4 times larger than the user input buffer.
// colors should either be 0 for no colors, 16 for ansi colors, or 256 for xterm 256 colors.
int substitute_color(char *input, char *output, int colors)
{
char *pti, *pto, old[6] = { 0 };
pti = input;
pto = output;
while (*pti)
{
switch (*pti)
{
case '^':
if (isalpha(pti[1]))
{
if (pti[2] == '^' && isalpha(pti[3]))
{
pti += 2;
continue;
}
if (strncmp(old, pti, 2) && colors)
{
if (pti[1] >= 'a' && pti[1] <= 'z')
{
pto += substitute_color(alphabet_colors_dark[pti[1] - 'a'], pto, colors);
}
else
{
pto += substitute_color(alphabet_colors_bold[pti[1] - 'A'], pto, colors);
}
}
pti += sprintf(old, "%c%c", pti[0], pti[1]);
}
else
{
if (pti[1] == '^')
{
pti++;
}
*pto++ = *pti++;
}
break;
case '<':
if (pti[1] >= 'a' && pti[1] <= 'f' && pti[2] >= 'a' && pti[2] <= 'f' && pti[3] >= 'a' && pti[3] <= 'f' && pti[4] == '>')
{
if (strncmp(old, pti, 5) && colors)
{
if (colors == 256)
{
pto += sprintf(pto, "\033[38;5;%dm", 16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a'));
}
else
{
pto += substitute_color(ansi_colors[16 + (pti[1] - 'a') * 36 + (pti[2] - 'a') * 6 + (pti[3] - 'a')], pto, colors);
}
}
pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
}
/*
else if (pti[1] >= 'A' && pti[1] <= 'F' && pti[2] >= 'A' && pti[2] <= 'F' && pti[3] >= 'A' && pti[3] <= 'F' && pti[4] == '>')
{
if (colors == 256)
{
pto += sprintf(pto, "\033[48;5;%dm", 16 + (pti[1] - 'A') * 36 + (pti[2] - 'A') * 6 + (pti[3] - 'A'));
}
else if (colors)
{
pto += sprintf(pto, "\033[4%dm", (pti[1] && pti[1] >= pti[2] ? pti[1] >= pti[3] : 0) + (pti[2] && pti[2] >= pti[1] ? pti[2] >= pti[3] : 0) * 2 + (pti[3] && pti[3] >= pti[2] ? pti[3] >= pti[1] : 0) * 4);
}
pti += 5;
}
*/
else if (pti[1] == 'g' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && (pti[2] - '0') * 10 + (pti[3] - '0') >= 0 && (pti[2] - '0') * 10 + (pti[3] - '0') < 24 && pti[4] == '>')
{
if (strncmp(old, pti, 5) && colors)
{
if (colors == 256)
{
pto += sprintf(pto, "\033[38;5;%dm", 232 + (pti[2] - '0') * 10 + (pti[3] - '0'));
}
else
{
pto += substitute_color(ansi_colors[232 + (pti[2] - '0') * 10 + (pti[3] - '0')], pto, colors);
}
}
pti += sprintf(old, "<%c%c%c>", pti[1], pti[2], pti[3]);
}
/*
else if (pti[1] == 'G' && isdigit((int) pti[2]) && isdigit((int) pti[3]) && (pti[2] - '0') * 10 + (pti[3] - '0') >= 0 && (pti[2] - '0') * 10 + (pti[3] - '0') < 24 && pti[4] == '>')
{
if (colors == 256)
{
pto += sprintf(pto, "\033[48;5;%dm", 232 + (pti[2] - '0') * 10 + (pti[3] - '0'));
}
else if (colors)
{
pto += sprintf(pto, "\033[4%dm", ((pti[2] - '0') * 10 + (pti[3] - '0')) / 12 ? 7 : 0);
}
pti += 5;
}
*/
else
{
*pto++ = *pti++;
}
break;
default:
*pto++ = *pti++;
break;
}
}
*pto = 0;
return pto - output;
}
/*
Compile for an example display
*/
int main(int argc, char **argv)
{
char buf[8000], tmp[8000], out[8000];
int x, y, z;
/*
Foreground
*/
for (x = 'a' ; x <= 'f' ; x++)
{
for (y = 'a' ; y <= 'f' ; y++)
{
buf[0] = 0;
for (z = 'a' ; z <= 'f' ; z++)
{
sprintf(tmp, "<%c%c%c><<%c%c%c>%c%c%c><aaa> ", x, y, z, x, y, z, x, y, z);
strcat(buf, tmp);
}
substitute_color(buf, out, 256);
printf("%s ", out);
substitute_color(buf, out, 16);
printf("%s\n", out);
}
}
buf[0] = 0;
for (x = 0 ; x < 24 ; x++)
{
sprintf(tmp, "<g%02d>%02d<ddd> ", x, x);
strcat(buf, tmp);
}
substitute_color(buf, out, 256);
printf("\n%s\n", out);
substitute_color(buf, out, 16);
printf("%s\n\n", out);
substitute_color(
" ^a - dark azure ^A - azure\n"
" ^b - dark blue ^B - blue\n"
" ^c - dark cyan ^C - cyan\n"
" ^e - dark ebony (black) ^E - ebony\n"
" ^g - dark green ^G - green\n"
" ^j - dark jade ^J - jade\n"
" ^l - dark lime (chartreuse) ^L - lime\n"
" ^m - dark magenta ^M - magenta\n"
" ^o - dark orange ^O - orange\n"
" ^p - dark pink (rose) ^P - pink\n"
" ^r - dark red ^R - red\n"
" ^s - dark silver ^S - silver\n"
" ^t - dark tan (brown) ^T - tan\n"
" ^v - dark violet ^V - violet\n"
" ^w - dark white ^W - white\n"
" ^y - dark yellow ^Y - yellow\n", out, 256);
printf("%s\n", out);
return 0;
}