/***************************************************************************
* Mud Telopt Handler 1.4 by Igor van den Hoven. 10 Jun 2011 *
***************************************************************************/
/*
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[0;30m", "\e[0;31m", "\e[0;32m", "\e[0;33m", "\e[0;34m", "\e[0;35m", "\e[0;36m", "\e[0;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[0;30m", "\e[0;34m", "\e[0;34m", "\e[0;34m", "\e[1;34m", "\e[1;34m",
"\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[0;34m", "\e[1;34m", "\e[1;34m",
"\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[0;36m", "\e[1;34m", "\e[1;34m",
"\e[0;32m", "\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[0;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[0;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[0;31m", "\e[0;35m", "\e[0;35m", "\e[0;34m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[1;30m", "\e[0;34m", "\e[0;34m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[1;34m", "\e[1;34m",
"\e[0;32m", "\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[0;36m", "\e[1;36m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[0;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[0;31m", "\e[0;35m", "\e[0;35m", "\e[0;35m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[0;31m", "\e[0;35m", "\e[0;35m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[0;33m", "\e[0;37m", "\e[0;34m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[0;33m", "\e[0;32m", "\e[0;36m", "\e[0;36m", "\e[1;34m",
"\e[1;32m", "\e[1;32m", "\e[1;32m", "\e[0;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[0;31m", "\e[0;31m", "\e[0;35m", "\e[0;35m", "\e[0;35m", "\e[1;35m",
"\e[0;31m", "\e[0;31m", "\e[0;35m", "\e[0;35m", "\e[0;35m", "\e[1;35m",
"\e[0;33m", "\e[0;33m", "\e[0;31m", "\e[0;35m", "\e[0;35m", "\e[1;34m",
"\e[0;33m", "\e[0;33m", "\e[0;33m", "\e[0;37m", "\e[1;34m", "\e[1;34m",
"\e[0;33m", "\e[0;33m", "\e[0;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[0;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[0;35m", "\e[1;35m", "\e[1;35m",
"\e[1;31m", "\e[1;31m", "\e[1;31m", "\e[0;35m", "\e[1;35m", "\e[1;35m",
"\e[0;33m", "\e[0;33m", "\e[0;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[0;37m", "\e[0;37m", "\e[0;37m", "\e[0;37m", "\e[0;37m", "\e[0;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] == '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
{
*pto++ = *pti++;
}
break;
default:
*pto++ = *pti++;
break;
}
}
*pto = 0;
return pto - output;
}