From 9f6956415a323d7696c98f98fef8a7b887603cce Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 3 Jul 2019 22:19:00 +0200 Subject: [PATCH] reapply a theme to previous formats --- README.md | 2 +- configure.ac | 2 +- src/core/expandos.c | 3 +- src/core/expandos.h | 1 + src/core/levels.h | 3 +- src/fe-common/core/formats.h | 2 + src/fe-common/core/printtext.c | 4 + src/fe-text/Makefile.am | 4 +- src/fe-text/gui-printtext.c | 3 +- src/fe-text/irssi.c | 5 + src/fe-text/textbuffer-commands.c | 22 +++ src/fe-text/textbuffer-formats.c | 216 ++++++++++++++++++++++++++++++ src/fe-text/textbuffer-formats.h | 22 +++ src/fe-text/textbuffer-view.c | 3 +- src/fe-text/textbuffer.c | 9 ++ src/fe-text/textbuffer.h | 5 + tests/fe-text/Makefile.am | 1 + 17 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 src/fe-text/textbuffer-formats.c create mode 100644 src/fe-text/textbuffer-formats.h diff --git a/README.md b/README.md index 9ea92940..a27e3794 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ make && sudo make install ### Requirements -- [glib-2.28](https://wiki.gnome.org/Projects/GLib) or greater +- [glib-2.58](https://wiki.gnome.org/Projects/GLib) or greater - [openssl](https://www.openssl.org/) - [perl-5.6](https://www.perl.org/) or greater (for perl support) - terminfo or ncurses (for text frontend) diff --git a/configure.ac b/configure.ac index 7d35aefa..fb84f8e1 100644 --- a/configure.ac +++ b/configure.ac @@ -273,7 +273,7 @@ for try in 1 2; do echo "*** trying without -lgmodule" glib_modules= fi - AM_PATH_GLIB_2_0(2.28.0,,, $glib_modules) + AM_PATH_GLIB_2_0(2.58.0,,, $glib_modules) if test "$GLIB_LIBS"; then if test $glib_modules = gmodule; then AC_DEFINE(HAVE_GMODULE) diff --git a/src/core/expandos.c b/src/core/expandos.c index 96e2d9f3..9280b6f3 100644 --- a/src/core/expandos.c +++ b/src/core/expandos.c @@ -48,6 +48,7 @@ typedef struct { } EXPANDO_REC; const char *current_expando = NULL; +time_t current_time = (time_t)-1; static int timer_tag; @@ -441,7 +442,7 @@ static char *expando_time(SERVER_REC *server, void *item, int *free_ret) struct tm *tm; char str[256]; - now = time(NULL); + now = current_time != (time_t)-1 ? current_time : time(NULL); tm = localtime(&now); if (strftime(str, sizeof(str), timestamp_format, tm) == 0) diff --git a/src/core/expandos.h b/src/core/expandos.h index 05dfcf11..c03333a7 100644 --- a/src/core/expandos.h +++ b/src/core/expandos.h @@ -17,6 +17,7 @@ typedef char* (*EXPANDO_FUNC) (SERVER_REC *server, void *item, int *free_ret); extern const char *current_expando; +extern time_t current_time; /* Create expando - overrides any existing ones. ... = signal, type, ..., NULL - list of signals that might change the diff --git a/src/core/levels.h b/src/core/levels.h index 385ecd0c..121e3a5a 100644 --- a/src/core/levels.h +++ b/src/core/levels.h @@ -38,7 +38,8 @@ enum { MSGLEVEL_NEVER = 0x4000000, /* never ignore / never log */ MSGLEVEL_LASTLOG = 0x8000000, /* used for /lastlog */ - MSGLEVEL_HIDDEN = 0x10000000 /* Hidden from view */ + MSGLEVEL_HIDDEN = 0x10000000, /* Hidden from view */ + MSGLEVEL_FORMAT = 0x80000000 /* Format data */ }; int level_get(const char *level); diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 2e6133be..95d83a9c 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -45,6 +45,8 @@ struct _FORMAT_REC { #define PRINT_FLAG_SET_SERVERTAG 0x0010 #define PRINT_FLAG_UNSET_SERVERTAG 0x0020 +#define PRINT_FLAG_FORMAT 0x0080 + typedef struct _HILIGHT_REC HILIGHT_REC; typedef struct _TEXT_DEST_REC { diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index 1826c754..692a3bc2 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -38,6 +38,7 @@ static int signal_gui_print_text_finished; static int signal_print_starting; static int signal_print_text; static int signal_print_format; +static int signal_print_noformat; static int sending_print_starting; @@ -313,6 +314,8 @@ static void printtext_dest_args(TEXT_DEST_REC *dest, const char *text, va_list v } str = printtext_get_args(dest, text, va); + signal_emit_id(signal_print_noformat, 2, + dest, str); print_line(dest, str); g_free(str); } @@ -515,6 +518,7 @@ void printtext_init(void) signal_print_starting = signal_get_uniq_id("print starting"); signal_print_text = signal_get_uniq_id("print text"); signal_print_format = signal_get_uniq_id("print format"); + signal_print_noformat = signal_get_uniq_id("print noformat"); read_settings(); signal_add("print text", (SIGNAL_FUNC) sig_print_text); diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am index 94ce1a3c..8835f4b9 100644 --- a/src/fe-text/Makefile.am +++ b/src/fe-text/Makefile.am @@ -45,6 +45,7 @@ irssi_SOURCES = \ textbuffer.c \ textbuffer-commands.c \ textbuffer-view.c \ + textbuffer-formats.c \ irssi.c \ module-formats.c @@ -57,7 +58,8 @@ pkginc_fe_text_HEADERS = \ statusbar-item.h \ term.h \ textbuffer.h \ - textbuffer-view.h + textbuffer-view.h \ + textbuffer-formats.h noinst_HEADERS = \ gui-entry.h \ diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 24e91624..84a6e9cd 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -329,7 +329,7 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor, GUI_WINDOW_REC *gui; TEXT_BUFFER_VIEW_REC *view; LINE_REC *insert_after; - LINE_INFO_REC lineinfo; + LINE_INFO_REC lineinfo = { 0 }; int fg, bg, flags, attr; flags = GPOINTER_TO_INT(pflags); @@ -346,6 +346,7 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor, gui = WINDOW_GUI(window); lineinfo.time = (gui->use_insert_after && gui->insert_after_time) ? gui->insert_after_time : time(NULL); + lineinfo.format = dest != NULL && dest->flags & PRINT_FLAG_FORMAT ? LINE_INFO_FORMAT_SET : NULL; view = gui->view; insert_after = gui->use_insert_after ? diff --git a/src/fe-text/irssi.c b/src/fe-text/irssi.c index 8b466905..924a5089 100644 --- a/src/fe-text/irssi.c +++ b/src/fe-text/irssi.c @@ -71,6 +71,9 @@ void gui_expandos_deinit(void); void textbuffer_commands_init(void); void textbuffer_commands_deinit(void); +void textbuffer_formats_init(void); +void textbuffer_formats_deinit(void); + void lastlog_init(void); void lastlog_deinit(void); @@ -168,6 +171,7 @@ static void textui_finish_init(void) textbuffer_init(); textbuffer_view_init(); textbuffer_commands_init(); + textbuffer_formats_init(); gui_expandos_init(); gui_printtext_init(); gui_readline_init(); @@ -256,6 +260,7 @@ static void textui_deinit(void) mainwindow_activity_deinit(); mainwindows_deinit(); gui_expandos_deinit(); + textbuffer_formats_deinit(); textbuffer_commands_deinit(); textbuffer_view_deinit(); textbuffer_deinit(); diff --git a/src/fe-text/textbuffer-commands.c b/src/fe-text/textbuffer-commands.c index 318ee077..37318690 100644 --- a/src/fe-text/textbuffer-commands.c +++ b/src/fe-text/textbuffer-commands.c @@ -20,6 +20,7 @@ #include "module.h" #include +#include #include #include #include @@ -360,6 +361,25 @@ static void cmd_scrollback_status(void) total_lines, (int)(total_mem / 1024)); } +/* SYNTAX: SCROLLBACK REDRAW */ +static void cmd_scrollback_redraw(void) +{ + GUI_WINDOW_REC *gui; + LINE_REC *line; + + gui = WINDOW_GUI(active_win); + + term_refresh_freeze(); + line = gui->view->buffer->cur_line; + while (line != NULL) { + line = textbuffer_reformat_line(active_win, line); + line = line->prev; + } + + gui_window_redraw(active_win); + term_refresh_thaw(); +} + static void sig_away_changed(SERVER_REC *server) { GSList *tmp; @@ -411,6 +431,7 @@ void textbuffer_commands_init(void) command_bind("scrollback home", NULL, (SIGNAL_FUNC) cmd_scrollback_home); command_bind("scrollback end", NULL, (SIGNAL_FUNC) cmd_scrollback_end); command_bind("scrollback status", NULL, (SIGNAL_FUNC) cmd_scrollback_status); + command_bind("scrollback redraw", NULL, (SIGNAL_FUNC) cmd_scrollback_redraw); command_set_options("clear", "all"); command_set_options("scrollback clear", "all"); @@ -434,6 +455,7 @@ void textbuffer_commands_deinit(void) command_unbind("scrollback home", (SIGNAL_FUNC) cmd_scrollback_home); command_unbind("scrollback end", (SIGNAL_FUNC) cmd_scrollback_end); command_unbind("scrollback status", (SIGNAL_FUNC) cmd_scrollback_status); + command_unbind("scrollback redraw", (SIGNAL_FUNC) cmd_scrollback_redraw); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); signal_remove("away mode changed", (SIGNAL_FUNC) sig_away_changed); diff --git a/src/fe-text/textbuffer-formats.c b/src/fe-text/textbuffer-formats.c new file mode 100644 index 00000000..89308652 --- /dev/null +++ b/src/fe-text/textbuffer-formats.c @@ -0,0 +1,216 @@ +#include "module.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int skip_next_printtext; +TEXT_BUFFER_FORMAT_REC *format_rec; + +#define g_ref_string_release_opt(str) ((str) == NULL ? (void)0 : g_ref_string_release(str)) + +void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec) +{ + int n; + if (rec == NULL) + return; + g_ref_string_release_opt(rec->module); + g_ref_string_release_opt(rec->format); + g_ref_string_release_opt(rec->server_tag); + g_ref_string_release_opt(rec->target); + g_ref_string_release_opt(rec->nick); + if (rec->nargs >= 1) { + g_ref_string_release_opt(rec->args[0]); + } + for (n = 1; n < rec->nargs; n++) { + g_free(rec->args[n]); + } + rec->nargs = 0; + g_free(rec); +} + +#define g_ref_string_new_intern_opt(str) ((str) == NULL ? NULL : g_ref_string_new_intern(str)) + +static TEXT_BUFFER_FORMAT_REC *format_rec_new(const char *module, const char *format_tag, + const char *server_tag, const char *target, const char *nick, + int nargs, const char **args) +{ + int n; + TEXT_BUFFER_FORMAT_REC *ret = g_new0(TEXT_BUFFER_FORMAT_REC, 1); + ret->module = g_ref_string_new_intern_opt(module); + ret->format = g_ref_string_new_intern_opt(format_tag); + ret->server_tag = g_ref_string_new_intern_opt(server_tag); + ret->target = g_ref_string_new_intern_opt(target); + ret->nick = g_ref_string_new_intern_opt(nick); + ret->nargs = nargs; + ret->args = g_new0(char *, nargs); + if (nargs >= 1) { + ret->args[0] = g_ref_string_new_intern_opt(args[0]); + } + for (n = 1; n < nargs; n++) { + ret->args[n] = g_strdup(args[n]); + } + return ret; +} + +static void sig_print_format(THEME_REC *theme, const char *module, TEXT_DEST_REC *dest, void *formatnump, const char **args) +{ + int formatnum; + FORMAT_REC *formats; + + skip_next_printtext = TRUE; + dest->flags |= PRINT_FLAG_FORMAT; + + formatnum = GPOINTER_TO_INT(formatnump); + formats = g_hash_table_lookup(default_formats, module); + + textbuffer_format_rec_free(format_rec); + format_rec = format_rec_new(module, formats[formatnum].tag, dest->server_tag, dest->target, dest->nick, + formats[formatnum].params, args); + format_rec->flags = dest->flags; +} + +static void sig_print_noformat(TEXT_DEST_REC *dest, const char *text) +{ + dest->flags |= PRINT_FLAG_FORMAT; + textbuffer_format_rec_free(format_rec); + format_rec = format_rec_new(NULL, NULL, dest->server_tag, dest->target, dest->nick, + 2, (const char *[]){ NULL, text }); + format_rec->flags = dest->flags; +} + +static void sig_print_text(TEXT_DEST_REC *dest, const char *text) +{ + if (skip_next_printtext) { + skip_next_printtext = FALSE; + return; + } +} + +static void sig_gui_print_text_finished(WINDOW_REC *window) +{ + GUI_WINDOW_REC *gui; + TEXT_BUFFER_VIEW_REC *view; + LINE_REC *insert_after; + LINE_INFO_REC lineinfo = { 0 }; + + static const unsigned char eol[] = { 0, LINE_CMD_EOL }; + + if (format_rec == NULL) + return; + + gui = WINDOW_GUI(window); + view = gui->view; + insert_after = gui->use_insert_after ? + gui->insert_after : view->buffer->cur_line; + + lineinfo.format = format_rec; + lineinfo.level = insert_after->info.level | MSGLEVEL_FORMAT; + lineinfo.time = insert_after->info.time; + format_rec = NULL; + + insert_after = textbuffer_insert(view->buffer, insert_after, eol, + 2, &lineinfo); + + if (gui->use_insert_after) + gui->insert_after = insert_after; +} + +LINE_REC *textbuffer_reformat_line(WINDOW_REC *window, LINE_REC *line) +{ + GUI_WINDOW_REC *gui; + LINE_REC *curr; + + gui = WINDOW_GUI(window); + if (line == NULL) + return NULL; + + if (line->info.level & MSGLEVEL_FORMAT) { + TEXT_DEST_REC dest; + THEME_REC *theme; + int formatnum; + TEXT_BUFFER_FORMAT_REC *format_rec; + char *text, *tmp, *str; + + term_refresh_freeze(); + + curr = line; + line = line->prev; + while (line != NULL && line->info.format != NULL && line->info.format == LINE_INFO_FORMAT_SET) { + LINE_REC *prev = line->prev; + textbuffer_view_remove_line(gui->view, line); + line = prev; + } + line = NULL; + format_rec = curr->info.format; + + format_create_dest(&dest, format_rec->server_tag != NULL ? server_find_tag(format_rec->server_tag) : NULL, + format_rec->target, curr->info.level & ~MSGLEVEL_FORMAT, window); + + theme = window_get_theme(dest.window); + + if (format_rec->format != NULL) { + formatnum = format_find_tag(format_rec->module, format_rec->format); + text = format_get_text_theme_charargs(theme, format_rec->module, &dest, + formatnum, format_rec->args); + } else { + text = g_strdup(format_rec->args[1]); + } + + if (*text != '\0') { + current_time = curr->info.time; + + tmp = format_get_level_tag(theme, &dest); + str = !theme->info_eol ? format_add_linestart(text, tmp) : + format_add_lineend(text, tmp); + g_free_not_null(tmp); + g_free_not_null(text); + text = str; + tmp = format_get_line_start(theme, &dest, curr->info.time); + str = !theme->info_eol ? format_add_linestart(text, tmp) : + format_add_lineend(text, tmp); + g_free_not_null(tmp); + g_free_not_null(text); + text = str; + str = g_strconcat(text, "\n", NULL); + g_free(text); + + dest.flags |= PRINT_FLAG_FORMAT; + gui_printtext_after_time(&dest, curr->prev, str, curr->info.time); + g_free(str); + + current_time = (time_t)-1; + } + term_refresh_thaw(); + return curr; + } else { + return line; + } +} + +void textbuffer_formats_init(void) +{ + skip_next_printtext = FALSE; + format_rec = NULL; + + signal_add("print format", (SIGNAL_FUNC) sig_print_format); + signal_add("print noformat", (SIGNAL_FUNC) sig_print_noformat); + signal_add("gui print text finished", (SIGNAL_FUNC) sig_gui_print_text_finished); + signal_add_first("print text", (SIGNAL_FUNC) sig_print_text); +} + +void textbuffer_formats_deinit(void) +{ + signal_remove("print format", (SIGNAL_FUNC) sig_print_format); + signal_remove("print noformat", (SIGNAL_FUNC) sig_print_noformat); + signal_remove("gui print text finished", (SIGNAL_FUNC) sig_gui_print_text_finished); + signal_remove("print text", (SIGNAL_FUNC) sig_print_text); + + textbuffer_format_rec_free(format_rec); +} diff --git a/src/fe-text/textbuffer-formats.h b/src/fe-text/textbuffer-formats.h new file mode 100644 index 00000000..08e94237 --- /dev/null +++ b/src/fe-text/textbuffer-formats.h @@ -0,0 +1,22 @@ +#ifndef IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H +#define IRSSI_FE_TEXT_TEXTBUFFER_FORMATS_H + +#include + +typedef struct _TEXT_BUFFER_FORMAT_REC { + char *module; + char *format; + char *server_tag; + char *target; + char *nick; + char **args; + int nargs; + int flags; +} TEXT_BUFFER_FORMAT_REC; + +void textbuffer_format_rec_free(TEXT_BUFFER_FORMAT_REC *rec); +LINE_REC *textbuffer_reformat_line(WINDOW_REC *window, LINE_REC *line); +void textbuffer_formats_init(void); +void textbuffer_formats_deinit(void); + +#endif diff --git a/src/fe-text/textbuffer-view.c b/src/fe-text/textbuffer-view.c index ec518cbf..ea74dece 100644 --- a/src/fe-text/textbuffer-view.c +++ b/src/fe-text/textbuffer-view.c @@ -22,6 +22,7 @@ #include "module.h" #include +#include #include #include @@ -45,7 +46,7 @@ static GSList *views; textbuffer_view_get_line_cache(view, line)->count #define view_line_is_hidden(view, line) \ - (((line)->info.level & (view)->hidden_level) != 0) + (((line)->info.level & ((view)->hidden_level | MSGLEVEL_FORMAT)) != 0) #define view_get_linecount(view, line) \ (view_line_is_hidden(view, line) ? 0 : view_get_linecount_hidden(view, line)) diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index 470c0b00..24878441 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -27,6 +27,7 @@ #include #include +#include #define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*)) @@ -396,6 +397,10 @@ void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line) buffer->lines_count--; text_chunk_line_free(buffer, line); + if (line->info.format != NULL && + line->info.format != LINE_INFO_FORMAT_SET) { + textbuffer_format_rec_free(line->info.format); + } g_slice_free(LINE_REC, line); } @@ -414,6 +419,10 @@ void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer) while (buffer->first_line != NULL) { line = buffer->first_line->next; + if (buffer->first_line->info.format != NULL && + buffer->first_line->info.format != LINE_INFO_FORMAT_SET) { + textbuffer_format_rec_free(buffer->first_line->info.format); + } g_slice_free(LINE_REC, buffer->first_line); buffer->first_line = line; } diff --git a/src/fe-text/textbuffer.h b/src/fe-text/textbuffer.h index cbe4fbf0..53460b4a 100644 --- a/src/fe-text/textbuffer.h +++ b/src/fe-text/textbuffer.h @@ -8,6 +8,8 @@ #define LINE_COLOR_BG 0x20 #define LINE_COLOR_DEFAULT 0x10 +#define LINE_INFO_FORMAT_SET (void*) 0x1 + enum { LINE_CMD_EOL=0x80, /* line ends here */ LINE_CMD_CONTINUE, /* line continues in next block */ @@ -26,9 +28,12 @@ enum { #endif }; +struct _TEXT_BUFFER_FORMAT_REC; + typedef struct { int level; time_t time; + struct _TEXT_BUFFER_FORMAT_REC *format; } LINE_INFO_REC; typedef struct _LINE_REC { diff --git a/tests/fe-text/Makefile.am b/tests/fe-text/Makefile.am index b1762c7d..2a3450e9 100644 --- a/tests/fe-text/Makefile.am +++ b/tests/fe-text/Makefile.am @@ -26,6 +26,7 @@ test_paste_join_multiline_SOURCES = \ ../../src/fe-text/term-terminfo.c \ ../../src/fe-text/terminfo-core.c \ ../../src/fe-text/term.c \ + ../../src/fe-text/textbuffer-formats.c \ ../../src/fe-text/textbuffer-view.c \ ../../src/fe-text/textbuffer.c \ ../../src/fe-text/gui-windows.c \