1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-22 18:35:09 +00:00

Fix memory leak.

This commit is contained in:
Jan Djärv 2003-02-02 18:54:32 +00:00
parent 769c4c6377
commit 49853a4d5c
2 changed files with 107 additions and 84 deletions

View File

@ -1,3 +1,10 @@
2003-02-02 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
* gtkutil.c (remove_from_container): Copying list is not needed.
(xg_update_menubar, xg_update_menu_item, xg_update_submenu)
(xg_modify_menubar_widgets, update_frame_tool_bar): Call g_list_free
on list returned from gtk_container_get_children to avoid memory leak.
2003-02-01 Jason Rumney <jasonr@gnu.org>
* w32fns.c (w32_create_pixmap_from_bitmap_data): Use alloca for

View File

@ -1576,11 +1576,9 @@ remove_from_container (wcont, list)
GtkWidget *wcont;
GList *list;
{
/* We must copy list because gtk_container_remove changes it. */
GList *clist = g_list_copy (list);
GList *iter;
for (iter = clist; iter; iter = g_list_next (iter))
for (iter = list; iter; iter = g_list_next (iter))
{
GtkWidget *w = GTK_WIDGET (iter->data);
@ -1595,39 +1593,44 @@ remove_from_container (wcont, list)
removing the detached window also if there was one. */
gtk_widget_destroy (w);
}
g_list_free (clist);
}
/* Update the top level names in MENUBAR (i.e. not submenus).
F is the frame the menu bar belongs to.
LIST is a list with the current menu bar names (menu item widgets).
*LIST is a list with the current menu bar names (menu item widgets).
ITER is the item within *LIST that shall be updated.
POS is the numerical position, starting at 0, of ITER in *LIST.
VAL describes what the menu bar shall look like after the update.
SELECT_CB is the callback to use when a menu item is selected.
HIGHLIGHT_CB is the callback to call when entering/leaving menu items.
CL_DATA points to the callback data to be used for this menu bar.
This function calls itself to walk through the menu bar names. */
static void
xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
xg_update_menubar (menubar, f, list, iter, pos, val,
select_cb, highlight_cb, cl_data)
GtkWidget *menubar;
FRAME_PTR f;
GList *list;
GList **list;
GList *iter;
int pos;
widget_value *val;
GCallback select_cb;
GCallback highlight_cb;
xg_menu_cb_data *cl_data;
{
if (! list && ! val)
if (! iter && ! val)
return;
else if (list && ! val)
else if (iter && ! val)
{
/* Item(s) have been removed. Remove all remaining items from list. */
remove_from_container (menubar, list);
/* Item(s) have been removed. Remove all remaining items. */
remove_from_container (menubar, iter);
/* All updated. */
val = 0;
list = 0;
iter = 0;
}
else if (! list && val)
else if (! iter && val)
{
/* Item(s) added. Add all new items in one call. */
create_menus (val, f, select_cb, 0, highlight_cb,
@ -1635,51 +1638,43 @@ xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
/* All updated. */
val = 0;
list = 0;
iter = 0;
}
/* Below this neither list or val is NULL */
else if (xg_item_label_same_p (GTK_MENU_ITEM (list->data), val->name))
/* Below this neither iter or val is NULL */
else if (xg_item_label_same_p (GTK_MENU_ITEM (iter->data), val->name))
{
/* This item is still the same, check next item. */
val = val->next;
list = g_list_next (list);
iter = g_list_next (iter);
++pos;
}
else /* This item is changed. */
{
GtkMenuItem *witem = GTK_MENU_ITEM (list->data);
GtkMenuItem *witem = GTK_MENU_ITEM (iter->data);
GtkMenuItem *witem2 = 0;
int pos = 0;
int val_in_menubar = 0;
int list_in_new_menubar = 0;
GList *list2;
GList *iter;
int iter_in_new_menubar = 0;
GList *iter2;
widget_value *cur;
/* Get position number for witem. */
list2 = gtk_container_get_children (GTK_CONTAINER (menubar));
for (iter = list2; iter; iter = g_list_next (iter))
{
if (list->data == iter->data) break;
++pos;
}
/* See if the changed entry (val) is present later in the menu bar */
for (iter = g_list_next (list);
iter && ! val_in_menubar;
iter = g_list_next (iter))
for (iter2 = iter;
iter2 && ! val_in_menubar;
iter2 = g_list_next (iter2))
{
witem2 = GTK_MENU_ITEM (iter->data);
witem2 = GTK_MENU_ITEM (iter2->data);
val_in_menubar = xg_item_label_same_p (witem2, val->name);
}
/* See if the current entry (list) is present later in the
/* See if the current entry (iter) is present later in the
specification for the new menu bar. */
for (cur = val; cur && ! list_in_new_menubar; cur = cur->next)
list_in_new_menubar = xg_item_label_same_p (witem, cur->name);
for (cur = val; cur && ! iter_in_new_menubar; cur = cur->next)
iter_in_new_menubar = xg_item_label_same_p (witem, cur->name);
if (val_in_menubar && ! list_in_new_menubar)
if (val_in_menubar && ! iter_in_new_menubar)
{
int nr = pos;
/* This corresponds to:
Current: A B C
New: A C
@ -1690,10 +1685,11 @@ xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
gtk_widget_destroy (GTK_WIDGET (witem));
/* Must get new list since the old changed. */
list = gtk_container_get_children (GTK_CONTAINER (menubar));
while (pos-- > 0) list = g_list_next (list);
g_list_free (*list);
*list = iter = gtk_container_get_children (GTK_CONTAINER (menubar));
while (nr-- > 0) iter = g_list_next (iter);
}
else if (! val_in_menubar && ! list_in_new_menubar)
else if (! val_in_menubar && ! iter_in_new_menubar)
{
/* This corresponds to:
Current: A B C
@ -1714,16 +1710,18 @@ xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
gtk_label_set_text_with_mnemonic (wlabel, utf8_label);
list = g_list_next (list);
iter = g_list_next (iter);
val = val->next;
++pos;
}
else if (! val_in_menubar && list_in_new_menubar)
else if (! val_in_menubar && iter_in_new_menubar)
{
/* This corresponds to:
Current: A B C
New: A X B C
Insert X. */
int nr = pos;
GList *group = 0;
GtkWidget *w = xg_create_one_menuitem (val,
f,
@ -1735,13 +1733,16 @@ xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
gtk_widget_set_name (w, MENU_ITEM_NAME);
gtk_menu_shell_insert (GTK_MENU_SHELL (menubar), w, pos);
list = gtk_container_get_children (GTK_CONTAINER (menubar));
while (pos-- > 0) list = g_list_next (list);
list = g_list_next (list);
g_list_free (*list);
*list = iter = gtk_container_get_children (GTK_CONTAINER (menubar));
while (nr-- > 0) iter = g_list_next (iter);
iter = g_list_next (iter);
val = val->next;
++pos;
}
else /* if (val_in_menubar && list_in_new_menubar) */
else /* if (val_in_menubar && iter_in_new_menubar) */
{
int nr = pos;
/* This corresponds to:
Current: A B C
New: A C B
@ -1753,16 +1754,17 @@ xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data)
GTK_WIDGET (witem2), pos);
gtk_widget_unref (GTK_WIDGET (witem2));
g_list_free (*list);
*list = iter = gtk_container_get_children (GTK_CONTAINER (menubar));
while (nr-- > 0) iter = g_list_next (iter);
val = val->next;
list = gtk_container_get_children (GTK_CONTAINER (menubar));
while (pos-- > 0) list = g_list_next (list);
list = g_list_next (list);
++pos;
}
}
/* Update the rest of the menu bar. */
xg_update_menubar (menubar, f, list, val, select_cb, highlight_cb, cl_data);
xg_update_menubar (menubar, f, list, iter, pos, val,
select_cb, highlight_cb, cl_data);
}
/* Update the menu item W so it corresponds to VAL.
@ -1797,6 +1799,8 @@ xg_update_menu_item (val, w, select_cb, highlight_cb, cl_data)
wlbl = GTK_LABEL (list->data);
wkey = GTK_LABEL (list->next->data);
g_list_free (list);
if (! utf8_key)
{
/* Remove the key and keep just the label. */
@ -1805,6 +1809,7 @@ xg_update_menu_item (val, w, select_cb, highlight_cb, cl_data)
gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (wlbl));
wkey = 0;
}
}
else /* Just a label. */
{
@ -1815,8 +1820,10 @@ xg_update_menu_item (val, w, select_cb, highlight_cb, cl_data)
{
GtkWidget *wtoadd = make_widget_for_menu_item (utf8_label, utf8_key);
GList *list = gtk_container_get_children (GTK_CONTAINER (wtoadd));
wlbl = GTK_LABEL (list->data);
wkey = GTK_LABEL (list->next->data);
g_list_free (list);
gtk_container_remove (GTK_CONTAINER (w), wchild);
gtk_container_add (GTK_CONTAINER (w), wtoadd);
@ -2056,6 +2063,8 @@ xg_update_submenu (submenu, f, val,
0);
}
if (list) g_list_free (list);
return newsub;
}
@ -2080,7 +2089,6 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p,
{
xg_menu_cb_data *cl_data;
GList *list = gtk_container_get_children (GTK_CONTAINER (menubar));
GList *iter;
if (! list) return;
@ -2090,7 +2098,7 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p,
if (! deep_p)
{
widget_value *cur = val->contents;
xg_update_menubar (menubar, f, list, cur,
xg_update_menubar (menubar, f, &list, list, 0, cur,
select_cb, highlight_cb, cl_data);
}
else
@ -2106,6 +2114,7 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p,
for (cur = val->contents; cur; cur = cur->next)
{
GList *iter;
GtkWidget *sub = 0;
GtkWidget *newsub;
GtkMenuItem *witem;
@ -2137,6 +2146,7 @@ xg_modify_menubar_widgets (menubar, f, val, deep_p,
}
}
g_list_free (list);
gtk_widget_show_all (menubar);
}
@ -2424,34 +2434,35 @@ xg_update_scrollbar_pos (f, scrollbar_id, top, left, width, height)
int width;
int height;
{
GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
if (wscroll)
{
int gheight = max (height, 1);
GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget),
wscroll, left, top);
if (wscroll)
{
int gheight = max (height, 1);
gtk_widget_set_size_request (wscroll, width, gheight);
gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget),
wscroll, left, top);
/* Must force out update so wscroll gets the resize.
Otherwise, the gdk_window_clear clears the old window size. */
gdk_window_process_all_updates ();
gtk_widget_set_size_request (wscroll, width, gheight);
/* The scroll bar doesn't explicitly redraw the whole window
when a resize occurs. Since the scroll bar seems to be fixed
in width it doesn't fill the space reserved, so we must clear
the whole window. */
gdk_window_clear (wscroll->window);
/* Must force out update so wscroll gets the resize.
Otherwise, the gdk_window_clear clears the old window size. */
gdk_window_process_all_updates ();
/* Since we are not using a pure gtk event loop, we must force out
pending update events with this call. */
gdk_window_process_all_updates ();
/* The scroll bar doesn't explicitly redraw the whole window
when a resize occurs. Since the scroll bar seems to be fixed
in width it doesn't fill the space reserved, so we must clear
the whole window. */
gdk_window_clear (wscroll->window);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
/* Since we are not using a pure gtk event loop, we must force out
pending update events with this call. */
gdk_window_process_all_updates ();
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
}
}
/* Set the thumb size and position of scroll bar BAR. We are currently
@ -2698,6 +2709,7 @@ update_frame_tool_bar (f)
int i;
GtkRequisition old_req, new_req;
GList *icon_list;
GList *iter;
struct x_output *x = f->output_data.x;
if (! FRAME_GTK_WIDGET (f))
@ -2711,7 +2723,8 @@ update_frame_tool_bar (f)
gtk_widget_size_request (x->toolbar_widget, &old_req);
icon_list = gtk_container_get_children (GTK_CONTAINER (x->toolbar_widget));
iter = icon_list;
for (i = 0; i < f->n_tool_bar_items; ++i)
{
#define PROP(IDX) AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
@ -2722,9 +2735,9 @@ update_frame_tool_bar (f)
int img_id;
struct image *img;
Lisp_Object image;
GtkWidget *wicon = icon_list ? GTK_WIDGET (icon_list->data) : 0;
GtkWidget *wicon = iter ? GTK_WIDGET (iter->data) : 0;
if (icon_list) icon_list = g_list_next (icon_list);
if (iter) iter = g_list_next (iter);
/* If image is a vector, choose the image according to the
button state. */
@ -2812,10 +2825,11 @@ update_frame_tool_bar (f)
/* The child of the tool bar is a button. Inside that button
is a vbox. Inside that vbox is the GtkImage. */
GtkWidget *wvbox = gtk_bin_get_child (GTK_BIN (wicon));
GList *ch = gtk_container_get_children (GTK_CONTAINER (wvbox));
GtkImage *wimage = GTK_IMAGE (ch->data);
GList *chlist = gtk_container_get_children (GTK_CONTAINER (wvbox));
GtkImage *wimage = GTK_IMAGE (chlist->data);
struct image *old_img = g_object_get_data (G_OBJECT (wimage),
XG_TOOL_BAR_IMAGE_DATA);
g_list_free (chlist);
if (! old_img
|| old_img->pixmap != img->pixmap
@ -2840,11 +2854,11 @@ update_frame_tool_bar (f)
/* Remove buttons not longer needed. We just hide them so they
can be reused later on. */
while (icon_list)
while (iter)
{
GtkWidget *w = GTK_WIDGET (icon_list->data);
GtkWidget *w = GTK_WIDGET (iter->data);
gtk_widget_hide (w);
icon_list = g_list_next (icon_list);
iter = g_list_next (iter);
}
gtk_widget_size_request (x->toolbar_widget, &new_req);
@ -2857,6 +2871,8 @@ update_frame_tool_bar (f)
/* Must force out update so changed images gets redrawn. */
gdk_window_process_all_updates ();
if (icon_list) g_list_free (icon_list);
UNBLOCK_INPUT;
}