summaryrefslogtreecommitdiff
path: root/src/fe-text
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2000-11-21 03:00:05 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2000-11-21 03:00:05 +0000
commite923b1651afc995cf75caf7c63cdf8b246272801 (patch)
treee640425514a26d764587d574bfe2335dfdde4538 /src/fe-text
parente3084d3ffae3e57ddf89507e69f61b83c5ceaf90 (diff)
downloadirssi-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/fe-text')
-rw-r--r--src/fe-text/gui-printtext.c138
-rw-r--r--src/fe-text/gui-printtext.h5
-rw-r--r--src/fe-text/gui-textwidget.c20
-rw-r--r--src/fe-text/gui-windows.c178
-rw-r--r--src/fe-text/gui-windows.h11
5 files changed, 313 insertions, 39 deletions
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);