/* GTK - The GIMP Toolkit
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

/*
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 */

/*
 * Modified by the GTK-MUI Team 2006
 *
 * $Id: gtk_box.c,v 1.8 2007/10/25 15:22:19 o1i Exp $
 */

#include <config.h>
#include "gtk/gtk.h"
#include "gtk/gtkbox.h"

#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/exec.h>
#include <proto/gadtools.h>
#ifdef __AROS__
#include <dos/dos.h>
#endif
#include <mui.h>

#include "classes/classes.h"
#include "gtk_globals.h"
#include "debug.h"

#if 0
#include "gtkintl.h"
#include "gtkalias.h"
#endif

enum {
  PROP_0,
  PROP_SPACING,
  PROP_HOMOGENEOUS
};

enum {
  CHILD_PROP_0,
  CHILD_PROP_EXPAND,
  CHILD_PROP_FILL,
  CHILD_PROP_PADDING,
  CHILD_PROP_PACK_TYPE,
  CHILD_PROP_POSITION
};

static void gtk_box_class_init (GtkBoxClass    *klass);
static void gtk_box_init       (GtkBox         *box);
static void gtk_box_set_property (GObject         *object,
				  guint            prop_id,
				  const GValue    *value,
				  GParamSpec      *pspec);
static void gtk_box_get_property (GObject         *object,
				  guint            prop_id,
				  GValue          *value,
				  GParamSpec      *pspec);
static void gtk_box_add        (GtkContainer   *container,
			        GtkWidget      *widget);
static void gtk_box_remove     (GtkContainer   *container,
			        GtkWidget      *widget);
static void gtk_box_forall     (GtkContainer   *container,
				gboolean	include_internals,
			        GtkCallback     callback,
			        gpointer        callback_data);
static void gtk_box_set_child_property (GtkContainer    *container,
					GtkWidget       *child,
					guint            property_id,
					const GValue    *value,
					GParamSpec      *pspec);
static void gtk_box_get_child_property (GtkContainer    *container,
					GtkWidget       *child,
					guint            property_id,
					GValue          *value,
					GParamSpec      *pspec);
static GType gtk_box_child_type (GtkContainer   *container);
     

static GtkContainerClass *parent_class = NULL;


GType gtk_box_get_type (void) {

  static GType box_type = 0;

  if (!box_type) {
    static const GTypeInfo box_info = {
      sizeof (GtkBoxClass),
      NULL,		/* base_init */
      NULL,		/* base_finalize */
      (GClassInitFunc) gtk_box_class_init,
      NULL,		/* class_finalize */
      NULL,		/* class_data */
      sizeof (GtkBox),
      0,		/* n_preallocs */
      (GInstanceInitFunc) gtk_box_init,
      NULL,		/* value_table */
    };

    box_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkBox", 
					 &box_info, G_TYPE_FLAG_ABSTRACT);
  }

  return box_type;
}

