diff --git a/src/core/iregex.h b/src/core/iregex.h index 68156e02..7b1cf206 100644 --- a/src/core/iregex.h +++ b/src/core/iregex.h @@ -3,7 +3,6 @@ #include -#include typedef GRegex Regex; typedef struct _MatchInfo MatchInfo; diff --git a/src/core/special-vars.c b/src/core/special-vars.c index 8c890645..b0ed037b 100644 --- a/src/core/special-vars.c +++ b/src/core/special-vars.c @@ -27,6 +27,7 @@ #include #include #include +#include #define isvarchar(c) \ (i_isalnum(c) || (c) == '_') @@ -81,12 +82,20 @@ static char *get_argument(char **cmd, char **arglist) } str = g_string_new(NULL); + g_string_append_c(str, 4); + g_string_append_c(str, FORMAT_STYLE_PUSH); while (arg >= 0 && arg < argcount && (arg <= max || max == -1)) { g_string_append(str, arglist[arg]); g_string_append_c(str, ' '); arg++; } - if (str->len > 0) g_string_truncate(str, str->len-1); + if (str->len > 2) { + g_string_truncate(str, str->len - 1); + g_string_append_c(str, 4); + g_string_append_c(str, FORMAT_STYLE_POP); + } else { + g_string_truncate(str, 0); + } ret = g_string_free_and_steal(str); return ret; diff --git a/src/core/window-item-def.h b/src/core/window-item-def.h index 6944c921..c93b031b 100644 --- a/src/core/window-item-def.h +++ b/src/core/window-item-def.h @@ -1,6 +1,9 @@ #ifndef IRSSI_CORE_WINDOW_ITEM_DEF_H #define IRSSI_CORE_WINDOW_ITEM_DEF_H +#include +#include + #define STRUCT_SERVER_REC SERVER_REC struct _WI_ITEM_REC { #include diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index db2148d0..3176da45 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -36,6 +36,14 @@ #include #include +#define FORMAT_STYLE_STACK_MAX 10 +typedef struct { + int fgcolor_s[FORMAT_STYLE_STACK_MAX]; + int bgcolor_s[FORMAT_STYLE_STACK_MAX]; + int flags_s[FORMAT_STYLE_STACK_MAX]; + int cur, keep; +} STYLE_STACK_REC; + static const char *format_backs = "04261537"; static const char *format_fores = "kbgcrmyw"; static const char *format_boldfores = "KBGCRMYW"; @@ -112,17 +120,15 @@ void format_ext_color(GString *out, int bg, int color) if (bg && color < 0x10) g_string_append_c(out, FORMAT_COLOR_NOCHANGE); if (color < 0x10) - g_string_append_c(out, color+'0'); + 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) + if (color >= 0xb0) + g_string_append_c(out, bg ? FORMAT_COLOR_EXT3_BG : FORMAT_COLOR_EXT3); + else if (color >= 0x60) 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, bg ? FORMAT_COLOR_EXT1_BG : FORMAT_COLOR_EXT1); g_string_append_c(out, FORMAT_COLOR_NOCHANGE + ((color-0x10)%0x50)); } @@ -142,14 +148,13 @@ static void format_ext_color_unexpand(GString *out, gboolean bg, int base, char g_string_append_c(out, ext_color_al[value % 36]); } -void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int *flags) +int unformat_24bit_color_alg(const char **ptr, int off, int *is_bg, unsigned int *color) { - unsigned int color; unsigned char rgbx[4]; unsigned int i; for (i = 0; i < 4; ++i) { if ((*ptr)[i + off] == '\0') - return; + return FALSE; rgbx[i] = (*ptr)[i + off]; } rgbx[3] -= 0x20; @@ -158,13 +163,26 @@ void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int * if (rgbx[3] & (0x10 << i)) rgbx[i] -= 0x20; } - color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2]; - if (rgbx[3] & 0x1) { + *color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2]; + *is_bg = rgbx[3] & 0x1; + return TRUE; +} + +static void unformat_24bit_color(const char **ptr, int off, int *fgcolor, int *bgcolor, int *flags) +{ + unsigned int color; + int is_bg; + + if (!unformat_24bit_color_alg(ptr, off, &is_bg, &color)) + return; + + if (is_bg) { *bgcolor = color; + *flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_BG; *flags |= GUI_PRINT_FLAG_COLOR_24_BG; - } - else { + } else { *fgcolor = color; + *flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_FG; *flags |= GUI_PRINT_FLAG_COLOR_24_FG; } } @@ -172,22 +190,13 @@ void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int * static void format_24bit_color_unexpand(GString *out, int off, const char **ptr) { unsigned int color; - unsigned char rgbx[4]; - unsigned int i; - for (i = 0; i < 4; ++i) { - if ((*ptr)[i + off] == '\0') - return; - rgbx[i] = (*ptr)[i + off]; - } - rgbx[3] -= 0x20; - *ptr += 4; + int is_bg; + + if (!unformat_24bit_color_alg(ptr, off, &is_bg, &color)) + return; + g_string_append_c(out, '%'); - for (i = 0; i < 3; ++i) { - if (rgbx[3] & (0x10 << i)) - rgbx[i] -= 0x20; - } - color = rgbx[0] << 16 | rgbx[1] << 8 | rgbx[2]; - g_string_append_c(out, rgbx[3] & 0x1 ? 'z' : 'Z'); + g_string_append_c(out, is_bg ? 'z' : 'Z'); g_string_append_printf(out, "%06X", color); } @@ -263,11 +272,15 @@ int format_expand_styles(GString *out, const char **format, int *flags) g_string_append_c(out, FORMAT_STYLE_BLINK); break; case 'n': - case 'N': /* default color */ g_string_append_c(out, 4); g_string_append_c(out, FORMAT_STYLE_DEFAULTS); break; + case 'N': + /* default theme color */ + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_STYLE_THEME_DEFAULTS); + break; case '>': /* clear to end of line */ g_string_append_c(out, 4); @@ -285,6 +298,18 @@ int format_expand_styles(GString *out, const char **format, int *flags) (*format)--; break; + case '(': + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_STYLE_PUSH); + break; + case ')': + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_STYLE_POP); + break; + case '`': + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_STYLE_KEEP); + break; case 'x': case 'X': if ((*format)[1] < '0' || (*format)[1] > '7') @@ -683,6 +708,9 @@ char *format_string_unexpand(const char *text, int flags) format_flag_unexpand(out, 'I'); break; case FORMAT_STYLE_DEFAULTS: + format_flag_unexpand(out, 'n'); + break; + case FORMAT_STYLE_THEME_DEFAULTS: format_flag_unexpand(out, 'N'); break; case FORMAT_STYLE_CLRTOEOL: @@ -691,6 +719,15 @@ char *format_string_unexpand(const char *text, int flags) case FORMAT_STYLE_MONOSPACE: format_flag_unexpand(out, '#'); break; + case FORMAT_STYLE_PUSH: + format_flag_unexpand(out, '('); + break; + case FORMAT_STYLE_POP: + format_flag_unexpand(out, ')'); + break; + case FORMAT_STYLE_KEEP: + format_flag_unexpand(out, '`'); + break; default: if (*text != FORMAT_COLOR_NOCHANGE) { unsigned int value = (unsigned char) *text - '0'; @@ -1045,10 +1082,113 @@ void format_newline(TEXT_DEST_REC *dest) GINT_TO_POINTER(-1), GINT_TO_POINTER(GUI_PRINT_FLAG_NEWLINE), "", dest); } +#define SS_FGCOLOR_CUR(stack) (stack)->fgcolor_s[(stack)->cur] +#define SS_FGCOLOR_PREV(stack) (stack)->fgcolor_s[(stack)->cur - 1] +#define SS_FGCOLOR_KEEP(stack) (stack)->fgcolor_s[(stack)->keep] + +#define SS_BGCOLOR_CUR(stack) (stack)->bgcolor_s[(stack)->cur] +#define SS_BGCOLOR_PREV(stack) (stack)->bgcolor_s[(stack)->cur - 1] +#define SS_BGCOLOR_KEEP(stack) (stack)->bgcolor_s[(stack)->keep] + +#define SS_FLAGS_CUR(stack) (stack)->flags_s[(stack)->cur] +#define SS_FLAGS_PREV(stack) (stack)->flags_s[(stack)->cur - 1] +#define SS_FLAGS_KEEP(stack) (stack)->flags_s[(stack)->keep] + +inline static void copy_flags(int in_flags, unsigned int copy_flags, int *out_flags) +{ + *out_flags &= ~copy_flags; + *out_flags |= (in_flags & copy_flags); +} + +inline static void ss_restore_fgcolor(THEME_REC *theme, STYLE_STACK_REC *stack, int *fgcolor, + int *flags) +{ + if (stack != NULL && stack->cur > 0) { + *fgcolor = SS_FGCOLOR_PREV(stack); + copy_flags(SS_FLAGS_PREV(stack), GUI_PRINT_FLAGS_FG_COLORS, flags); + } else { + if (theme != NULL) + *fgcolor = theme->default_color; + else + *fgcolor = -1; + *flags &= ~GUI_PRINT_FLAGS_FG_COLORS; + } +} + +inline static void ss_restore_bgcolor(THEME_REC *theme, STYLE_STACK_REC *stack, int *bgcolor, + int *flags) +{ + (void) theme; + if (stack != NULL && stack->cur > 0) { + *bgcolor = SS_BGCOLOR_PREV(stack); + copy_flags(SS_FLAGS_PREV(stack), GUI_PRINT_FLAGS_BG_COLORS, flags); + } else { + *bgcolor = -1; + *flags &= ~GUI_PRINT_FLAGS_BG_COLORS; + } +} + +inline static void ss_restore_flags(THEME_REC *theme, STYLE_STACK_REC *stack, int *flags, int reset) +{ + int oldflags = *flags; + (void) theme; + if (reset) + oldflags &= ~reset; + else + oldflags &= GUI_PRINT_FLAGS_COLORS; + if (stack != NULL && stack->cur > 0) + *flags = (SS_FLAGS_PREV(stack) & ~GUI_PRINT_FLAGS_COLORS) | oldflags; + else + *flags = oldflags; +} + +inline static void ss_push(THEME_REC *theme, STYLE_STACK_REC *stack, int flags, int fgcolor, + int bgcolor) +{ + (void) theme; + SS_FLAGS_CUR(stack) = + flags & ~(GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_NEWLINE | GUI_PRINT_FLAG_CLRTOEOL); + SS_FGCOLOR_CUR(stack) = fgcolor; + SS_BGCOLOR_CUR(stack) = bgcolor; + if (stack->cur + 1 < FORMAT_STYLE_STACK_MAX) + stack->cur++; +} + +inline static void ss_pop(THEME_REC *theme, STYLE_STACK_REC *stack, int oldflags, int *flags, + int *fgcolor, int *bgcolor) +{ + stack->keep = stack->cur; + SS_FLAGS_KEEP(stack) = + oldflags & ~(GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_NEWLINE | GUI_PRINT_FLAG_CLRTOEOL); + SS_FGCOLOR_KEEP(stack) = *fgcolor; + SS_BGCOLOR_KEEP(stack) = *bgcolor; + if (stack->cur > 0) { + stack->cur--; + *flags = SS_FLAGS_CUR(stack); + *fgcolor = SS_FGCOLOR_CUR(stack); + *bgcolor = SS_BGCOLOR_CUR(stack); + } else { + *flags = 0; + *fgcolor = theme->default_color; + *bgcolor = -1; + } +} + +inline static void ss_keep(THEME_REC *theme, STYLE_STACK_REC *stack, int oldflags, int *flags, + int *fgcolor, int *bgcolor) +{ + *flags = oldflags; + if (stack->keep >= 0) { + *flags = SS_FLAGS_KEEP(stack); + *bgcolor = SS_BGCOLOR_KEEP(stack); + *fgcolor = SS_FGCOLOR_KEEP(stack); + stack->keep--; + } +} /* 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 const char *get_ansi_color(THEME_REC *theme, const char *str, int *fg_ret, int *bg_ret, + int *flags_ret, STYLE_STACK_REC *style_stack) { static char ansitab[8] = { 0, 4, 2, 6, 1, 5, 3, 7 }; const char *start; @@ -1056,13 +1196,24 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, int fg, bg, flags, i; guint num, num2; + flags = 0; + if (*str != '[') return str; start = str++; - fg = fg_ret == NULL || *fg_ret < 0 ? theme->default_color : *fg_ret; - bg = bg_ret == NULL || *bg_ret < 0 ? -1 : *bg_ret; - flags = flags_ret == NULL ? 0 : *flags_ret; + if (fg_ret == NULL || *fg_ret < 0) + ss_restore_fgcolor(theme, style_stack, &fg, &flags); + else + fg = *fg_ret; + if (bg_ret == NULL || *bg_ret < 0) + ss_restore_bgcolor(theme, style_stack, &bg, &flags); + else + bg = *bg_ret; + if (flags_ret == NULL) + ss_restore_flags(theme, style_stack, &flags, 0); + else + flags = *flags_ret; num = 0; for (;; str++) { @@ -1075,18 +1226,19 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, str = endptr; } - if (*str != ';' && *str != 'm') + if (!(*str == ';' || *str == 'm' || (*str == ':' && (num == 38 || num == 48)))) return start; switch (num) { case 0: /* reset colors and attributes back to default */ - fg = theme->default_color; - bg = -1; - flags &= ~(GUI_PRINT_FLAG_INDENT | - GUI_PRINT_FLAG_BOLD | GUI_PRINT_FLAG_ITALIC | GUI_PRINT_FLAG_UNDERLINE | - GUI_PRINT_FLAG_BLINK | GUI_PRINT_FLAG_REVERSE | - GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG); + ss_restore_flags(theme, style_stack, &flags, + GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_BOLD | + GUI_PRINT_FLAG_ITALIC | GUI_PRINT_FLAG_UNDERLINE | + GUI_PRINT_FLAG_BLINK | GUI_PRINT_FLAG_REVERSE | + GUI_PRINT_FLAGS_COLORS); + ss_restore_fgcolor(theme, style_stack, &fg, &flags); + ss_restore_bgcolor(theme, style_stack, &bg, &flags); break; case 1: /* hilight */ @@ -1130,18 +1282,18 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, break; case 39: /* reset fg */ - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; - fg = theme->default_color; + ss_restore_fgcolor(theme, style_stack, &fg, &flags); break; case 49: /* reset bg */ - bg = -1; - flags &= ~(GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_INDENT); + ss_restore_bgcolor(theme, style_stack, &bg, &flags); + flags &= ~GUI_PRINT_FLAG_INDENT; break; case 38: case 48: /* ANSI indexed color or RGB color */ - if (*str != ';') break; + if (*str != ';' && *str != ':') + break; str++; if (!parse_uint(str, &endptr, 10, &num2)) { @@ -1174,9 +1326,11 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, if (i == -1) break; if (num == 38) { + flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_FG; flags |= GUI_PRINT_FLAG_COLOR_24_FG; fg = num2; } else if (num == 48) { + flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_BG; flags |= GUI_PRINT_FLAG_COLOR_24_BG; bg = num2; } @@ -1184,7 +1338,8 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, break; case 5: /* indexed */ - if (*str != ';') break; + if (*str != ';' && *str != ':') + break; str++; if (!parse_uint(str, &endptr, 10, &num2)) { @@ -1195,10 +1350,10 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, if (*str == '\0') return start; if (num == 38) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; fg = num2; } else if (num == 48) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; bg = num2; } @@ -1207,16 +1362,16 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, break; default: if (num >= 30 && num <= 37) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; fg = ansitab[num-30]; } else if (num >= 40 && num <= 47) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; bg = ansitab[num-40]; } else if (num >= 90 && num <= 97) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; fg = 8 + ansitab[num-90]; } else if (num >= 100 && num <= 107) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; bg = 8 + ansitab[num-100]; } break; @@ -1237,17 +1392,17 @@ static const char *get_ansi_color(THEME_REC *theme, const char *str, } /* parse MIRC color string */ -static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret) +static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret, int *flags) { int fg, bg; - fg = fg_ret == NULL ? -1 : *fg_ret; - bg = bg_ret == NULL ? -1 : *bg_ret; + fg = -1; + bg = -1; if (!i_isdigit(**str)) { /* turn off color */ - fg = -1; - bg = -1; + fg = 99; + bg = 99; } else { /* foreground color */ fg = **str-'0'; @@ -1269,8 +1424,20 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret) } } - if (fg_ret) *fg_ret = fg; - if (bg_ret) *bg_ret = bg; + if (fg_ret && fg > -1) { + *fg_ret = fg; + if (flags) { + *flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + *flags |= GUI_PRINT_FLAG_MIRC_COLOR_FG; + } + } + if (bg_ret && bg > -1) { + *bg_ret = bg; + if (flags) { + *flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + *flags |= GUI_PRINT_FLAG_MIRC_COLOR_BG; + } + } } #define IS_COLOR_CODE(c) \ @@ -1290,53 +1457,94 @@ int strip_real_length(const char *str, int len, *last_color_len = -1; while (*str != '\0') { - if (*str == 3) { /* mIRC color */ + switch (str[0]) { + case 3: { /* mIRC color */ const char *mircstart = str; if (last_color_pos != NULL) *last_color_pos = (int) (str-start); str++; - get_mirc_color(&str, NULL, NULL); + get_mirc_color(&str, NULL, NULL, NULL); if (last_color_len != NULL) *last_color_len = (int) (str-mircstart); - - } else if (*str == 4 && str[1] != '\0') { + } break; + case 4: /* We expect 4 to indicate an internal Irssi color code. However 4 * also means hex color, an alternative to mIRC color codes. We * don't support those. */ - 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; + switch (str[1]) { + case '\0': + str++; + break; + case FORMAT_COLOR_24: + if (str[2] == '\0') + str += 2; + else if (str[3] == '\0') + str += 3; + else if (str[4] == '\0') + str += 4; + else if (str[5] == '\0') + str += 5; else { if (last_color_pos != NULL) *last_color_pos = (int) (str-start); if (last_color_len != NULL) *last_color_len = 6; - str+=4; + str += 6; } - } else if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') { - if (last_color_pos != NULL) - *last_color_pos = (int) (str-start); - if (last_color_len != NULL) - *last_color_len = 3; - str++; - } else if (str[1] == FORMAT_STYLE_DEFAULTS) { + break; + case FORMAT_STYLE_DEFAULTS: + case FORMAT_STYLE_THEME_DEFAULTS: if (last_color_pos != NULL) *last_color_pos = (int) (str-start); if (last_color_len != NULL) *last_color_len = 2; + str += 2; + break; + default: + if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') { + if (last_color_pos != NULL) + *last_color_pos = (int) (str - start); + if (last_color_len != NULL) + *last_color_len = 3; + str += 3; + } else { + str += 2; + } + break; } - str += 2; - } else { + break; + case 15: + /* remove all styling */ + if (last_color_pos != NULL) + *last_color_pos = -1; + if (last_color_len != NULL) + *last_color_len = -1; + str++; + break; + case 27: { + const char *ansistart; + int unchanged = 0x7fffffff, fg = unchanged, bg = unchanged; + ansistart = str; + str++; + str = get_ansi_color(NULL, str, &fg, &bg, NULL, NULL); + if (fg < unchanged || bg < unchanged) { + if (last_color_pos != NULL) + *last_color_pos = (int) (ansistart - start); + if (last_color_len != NULL) + *last_color_len = (int) (str - ansistart); + } + } break; + default: if (!IS_COLOR_CODE(*str)) { if (len-- == 0) - break; + goto out; } str++; + break; } } - +out: return (int) (str-start); } @@ -1351,7 +1559,7 @@ char *strip_codes(const char *input) p++; /* mirc color */ - get_mirc_color(&p, NULL, NULL); + get_mirc_color(&p, NULL, NULL, NULL); p--; continue; } @@ -1370,14 +1578,17 @@ char *strip_codes(const char *input) else if (p[5] == '\0') p += 4; else p += 5; } else - p += 2; + p += 2; continue; } } if (*p == 27 && p[1] != '\0') { p++; - p = get_ansi_color(current_theme, p, NULL, NULL, NULL); + if (strncmp(p, "[#", 2) == 0 && (p[2] == '}' || p[2] == '{')) + p += 3; + else + p = get_ansi_color(current_theme, p, NULL, NULL, NULL, NULL); p--; } else if (!IS_COLOR_CODE(*p)) *out++ = *p; @@ -1399,13 +1610,18 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC THEME_REC *theme; char *dup, *str, *ptr, type; int fgcolor, bgcolor; - int flags; + int flags, oldflags; + STYLE_STACK_REC style_stack; theme = window_get_theme(dest->window); dup = str = g_strdup(text); - flags = 0; fgcolor = theme->default_color; bgcolor = -1; + flags = 0; + fgcolor = theme->default_color; + bgcolor = -1; + style_stack.cur = 0; + style_stack.keep = -1; if (*str == '\0') { /* empty line, write line info only */ @@ -1438,14 +1654,16 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC if (type == '\n') { handler(dest->window, GINT_TO_POINTER(-1), GINT_TO_POINTER(-1), GINT_TO_POINTER(GUI_PRINT_FLAG_NEWLINE), "", dest); - fgcolor = theme->default_color; - bgcolor = -1; - flags &= GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_MONOSPACE; + ss_restore_fgcolor(theme, &style_stack, &fgcolor, &flags); + ss_restore_bgcolor(theme, &style_stack, &bgcolor, &flags); + ss_restore_flags(theme, &style_stack, &flags, + ~(GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_MONOSPACE)); } if (*ptr == '\0') break; + oldflags = flags; switch (type) { case 2: @@ -1455,15 +1673,19 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC break; case 3: /* MIRC color */ - get_mirc_color((const char **) &ptr, - hide_colors ? NULL : &fgcolor, - hide_colors ? NULL : &bgcolor); - if (!hide_colors) - flags |= GUI_PRINT_FLAG_MIRC_COLOR; + get_mirc_color((const char **) &ptr, hide_colors ? NULL : &fgcolor, + hide_colors ? NULL : &bgcolor, hide_colors ? NULL : &flags); + if ((flags & GUI_PRINT_FLAG_MIRC_COLOR_FG) && fgcolor == 99) { + flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_FG; + ss_restore_fgcolor(theme, &style_stack, &fgcolor, &flags); + } + if ((flags & GUI_PRINT_FLAG_MIRC_COLOR_BG) && bgcolor == 99) { + flags &= ~GUI_PRINT_FLAG_MIRC_COLOR_BG; + ss_restore_bgcolor(theme, &style_stack, &bgcolor, &flags); + } break; case 4: /* user specific colors */ - flags &= ~GUI_PRINT_FLAG_MIRC_COLOR; switch (*ptr) { case FORMAT_STYLE_BLINK: flags ^= GUI_PRINT_FLAG_BLINK; @@ -1487,51 +1709,76 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC flags |= GUI_PRINT_FLAG_INDENT; break; case FORMAT_STYLE_DEFAULTS: + ss_restore_fgcolor(theme, &style_stack, &fgcolor, &flags); + ss_restore_bgcolor(theme, &style_stack, &bgcolor, &flags); + ss_restore_flags(theme, &style_stack, &flags, 0); + break; + case FORMAT_STYLE_THEME_DEFAULTS: fgcolor = theme->default_color; bgcolor = -1; flags &= GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_MONOSPACE; break; case FORMAT_STYLE_CLRTOEOL: break; + case FORMAT_STYLE_PUSH: + ss_push(theme, &style_stack, oldflags, fgcolor, bgcolor); + break; + case FORMAT_STYLE_POP: + ss_pop(theme, &style_stack, oldflags, &flags, &fgcolor, &bgcolor); + break; + case FORMAT_STYLE_KEEP: + ss_keep(theme, &style_stack, oldflags, &flags, &fgcolor, &bgcolor); + break; case FORMAT_COLOR_EXT1: fgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; break; case FORMAT_COLOR_EXT1_BG: bgcolor = 0x10 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; break; case FORMAT_COLOR_EXT2: fgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; break; case FORMAT_COLOR_EXT2_BG: bgcolor = 0x60 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; break; case FORMAT_COLOR_EXT3: fgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; break; case FORMAT_COLOR_EXT3_BG: bgcolor = 0xb0 + *++ptr - FORMAT_COLOR_NOCHANGE; - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; break; case FORMAT_COLOR_24: - unformat_24bit_color(&ptr, 1, &fgcolor, &bgcolor, &flags); + unformat_24bit_color((const char **) &ptr, 1, &fgcolor, &bgcolor, + &flags); break; default: if (*ptr != FORMAT_COLOR_NOCHANGE) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; - fgcolor = *ptr==(char)0xff ? -1 : (unsigned char) *ptr-'0'; + if (*ptr == (char) 0xff) { + ss_restore_fgcolor(theme, &style_stack, &fgcolor, + &flags); + } else { + flags &= ~GUI_PRINT_FLAGS_FG_COLORS; + fgcolor = (unsigned char) *ptr - '0'; + } } if (ptr[1] == '\0') break; ptr++; if (*ptr != FORMAT_COLOR_NOCHANGE) { - flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; - bgcolor = *ptr==(char)0xff ? -1 : *ptr-'0'; + if (*ptr == (char) 0xff) { + ss_restore_bgcolor(theme, &style_stack, &bgcolor, + &flags); + } else { + flags &= ~GUI_PRINT_FLAGS_BG_COLORS; + bgcolor = *ptr - '0'; + } } } if (*ptr == '\0') @@ -1548,10 +1795,10 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC /* remove all styling */ if (!hide_text_style) { if (!hide_colors) { - fgcolor = theme->default_color; - bgcolor = -1; + ss_restore_fgcolor(theme, &style_stack, &fgcolor, &flags); + ss_restore_bgcolor(theme, &style_stack, &bgcolor, &flags); } - flags &= GUI_PRINT_FLAG_INDENT | GUI_PRINT_FLAG_MONOSPACE; + ss_restore_flags(theme, &style_stack, &flags, 0); } break; case 17: @@ -1574,12 +1821,25 @@ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC flags ^= GUI_PRINT_FLAG_UNDERLINE; break; case 27: - /* ansi color code */ - ptr = (char *) - get_ansi_color(theme, ptr, - hide_colors ? NULL : &fgcolor, - hide_colors ? NULL : &bgcolor, - hide_colors ? NULL : &flags); + if (strncmp(ptr, "[#", 2) == 0) { + switch (ptr[2]) { + case '{': + ss_push(theme, &style_stack, oldflags, fgcolor, bgcolor); + ptr += 3; + break; + case '}': + ss_pop(theme, &style_stack, oldflags, &flags, &fgcolor, + &bgcolor); + ptr += 3; + break; + } + } else { + /* ansi color code */ + ptr = (char *) get_ansi_color( + theme, ptr, hide_colors ? NULL : &fgcolor, + hide_colors ? NULL : &bgcolor, hide_colors ? NULL : &flags, + &style_stack); + } break; } diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 79b90ded..f0e23f95 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -5,11 +5,11 @@ #include #include +/* clang-format off */ #define GUI_PRINT_FLAG_BOLD 0x0001 #define GUI_PRINT_FLAG_REVERSE 0x0002 #define GUI_PRINT_FLAG_UNDERLINE 0x0004 #define GUI_PRINT_FLAG_BLINK 0x0008 -#define GUI_PRINT_FLAG_MIRC_COLOR 0x0010 #define GUI_PRINT_FLAG_INDENT 0x0020 #define GUI_PRINT_FLAG_ITALIC 0x0040 #define GUI_PRINT_FLAG_NEWLINE 0x0080 @@ -17,6 +17,17 @@ #define GUI_PRINT_FLAG_MONOSPACE 0x0200 #define GUI_PRINT_FLAG_COLOR_24_FG 0x0400 #define GUI_PRINT_FLAG_COLOR_24_BG 0x0800 +#define GUI_PRINT_FLAG_MIRC_COLOR_FG 0x1000 +#define GUI_PRINT_FLAG_MIRC_COLOR_BG 0x2000 +/* clang-format on */ + +#define GUI_PRINT_FLAGS_COLORS_24 (GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG) +#define GUI_PRINT_FLAGS_MIRC_COLORS (GUI_PRINT_FLAG_MIRC_COLOR_FG | GUI_PRINT_FLAG_MIRC_COLOR_BG) +#define GUI_PRINT_FLAGS_FG_COLORS (GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_MIRC_COLOR_FG) +#define GUI_PRINT_FLAGS_BG_COLORS (GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_MIRC_COLOR_BG) +#define GUI_PRINT_FLAGS_COLORS \ + (GUI_PRINT_FLAG_COLOR_24_FG | GUI_PRINT_FLAG_COLOR_24_BG | GUI_PRINT_FLAG_MIRC_COLOR_FG | \ + GUI_PRINT_FLAG_MIRC_COLOR_BG) #define MAX_FORMAT_PARAMS 10 #define DEFAULT_FORMAT_ARGLIST_SIZE 200 @@ -37,17 +48,17 @@ struct _FORMAT_REC { }; /* clang-format off */ -#define PRINT_FLAG_SET_LINE_START 0x0001 -#define PRINT_FLAG_SET_LINE_START_IRSSI 0x0002 -#define PRINT_FLAG_UNSET_LINE_START 0x0040 +#define PRINT_FLAG_SET_LINE_START 0x0001 +#define PRINT_FLAG_SET_LINE_START_IRSSI 0x0002 +#define PRINT_FLAG_UNSET_LINE_START 0x0040 -#define PRINT_FLAG_SET_TIMESTAMP 0x0004 -#define PRINT_FLAG_UNSET_TIMESTAMP 0x0008 +#define PRINT_FLAG_SET_TIMESTAMP 0x0004 +#define PRINT_FLAG_UNSET_TIMESTAMP 0x0008 -#define PRINT_FLAG_SET_SERVERTAG 0x0010 -#define PRINT_FLAG_UNSET_SERVERTAG 0x0020 +#define PRINT_FLAG_SET_SERVERTAG 0x0010 +#define PRINT_FLAG_UNSET_SERVERTAG 0x0020 -#define PRINT_FLAG_FORMAT 0x0080 +#define PRINT_FLAG_FORMAT 0x0080 /* clang-format on */ typedef struct _HILIGHT_REC HILIGHT_REC; @@ -151,28 +162,40 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text); */ void format_send_as_gui_flags(TEXT_DEST_REC *dest, const char *text, SIGNAL_FUNC handler); -#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) -#define FORMAT_COLOR_24 ('0'-13) +enum { + FORMAT_COLOR_24 = ('0' - 13), + FORMAT_COLOR_EXT3_BG = ('0' - 10), + FORMAT_COLOR_EXT2_BG, + FORMAT_COLOR_EXT1_BG = ('0' - 5), + FORMAT_COLOR_EXT3, + FORMAT_COLOR_EXT2, + FORMAT_COLOR_EXT1, + FORMAT_COLOR_NOCHANGE +}; +/* don't change this, at least hilighting depends this value */ +G_STATIC_ASSERT(FORMAT_COLOR_NOCHANGE == ('0' - 1)); + +enum { + FORMAT_STYLE_SPECIAL = 0x60, + FORMAT_STYLE_BLINK, + FORMAT_STYLE_UNDERLINE, + FORMAT_STYLE_BOLD, + FORMAT_STYLE_REVERSE, + FORMAT_STYLE_INDENT, + FORMAT_STYLE_ITALIC, + FORMAT_STYLE_DEFAULTS, + FORMAT_STYLE_CLRTOEOL, + FORMAT_STYLE_MONOSPACE, + FORMAT_STYLE_THEME_DEFAULTS, + FORMAT_STYLE_PUSH, + FORMAT_STYLE_POP, + FORMAT_STYLE_KEEP +}; -#define FORMAT_STYLE_SPECIAL 0x60 -#define FORMAT_STYLE_BLINK (0x01 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_UNDERLINE (0x02 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_BOLD (0x03 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_REVERSE (0x04 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_INDENT (0x05 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_ITALIC (0x06 + FORMAT_STYLE_SPECIAL) -#define FORMAT_STYLE_DEFAULTS (0x07 + FORMAT_STYLE_SPECIAL) -#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); +int unformat_24bit_color_alg(const char **ptr, int off, int *is_bg, unsigned int *color); void format_gui_flags(GString *out, int *last_fg, int *last_bg, int *last_flags, int fg, int bg, int flags); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 2412a1f8..ae247881 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -375,13 +375,11 @@ static void sig_render_line_text(TEXT_DEST_REC *dest, GString *str, LINE_INFO_ME /* end of the line */ pos = strip_real_length(str->str, hilight_end, &color_pos, &color_len); - if (color_pos > 0) { + g_string_append_c(str2, 4); + g_string_append_c(str2, (char) -1); + g_string_append_c(str2, (char) -1); + if (color_pos > 0) g_string_append_len(str2, str->str + color_pos, color_len); - } else { - /* no colors in line, change back to default */ - g_string_append_c(str2, 4); - g_string_append_c(str2, FORMAT_STYLE_DEFAULTS); - } g_string_append(str2, str->str + pos); g_string_assign(str, g_string_free(str2, FALSE)); diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 58d17b8e..1fbe17f7 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -33,6 +33,8 @@ #include "default-theme.h" +#define THEME_NESTED_MAX 20 + GSList *themes; THEME_REC *current_theme; GHashTable *default_formats; @@ -113,10 +115,14 @@ void theme_destroy(THEME_REC *rec) theme_unref(rec); } -static char *theme_replace_expand(THEME_REC *theme, int index, - theme_rm_col default_fg, theme_rm_col default_bg, - theme_rm_col *last_fg, theme_rm_col *last_bg, - char chr, int flags) +static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *save_last_fg, theme_rm_col *save_last_bg, + int flags, GTree *block_list); + +static char *theme_replace_expand(THEME_REC *theme, int index, theme_rm_col default_fg, + theme_rm_col default_bg, theme_rm_col *last_fg, + theme_rm_col *last_bg, char chr, int flags, GTree *block_list) { GSList *rec; char *ret, *abstract, data[2]; @@ -127,9 +133,9 @@ static char *theme_replace_expand(THEME_REC *theme, int index, data[0] = chr; data[1] = '\0'; abstract = rec->data; - abstract = theme_format_expand_data(theme, (const char **) &abstract, - default_fg, default_bg, - last_fg, last_bg, (flags | EXPAND_FLAG_IGNORE_REPLACES)); + abstract = theme_format_expand_data_rec(theme, (const char **) &abstract, default_fg, + default_bg, last_fg, last_bg, + (flags | EXPAND_FLAG_IGNORE_REPLACES), block_list); ret = parse_special_string(abstract, NULL, NULL, data, NULL, PARSE_FLAG_ONLY_ARGS); g_free(abstract); @@ -196,11 +202,10 @@ static inline int chr_is_valid_ext(const char format[]) } /* append next "item", either a character, $variable or %format */ -static void theme_format_append_next(THEME_REC *theme, GString *str, - const char **format, - theme_rm_col default_fg, theme_rm_col default_bg, - theme_rm_col *last_fg, theme_rm_col *last_bg, - int flags) +static void theme_format_append_next(THEME_REC *theme, GString *str, const char **format, + theme_rm_col default_fg, theme_rm_col default_bg, + theme_rm_col *last_fg, theme_rm_col *last_bg, int flags, + GTree *block_list) { int index; unsigned char chr; @@ -295,9 +300,8 @@ static void theme_format_append_next(THEME_REC *theme, GString *str, else { char *value; - value = theme_replace_expand(theme, index, - default_fg, default_bg, - last_fg, last_bg, chr, flags); + value = theme_replace_expand(theme, index, default_fg, default_bg, last_fg, last_bg, + chr, flags, block_list); g_string_append(str, value); g_free(value); } @@ -358,8 +362,8 @@ static int data_is_empty(const char **data) return FALSE; } -/* return "data" from {abstract data} string */ -char *theme_format_expand_get(THEME_REC *theme, const char **format) +static char *theme_format_expand_get_rec(THEME_REC *theme, const char **format, int rec_count, + GTree *block_list) { GString *str; char *ret; @@ -379,10 +383,9 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format) (*format)++; continue; } else { - theme_format_append_next(theme, str, format, - reset, reset, - &dummy, &dummy, - EXPAND_FLAG_IGNORE_REPLACES); + theme_format_append_next(theme, str, format, reset, reset, &dummy, &dummy, + (rec_count << 8) | EXPAND_FLAG_IGNORE_REPLACES, + block_list); continue; } @@ -399,10 +402,11 @@ char *theme_format_expand_get(THEME_REC *theme, const char **format) return ret; } -static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format, - theme_rm_col default_fg, theme_rm_col default_bg, - theme_rm_col *save_last_fg, theme_rm_col *save_last_bg, - int flags, GTree *block_list); +/* return "data" from {abstract data} string */ +char *theme_format_expand_get(THEME_REC *theme, const char **format) +{ + return theme_format_expand_get_rec(theme, format, 0, NULL); +} /* expand a single {abstract ...data... } */ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp, @@ -413,7 +417,9 @@ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp const char *p, *format; char *abstract, *data, *ret, *blocking; theme_rm_col default_fg, default_bg; - int len; + int len, recurse_count; + + recurse_count = (flags & EXPAND_FLAG_COUNT_MASK) >> 8; format = *formatp; default_fg = *last_fg; @@ -447,6 +453,10 @@ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp g_tree_ref(block_list); } + if (recurse_count >= THEME_NESTED_MAX) { + g_warning("Theme nesting cannot exceed %d at {%s ...}", THEME_NESTED_MAX, abstract); + } + /* get the abstract data */ data = g_hash_table_lookup(theme->abstracts, abstract); if (data == NULL || g_tree_lookup(block_list, abstract) != NULL) { @@ -462,7 +472,7 @@ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp /* we'll need to get the data part. it may contain more abstracts, they are _NOT_ expanded. */ - data = theme_format_expand_get(theme, formatp); + data = theme_format_expand_get_rec(theme, formatp, recurse_count, block_list); len = strlen(data); if (len > 1 && i_isdigit(data[len-1]) && data[len-2] == '$') { @@ -499,8 +509,13 @@ static char *theme_format_expand_abstract(THEME_REC *theme, const char **formatp /* abstract may itself contain abstracts or replaces */ p = abstract; - ret = theme_format_expand_data_rec(theme, &p, default_fg, default_bg, last_fg, last_bg, - flags | EXPAND_FLAG_LASTCOLOR_ARG, block_list); + if (recurse_count >= THEME_NESTED_MAX) { + ret = g_strdup(p); + } else { + ret = theme_format_expand_data_rec(theme, &p, default_fg, default_bg, last_fg, + last_bg, flags | EXPAND_FLAG_LASTCOLOR_ARG, + block_list); + } g_free(abstract); if (blocking != NULL) { g_tree_remove(block_list, blocking); @@ -521,7 +536,7 @@ static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format, last_fg = default_fg; last_bg = default_bg; - recurse_flags = flags & EXPAND_FLAG_RECURSIVE_MASK; + recurse_flags = (flags + (1 << 8)) & (EXPAND_FLAG_RECURSIVE_MASK | EXPAND_FLAG_COUNT_MASK); str = g_string_new(NULL); while (**format != '\0') { @@ -546,10 +561,8 @@ static char *theme_format_expand_data_rec(THEME_REC *theme, const char **format, } } - theme_format_append_next(theme, str, format, - default_fg, default_bg, - &last_fg, &last_bg, - recurse_flags); + theme_format_append_next(theme, str, format, default_fg, default_bg, + &last_fg, &last_bg, recurse_flags, block_list); continue; } diff --git a/src/fe-common/core/themes.h b/src/fe-common/core/themes.h index 53426f3b..1a2e80dc 100644 --- a/src/fe-common/core/themes.h +++ b/src/fe-common/core/themes.h @@ -1,6 +1,8 @@ #ifndef IRSSI_FE_COMMON_CORE_THEMES_H #define IRSSI_FE_COMMON_CORE_THEMES_H +#include + typedef struct { char *name; @@ -50,12 +52,16 @@ void theme_unregister_module(const char *module); void theme_set_default_abstract(const char *key, const char *value); +/* clang-format off */ #define EXPAND_FLAG_IGNORE_REPLACES 0x01 /* don't use the character replaces when expanding */ #define EXPAND_FLAG_IGNORE_EMPTY 0x02 /* if abstract's argument is empty, or the argument is a $variable that is empty, don't try to expand it (ie. {xx }, but not {xx}) */ #define EXPAND_FLAG_RECURSIVE_MASK 0x0f /* private */ -#define EXPAND_FLAG_ROOT 0x10 -#define EXPAND_FLAG_LASTCOLOR_ARG 0x20 +#define EXPAND_FLAG_ROOT 0x10 +#define EXPAND_FLAG_LASTCOLOR_ARG 0x20 +#define EXPAND_FLAG_PRIVATE_MASK 0xf0 +#define EXPAND_FLAG_COUNT_MASK 0xff00 +/* clang-format on */ typedef struct { char m[8]; diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 7482d470..c472aa97 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -32,6 +32,7 @@ #include /* Terminal indexed colour map */ +/* clang-format off */ int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7, /* 16-27 */ 52, 94, 100, 58, 22, 29, 23, 24, 17, 54, 53, 89, /* 28-39 */ 88, 130, 142, 64, 28, 35, 30, 25, 18, 91, 90, 125, @@ -40,9 +41,11 @@ int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7, /* 64-75 */ 203, 215, 227, 191, 83, 122, 87, 111, 63, 177, 207, 205, /* 76-87 */ 217, 223, 229, 193, 157, 158, 159, 153, 147, 183, 219, 212, /* 88-98 */ 16, 233, 235, 237, 239, 241, 244, 247, 250, 254, 231, -1 }; +/* clang-format on */ /* RGB colour map */ -int mirc_colors24[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +/* clang-format off */ +int mirc_colors_24bit[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 16-27 */ 0x470000, 0x472100, 0x474700, 0x324700, 0x004700, 0x00472c, 0x004747, 0x002747, 0x000047, 0x2e0047, 0x470047, 0x47002a, /* 28-39 */ 0x740000, 0x743a00, 0x747400, 0x517400, 0x007400, 0x007449, 0x007474, 0x004074, 0x000074, 0x4b0074, 0x740074, 0x740045, /* 40-51 */ 0xb50000, 0xb56300, 0xb5b500, 0x7db500, 0x00b500, 0x00b571, 0x00b5b5, 0x0063b5, 0x0000b5, 0x7500b5, 0xb500b5, 0xb5006b, @@ -50,8 +53,9 @@ int mirc_colors24[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 64-75 */ 0xff5959, 0xffb459, 0xffff71, 0xcfff60, 0x6fff6f, 0x65ffc9, 0x6dffff, 0x59b4ff, 0x5959ff, 0xc459ff, 0xff66ff, 0xff59bc, /* 76-87 */ 0xff9c9c, 0xffd39c, 0xffff9c, 0xe2ff9c, 0x9cff9c, 0x9cffdb, 0x9cffff, 0x9cd3ff, 0x9c9cff, 0xdc9cff, 0xff9cff, 0xff94d3, /* 88-98 */ 0x000000, 0x131313, 0x282828, 0x363636, 0x4d4d4d, 0x656565, 0x818181, 0x9f9f9f, 0xbcbcbc, 0xe2e2e2, 0xffffff, -1 }; +/* clang-format on */ -static int scrollback_lines, scrollback_time, scrollback_burst_remove; +static int scrollback_lines, scrollback_time, scrollback_burst_remove, colors_ansi_24bit; /* * If positive, remove lines older than scrollback_max_age seconds. * Deletion is triggered by the "gui print text finished" signal (i.e. a message @@ -242,33 +246,29 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view) void gui_printtext_get_colors(int *flags, int *fg, int *bg, int *attr) { *attr = 0; - if (*flags & GUI_PRINT_FLAG_MIRC_COLOR) { - /* mirc colors - extended colours proposal */ - gboolean use_24_map = FALSE; - use_24_map = settings_get_bool("colors_ansi_24bit"); - if (*bg >= 0) { - if (use_24_map && mirc_colors24[*bg % 100] != -1) { - *bg = mirc_colors24[*bg % 100]; - *flags |= GUI_PRINT_FLAG_COLOR_24_BG; - } else { - *bg = mirc_colors[*bg % 100]; - *flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; - /* ignore mirc color 99 = -1 (reset) */ - if (*bg != -1 && settings_get_bool("mirc_blink_fix")) { - if (*bg < 16) /* ansi bit flip :-( */ - *bg = (*bg&8) | (*bg&4)>>2 | (*bg&2) | (*bg&1)<<2; - *bg = term_color256map[*bg&0xff] & 7; - } + /* mirc colors - extended colours proposal */ + if ((*flags & GUI_PRINT_FLAG_MIRC_COLOR_BG) && (*bg >= 0)) { + if (colors_ansi_24bit && mirc_colors_24bit[*bg % 100] != -1) { + *bg = mirc_colors_24bit[*bg % 100]; + *flags |= GUI_PRINT_FLAG_COLOR_24_BG; + } else { + *bg = mirc_colors[*bg % 100]; + *flags &= ~GUI_PRINT_FLAG_COLOR_24_BG; + if (*bg != -1 && settings_get_bool("mirc_blink_fix")) { + if (*bg < 16) /* ansi bit flip :-( */ + *bg = + (*bg & 8) | (*bg & 4) >> 2 | (*bg & 2) | (*bg & 1) << 2; + *bg = term_color256map[*bg & 0xff] & 7; } } - if (*fg >= 0) { - if (use_24_map && mirc_colors24[*fg % 100] != -1) { - *fg = mirc_colors24[*fg % 100]; - *flags |= GUI_PRINT_FLAG_COLOR_24_FG; - } else { - *fg = mirc_colors[*fg % 100]; - *flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; - } + } + if ((*flags & GUI_PRINT_FLAG_MIRC_COLOR_FG) && (*fg >= 0)) { + if (colors_ansi_24bit && mirc_colors_24bit[*fg % 100] != -1) { + *fg = mirc_colors_24bit[*fg % 100]; + *flags |= GUI_PRINT_FLAG_COLOR_24_FG; + } else { + *fg = mirc_colors[*fg % 100]; + *flags &= ~GUI_PRINT_FLAG_COLOR_24_FG; } } @@ -396,6 +396,7 @@ static void read_settings(void) scrollback_time = settings_get_time("scrollback_time")/1000; scrollback_max_age = settings_get_time("scrollback_max_age")/1000; scrollback_burst_remove = settings_get_int("scrollback_burst_remove"); + colors_ansi_24bit = settings_get_bool("colors_ansi_24bit"); } void gui_printtext_init(void) diff --git a/src/fe-text/terminfo-core.h b/src/fe-text/terminfo-core.h index cb0e41e2..4ba66957 100644 --- a/src/fe-text/terminfo-core.h +++ b/src/fe-text/terminfo-core.h @@ -1,6 +1,7 @@ #ifndef IRSSI_FE_TEXT_TERMINFO_CORE_H #define IRSSI_FE_TEXT_TERMINFO_CORE_H +#include #include #define terminfo_move(x, y) current_term->tr_move(current_term, x, y) diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c index ee474785..40a0ea59 100644 --- a/src/fe-text/textbuffer-view.c +++ b/src/fe-text/textbuffer-view.c @@ -121,25 +121,15 @@ static void textbuffer_cache_unref(TEXT_BUFFER_CACHE_REC *cache) static void unformat_24bit_line_color(const unsigned char **ptr, int off, int *flags, unsigned int *fg, unsigned int *bg) { unsigned int color; - unsigned char rgbx[4]; - unsigned int i; - for (i = 0; i < 4; ++i) { - if ((*ptr)[i + off] == '\0') - return; - 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) { + int is_bg; + + if (!unformat_24bit_color_alg((const char **) ptr, off, &is_bg, &color)) + return; + + if (is_bg) { *flags = (*flags & FGATTR) | ATTR_BGCOLOR24; *bg = color; - } - else { + } else { *flags = (*flags & BGATTR) | ATTR_FGCOLOR24; *fg = color; } @@ -182,10 +172,16 @@ static inline void unformat(const unsigned char **ptr, int *color, unsigned int case FORMAT_STYLE_MONOSPACE: /* *color ^= ATTR_MONOSPACE; */ break; + case FORMAT_STYLE_SPECIAL: + case FORMAT_STYLE_INDENT: /* this must be handled by view_line_draw */ case FORMAT_STYLE_DEFAULTS: - *color = ATTR_RESET; - break; case FORMAT_STYLE_CLRTOEOL: + case FORMAT_STYLE_THEME_DEFAULTS: + case FORMAT_STYLE_PUSH: + case FORMAT_STYLE_POP: + case FORMAT_STYLE_KEEP: + /* these are not supposed to leak into the textbuffer-view */ + g_assert_not_reached(); break; #define SET_COLOR_EXT_FG_BITS(base, pc) \ *color &= ~ATTR_FGCOLOR24; \ diff --git a/src/fe-text/textbuffer.h b/src/fe-text/textbuffer.h index 6c72a569..de010d3a 100644 --- a/src/fe-text/textbuffer.h +++ b/src/fe-text/textbuffer.h @@ -1,6 +1,8 @@ #ifndef IRSSI_FE_TEXT_TEXTBUFFER_H #define IRSSI_FE_TEXT_TEXTBUFFER_H +#include + /* Make sure TEXT_CHUNK_REC is not slightly more than a page, as that wastes a lot of memory. */ #define LINE_TEXT_CHUNK_SIZE (16384 - 16)