From 6deb4714235582644142e6028274757f90cfc2bf Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Sun, 10 May 2015 09:55:44 +0200
Subject: degesch: halfplement mIRC formatting
Now for the displaying part.
---
degesch.c | 154 ++++++++++++++++++++++++++++++++++++++------------------------
1 file changed, 94 insertions(+), 60 deletions(-)
diff --git a/degesch.c b/degesch.c
index 924032f..012e54a 100644
--- a/degesch.c
+++ b/degesch.c
@@ -1465,7 +1465,13 @@ serialize_configuration (struct app_context *ctx, struct str *output)
config_item_write (ctx->config.root, true, output);
}
-// --- Attributed output -------------------------------------------------------
+// --- Terminal output ---------------------------------------------------------
+
+/// Default color pair
+#define COLOR_DEFAULT -1
+
+/// Bright versions of the basic color set
+#define COLOR_BRIGHT(x) (COLOR_ ## x + 8)
static struct
{
@@ -1721,7 +1727,14 @@ enum formatter_item_type
FORMATTER_ITEM_TEXT, ///< Text
FORMATTER_ITEM_ATTR, ///< Formatting attributes
FORMATTER_ITEM_FG_COLOR, ///< Foreground color
- FORMATTER_ITEM_BG_COLOR ///< Background color
+ FORMATTER_ITEM_BG_COLOR, ///< Background color
+
+ // These are internal, for mIRC formatting only so far:
+
+ FORMATTER_ITEM_BOLD, ///< Bold
+ FORMATTER_ITEM_ITALIC, ///< Italic
+ FORMATTER_ITEM_UNDERLINE, ///< Underline
+ FORMATTER_ITEM_INVERSE ///< Inverse
};
struct formatter_item
@@ -1850,83 +1863,104 @@ enum
// without the bold/blink attributes), 88 colors (the same plus a 4^3 RGB cube
// and a few shades of gray), or 256 colors (best)
-#define FORMATTER_NORMAL 0
-#define FORMATTER_BRIGHT 1 << 8
-
-#define FORMATTER_MAP(name, flags, c256) \
- COLOR_ ## name | FORMATTER_ ## flags | c256 << 16
-
-static const uint32_t g_mirc_to_term[] =
-{
- [MIRC_WHITE] = FORMATTER_MAP (WHITE, BRIGHT, 231),
- [MIRC_BLACK] = FORMATTER_MAP (BLACK, NORMAL, 16),
- [MIRC_BLUE] = FORMATTER_MAP (BLUE, NORMAL, 19),
- [MIRC_GREEN] = FORMATTER_MAP (GREEN, NORMAL, 34),
- [MIRC_L_RED] = FORMATTER_MAP (RED, BRIGHT, 196),
- [MIRC_RED] = FORMATTER_MAP (RED, NORMAL, 124),
- [MIRC_PURPLE] = FORMATTER_MAP (MAGENTA, NORMAL, 127),
- [MIRC_ORANGE] = FORMATTER_MAP (YELLOW, BRIGHT, 214),
- [MIRC_YELLOW] = FORMATTER_MAP (YELLOW, BRIGHT, 226),
- [MIRC_L_GREEN] = FORMATTER_MAP (GREEN, BRIGHT, 46),
- [MIRC_CYAN] = FORMATTER_MAP (CYAN, NORMAL, 37),
- [MIRC_L_CYAN] = FORMATTER_MAP (CYAN, BRIGHT, 51),
- [MIRC_L_BLUE] = FORMATTER_MAP (BLUE, BRIGHT, 21),
- [MIRC_L_PURPLE] = FORMATTER_MAP (MAGENTA, BRIGHT, 201),
- [MIRC_GRAY] = FORMATTER_MAP (BLACK, BRIGHT, 244),
- [MIRC_L_GRAY] = FORMATTER_MAP (WHITE, NORMAL, 252),
+/// Builds a color pair for 256-color terminals with a 16-color backup value
+#define FORMATTER_COLOR(name, c256) \
+ (COLOR_ ## name) & 0xFFFF | ((c256 << 16) & 0xFFFF)
+
+static const int g_mirc_to_term[] =
+{
+ [MIRC_WHITE] = FORMATTER_COLOR (BRIGHT (WHITE), 231),
+ [MIRC_BLACK] = FORMATTER_COLOR (BLACK, 16),
+ [MIRC_BLUE] = FORMATTER_COLOR (BLUE, 19),
+ [MIRC_GREEN] = FORMATTER_COLOR (GREEN, 34),
+ [MIRC_L_RED] = FORMATTER_COLOR (BRIGHT (RED), 196),
+ [MIRC_RED] = FORMATTER_COLOR (RED, 124),
+ [MIRC_PURPLE] = FORMATTER_COLOR (MAGENTA, 127),
+ [MIRC_ORANGE] = FORMATTER_COLOR (BRIGHT (YELLOW), 214),
+ [MIRC_YELLOW] = FORMATTER_COLOR (BRIGHT (YELLOW), 226),
+ [MIRC_L_GREEN] = FORMATTER_COLOR (BRIGHT (GREEN), 46),
+ [MIRC_CYAN] = FORMATTER_COLOR (CYAN, 37),
+ [MIRC_L_CYAN] = FORMATTER_COLOR (BRIGHT (CYAN), 51),
+ [MIRC_L_BLUE] = FORMATTER_COLOR (BRIGHT (BLUE), 21),
+ [MIRC_L_PURPLE] = FORMATTER_COLOR (BRIGHT (MAGENTA),201),
+ [MIRC_GRAY] = FORMATTER_COLOR (BRIGHT (BLACK), 244),
+ [MIRC_L_GRAY] = FORMATTER_COLOR (WHITE, 252),
};
static void
-formatter_parse_mirc (struct formatter *self, const char *s)
+formatter_add_simple (struct formatter *self, enum formatter_item_type type)
{
- struct str buffer;
- str_init (&buffer);
+ if (!self->ignore_new_attributes)
+ formatter_add_blank (self)->type = type;
+}
+
+static const char *
+formatter_parse_mirc_color (struct formatter *self, const char *s)
+{
+ if (!isdigit_ascii (*s))
+ return s;
+
+ int fg = *s++ - '0';
+ if (isdigit_ascii (*s))
+ fg = fg * 10 + (*s++ - '0');
+ if (fg >= 0 && fg < 16)
+ formatter_add_fg_color (self, g_mirc_to_term[fg]);
+
+ if (*s != ',' || !isdigit_ascii (s[1]))
+ return s;
-#define FLUSH if (buffer.len) \
- { formatter_add_text (self, buffer.str); str_reset (&buffer); }
+ int bg = *++s - '0';
+ if (isdigit_ascii (s[1]))
+ bg = bg * 10 + (*++s - '0');
+ if (bg >= 0 && bg < 16)
+ formatter_add_bg_color (self, g_mirc_to_term[bg]);
+
+ return s;
+}
+
+static void
+formatter_parse_mirc (struct formatter *self, const char *s)
+{
+ struct str buf;
+ str_init (&buf);
formatter_add_reset (self);
char c;
while ((c = *s++))
{
+ if (buf.len && c < 0x20)
+ {
+ formatter_add_text (self, buf.str);
+ str_reset (&buf);
+ }
+
+#define SIMPLE(type) formatter_add_simple (self, FORMATTER_ITEM_ ## type)
+
switch (c)
{
- case '\x02':
- FLUSH
- // TODO: bold
- break;
+ case '\x02': SIMPLE (BOLD); break;
+ case '\x1d': SIMPLE (ITALIC); break;
+ case '\x1f': SIMPLE (UNDERLINE); break;
+ case '\x16': SIMPLE (INVERSE); break;
+
+#undef SIMPLE
+
case '\x03':
- FLUSH
- // TODO: color
- // TODO: parse \d(\d(,\d(\d)?)?)?
- break;
- case '\x1d':
- FLUSH
- // TODO: italic
- break;
- case '\x1f':
- FLUSH
- // TODO: underline
- break;
- case '\x16':
- FLUSH
- // TODO: swap background/foreground
+ s = formatter_parse_mirc_color (self, s);
break;
case '\x0f':
- FLUSH
formatter_add_reset (self);
break;
default:
- str_append_c (&buffer, c);
+ str_append_c (&buf, c);
}
}
- FLUSH
- str_free (&buffer);
-
-#undef FLUSH
+ if (buf.len)
+ formatter_add_text (self, buf.str);
+ str_free (&buf);
formatter_add_reset (self);
}
@@ -1953,10 +1987,6 @@ restart:
str_append_c (buf, ' ');
str_append (buf, s);
break;
- case 'm':
- s = va_arg (*ap, char *);
- formatter_parse_mirc (self, s);
- break;
case 'd':
s = xstrdup_printf ("%d", va_arg (*ap, int));
for (size_t len = strlen (s); len < width; len++)
@@ -1965,6 +1995,10 @@ restart:
free (s);
break;
+ case 'm':
+ formatter_parse_mirc (self, va_arg (*ap, char *));
+ break;
+
case 'a':
formatter_add_attr (self, va_arg (*ap, int));
break;
--
cgit v1.2.3-70-g09d2