1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

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
parent dd37b9ca2c
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) {
/* remove lines by line count */
while (view->buffer->lines_count > scrollback_lines) {
line = view->buffer->lines->data;
line = view->buffer->first_line;
if (line->info.time >= old_time ||
scrollback_lines == 0) {
/* too new line, don't remove yet - also

View File

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

View File

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

View File

@ -321,7 +321,7 @@ static int view_line_draw(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
original if possible */
static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
{
GList *tmp;
LINE_REC *line;
int linecount, total;
if (view->empty_linecount == 0) {
@ -331,12 +331,10 @@ static void textbuffer_view_init_bottom(TEXT_BUFFER_VIEW_REC *view)
}
total = 0;
tmp = g_list_last(view->buffer->lines);
for (; tmp != NULL; tmp = tmp->prev) {
LINE_REC *line = tmp->data;
line = textbuffer_line_last(view->buffer);
for (; line != NULL; line = line->prev) {
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 */
if (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;
if (total >= view->height) {
view->bottom_startline = tmp;
view->bottom_startline = line;
view->bottom_subline = total - view->height;
view->empty_linecount = 0;
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 */
view->bottom_startline = view->buffer->lines;
view->bottom_startline = view->buffer->first_line;
view->bottom_subline = 0;
view->empty_linecount = view->height - total;
}
static void textbuffer_view_init_ypos(TEXT_BUFFER_VIEW_REC *view)
{
GList *tmp;
LINE_REC *line;
g_return_if_fail(view != NULL);
view->ypos = -view->subline-1;
for (tmp = view->startline; tmp != NULL; tmp = tmp->next)
view->ypos += view_get_linecount(view, tmp->data);
for (line = view->startline; line != NULL; line = line->next)
view->ypos += view_get_linecount(view, line);
}
/* Create new view. */
@ -445,28 +443,26 @@ void textbuffer_view_set_default_indent(TEXT_BUFFER_VIEW_REC *view,
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;
linecount = 0;
while (lines != NULL) {
linecount += view_get_linecount(view, lines->data);
lines = lines->next;
while (line != NULL) {
linecount += view_get_linecount(view, line);
line = line->next;
}
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 linecount;
while (line != NULL && lines > 0) {
LINE_REC *rec = line->data;
linecount = view_line_draw(view, rec, subline, ypos, lines);
linecount = view_line_draw(view, line, subline, ypos, lines);
ypos += linecount; lines -= linecount;
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)
{
GList *line;
LINE_REC *line;
int ypos, maxline, subline, linecount;
maxline = view->height-lines;
line = view->startline; ypos = -view->subline; subline = 0;
while (line != NULL && ypos < maxline) {
linecount = view_get_linecount(view, line->data);
linecount = view_get_linecount(view, line);
ypos += linecount;
if (ypos > maxline) {
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 */
static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline,
int scrollcount, int draw_nonclean)
static int view_scroll(TEXT_BUFFER_VIEW_REC *view, LINE_REC **lines,
int *subline, int scrollcount, int draw_nonclean)
{
int linecount, realcount, scroll_visible;
@ -520,7 +516,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline,
scrollcount += *subline;
*subline = 0;
while (scrollcount > 0) {
linecount = view_get_linecount(view, (*lines)->data);
linecount = view_get_linecount(view, *lines);
if ((scroll_visible && *lines == view->bottom_startline) &&
(scrollcount >= view->bottom_subline)) {
@ -545,7 +541,7 @@ static int view_scroll(TEXT_BUFFER_VIEW_REC *view, GList **lines, int *subline,
/* scroll up */
while (scrollcount < 0 && (*lines)->prev != NULL) {
*lines = (*lines)->prev;
linecount = view_get_linecount(view, (*lines)->data);
linecount = view_get_linecount(view, *lines);
realcount -= linecount;
scrollcount += linecount;
@ -595,7 +591,7 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
view->width = width;
view->height = height;
if (view->buffer->lines == NULL) {
if (view->buffer->first_line == NULL) {
view->empty_linecount = height;
return;
}
@ -603,8 +599,8 @@ void textbuffer_view_resize(TEXT_BUFFER_VIEW_REC *view, int width, int height)
textbuffer_view_init_bottom(view);
/* check that we didn't scroll lower than bottom startline.. */
if (g_list_find(view->bottom_startline->next,
view->startline->data) != NULL) {
if (textbuffer_line_exists_after(view->bottom_startline->next,
view->startline)) {
view->startline = view->bottom_startline;
view->subline = view->bottom_subline;
} 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;
} else {
/* 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)
view->subline = linecount;
}
@ -649,7 +645,7 @@ void textbuffer_view_clear(TEXT_BUFFER_VIEW_REC *view)
view->ypos = -1;
view->bottom_startline = view->startline =
g_list_last(view->buffer->lines);
textbuffer_line_last(view->buffer);
view->bottom_subline = view->subline =
view->buffer->cur_line == NULL ? 0 :
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 */
void textbuffer_view_scroll_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line)
{
GList *tmp;
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->subline = view->bottom_subline;
} else {
for (tmp = view->buffer->lines; tmp != NULL; tmp = tmp->next) {
LINE_REC *rec = tmp->data;
if (rec == line) {
view->startline = tmp;
view->subline = 0;
break;
}
}
view->startline = line;
view->subline = 0;
}
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) {
view->startline = view->bottom_startline =
view->buffer->lines;
view->buffer->first_line;
}
if (view->buffer->cur_line != line &&
g_list_find(view->bottom_startline, line) == NULL)
!textbuffer_line_exists_after(view->bottom_startline, line))
return;
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);
if (rec.remove_list != NULL) {
GList *pos = g_list_find(view->buffer->lines, line);
new_line = pos == NULL || pos->prev == NULL ? NULL :
(pos->next == NULL ? pos->prev->data :
pos->next->data);
new_line = line->prev == NULL ? NULL :
(line->next == NULL ? line->prev : line->next);
for (tmp = rec.remove_list; tmp != NULL; tmp = tmp->next) {
g_hash_table_remove(view->bookmarks, tmp->data);
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 -
stops counting when the height reaches the view height */
static int view_get_lines_height(TEXT_BUFFER_VIEW_REC *view,
GList *lines, int subline,
LINE_REC *line, int subline,
LINE_REC *skip_line)
{
int height, linecount;
height = -subline;
while (lines != NULL && height < view->height) {
LINE_REC *line = lines->data;
while (line != NULL && height < view->height) {
if (line != skip_line) {
linecount = view_get_linecount(view, line);
height += linecount;
}
lines = lines->next;
line = line->next;
}
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 */
LINE_REC *prevline;
prevline = view->buffer->lines->data == line ? NULL :
g_list_last(view->bottom_startline)->data;
prevline = view->buffer->first_line == line ? NULL :
textbuffer_line_last(view->buffer);
view->cache->last_linecount = prevline == NULL ? 0 :
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
removed line.. */
if (view->bottom_startline->data == line) {
if (view->bottom_startline == line) {
/* very small scrollback.. */
view->bottom_startline = view->bottom_startline->next;
view->bottom_subline = 0;
}
if (view->startline->data == line) {
if (view->startline == line) {
/* removing the first line in screen */
realcount = view_scroll(view, &view->startline,
&view->subline,
@ -922,7 +904,8 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
view->ypos -= 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,
&view->bottom_subline,
-linecount, FALSE);
@ -933,7 +916,7 @@ static void view_remove_line(TEXT_BUFFER_VIEW_REC *view, LINE_REC *line,
&view->subline, -linecount, TRUE);
view->ypos -= linecount-realcount;
} else {
if (view->startline->data == line) {
if (view->startline == line) {
view->startline =
view->startline->next != NULL ?
view->startline->next :
@ -1037,7 +1020,7 @@ void textbuffer_view_set_bookmark_bottom(TEXT_BUFFER_VIEW_REC *view,
g_return_if_fail(name != 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);
}
}

View File

@ -50,11 +50,11 @@ typedef struct {
TEXT_BUFFER_CACHE_REC *cache;
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' */
/* marks the bottom of the text buffer */
GList *bottom_startline;
LINE_REC *bottom_startline;
int bottom_subline;
/* 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);
#define textbuffer_view_get_lines(view) \
((view)->buffer->lines)
((view)->buffer->first_line)
/* Scroll the view up/down */
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 = textbuffer_line_create(buffer);
if (prev == buffer->cur_line) {
buffer->cur_line = line;
buffer->lines = g_list_append(buffer->lines, buffer->cur_line);
line = textbuffer_line_create(buffer);
line->prev = prev;
if (prev == NULL) {
line->next = buffer->first_line;
if (buffer->first_line != NULL)
buffer->first_line->prev = line;
buffer->first_line = line;
} else {
buffer->lines = g_list_insert(buffer->lines, line,
g_list_index(buffer->lines, prev)+1);
line->prev = prev;
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++;
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,
const unsigned char *data, int len,
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(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) {
buffer->cur_line = buffer->lines == NULL ? NULL :
g_list_last(buffer->lines)->data;
buffer->cur_line = line->next != NULL ?
line->next : line->prev;
}
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)
{
GSList *tmp;
LINE_REC *line;
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);
buffer->text_chunks = NULL;
g_list_free(buffer->lines);
buffer->lines = NULL;
while (buffer->first_line != NULL) {
line = buffer->first_line->next;
g_mem_chunk_free(line_chunk, buffer->first_line);
buffer->first_line = line;
}
buffer->cur_line = NULL;
buffer->lines_count = 0;
@ -365,7 +405,7 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
#ifdef HAVE_REGEX_H
regex_t preg;
#endif
GList *line, *tmp;
LINE_REC *line;
GList *matches;
GString *str;
@ -386,25 +426,21 @@ GList *textbuffer_find_text(TEXT_BUFFER_REC *buffer, LINE_REC *startline,
matches = NULL;
str = g_string_new(NULL);
line = g_list_find(buffer->lines, startline);
if (line == NULL)
line = buffer->lines;
line = startline != NULL ? startline : buffer->first_line;
for (tmp = line; tmp != NULL; tmp = tmp->next) {
LINE_REC *rec = tmp->data;
if ((rec->info.level & level) == 0 ||
(rec->info.level & nolevel) != 0)
for (; line != NULL; line = line->next) {
if ((line->info.level & level) == 0 ||
(line->info.level & nolevel) != 0)
continue;
if (*text == '\0') {
/* no search word, everything matches */
textbuffer_line_ref(rec);
matches = g_list_append(matches, rec);
textbuffer_line_ref(line);
matches = g_list_append(matches, line);
continue;
}
textbuffer_line2text(rec, FALSE, str);
textbuffer_line2text(line, FALSE, str);
if (
#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 :
stristr(str->str, text) != NULL) {
/* matched */
textbuffer_line_ref(rec);
matches = g_list_append(matches, rec);
textbuffer_line_ref(line);
matches = g_list_append(matches, line);
}
}
#ifdef HAVE_REGEX_H

View File

@ -1,10 +1,6 @@
#ifndef __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
enum {
@ -27,13 +23,15 @@ typedef struct {
time_t time;
} LINE_INFO_REC;
typedef struct {
typedef struct _LINE_REC {
/* 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
first 7 bits are the command. See LINE_CMD_xxxx.
DO NOT ADD BLACK WITH \0\0 - this will break things. Use
LINE_CMD_COLOR0 instead. */
struct _LINE_REC *prev, *next;
unsigned char *text;
unsigned char refcount;
LINE_INFO_REC info;
@ -47,7 +45,7 @@ typedef struct {
typedef struct {
GSList *text_chunks;
GList *lines;
LINE_REC *first_line;
int lines_count;
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_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
line is created. You must send the EOL command before you can do anything
else with the buffer. */