static void gtk_box_class_init (GtkBoxClass *class) {

  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (class);

  DebOut("gtk_box_class_init(%lx)\n",class);

  parent_class = g_type_class_peek_parent (class);

  gobject_class->set_property = gtk_box_set_property;
  gobject_class->get_property = gtk_box_get_property;
   
  container_class->add = gtk_box_add;
  container_class->remove = gtk_box_remove;
  container_class->forall = gtk_box_forall;
  container_class->child_type = gtk_box_child_type;
  container_class->set_child_property = gtk_box_set_child_property;
  container_class->get_child_property = gtk_box_get_child_property;

  DebOut("  gtk_box_class_init 1\n");

  g_object_class_install_property (gobject_class,
                                   PROP_SPACING,
                                   g_param_spec_int ("spacing",
                                                     P_("Spacing"),
                                                     P_("The amount of space between children"),
                                                     0,
                                                     G_MAXINT,
                                                     0,
                                                     G_PARAM_READABLE | G_PARAM_WRITABLE));
  
#if 0
  DebOut("  gtk_box_class_init 2\n");
  g_object_class_install_property (gobject_class,
                                   PROP_HOMOGENEOUS,
                                   g_param_spec_boolean ("homogeneous",
							 P_("Homogeneous"),
							 P_("Whether the children should all be the same size"),
							 FALSE,
							 G_PARAM_READABLE | G_PARAM_WRITABLE));

  DebOut("  gtk_box_class_init 3\n");
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_EXPAND,
					      g_param_spec_boolean ("expand", 
								    P_("Expand"), 
								    P_("Whether the child should receive extra space when the parent grows"),
								    TRUE,
								    G_PARAM_READWRITE));
  DebOut("  gtk_box_class_init 4\n");
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_FILL,
					      g_param_spec_boolean ("fill", 
								    P_("Fill"), 
								    P_("Whether extra space given to the child should be allocated to the child or used as padding"),
								    TRUE,
								    G_PARAM_READWRITE));
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_PADDING,
					      g_param_spec_uint ("padding", 
								 P_("Padding"), 
								 P_("Extra space to put between the child and its neighbors, in pixels"),
								 0, G_MAXINT, 0,
								 G_PARAM_READWRITE));
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_PACK_TYPE,
					      g_param_spec_enum ("pack_type", 
								 P_("Pack type"), 
								 P_("A GtkPackType indicating whether the child is packed with reference to the start or end of the parent"),
								 GTK_TYPE_PACK_TYPE, GTK_PACK_START,
								 G_PARAM_READWRITE));
  gtk_container_class_install_child_property (container_class,
					      CHILD_PROP_POSITION,
					      g_param_spec_int ("position", 
								P_("Position"), 
								P_("The index of the child in the parent"),
								-1, G_MAXINT, 0,
								G_PARAM_READWRITE));
#endif
  DebOut("  gtk_box_class_init ok\n");
}

static void gtk_box_init (GtkBox *box) {

  DebOut("gtk_box_init(%lx)\n",box);

  GTK_WIDGET_SET_FLAGS (box, GTK_NO_WINDOW);
#if 0
  gtk_widget_set_redraw_on_allocate (GTK_WIDGET (box), FALSE);
#endif
  
  box->children = NULL;
  box->spacing = 0;
  box->homogeneous = FALSE;

  GtkSetObj(GTK_WIDGET(box),NewObject(CL_Group->mcc_Class, NULL,
                                             MA_Widget,(LONG) box,
                                             TAG_DONE));

  GTK_MUI(box)->mainclass=CL_AREA;

  DebOut("gtk_box_init(%lx) DONE!\n");
}

