summaryrefslogtreecommitdiff
path: root/src/fe-text/gui-printtext.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/fe-text/gui-printtext.c')
-rw-r--r--src/fe-text/gui-printtext.c478
1 files changed, 64 insertions, 414 deletions
diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c
index 2e839dcd..5faae0fa 100644
--- a/src/fe-text/gui-printtext.c
+++ b/src/fe-text/gui-printtext.c
@@ -20,7 +20,6 @@
#include "module.h"
#include "signals.h"
-#include "commands.h"
#include "settings.h"
#include "formats.h"
@@ -29,220 +28,15 @@
#include "screen.h"
#include "gui-windows.h"
-#define TEXT_CHUNK_USABLE_SIZE (LINE_TEXT_CHUNK_SIZE-2-(int)sizeof(char*))
-
int mirc_colors[] = { 15, 0, 1, 2, 12, 6, 5, 4, 14, 10, 3, 11, 9, 13, 8, 7 };
-static int scrollback_lines, scrollback_hours;
+static int scrollback_lines, scrollback_hours, scrollback_burst_remove;
static int scrollback_save_formats;
static GString *format;
+static int last_color, last_flags;
static int next_xpos, next_ypos;
-#define mark_temp_eol(text) \
- memcpy((text)->buffer + (text)->pos, "\0\200", 2);
-
-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);
-
- 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->cur_text->lines++;
-
- gui->last_color = -1;
- gui->last_flags = 0;
-
- 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 rec;
-}
-
-static TEXT_CHUNK_REC *create_text_chunk(GUI_WINDOW_REC *gui)
-{
- TEXT_CHUNK_REC *rec;
- char *buffer, *ptr, **pptr;
-
- g_return_val_if_fail(gui != NULL, NULL);
-
- rec = g_new(TEXT_CHUNK_REC, 1);
- rec->pos = 0;
- rec->lines = 0;
-
- if (gui->cur_line != NULL && gui->cur_line->text != NULL) {
- /* create a link to new block from the old block */
- buffer = gui->cur_text->buffer + gui->cur_text->pos;
- *buffer++ = 0; *buffer++ = (char) LINE_CMD_CONTINUE;
-
- ptr = rec->buffer; pptr = &ptr;
- memcpy(buffer, pptr, sizeof(char *));
- } else {
- /* just to be safe */
- mark_temp_eol(rec);
- }
-
- gui->cur_text = rec;
- gui->text_chunks = g_slist_append(gui->text_chunks, rec);
- return rec;
-}
-
-static void text_chunk_free(GUI_WINDOW_REC *gui, TEXT_CHUNK_REC *chunk)
-{
- g_return_if_fail(gui != NULL);
- g_return_if_fail(chunk != NULL);
-
- gui->text_chunks = g_slist_remove(gui->text_chunks, chunk);
- g_free(chunk);
-}
-
-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)
-{
- TEXT_CHUNK_REC *chunk;
- const char *text;
-
- text = line->text;
- for (;;) {
- if (*text == '\0') {
- text++;
- if ((unsigned char) *text == LINE_CMD_EOL)
- break;
-
- if ((unsigned char) *text == LINE_CMD_CONTINUE) {
- 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 ((unsigned char) *text & 0x80)
- text++;
- continue;
- }
-
- text++;
- }
-
- /* free the last block */
- chunk = text_chunk_find(gui, text);
- if (--chunk->lines == 0) {
- if (gui->cur_text == chunk)
- chunk->pos = 0;
- else
- text_chunk_free(gui, chunk);
- }
-}
-
-void gui_window_line_remove(WINDOW_REC *window, LINE_REC *line, int redraw)
-{
- GUI_WINDOW_REC *gui;
- GList *last;
- int screenchange;
-
- g_return_if_fail(window != NULL);
- g_return_if_fail(line != NULL);
-
- gui = WINDOW_GUI(window);
-
- if (gui->lines->next == NULL) {
- /* last line in window */
- gui_window_clear(window);
- return;
- }
-
- screenchange = g_list_find(gui->startline, line) != NULL;
- if (screenchange) gui->ypos -= gui_window_get_linecount(gui, line);
-
- gui_window_cache_remove(gui, line);
- gui_window_line_text_free(gui, line);
- if (gui->lastlog_last_check != NULL &&
- gui->lastlog_last_check->data == line)
- gui->lastlog_last_check = NULL;
- if (gui->lastlog_last_away != NULL &&
- gui->lastlog_last_away->data == line)
- gui->lastlog_last_away = NULL;
-
- last = g_list_last(gui->bottom_startline);
- if (last->data == line) {
- /* removing last line */
- gui->last_subline =
- gui_window_get_linecount(gui, last->prev->data)-1;
- }
-
- if (gui->bottom_startline->data == line) {
- /* bottom line removed */
- if (gui->bottom_startline->next != NULL) {
- gui->bottom_startline = gui->bottom_startline->next;
- gui->bottom_subline = 0;
- } else {
- gui->bottom_startline = gui->bottom_startline->prev;
- gui->bottom_subline = gui->last_subline+1;
- }
- }
-
- if (gui->startline->data == line) {
- /* first line in screen removed */
- if (gui->startline->next != NULL) {
- gui->startline = gui->startline->next;
- gui->subline = 0;
- } else {
- gui->startline = gui->startline->prev;
- gui->subline = gui->last_subline+1;
- gui->ypos = -1;
- gui->empty_linecount = gui->parent->lines;
- gui->bottom = TRUE;
- }
- }
-
- window->lines--;
- g_mem_chunk_free(gui->line_chunk, line);
- gui->lines = g_list_remove(gui->lines, line);
-
- if (window->lines == 0)
- gui_window_clear(window);
-
- if (redraw && screenchange && is_window_visible(window))
- gui_window_redraw(window);
-}
-
void gui_printtext(int xpos, int ypos, const char *str)
{
next_xpos = xpos;
@@ -253,24 +47,22 @@ void gui_printtext(int xpos, int ypos, const char *str)
next_xpos = next_ypos = -1;
}
-static void remove_old_lines(WINDOW_REC *window)
+static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
{
- GUI_WINDOW_REC *gui;
LINE_REC *line;
time_t old_time;
- gui = WINDOW_GUI(window);
-
old_time = time(NULL)-(scrollback_hours*3600)+1;
- if (scrollback_lines > 0) {
+ if (view->buffer->lines_count >=
+ scrollback_lines+scrollback_burst_remove) {
/* remove lines by line count */
- while (window->lines > scrollback_lines) {
- line = gui->lines->data;
- if (line->time >= old_time) {
+ while (view->buffer->lines_count > scrollback_lines) {
+ line = view->buffer->lines->data;
+ if (line->info.time >= old_time) {
/* too new line, don't remove yet */
break;
}
- gui_window_line_remove(window, line, TRUE);
+ textbuffer_view_remove_line(view, line);
}
}
}
@@ -308,37 +100,10 @@ static void get_colors(int flags, int *fg, int *bg)
if (flags & PRINTFLAG_BLINK) *bg |= 0x08;
}
-static void linebuf_add(GUI_WINDOW_REC *gui, const char *str, int len)
-{
- int left;
-
- if (len == 0) return;
-
- while (gui->cur_text->pos + len >= TEXT_CHUNK_USABLE_SIZE) {
- left = TEXT_CHUNK_USABLE_SIZE - gui->cur_text->pos;
- if (str[left-1] == 0) left--; /* don't split the commands */
-
- memcpy(gui->cur_text->buffer + gui->cur_text->pos, str, left);
- gui->cur_text->pos += left;
-
- create_text_chunk(gui);
- gui->cur_text->lines++;
- len -= left; str += left;
- }
-
- memcpy(gui->cur_text->buffer + gui->cur_text->pos, str, 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)
+static void line_add_colors(TEXT_BUFFER_REC *buffer, LINE_REC **line,
+ int fg, int bg, int flags)
{
- unsigned char buffer[12];
+ unsigned char data[12];
int color, pos;
/* color should never have last bit on or it would be treated as a
@@ -346,49 +111,60 @@ static void line_add_colors(GUI_WINDOW_REC *gui, int fg, int bg, int flags)
color = (fg & 0x0f) | ((bg & 0x07) << 4);
pos = 0;
- if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != gui->last_color) ||
- ((fg & ATTR_COLOR8) && (fg & 0xf0) != (gui->last_color & 0xf0))) {
- buffer[pos++] = 0;
- buffer[pos++] = color == 0 ? LINE_CMD_COLOR0 : color;
+ if (((fg & ATTR_COLOR8) == 0 && (fg|(bg << 4)) != last_color) ||
+ ((fg & ATTR_COLOR8) && (fg & 0xf0) != (last_color & 0xf0))) {
+ data[pos++] = 0;
+ data[pos++] = color == 0 ? LINE_CMD_COLOR0 : color;
}
- if ((flags & PRINTFLAG_UNDERLINE) != (gui->last_flags & PRINTFLAG_UNDERLINE)) {
- buffer[pos++] = 0;
- buffer[pos++] = LINE_CMD_UNDERLINE;
+ if ((flags & PRINTFLAG_UNDERLINE) != (last_flags & PRINTFLAG_UNDERLINE)) {
+ data[pos++] = 0;
+ data[pos++] = LINE_CMD_UNDERLINE;
}
if (fg & ATTR_COLOR8) {
- buffer[pos++] = 0;
- buffer[pos++] = LINE_CMD_COLOR8;
+ data[pos++] = 0;
+ data[pos++] = LINE_CMD_COLOR8;
}
if (bg & 0x08) {
- buffer[pos++] = 0;
- buffer[pos++] = LINE_CMD_BLINK;
+ data[pos++] = 0;
+ data[pos++] = LINE_CMD_BLINK;
}
if (flags & PRINTFLAG_INDENT) {
- buffer[pos++] = 0;
- buffer[pos++] = LINE_CMD_INDENT;
+ data[pos++] = 0;
+ data[pos++] = LINE_CMD_INDENT;
}
- linebuf_add(gui, (char *) buffer, pos);
+ *line = textbuffer_insert(buffer, *line, data, pos, NULL);
- gui->last_flags = flags;
- gui->last_color = fg | (bg << 4);
+ last_flags = flags;
+ last_color = fg | (bg << 4);
+}
+
+static void view_add_eol(TEXT_BUFFER_VIEW_REC *view, LINE_REC **line)
+{
+ static const unsigned char eol[] = { 0, LINE_CMD_EOL };
+
+ *line = textbuffer_insert(view->buffer, *line, eol, 2, NULL);
+ textbuffer_view_insert_line(view, *line);
}
static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
void *bgcolor, void *pflags,
char *str, void *level)
{
- GUI_WINDOW_REC *gui;
- LINE_REC *line;
- int fg, bg, flags, new_lines, n, visible, ypos, subline;
+ TEXT_BUFFER_VIEW_REC *view;
+ LINE_REC *insert_after;
+ LINE_INFO_REC lineinfo;
+ int fg, bg, flags;
flags = GPOINTER_TO_INT(pflags);
fg = GPOINTER_TO_INT(fgcolor);
bg = GPOINTER_TO_INT(bgcolor);
get_colors(flags, &fg, &bg);
- if (window == NULL && next_xpos != -1) {
+ if (window == NULL) {
+ g_return_if_fail(next_xpos != -1);
+
wmove(stdscr, next_ypos, next_xpos);
set_color(stdscr, fg | (bg << 4));
addstr(str);
@@ -396,159 +172,34 @@ static void sig_gui_print_text(WINDOW_REC *window, void *fgcolor,
return;
}
- g_return_if_fail(window != NULL);
-
- gui = WINDOW_GUI(window);
- visible = is_window_visible(window) && gui->bottom;
-
- if (gui->cur_text == NULL)
- create_text_chunk(gui);
-
- /* newline can be only at the start of the line.. */
- if (flags & PRINTFLAG_NEWLINE) {
- remove_old_lines(window);
- 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);
- if (gui->temp_line == NULL ||
- g_list_find(gui->startline, gui->temp_line) != NULL)
- gui_window_newline(gui, visible);
-
- gui->last_subline = 0;
- } else {
- 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);
- }
+ lineinfo.level = GPOINTER_TO_INT(level);
+ lineinfo.time = time(NULL);
- line_add_colors(gui, fg, bg, flags);
- linebuf_add(gui, str, strlen(str));
- mark_temp_eol(gui->cur_text);
+ view = WINDOW_GUI(window)->view;
+ insert_after = WINDOW_GUI(window)->use_insert_after ?
+ WINDOW_GUI(window)->insert_after : view->buffer->cur_line;
- 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++)
- gui_window_newline(gui, visible);
-
- if (visible) {
- /* draw the line to screen. */
- ypos = gui->ypos-new_lines;
- if (new_lines > 0) {
-#ifdef USE_CURSES_WINDOWS
- set_color(gui->parent->curses_win, 0);
- wmove(gui->parent->curses_win, ypos, 0);
- wclrtoeol(gui->parent->curses_win);
-#else
- set_color(stdscr, 0);
- move(ypos + gui->parent->first_line, 0);
- wclrtoeol(stdscr);
-#endif
- }
-
- if (ypos >= 0)
- subline = gui->last_subline;
- else {
- /* *LONG* line - longer than screen height */
- subline = -ypos+gui->last_subline;
- ypos = 0;
- }
- gui_window_line_draw(gui, line, ypos, subline, -1);
- }
-
- gui->last_subline += new_lines;
-}
-
-static void window_clear_screen(GUI_WINDOW_REC *gui)
-{
-#ifdef USE_CURSES_WINDOWS
- wclear(gui->parent->curses_win);
- screen_refresh(gui->parent->curses_win);
-#else
- int n;
-
- for (n = gui->parent->first_line; n < gui->parent->last_line; n++) {
- move(n, 0);
- clrtoeol();
- }
- screen_refresh(NULL);
-#endif
-}
-
-static void window_clear(WINDOW_REC *window)
-{
- GUI_WINDOW_REC *gui = WINDOW_GUI(window);
-
- if (is_window_visible(window))
- window_clear_screen(gui);
-
- gui->ypos = -1;
- gui->bottom_startline = gui->startline = g_list_last(gui->lines);
- gui->bottom_subline = gui->subline = gui->last_subline+1;
- gui->empty_linecount = gui->parent->lines;
- gui->bottom = TRUE;
-}
-
-/* SYNTAX: CLEAR */
-static void cmd_clear(const char *data)
-{
- GHashTable *optlist;
- void *free_arg;
-
- g_return_if_fail(data != NULL);
-
- if (!cmd_get_params(data, &free_arg, PARAM_FLAG_OPTIONS,
- "clear", &optlist)) return;
-
- if (g_hash_table_lookup(optlist, "all") != NULL)
- g_slist_foreach(windows, (GFunc) window_clear, NULL);
- else
- window_clear(active_win);
-
- cmd_params_free(free_arg);
+ if (flags & PRINTFLAG_NEWLINE)
+ view_add_eol(view, &insert_after);
+ line_add_colors(view->buffer, &insert_after, fg, bg, flags);
+ textbuffer_insert(view->buffer, insert_after,
+ str, strlen(str), &lineinfo);
}
static void sig_printtext_finished(WINDOW_REC *window)
{
- GUI_WINDOW_REC *gui;
+ TEXT_BUFFER_VIEW_REC *view;
+ LINE_REC *insert_after;
- gui = WINDOW_GUI(window);
- if (gui->cur_line == NULL)
- return;
+ last_color = 0;
+ last_flags = 0;
- if (format->len > 0) {
- /* save format of the line */
- linebuf_add(gui, format->str, format->len);
+ view = WINDOW_GUI(window)->view;
+ insert_after = WINDOW_GUI(window)->use_insert_after ?
+ WINDOW_GUI(window)->insert_after : view->buffer->cur_line;
- 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);
-#else
- screen_refresh(NULL);
-#endif
- }
+ view_add_eol(view, &insert_after);
+ remove_old_lines(view);
}
static void sig_print_format(THEME_REC *theme, const char *module,
@@ -589,6 +240,7 @@ static void read_settings(void)
{
scrollback_lines = settings_get_int("scrollback_lines");
scrollback_hours = settings_get_int("scrollback_hours");
+ scrollback_burst_remove = settings_get_int("scrollback_burst_remove");
scrollback_save_formats = settings_get_bool("scrollback_save_formats");
}
@@ -599,6 +251,7 @@ void gui_printtext_init(void)
settings_add_int("history", "scrollback_lines", 500);
settings_add_int("history", "scrollback_hours", 24);
+ settings_add_int("history", "scrollback_burst_remove", 10);
settings_add_bool("history", "scrollback_save_formats", FALSE);
signal_add("gui print text", (SIGNAL_FUNC) sig_gui_print_text);
@@ -606,8 +259,6 @@ void gui_printtext_init(void)
signal_add("print format", (SIGNAL_FUNC) sig_print_format);
signal_add("setup changed", (SIGNAL_FUNC) read_settings);
signal_add("beep", (SIGNAL_FUNC) beep);
- command_bind("clear", NULL, (SIGNAL_FUNC) cmd_clear);
- command_set_options("clear", "all");
read_settings();
}
@@ -621,5 +272,4 @@ void gui_printtext_deinit(void)
signal_remove("print format", (SIGNAL_FUNC) sig_print_format);
signal_remove("setup changed", (SIGNAL_FUNC) read_settings);
signal_remove("beep", (SIGNAL_FUNC) beep);
- command_unbind("clear", (SIGNAL_FUNC) cmd_clear);
}