/*************************************************************************** * 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; }