1
0
mirror of https://github.com/weechat/weechat.git synced 2026-06-30 06:46:38 +02:00

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).
This commit is contained in:
Sébastien Helleu
2023-11-01 13:21:06 +01:00
parent 6d69cde186
commit 082cbe519b
13 changed files with 448 additions and 125 deletions
+264 -85
View File
@@ -83,6 +83,121 @@ char irc_color_term2irc[IRC_COLOR_TERM2IRC_NUM_COLORS] =
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.
*
@@ -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);
@@ -398,80 +651,6 @@ irc_color_encode (const char *string, int keep_colors)
return weechat_string_dyn_free (out, 0);
}
/*
* 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).
*
+4 -1
View File
@@ -41,9 +41,12 @@
#define IRC_COLOR_BOLD_CHAR '\x02' /* bold text */
#define IRC_COLOR_BOLD_STR "\x02" /* [02]...[02] */
#define IRC_COLOR_COLOR_CHAR '\x03' /* text color: fg / fg,bg / ,bg */
#define IRC_COLOR_COLOR_CHAR '\x03' /* text color: fg/fg,bg/,bg */
#define IRC_COLOR_COLOR_STR "\x03" /* [03]15,05...[03] */
#define IRC_COLOR_HEX_COLOR_CHAR '\x04' /* text color (hex): fg/fg,bg/,bg */
#define IRC_COLOR_HEX_COLOR_STR "\x04" /* [04]FFFF00,8B008B...[04] */
#define IRC_COLOR_RESET_CHAR '\x0F' /* reset color/attributes */
#define IRC_COLOR_RESET_STR "\x0F" /* [0F]... */