From 25ad30d5e42e918358ef325ea59db9d52ea477f3 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Sat, 13 Mar 2021 21:51:01 +0100 Subject: [PATCH 1/2] add format_string_expand to Perl --- src/perl/ui/Formats.xs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/perl/ui/Formats.xs b/src/perl/ui/Formats.xs index 8e34b7b9..fbd0cbf4 100644 --- a/src/perl/ui/Formats.xs +++ b/src/perl/ui/Formats.xs @@ -50,6 +50,16 @@ format_real_length(str, len) char *str int len +void +format_string_expand(str) + char *str +PREINIT: + char *ret; +PPCODE: + ret = format_string_expand(str, NULL); + XPUSHs(sv_2mortal(new_pv(ret))); + g_free(ret); + void strip_codes(input) char *input From 030da3ec9c62e7c30b4a6ebe49a285aed278a5b5 Mon Sep 17 00:00:00 2001 From: Ailin Nemui Date: Sun, 14 Mar 2021 18:31:56 +0100 Subject: [PATCH 2/2] add format_string_expand and format_string_unexpand methods to Perl --- src/fe-common/core/formats.c | 163 +++++++++++++++++++++++++++++++ src/fe-common/core/formats.h | 1 + src/fe-text/textbuffer-formats.c | 6 +- src/fe-text/textbuffer-formats.h | 2 +- src/fe-text/textbuffer-view.c | 2 +- src/fe-text/textbuffer.c | 10 +- src/fe-text/textbuffer.h | 7 ++ src/perl/textui/TextBuffer.xs | 32 ++++++ src/perl/ui/Formats.xs | 9 ++ 9 files changed, 226 insertions(+), 6 deletions(-) diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index de3898ee..51588afb 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -38,6 +38,7 @@ static const char *format_backs = "04261537"; static const char *format_fores = "kbgcrmyw"; static const char *format_boldfores = "KBGCRMYW"; +static const char *ext_color_al = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; static int signal_gui_print_text; static int hide_text_style, hide_server_tags, hide_colors; @@ -121,10 +122,23 @@ void format_ext_color(GString *out, int bg, int color) : 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); } +static void format_ext_color_unexpand(GString *out, gboolean bg, int base, char color) +{ + unsigned char value = base + (unsigned char) color - FORMAT_COLOR_NOCHANGE - 0x10; + + g_string_append_c(out, '%'); + g_string_append_c(out, bg ? 'x' : 'X'); + if (value > 214) + value += 10; + g_string_append_c(out, '1' + (value / 36)); + g_string_append_c(out, ext_color_al[value % 36]); +} + #ifdef TERM_TRUECOLOR void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int *flags) { @@ -152,6 +166,28 @@ void unformat_24bit_color(char **ptr, int off, int *fgcolor, int *bgcolor, int * *flags |= GUI_PRINT_FLAG_COLOR_24_FG; } } + +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; + 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_printf(out, "%06X", color); +} #endif void format_24bit_color(GString *out, int bg, unsigned int color) @@ -308,6 +344,16 @@ int format_expand_styles(GString *out, const char **format, int *flags) format_24bit_color(out, fmt == 'z', tmp2); break; + case 'o': + g_string_append_c(out, 4); + g_string_append_c(out, FORMAT_COLOR_NOCHANGE); + g_string_append_c(out, (char) -1); + break; + case 'O': + g_string_append_c(out, 4); + g_string_append_c(out, (char) -1); + g_string_append_c(out, FORMAT_COLOR_NOCHANGE); + break; default: /* check if it's a background color */ p = strchr(format_backs, fmt); @@ -557,6 +603,123 @@ char *format_string_expand(const char *text, int *flags) return ret; } +inline static void format_flag_unexpand(GString *out, char flag) +{ + g_string_append_c(out, '%'); + g_string_append_c(out, flag); +} + +char *format_string_unexpand(const char *text, int flags) +{ + GString *out; + + g_return_val_if_fail(text != NULL, NULL); + + out = g_string_sized_new(strlen(text)); + while (*text != '\0') { + switch (*text) { + case '%': + g_string_append(out, "%%"); + break; + case 4: + text++; + if (*text == '\0') + break; + switch (*text) { + case FORMAT_COLOR_EXT1: + format_ext_color_unexpand(out, FALSE, 0x10, *++text); + break; + case FORMAT_COLOR_EXT1_BG: + format_ext_color_unexpand(out, TRUE, 0x10, *++text); + break; + case FORMAT_COLOR_EXT2: + format_ext_color_unexpand(out, FALSE, 0x60, *++text); + break; + case FORMAT_COLOR_EXT2_BG: + format_ext_color_unexpand(out, TRUE, 0x60, *++text); + break; + case FORMAT_COLOR_EXT3: + format_ext_color_unexpand(out, FALSE, 0xb0, *++text); + break; + case FORMAT_COLOR_EXT3_BG: + format_ext_color_unexpand(out, TRUE, 0xb0, *++text); + break; +#ifdef TERM_TRUECOLOR + case FORMAT_COLOR_24: + format_24bit_color_unexpand(out, 1, &text); + break; +#endif + case FORMAT_STYLE_BLINK: + format_flag_unexpand(out, 'F'); + break; + case FORMAT_STYLE_UNDERLINE: + format_flag_unexpand(out, 'U'); + break; + case FORMAT_STYLE_BOLD: + format_flag_unexpand(out, '9'); + break; + case FORMAT_STYLE_REVERSE: + format_flag_unexpand(out, '8'); + break; + case FORMAT_STYLE_INDENT: + format_flag_unexpand(out, '|'); + break; + case FORMAT_STYLE_ITALIC: + format_flag_unexpand(out, 'I'); + break; + case FORMAT_STYLE_DEFAULTS: + format_flag_unexpand(out, 'N'); + break; + case FORMAT_STYLE_CLRTOEOL: + format_flag_unexpand(out, '>'); + break; + case FORMAT_STYLE_MONOSPACE: + format_flag_unexpand(out, '#'); + break; + default: + if (*text != FORMAT_COLOR_NOCHANGE) { + unsigned int value = (unsigned char) *text - '0'; + + g_string_append_c(out, '%'); + if (value < 8) { + g_string_append_c(out, format_fores[value]); + } else if (value < 16) { + g_string_append_c(out, format_boldfores[value - 8]); + } else { + g_string_append_c(out, 'O'); + } + } + text++; + if (*text == '\0') + break; + + if (*text != FORMAT_COLOR_NOCHANGE) { + unsigned int value = (unsigned char) *text - '0'; + + g_string_append_c(out, '%'); + if (value < 8) { + g_string_append_c(out, format_backs[value]); + } else if (value < 16) { + g_string_append(out, "x0"); + g_string_append_c(out, ext_color_al[value]); + } else { + g_string_append_c(out, 'o'); + } + } + break; + } + break; + default: + g_string_append_c(out, *text); + break; + } + if (*text != '\0') + text++; + } + + return g_string_free(out, FALSE); +} + static char *format_get_text_args(TEXT_DEST_REC *dest, const char *text, char **arglist) { diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 530f42bf..12274638 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -81,6 +81,7 @@ int format_get_length(const char *str); int format_real_length(const char *str, int len); char *format_string_expand(const char *text, int *flags); +char *format_string_unexpand(const char *text, int flags); char *format_get_text(const char *module, WINDOW_REC *window, void *server, const char *target, diff --git a/src/fe-text/textbuffer-formats.c b/src/fe-text/textbuffer-formats.c index e3d331f1..2aa06cb2 100644 --- a/src/fe-text/textbuffer-formats.c +++ b/src/fe-text/textbuffer-formats.c @@ -344,7 +344,7 @@ static char *fallback_format(TEXT_BUFFER_FORMAT_REC *format_rec) return g_string_free(bs, FALSE); } -char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line) +char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean raw) { TEXT_DEST_REC dest; GUI_WINDOW_REC *gui; @@ -430,6 +430,10 @@ char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line) format_create_dest(&dest, NULL, NULL, line->info.level, buffer->window); text = g_strdup(line->info.text); } + + if (raw) + return text; + tmp = parse_colors(&dest, text); g_free(text); return tmp; diff --git a/src/fe-text/textbuffer-formats.h b/src/fe-text/textbuffer-formats.h index d595df8a..17a907c1 100644 --- a/src/fe-text/textbuffer-formats.h +++ b/src/fe-text/textbuffer-formats.h @@ -23,7 +23,7 @@ typedef struct _TEXT_BUFFER_FORMAT_REC { void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec); void textbuffer_meta_rec_free(TEXT_BUFFER_META_REC *rec); -char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line); +char *textbuffer_line_get_text(TEXT_BUFFER_REC *buffer, LINE_REC *line, gboolean raw); void textbuffer_formats_init(void); void textbuffer_formats_deinit(void); diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c index 9af3cb3c..79f3522c 100644 --- a/src/fe-text/textbuffer-view.c +++ b/src/fe-text/textbuffer-view.c @@ -274,7 +274,7 @@ view_update_line_cache(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) linecount = 1; lines = NULL; - line_text = textbuffer_line_get_text(view->buffer, line); + line_text = textbuffer_line_get_text(view->buffer, line, FALSE); if (line_text != NULL) { for (ptr = (unsigned char *) line_text;;) { if (*ptr == '\0') diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 5a5ddf21..25fce22f 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -238,11 +238,15 @@ void textbuffer_line2text(TEXT_BUFFER_REC *buffer, LINE_REC *line, int coloring, g_string_truncate(str, 0); - if ((ptr = textbuffer_line_get_text(buffer, line)) != NULL) { - if (coloring == 0) { + if ((ptr = textbuffer_line_get_text(buffer, line, coloring == COLORING_RAW)) != NULL) { + if (coloring == COLORING_STRIP) { tmp = ptr; ptr = strip_codes(tmp); g_free(tmp); + } else if (coloring == COLORING_UNEXPAND) { + tmp = ptr; + ptr = format_string_unexpand(tmp, 0); + g_free(tmp); } g_string_append(str, ptr); g_free(ptr); @@ -288,7 +292,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline, (line->info.level & nolevel) == 0; if (*text != '\0') { - textbuffer_line2text(buffer, line, FALSE, str); + textbuffer_line2text(buffer, line, 0, str); if (line_matched) { line_matched = regexp ? diff --git a/src/fe-text/textbuffer.h b/src/fe-text/textbuffer.h index bb4e820a..5f5f9a27 100644 --- a/src/fe-text/textbuffer.h +++ b/src/fe-text/textbuffer.h @@ -11,6 +11,13 @@ enum { LINE_CMD_EOL=0x80, /* line ends here */ }; +enum { + COLORING_STRIP = 0, + COLORING_EXPAND = 1, + COLORING_UNEXPAND = 2, + COLORING_RAW = 3, +}; + struct _TEXT_BUFFER_FORMAT_REC; typedef struct { diff --git a/src/perl/textui/TextBuffer.xs b/src/perl/textui/TextBuffer.xs index 4859f3da..6695eae0 100644 --- a/src/perl/textui/TextBuffer.xs +++ b/src/perl/textui/TextBuffer.xs @@ -6,6 +6,38 @@ MODULE = Irssi::TextUI::TextBuffer PACKAGE = Irssi PROTOTYPES: ENABLE +#******************************* +MODULE = Irssi::TextUI::TextBuffer PACKAGE = Irssi +#******************************* + +int +COLORING_STRIP() +CODE: + RETVAL = COLORING_STRIP; +OUTPUT: + RETVAL + +int +COLORING_EXPAND() +CODE: + RETVAL = COLORING_EXPAND; +OUTPUT: + RETVAL + +int +COLORING_UNEXPAND() +CODE: + RETVAL = COLORING_UNEXPAND; +OUTPUT: + RETVAL + +int +COLORING_RAW() +CODE: + RETVAL = COLORING_RAW; +OUTPUT: + RETVAL + #******************************* MODULE = Irssi::TextUI::TextBuffer PACKAGE = Irssi::TextUI::Line PREFIX = textbuffer_line_ #******************************* diff --git a/src/perl/ui/Formats.xs b/src/perl/ui/Formats.xs index fbd0cbf4..c03e6bb5 100644 --- a/src/perl/ui/Formats.xs +++ b/src/perl/ui/Formats.xs @@ -70,6 +70,15 @@ PPCODE: XPUSHs(sv_2mortal(new_pv(ret))); g_free(ret); +void +format_string_unexpand(input) + char *input +PREINIT: + char *ret; +PPCODE: + ret = format_string_unexpand(input, 0); + XPUSHs(sv_2mortal(new_pv(ret))); + g_free(ret); void format_create_dest(target, level=MSGLEVEL_CLIENTNOTICE, window=NULL)