Merge pull request #48 from ailin-nemui/256-colour-history

256 colour support for Irssi
This commit is contained in:
Alexander Færøy 2014-07-02 23:17:36 +02:00
commit fd3676e407
23 changed files with 867 additions and 124 deletions

View file

@ -588,6 +588,63 @@ static void window_print_daychange(WINDOW_REC *window, struct tm *tm)
printtext_string_window(window, MSGLEVEL_NEVER, str);
}
short color_24bit_256 (const unsigned char rgb[])
{
static const int cstep_size = 40;
static const int cstep_start = 0x5f;
static const int gstep_size = 10;
static const int gstep_start = 0x08;
int dist[3] = {0};
int r[3], gr[3];
size_t i;
for (i = 0; i < 3; ++i) {
const int n = rgb[i];
gr[i] = -1;
if (n < cstep_start /2) {
r[i] = 0;
dist[i] = -cstep_size/2;
}
else {
r[i] = 1+((n-cstep_start + cstep_size /2)/cstep_size);
dist[i] = ((n-cstep_start + cstep_size /2)%cstep_size - cstep_size/2);
}
if (n < gstep_start /2) {
gr[i] = -1;
}
else {
gr[i] = ((n-gstep_start + gstep_size /2)/gstep_size);
}
}
if (r[0] == r[1] && r[1] == r[2] &&
4*abs(dist[0]) < gstep_size && 4*abs(dist[1]) < gstep_size && 4*abs(dist[2]) < gstep_size) {
/* skip gray detection */
}
else {
const int j = r[1] == r[2] ? 0 : 1;
if ((r[0] == r[1] || r[j] == r[2]) && abs(r[j]-r[(j+1)%3]) <= 1) {
const int k = gr[1] == gr[2] ? 0 : 1;
if ((gr[0] == gr[1] || gr[k] == gr[2]) && abs(gr[k]-gr[(k+1)%3]) <= 2) {
if (gr[k] < 0) {
r[0] = r[1] = r[2] = 0;
}
else if (gr[k] > 23) {
r[0] = r[1] = r[2] = 5;
}
else {
r[0] = 6;
r[1] = (gr[k] / 6);
r[2] = gr[k]%6;
}
}
}
}
return 16 + r[0]*36 + r[1] * 6 + r[2];
}
static void sig_print_text(void)
{
GSList *tmp;

View file

@ -97,4 +97,6 @@ void window_bind_remove_unsticky(WINDOW_REC *window);
void windows_init(void);
void windows_deinit(void);
short color_24bit_256(const unsigned char rgb[]);
#endif

View file

@ -101,10 +101,88 @@ static void format_expand_code(const char **format, GString *out, int *flags)
}
}
void format_ext_color(GString *out, int bg, int color)
{
g_string_append_c(out, 4);
if (bg && color < 0x10)
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
if (color < 0x10)
g_string_append_c(out, color+'0');
else {
if (color < 0x60)
g_string_append_c(out, bg ? FORMAT_COLOR_EXT1_BG
: FORMAT_COLOR_EXT1);
else if (color < 0xb0)
g_string_append_c(out, bg ? FORMAT_COLOR_EXT2_BG
: FORMAT_COLOR_EXT2);
else
g_string_append_c(out, bg ? FORMAT_COLOR_EXT3_BG
: FORMAT_COLOR_EXT3);
g_string_append_c(out, FORMAT_COLOR_NOCHANGE + ((color-0x10)%0x50));
}
if (!bg && color < 0x10)
g_string_append_c(out, FORMAT_COLOR_NOCHANGE);
}
#ifdef TERM_TRUECOLOR
void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int *flags)
{
unsigned int color;
unsigned char rgbx[4];
unsigned int i;
for (i = 0; i < 4; ++i) {
rgbx[i] = (*ptr)[i + off];
}
rgbx[3] -= 0x20;
*ptr += 4;
for (i = 0; i < 3; ++i) {
if (rgbx[3] & (0x10 << i))
rgbx[i] -= 0x20;
}
color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2];
if (rgbx[3] & 0x1) {
*bgcolor = color;
*flags |= GUI_PRINT_FLAG_COLOR_24_BG;
}
else {
*fgcolor = color;
*flags |= GUI_PRINT_FLAG_COLOR_24_FG;
}
}
#endif
void format_24bit_color(GString *out, int bg, unsigned int color)
{
unsigned char rgb[] = { color >> 16, color >> 8, color };
#ifdef TERM_TRUECOLOR
unsigned char x = bg ? 0x1 : 0;
unsigned int i;
g_string_append_c(out, 4);
g_string_append_c(out, FORMAT_COLOR_24);
for (i = 0; i < 3; ++i) {
if (rgb[i] > 0x20)
g_string_append_c(out, rgb[i]);
else {
g_string_append_c(out, 0x20 + rgb[i]);
x |= 0x10 << i;
}
}
g_string_append_c(out, 0x20 + x);
#else /* !TERM_TRUECOLOR */
format_ext_color(out, bg, color_24bit_256(rgb));
#endif /* TERM_TRUECOLOR */
}
int format_expand_styles(GString *out, const char **format, int *flags)
{
int retval = 1;
char *p, fmt;
/* storage for numerical parsing code for %x/X formats. */
int tmp;
unsigned int tmp2;
fmt = **format;
switch (fmt) {
case '{':
@ -162,6 +240,62 @@ int format_expand_styles(GString *out, const char **format, int *flags)
/* code */
format_expand_code(format, out, flags);
break;
case 'x':
case 'X':
if ((*format)[1] < '0' || (*format)[1] > '7')
break;
tmp = 16 + ((*format)[1]-'0'-1)*36;
if (tmp > 231) {
if (!isalpha((*format)[2]))
break;
tmp += (*format)[2] >= 'a' ? (*format)[2] - 'a' : (*format)[2] - 'A';
if (tmp > 255)
break;
}
else if (tmp > 0) {
if (!isalnum((*format)[2]))
break;
if ((*format)[2] >= 'a')
tmp += 10 + (*format)[2] - 'a';
else if ((*format)[2] >= 'A')
tmp += 10 + (*format)[2] - 'A';
else
tmp += (*format)[2] - '0';
}
else {
if (!isxdigit((*format)[2]))
break;
tmp = g_ascii_xdigit_value((*format)[2]);
}
retval += 2;
format_ext_color(out, fmt == 'x', tmp);
break;
case 'z':
case 'Z':
tmp2 = 0;
for (tmp = 1; tmp < 7; ++tmp) {
if (!isxdigit((*format)[tmp])) {
tmp2 = UINT_MAX;
break;
}
tmp2 <<= 4;
tmp2 |= g_ascii_xdigit_value((*format)[tmp]);
}
if (tmp2 == UINT_MAX)
break;
retval += 6;
format_24bit_color(out, fmt == 'z', tmp2);
break;
default:
/* check if it's a background color */
p = strchr(format_backs, fmt);
@ -195,7 +329,7 @@ int format_expand_styles(GString *out, const char **format, int *flags)
return FALSE;
}
return TRUE;
return retval;
}
void format_read_arglist(va_list va, FORMAT_REC *format,
@ -303,6 +437,7 @@ int format_get_length(const char *str)
GString *tmp;
int len;
gboolean utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0);
@ -313,9 +448,10 @@ int format_get_length(const char *str)
while (*str != '\0') {
if (*str == '%' && str[1] != '\0') {
str++;
if (*str != '%' &&
format_expand_styles(tmp, &str, NULL)) {
str++;
if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL);
str += adv;
if (adv)
continue;
}
@ -340,7 +476,7 @@ int format_real_length(const char *str, int len)
const char *start;
const char *oldstr;
gboolean utf8;
int adv = 0;
g_return_val_if_fail(str != NULL, 0);
g_return_val_if_fail(len >= 0, 0);
@ -351,9 +487,10 @@ int format_real_length(const char *str, int len)
while (*str != '\0' && len > 0) {
if (*str == '%' && str[1] != '\0') {
str++;
if (*str != '%' &&
format_expand_styles(tmp, &str, NULL)) {
str++;
if (*str != '%') {
adv = format_expand_styles(tmp, &str, NULL);
str += adv;
if (adv)
continue;
}
@ -378,6 +515,7 @@ char *format_string_expand(const char *text, int *flags)
{
GString *out;
char code, *ret;
int adv;
g_return_val_if_fail(text != NULL, NULL);
@ -388,10 +526,13 @@ char *format_string_expand(const char *text, int *flags)
while (*text != '\0') {
if (code == '%') {
/* color code */
if (!format_expand_styles(out, &text, flags)) {
adv = format_expand_styles(out, &text, flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, '%');
g_string_append_c(out, *text);
} else {
text += adv - 1;
}
code = 0;
} else {
@ -415,6 +556,7 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
GString *out;
char code, *ret;
int need_free;
int adv;
out = g_string_new(NULL);
@ -422,10 +564,13 @@ static char *format_get_text_args(TEXT_DEST_REC *dest,
while (*text != '\0') {
if (code == '%') {
/* color code */
if (!format_expand_styles(out, &text, &dest->flags)) {
adv = format_expand_styles(out, &text, &dest->flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, '%');
g_string_append_c(out, *text);
} else {
text += adv - 1;
}
code = 0;
} else if (code == '$') {
@ -716,13 +861,22 @@ void format_newline(WINDOW_REC *window)
"", NULL);
}
#ifndef TERM_TRUECOLOR
inline static int color_24bit_256_int(unsigned int color)
{
unsigned char rgb[] = { color >> 16, color >> 8, color };
return color_24bit_256(rgb);
}
#endif /* !TERM_TRUECOLOR */
/* parse ANSI color string */
static const char *get_ansi_color(THEME_REC *theme, const char *str,
int *fg_ret, int *bg_ret, int *flags_ret)
{
static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
const char *start;
int fg, bg, flags, num;
int fg, bg, flags, num, i;
unsigned int num2;
if (*str != '[')
return str;
@ -749,28 +903,127 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str,
/* reset colors back to default */
fg = theme->default_color;
bg = -1;
flags &= ~GUI_PRINT_FLAG_INDENT;
flags &= ~(GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT);
break;
case 1:
/* hilight */
flags |= GUI_PRINT_FLAG_BOLD;
break;
case 22:
/* normal */
flags &= ~GUI_PRINT_FLAG_BOLD;
break;
case 4:
/* underline */
flags |= GUI_PRINT_FLAG_UNDERLINE;
break;
case 24:
/* not underline */
flags &= ~GUI_PRINT_FLAG_UNDERLINE;
break;
case 5:
/* blink */
flags |= GUI_PRINT_FLAG_BLINK;
break;
case 25:
/* steady */
flags &= ~GUI_PRINT_FLAG_BLINK;
break;
case 7:
/* reverse */
flags |= GUI_PRINT_FLAG_REVERSE;
break;
case 27:
/* positive */
flags &= ~GUI_PRINT_FLAG_REVERSE;
break;
case 39:
/* reset fg */
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = theme->default_color;
break;
case 49:
/* reset bg */
bg = -1;
flags &= ~(GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT);
break;
case 38:
case 48:
/* ANSI indexed color or RGB color */
if (*str != ';') break;
str++;
for (num2 = 0; i_isdigit(*str); str++)
num2 = num2*10 + (*str-'0');
switch (num2) {
case 2:
/* RGB */
num2 = 0;
for (i = 0; i < 3; ++i) {
num2 <<= 8;
if (*str != ';' && *str != ':') {
i = -1;
break;
}
str++;
for (; i_isdigit(*str); str++)
num2 = (num2&~0xff) |
(((num2&0xff) * 10 + (*str-'0'))&0xff);
}
if (i == -1) break;
#ifdef TERM_TRUECOLOR
if (num == 38) {
flags |= GUI_PRINT_FLAG_COLOR_24_FG;
fg = num2;
} else if (num == 48) {
flags |= GUI_PRINT_FLAG_COLOR_24_BG;
bg = num2;
}
#else /* !TERM_TRUECOLOR */
if (num == 38) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = color_24bit_256_int(num2);
} else if (num == 48) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = color_24bit_256_int(num2);
}
#endif
break;
case 5:
/* indexed */
if (*str != ';') break;
str++;
for (num2 = 0; i_isdigit(*str); str++)
num2 = num2*10 + (*str-'0');
if (num == 38) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = num2;
} else if (num == 48) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = num2;
}
break;
}
break;
default:
if (num >= 30 && num <= 37) {
if (fg == -1) fg = 0;
fg = (fg & 0xf8) | ansitab[num-30];
}
if (num >= 40 && num <= 47) {
if (bg == -1) bg = 0;
bg = (bg & 0xf8) | ansitab[num-40];
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = ansitab[num-30];
} else if (num >= 40 && num <= 47) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = ansitab[num-40];
} else if (num >= 90 && num <= 97) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fg = 8 + ansitab[num-90];
} else if (num >= 100 && num <= 107) {
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bg = 8 + ansitab[num-100];
}
break;
}
@ -858,6 +1111,20 @@ int strip_real_length(const char *str, int len,
*last_color_len = (int) (str-mircstart);
} else if (*str == 4 && str[1] != '\0') {
#ifdef TERM_TRUECOLOR
if (str[1] == FORMAT_COLOR_24 && str[2] != '\0') {
if (str[3] == '\0') str++;
else if (str[4] == '\0') str += 2;
else if (str[5] == '\0') str += 3;
else {
if (last_color_pos != NULL)
*last_color_pos = (int) (str-start);
if (last_color_len != NULL)
*last_color_len = 6;
str+=4;
}
} else
#endif
if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') {
if (last_color_pos != NULL)
*last_color_pos = (int) (str-start);
@ -907,6 +1174,14 @@ char *strip_codes(const char *input)
/* irssi color */
if (p[2] != '\0') {
#ifdef TERM_TRUECOLOR
if (p[1] == FORMAT_COLOR_24) {
if (p[3] == '\0') p += 2;
else if (p[4] == '\0') p += 3;
else if (p[5] == '\0') p += 4;
else p += 5;
} else
#endif /* TERM_TRUECOLOR */
p += 2;
continue;
}
@ -1020,16 +1295,47 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text)
break;
case FORMAT_STYLE_CLRTOEOL:
break;
case FORMAT_COLOR_EXT1:
fgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT1_BG:
bgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
case FORMAT_COLOR_EXT2:
fgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT2_BG:
bgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
case FORMAT_COLOR_EXT3:
fgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
break;
case FORMAT_COLOR_EXT3_BG:
bgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE;
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
break;
#ifdef TERM_TRUECOLOR
case FORMAT_COLOR_24:
unformat_24bit_color(&ptr, 1, &fgcolor, &bgcolor, &flags);
break;
#endif
default:
if (*ptr != FORMAT_COLOR_NOCHANGE) {
fgcolor = (unsigned char) *ptr-'0';
flags &= ~GUI_PRINT_FLAG_COLOR_24_FG;
fgcolor = *ptr==(char)0xff ? -1 : (unsigned char) *ptr-'0';
}
if (ptr[1] == '\0')
break;
ptr++;
if (*ptr != FORMAT_COLOR_NOCHANGE) {
bgcolor = *ptr-'0';
flags &= ~GUI_PRINT_FLAG_COLOR_24_BG;
bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0';
}
}
ptr++;

View file

@ -13,6 +13,8 @@
#define GUI_PRINT_FLAG_NEWLINE 0x0080
#define GUI_PRINT_FLAG_CLRTOEOL 0x0100
#define GUI_PRINT_FLAG_MONOSPACE 0x0200
#define GUI_PRINT_FLAG_COLOR_24_FG 0x0400
#define GUI_PRINT_FLAG_COLOR_24_BG 0x0800
#define MAX_FORMAT_PARAMS 10
#define DEFAULT_FORMAT_ARGLIST_SIZE 200
@ -121,6 +123,15 @@ char *strip_codes(const char *input);
void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
#define FORMAT_COLOR_NOCHANGE ('0'-1) /* don't change this, at least hilighting depends this value */
#define FORMAT_COLOR_EXT1 ('0'-2)
#define FORMAT_COLOR_EXT2 ('0'-3)
#define FORMAT_COLOR_EXT3 ('0'-4)
#define FORMAT_COLOR_EXT1_BG ('0'-5)
#define FORMAT_COLOR_EXT2_BG ('0'-9)
#define FORMAT_COLOR_EXT3_BG ('0'-10)
#ifdef TERM_TRUECOLOR
#define FORMAT_COLOR_24 ('0'-13)
#endif
#define FORMAT_STYLE_SPECIAL 0x60
#define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL)
@ -132,6 +143,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text);
#define FORMAT_STYLE_CLRTOEOL (0x08 + FORMAT_STYLE_SPECIAL)
#define FORMAT_STYLE_MONOSPACE (0x09 + FORMAT_STYLE_SPECIAL)
int format_expand_styles(GString *out, const char **format, int *flags);
void format_ext_color(GString *out, int bg, int color);
void format_24bit_color(GString *out, int bg, unsigned int color);
void formats_init(void);
void formats_deinit(void);