static void gtk_box_set_property (GObject         *object,
		      guint            prop_id,
		      const GValue    *value,
		      GParamSpec      *pspec) {

  GtkBox *box;

  box = GTK_BOX (object);

  switch (prop_id)
    {
    case PROP_SPACING:
      gtk_box_set_spacing (box, g_value_get_int (value));
      break;
    case PROP_HOMOGENEOUS:
      gtk_box_set_homogeneous (box, g_value_get_boolean (value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static void gtk_box_get_property (GObject         *object,
				  guint            prop_id,
				  GValue          *value,
				  GParamSpec      *pspec)
{
  GtkBox *box;

  box = GTK_BOX (object);

  switch (prop_id)
    {
    case PROP_SPACING:
      g_value_set_int (value, box->spacing);
      break;
    case PROP_HOMOGENEOUS:
      g_value_set_boolean (value, box->homogeneous);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
    }
}

static GType gtk_box_child_type (GtkContainer   *container) {

  return GTK_TYPE_WIDGET;
}

static void
gtk_box_set_child_property (GtkContainer    *container,
			    GtkWidget       *child,
			    guint            property_id,
			    const GValue    *value,
			    GParamSpec      *pspec)
{
  gboolean expand = 0;
  gboolean fill = 0;
  guint padding = 0;
  GtkPackType pack_type = 0;

  DebOut("gtk_box_set_child_property(%lx,%lx,%d,..)\n",container,child,property_id);

  if (property_id != CHILD_PROP_POSITION)
    gtk_box_query_child_packing (GTK_BOX (container),
				 child,
				 &expand,
				 &fill,
				 &padding,
				 &pack_type);
  switch (property_id)
    {
    case CHILD_PROP_EXPAND:
      gtk_box_set_child_packing (GTK_BOX (container),
				 child,
				 g_value_get_boolean (value),
				 fill,
				 padding,
				 pack_type);
      break;
    case CHILD_PROP_FILL:
      gtk_box_set_child_packing (GTK_BOX (container),
				 child,
				 expand,
				 g_value_get_boolean (value),
				 padding,
				 pack_type);
      break;
    case CHILD_PROP_PADDING:
      gtk_box_set_child_packing (GTK_BOX (container),
				 child,
				 expand,
				 fill,
				 g_value_get_uint (value),
				 pack_type);
      break;
    case CHILD_PROP_PACK_TYPE:
      gtk_box_set_child_packing (GTK_BOX (container),
				 child,
				 expand,
				 fill,
				 padding,
				 g_value_get_enum (value));
      break;
    case CHILD_PROP_POSITION:
      gtk_box_reorder_child (GTK_BOX (container),
			     child,
			     g_value_get_int (value));
      break;
    default:
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      break;
    }
}

static void
gtk_box_get_child_property (GtkContainer *container,
			    GtkWidget    *child,
			    guint         property_id,
			    GValue       *value,
			    GParamSpec   *pspec)
{
  gboolean expand = 0;
  gboolean fill = 0;
  guint padding = 0;
  GtkPackType pack_type = 0;
  GList *list;

  if (property_id != CHILD_PROP_POSITION)
    gtk_box_query_child_packing (GTK_BOX (container),
				 child,
				 &expand,
				 &fill,
				 &padding,
				 &pack_type);
  switch (property_id)
    {
      guint i;
    case CHILD_PROP_EXPAND:
      g_value_set_boolean (value, expand);
      break;
    case CHILD_PROP_FILL:
      g_value_set_boolean (value, fill);
      break;
    case CHILD_PROP_PADDING:
      g_value_set_uint (value, padding);
      break;
    case CHILD_PROP_PACK_TYPE:
      g_value_set_enum (value, pack_type);
      break;
    case CHILD_PROP_POSITION:
      i = 0;
      for (list = GTK_BOX (container)->children; list; list = list->next)
	{
	  GtkBoxChild *child_entry;

	  child_entry = list->data;
	  if (child_entry->widget == child)
	    break;
	  i++;
	}
      g_value_set_int (value, list ? i : -1);
      break;
    default:
      GTK_CONTAINER_WARN_INVALID_CHILD_PROPERTY_ID (container, property_id, pspec);
      break;
    }
}

void mgtk_initchange(GtkWidget *change);
void mgtk_exitchange(GtkWidget *change);


#if 0
static void mgtk_box_pack_start(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding ) {

  if(!GtkObj(box) || !GtkObj(child)) {
    ErrOut("mgtk_container_add: One widget has no Mui Object (%lx->%lx,%lx->%lx)!\n",box,GtkObj(box),child,GtkObj(child));
    return;
  }

  ErrOut("mgtk_box_pack_start?\n");
  mgtk_initchange(box);
  DoMethod(GtkObj(box),OM_ADDMEMBER,(LONG) GtkObj(child));
  mgtk_exitchange(box);

  return;
}


static void mgtk_box_pack_start_old(GtkBox *box, GtkWidget *child, gint expand, gint fill, gint padding ) {

  DebOut("mgtk_box_pack_start: box %lx, widget %lx begin\n",box,child);
  DebOut("  box is a   %s\n",g_type_name(G_OBJECT_TYPE (box)));
  DebOut("  child is a %s\n",g_type_name(G_OBJECT_TYPE (child)));

  DebOut("  box->MuiObject, child->MuiObject: %lx,%lx\n",GtkObj(box),GtkObj(child));

  /* expand: TRUE if the new child is to be given extra space 
             allocated to box. The extra space will be divided 
             evenly between all children of box that use this option.  
     fill.:  TRUE if space given to child by the expand option is 
             actually allocated to child, rather than just padding it. 
             This parameter has no effect if expand is set to FALSE. 
             A child is always allocated the full height of a GtkHBox 
             and the full width of a GtkVBox. 
             This option affects the other dimension.
     padding.: extra space in pixels to put between this child 
             and its neighbors, over and above the global amount 
             specified by spacing in GtkBox-struct. If child is a 
             widget at one of the reference ends of box, then 
             padding pixels are also put between child and the 
             reference edge of box.
  */

DebOut("==1=\n");
#if 0
  if(fill || expand) {
    set(GtkObj(child),MA_Group_Fill,(LONG) TRUE);
  }
  else {
    set(GtkObj(child),MA_Group_Fill,(LONG) FALSE);
  }
#endif

DebOut("==2==\n");
  //if(GTK_WIDGET_VISIBLE(child)) {
      DoMethod(GtkObj(box),MUIM_Group_InitChange);
  //}
  //else {
    //DebOut("  child is !GTK_WIDGET_VISIBLE, no group_init/exit change\n");
  //}

DebOut("==2a==\n");
  if(GtkObj(child)) {
    DoMethod(GtkObj(box),OM_ADDMEMBER,(LONG) GtkObj(child));
  }
  else {
    ErrOut("Cannot add something (%s) without MUI Object: %lx\n",g_type_name(G_OBJECT_TYPE (child)),child);
  }

DebOut("==3==\n");
  /* if we are not yet visible, this will lead to a deadlock..!(?)*/
  //if(GTK_WIDGET_VISIBLE(child)) {
    DoMethod(GtkObj(box),MUIM_Group_ExitChange);
  //}
DebOut("====\n");
  DebOut("  child is still a %s\n",g_type_name(G_OBJECT_TYPE (child)));
  DebOut("mgtk_box_pack_start: box %lx, widget %lx end\n",box,child);
  return;
}
#endif

void gtk_box_pack_start (GtkBox    *box,
		    GtkWidget *child,
		    gboolean   expand,
		    gboolean   fill,
		    guint      padding) {

  GtkBoxChild *child_info;

  DebOut("gtk_box_pack_start(%lx,%lx,..)\n",box,child);

  g_return_if_fail (GTK_IS_BOX (box));
  g_return_if_fail (GTK_IS_WIDGET (child));

  DebOut("  box is a   %s\n",g_type_name(G_OBJECT_TYPE (box)));
  DebOut("  child is a %s\n",g_type_name(G_OBJECT_TYPE (child)));

  g_return_if_fail (child->parent == NULL);    

#if 0
  if((GTK_MUI(box)->MuiObject) && (GTK_MUI(child)->MuiObject)) {
    if(!GTK_IS_BOX (box)) {
      WarnOut("gtk_box_pack_start called on a non-box: %lx is a %s\n",box,g_type_name(G_OBJECT_TYPE (box)));
      /* g_return_if_fail (GTK_IS_BOX (box));*/
    }
    g_return_if_fail (GTK_IS_WIDGET (child));
  }
  g_return_if_fail (child->parent == NULL);
#endif


  child_info = g_new (GtkBoxChild, 1);
  child_info->widget = child;
  child_info->padding = padding;
  child_info->expand = expand ? TRUE : FALSE;
  child_info->fill = fill ? TRUE : FALSE;
  child_info->pack = GTK_PACK_START;
  child_info->is_secondary = FALSE;

  box->children = g_list_append (box->children, child_info);

#if 0
  gtk_widget_freeze_child_notify (child);
#endif

  gtk_widget_set_parent (child, GTK_WIDGET (box));
  
#if 0
  gtk_widget_child_notify (child, "expand");
  gtk_widget_child_notify (child, "fill");
  gtk_widget_child_notify (child, "padding");
  gtk_widget_child_notify (child, "pack_type");
  gtk_widget_child_notify (child, "position");
  gtk_widget_thaw_child_notify (child);
#endif

#if 0
  mgtk_box_pack_start(box,child,expand,fill,padding);
#endif
  mgtk_add(GTK_MUI(box),GTK_MUI(child));
}

void
gtk_box_pack_end (GtkBox    *box,
		  GtkWidget *child,
		  gboolean   expand,
		  gboolean   fill,
		  guint      padding)
{
  GtkBoxChild *child_info;

  DebOut("gtk_box_pack_end(%lx,%lx..)\n",box,child);

  if(!GTK_IS_BOX (box)) {
    WarnOut("gtk_box_pack_end called on a non-box: %lx is a %s\n",box,g_type_name(G_OBJECT_TYPE (box)));
      /* g_return_if_fail (GTK_IS_BOX (box));*/
  }
  g_return_if_fail (GTK_IS_WIDGET (child));
  g_return_if_fail (child->parent == NULL);

  child_info = g_new (GtkBoxChild, 1);
  child_info->widget = child;
  child_info->padding = padding;
  child_info->expand = expand ? TRUE : FALSE;
  child_info->fill = fill ? TRUE : FALSE;
  child_info->pack = GTK_PACK_END;
  child_info->is_secondary = FALSE;

  box->children = g_list_append (box->children, child_info);

#if 0
  gtk_widget_freeze_child_notify (child);
#endif

  if((GTK_MUI(box)->MuiObject) && (GTK_MUI(child)->MuiObject)) {
    gtk_widget_set_parent (child, GTK_WIDGET (box));
  }

#if 0
  gtk_widget_child_notify (child, "expand");
  gtk_widget_child_notify (child, "fill");
  gtk_widget_child_notify (child, "padding");
  gtk_widget_child_notify (child, "pack_type");
  gtk_widget_child_notify (child, "position");
  gtk_widget_thaw_child_notify (child);
#endif

#warning gtk_box_pack_end just calls mgtk_box_pack_start

  WarnOut("gtk_box_pack_end just calls mgtk_box_pack_start\n");

/*
  mgtk_box_pack_start(box,child,expand,fill,padding);
  */

  mgtk_add(GTK_MUI(box),GTK_MUI(child));

}

void
gtk_box_pack_start_defaults (GtkBox    *box,
			     GtkWidget *child)
{
  gtk_box_pack_start (box, child, TRUE, TRUE, 0);
}

void
gtk_box_pack_end_defaults (GtkBox    *box,
			   GtkWidget *child)
{
  gtk_box_pack_end (box, child, TRUE, TRUE, 0);
}

void
gtk_box_set_homogeneous (GtkBox  *box,
			 gboolean homogeneous)
{
  g_return_if_fail (GTK_IS_BOX (box));

  if ((homogeneous ? TRUE : FALSE) != box->homogeneous)
    {
      box->homogeneous = homogeneous ? TRUE : FALSE;
      g_object_notify (G_OBJECT (box), "homogeneous");
      gtk_widget_queue_resize (GTK_WIDGET (box));
    }
}

/**
 * gtk_box_get_homogeneous:
 * @box: a #GtkBox
 *
 * Returns whether the box is homogeneous (all children are the
 * same size). See gtk_box_set_homogeneous ().
 *
 * Return value: %TRUE if the box is homogeneous.
 **/
gboolean
gtk_box_get_homogeneous (GtkBox *box)
{
  g_return_val_if_fail (GTK_IS_BOX (box), FALSE);

  return box->homogeneous;
}

void
gtk_box_set_spacing (GtkBox *box,
		     gint    spacing)
{
  g_return_if_fail (GTK_IS_BOX (box));

  if (spacing != box->spacing)
    {
      box->spacing = spacing;
      g_object_notify (G_OBJECT (box), "spacing");
      gtk_widget_queue_resize (GTK_WIDGET (box));
    }
}

/**
 * gtk_box_get_spacing:
 * @box: a #GtkBox
 * 
 * Gets the value set by gtk_box_set_spacing().
 * 
 * Return value: spacing between children
 **/
gint
gtk_box_get_spacing (GtkBox *box)
{
  g_return_val_if_fail (GTK_IS_BOX (box), 0);

  return box->spacing;
}

void
gtk_box_reorder_child (GtkBox    *box,
		       GtkWidget *child,
		       gint       position)
{
  GList *old_link;
  GList *new_link;
  GtkBoxChild *child_info = NULL;
  gint old_position;

  g_return_if_fail (GTK_IS_BOX (box));
  g_return_if_fail (GTK_IS_WIDGET (child));

  old_link = box->children;
  old_position = 0;
  while (old_link)
    {
      child_info = old_link->data;
      if (child_info->widget == child)
	break;

      old_link = old_link->next;
      old_position++;
    }

  g_return_if_fail (old_link != NULL);

  if (position == old_position)
    return;

  box->children = g_list_delete_link (box->children, old_link);

  if (position < 0)
    new_link = NULL;
  else
    new_link = g_list_nth (box->children, position);

  box->children = g_list_insert_before (box->children, new_link, child_info);

#if 0
  gtk_widget_child_notify (child, "position");
#endif
  if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
    gtk_widget_queue_resize (child);
}

void
gtk_box_query_child_packing (GtkBox             *box,
			     GtkWidget          *child,
			     gboolean           *expand,
			     gboolean           *fill,
			     guint              *padding,
			     GtkPackType        *pack_type)
{
  GList *list;
  GtkBoxChild *child_info = NULL;

  g_return_if_fail (GTK_IS_BOX (box));
  g_return_if_fail (GTK_IS_WIDGET (child));

  list = box->children;
  while (list)
    {
      child_info = list->data;
      if (child_info->widget == child)
	break;

      list = list->next;
    }

  if (list)
    {
      if (expand)
	*expand = child_info->expand;
      if (fill)
	*fill = child_info->fill;
      if (padding)
	*padding = child_info->padding;
      if (pack_type)
	*pack_type = child_info->pack;
    }
}

void
gtk_box_set_child_packing (GtkBox               *box,
			   GtkWidget            *child,
			   gboolean              expand,
			   gboolean              fill,
			   guint                 padding,
			   GtkPackType           pack_type)
{
  GList *list;
  GtkBoxChild *child_info = NULL;

  g_return_if_fail (GTK_IS_BOX (box));
  g_return_if_fail (GTK_IS_WIDGET (child));

  list = box->children;
  while (list)
    {
      child_info = list->data;
      if (child_info->widget == child)
	break;

      list = list->next;
    }

#if 0
  gtk_widget_freeze_child_notify (child);
#endif

  if (list) {
      child_info->expand = expand != FALSE;
#if 0
      gtk_widget_child_notify (child, "expand");
#endif
      child_info->fill = fill != FALSE;
#if 0
      gtk_widget_child_notify (child, "fill");
#endif
      child_info->padding = padding;
#if 0
      gtk_widget_child_notify (child, "padding");
#endif
      if (pack_type == GTK_PACK_END)
        child_info->pack = GTK_PACK_END;
      else
        child_info->pack = GTK_PACK_START;
#if 0
      gtk_widget_child_notify (child, "pack_type");
#endif

      if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (box))
	gtk_widget_queue_resize (child);
    }
#if 0
  gtk_widget_thaw_child_notify (child);
#endif
}

static void
gtk_box_add (GtkContainer *container,
	     GtkWidget    *widget)
{
  gtk_box_pack_start_defaults (GTK_BOX (container), widget);
}

static void
gtk_box_remove (GtkContainer *container,
		GtkWidget    *widget)
{
  GtkBox *box;
  GtkBoxChild *child;
  GList *children;

  box = GTK_BOX (container);

  children = box->children;
  while (children)
    {
      child = children->data;

      if (child->widget == widget)
	{
	  gboolean was_visible;

	  was_visible = GTK_WIDGET_VISIBLE (widget);
#if 0
	  gtk_widget_unparent (widget);
#endif

	  box->children = g_list_remove_link (box->children, children);
	  g_list_free (children);
	  g_free (child);

	  /* queue resize regardless of GTK_WIDGET_VISIBLE (container),
	   * since that's what is needed by toplevels.
	   */
	  if (was_visible)
	    gtk_widget_queue_resize (GTK_WIDGET (container));

	  break;
	}

      children = children->next;
    }
}

static void
gtk_box_forall (GtkContainer *container,
		gboolean      include_internals,
		GtkCallback   callback,
		gpointer      callback_data)
{
  GtkBox *box;
  GtkBoxChild *child;
  GList *children;

  g_return_if_fail (callback != NULL);

  box = GTK_BOX (container);

  children = box->children;
  while (children)
    {
      child = children->data;
      children = children->next;

      if (child->pack == GTK_PACK_START)
	(* callback) (child->widget, callback_data);
    }

  children = g_list_last (box->children);
  while (children)
    {
      child = children->data;
      children = children->prev;

      if (child->pack == GTK_PACK_END)
	(* callback) (child->widget, callback_data);
    }
}

#define __GTK_BOX_C__
