# HG changeset patch # User Mikael Berthe # Date 1446895272 -3600 # Node ID dc3b3ac1ba768b774a41c172e2b96130e0c334be # Parent 736f9323d701c7b8935218d47af468f7d0634138 Free the buffdata structures when buffers are closed Free the buffdata strcutures when buffers are closed and there are no more users (these structures can be shared if the "symlink" shared history is used). diff -r 736f9323d701 -r dc3b3ac1ba76 mcabber/mcabber/screen.c --- a/mcabber/mcabber/screen.c Sat Nov 07 12:16:15 2015 +0100 +++ b/mcabber/mcabber/screen.c Sat Nov 07 12:21:12 2015 +0100 @@ -100,10 +100,12 @@ static GHashTable *winbufhash; typedef struct { - GList *hbuf; - GList *top; // If top is NULL, we'll display the last lines - char cleared; // For ex, user has issued a /clear command... - char lock; + GList *hbuf; + GList *top; // If top is NULL, we'll display the last lines + char cleared; // For ex, user has issued a /clear command... + char lock; + char refcount; // refcount > 0 if there are other users of this struct + // e.g. with symlinked history } buffdata; typedef struct { @@ -1038,6 +1040,7 @@ static winbuf *scr_new_buddy(const char *title, int dont_show) { winbuf *tmp; + char *id; tmp = g_new0(winbuf, 1); @@ -1055,30 +1058,34 @@ update_panels(); // If title is NULL, this is a special buffer - if (title) { - char *id; - id = hlog_get_log_jid(title); - if (id) { - winbuf *wb = scr_search_window(id, FALSE); - if (!wb) - wb = scr_new_buddy(id, TRUE); - tmp->bd=wb->bd; - g_free(id); - } else { // Load buddy history from file (if enabled) - tmp->bd = g_new0(buffdata, 1); - hlog_read_history(title, &tmp->bd->hbuf, - maxX - Roster_Width - scr_getprefixwidth()); - - // Set a readmark to separate new content - hbuf_set_readmark(tmp->bd->hbuf, TRUE); - } - - id = g_strdup(title); - mc_strtolower(id); - g_hash_table_insert(winbufhash, id, tmp); - } else { + if (!title) { tmp->bd = g_new0(buffdata, 1); + return tmp; } + + id = hlog_get_log_jid(title); + if (id) { + // This is a symlinked history log file. + // Let's check if the target JID buffer has already been created. + winbuf *wb = scr_search_window(id, FALSE); + if (!wb) + wb = scr_new_buddy(id, TRUE); + tmp->bd = wb->bd; + tmp->bd->refcount++; + g_free(id); + } else { // Load buddy history from file (if enabled) + tmp->bd = g_new0(buffdata, 1); + hlog_read_history(title, &tmp->bd->hbuf, + maxX - Roster_Width - scr_getprefixwidth()); + + // Set a readmark to separate new content + hbuf_set_readmark(tmp->bd->hbuf, TRUE); + } + + id = g_strdup(title); + mc_strtolower(id); + g_hash_table_insert(winbufhash, id, tmp); + return tmp; } @@ -2867,7 +2874,9 @@ gboolean retval = FALSE; // Delete the current hbuf - hbuf_free(&win_entry->bd->hbuf); + // unless we close the buffer *and* this is a shared bd structure + if (!(*p_closebuf && win_entry->bd->refcount)) + hbuf_free(&win_entry->bd->hbuf); if (*p_closebuf) { GSList *roster_elt; @@ -2876,6 +2885,12 @@ ROSTER_TYPE_USER|ROSTER_TYPE_AGENT); if (roster_elt) buddy_setactiveresource(roster_elt->data, NULL); + if (win_entry->bd->refcount) { + win_entry->bd->refcount--; + } else { + g_free(win_entry->bd); + win_entry->bd = NULL; + } } else { win_entry->bd->cleared = FALSE; win_entry->bd->top = NULL;