#define LC_MESSAGES 6
#endif
+struct colormap {
+ char *name;
+ int i_xterm;
+ int i_ansi_fg;
+ int i_ansi_bg;
+};
+
+/* This array maps color names to both the 8-bit 'xterm' color number and the
+ * nearest 4-bit ANSI color. Color names are case-insensitive. Nonstandard
+ * names for colors can be added at the end of the array. */
+static struct colormap xterm_colors[] = {
+ { "Black", 0, 0, 0 },
+ { "Maroon", 1, 1, 1 },
+ { "Green", 2, 2, 2 },
+ { "Olive", 3, 3, 3 },
+ { "Navy", 4, 4, 4 },
+ { "Purple", 5, 5, 5 },
+ { "Teal", 6, 6, 6 },
+ { "Silver", 7, 7, 7 },
+ { "Grey", 8, 8, 3 },
+ { "Red", 9, 9, 1 },
+ { "Lime", 10, 10, 2 },
+ { "Yellow", 11, 11, 3 },
+ { "Blue", 12, 4, 4 },
+ { "Fuchsia", 13, 13, 5 },
+ { "Aqua", 14, 14, 6 },
+ { "White", 15, 15, 7 },
+ { "Grey0", 16, 0, 0 },
+ { "NavyBlue", 17, 0, 0 },
+ { "DarkBlue", 18, 4, 4 },
+ { "Blue3", 19, 4, 4 },
+ { "Blue3", 20, 4, 4 },
+ { "Blue1", 21, 4, 4 },
+ { "DarkGreen", 22, 0, 0 },
+ { "DeepSkyBlue4", 23, 0, 0 },
+ { "DeepSkyBlue4", 24, 6, 6 },
+ { "DeepSkyBlue4", 25, 4, 4 },
+ { "DodgerBlue3", 26, 4, 4 },
+ { "DodgerBlue2", 27, 12, 4 },
+ { "Green4", 28, 2, 2 },
+ { "SpringGreen4", 29, 2, 2 },
+ { "Turquoise4", 30, 6, 6 },
+ { "DeepSkyBlue3", 31, 6, 6 },
+ { "DeepSkyBlue3", 32, 6, 6 },
+ { "DodgerBlue1", 33, 6, 6 },
+ { "Green3", 34, 2, 2 },
+ { "SpringGreen3", 35, 2, 2 },
+ { "DarkCyan", 36, 6, 6 },
+ { "LightSeaGreen", 37, 6, 6 },
+ { "DeepSkyBlue2", 38, 6, 6 },
+ { "DeepSkyBlue1", 39, 6, 6 },
+ { "Green3", 40, 2, 2 },
+ { "SpringGreen3", 41, 2, 2 },
+ { "SpringGreen2", 42, 6, 6 },
+ { "Cyan3", 43, 6, 6 },
+ { "DarkTurquoise", 44, 6, 6 },
+ { "Turquoise2", 45, 14, 6 },
+ { "Green1", 46, 10, 2 },
+ { "SpringGreen2", 47, 10, 2 },
+ { "SpringGreen1", 48, 6, 6 },
+ { "MediumSpringGreen", 49, 6, 6 },
+ { "Cyan2", 50, 14, 6 },
+ { "Cyan1", 51, 14, 6 },
+ { "DarkRed", 52, 0, 0 },
+ { "DeepPink4", 53, 0, 0 },
+ { "Purple4", 54, 5, 5 },
+ { "Purple4", 55, 4, 4 },
+ { "Purple3", 56, 4, 4 },
+ { "BlueViolet", 57, 12, 4 },
+ { "Orange4", 58, 0, 0 },
+ { "Grey37", 59, 8, 0 },
+ { "MediumPurple4", 60, 8, 5 },
+ { "SlateBlue3", 61, 8, 4 },
+ { "SlateBlue3", 62, 12, 4 },
+ { "RoyalBlue1", 63, 12, 4 },
+ { "Chartreuse4", 64, 2, 2 },
+ { "DarkSeaGreen4", 65, 8, 2 },
+ { "PaleTurquoise4", 66, 8, 6 },
+ { "SteelBlue", 67, 8, 6 },
+ { "SteelBlue3", 68, 12, 6 },
+ { "CornflowerBlue", 69, 12, 6 },
+ { "Chartreuse3", 70, 2, 2 },
+ { "DarkSeaGreen4", 71, 8, 2 },
+ { "CadetBlue", 72, 8, 6 },
+ { "CadetBlue", 73, 8, 6 },
+ { "SkyBlue3", 74, 12, 6 },
+ { "SteelBlue1", 75, 12, 6 },
+ { "Chartreuse3", 76, 2, 2 },
+ { "PaleGreen3", 77, 8, 2 },
+ { "SeaGreen3", 78, 8, 6 },
+ { "Aquamarine3", 79, 6, 6 },
+ { "MediumTurquoise", 80, 6, 6 },
+ { "SteelBlue1", 81, 14, 6 },
+ { "Chartreuse2", 82, 10, 2 },
+ { "SeaGreen2", 83, 10, 2 },
+ { "SeaGreen1", 84, 6, 6 },
+ { "SeaGreen1", 85, 6, 6 },
+ { "Aquamarine1", 86, 14, 6 },
+ { "DarkSlateGray2", 87, 14, 6 },
+ { "DarkRed", 88, 1, 1 },
+ { "DeepPink4", 89, 1, 1 },
+ { "DarkMagenta", 90, 5, 5 },
+ { "DarkMagenta", 91, 5, 5 },
+ { "DarkViolet", 92, 5, 5 },
+ { "Purple", 93, 5, 5 },
+ { "Orange4", 94, 1, 1 },
+ { "LightPink4", 95, 8, 1 },
+ { "Plum4", 96, 8, 5 },
+ { "MediumPurple3", 97, 8, 5 },
+ { "MediumPurple3", 98, 12, 5 },
+ { "SlateBlue1", 99, 12, 5 },
+ { "Yellow4", 100, 3, 3 },
+ { "Wheat4", 101, 8, 3 },
+ { "Grey53", 102, 8, 7 },
+ { "LightSlateGrey", 103, 8, 7 },
+ { "MediumPurple", 104, 12, 7 },
+ { "LightSlateBlue", 105, 12, 7 },
+ { "Yellow4", 106, 3, 3 },
+ { "DarkOliveGreen3", 107, 8, 3 },
+ { "DarkSeaGreen", 108, 8, 7 },
+ { "LightSkyBlue3", 109, 8, 7 },
+ { "LightSkyBlue3", 110, 8, 7 },
+ { "SkyBlue2", 111, 12, 7 },
+ { "Chartreuse2", 112, 3, 3 },
+ { "DarkOliveGreen3", 113, 8, 3 },
+ { "PaleGreen3", 114, 8, 7 },
+ { "DarkSeaGreen3", 115, 8, 7 },
+ { "DarkSlateGray3", 116, 7, 7 },
+ { "SkyBlue1", 117, 7, 7 },
+ { "Chartreuse1", 118, 3, 3 },
+ { "LightGreen", 119, 3, 3 },
+ { "LightGreen", 120, 8, 7 },
+ { "PaleGreen1", 121, 7, 7 },
+ { "Aquamarine1", 122, 7, 7 },
+ { "DarkSlateGray1", 123, 7, 7 },
+ { "Red3", 124, 1, 1 },
+ { "DeepPink4", 125, 1, 1 },
+ { "MediumVioletRed", 126, 5, 5 },
+ { "Magenta3", 127, 5, 5 },
+ { "DarkViolet", 128, 5, 5 },
+ { "Purple", 129, 5, 5 },
+ { "DarkOrange3", 130, 1, 1 },
+ { "IndianRed", 131, 8, 1 },
+ { "HotPink3", 132, 8, 5 },
+ { "MediumOrchid3", 133, 8, 5 },
+ { "MediumOrchid", 134, 12, 5 },
+ { "MediumPurple2", 135, 12, 5 },
+ { "DarkGoldenrod", 136, 3, 3 },
+ { "LightSalmon3", 137, 8, 3 },
+ { "RosyBrown", 138, 8, 7 },
+ { "Grey63", 139, 8, 7 },
+ { "MediumPurple2", 140, 8, 7 },
+ { "MediumPurple1", 141, 12, 7 },
+ { "Gold3", 142, 3, 3 },
+ { "DarkKhaki", 143, 8, 3 },
+ { "NavajoWhite3", 144, 8, 7 },
+ { "Grey69", 145, 8, 7 },
+ { "LightSteelBlue3", 146, 7, 7 },
+ { "LightSteelBlue", 147, 7, 7 },
+ { "Yellow3", 148, 3, 3 },
+ { "DarkOliveGreen3", 149, 3, 3 },
+ { "DarkSeaGreen3", 150, 8, 7 },
+ { "DarkSeaGreen2", 151, 7, 7 },
+ { "LightCyan3", 152, 7, 7 },
+ { "LightSkyBlue1", 153, 7, 7 },
+ { "GreenYellow", 154, 3, 3 },
+ { "DarkOliveGreen2", 155, 3, 3 },
+ { "PaleGreen1", 156, 7, 7 },
+ { "DarkSeaGreen2", 157, 7, 7 },
+ { "DarkSeaGreen1", 158, 7, 7 },
+ { "PaleTurquoise1", 159, 7, 7 },
+ { "Red3", 160, 1, 1 },
+ { "DeepPink3", 161, 1, 1 },
+ { "DeepPink3", 162, 5, 5 },
+ { "Magenta3", 163, 5, 5 },
+ { "Magenta3", 164, 5, 5 },
+ { "Magenta2", 165, 13, 5 },
+ { "DarkOrange3", 166, 1, 1 },
+ { "IndianRed", 167, 8, 1 },
+ { "HotPink3", 168, 8, 5 },
+ { "HotPink2", 169, 5, 5 },
+ { "Orchid", 170, 5, 5 },
+ { "MediumOrchid1", 171, 13, 5 },
+ { "Orange3", 172, 3, 3 },
+ { "LightSalmon3", 173, 8, 3 },
+ { "LightPink3", 174, 8, 7 },
+ { "Pink3", 175, 8, 7 },
+ { "Plum3", 176, 7, 7 },
+ { "Violet", 177, 7, 7 },
+ { "Gold3", 178, 3, 3 },
+ { "LightGoldenrod3", 179, 3, 3 },
+ { "Tan", 180, 8, 7 },
+ { "MistyRose3", 181, 7, 7 },
+ { "Thistle3", 182, 7, 7 },
+ { "Plum2", 183, 7, 7 },
+ { "Yellow3", 184, 3, 3 },
+ { "Khaki3", 185, 3, 3 },
+ { "LightGoldenrod2", 186, 7, 7 },
+ { "LightYellow3", 187, 7, 7 },
+ { "Grey84", 188, 7, 7 },
+ { "LightSteelBlue1", 189, 7, 7 },
+ { "Yellow2", 190, 11, 3 },
+ { "DarkOliveGreen1", 191, 11, 3 },
+ { "DarkOliveGreen1", 192, 7, 7 },
+ { "DarkSeaGreen1", 193, 7, 7 },
+ { "Honeydew2", 194, 7, 7 },
+ { "LightCyan1", 195, 7, 7 },
+ { "Red1", 196, 9, 1 },
+ { "DeepPink2", 197, 9, 1 },
+ { "DeepPink1", 198, 5, 5 },
+ { "DeepPink1", 199, 5, 5 },
+ { "Magenta2", 200, 13, 5 },
+ { "Magenta1", 201, 13, 5 },
+ { "OrangeRed1", 202, 9, 1 },
+ { "IndianRed1", 203, 9, 1 },
+ { "IndianRed1", 204, 5, 5 },
+ { "HotPink", 205, 5, 5 },
+ { "HotPink", 206, 13, 5 },
+ { "MediumOrchid1", 207, 13, 5 },
+ { "DarkOrange", 208, 3, 3 },
+ { "Salmon1", 209, 3, 3 },
+ { "LightCoral", 210, 8, 7 },
+ { "PaleVioletRed1", 211, 7, 7 },
+ { "Orchid2", 212, 7, 7 },
+ { "Orchid1", 213, 7, 7 },
+ { "Orange1", 214, 3, 3 },
+ { "SandyBrown", 215, 3, 3 },
+ { "LightSalmon1", 216, 7, 7 },
+ { "LightPink1", 217, 7, 7 },
+ { "Pink1", 218, 7, 7 },
+ { "Plum1", 219, 7, 7 },
+ { "Gold1", 220, 11, 3 },
+ { "LightGoldenrod2", 221, 11, 3 },
+ { "LightGoldenrod2", 222, 7, 7 },
+ { "NavajoWhite1", 223, 7, 7 },
+ { "MistyRose1", 224, 7, 7 },
+ { "Thistle1", 225, 7, 7 },
+ { "Yellow1", 226, 11, 3 },
+ { "LightGoldenrod1", 227, 11, 3 },
+ { "Khaki1", 228, 7, 7 },
+ { "Wheat1", 229, 7, 7 },
+ { "Cornsilk1", 230, 7, 7 },
+ { "Grey100", 231, 15, 7 },
+ { "Grey3", 232, 0, 0 },
+ { "Grey7", 233, 0, 0 },
+ { "Grey11", 234, 0, 0 },
+ { "Grey15", 235, 0, 0 },
+ { "Grey19", 236, 0, 0 },
+ { "Grey23", 237, 0, 0 },
+ { "Grey27", 238, 8, 0 },
+ { "Grey30", 239, 8, 0 },
+ { "Grey35", 240, 8, 0 },
+ { "Grey39", 241, 8, 0 },
+ { "Grey42", 242, 8, 3 },
+ { "Grey46", 243, 8, 3 },
+ { "Grey50", 244, 8, 3 },
+ { "Grey54", 245, 8, 7 },
+ { "Grey58", 246, 8, 7 },
+ { "Grey62", 247, 8, 7 },
+ { "Grey66", 248, 8, 7 },
+ { "Grey70", 249, 7, 7 },
+ { "Grey74", 250, 7, 7 },
+ { "Grey78", 251, 7, 7 },
+ { "Grey82", 252, 7, 7 },
+ { "Grey85", 253, 7, 7 },
+ { "Grey89", 254, 7, 7 },
+ { "Grey93", 255, 7, 7 },
+ { NULL, 0, 0, 0 }
+};
+
+int xterm_to_ansi_fg[256];
+int xterm_to_ansi_bg[256];
+
+HASHTAB htab_xterm_colors; /**< Hash table of color names */
+
HASHTAB htab_tag; /**< Hash table of safe html tags */
#define MAX_COLS 32 /**< Maximum number of columns for align() */
char flags; /**< Ansi text attributes */
char fore; /**< Ansi foreground color */
char back; /**< Ansi background color */
+ int forexterm; /**< Ansi xterm foreground color */
+ int backxterm; /**< Ansi xterm background color */
} ansi_data;
static void dump_ansi_codes(ansi_data * ad, char *buff, char **bp);
/** If we're adding y to x, do we need to add z as well? */
#define EDGE_UP(x,y,z) (((y) & (z)) && !((x) & (z)))
+#define ANSI_XTERM_BG "\x1B[48;5;"
+#define ANSI_XTERM_FG "\x1B[38;5;"
+
static void
dump_ansi_codes(ansi_data * ad, char *buff, char **bp)
{
- static ansi_data old_ad = { 0, 0, 0 };
+ static ansi_data old_ad = { 0, 0, 0, 0, 0 };
int f = 0;
- if ((old_ad.fore && !ad->fore)
- || (old_ad.back && !ad->back)
+ if ( (old_ad.fore && !ad->fore)
+ || (old_ad.back && !ad->back)
+ || (old_ad.forexterm && !ad->forexterm)
+ || (old_ad.backxterm && !ad->backxterm)
|| ((old_ad.flags & ad->flags) != old_ad.flags)) {
safe_str(ANSI_NORMAL, buff, bp);
old_ad.flags = 0;
old_ad.fore = 0;
old_ad.back = 0;
+ old_ad.forexterm = 0;
+ old_ad.backxterm = 0;
}
- if ((old_ad.fore == ad->fore)
+ if ( (old_ad.fore == ad->fore)
&& (old_ad.back == ad->back)
+ && (old_ad.forexterm == ad->forexterm)
+ && (old_ad.backxterm == ad->backxterm)
&& (old_ad.flags == ad->flags))
/* If nothing has changed, don't bother doing anything.
* This stops the entirely pointless \e[m being generated. */
return;
+ /* XTERM always has priority */
+ if ( ad->forexterm || ad->backxterm ) {
+ if ( ad->forexterm ) {
+ safe_str(ANSI_XTERM_FG, buff, bp);
+ safe_integer(ad->forexterm, buff, bp);
+ safe_str(ANSI_END, buff, bp);
+ }
+ if ( ad->backxterm ) {
+ safe_str(ANSI_XTERM_BG, buff, bp);
+ safe_integer(ad->backxterm, buff, bp);
+ safe_str(ANSI_END, buff, bp);
+ }
+ old_ad = *ad;
+ return;
+ }
+
safe_str(ANSI_BEGIN, buff, bp);
if (EDGE_UP(old_ad.flags, ad->flags, COL_FLASH)) {
}
+void
+init_xterm_colors(void)
+{
+ int i;
+
+ hashinit(&htab_xterm_colors, 512, sizeof(struct colormap *));
+
+ for (i = 0; xterm_colors[i].name; i++) {
+ if (i < 256) {
+ xterm_to_ansi_fg[i] = xterm_colors[i].i_ansi_fg;
+ xterm_to_ansi_bg[i] = xterm_colors[i].i_ansi_bg;
+ }
+
+ hashadd(strlower(xterm_colors[i].name),
+ &xterm_colors[i], &htab_xterm_colors);
+ }
+}
/* ARGSUSED */
FUNCTION(fun_ansi)
{
static char tbuff[BUFFER_LEN];
- static ansi_data stack[1024] = { {0, 0, 0} }, *sp = stack;
+ static ansi_data stack[1024] = { {0, 0, 0, 0, 0} }, *sp = stack;
char const *arg0, *arg1;
char *tbp;
+ char *solidus;
+ char *fgname;
+ char *bgname;
+ int fgnum, bgnum;
+ struct colormap *cm;
tbp = tbuff;
arg0 = args[0];
sp[1] = sp[0];
sp++;
- for (tbp = tbuff; *tbp; tbp++) {
- switch (*tbp) {
- case 'n': /* normal */
- sp->flags = 0;
- sp->fore = 0;
- sp->back = 0;
- break;
- case 'f': /* flash */
- sp->flags |= COL_FLASH;
- break;
- case 'h': /* hilite */
- sp->flags |= COL_HILITE;
- break;
- case 'i': /* inverse */
- sp->flags |= COL_INVERT;
- break;
- case 'u': /* underscore */
- sp->flags |= COL_UNDERSCORE;
- break;
- case 'F': /* flash */
- sp->flags &= ~COL_FLASH;
- break;
- case 'H': /* hilite */
- sp->flags &= ~COL_HILITE;
- break;
- case 'I': /* inverse */
- sp->flags &= ~COL_INVERT;
- break;
- case 'U': /* underscore */
- sp->flags &= ~COL_UNDERSCORE;
- break;
- case 'b': /* blue fg */
- sp->fore = COL_BLUE;
- break;
- case 'c': /* cyan fg */
- sp->fore = COL_CYAN;
- break;
- case 'g': /* green fg */
- sp->fore = COL_GREEN;
- break;
- case 'm': /* magenta fg */
- sp->fore = COL_MAGENTA;
- break;
- case 'r': /* red fg */
- sp->fore = COL_RED;
- break;
- case 'w': /* white fg */
- sp->fore = COL_WHITE;
- break;
- case 'x': /* black fg */
- sp->fore = COL_BLACK;
- break;
- case 'y': /* yellow fg */
- sp->fore = COL_YELLOW;
- break;
- case 'B': /* blue bg */
- sp->back = COL_BLUE;
- break;
- case 'C': /* cyan bg */
- sp->back = COL_CYAN;
- break;
- case 'G': /* green bg */
- sp->back = COL_GREEN;
- break;
- case 'M': /* magenta bg */
- sp->back = COL_MAGENTA;
- break;
- case 'R': /* red bg */
- sp->back = COL_RED;
- break;
- case 'W': /* white bg */
- sp->back = COL_WHITE;
- break;
- case 'X': /* black bg */
- sp->back = COL_BLACK;
- break;
- case 'Y': /* yellow bg */
- sp->back = COL_YELLOW;
- break;
+ fgnum = -1;
+ bgnum = -1;
+ solidus = strchr(tbuff, '/');
+ if (solidus) {
+ if (solidus == tbuff) {
+ fgname = NULL;
+ bgname = &solidus[1];
+ } else {
+ fgname = tbuff;
+ solidus[0] = '\0';
+ bgname = &solidus[1];
+ }
+ } else {
+ fgname = tbuff;
+ bgname = NULL;
+ }
+ if (fgname && *fgname) {
+ if (is_integer(fgname)) {
+ fgnum = parse_integer(fgname);
+ if (fgnum < 0 || fgnum > 255)
+ fgnum = -1;
+ }
+ if (fgnum < 0) {
+ cm = hashfind(strlower(fgname), &htab_xterm_colors);
+ if (cm)
+ fgnum = cm->i_xterm;
+ }
+ }
+ if (bgname && *bgname) {
+ if (is_integer(bgname)) {
+ bgnum = parse_integer(bgname);
+ if (bgnum < 0 || bgnum > 255)
+ bgnum = -1;
+ }
+ if (bgnum < 0) {
+ cm = hashfind(strlower(bgname), &htab_xterm_colors);
+ if (cm)
+ bgnum = cm->i_xterm;
+ }
+ }
+
+ if (fgnum != -1)
+ sp->forexterm = fgnum;
+
+ if (bgnum != -1)
+ sp->backxterm = bgnum;
+
+ if (fgnum == -1 && bgnum == -1) {
+ for (tbp = tbuff; *tbp; tbp++) {
+ switch (*tbp) {
+ case 'n': /* normal */
+ sp->flags = 0;
+ sp->fore = 0;
+ sp->back = 0;
+ break;
+ case 'f': /* flash */
+ sp->flags |= COL_FLASH;
+ break;
+ case 'h': /* hilite */
+ sp->flags |= COL_HILITE;
+ break;
+ case 'i': /* inverse */
+ sp->flags |= COL_INVERT;
+ break;
+ case 'u': /* underscore */
+ sp->flags |= COL_UNDERSCORE;
+ break;
+ case 'F': /* flash */
+ sp->flags &= ~COL_FLASH;
+ break;
+ case 'H': /* hilite */
+ sp->flags &= ~COL_HILITE;
+ break;
+ case 'I': /* inverse */
+ sp->flags &= ~COL_INVERT;
+ break;
+ case 'U': /* underscore */
+ sp->flags &= ~COL_UNDERSCORE;
+ break;
+ case 'b': /* blue fg */
+ sp->fore = COL_BLUE;
+ break;
+ case 'c': /* cyan fg */
+ sp->fore = COL_CYAN;
+ break;
+ case 'g': /* green fg */
+ sp->fore = COL_GREEN;
+ break;
+ case 'm': /* magenta fg */
+ sp->fore = COL_MAGENTA;
+ break;
+ case 'r': /* red fg */
+ sp->fore = COL_RED;
+ break;
+ case 'w': /* white fg */
+ sp->fore = COL_WHITE;
+ break;
+ case 'x': /* black fg */
+ sp->fore = COL_BLACK;
+ break;
+ case 'y': /* yellow fg */
+ sp->fore = COL_YELLOW;
+ break;
+ case 'B': /* blue bg */
+ sp->back = COL_BLUE;
+ break;
+ case 'C': /* cyan bg */
+ sp->back = COL_CYAN;
+ break;
+ case 'G': /* green bg */
+ sp->back = COL_GREEN;
+ break;
+ case 'M': /* magenta bg */
+ sp->back = COL_MAGENTA;
+ break;
+ case 'R': /* red bg */
+ sp->back = COL_RED;
+ break;
+ case 'W': /* white bg */
+ sp->back = COL_WHITE;
+ break;
+ case 'X': /* black bg */
+ sp->back = COL_BLACK;
+ break;
+ case 'Y': /* yellow bg */
+ sp->back = COL_YELLOW;
+ break;
+ }
}
}
NA_ASCII = 0, /**< Plain old ascii. */
NA_ANSI, /**< ANSI flag */
NA_COLOR, /**< ANSI and COLOR flags */
+ NA_XTERMCOLOR, /**< XTERMCOLOR flag */
+ NA_TXTERMCOLOR, /**< Like above with telnet-aware client */
+ NA_NXTERMCOLOR, /**< XTERMCOLOR and NOACCENTS */
NA_PUEBLO, /**< html */
NA_PASCII, /**< Player without any of the above */
NA_TANSI, /**< Like above with telnet-aware client */
};
/** Number of possible message text renderings */
-#define MESSAGE_TYPES 12
+#define MESSAGE_TYPES 15
#define TA_BGC 0 /**< Text attribute background color */
#define TA_FGC 1 /**< Text attribute foreground color */
#define TA_REV 3 /**< Text attribute reverse/inverse */
#define TA_BLINK 4 /**< Text attribute blinking/flashing */
#define TA_ULINE 5 /**< Text attribute underline */
+#define TA_XTERMFG 6 /**< Xterm color, foreground */
+#define TA_XTERMBG 7 /**< Xterm color, background */
static int na_depth = 0;
struct notify_strings messages[],
enum na_type type);
+extern int xterm_to_ansi_fg[];
+extern int xterm_to_ansi_bg[];
static void
-fillstate(int state[6], const unsigned char **f)
+fillstate(int state[8], const unsigned char **f)
{
const unsigned char *p;
int i;
- int n;
+ int n, m;
p = *f;
p++;
if (*p != '[') {
while (*p && *p != 'm') {
if ((*p > '9') || (*p < '0')) {
/* Nada */
- } else if (!(*(p + 1)) || (*(p + 1) == 'm') || (*(p + 1) == ';')) {
+ p++;
+ } else if (!p[1] || p[1] == 'm' || p[1] == ';') {
/* ShortCode */ ;
switch (*p) {
case '0':
- for (i = 0; i < 6; i++)
+ for (i = 0; i < 8; i++)
state[i] = 0;
break;
case '1':
state[TA_ULINE] = 1;
break;
}
+ p++;
} else {
n = (*p - '0') * 10;
p++;
n += (*p - '0');
- if ((n >= 30) && (n <= 37))
+ p++;
+ if ((n >= 30) && (n <= 37)) {
state[TA_FGC] = n - 29;
- else if ((n >= 40) && (n <= 47))
+ } else if ((n >= 40) && (n <= 47)) {
state[TA_BGC] = n - 39;
+ } else if ((n == 38) || (n == 48)) {
+ if (p[0] == ';' && p[1] == '5' && p[2] == ';') {
+ p = &p[3];
+ m = 0;
+ while (*p >= '0' && *p <= '9') {
+ m = m * 10 + *p - '0';
+ p++;
+ }
+ if (n == 38) {
+ state[TA_XTERMFG] = m + 1;
+ } else {
+ state[TA_XTERMBG] = m + 1;
+ }
+ }
+ }
}
- p++;
}
}
if ((p != *f) && (*p != 'm'))
p--;
*f = p;
+
+ if (state[TA_FGC] && !state[TA_XTERMFG]) {
+ switch (state[TA_FGC]) {
+ case 1: /* Black */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 244; /* Grey50 */
+ else
+ state[TA_XTERMFG] = 0; /* Black */
+ break;
+ case 2: /* Red */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 9; /* Red */
+ else
+ state[TA_XTERMFG] = 160; /* Red3 */
+ break;
+ case 3: /* Green */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 2; /* Green */
+ else
+ state[TA_XTERMFG] = 40; /* Green3 */
+ break;
+ case 4: /* Yellow */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 11; /* Yellow */
+ else
+ state[TA_XTERMFG] = 148; /* Yellow3 */
+ break;
+ case 5: /* Blue */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 63; /* RoyalBlue1 */
+ else
+ state[TA_XTERMFG] = 20; /* Blue3 */
+ break;
+ case 6: /* Magenta */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 201; /* Magenta1 */
+ else
+ state[TA_XTERMFG] = 164; /* Magenta3 */
+ break;
+ case 7: /* Cyan */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 51; /* Cyan1 */
+ else
+ state[TA_XTERMFG] = 43; /* Cyan3 */
+ break;
+ case 8: /* White */
+ if (state[TA_BOLD])
+ state[TA_XTERMFG] = 15; /* White */
+ else
+ state[TA_XTERMFG] = 254; /* Grey89 */
+ break;
+ }
+ state[TA_XTERMFG] += 1;
+ } else if (state[TA_XTERMFG]) {
+ state[TA_FGC] = xterm_to_ansi_fg[state[TA_XTERMFG] - 1] + 1;
+ if (state[TA_FGC] > 8) {
+ state[TA_FGC] -= 8;
+ state[TA_BOLD] = 1;
+ }
+ }
+
+ if (state[TA_BGC] && !state[TA_XTERMBG]) {
+ switch (state[TA_BGC]) {
+ case 1: /* Black */
+ state[TA_XTERMBG] = 0; /* Black */
+ break;
+ case 2: /* Red */
+ state[TA_XTERMBG] = 160; /* Red3 */
+ break;
+ case 3: /* Green */
+ state[TA_XTERMBG] = 40; /* Green3 */
+ break;
+ case 4: /* Yellow */
+ state[TA_XTERMBG] = 148; /* Yellow3 */
+ break;
+ case 5: /* Blue */
+ state[TA_XTERMBG] = 20; /* Blue3 */
+ break;
+ case 6: /* Magenta */
+ state[TA_XTERMBG] = 164; /* Magenta3 */
+ break;
+ case 7: /* Cyan */
+ state[TA_XTERMBG] = 43; /* Cyan3 */
+ break;
+ case 8: /* White */
+ state[TA_XTERMBG] = 254; /* Grey89 */
+ break;
+ }
+ state[TA_XTERMBG] += 1;
+ } else if (state[TA_XTERMBG]) {
+ state[TA_BGC] = xterm_to_ansi_bg[state[TA_XTERMBG] - 1] + 1;
+ }
}
/** Add an ansi tag if it's needed here */
(state[TA_BLINK] && !newstate[TA_BLINK]) ||
(state[TA_ULINE] && !newstate[TA_ULINE]) ||
(color && state[TA_FGC] && !newstate[TA_FGC]) ||
- (color && state[TA_BGC] && !newstate[TA_BGC])) {
- for (n = 0; n < 6; n++)
+ (color && state[TA_BGC] && !newstate[TA_BGC]) ||
+ (color > 1 && state[TA_XTERMFG] && !newstate[TA_XTERMFG]) ||
+ (color > 1 && state[TA_XTERMBG] && !newstate[TA_XTERMBG])) {
+ for (n = 0; n < 8; n++)
state[n] = 0;
safe_str(ANSI_NORMAL, t, o);
}
(newstate[TA_BLINK] && (newstate[TA_BLINK] != state[TA_BLINK])) ||
(newstate[TA_ULINE] && (newstate[TA_ULINE] != state[TA_ULINE])) ||
(color && newstate[TA_FGC] && (newstate[TA_FGC] != state[TA_FGC])) ||
- (color && newstate[TA_BGC] && (newstate[TA_BGC] != state[TA_BGC]))) {
+ (color && newstate[TA_BGC] && (newstate[TA_BGC] != state[TA_BGC])) ||
+ (color > 1 && newstate[TA_XTERMFG] &&
+ (newstate[TA_XTERMFG] != state[TA_XTERMFG])) ||
+ (color > 1 && newstate[TA_XTERMBG] &&
+ (newstate[TA_XTERMBG] != state[TA_XTERMBG]))) {
safe_chr(ESC_CHAR, t, o);
safe_chr('[', t, o);
i = 0;
add_ansi_if(TA_REV, "7");
add_ansi_if(TA_BLINK, "5");
add_ansi_if(TA_ULINE, "4");
- if (color) {
+ switch (color) {
+ case 2: /* XTERM */
+ add_ansi_if(TA_XTERMFG, tprintf("38;5;%u", newstate[TA_XTERMFG] - 1));
+ add_ansi_if(TA_XTERMBG, tprintf("48;5;%u", newstate[TA_XTERMBG] - 1));
+ break;
+ case 1: /* ANSI */
add_ansi_if(TA_FGC, unparse_integer(newstate[TA_FGC] + 29));
add_ansi_if(TA_BGC, unparse_integer(newstate[TA_BGC] + 39));
+ break;
}
safe_chr('m', t, o);
}
- for (n = 0; n < 6; n++)
+ for (n = 0; n < 8; n++)
state[n] = newstate[n];
}
char *o;
const unsigned char *p;
char *t;
- int state[6] = { 0, 0, 0, 0, 0, 0 };
- int newstate[6] = { 0, 0, 0, 0, 0, 0 };
+ int state[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ int newstate[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int changed = 0;
int color = 0;
int strip = 0;
case NA_COLOR:
case NA_TCOLOR:
case NA_NCOLOR:
- color = 1;
+ case NA_XTERMCOLOR:
+ case NA_TXTERMCOLOR:
+ case NA_NXTERMCOLOR:
+ if (type == NA_XTERMCOLOR)
+ color = 2;
+ else
+ color = 1;
/* FALLTHROUGH */
case NA_ANSI:
case NA_TANSI:
case NA_NANSI:
- if (type == NA_NCOLOR || type == NA_NANSI || type == NA_NPUEBLO)
+ if (type == NA_NCOLOR || type == NA_NANSI || type == NA_NPUEBLO ||
+ type == NA_NXTERMCOLOR)
strip = 1;
while (*p) {
switch ((unsigned char) *p) {
changed = 0;
ansi_change_state(t, &o, color, state, newstate);
}
- if (type == NA_TANSI || type == NA_TCOLOR)
+ if (type == NA_TANSI || type == NA_TCOLOR || type == NA_TXTERMCOLOR)
safe_str("\xFF\xFF", t, &o);
else if (strip && accent_table[IAC].base)
safe_str(accent_table[IAC].base, t, &o);
}
if (state[TA_BOLD] || state[TA_REV] ||
state[TA_BLINK] || state[TA_ULINE] ||
- (color && (state[TA_FGC] || state[TA_BGC])))
+ (color && (state[TA_FGC] || state[TA_BGC]
+ || state[TA_XTERMFG] || state[TA_XTERMBG])))
safe_str(ANSI_NORMAL, t, &o);
break;
if (d->conn_flags & CONN_HTML) {
poutput = strip ? NA_NPUEBLO : NA_PUEBLO;
} else if (ShowAnsi(d->player)) {
- if (ShowAnsiColor(d->player)) {
+ if (ShowXtermColor(d->player)) {
+ if (strip)
+ poutput = NA_NXTERMCOLOR;
+ else
+ poutput = (d->conn_flags & CONN_TELNET) ? NA_TXTERMCOLOR : NA_XTERMCOLOR;
+ } else if (ShowAnsiColor(d->player)) {
if (strip)
poutput = NA_NCOLOR;
else