Replaced GList by adding prev/next pointers to LINE_REC. This should make

some things faster and take a bit less memory. Also fixed an evil memory
leak.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1611 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-07-12 21:44:01 +00:00 committed by cras
commit 9eed52fa40
7 changed files with 135 additions and 117 deletions

View file

@ -57,7 +57,7 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view)
scrollback_lines+scrollback_burst_remove) { scrollback_lines+scrollback_burst_remove) {
/* remove lines by line count */ /* remove lines by line count */
while (view->buffer->lines_count > scrollback_lines) { while (view->buffer->lines_count > scrollback_lines) {
line = view->buffer->lines->data; line = view->buffer->first_line;
if (line->info.time >= old_time || if (line->info.time >= old_time ||
scrollback_lines == 0) { scrollback_lines == 0) {
/* too new line, don't remove yet - also /* too new line, don't remove yet - also

View file

@ -35,17 +35,19 @@
static void window_lastlog_clear(WINDOW_REC *window) static void window_lastlog_clear(WINDOW_REC *window)
{ {
TEXT_BUFFER_VIEW_REC *view; TEXT_BUFFER_VIEW_REC *view;
GList *tmp, *next; LINE_REC *line, *next;
screen_refresh_freeze(); screen_refresh_freeze();
view = WINDOW_GUI(window)->view; view = WINDOW_GUI(window)->view;
for (tmp = textbuffer_view_get_lines(view); tmp != NULL; tmp = next) { line = textbuffer_view_get_lines(view);
LINE_REC *line = tmp->data;
next = tmp->next; while (line != NULL) {
if (line->info.level & MSGLEVEL_LASTLOG) next = line->next;
if (line->info.level & MSGLEVEL_LASTLOG)
textbuffer_view_remove_line(view, line); textbuffer_view_remove_line(view, line);
line = next;
} }
textbuffer_view_redraw(view); textbuffer_view_redraw(view);
screen_refresh_thaw(); screen_refresh_thaw();
@ -131,10 +133,8 @@ static void show_lastlog(const char *searchtext, GHashTable *optlist,
else else
startline = NULL; startline = NULL;
if (startline == NULL) { if (startline == NULL)
list = textbuffer_view_get_lines(WINDOW_GUI(window)->view); startline = textbuffer_view_get_lines(WINDOW_GUI(window)->view);
startline = list == NULL ? NULL : list->data;
}
list = textbuffer_find_text(WINDOW_GUI(window)->view->buffer, startline, list = textbuffer_find_text(WINDOW_GUI(window)->view->buffer, startline,
level, MSGLEVEL_LASTLOG, level, MSGLEVEL_LASTLOG,

View file

@ -74,13 +74,13 @@ static void scrollback_goto_line(int linenum)
if (view->buffer->lines_count == 0) if (view->buffer->lines_count == 0)
return; return;
textbuffer_view_scroll_line(view, view->buffer->lines->data); textbuffer_view_scroll_line(view, view->buffer->first_line);
gui_window_scroll(active_win, linenum); gui_window_scroll(active_win, linenum);
} }
static void scrollback_goto_time(const char *datearg, const char *timearg) static void scrollback_goto_time(const char *datearg, const char *timearg)
{ {
GList *tmp; LINE_REC *line;
struct tm tm; struct tm tm;
time_t now, stamp; time_t now, stamp;
int day, month; int day, month;
@ -145,12 +145,10 @@ static void scrollback_goto_time(const char *datearg, const char *timearg)
} }
/* scroll to first line after timestamp */ /* scroll to first line after timestamp */
tmp = textbuffer_view_get_lines(WINDOW_GUI(active_win)->view); line = textbuffer_view_get_lines(WINDOW_GUI(active_win)->view);
for (; tmp != NULL; tmp = tmp->next) { for (; line != NULL; line = line->next) {
LINE_REC *rec = tmp->data; if (line->info.time >= stamp) {
gui_window_scroll_line(active_win, line);
if (rec->info.time >= stamp) {
gui_window_scroll_line(active_win, rec);
break; break;
} }
} }
@ -188,7 +186,7 @@ static void cmd_scrollback_home(const char *data)
buffer = WINDOW_GUI(active_win)->view->buffer; buffer = WINDOW_GUI(active_win)->view->buffer;
if (buffer->lines_count > 0) if (buffer->lines_count > 0)
gui_window_scroll_line(active_win, buffer->lines->data); gui_window_scroll_line(active_win, buffer->first_line);
} }
/* SYNTAX: SCROLLBACK END */ /* SYNTAX: SCROLLBACK END */
@ -200,7 +198,7 @@ static void cmd_scrollback_end(const char *data)
if (view->bottom_startline == NULL) if (view->bottom_startline == NULL)
return; return;
textbuffer_view_scroll_line(view, view->bottom_startline->data); textbuffer_view_scroll_line(view, view->bottom_startline);
gui_window_scroll(active_win, view->bottom_subline); gui_window_scroll(active_win, view->bottom_subline);
} }

View file

@ -321,7 +321,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
original if possible */ original if possible */
static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view) static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
{ {
GList *tmp; LINE_REC *line;
int linecount, total; int linecount, total;
if (view->empty_linecount == 0) { if (view->empty_linecount == 0) {
@ -331,12 +331,10 @@ static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
} }
total = 0; total = 0;
tmp = g_list_last(view->buffer->lines); line = textbuffer_line_last(view->buffer);
for (; tmp != NULL; tmp = tmp->prev) { for (; line != NULL; line = line->prev) {
LINE_REC *line = tmp->data;
linecount = view_get_linecount(view, line); linecount = view_get_linecount(view, line);
if (tmp == view->bottom_startline) { if (line == view->bottom_startline) {
/* keep the old one, make sure that subline is ok */ /* keep the old one, make sure that subline is ok */
if (view->bottom_subline > linecount) if (view->bottom_subline > linecount)
view->bottom_subline = linecount; view->bottom_subline = linecount;
@ -347,7 +345,7 @@ static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
total += linecount; total += linecount;
if (total >= view->height) { if (total >= view->height) {
view->bottom_startline = tmp; view->bottom_startline = line;
view->bottom_subline = total - view->height; view->bottom_subline = total - view->height;
view->empty_linecount = 0; view->empty_linecount = 0;
return; return;
@ -355,20 +353,20 @@ static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
} }
/* not enough lines so we must be at the beginning of the buffer */ /* not enough lines so we must be at the beginning of the buffer */
view->bottom_startline = view->buffer->lines; view->bottom_startline = view->buffer->first_line;
view->bottom_subline = 0; view->bottom_subline = 0;
view->empty_linecount = view->height - total; view->empty_linecount = view->height - total;
} }
static void textbuffer_view_init_ypos(TEXT_BUFFER_VIEW_REC *view) static void textbuffer_view_init_ypos(TEXT_BUFFER_VIEW_REC *view)
{ {
GList *tmp; LINE_REC *line;
g_return_if_fail(view != NULL); g_return_if_fail(view != NULL);
view->ypos = -view->subline-1; view->ypos = -view->subline-1;
for (tmp = view->startline; tmp != NULL; tmp = tmp->next) for (line = view->startline; line != NULL; line = line->next)
view->ypos += view_get_linecount(view, tmp->data); view->ypos += view_get_linecount(view, line);
} }
/* Create new view. */ /* Create new view. */
@ -445,28 +443,26 @@ void textbuffer_view_set_default_indent(TEXT_BUFFER_VIEW_REC *view,
view->longword_noindent = longword_noindent; view->longword_noindent = longword_noindent;
} }
static int view_get_linecount_all(TEXT_BUFFER_VIEW_REC *view, GList *lines) static int view_get_linecount_all(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
{ {
int linecount; int linecount;
linecount = 0; linecount = 0;
while (lines != NULL) { while (line != NULL) {
linecount += view_get_linecount(view, lines->data); linecount += view_get_linecount(view, line);
lines = lines->next; line = line->next;
} }
return linecount; return linecount;
} }
static void view_draw(TEXT_BUFFER_VIEW_REC *view, GList *line, static void view_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
int subline, int ypos, int lines) int subline, int ypos, int lines)
{ {
int linecount; int linecount;
while (line != NULL && lines > 0) { while (line != NULL && lines > 0) {
LINE_REC *rec = line->data; linecount = view_line_draw(view, line, subline, ypos, lines);
linecount = view_line_draw(view, rec, subline, ypos, lines);
ypos += linecount; lines -= linecount; ypos += linecount; lines -= linecount;
subline = 0; subline = 0;
@ -486,13 +482,13 @@ static void view_draw(TEXT_BUFFER_VIEW_REC *view, GList *line,
static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines) static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines)
{ {
GList *line; LINE_REC *line;
int ypos, maxline, subline, linecount; int ypos, maxline, subline, linecount;
maxline = view->height-lines; maxline = view->height-lines;
line = view->startline; ypos = -view->subline; subline = 0; line = view->startline; ypos = -view->subline; subline = 0;
while (line != NULL && ypos < maxline) { while (line != NULL && ypos < maxline) {
linecount = view_get_linecount(view, line->data); linecount = view_get_linecount(view, line);
ypos += linecount; ypos += linecount;
if (ypos > maxline) { if (ypos > maxline) {
subline = maxline-(ypos-linecount); subline = maxline-(ypos-linecount);
@ -505,8 +501,8 @@ static void view_draw_bottom(TEXT_BUFFER_VIEW_REC *view, int lines)
} }
/* Returns number of lines actually scrolled */ /* Returns number of lines actually scrolled */
static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline, static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
int scrollcount, int draw_nonclean) int *subline, int scrollcount, int draw_nonclean)
{ {
int linecount, realcount, scroll_visible; int linecount, realcount, scroll_visible;
@ -520,7 +516,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline,
scrollcount += *subline; scrollcount += *subline;
*subline = 0; *subline = 0;
while (scrollcount > 0) { while (scrollcount > 0) {
linecount = view_get_linecount(view, (*lines)->data); linecount = view_get_linecount(view, *lines);
if ((scroll_visible && *lines == view->bottom_startline) && if ((scroll_visible && *lines == view->bottom_startline) &&
(scrollcount >= view->bottom_subline)) { (scrollcount >= view->bottom_subline)) {
@ -545,7 +541,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline,
/* scroll up */ /* scroll up */
while (scrollcount < 0 && (*lines)->prev != NULL) { while (scrollcount < 0 && (*lines)->prev != NULL) {
*lines = (*lines)->prev; *lines = (*lines)->prev;
linecount = view_get_linecount(view, (*lines)->data); linecount = view_get_linecount(view, *lines);
realcount -= linecount; realcount -= linecount;
scrollcount += linecount; scrollcount += linecount;
@ -595,7 +591,7 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
view->width = width; view->width = width;
view->height = height; view->height = height;
if (view->buffer->lines == NULL) { if (view->buffer->first_line == NULL) {
view->empty_linecount = height; view->empty_linecount = height;
return; return;
} }
@ -603,8 +599,8 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
textbuffer_view_init_bottom(view); textbuffer_view_init_bottom(view);
/* check that we didn't scroll lower than bottom startline.. */ /* check that we didn't scroll lower than bottom startline.. */
if (g_list_find(view->bottom_startline->next, if (textbuffer_line_exists_after(view->bottom_startline->next,
view->startline->data) != NULL) { view->startline)) {
view->startline = view->bottom_startline; view->startline = view->bottom_startline;
view->subline = view->bottom_subline; view->subline = view->bottom_subline;
} else if (view->startline == view->bottom_startline && } else if (view->startline == view->bottom_startline &&
@ -612,7 +608,7 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
view->subline = view->bottom_subline; view->subline = view->bottom_subline;
} else { } else {
/* make sure the subline is still in allowed range */ /* make sure the subline is still in allowed range */
linecount = view_get_linecount(view, view->startline->data); linecount = view_get_linecount(view, view->startline);
if (view->subline > linecount) if (view->subline > linecount)
view->subline = linecount; view->subline = linecount;
} }
@ -649,7 +645,7 @@ void textbuffer_view_clear(TEXT_BUFFER_VIEW_REC *view)
view->ypos = -1; view->ypos = -1;
view->bottom_startline = view->startline = view->bottom_startline = view->startline =
g_list_last(view->buffer->lines); textbuffer_line_last(view->buffer);
view->bottom_subline = view->subline = view->bottom_subline = view->subline =
view->buffer->cur_line == NULL ? 0 : view->buffer->cur_line == NULL ? 0 :
view_get_linecount(view, view->buffer->cur_line); view_get_linecount(view, view->buffer->cur_line);
@ -678,23 +674,14 @@ void textbuffer_view_scroll(TEXT_BUFFER_VIEW_REC *view, int lines)
/* Scroll to specified line */ /* Scroll to specified line */
void textbuffer_view_scroll_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line) void textbuffer_view_scroll_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
{ {
GList *tmp;
g_return_if_fail(view != NULL); g_return_if_fail(view != NULL);
if (g_list_find(view->bottom_startline->next, line) != NULL) { if (textbuffer_line_exists_after(view->bottom_startline->next, line)) {
view->startline = view->bottom_startline; view->startline = view->bottom_startline;
view->subline = view->bottom_subline; view->subline = view->bottom_subline;
} else { } else {
for (tmp = view->buffer->lines; tmp != NULL; tmp = tmp->next) { view->startline = line;
LINE_REC *rec = tmp->data; view->subline = 0;
if (rec == line) {
view->startline = tmp;
view->subline = 0;
break;
}
}
} }
textbuffer_view_init_ypos(view); textbuffer_view_init_ypos(view);
@ -752,11 +739,11 @@ static void view_insert_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
if (view->bottom_startline == NULL) { if (view->bottom_startline == NULL) {
view->startline = view->bottom_startline = view->startline = view->bottom_startline =
view->buffer->lines; view->buffer->first_line;
} }
if (view->buffer->cur_line != line && if (view->buffer->cur_line != line &&
g_list_find(view->bottom_startline, line) == NULL) !textbuffer_line_exists_after(view->bottom_startline, line))
return; return;
linecount = view->cache->last_linecount; linecount = view->cache->last_linecount;
@ -850,11 +837,8 @@ static void view_bookmarks_check(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
(GHFunc) bookmark_check_remove, &rec); (GHFunc) bookmark_check_remove, &rec);
if (rec.remove_list != NULL) { if (rec.remove_list != NULL) {
GList *pos = g_list_find(view->buffer->lines, line); new_line = line->prev == NULL ? NULL :
(line->next == NULL ? line->prev : line->next);
new_line = pos == NULL || pos->prev == NULL ? NULL :
(pos->next == NULL ? pos->prev->data :
pos->next->data);
for (tmp = rec.remove_list; tmp != NULL; tmp = tmp->next) { for (tmp = rec.remove_list; tmp != NULL; tmp = tmp->next) {
g_hash_table_remove(view->bookmarks, tmp->data); g_hash_table_remove(view->bookmarks, tmp->data);
if (new_line != NULL) { if (new_line != NULL) {
@ -869,20 +853,18 @@ static void view_bookmarks_check(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
/* Return number of real lines `lines' list takes - /* Return number of real lines `lines' list takes -
stops counting when the height reaches the view height */ stops counting when the height reaches the view height */
static int view_get_lines_height(TEXT_BUFFER_VIEW_REC *view, static int view_get_lines_height(TEXT_BUFFER_VIEW_REC *view,
GList *lines, int subline, LINE_REC *line, int subline,
LINE_REC *skip_line) LINE_REC *skip_line)
{ {
int height, linecount; int height, linecount;
height = -subline; height = -subline;
while (lines != NULL && height < view->height) { while (line != NULL && height < view->height) {
LINE_REC *line = lines->data;
if (line != skip_line) { if (line != skip_line) {
linecount = view_get_linecount(view, line); linecount = view_get_linecount(view, line);
height += linecount; height += linecount;
} }
lines = lines->next; line = line->next;
} }
return height < view->height ? height : view->height; return height < view->height ? height : view->height;
@ -899,22 +881,22 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
/* the last line is being removed */ /* the last line is being removed */
LINE_REC *prevline; LINE_REC *prevline;
prevline = view->buffer->lines->data == line ? NULL : prevline = view->buffer->first_line == line ? NULL :
g_list_last(view->bottom_startline)->data; textbuffer_line_last(view->buffer);
view->cache->last_linecount = prevline == NULL ? 0 : view->cache->last_linecount = prevline == NULL ? 0 :
view_get_linecount(view, prevline); view_get_linecount(view, prevline);
} }
if (line == view->buffer->lines->data) { if (line == view->buffer->first_line) {
/* first line in the buffer - this is the most commonly /* first line in the buffer - this is the most commonly
removed line.. */ removed line.. */
if (view->bottom_startline->data == line) { if (view->bottom_startline == line) {
/* very small scrollback.. */ /* very small scrollback.. */
view->bottom_startline = view->bottom_startline->next; view->bottom_startline = view->bottom_startline->next;
view->bottom_subline = 0; view->bottom_subline = 0;
} }
if (view->startline->data == line) { if (view->startline == line) {
/* removing the first line in screen */ /* removing the first line in screen */
realcount = view_scroll(view, &view->startline, realcount = view_scroll(view, &view->startline,
&view->subline, &view->subline,
@ -922,7 +904,8 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
view->ypos -= realcount; view->ypos -= realcount;
view->empty_linecount += linecount-realcount; view->empty_linecount += linecount-realcount;
} }
} else if (g_list_find(view->bottom_startline, line) != NULL) { } else if (textbuffer_line_exists_after(view->bottom_startline,
line)) {
realcount = view_scroll(view, &view->bottom_startline, realcount = view_scroll(view, &view->bottom_startline,
&view->bottom_subline, &view->bottom_subline,
-linecount, FALSE); -linecount, FALSE);
@ -933,7 +916,7 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
&view->subline, -linecount, TRUE); &view->subline, -linecount, TRUE);
view->ypos -= linecount-realcount; view->ypos -= linecount-realcount;
} else { } else {
if (view->startline->data == line) { if (view->startline == line) {
view->startline = view->startline =
view->startline->next != NULL ? view->startline->next != NULL ?
view->startline->next : view->startline->next :
@ -1037,7 +1020,7 @@ void textbuffer_view_set_bookmark_bottom(TEXT_BUFFER_VIEW_REC *view,
g_return_if_fail(name != NULL); g_return_if_fail(name != NULL);
if (view->bottom_startline != NULL) { if (view->bottom_startline != NULL) {
line = g_list_last(view->bottom_startline)->data; line = textbuffer_line_last(view->buffer);
textbuffer_view_set_bookmark(view, name, line); textbuffer_view_set_bookmark(view, name, line);
} }
} }

View file

@ -50,11 +50,11 @@ typedef struct {
TEXT_BUFFER_CACHE_REC *cache; TEXT_BUFFER_CACHE_REC *cache;
int ypos; /* cursor position - visible area is 0..height-1 */ int ypos; /* cursor position - visible area is 0..height-1 */
GList *startline; /* line at the top of the screen */ LINE_REC *startline; /* line at the top of the screen */
int subline; /* number of "real lines" to skip from `startline' */ int subline; /* number of "real lines" to skip from `startline' */
/* marks the bottom of the text buffer */ /* marks the bottom of the text buffer */
GList *bottom_startline; LINE_REC *bottom_startline;
int bottom_subline; int bottom_subline;
/* how many empty lines are in screen. a screenful when started /* how many empty lines are in screen. a screenful when started
@ -86,7 +86,7 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height);
void textbuffer_view_clear(TEXT_BUFFER_VIEW_REC *view); void textbuffer_view_clear(TEXT_BUFFER_VIEW_REC *view);
#define textbuffer_view_get_lines(view) \ #define textbuffer_view_get_lines(view) \
((view)->buffer->lines) ((view)->buffer->first_line)
/* Scroll the view up/down */ /* Scroll the view up/down */
void textbuffer_view_scroll(TEXT_BUFFER_VIEW_REC *view, int lines); void textbuffer_view_scroll(TEXT_BUFFER_VIEW_REC *view, int lines);

View file

@ -187,14 +187,23 @@ static LINE_REC *textbuffer_line_insert(TEXT_BUFFER_REC *buffer,
{ {
LINE_REC *line; LINE_REC *line;
line = textbuffer_line_create(buffer); line = textbuffer_line_create(buffer);
if (prev == buffer->cur_line) { line->prev = prev;
buffer->cur_line = line; if (prev == NULL) {
buffer->lines = g_list_append(buffer->lines, buffer->cur_line); line->next = buffer->first_line;
if (buffer->first_line != NULL)
buffer->first_line->prev = line;
buffer->first_line = line;
} else { } else {
buffer->lines = g_list_insert(buffer->lines, line, line->prev = prev;
g_list_index(buffer->lines, prev)+1); line->next = prev->next;
if (line->next != NULL)
line->next->prev = line;
prev->next = line;
} }
if (prev == buffer->cur_line)
buffer->cur_line = line;
buffer->lines_count++; buffer->lines_count++;
return line; return line;
@ -229,6 +238,28 @@ void textbuffer_line_unref_list(TEXT_BUFFER_REC *buffer, GList *list)
} }
} }
LINE_REC *textbuffer_line_last(TEXT_BUFFER_REC *buffer)
{
LINE_REC *line;
line = buffer->cur_line;
if (line != NULL) {
while (line->next != NULL)
line = line->next;
}
return line;
}
int textbuffer_line_exists_after(LINE_REC *line, LINE_REC *search)
{
while (line != NULL) {
if (line == search)
return TRUE;
line = line->next;
}
return FALSE;
}
LINE_REC *textbuffer_append(TEXT_BUFFER_REC *buffer, LINE_REC *textbuffer_append(TEXT_BUFFER_REC *buffer,
const unsigned char *data, int len, const unsigned char *data, int len,
LINE_INFO_REC *info) LINE_INFO_REC *info)
@ -264,11 +295,16 @@ void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line)
g_return_if_fail(buffer != NULL); g_return_if_fail(buffer != NULL);
g_return_if_fail(line != NULL); g_return_if_fail(line != NULL);
buffer->lines = g_list_remove(buffer->lines, line); if (buffer->first_line == line)
buffer->first_line = line->next;
if (line->prev != NULL)
line->prev->next = line->next;
if (line->next != NULL)
line->next->prev = line->prev;
if (buffer->cur_line == line) { if (buffer->cur_line == line) {
buffer->cur_line = buffer->lines == NULL ? NULL : buffer->cur_line = line->next != NULL ?
g_list_last(buffer->lines)->data; line->next : line->prev;
} }
buffer->lines_count--; buffer->lines_count--;
@ -279,6 +315,7 @@ void textbuffer_remove(TEXT_BUFFER_REC *buffer, LINE_REC *line)
void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer) void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer)
{ {
GSList *tmp; GSList *tmp;
LINE_REC *line;
g_return_if_fail(buffer != NULL); g_return_if_fail(buffer != NULL);
@ -287,8 +324,11 @@ void textbuffer_remove_all_lines(TEXT_BUFFER_REC *buffer)
g_slist_free(buffer->text_chunks); g_slist_free(buffer->text_chunks);
buffer->text_chunks = NULL; buffer->text_chunks = NULL;
g_list_free(buffer->lines); while (buffer->first_line != NULL) {
buffer->lines = NULL; line = buffer->first_line->next;
g_mem_chunk_free(line_chunk, buffer->first_line);
buffer->first_line = line;
}
buffer->cur_line = NULL; buffer->cur_line = NULL;
buffer->lines_count = 0; buffer->lines_count = 0;
@ -365,7 +405,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
regex_t preg; regex_t preg;
#endif #endif
GList *line, *tmp; LINE_REC *line;
GList *matches; GList *matches;
GString *str; GString *str;
@ -386,25 +426,21 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
matches = NULL; matches = NULL;
str = g_string_new(NULL); str = g_string_new(NULL);
line = g_list_find(buffer->lines, startline); line = startline != NULL ? startline : buffer->first_line;
if (line == NULL)
line = buffer->lines;
for (tmp = line; tmp != NULL; tmp = tmp->next) { for (; line != NULL; line = line->next) {
LINE_REC *rec = tmp->data; if ((line->info.level & level) == 0 ||
(line->info.level & nolevel) != 0)
if ((rec->info.level & level) == 0 ||
(rec->info.level & nolevel) != 0)
continue; continue;
if (*text == '\0') { if (*text == '\0') {
/* no search word, everything matches */ /* no search word, everything matches */
textbuffer_line_ref(rec); textbuffer_line_ref(line);
matches = g_list_append(matches, rec); matches = g_list_append(matches, line);
continue; continue;
} }
textbuffer_line2text(rec, FALSE, str); textbuffer_line2text(line, FALSE, str);
if ( if (
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H
@ -415,8 +451,8 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
case_sensitive ? strstr(str->str, text) != NULL : case_sensitive ? strstr(str->str, text) != NULL :
stristr(str->str, text) != NULL) { stristr(str->str, text) != NULL) {
/* matched */ /* matched */
textbuffer_line_ref(rec); textbuffer_line_ref(line);
matches = g_list_append(matches, rec); matches = g_list_append(matches, line);
} }
} }
#ifdef HAVE_REGEX_H #ifdef HAVE_REGEX_H

View file

@ -1,10 +1,6 @@
#ifndef __TEXTBUFFER_H #ifndef __TEXTBUFFER_H
#define __TEXTBUFFER_H #define __TEXTBUFFER_H
/* FIXME: Textbuffer code gets a lot faster in some points when I get rid of
GList and make prev/next pointers directly in LINE_REC. However, this
can still wait for a while until I get rid of GList entirely everywhere. */
#define LINE_TEXT_CHUNK_SIZE 16384 #define LINE_TEXT_CHUNK_SIZE 16384
enum { enum {
@ -27,13 +23,15 @@ typedef struct {
time_t time; time_t time;
} LINE_INFO_REC; } LINE_INFO_REC;
typedef struct { typedef struct _LINE_REC {
/* text in the line. \0 means that the next char will be a /* text in the line. \0 means that the next char will be a
color or command. <= 127 = color or if 8. bit is set, the color or command. <= 127 = color or if 8. bit is set, the
first 7 bits are the command. See LINE_CMD_xxxx. first 7 bits are the command. See LINE_CMD_xxxx.
DO NOT ADD BLACK WITH \0\0 - this will break things. Use DO NOT ADD BLACK WITH \0\0 - this will break things. Use
LINE_CMD_COLOR0 instead. */ LINE_CMD_COLOR0 instead. */
struct _LINE_REC *prev, *next;
unsigned char *text; unsigned char *text;
unsigned char refcount; unsigned char refcount;
LINE_INFO_REC info; LINE_INFO_REC info;
@ -47,7 +45,7 @@ typedef struct {
typedef struct { typedef struct {
GSList *text_chunks; GSList *text_chunks;
GList *lines; LINE_REC *first_line;
int lines_count; int lines_count;
LINE_REC *cur_line; LINE_REC *cur_line;
@ -65,6 +63,9 @@ void textbuffer_line_ref(LINE_REC *line);
void textbuffer_line_unref(TEXT_BUFFER_REC *buffer, LINE_REC *line); void textbuffer_line_unref(TEXT_BUFFER_REC *buffer, LINE_REC *line);
void textbuffer_line_unref_list(TEXT_BUFFER_REC *buffer, GList *list); void textbuffer_line_unref_list(TEXT_BUFFER_REC *buffer, GList *list);
LINE_REC *textbuffer_line_last(TEXT_BUFFER_REC *buffer);
int textbuffer_line_exists_after(LINE_REC *line, LINE_REC *search);
/* Append text to buffer. When \0<EOL> is found at the END OF DATA, a new /* Append text to buffer. When \0<EOL> is found at the END OF DATA, a new
line is created. You must send the EOL command before you can do anything line is created. You must send the EOL command before you can do anything
else with the buffer. */ else with the buffer. */