diff options
author | Timo Sirainen <cras@irssi.org> | 2000-11-21 03:00:05 +0000 |
---|---|---|
committer | cras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2000-11-21 03:00:05 +0000 |
commit | e923b1651afc995cf75caf7c63cdf8b246272801 (patch) | |
tree | e640425514a26d764587d574bfe2335dfdde4538 /src | |
parent | e3084d3ffae3e57ddf89507e69f61b83c5ceaf90 (diff) | |
download | irssi-e923b1651afc995cf75caf7c63cdf8b246272801.zip |
/SCROLLBACK REDRAW - redraw the contents of current window according to
active formats, ie. changing theme changes scrollback.
It's still a bit buggy (can crash) with multiline formats, need to fix
it as soon as I figure out where the problem is..
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@852 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src')
-rw-r--r-- | src/fe-common/core/fe-common-core.c | 2 | ||||
-rw-r--r-- | src/fe-common/core/fe-log.c | 2 | ||||
-rw-r--r-- | src/fe-common/core/formats.c | 105 | ||||
-rw-r--r-- | src/fe-common/core/formats.h | 5 | ||||
-rw-r--r-- | src/fe-common/core/module-formats.c | 4 | ||||
-rw-r--r-- | src/fe-common/core/printtext.c | 80 | ||||
-rw-r--r-- | src/fe-common/core/themes.c | 23 | ||||
-rw-r--r-- | src/fe-text/gui-printtext.c | 138 | ||||
-rw-r--r-- | src/fe-text/gui-printtext.h | 5 | ||||
-rw-r--r-- | src/fe-text/gui-textwidget.c | 20 | ||||
-rw-r--r-- | src/fe-text/gui-windows.c | 178 | ||||
-rw-r--r-- | src/fe-text/gui-windows.h | 11 |
12 files changed, 442 insertions, 131 deletions
diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index a44bea51..8e1b4070 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -162,7 +162,9 @@ void fe_common_core_finish_init(void) signal_emit("irssi init read settings", 0); +#ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); +#endif windows_restore(); if (windows != NULL) diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 33b20f43..95ab07e4 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -461,7 +461,7 @@ static void sig_print_format(THEME_REC *theme, const char *module, if (*str != '\0') { /* add the line start format */ - linestart = format_get_line_start(log_theme, dest); + linestart = format_get_level_tag(log_theme, dest); tmp = str; str = format_add_linestart(tmp, linestart); g_free_not_null(linestart); diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 205ffec1..8d8ccaac 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -34,6 +34,27 @@ static int signal_gui_print_text; static int hide_text_style; +static int timestamps, msgs_timestamps; +static int timestamp_timeout; + +int format_find_tag(const char *module, const char *tag) +{ + FORMAT_REC *formats; + int n; + + formats = g_hash_table_lookup(default_formats, module); + if (formats == NULL) + return -1; + + for (n = 0; formats[n].def != NULL; n++) { + if (formats[n].tag != NULL && + g_strcasecmp(formats[n].tag, tag) == 0) + return n; + } + + return -1; +} + int format_expand_styles(GString *out, char format, TEXT_DEST_REC *dest) { static const char *backs = "04261537"; @@ -286,11 +307,11 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module, char **args) { MODULE_THEME_REC *module_theme; - FORMAT_REC *formats; char *text; module_theme = g_hash_table_lookup(theme->modules, module); - formats = g_hash_table_lookup(default_formats, module); + if (module_theme == NULL) + return NULL; text = module_theme->expanded_formats[formatnum]; return format_get_text_args(dest, text, args); @@ -351,7 +372,7 @@ char *format_add_linestart(const char *text, const char *linestart) MSGLEVEL_ACTIONS | MSGLEVEL_NOTICES | MSGLEVEL_SNOTES | MSGLEVEL_CTCPS) /* return the "-!- " text at the start of the line */ -char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest) +char *format_get_level_tag(THEME_REC *theme, TEXT_DEST_REC *dest) { int format; @@ -365,6 +386,81 @@ char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest) return format_get_text_theme(theme, MODULE_NAME, dest, format); } +#define show_timestamp(level) \ + ((level & (MSGLEVEL_NEVER|MSGLEVEL_LASTLOG)) == 0 && \ + (timestamps || (msgs_timestamps && ((level) & MSGLEVEL_MSGS)))) + +static char *get_timestamp(THEME_REC *theme, TEXT_DEST_REC *dest) +{ + struct tm *tm; + time_t t; + int diff; + + if (!show_timestamp(dest->level)) + return NULL; + + t = time(NULL); + + if (timestamp_timeout > 0) { + diff = t - dest->window->last_timestamp; + dest->window->last_timestamp = t; + if (diff < timestamp_timeout) + return NULL; + } + + tm = localtime(&t); + return format_get_text_theme(theme, MODULE_NAME, dest, IRCTXT_TIMESTAMP, + tm->tm_year+1900, + tm->tm_mon+1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +static char *get_server_tag(THEME_REC *theme, TEXT_DEST_REC *dest) +{ + SERVER_REC *server; + int count = 0; + + server = dest->server; + + if (server == NULL || (dest->window->active != NULL && + dest->window->active->server == server)) + return NULL; + + if (servers != NULL) { + count++; + if (servers->next != NULL) + count++; + } + if (count == 2 || lookup_servers != NULL) { + count++; + if (lookup_servers->next != NULL) + count++; + } + + return count < 2 ? NULL : + format_get_text_theme(theme, MODULE_NAME, dest, + IRCTXT_SERVERTAG, server->tag); +} + +char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest) +{ + char *timestamp, *servertag; + char *linestart; + + timestamp = get_timestamp(theme, dest); + servertag = get_server_tag(theme, dest); + + if (timestamp == NULL && servertag == NULL) + return NULL; + + linestart = g_strconcat(timestamp != NULL ? timestamp : "", + servertag, NULL); + + g_free_not_null(timestamp); + g_free_not_null(servertag); + return linestart; +} + void format_newline(WINDOW_REC *window) { window->lines++; @@ -665,6 +761,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) static void read_settings(void) { hide_text_style = settings_get_bool("hide_text_style"); + timestamps = settings_get_bool("timestamps"); + timestamp_timeout = settings_get_int("timestamp_timeout"); + msgs_timestamps = settings_get_bool("msgs_timestamps"); } void formats_init(void) diff --git a/src/fe-common/core/formats.h b/src/fe-common/core/formats.h index 6a042156..7038b5ae 100644 --- a/src/fe-common/core/formats.h +++ b/src/fe-common/core/formats.h @@ -38,6 +38,8 @@ typedef struct { int level; } TEXT_DEST_REC; +int format_find_tag(const char *module, const char *tag); + char *format_get_text(const char *module, WINDOW_REC *window, void *server, const char *target, int formatnum, ...); @@ -60,6 +62,9 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module, char *format_add_linestart(const char *text, const char *linestart); /* return the "-!- " text at the start of the line */ +char *format_get_level_tag(THEME_REC *theme, TEXT_DEST_REC *dest); + +/* return timestamp + server tag */ char *format_get_line_start(THEME_REC *theme, TEXT_DEST_REC *dest); diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 7a93ebe0..f90a4dee 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -27,8 +27,8 @@ FORMAT_REC fecommon_core_formats[] = { /* ---- */ { NULL, "Windows", 0 }, - { "line_start", "{line_start} ", 0 }, - { "line_start_irssi", "{line_start} {hilight Irssi:} ", 0 }, + { "line_start", "{line_start}", 0 }, + { "line_start_irssi", "{line_start}{hilight Irssi:} ", 0 }, { "timestamp", "$[-2.0]3:$[-2.0]4 ", 6, { 1, 1, 1, 1, 1, 1 } }, { "servertag", "[$0] ", 1, { 0 } }, { "daychange", "Day changed to $[-2.0]{0} $3 $2", 4, { 1, 1, 1, 0 } }, diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index fe05298c..d01508e7 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -33,8 +33,6 @@ #include "printtext.h" static int beep_msg_level, beep_when_away; -static int timestamps, msgs_timestamps; -static int timestamp_timeout; static int signal_gui_print_text; static int signal_print_text_stripped; @@ -120,7 +118,7 @@ static void print_line(TEXT_DEST_REC *dest, const char *text) g_return_if_fail(dest != NULL); g_return_if_fail(text != NULL); - tmp = format_get_line_start(current_theme, dest); + tmp = format_get_level_tag(current_theme, dest); str = format_add_linestart(text, tmp); g_free_not_null(tmp); @@ -250,49 +248,6 @@ void printtext_window(WINDOW_REC *window, int level, const char *text, ...) g_free(str); } -#define show_timestamp(level) \ - ((level & (MSGLEVEL_NEVER|MSGLEVEL_LASTLOG)) == 0 && \ - (timestamps || (msgs_timestamps && ((level) & MSGLEVEL_MSGS)))) - -static char *get_timestamp(TEXT_DEST_REC *dest) -{ - struct tm *tm; - time_t t; - int diff; - - if (!show_timestamp(dest->level)) - return NULL; - - t = time(NULL); - - if (timestamp_timeout > 0) { - diff = t - dest->window->last_timestamp; - dest->window->last_timestamp = t; - if (diff < timestamp_timeout) - return NULL; - } - - tm = localtime(&t); - return format_get_text_theme(NULL, MODULE_NAME, dest, IRCTXT_TIMESTAMP, - tm->tm_year+1900, - tm->tm_mon+1, tm->tm_mday, - tm->tm_hour, tm->tm_min, tm->tm_sec); -} - -static char *get_server_tag(TEXT_DEST_REC *dest) -{ - SERVER_REC *server; - - server = dest->server; - - if (server == NULL || servers == NULL || servers->next == NULL || - (dest->window->active != NULL && dest->window->active->server == server)) - return NULL; - - return format_get_text_theme(NULL, MODULE_NAME, dest, - IRCTXT_SERVERTAG, server->tag); -} - static void msg_beep_check(SERVER_REC *server, int level) { if (level != 0 && (level & MSGLEVEL_NOHILIGHT) == 0 && @@ -302,30 +257,9 @@ static void msg_beep_check(SERVER_REC *server, int level) } } -static char *fix_line_start(TEXT_DEST_REC *dest, const char *text) -{ - char *timestamp, *servertag; - char *linestart, *str; - - timestamp = get_timestamp(dest); - servertag = get_server_tag(dest); - - if (timestamp == NULL && servertag == NULL) - return g_strdup(text); - - linestart = g_strconcat(timestamp != NULL ? timestamp : "", - servertag, NULL); - str = format_add_linestart(text, linestart); - g_free(linestart); - - g_free_not_null(timestamp); - g_free_not_null(servertag); - return str; -} - static void sig_print_text(TEXT_DEST_REC *dest, const char *text) { - char *str; + char *str, *tmp; g_return_if_fail(dest != NULL); g_return_if_fail(text != NULL); @@ -335,7 +269,12 @@ static void sig_print_text(TEXT_DEST_REC *dest, const char *text) dest->window->last_line = time(NULL); format_newline(dest->window); - str = fix_line_start(dest, text); + /* add timestamp/server tag here - if it's done in print_line() + it would be written to log files too */ + tmp = format_get_line_start(current_theme, dest); + str = format_add_linestart(text, tmp); + g_free(tmp); + format_send_to_gui(dest, str); g_free(str); @@ -372,9 +311,6 @@ static void sig_gui_dialog(const char *type, const char *text) static void read_settings(void) { - timestamps = settings_get_bool("timestamps"); - timestamp_timeout = settings_get_int("timestamp_timeout"); - msgs_timestamps = settings_get_bool("msgs_timestamps"); beep_msg_level = level2bits(settings_get_str("beep_on_msg")); beep_when_away = settings_get_bool("beep_when_away"); } diff --git a/src/fe-common/core/themes.c b/src/fe-common/core/themes.c index 24685c17..076e0489 100644 --- a/src/fe-common/core/themes.c +++ b/src/fe-common/core/themes.c @@ -459,25 +459,20 @@ static void theme_read_abstracts(CONFIG_REC *config, THEME_REC *theme) } static void theme_set_format(THEME_REC *theme, MODULE_THEME_REC *rec, - FORMAT_REC *formats, + const char *module, const char *key, const char *value) { - int n; + int num; - for (n = 0; formats[n].def != NULL; n++) { - if (formats[n].tag != NULL && - g_strcasecmp(formats[n].tag, key) == 0) { - rec->formats[n] = g_strdup(value); - rec->expanded_formats[n] = - theme_format_expand(theme, value); - break; - } + num = format_find_tag(module, key); + if (num != -1) { + rec->formats[num] = g_strdup(value); + rec->expanded_formats[num] = theme_format_expand(theme, value); } } static void theme_read_formats(THEME_REC *theme, const char *module, - CONFIG_REC *config, FORMAT_REC *formats, - MODULE_THEME_REC *rec) + CONFIG_REC *config, MODULE_THEME_REC *rec) { CONFIG_NODE *node; GSList *tmp; @@ -491,7 +486,7 @@ static void theme_read_formats(THEME_REC *theme, const char *module, node = tmp->data; if (node->key != NULL && node->value != NULL) { - theme_set_format(theme, rec, formats, + theme_set_format(theme, rec, module, node->key, node->value); } } @@ -510,7 +505,7 @@ static void theme_init_module(THEME_REC *theme, const char *module, rec = theme_module_create(theme, module); if (config != NULL) - theme_read_formats(theme, module, config, formats, rec); + theme_read_formats(theme, module, config, rec); /* expand the remaining formats */ for (n = 0; n < rec->count; n++) { diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index afc960c0..3a206843 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -44,26 +44,35 @@ static GString *format; static LINE_REC *create_line(GUI_WINDOW_REC *gui, int level) { + LINE_REC *rec; + g_return_val_if_fail(gui != NULL, NULL); g_return_val_if_fail(gui->cur_text != NULL, NULL); - gui->cur_line = g_mem_chunk_alloc(gui->line_chunk); - gui->cur_line->text = gui->cur_text->buffer+gui->cur_text->pos; - gui->cur_line->level = GPOINTER_TO_INT(level); - gui->cur_line->time = time(NULL); + rec = g_mem_chunk_alloc(gui->line_chunk); + rec->text = gui->cur_text->buffer+gui->cur_text->pos; + rec->level = GPOINTER_TO_INT(level); + rec->time = time(NULL); mark_temp_eol(gui->cur_text); gui->last_color = -1; gui->last_flags = 0; - gui->lines = g_list_append(gui->lines, gui->cur_line); - if (gui->startline == NULL) { - /* first line */ - gui->startline = gui->lines; - gui->bottom_startline = gui->lines; + if (gui->temp_line != NULL) { + int pos = g_list_index(gui->lines, gui->temp_line); + gui->lines = g_list_insert(gui->lines, rec, pos+1); + gui->temp_line = rec; + } else { + gui->cur_line = rec; + gui->lines = g_list_append(gui->lines, rec); + if (gui->startline == NULL) { + /* first line */ + gui->startline = gui->lines; + gui->bottom_startline = gui->lines; + } } - return gui->cur_line; + return rec; } static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui) @@ -74,8 +83,6 @@ static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui) g_return_val_if_fail(gui != NULL, NULL); rec = g_new(TEXT_CHUNK_REC, 1); - rec->overflow[0] = 0; - rec->overflow[1] = (char) LINE_CMD_OVERFLOW; rec->pos = 0; rec->lines = 0; @@ -105,24 +112,73 @@ static void text_chunk_free(GUI_WINDOW_REC *gui, TEXT_CHUNK_REC *chunk) g_free(chunk); } -static void remove_first_line(WINDOW_REC *window) +static TEXT_CHUNK_REC *text_chunk_find(GUI_WINDOW_REC *gui, const char *data) +{ + GSList *tmp; + + for (tmp = gui->text_chunks; tmp != NULL; tmp = tmp->next) { + TEXT_CHUNK_REC *rec = tmp->data; + + if (data >= rec->buffer && + data < rec->buffer+sizeof(rec->buffer)) + return rec; + } + + return NULL; +} + +void gui_window_line_text_free(GUI_WINDOW_REC *gui, LINE_REC *line) { - GUI_WINDOW_REC *gui; TEXT_CHUNK_REC *chunk; + const unsigned char *text; - g_return_if_fail(window != NULL); + text = line->text; + for (;;) { + if (*text == '\0') { + text++; + if (*text == LINE_CMD_EOL) + break; - gui = WINDOW_GUI(window); - chunk = gui->text_chunks->data; + if (*text == LINE_CMD_CONTINUE) { + unsigned char *tmp; + memcpy(&tmp, text+1, sizeof(char *)); + + /* free the previous block */ + chunk = text_chunk_find(gui, text); + if (--chunk->lines == 0) + text_chunk_free(gui, chunk); + + text = tmp; + continue; + } + if (*text & 0x80) + text++; + } + + text++; + } + + /* free the last block */ + chunk = text_chunk_find(gui, text); if (--chunk->lines == 0) text_chunk_free(gui, chunk); +} +void gui_window_line_remove(WINDOW_REC *window, LINE_REC *line) +{ + GUI_WINDOW_REC *gui; + + g_return_if_fail(window != NULL); + + gui = WINDOW_GUI(window); + + gui_window_line_text_free(gui, line); if (gui->lastlog_last_check != NULL && - gui->lastlog_last_check->data == window) + gui->lastlog_last_check->data == line) gui->lastlog_last_check = NULL; if (gui->lastlog_last_away != NULL && - gui->lastlog_last_away->data == window) + gui->lastlog_last_away->data == line) gui->lastlog_last_away = NULL; if (gui->startline->prev == NULL) { @@ -138,8 +194,8 @@ static void remove_first_line(WINDOW_REC *window) } window->lines--; - g_mem_chunk_free(gui->line_chunk, gui->lines->data); - gui->lines = g_list_remove(gui->lines, gui->lines->data); + g_mem_chunk_free(gui->line_chunk, line); + gui->lines = g_list_remove(gui->lines, line); if (gui->startline->prev == NULL && is_window_visible(window)) gui_window_redraw(window); @@ -162,7 +218,7 @@ static void remove_old_lines(WINDOW_REC *window) /* too new line, don't remove yet */ break; } - remove_first_line(window); + gui_window_line_remove(window, line); } } } @@ -212,6 +268,7 @@ static void linebuf_add(GUI_WINDOW_REC *gui, const char *str, int len) gui->cur_text->pos += left; create_text_chunk(gui); + gui->cur_text->lines++; len -= left; str += left; } @@ -219,6 +276,12 @@ static void linebuf_add(GUI_WINDOW_REC *gui, const char *str, int len) gui->cur_text->pos += len; } +void gui_window_line_append(GUI_WINDOW_REC *gui, const char *str, int len) +{ + linebuf_add(gui, str, len); + mark_temp_eol(gui->cur_text); +} + static void line_add_colors(GUI_WINDOW_REC *gui, int fg, int bg, int flags) { unsigned char buffer[12]; @@ -282,15 +345,26 @@ static void gui_printtext(WINDOW_REC *window, void *fgcolor, void *bgcolor, /* newline can be only at the start of the line.. */ if (flags & PRINTFLAG_NEWLINE) { - linebuf_add(gui, "\0\200", 2); /* mark EOL */ + if (!gui->eol_marked) { + if (format->len > 0 || gui->temp_line != NULL) { + /* mark format continuing to next line */ + char tmp[2] = { 0, (char)LINE_CMD_FORMAT_CONT }; + linebuf_add(gui, tmp, 2); + } + linebuf_add(gui, "\0\200", 2); /* mark EOL */ + } + gui->eol_marked = FALSE; line = create_line(gui, 0); - gui_window_newline(gui, visible); + gui_window_newline(gui, visible && gui->temp_line == NULL); gui->cur_text->lines++; gui->last_subline = 0; } else { - line = gui->cur_line != NULL ? gui->cur_line : + if (gui->eol_marked) + g_warning("gui_printtext(): eol_marked"); + line = gui->temp_line != NULL ? gui->temp_line : + gui->cur_line != NULL ? gui->cur_line : create_line(gui, 0); if (line->level == 0) line->level = GPOINTER_TO_INT(level); } @@ -301,6 +375,13 @@ static void gui_printtext(WINDOW_REC *window, void *fgcolor, void *bgcolor, mark_temp_eol(gui->cur_text); gui_window_cache_remove(gui, line); + + if (gui->temp_line != NULL) { + /* updating existing line - don't even + try to print it to screen */ + return; + } + new_lines = gui_window_get_linecount(gui, line)-1 - gui->last_subline; for (n = 0; n < new_lines; n++) @@ -376,11 +457,13 @@ static void sig_printtext_finished(WINDOW_REC *window) if (format->len > 0) { /* save format of the line */ linebuf_add(gui, format->str, format->len); - mark_temp_eol(gui->cur_text); g_string_truncate(format, 0); } + linebuf_add(gui, "\0\200", 2); /* mark EOL */ + gui->eol_marked = TRUE; + if (is_window_visible(window)) { #ifdef USE_CURSES_WINDOWS screen_refresh(gui->parent->curses_win); @@ -410,9 +493,10 @@ static void sig_print_format(THEME_REC *theme, const char *module, g_string_append_c(format, (char)LINE_CMD_FORMAT); g_string_append(format, module); - g_string_append_c(format, '\0'); + g_string_append_c(format, '\0'); g_string_append_c(format, (char)LINE_CMD_FORMAT); + g_string_append(format, formats[formatnum].tag); for (n = 0; n < formats[formatnum].params; n++) { diff --git a/src/fe-text/gui-printtext.h b/src/fe-text/gui-printtext.h index aeeb5cce..97d20e12 100644 --- a/src/fe-text/gui-printtext.h +++ b/src/fe-text/gui-printtext.h @@ -1,6 +1,8 @@ #ifndef __GUI_PRINTTEXT_H #define __GUI_PRINTTEXT_H +#include "gui-windows.h" + enum { BLACK = 0, @@ -27,4 +29,7 @@ extern int mirc_colors[]; void gui_printtext_init(void); void gui_printtext_deinit(void); +void gui_window_line_append(GUI_WINDOW_REC *gui, const char *str, int len); +void gui_window_line_remove(WINDOW_REC *window, LINE_REC *line); + #endif diff --git a/src/fe-text/gui-textwidget.c b/src/fe-text/gui-textwidget.c index 67f35882..b3527eac 100644 --- a/src/fe-text/gui-textwidget.c +++ b/src/fe-text/gui-textwidget.c @@ -417,6 +417,24 @@ static void cmd_scrollback_end(const char *data) signal_emit("gui page scrolled", 1, active_win); } +/* SYNTAX: SCROLLBACK REDRAW */ +static void cmd_scrollback_redraw(void) +{ + GUI_WINDOW_REC *gui; + GList *tmp, *next; + + gui = WINDOW_GUI(active_win); + + screen_refresh_freeze(); + for (tmp = gui->lines; tmp != NULL; tmp = next) { + next = tmp->next; + gui_window_reformat_line(active_win, tmp->data); + } + + gui_window_redraw(active_win); + screen_refresh_thaw(); +} + static void sig_away_changed(IRC_SERVER_REC *server) { GSList *tmp; @@ -440,6 +458,7 @@ void gui_textwidget_init(void) command_bind("scrollback goto", NULL, (SIGNAL_FUNC) cmd_scrollback_goto); command_bind("scrollback home", NULL, (SIGNAL_FUNC) cmd_scrollback_home); command_bind("scrollback end", NULL, (SIGNAL_FUNC) cmd_scrollback_end); + command_bind("scrollback redraw", NULL, (SIGNAL_FUNC) cmd_scrollback_redraw); command_set_options("lastlog", "!- new away word regexp"); signal_add("away mode changed", (SIGNAL_FUNC) sig_away_changed); @@ -453,6 +472,7 @@ void gui_textwidget_deinit(void) command_unbind("scrollback goto", (SIGNAL_FUNC) cmd_scrollback_goto); command_unbind("scrollback home", (SIGNAL_FUNC) cmd_scrollback_home); command_unbind("scrollback end", (SIGNAL_FUNC) cmd_scrollback_end); + command_unbind("scrollback redraw", (SIGNAL_FUNC) cmd_scrollback_redraw); signal_remove("away mode changed", (SIGNAL_FUNC) sig_away_changed); } diff --git a/src/fe-text/gui-windows.c b/src/fe-text/gui-windows.c index acc2c2f3..3021485b 100644 --- a/src/fe-text/gui-windows.c +++ b/src/fe-text/gui-windows.c @@ -20,7 +20,6 @@ #include "module.h" #include "signals.h" -#include "commands.h" #include "servers.h" #include "misc.h" #include "settings.h" @@ -28,10 +27,12 @@ #include "irc.h" #include "channels.h" #include "fe-windows.h" +#include "formats.h" #include "screen.h" #include "gui-entry.h" #include "gui-windows.h" +#include "gui-printtext.h" #ifdef HAVE_REGEX_H # include <regex.h> @@ -294,8 +295,6 @@ static LINE_CACHE_REC *gui_window_line_cache(GUI_WINDOW_REC *gui, /* set color */ color = (color & ATTR_UNDERLINE) | *ptr; } else switch (*ptr) { - case LINE_CMD_OVERFLOW: - g_error("buffer overflow! (cache)"); case LINE_CMD_UNDERLINE: color ^= ATTR_UNDERLINE; break; @@ -444,8 +443,6 @@ static void single_line_draw(GUI_WINDOW_REC *gui, int ypos, text = tmp; continue; } else switch ((unsigned char) *text) { - case LINE_CMD_OVERFLOW: - g_error("buffer overflow! (draw)"); case LINE_CMD_EOL: case LINE_CMD_FORMAT: return; @@ -790,8 +787,6 @@ GList *gui_window_find_text(WINDOW_REC *window, gchar *text, GList *startline, i else if ((guchar) *ptr == LINE_CMD_EOL || (guchar) *ptr == LINE_CMD_FORMAT) break; - else if ((guchar) *ptr == LINE_CMD_OVERFLOW) - g_error("buffer overflow! (find)"); } } str[n] = '\0'; @@ -899,6 +894,175 @@ static int sig_check_linecache(void) return 1; } +static char *line_read_format(unsigned const char **text) +{ + GString *str; + char *ret; + + str = g_string_new(NULL); + for (;;) { + if (**text == '\0') { + if ((*text)[1] == LINE_CMD_EOL) { + /* leave text at \0<eof> */ + break; + } + if ((*text)[1] == LINE_CMD_FORMAT_CONT) { + /* leave text at \0<format_cont> */ + break; + } + (*text)++; + + if (**text == LINE_CMD_FORMAT) { + /* move text to start after \0<format> */ + (*text)++; + break; + } + + if (**text == LINE_CMD_CONTINUE) { + unsigned char *tmp; + + memcpy(&tmp, (*text)+1, sizeof(char *)); + *text = tmp; + continue; + } else if (**text & 0x80) + (*text)++; + } + + g_string_append_c(str, (char) **text); + (*text)++; + } + + ret = str->str; + g_string_free(str, FALSE); + return ret; +} + +static char *gui_window_line_get_format(WINDOW_REC *window, LINE_REC *line, + GString *raw) +{ + const unsigned char *text; + char *module, *format_name, *args[MAX_FORMAT_PARAMS], *ret; + TEXT_DEST_REC dest; + int formatnum, argcount; + + text = line->text; + + /* skip the beginning of the line until we find the format */ + g_free(line_read_format(&text)); + if (text[1] == LINE_CMD_FORMAT_CONT) { + g_string_append_c(raw, '\0'); + g_string_append_c(raw, (char)LINE_CMD_FORMAT_CONT); + return NULL; + } + + /* read format information */ + module = line_read_format(&text); + format_name = line_read_format(&text); + + if (raw != NULL) { + g_string_append_c(raw, '\0'); + g_string_append_c(raw, (char)LINE_CMD_FORMAT); + + g_string_append(raw, module); + + g_string_append_c(raw, '\0'); + g_string_append_c(raw, (char)LINE_CMD_FORMAT); + + g_string_append(raw, format_name); + } + + formatnum = format_find_tag(module, format_name); + if (formatnum == -1) + ret = NULL; + else { + THEME_REC *theme; + + theme = window->theme == NULL ? current_theme : + window->theme; + + argcount = 0; + while (*text != '\0' || text[1] != LINE_CMD_EOL) { + args[argcount] = line_read_format(&text); + if (raw != NULL) { + g_string_append_c(raw, '\0'); + g_string_append_c(raw, + (char)LINE_CMD_FORMAT); + + g_string_append(raw, args[argcount]); + } + argcount++; + } + + /* get the format text */ + format_create_dest(&dest, NULL, NULL, line->level, window); + ret = format_get_text_theme_charargs(current_theme, + module, &dest, + formatnum, args); + while (argcount > 0) + g_free(args[--argcount]); + } + + g_free(module); + g_free(format_name); + + return ret; +} + +void gui_window_reformat_line(WINDOW_REC *window, LINE_REC *line) +{ + GUI_WINDOW_REC *gui; + TEXT_DEST_REC dest; + GString *raw; + char *str, *tmp, *prestr, *linestart, *leveltag; + + gui = WINDOW_GUI(window); + + raw = g_string_new(NULL); + str = gui_window_line_get_format(window, line, raw); + + if (str == NULL) { + if (raw->len == 2 && + raw->str[1] == (char)LINE_CMD_FORMAT_CONT) { + /* multiline format, format explained in one the + following lines. remove this line. */ + gui_window_line_remove(window, line); + } + } else { + /* FIXME: ugly ugly .. at least timestamps should be + printed by GUI itself.. server tags are also a bit + problematic.. */ + g_string_append_c(raw, '\0'); + g_string_append_c(raw, (char)LINE_CMD_EOL); + + gui->temp_line = line; + gui->temp_line->text = gui->cur_text->buffer+gui->cur_text->pos; + gui->eol_marked = FALSE; + + format_create_dest(&dest, NULL, NULL, line->level, window); + + linestart = format_get_line_start(current_theme, &dest); + leveltag = format_get_level_tag(current_theme, &dest); + + prestr = g_strconcat(linestart == NULL ? "" : linestart, + leveltag, NULL); + g_free_not_null(linestart); + g_free_not_null(leveltag); + + tmp = format_add_linestart(str, prestr); + g_free(str); + g_free(prestr); + + format_send_to_gui(&dest, tmp); + g_free(tmp); + + gui_window_line_append(gui, raw->str, raw->len); + + gui->eol_marked = TRUE; + gui->temp_line = NULL; + } + g_string_free(raw, TRUE); +} + static void read_settings(void) { default_indent_pos = settings_get_int("indent"); diff --git a/src/fe-text/gui-windows.h b/src/fe-text/gui-windows.h index 1d037722..ec2d8760 100644 --- a/src/fe-text/gui-windows.h +++ b/src/fe-text/gui-windows.h @@ -15,16 +15,16 @@ enum { LINE_CMD_EOL=0x80, /* line ends here. */ LINE_CMD_CONTINUE, /* line continues in next block */ - LINE_CMD_OVERFLOW, /* buffer overflow! */ LINE_CMD_COLOR0, /* change to black, would be same as \0\0 but it breaks things.. */ LINE_CMD_COLOR8, /* change to dark grey, normally 8 = bold black */ LINE_CMD_UNDERLINE, /* enable/disable underlining */ LINE_CMD_INDENT, /* if line is split, indent it at this position */ LINE_CMD_BLINK, /* blinking background */ - LINE_CMD_FORMAT /* end of line, but next will come the format that was used to create the + LINE_CMD_FORMAT, /* end of line, but next will come the format that was used to create the text in format <module><format_name><arg><arg2...> - fields are separated with \0<format> and last argument ends with \0<eol>. \0<continue> is allowed anywhere */ + LINE_CMD_FORMAT_CONT /* multiline format, continues to next line */ }; typedef struct { @@ -56,7 +56,6 @@ typedef struct { typedef struct { char buffer[LINE_TEXT_CHUNK_SIZE]; - char overflow[2]; int pos; int lines; } TEXT_CHUNK_REC; @@ -69,7 +68,7 @@ typedef struct { GList *lines; GHashTable *line_cache; - LINE_REC *cur_line; + LINE_REC *cur_line, *temp_line; TEXT_CHUNK_REC *cur_text; int xpos, ypos; /* cursor position in screen */ @@ -80,7 +79,8 @@ typedef struct { int bottom_subline; int empty_linecount; /* how many empty lines are in screen. a screenful when started or used /CLEAR */ - int bottom; /* window is at the bottom of the text buffer */ + int bottom:1; /* window is at the bottom of the text buffer */ + int eol_marked:1; /* last line marked for eol */ /* For /LAST -new and -away */ GList *lastlog_last_check; @@ -106,6 +106,7 @@ int gui_window_line_draw(GUI_WINDOW_REC *gui, LINE_REC *line, int ypos, int skip void gui_window_clear(WINDOW_REC *window); void gui_window_redraw(WINDOW_REC *window); +void gui_window_reformat_line(WINDOW_REC *window, LINE_REC *line); void gui_window_resize(WINDOW_REC *window, int ychange, int xchange); void gui_window_reparent(WINDOW_REC *window, MAIN_WINDOW_REC *parent); |