changeset 49572:f492ad3945ad

Fix memory leak.
author Jan Djärv <jan.h.d@swipnet.se>
date Sun, 02 Feb 2003 18:54:32 +0000
parents 77c6a7852f3b
children 3261228348b4
files src/ChangeLog src/gtkutil.c
diffstat 2 files changed, 116 insertions(+), 93 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Sun Feb 02 17:35:47 2003 +0000
+++ b/src/ChangeLog	Sun Feb 02 18:54:32 2003 +0000
@@ -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
--- a/src/gtkutil.c	Sun Feb 02 17:35:47 2003 +0000
+++ b/src/gtkutil.c	Sun Feb 02 18:54:32 2003 +0000
@@ -1576,11 +1576,9 @@
      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 @@
          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 @@
 
       /* 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);
-
-      if (val_in_menubar && ! list_in_new_menubar)
+      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 && ! iter_in_new_menubar)
         {
+          int nr = pos;
+
           /*  This corresponds to:
                 Current:  A B C
                 New:      A C
@@ -1690,10 +1685,11 @@
           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 @@
           
           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 @@
           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 @@
                                  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 @@
 
       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 @@
           gtk_container_add (GTK_CONTAINER (w), GTK_WIDGET (wlbl));
           wkey = 0;
         }
+
     }
   else /* Just a label.  */
     {
@@ -1815,8 +1820,10 @@
         {
           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 @@
                              0);
     }
     
+  if (list) g_list_free (list);
+
   return newsub;
 }
 
@@ -2080,7 +2089,6 @@
 {
   xg_menu_cb_data *cl_data;
   GList *list = gtk_container_get_children (GTK_CONTAINER (menubar));
-  GList *iter;
 
   if (! list) return;
   
@@ -2090,7 +2098,7 @@
   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 @@
 
       for (cur = val->contents; cur; cur = cur->next)
         {
+          GList *iter;
           GtkWidget *sub = 0;
           GtkWidget *newsub;
           GtkMenuItem *witem;
@@ -2137,6 +2146,7 @@
         }
     }
 
+  g_list_free (list);
   gtk_widget_show_all (menubar);
 }
 
@@ -2424,34 +2434,35 @@
      int width;
      int height;
 {
-    GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
-
-    if (wscroll)
-      {
-        int gheight = max (height, 1);
-
-        gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget),
-                        wscroll, left, top);
-
-        gtk_widget_set_size_request (wscroll, width, gheight);
-
-        /* Must force out update so wscroll gets the resize.
-           Otherwise, the gdk_window_clear clears the old window size.  */
-        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);
-
-        /* 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);
-      }
+
+  GtkWidget *wscroll = xg_get_widget_from_map (scrollbar_id);
+
+  if (wscroll)
+    {
+      int gheight = max (height, 1);
+
+      gtk_fixed_move (GTK_FIXED (f->output_data.x->edit_widget),
+                      wscroll, left, top);
+
+      gtk_widget_set_size_request (wscroll, width, gheight);
+
+      /* Must force out update so wscroll gets the resize.
+         Otherwise, the gdk_window_clear clears the old window size.  */
+      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);
+
+      /* 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 @@
   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 @@
   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 @@
       int img_id;
       struct image *img;
       Lisp_Object image;
-      GtkWidget *wicon = icon_list ? GTK_WIDGET (icon_list->data) : 0;
-
-      if (icon_list) icon_list = g_list_next (icon_list);
+      GtkWidget *wicon = iter ? GTK_WIDGET (iter->data) : 0;
+
+      if (iter) iter = g_list_next (iter);
 
       /* If image is a vector, choose the image according to the
 	 button state.  */
@@ -2812,10 +2825,11 @@
           /* 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 @@
 
   /* 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 @@
   /* Must force out update so changed images gets redrawn.  */
   gdk_window_process_all_updates ();
 
+  if (icon_list) g_list_free (icon_list);
+
   UNBLOCK_INPUT;
 }