summaryrefslogtreecommitdiff
path: root/src/plugins/irc/irc-color.c
diff options
context:
space:
mode:
authorSébastien Helleu <flashcode@flashtux.org>2023-11-01 13:21:06 +0100
committerSébastien Helleu <flashcode@flashtux.org>2023-11-01 13:21:06 +0100
commit082cbe519bd14453fc4669758a81ff8d9ed6baca (patch)
tree41011b09c1b90f51cde5f51b074a9fc2ed5d26a5 /src/plugins/irc/irc-color.c
parent6d69cde18674105e63b2c85e9a3cd996c8a3a3ea (diff)
downloadweechat-082cbe519bd14453fc4669758a81ff8d9ed6baca.zip
irc: add support of RGB colors in messages (issue #2025)
This is made using standard color code '\x04' followed by text color (RGB as hexadecimal) and optional background (RGB as hexadecimal).
Diffstat (limited to 'src/plugins/irc/irc-color.c')
-rw-r--r--src/plugins/irc/irc-color.c349
1 files changed, 264 insertions, 85 deletions
diff --git a/src/plugins/irc/irc-color.c b/src/plugins/irc/irc-color.c
index 012cfa5cd..b110fcfbc 100644
--- a/src/plugins/irc/irc-color.c
+++ b/src/plugins/irc/irc-color.c
@@ -84,6 +84,121 @@ regex_t *irc_color_regex_ansi = NULL;
/*
+ * Converts a RGB color to terminal color.
+ *
+ * Returns a terminal color (between 0 and 255), -1 if error.
+ */
+
+int
+irc_color_convert_rgb2term (long rgb)
+{
+ char str_color[64], *info_color, *error;
+ long number;
+
+ if (rgb < 0)
+ return -1;
+
+ snprintf (str_color, sizeof (str_color), "%ld", rgb);
+
+ info_color = weechat_info_get ("color_rgb2term", str_color);
+ if (!info_color || !info_color[0])
+ {
+ if (info_color)
+ free (info_color);
+ return -1;
+ }
+
+ error = NULL;
+ number = strtol (info_color, &error, 10);
+ if (!error || error[0])
+ {
+ free (info_color);
+ return -1;
+ }
+
+ free (info_color);
+
+ return (int)number;
+}
+
+/*
+ * Converts a RGB color to IRC color.
+ *
+ * Returns a IRC color number (between 0 and 15), -1 if error.
+ */
+
+int
+irc_color_convert_rgb2irc (long rgb)
+{
+ char str_color[64], *error, *info_color;
+ long number;
+
+ if (rgb < 0)
+ return -1;
+
+ snprintf (str_color, sizeof (str_color),
+ "%ld,%d",
+ rgb,
+ IRC_COLOR_TERM2IRC_NUM_COLORS);
+
+ info_color = weechat_info_get ("color_rgb2term", str_color);
+ if (!info_color || !info_color[0])
+ {
+ if (info_color)
+ free (info_color);
+ return -1;
+ }
+
+ error = NULL;
+ number = strtol (info_color, &error, 10);
+ if (!error || error[0]
+ || (number < 0) || (number >= IRC_COLOR_TERM2IRC_NUM_COLORS))
+ {
+ free (info_color);
+ return -1;
+ }
+
+ free (info_color);
+
+ return irc_color_term2irc[number];
+}
+
+/*
+ * Converts a terminal color to IRC color.
+ *
+ * Returns a IRC color number (between 0 and 15), -1 if error.
+ */
+
+int
+irc_color_convert_term2irc (int color)
+{
+ char str_color[64], *error, *info_color;
+ long number;
+
+ snprintf (str_color, sizeof (str_color), "%d", color);
+
+ info_color = weechat_info_get ("color_term2rgb", str_color);
+ if (!info_color || !info_color[0])
+ {
+ if (info_color)
+ free (info_color);
+ return -1;
+ }
+
+ error = NULL;
+ number = strtol (info_color, &error, 10);
+ if (!error || error[0] || (number < 0) || (number > 0xFFFFFF))
+ {
+ free (info_color);
+ return -1;
+ }
+
+ free (info_color);
+
+ return irc_color_convert_rgb2irc (number);
+}
+
+/*
* Replaces IRC colors by WeeChat colors.
*
* If keep_colors == 0: removes any color/style in message otherwise keeps
@@ -95,11 +210,12 @@ regex_t *irc_color_regex_ansi = NULL;
char *
irc_color_decode (const char *string, int keep_colors)
{
- char **out;
- char str_fg[3], str_bg[3], str_color[128], str_key[128], str_to_add[128];
+ char **out, *error;
+ char str_fg[16], str_bg[16], str_color[128], str_key[128], str_to_add[128];
const char *remapped_color;
unsigned char *ptr_string;
- int length, fg, bg, bold, reverse, italic, underline, rc;
+ int length, fg, bg, bold, reverse, italic, underline, color_number;
+ long fg_rgb, bg_rgb;
if (!string)
return NULL;
@@ -211,19 +327,21 @@ irc_color_decode (const char *string, int keep_colors)
bg = -1;
if (str_fg[0])
{
- rc = sscanf (str_fg, "%d", &fg);
- if ((rc != EOF) && (rc >= 1))
- {
+ error = NULL;
+ fg = (int)strtol (str_fg, &error, 10);
+ if (error && !error[0])
fg %= IRC_NUM_COLORS;
- }
+ else
+ fg = -1;
}
if (str_bg[0])
{
- rc = sscanf (str_bg, "%d", &bg);
- if ((rc != EOF) && (rc >= 1))
- {
+ error = NULL;
+ bg = (int)strtol (str_bg, &error, 10);
+ if (error && !error[0])
bg %= IRC_NUM_COLORS;
- }
+ else
+ bg = -1;
}
/* search "fg,bg" in hashtable of remapped colors */
snprintf (str_key, sizeof (str_key), "%d,%d", fg, bg);
@@ -253,6 +371,94 @@ irc_color_decode (const char *string, int keep_colors)
}
}
break;
+ case IRC_COLOR_HEX_COLOR_CHAR:
+ ptr_string++;
+ str_fg[0] = '\0';
+ str_bg[0] = '\0';
+ if (isxdigit (ptr_string[0]))
+ {
+ /* foreground */
+ length = 1;
+ while (isxdigit (ptr_string[length]))
+ {
+ length++;
+ if (length == 6)
+ break;
+ }
+ memcpy (str_fg, ptr_string, length);
+ str_fg[length] = '\0';
+ ptr_string += length;
+ }
+ if ((ptr_string[0] == ',') && (isxdigit (ptr_string[1])))
+ {
+ /* background */
+ ptr_string++;
+ length = 1;
+ while (isxdigit (ptr_string[length]))
+ {
+ length++;
+ if (length == 6)
+ break;
+ }
+ memcpy (str_bg, ptr_string, length);
+ str_bg[length] = '\0';
+ ptr_string += length;
+ }
+ if (keep_colors)
+ {
+ if (str_fg[0] || str_bg[0])
+ {
+ fg_rgb = -1;
+ bg_rgb = -1;
+ if (str_fg[0])
+ {
+ error = NULL;
+ fg_rgb = strtol (str_fg, &error, 16);
+ if (!error || error[0])
+ fg_rgb = -1;
+ }
+ if (str_bg[0])
+ {
+ error = NULL;
+ bg_rgb = strtol (str_bg, &error, 16);
+ if (!error || error[0])
+ bg_rgb = -1;
+ }
+ str_fg[0] = '\0';
+ str_bg[0] = '\0';
+ if (fg_rgb >= 0)
+ {
+ color_number = irc_color_convert_rgb2term (fg_rgb);
+ if (color_number >= 0)
+ {
+ snprintf (str_fg, sizeof (str_fg),
+ "%d", color_number);
+ }
+ }
+ if (bg_rgb >= 0)
+ {
+ color_number = irc_color_convert_rgb2term (bg_rgb);
+ if (color_number >= 0)
+ {
+ snprintf (str_bg, sizeof (str_bg),
+ "%d", color_number);
+ }
+ }
+ snprintf (str_color, sizeof (str_color),
+ "|%s%s%s",
+ str_fg,
+ (str_bg[0]) ? "," : "",
+ str_bg);
+ snprintf (str_to_add, sizeof (str_to_add), "%s",
+ weechat_color (str_color));
+ }
+ else
+ {
+ snprintf (str_to_add, sizeof (str_to_add), "%s",
+ weechat_color ("resetcolor"));
+ }
+ }
+ break;
default:
/*
* we are not on an IRC color code, just copy the UTF-8 char
@@ -364,6 +570,53 @@ irc_color_encode (const char *string, int keep_colors)
}
}
break;
+ case 0x04: /* ^D */
+ if (keep_colors)
+ weechat_string_dyn_concat (out, IRC_COLOR_HEX_COLOR_STR, -1);
+ ptr_string++;
+ if (isxdigit (ptr_string[0]))
+ {
+ /* foreground */
+ length = 1;
+ while (isxdigit (ptr_string[length]))
+ {
+ length++;
+ if (length == 6)
+ break;
+ }
+ if (keep_colors)
+ {
+ weechat_string_dyn_concat (out,
+ (const char *)ptr_string,
+ length);
+ }
+ ptr_string += length;
+ }
+ if (ptr_string[0] == ',')
+ {
+ /* background */
+ if (keep_colors)
+ weechat_string_dyn_concat (out, ",", -1);
+ ptr_string++;
+ if (isxdigit (ptr_string[0]))
+ {
+ length = 1;
+ while (isxdigit (ptr_string[length]))
+ {
+ length++;
+ if (length == 6)
+ break;
+ }
+ if (keep_colors)
+ {
+ weechat_string_dyn_concat (out,
+ (const char *)ptr_string,
+ length);
+ }
+ ptr_string += length;
+ }
+ }
+ break;
case 0x0F: /* ^O */
if (keep_colors)
weechat_string_dyn_concat (out, IRC_COLOR_RESET_STR, -1);
@@ -399,80 +652,6 @@ irc_color_encode (const char *string, int keep_colors)
}
/*
- * Converts a RGB color to IRC color.
- *
- * Returns a IRC color number (between 0 and 15), -1 if error.
- */
-
-int
-irc_color_convert_rgb2irc (int rgb)
-{
- char str_color[64], *error, *info_color;
- long number;
-
- snprintf (str_color, sizeof (str_color),
- "%d,%d",
- rgb,
- IRC_COLOR_TERM2IRC_NUM_COLORS);
-
- info_color = weechat_info_get ("color_rgb2term", str_color);
- if (!info_color || !info_color[0])
- {
- if (info_color)
- free (info_color);
- return -1;
- }
-
- error = NULL;
- number = strtol (info_color, &error, 10);
- if (!error || error[0]
- || (number < 0) || (number >= IRC_COLOR_TERM2IRC_NUM_COLORS))
- {
- free (info_color);
- return -1;
- }
-
- free (info_color);
-
- return irc_color_term2irc[number];
-}
-
-/*
- * Converts a terminal color to IRC color.
- *
- * Returns a IRC color number (between 0 and 15), -1 if error.
- */
-
-int
-irc_color_convert_term2irc (int color)
-{
- char str_color[64], *error, *info_color;
- long number;
-
- snprintf (str_color, sizeof (str_color), "%d", color);
-
- info_color = weechat_info_get ("color_term2rgb", str_color);
- if (!info_color || !info_color[0])
- {
- if (info_color)
- free (info_color);
- return -1;
- }
-
- error = NULL;
- number = strtol (info_color, &error, 10);
- if (!error || error[0] || (number < 0) || (number > 0xFFFFFF))
- {
- free (info_color);
- return -1;
- }
-
- free (info_color);
-
- return irc_color_convert_rgb2irc (number);
-}
-
-/*
* Replaces ANSI colors by IRC colors (or removes them).
*
* This callback is called by irc_color_decode_ansi, it must not be called