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:
+264
-85
@@ -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).
|
||||
*
|
||||
|
||||
@@ -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]... */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user