View file

@ -206,6 +206,7 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
{
GString *out;
char *ret;
int adv;
out = g_string_new(NULL);
for (; *str != '\0'; str++) {
@ -255,9 +256,12 @@ static char *printtext_get_args(TEXT_DEST_REC *dest, const char *str,
break;
}
default:
if (!format_expand_styles(out, &str, &dest->flags)) {
adv = format_expand_styles(out, &str, &dest->flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, *str);
} else {
str += adv - 1;
}
break;
}
@ -272,6 +276,7 @@ static char *printtext_expand_formats(const char *str, int *flags)
{
GString *out;
char *ret;
int adv;
out = g_string_new(NULL);
for (; *str != '\0'; str++) {
@ -283,9 +288,12 @@ static char *printtext_expand_formats(const char *str, int *flags)
if (*++str == '\0')
break;
if (!format_expand_styles(out, &str, flags)) {
adv = format_expand_styles(out, &str, flags);
if (!adv) {
g_string_append_c(out, '%');
g_string_append_c(out, *str);
} else {
str += adv - 1;
}
}

View file

@ -115,8 +115,8 @@ void theme_destroy(THEME_REC *rec)
}
static char *theme_replace_expand(THEME_REC *theme, int index,
char default_fg, char default_bg,
char *last_fg, char *last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *last_fg, theme_rm_col *last_bg,
char chr, int flags)
{
GSList *rec;
@ -168,15 +168,44 @@ static void theme_format_append_variable(GString *str, const char **format)
g_free(value);
}
static inline int chr_is_valid_rgb(const char format[])
{
int tmp;
for (tmp = 1; tmp < 7; ++tmp) {
if (!isxdigit(format[tmp]))
return tmp;
}
return 0;
}
static inline int chr_is_valid_ext(const char format[])
{
if (format[1] < '0' || format[1] > '7')
return 1;
if (format[1] == '7') {
if (!isalpha(format[2]) || format[2] == 'y' || format[2] == 'Y'
|| format[2] =='z' || format[2] == 'Z')
return 2;
} else if (format[1] == '0') {
if (!isxdigit(format[2]))
return 2;
} else if (!isalnum(format[2]))
return 2;
return 0;
}
/* append next "item", either a character, $variable or %format */
static void theme_format_append_next(THEME_REC *theme, GString *str,
const char **format,
char default_fg, char default_bg,
char *last_fg, char *last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *last_fg, theme_rm_col *last_bg,
int flags)
{
int index;
unsigned char chr;
char *t;
chr = **format;
if ((chr == '$' || chr == '%') &&
@ -203,22 +232,50 @@ static void theme_format_append_next(THEME_REC *theme, GString *str,
/* %n = change to default color */
g_string_append(str, "%n");
if (default_bg != 'n') {
if (default_bg.m[0] != 'n') {
g_string_append_c(str, '%');
g_string_append_c(str, default_bg);
g_string_append(str, default_bg.m);
}
if (default_fg != 'n') {
if (default_fg.m[0] != 'n') {
g_string_append_c(str, '%');
g_string_append_c(str, default_fg);
g_string_append(str, default_fg.m);
}
*last_fg = default_fg;
*last_bg = default_bg;
} else if (chr == 'z' || chr == 'Z') {
if (chr_is_valid_rgb(*format) == 0) {
t = chr == 'z' ? (*last_bg).m : (*last_fg).m;
strncpy(t, *format, 7);
t[7] = '\0';
g_string_append_c(str, '%');
g_string_append(str, t);
(*format)+=6;
} else {
g_string_append(str, "%%");
g_string_append_c(str, **format);
}
} else if (chr == 'x' || chr == 'X') {
if (chr_is_valid_ext(*format) == 0) {
t = chr == 'x' ? (*last_bg).m : (*last_fg).m;
strncpy(t, *format, 3);
t[3] = '\0';
g_string_append_c(str, '%');
g_string_append(str, t);
(*format)+=2;
} else {
g_string_append(str, "%%");
g_string_append_c(str, **format);
}
} else {
if (IS_FGCOLOR_FORMAT(chr))
*last_fg = chr;
if (IS_BGCOLOR_FORMAT(chr))
*last_bg = chr;
if (IS_FGCOLOR_FORMAT(chr)) {
(*last_fg).m[0] = chr;
(*last_fg).m[1] = '\0';
}
if (IS_BGCOLOR_FORMAT(chr)) {
(*last_bg).m[0] = chr;
(*last_bg).m[1] = '\0';
}
g_string_append_c(str, '%');
g_string_append_c(str, chr);
}
@ -306,7 +363,10 @@ static int data_is_empty(const char **data)
char *theme_format_expand_get(THEME_REC *theme, const char **format)
{
GString *str;
char *ret, dummy;
char *ret;
theme_rm_col dummy, reset;
dummy.m[0] = '\0';
strcpy(reset.m, "n");
int braces = 1; /* we start with one brace opened */
str = g_string_new(NULL);
@ -321,7 +381,7 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
continue;
} else {
theme_format_append_next(theme, str, format,
'n', 'n',
reset, reset,
&dummy, &dummy, 0);
continue;
}
@ -343,15 +403,19 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format)
/* expand a single {abstract ...data... } */
static char *theme_format_expand_abstract(THEME_REC *theme,
const char **formatp,
char default_fg, char default_bg,
theme_rm_col *last_fg,
theme_rm_col *last_bg,
int flags)
{
GString *str;
const char *p, *format;
char *abstract, *data, *ret;
theme_rm_col default_fg, default_bg;
int len;
format = *formatp;
default_fg = *last_fg;
default_bg = *last_bg;
/* get abstract name first */
p = format;
@ -425,7 +489,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* abstract may itself contain abstracts or replaces */
p = abstract;
ret = theme_format_expand_data(theme, &p, default_fg, default_bg,
&default_fg, &default_bg,
last_fg, last_bg,
flags | EXPAND_FLAG_LASTCOLOR_ARG);
g_free(abstract);
return ret;
@ -433,13 +497,13 @@ static char *theme_format_expand_abstract(THEME_REC *theme,
/* expand the data part in {abstract data} */
char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg,
char *save_last_fg, char *save_last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags)
{
GString *str;
char *ret, *abstract;
char last_fg, last_bg;
theme_rm_col last_fg, last_bg;
int recurse_flags;
last_fg = default_fg;
@ -482,7 +546,7 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
/* get a single {...} */
abstract = theme_format_expand_abstract(theme, format,
last_fg, last_bg,
&last_fg, &last_bg,
recurse_flags);
if (abstract != NULL) {
g_string_append(str, abstract);
@ -490,13 +554,11 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
}
}
if ((flags & EXPAND_FLAG_LASTCOLOR_ARG) == 0) {
/* save the last color */
if (save_last_fg != NULL)
*save_last_fg = last_fg;
if (save_last_bg != NULL)
*save_last_bg = last_bg;
}
ret = str->str;
g_string_free(str, FALSE);
@ -510,7 +572,8 @@ char *theme_format_expand_data(THEME_REC *theme, const char **format,
static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
{
GString *str;
char *ret, last_fg, last_bg;
char *ret;
char last_fg, last_bg;
str = g_string_new(NULL);
@ -543,8 +606,12 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
if (IS_FGCOLOR_FORMAT(*format))
last_fg = *format;
else if (*format == 'Z' || *format == 'X')
last_fg = '\0';
if (IS_BGCOLOR_FORMAT(*format))
last_bg = *format;
else if (*format == 'z' || *format == 'x')
last_bg = '\0';
}
format++;
}
@ -558,11 +625,13 @@ static char *theme_format_compress_colors(THEME_REC *theme, const char *format)
char *theme_format_expand(THEME_REC *theme, const char *format)
{
char *data, *ret;
theme_rm_col reset;
strcpy(reset.m, "n");
g_return_val_if_fail(theme != NULL, NULL);
g_return_val_if_fail(format != NULL, NULL);
data = theme_format_expand_data(theme, &format, 'n', 'n', NULL, NULL,
data = theme_format_expand_data(theme, &format, reset, reset, NULL, NULL,
EXPAND_FLAG_ROOT);
ret = theme_format_compress_colors(theme, data);
g_free(data);
@ -944,10 +1013,6 @@ static int theme_read(THEME_REC *theme, const char *path)
config_get_int(config, NULL, "default_color", -1);
theme->info_eol = config_get_bool(config, NULL, "info_eol", FALSE);
/* FIXME: remove after 0.7.99 */
if (theme->default_color == 0 &&
config_get_int(config, NULL, "default_real_color", -1) != -1)
theme->default_color = -1;
theme_read_replaces(config, theme);
if (path != NULL)

View file

@ -57,10 +57,14 @@ void theme_set_default_abstract(const char *key, const char *value);
#define EXPAND_FLAG_ROOT 0x10
#define EXPAND_FLAG_LASTCOLOR_ARG 0x20
typedef struct {
char m[8];
} theme_rm_col;
char *theme_format_expand(THEME_REC *theme, const char *format);
char *theme_format_expand_data(THEME_REC *theme, const char **format,
char default_fg, char default_bg,
char *save_last_fg, char *save_last_bg,
theme_rm_col default_fg, theme_rm_col default_bg,
theme_rm_col *save_last_fg, theme_rm_col *save_last_bg,
int flags);
void themes_reload(void);