]> Pileus Git - ~andy/gtk/blob - gtk/gtktable.c
applied patch from Andreas Persenius <ndap@swipnet.se> that updates the
[~andy/gtk] / gtk / gtktable.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gtktable.h"
28
29 enum
30 {
31   ARG_0,
32   ARG_N_ROWS,
33   ARG_N_COLUMNS,
34   ARG_COLUMN_SPACING,
35   ARG_ROW_SPACING,
36   ARG_HOMOGENEOUS
37 };
38
39 enum
40 {
41   CHILD_ARG_0,
42   CHILD_ARG_LEFT_ATTACH,
43   CHILD_ARG_RIGHT_ATTACH,
44   CHILD_ARG_TOP_ATTACH,
45   CHILD_ARG_BOTTOM_ATTACH,
46   CHILD_ARG_X_OPTIONS,
47   CHILD_ARG_Y_OPTIONS,
48   CHILD_ARG_X_PADDING,
49   CHILD_ARG_Y_PADDING
50 };
51   
52
53 static void gtk_table_class_init    (GtkTableClass  *klass);
54 static void gtk_table_init          (GtkTable       *table);
55 static void gtk_table_finalize      (GObject        *object);
56 static void gtk_table_map           (GtkWidget      *widget);
57 static void gtk_table_unmap         (GtkWidget      *widget);
58 static void gtk_table_draw          (GtkWidget      *widget,
59                                      GdkRectangle   *area);
60 static gint gtk_table_expose        (GtkWidget      *widget,
61                                      GdkEventExpose *event);
62 static void gtk_table_size_request  (GtkWidget      *widget,
63                                      GtkRequisition *requisition);
64 static void gtk_table_size_allocate (GtkWidget      *widget,
65                                      GtkAllocation  *allocation);
66 static void gtk_table_add           (GtkContainer   *container,
67                                      GtkWidget      *widget);
68 static void gtk_table_remove        (GtkContainer   *container,
69                                      GtkWidget      *widget);
70 static void gtk_table_forall        (GtkContainer   *container,
71                                      gboolean        include_internals,
72                                      GtkCallback     callback,
73                                      gpointer        callback_data);
74 static void gtk_table_get_arg       (GtkObject      *object,
75                                      GtkArg         *arg,
76                                      guint           arg_id);
77 static void gtk_table_set_arg       (GtkObject      *object,
78                                      GtkArg         *arg,
79                                      guint           arg_id);
80 static void gtk_table_set_child_arg (GtkContainer   *container,
81                                      GtkWidget      *child,
82                                      GtkArg         *arg,
83                                      guint           arg_id);
84 static void gtk_table_get_child_arg (GtkContainer   *container,
85                                      GtkWidget      *child,
86                                      GtkArg         *arg,
87                                      guint           arg_id);
88 static GtkType gtk_table_child_type (GtkContainer   *container);
89
90
91 static void gtk_table_size_request_init  (GtkTable *table);
92 static void gtk_table_size_request_pass1 (GtkTable *table);
93 static void gtk_table_size_request_pass2 (GtkTable *table);
94 static void gtk_table_size_request_pass3 (GtkTable *table);
95
96 static void gtk_table_size_allocate_init  (GtkTable *table);
97 static void gtk_table_size_allocate_pass1 (GtkTable *table);
98 static void gtk_table_size_allocate_pass2 (GtkTable *table);
99
100
101 static GtkContainerClass *parent_class = NULL;
102
103
104 GtkType
105 gtk_table_get_type (void)
106 {
107   static GtkType table_type = 0;
108   
109   if (!table_type)
110     {
111       static const GtkTypeInfo table_info =
112       {
113         "GtkTable",
114         sizeof (GtkTable),
115         sizeof (GtkTableClass),
116         (GtkClassInitFunc) gtk_table_class_init,
117         (GtkObjectInitFunc) gtk_table_init,
118         /* reserved_1 */ NULL,
119         /* reserved_2 */ NULL,
120         (GtkClassInitFunc) NULL,
121       };
122       
123       table_type = gtk_type_unique (gtk_container_get_type (), &table_info);
124     }
125   
126   return table_type;
127 }
128
129 static void
130 gtk_table_class_init (GtkTableClass *class)
131 {
132   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
133   GtkObjectClass *object_class;
134   GtkWidgetClass *widget_class;
135   GtkContainerClass *container_class;
136   
137   object_class = (GtkObjectClass*) class;
138   widget_class = (GtkWidgetClass*) class;
139   container_class = (GtkContainerClass*) class;
140   
141   parent_class = gtk_type_class (gtk_container_get_type ());
142
143   gobject_class->finalize = gtk_table_finalize;
144
145   object_class->get_arg = gtk_table_get_arg;
146   object_class->set_arg = gtk_table_set_arg;
147   
148   widget_class->map = gtk_table_map;
149   widget_class->unmap = gtk_table_unmap;
150   widget_class->draw = gtk_table_draw;
151   widget_class->expose_event = gtk_table_expose;
152   widget_class->size_request = gtk_table_size_request;
153   widget_class->size_allocate = gtk_table_size_allocate;
154   
155   container_class->add = gtk_table_add;
156   container_class->remove = gtk_table_remove;
157   container_class->forall = gtk_table_forall;
158   container_class->child_type = gtk_table_child_type;
159   container_class->set_child_arg = gtk_table_set_child_arg;
160   container_class->get_child_arg = gtk_table_get_child_arg;
161   
162   gtk_object_add_arg_type ("GtkTable::n_rows", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_N_ROWS);
163   gtk_object_add_arg_type ("GtkTable::n_columns", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_N_COLUMNS);
164   gtk_object_add_arg_type ("GtkTable::row_spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_ROW_SPACING);
165   gtk_object_add_arg_type ("GtkTable::column_spacing", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_COLUMN_SPACING);
166   gtk_object_add_arg_type ("GtkTable::homogeneous", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HOMOGENEOUS);
167   gtk_container_add_child_arg_type ("GtkTable::left_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_LEFT_ATTACH);
168   gtk_container_add_child_arg_type ("GtkTable::right_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_RIGHT_ATTACH);
169   gtk_container_add_child_arg_type ("GtkTable::top_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_TOP_ATTACH);
170   gtk_container_add_child_arg_type ("GtkTable::bottom_attach", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_BOTTOM_ATTACH);
171   gtk_container_add_child_arg_type ("GtkTable::x_options", GTK_TYPE_ATTACH_OPTIONS, GTK_ARG_READWRITE, CHILD_ARG_X_OPTIONS);
172   gtk_container_add_child_arg_type ("GtkTable::y_options", GTK_TYPE_ATTACH_OPTIONS, GTK_ARG_READWRITE, CHILD_ARG_Y_OPTIONS);
173   gtk_container_add_child_arg_type ("GtkTable::x_padding", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_X_PADDING);
174   gtk_container_add_child_arg_type ("GtkTable::y_padding", GTK_TYPE_UINT, GTK_ARG_READWRITE, CHILD_ARG_Y_PADDING);
175 }
176
177 static GtkType
178 gtk_table_child_type (GtkContainer   *container)
179 {
180   return GTK_TYPE_WIDGET;
181 }
182
183 static void
184 gtk_table_get_arg (GtkObject      *object,
185                    GtkArg         *arg,
186                    guint           arg_id)
187 {
188   GtkTable *table;
189
190   table = GTK_TABLE (object);
191
192   switch (arg_id)
193     {
194     case ARG_N_ROWS:
195       GTK_VALUE_UINT (*arg) = table->nrows;
196       break;
197     case ARG_N_COLUMNS:
198       GTK_VALUE_UINT (*arg) = table->ncols;
199       break;
200     case ARG_ROW_SPACING:
201       GTK_VALUE_UINT (*arg) = table->row_spacing;
202       break;
203     case ARG_COLUMN_SPACING:
204       GTK_VALUE_UINT (*arg) = table->column_spacing;
205       break;
206     case ARG_HOMOGENEOUS:
207       GTK_VALUE_BOOL (*arg) = table->homogeneous;
208       break;
209     default:
210       arg->type = GTK_TYPE_INVALID;
211       break;
212     }
213 }
214
215 static void
216 gtk_table_set_arg (GtkObject      *object,
217                    GtkArg         *arg,
218                    guint           arg_id)
219 {
220   GtkTable *table;
221
222   table = GTK_TABLE (object);
223
224   switch (arg_id)
225     {
226     case ARG_N_ROWS:
227       gtk_table_resize (table, GTK_VALUE_UINT (*arg), table->ncols);
228       break;
229     case ARG_N_COLUMNS:
230       gtk_table_resize (table, table->nrows, GTK_VALUE_UINT (*arg));
231       break;
232     case ARG_ROW_SPACING:
233       gtk_table_set_row_spacings (table, GTK_VALUE_UINT (*arg));
234       break;
235     case ARG_COLUMN_SPACING:
236       gtk_table_set_col_spacings (table, GTK_VALUE_UINT (*arg));
237       break;
238     case ARG_HOMOGENEOUS:
239       gtk_table_set_homogeneous (table, GTK_VALUE_BOOL (*arg));
240       break;
241     default:
242       break;
243     }
244 }
245
246 static void
247 gtk_table_set_child_arg (GtkContainer   *container,
248                          GtkWidget      *child,
249                          GtkArg         *arg,
250                          guint           arg_id)
251 {
252   GtkTable *table;
253   GtkTableChild *table_child;
254   GList *list;
255
256   table = GTK_TABLE (container);
257   table_child = NULL;
258   for (list = table->children; list; list = list->next)
259     {
260       table_child = list->data;
261
262       if (table_child->widget == child)
263         break;
264     }
265   if (!list)
266     return;
267
268   switch (arg_id)
269     {
270     case CHILD_ARG_LEFT_ATTACH:
271       table_child->left_attach = GTK_VALUE_UINT (*arg);
272       if (table_child->right_attach <= table_child->left_attach)
273         table_child->right_attach = table_child->left_attach + 1;
274       if (table_child->right_attach >= table->ncols)
275         gtk_table_resize (table, table->ncols, table_child->right_attach);
276       break;
277     case CHILD_ARG_RIGHT_ATTACH:
278       if (GTK_VALUE_UINT (*arg) > 0)
279         {
280           table_child->right_attach = GTK_VALUE_UINT (*arg);
281           if (table_child->right_attach <= table_child->left_attach)
282             table_child->left_attach = table_child->right_attach - 1;
283           if (table_child->right_attach >= table->ncols)
284             gtk_table_resize (table, table->ncols, table_child->right_attach);
285         }
286       break;
287     case CHILD_ARG_TOP_ATTACH:
288       table_child->top_attach = GTK_VALUE_UINT (*arg);
289       if (table_child->bottom_attach <= table_child->top_attach)
290         table_child->bottom_attach = table_child->top_attach + 1;
291       if (table_child->bottom_attach >= table->nrows)
292         gtk_table_resize (table, table_child->bottom_attach, table->ncols);
293       break;
294     case CHILD_ARG_BOTTOM_ATTACH:
295       if (GTK_VALUE_UINT (*arg) > 0)
296         {
297           table_child->bottom_attach = GTK_VALUE_UINT (*arg);
298           if (table_child->bottom_attach <= table_child->top_attach)
299             table_child->top_attach = table_child->bottom_attach - 1;
300           if (table_child->bottom_attach >= table->nrows)
301             gtk_table_resize (table, table_child->bottom_attach, table->ncols);
302         }
303       break;
304     case CHILD_ARG_X_OPTIONS:
305       table_child->xexpand = (GTK_VALUE_FLAGS (*arg) & GTK_EXPAND) != 0;
306       table_child->xshrink = (GTK_VALUE_FLAGS (*arg) & GTK_SHRINK) != 0;
307       table_child->xfill = (GTK_VALUE_FLAGS (*arg) & GTK_FILL) != 0;
308       break;
309     case CHILD_ARG_Y_OPTIONS:
310       table_child->yexpand = (GTK_VALUE_FLAGS (*arg) & GTK_EXPAND) != 0;
311       table_child->yshrink = (GTK_VALUE_FLAGS (*arg) & GTK_SHRINK) != 0;
312       table_child->yfill = (GTK_VALUE_FLAGS (*arg) & GTK_FILL) != 0;
313       break;
314     case CHILD_ARG_X_PADDING:
315       table_child->xpadding = GTK_VALUE_UINT (*arg);
316       break;
317     case CHILD_ARG_Y_PADDING:
318       table_child->ypadding = GTK_VALUE_UINT (*arg);
319       break;
320     default:
321       break;
322     }
323   if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (table))
324     gtk_widget_queue_resize (child);
325 }
326
327 static void
328 gtk_table_get_child_arg (GtkContainer   *container,
329                          GtkWidget      *child,
330                          GtkArg         *arg,
331                          guint           arg_id)
332 {
333   GtkTable *table;
334   GtkTableChild *table_child;
335   GList *list;
336
337   table = GTK_TABLE (container);
338   table_child = NULL;
339   for (list = table->children; list; list = list->next)
340     {
341       table_child = list->data;
342
343       if (table_child->widget == child)
344         break;
345     }
346   if (!list)
347     return;
348
349   switch (arg_id)
350     {
351     case CHILD_ARG_LEFT_ATTACH:
352       GTK_VALUE_UINT (*arg) = table_child->left_attach;
353       break;
354     case CHILD_ARG_RIGHT_ATTACH:
355       GTK_VALUE_UINT (*arg) = table_child->right_attach;
356       break;
357     case CHILD_ARG_TOP_ATTACH:
358       GTK_VALUE_UINT (*arg) = table_child->top_attach;
359       break;
360     case CHILD_ARG_BOTTOM_ATTACH:
361       GTK_VALUE_UINT (*arg) = table_child->bottom_attach;
362       break;
363     case CHILD_ARG_X_OPTIONS:
364       GTK_VALUE_FLAGS (*arg) = (table_child->xexpand * GTK_EXPAND |
365                                 table_child->xshrink * GTK_SHRINK |
366                                 table_child->xfill * GTK_FILL);
367       break;
368     case CHILD_ARG_Y_OPTIONS:
369       GTK_VALUE_FLAGS (*arg) = (table_child->yexpand * GTK_EXPAND |
370                                 table_child->yshrink * GTK_SHRINK |
371                                 table_child->yfill * GTK_FILL);
372       break;
373     case CHILD_ARG_X_PADDING:
374       GTK_VALUE_UINT (*arg) = table_child->xpadding;
375       break;
376     case CHILD_ARG_Y_PADDING:
377       GTK_VALUE_UINT (*arg) = table_child->ypadding;
378       break;
379     default:
380       arg->type = GTK_TYPE_INVALID;
381       break;
382     }
383 }
384
385 static void
386 gtk_table_init (GtkTable *table)
387 {
388   GTK_WIDGET_SET_FLAGS (table, GTK_NO_WINDOW);
389   
390   table->children = NULL;
391   table->rows = NULL;
392   table->cols = NULL;
393   table->nrows = 0;
394   table->ncols = 0;
395   table->column_spacing = 0;
396   table->row_spacing = 0;
397   table->homogeneous = FALSE;
398
399   gtk_table_resize (table, 1, 1);
400 }
401
402 GtkWidget*
403 gtk_table_new (guint    rows,
404                guint    columns,
405                gboolean homogeneous)
406 {
407   GtkTable *table;
408
409   if (rows == 0)
410           rows = 1;
411   if (columns == 0)
412           columns = 1;
413   
414   table = gtk_type_new (gtk_table_get_type ());
415   
416   table->homogeneous = (homogeneous ? TRUE : FALSE);
417
418   gtk_table_resize (table, rows, columns);
419   
420   return GTK_WIDGET (table);
421 }
422
423 void
424 gtk_table_resize (GtkTable *table,
425                   guint     n_rows,
426                   guint     n_cols)
427 {
428   g_return_if_fail (table != NULL);
429   g_return_if_fail (GTK_IS_TABLE (table));
430
431   n_rows = MAX (n_rows, 1);
432   n_cols = MAX (n_cols, 1);
433   
434   if (n_rows != table->nrows ||
435       n_cols != table->ncols)
436     {
437       GList *list;
438       
439       for (list = table->children; list; list = list->next)
440         {
441           GtkTableChild *child;
442           
443           child = list->data;
444           
445           n_rows = MAX (n_rows, child->bottom_attach);
446           n_cols = MAX (n_cols, child->right_attach);
447         }
448       
449       if (n_rows != table->nrows)
450         {
451           guint i;
452
453           i = table->nrows;
454           table->nrows = n_rows;
455           table->rows = g_realloc (table->rows, table->nrows * sizeof (GtkTableRowCol));
456           
457           for (; i < table->nrows; i++)
458             {
459               table->rows[i].requisition = 0;
460               table->rows[i].allocation = 0;
461               table->rows[i].spacing = table->row_spacing;
462               table->rows[i].need_expand = 0;
463               table->rows[i].need_shrink = 0;
464               table->rows[i].expand = 0;
465               table->rows[i].shrink = 0;
466             }
467         }
468
469       if (n_cols != table->ncols)
470         {
471           guint i;
472
473           i = table->ncols;
474           table->ncols = n_cols;
475           table->cols = g_realloc (table->cols, table->ncols * sizeof (GtkTableRowCol));
476           
477           for (; i < table->ncols; i++)
478             {
479               table->cols[i].requisition = 0;
480               table->cols[i].allocation = 0;
481               table->cols[i].spacing = table->column_spacing;
482               table->cols[i].need_expand = 0;
483               table->cols[i].need_shrink = 0;
484               table->cols[i].expand = 0;
485               table->cols[i].shrink = 0;
486             }
487         }
488     }
489 }
490
491 void
492 gtk_table_attach (GtkTable        *table,
493                   GtkWidget       *child,
494                   guint            left_attach,
495                   guint            right_attach,
496                   guint            top_attach,
497                   guint            bottom_attach,
498                   GtkAttachOptions xoptions,
499                   GtkAttachOptions yoptions,
500                   guint            xpadding,
501                   guint            ypadding)
502 {
503   GtkTableChild *table_child;
504   
505   g_return_if_fail (table != NULL);
506   g_return_if_fail (GTK_IS_TABLE (table));
507   g_return_if_fail (child != NULL);
508   g_return_if_fail (GTK_IS_WIDGET (child));
509   g_return_if_fail (child->parent == NULL);
510   
511   /* g_return_if_fail (left_attach >= 0); */
512   g_return_if_fail (left_attach < right_attach);
513   /* g_return_if_fail (top_attach >= 0); */
514   g_return_if_fail (top_attach < bottom_attach);
515   
516   if (right_attach >= table->ncols)
517     gtk_table_resize (table, table->nrows, right_attach);
518   
519   if (bottom_attach >= table->nrows)
520     gtk_table_resize (table, bottom_attach, table->ncols);
521   
522   table_child = g_new (GtkTableChild, 1);
523   table_child->widget = child;
524   table_child->left_attach = left_attach;
525   table_child->right_attach = right_attach;
526   table_child->top_attach = top_attach;
527   table_child->bottom_attach = bottom_attach;
528   table_child->xexpand = (xoptions & GTK_EXPAND) != 0;
529   table_child->xshrink = (xoptions & GTK_SHRINK) != 0;
530   table_child->xfill = (xoptions & GTK_FILL) != 0;
531   table_child->xpadding = xpadding;
532   table_child->yexpand = (yoptions & GTK_EXPAND) != 0;
533   table_child->yshrink = (yoptions & GTK_SHRINK) != 0;
534   table_child->yfill = (yoptions & GTK_FILL) != 0;
535   table_child->ypadding = ypadding;
536   
537   table->children = g_list_prepend (table->children, table_child);
538   
539   gtk_widget_set_parent (child, GTK_WIDGET (table));
540   
541   if (GTK_WIDGET_REALIZED (child->parent))
542     gtk_widget_realize (child);
543
544   if (GTK_WIDGET_VISIBLE (child->parent) && GTK_WIDGET_VISIBLE (child))
545     {
546       if (GTK_WIDGET_MAPPED (child->parent))
547         gtk_widget_map (child);
548
549       gtk_widget_queue_resize (child);
550     }
551 }
552
553 void
554 gtk_table_attach_defaults (GtkTable  *table,
555                            GtkWidget *widget,
556                            guint      left_attach,
557                            guint      right_attach,
558                            guint      top_attach,
559                            guint      bottom_attach)
560 {
561   gtk_table_attach (table, widget,
562                     left_attach, right_attach,
563                     top_attach, bottom_attach,
564                     GTK_EXPAND | GTK_FILL,
565                     GTK_EXPAND | GTK_FILL,
566                     0, 0);
567 }
568
569 void
570 gtk_table_set_row_spacing (GtkTable *table,
571                            guint     row,
572                            guint     spacing)
573 {
574   g_return_if_fail (table != NULL);
575   g_return_if_fail (GTK_IS_TABLE (table));
576   g_return_if_fail (row + 1 < table->nrows);
577   
578   if (table->rows[row].spacing != spacing)
579     {
580       table->rows[row].spacing = spacing;
581       
582       if (GTK_WIDGET_VISIBLE (table))
583         gtk_widget_queue_resize (GTK_WIDGET (table));
584     }
585 }
586
587 void
588 gtk_table_set_col_spacing (GtkTable *table,
589                            guint     column,
590                            guint     spacing)
591 {
592   g_return_if_fail (table != NULL);
593   g_return_if_fail (GTK_IS_TABLE (table));
594   g_return_if_fail (column + 1 < table->ncols);
595   
596   if (table->cols[column].spacing != spacing)
597     {
598       table->cols[column].spacing = spacing;
599       
600       if (GTK_WIDGET_VISIBLE (table))
601         gtk_widget_queue_resize (GTK_WIDGET (table));
602     }
603 }
604
605 void
606 gtk_table_set_row_spacings (GtkTable *table,
607                             guint     spacing)
608 {
609   guint row;
610   
611   g_return_if_fail (table != NULL);
612   g_return_if_fail (GTK_IS_TABLE (table));
613   
614   table->row_spacing = spacing;
615   for (row = 0; row + 1 < table->nrows; row++)
616     table->rows[row].spacing = spacing;
617   
618   if (GTK_WIDGET_VISIBLE (table))
619     gtk_widget_queue_resize (GTK_WIDGET (table));
620 }
621
622 void
623 gtk_table_set_col_spacings (GtkTable *table,
624                             guint     spacing)
625 {
626   guint col;
627   
628   g_return_if_fail (table != NULL);
629   g_return_if_fail (GTK_IS_TABLE (table));
630   
631   table->column_spacing = spacing;
632   for (col = 0; col + 1 < table->ncols; col++)
633     table->cols[col].spacing = spacing;
634   
635   if (GTK_WIDGET_VISIBLE (table))
636     gtk_widget_queue_resize (GTK_WIDGET (table));
637 }
638
639 void
640 gtk_table_set_homogeneous (GtkTable *table,
641                            gboolean  homogeneous)
642 {
643   g_return_if_fail (table != NULL);
644   g_return_if_fail (GTK_IS_TABLE (table));
645
646   homogeneous = (homogeneous != 0);
647   if (homogeneous != table->homogeneous)
648     {
649       table->homogeneous = homogeneous;
650       
651       if (GTK_WIDGET_VISIBLE (table))
652         gtk_widget_queue_resize (GTK_WIDGET (table));
653     }
654 }
655
656 static void
657 gtk_table_finalize (GObject *object)
658 {
659   GtkTable *table;
660   
661   g_return_if_fail (GTK_IS_TABLE (object));
662   
663   table = GTK_TABLE (object);
664   
665   g_free (table->rows);
666   g_free (table->cols);
667   
668   G_OBJECT_CLASS (parent_class)->finalize (object);
669 }
670
671 static void
672 gtk_table_map (GtkWidget *widget)
673 {
674   GtkTable *table;
675   GtkTableChild *child;
676   GList *children;
677   
678   g_return_if_fail (widget != NULL);
679   g_return_if_fail (GTK_IS_TABLE (widget));
680   
681   table = GTK_TABLE (widget);
682   GTK_WIDGET_SET_FLAGS (table, GTK_MAPPED);
683   
684   children = table->children;
685   while (children)
686     {
687       child = children->data;
688       children = children->next;
689       
690       if (GTK_WIDGET_VISIBLE (child->widget) &&
691           !GTK_WIDGET_MAPPED (child->widget))
692         gtk_widget_map (child->widget);
693     }
694 }
695
696 static void
697 gtk_table_unmap (GtkWidget *widget)
698 {
699   GtkTable *table;
700   GtkTableChild *child;
701   GList *children;
702   
703   g_return_if_fail (widget != NULL);
704   g_return_if_fail (GTK_IS_TABLE (widget));
705   
706   table = GTK_TABLE (widget);
707   GTK_WIDGET_UNSET_FLAGS (table, GTK_MAPPED);
708   
709   children = table->children;
710   while (children)
711     {
712       child = children->data;
713       children = children->next;
714       
715       if (GTK_WIDGET_VISIBLE (child->widget) &&
716           GTK_WIDGET_MAPPED (child->widget))
717         gtk_widget_unmap (child->widget);
718     }
719 }
720
721 static void
722 gtk_table_draw (GtkWidget    *widget,
723                 GdkRectangle *area)
724 {
725   GtkTable *table;
726   GtkTableChild *child;
727   GList *children;
728   GdkRectangle child_area;
729   
730   g_return_if_fail (widget != NULL);
731   g_return_if_fail (GTK_IS_TABLE (widget));
732   
733   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
734     {
735       table = GTK_TABLE (widget);
736       
737       children = table->children;
738       while (children)
739         {
740           child = children->data;
741           children = children->next;
742           
743           if (gtk_widget_intersect (child->widget, area, &child_area))
744             gtk_widget_draw (child->widget, &child_area);
745         }
746     }
747 }
748
749 static gint
750 gtk_table_expose (GtkWidget      *widget,
751                   GdkEventExpose *event)
752 {
753   GtkTable *table;
754   GtkTableChild *child;
755   GList *children;
756   GdkEventExpose child_event;
757   
758   g_return_val_if_fail (widget != NULL, FALSE);
759   g_return_val_if_fail (GTK_IS_TABLE (widget), FALSE);
760   
761   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
762     {
763       table = GTK_TABLE (widget);
764       
765       child_event = *event;
766       
767       children = table->children;
768       while (children)
769         {
770           child = children->data;
771           children = children->next;
772           
773           if (GTK_WIDGET_NO_WINDOW (child->widget) &&
774               gtk_widget_intersect (child->widget, &event->area, &child_event.area))
775             gtk_widget_event (child->widget, (GdkEvent*) &child_event);
776         }
777     }
778   
779   return FALSE;
780 }
781
782 static void
783 gtk_table_size_request (GtkWidget      *widget,
784                         GtkRequisition *requisition)
785 {
786   GtkTable *table;
787   gint row, col;
788   
789   g_return_if_fail (widget != NULL);
790   g_return_if_fail (GTK_IS_TABLE (widget));
791   g_return_if_fail (requisition != NULL);
792   
793   table = GTK_TABLE (widget);
794   
795   requisition->width = 0;
796   requisition->height = 0;
797   
798   gtk_table_size_request_init (table);
799   gtk_table_size_request_pass1 (table);
800   gtk_table_size_request_pass2 (table);
801   gtk_table_size_request_pass3 (table);
802   gtk_table_size_request_pass2 (table);
803   
804   for (col = 0; col < table->ncols; col++)
805     requisition->width += table->cols[col].requisition;
806   for (col = 0; col + 1 < table->ncols; col++)
807     requisition->width += table->cols[col].spacing;
808   
809   for (row = 0; row < table->nrows; row++)
810     requisition->height += table->rows[row].requisition;
811   for (row = 0; row + 1 < table->nrows; row++)
812     requisition->height += table->rows[row].spacing;
813   
814   requisition->width += GTK_CONTAINER (table)->border_width * 2;
815   requisition->height += GTK_CONTAINER (table)->border_width * 2;
816 }
817
818 static void
819 gtk_table_size_allocate (GtkWidget     *widget,
820                          GtkAllocation *allocation)
821 {
822   GtkTable *table;
823   
824   g_return_if_fail (widget != NULL);
825   g_return_if_fail (GTK_IS_TABLE (widget));
826   g_return_if_fail (allocation != NULL);
827   
828   widget->allocation = *allocation;
829   table = GTK_TABLE (widget);
830   
831   gtk_table_size_allocate_init (table);
832   gtk_table_size_allocate_pass1 (table);
833   gtk_table_size_allocate_pass2 (table);
834 }
835
836 static void
837 gtk_table_add (GtkContainer *container,
838                GtkWidget    *widget)
839 {
840   g_return_if_fail (container != NULL);
841   g_return_if_fail (GTK_IS_TABLE (container));
842   g_return_if_fail (widget != NULL);
843   
844   gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1);
845 }
846
847 static void
848 gtk_table_remove (GtkContainer *container,
849                   GtkWidget    *widget)
850 {
851   GtkTable *table;
852   GtkTableChild *child;
853   GList *children;
854   
855   g_return_if_fail (container != NULL);
856   g_return_if_fail (GTK_IS_TABLE (container));
857   g_return_if_fail (widget != NULL);
858   
859   table = GTK_TABLE (container);
860   children = table->children;
861   
862   while (children)
863     {
864       child = children->data;
865       children = children->next;
866       
867       if (child->widget == widget)
868         {
869           gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
870           
871           gtk_widget_unparent (widget);
872           
873           table->children = g_list_remove (table->children, child);
874           g_free (child);
875           
876           if (was_visible && GTK_WIDGET_VISIBLE (container))
877             gtk_container_queue_resize (container);
878           break;
879         }
880     }
881 }
882
883 static void
884 gtk_table_forall (GtkContainer *container,
885                   gboolean      include_internals,
886                   GtkCallback   callback,
887                   gpointer      callback_data)
888 {
889   GtkTable *table;
890   GtkTableChild *child;
891   GList *children;
892   
893   g_return_if_fail (container != NULL);
894   g_return_if_fail (GTK_IS_TABLE (container));
895   g_return_if_fail (callback != NULL);
896   
897   table = GTK_TABLE (container);
898   children = table->children;
899   
900   while (children)
901     {
902       child = children->data;
903       children = children->next;
904       
905       (* callback) (child->widget, callback_data);
906     }
907 }
908
909 static void
910 gtk_table_size_request_init (GtkTable *table)
911 {
912   GtkTableChild *child;
913   GList *children;
914   gint row, col;
915   
916   for (row = 0; row < table->nrows; row++)
917     table->rows[row].requisition = 0;
918   for (col = 0; col < table->ncols; col++)
919     table->cols[col].requisition = 0;
920   
921   children = table->children;
922   while (children)
923     {
924       child = children->data;
925       children = children->next;
926       
927       if (GTK_WIDGET_VISIBLE (child->widget))
928         gtk_widget_size_request (child->widget, NULL);
929     }
930 }
931
932 static void
933 gtk_table_size_request_pass1 (GtkTable *table)
934 {
935   GtkTableChild *child;
936   GList *children;
937   gint width;
938   gint height;
939   
940   children = table->children;
941   while (children)
942     {
943       child = children->data;
944       children = children->next;
945       
946       if (GTK_WIDGET_VISIBLE (child->widget))
947         {
948           GtkRequisition child_requisition;
949           gtk_widget_get_child_requisition (child->widget, &child_requisition);
950
951           /* Child spans a single column.
952            */
953           if (child->left_attach == (child->right_attach - 1))
954             {
955               width = child_requisition.width + child->xpadding * 2;
956               table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width);
957             }
958           
959           /* Child spans a single row.
960            */
961           if (child->top_attach == (child->bottom_attach - 1))
962             {
963               height = child_requisition.height + child->ypadding * 2;
964               table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height);
965             }
966         }
967     }
968 }
969
970 static void
971 gtk_table_size_request_pass2 (GtkTable *table)
972 {
973   gint max_width;
974   gint max_height;
975   gint row, col;
976   
977   if (table->homogeneous)
978     {
979       max_width = 0;
980       max_height = 0;
981       
982       for (col = 0; col < table->ncols; col++)
983         max_width = MAX (max_width, table->cols[col].requisition);
984       for (row = 0; row < table->nrows; row++)
985         max_height = MAX (max_height, table->rows[row].requisition);
986       
987       for (col = 0; col < table->ncols; col++)
988         table->cols[col].requisition = max_width;
989       for (row = 0; row < table->nrows; row++)
990         table->rows[row].requisition = max_height;
991     }
992 }
993
994 static void
995 gtk_table_size_request_pass3 (GtkTable *table)
996 {
997   GtkTableChild *child;
998   GList *children;
999   gint width, height;
1000   gint row, col;
1001   gint extra;
1002   
1003   children = table->children;
1004   while (children)
1005     {
1006       child = children->data;
1007       children = children->next;
1008       
1009       if (GTK_WIDGET_VISIBLE (child->widget))
1010         {
1011           /* Child spans multiple columns.
1012            */
1013           if (child->left_attach != (child->right_attach - 1))
1014             {
1015               GtkRequisition child_requisition;
1016
1017               gtk_widget_get_child_requisition (child->widget, &child_requisition);
1018               
1019               /* Check and see if there is already enough space
1020                *  for the child.
1021                */
1022               width = 0;
1023               for (col = child->left_attach; col < child->right_attach; col++)
1024                 {
1025                   width += table->cols[col].requisition;
1026                   if ((col + 1) < child->right_attach)
1027                     width += table->cols[col].spacing;
1028                 }
1029               
1030               /* If we need to request more space for this child to fill
1031                *  its requisition, then divide up the needed space evenly
1032                *  amongst the columns it spans.
1033                */
1034               if (width < child_requisition.width + child->xpadding * 2)
1035                 {
1036                   width = child_requisition.width + child->xpadding * 2 - width;
1037                   
1038                   for (col = child->left_attach; col < child->right_attach; col++)
1039                     {
1040                       extra = width / (child->right_attach - col);
1041                       table->cols[col].requisition += extra;
1042                       width -= extra;
1043                     }
1044                 }
1045             }
1046           
1047           /* Child spans multiple rows.
1048            */
1049           if (child->top_attach != (child->bottom_attach - 1))
1050             {
1051               GtkRequisition child_requisition;
1052
1053               gtk_widget_get_child_requisition (child->widget, &child_requisition);
1054
1055               /* Check and see if there is already enough space
1056                *  for the child.
1057                */
1058               height = 0;
1059               for (row = child->top_attach; row < child->bottom_attach; row++)
1060                 {
1061                   height += table->rows[row].requisition;
1062                   if ((row + 1) < child->bottom_attach)
1063                     height += table->rows[row].spacing;
1064                 }
1065               
1066               /* If we need to request more space for this child to fill
1067                *  its requisition, then divide up the needed space evenly
1068                *  amongst the columns it spans.
1069                */
1070               if (height < child_requisition.height + child->ypadding * 2)
1071                 {
1072                   height = child_requisition.height + child->ypadding * 2 - height;
1073                   
1074                   for (row = child->top_attach; row < child->bottom_attach; row++)
1075                     {
1076                       extra = height / (child->bottom_attach - row);
1077                       table->rows[row].requisition += extra;
1078                       height -= extra;
1079                     }
1080                 }
1081             }
1082         }
1083     }
1084 }
1085
1086 static void
1087 gtk_table_size_allocate_init (GtkTable *table)
1088 {
1089   GtkTableChild *child;
1090   GList *children;
1091   gint row, col;
1092   gint has_expand;
1093   gint has_shrink;
1094   
1095   /* Initialize the rows and cols.
1096    *  By default, rows and cols do not expand and do shrink.
1097    *  Those values are modified by the children that occupy
1098    *  the rows and cols.
1099    */
1100   for (col = 0; col < table->ncols; col++)
1101     {
1102       table->cols[col].allocation = table->cols[col].requisition;
1103       table->cols[col].need_expand = FALSE;
1104       table->cols[col].need_shrink = TRUE;
1105       table->cols[col].expand = FALSE;
1106       table->cols[col].shrink = TRUE;
1107       table->cols[col].empty = TRUE;
1108     }
1109   for (row = 0; row < table->nrows; row++)
1110     {
1111       table->rows[row].allocation = table->rows[row].requisition;
1112       table->rows[row].need_expand = FALSE;
1113       table->rows[row].need_shrink = TRUE;
1114       table->rows[row].expand = FALSE;
1115       table->rows[row].shrink = TRUE;
1116       table->rows[row].empty = TRUE;
1117     }
1118   
1119   /* Loop over all the children and adjust the row and col values
1120    *  based on whether the children want to be allowed to expand
1121    *  or shrink. This loop handles children that occupy a single
1122    *  row or column.
1123    */
1124   children = table->children;
1125   while (children)
1126     {
1127       child = children->data;
1128       children = children->next;
1129       
1130       if (GTK_WIDGET_VISIBLE (child->widget))
1131         {
1132           if (child->left_attach == (child->right_attach - 1))
1133             {
1134               if (child->xexpand)
1135                 table->cols[child->left_attach].expand = TRUE;
1136               
1137               if (!child->xshrink)
1138                 table->cols[child->left_attach].shrink = FALSE;
1139               
1140               table->cols[child->left_attach].empty = FALSE;
1141             }
1142           
1143           if (child->top_attach == (child->bottom_attach - 1))
1144             {
1145               if (child->yexpand)
1146                 table->rows[child->top_attach].expand = TRUE;
1147               
1148               if (!child->yshrink)
1149                 table->rows[child->top_attach].shrink = FALSE;
1150
1151               table->rows[child->top_attach].empty = FALSE;
1152             }
1153         }
1154     }
1155   
1156   /* Loop over all the children again and this time handle children
1157    *  which span multiple rows or columns.
1158    */
1159   children = table->children;
1160   while (children)
1161     {
1162       child = children->data;
1163       children = children->next;
1164       
1165       if (GTK_WIDGET_VISIBLE (child->widget))
1166         {
1167           if (child->left_attach != (child->right_attach - 1))
1168             {
1169               for (col = child->left_attach; col < child->right_attach; col++)
1170                 table->cols[col].empty = FALSE;
1171
1172               if (child->xexpand)
1173                 {
1174                   has_expand = FALSE;
1175                   for (col = child->left_attach; col < child->right_attach; col++)
1176                     if (table->cols[col].expand)
1177                       {
1178                         has_expand = TRUE;
1179                         break;
1180                       }
1181                   
1182                   if (!has_expand)
1183                     for (col = child->left_attach; col < child->right_attach; col++)
1184                       table->cols[col].need_expand = TRUE;
1185                 }
1186               
1187               if (!child->xshrink)
1188                 {
1189                   has_shrink = TRUE;
1190                   for (col = child->left_attach; col < child->right_attach; col++)
1191                     if (!table->cols[col].shrink)
1192                       {
1193                         has_shrink = FALSE;
1194                         break;
1195                       }
1196                   
1197                   if (has_shrink)
1198                     for (col = child->left_attach; col < child->right_attach; col++)
1199                       table->cols[col].need_shrink = FALSE;
1200                 }
1201             }
1202           
1203           if (child->top_attach != (child->bottom_attach - 1))
1204             {
1205               for (row = child->top_attach; row < child->bottom_attach; row++)
1206                 table->rows[row].empty = FALSE;
1207
1208               if (child->yexpand)
1209                 {
1210                   has_expand = FALSE;
1211                   for (row = child->top_attach; row < child->bottom_attach; row++)
1212                     if (table->rows[row].expand)
1213                       {
1214                         has_expand = TRUE;
1215                         break;
1216                       }
1217                   
1218                   if (!has_expand)
1219                     for (row = child->top_attach; row < child->bottom_attach; row++)
1220                       table->rows[row].need_expand = TRUE;
1221                 }
1222               
1223               if (!child->yshrink)
1224                 {
1225                   has_shrink = TRUE;
1226                   for (row = child->top_attach; row < child->bottom_attach; row++)
1227                     if (!table->rows[row].shrink)
1228                       {
1229                         has_shrink = FALSE;
1230                         break;
1231                       }
1232                   
1233                   if (has_shrink)
1234                     for (row = child->top_attach; row < child->bottom_attach; row++)
1235                       table->rows[row].need_shrink = FALSE;
1236                 }
1237             }
1238         }
1239     }
1240   
1241   /* Loop over the columns and set the expand and shrink values
1242    *  if the column can be expanded or shrunk.
1243    */
1244   for (col = 0; col < table->ncols; col++)
1245     {
1246       if (table->cols[col].empty)
1247         {
1248           table->cols[col].expand = FALSE;
1249           table->cols[col].shrink = FALSE;
1250         }
1251       else
1252         {
1253           if (table->cols[col].need_expand)
1254             table->cols[col].expand = TRUE;
1255           if (!table->cols[col].need_shrink)
1256             table->cols[col].shrink = FALSE;
1257         }
1258     }
1259   
1260   /* Loop over the rows and set the expand and shrink values
1261    *  if the row can be expanded or shrunk.
1262    */
1263   for (row = 0; row < table->nrows; row++)
1264     {
1265       if (table->rows[row].empty)
1266         {
1267           table->rows[row].expand = FALSE;
1268           table->rows[row].shrink = FALSE;
1269         }
1270       else
1271         {
1272           if (table->rows[row].need_expand)
1273             table->rows[row].expand = TRUE;
1274           if (!table->rows[row].need_shrink)
1275             table->rows[row].shrink = FALSE;
1276         }
1277     }
1278 }
1279
1280 static void
1281 gtk_table_size_allocate_pass1 (GtkTable *table)
1282 {
1283   gint real_width;
1284   gint real_height;
1285   gint width, height;
1286   gint row, col;
1287   gint nexpand;
1288   gint nshrink;
1289   gint extra;
1290   
1291   /* If we were allocated more space than we requested
1292    *  then we have to expand any expandable rows and columns
1293    *  to fill in the extra space.
1294    */
1295   
1296   real_width = GTK_WIDGET (table)->allocation.width - GTK_CONTAINER (table)->border_width * 2;
1297   real_height = GTK_WIDGET (table)->allocation.height - GTK_CONTAINER (table)->border_width * 2;
1298   
1299   if (table->homogeneous)
1300     {
1301       nexpand = 0;
1302       for (col = 0; col < table->ncols; col++)
1303         if (table->cols[col].expand)
1304           {
1305             nexpand += 1;
1306             break;
1307           }
1308       
1309       if (nexpand > 0)
1310         {
1311           width = real_width;
1312           
1313           for (col = 0; col + 1 < table->ncols; col++)
1314             width -= table->cols[col].spacing;
1315           
1316           for (col = 0; col < table->ncols; col++)
1317             {
1318               extra = width / (table->ncols - col);
1319               table->cols[col].allocation = MAX (1, extra);
1320               width -= extra;
1321             }
1322         }
1323     }
1324   else
1325     {
1326       width = 0;
1327       nexpand = 0;
1328       nshrink = 0;
1329       
1330       for (col = 0; col < table->ncols; col++)
1331         {
1332           width += table->cols[col].requisition;
1333           if (table->cols[col].expand)
1334             nexpand += 1;
1335           if (table->cols[col].shrink)
1336             nshrink += 1;
1337         }
1338       for (col = 0; col + 1 < table->ncols; col++)
1339         width += table->cols[col].spacing;
1340       
1341       /* Check to see if we were allocated more width than we requested.
1342        */
1343       if ((width < real_width) && (nexpand >= 1))
1344         {
1345           width = real_width - width;
1346           
1347           for (col = 0; col < table->ncols; col++)
1348             if (table->cols[col].expand)
1349               {
1350                 extra = width / nexpand;
1351                 table->cols[col].allocation += extra;
1352                 
1353                 width -= extra;
1354                 nexpand -= 1;
1355               }
1356         }
1357       
1358       /* Check to see if we were allocated less width than we requested,
1359        * then shrink until we fit the size give.
1360        */
1361       if (width > real_width)
1362         {
1363           gint total_nshrink = nshrink;
1364
1365           extra = width - real_width;
1366           while (total_nshrink > 0 && extra > 0)
1367             {
1368               nshrink = total_nshrink;
1369               for (col = 0; col < table->ncols; col++)
1370                 if (table->cols[col].shrink)
1371                   {
1372                     gint allocation = table->cols[col].allocation;
1373
1374                     table->cols[col].allocation = MAX (1, (gint) table->cols[col].allocation - extra / nshrink);
1375                     extra -= allocation - table->cols[col].allocation;
1376                     nshrink -= 1;
1377                     if (table->cols[col].allocation < 2)
1378                       {
1379                         total_nshrink -= 1;
1380                         table->cols[col].shrink = FALSE;
1381                       }
1382                   }
1383             }
1384         }
1385     }
1386   
1387   if (table->homogeneous)
1388     {
1389       nexpand = 0;
1390       for (row = 0; row < table->nrows; row++)
1391         if (table->rows[row].expand)
1392           {
1393             nexpand += 1;
1394             break;
1395           }
1396       
1397       if (nexpand > 0)
1398         {
1399           height = real_height;
1400           
1401           for (row = 0; row + 1 < table->nrows; row++)
1402             height -= table->rows[row].spacing;
1403           
1404           
1405           for (row = 0; row < table->nrows; row++)
1406             {
1407               extra = height / (table->nrows - row);
1408               table->rows[row].allocation = MAX (1, extra);
1409               height -= extra;
1410             }
1411         }
1412     }
1413   else
1414     {
1415       height = 0;
1416       nexpand = 0;
1417       nshrink = 0;
1418       
1419       for (row = 0; row < table->nrows; row++)
1420         {
1421           height += table->rows[row].requisition;
1422           if (table->rows[row].expand)
1423             nexpand += 1;
1424           if (table->rows[row].shrink)
1425             nshrink += 1;
1426         }
1427       for (row = 0; row + 1 < table->nrows; row++)
1428         height += table->rows[row].spacing;
1429       
1430       /* Check to see if we were allocated more height than we requested.
1431        */
1432       if ((height < real_height) && (nexpand >= 1))
1433         {
1434           height = real_height - height;
1435           
1436           for (row = 0; row < table->nrows; row++)
1437             if (table->rows[row].expand)
1438               {
1439                 extra = height / nexpand;
1440                 table->rows[row].allocation += extra;
1441                 
1442                 height -= extra;
1443                 nexpand -= 1;
1444               }
1445         }
1446       
1447       /* Check to see if we were allocated less height than we requested.
1448        * then shrink until we fit the size give.
1449        */
1450       if (height > real_height)
1451         {
1452           gint total_nshrink = nshrink;
1453           
1454           extra = height - real_height;
1455           while (total_nshrink > 0 && extra > 0)
1456             {
1457               nshrink = total_nshrink;
1458               for (row = 0; row < table->nrows; row++)
1459                 if (table->rows[row].shrink)
1460                   {
1461                     gint allocation = table->rows[row].allocation;
1462                     
1463                     table->rows[row].allocation = MAX (1, (gint) table->rows[row].allocation - extra / nshrink);
1464                     extra -= allocation - table->rows[row].allocation;
1465                     nshrink -= 1;
1466                     if (table->rows[row].allocation < 2)
1467                       {
1468                         total_nshrink -= 1;
1469                         table->rows[row].shrink = FALSE;
1470                       }
1471                   }
1472             }
1473         }
1474     }
1475 }
1476
1477 static void
1478 gtk_table_size_allocate_pass2 (GtkTable *table)
1479 {
1480   GtkTableChild *child;
1481   GList *children;
1482   gint max_width;
1483   gint max_height;
1484   gint x, y;
1485   gint row, col;
1486   GtkAllocation allocation;
1487   GtkWidget *widget = GTK_WIDGET (table);
1488   
1489   children = table->children;
1490   while (children)
1491     {
1492       child = children->data;
1493       children = children->next;
1494       
1495       if (GTK_WIDGET_VISIBLE (child->widget))
1496         {
1497           GtkRequisition child_requisition;
1498           gtk_widget_get_child_requisition (child->widget, &child_requisition);
1499
1500           x = GTK_WIDGET (table)->allocation.x + GTK_CONTAINER (table)->border_width;
1501           y = GTK_WIDGET (table)->allocation.y + GTK_CONTAINER (table)->border_width;
1502           max_width = 0;
1503           max_height = 0;
1504           
1505           for (col = 0; col < child->left_attach; col++)
1506             {
1507               x += table->cols[col].allocation;
1508               x += table->cols[col].spacing;
1509             }
1510           
1511           for (col = child->left_attach; col < child->right_attach; col++)
1512             {
1513               max_width += table->cols[col].allocation;
1514               if ((col + 1) < child->right_attach)
1515                 max_width += table->cols[col].spacing;
1516             }
1517           
1518           for (row = 0; row < child->top_attach; row++)
1519             {
1520               y += table->rows[row].allocation;
1521               y += table->rows[row].spacing;
1522             }
1523           
1524           for (row = child->top_attach; row < child->bottom_attach; row++)
1525             {
1526               max_height += table->rows[row].allocation;
1527               if ((row + 1) < child->bottom_attach)
1528                 max_height += table->rows[row].spacing;
1529             }
1530           
1531           if (child->xfill)
1532             {
1533               allocation.width = MAX (1, max_width - (gint)child->xpadding * 2);
1534               allocation.x = x + (max_width - allocation.width) / 2;
1535             }
1536           else
1537             {
1538               allocation.width = child_requisition.width;
1539               allocation.x = x + (max_width - allocation.width) / 2;
1540             }
1541           
1542           if (child->yfill)
1543             {
1544               allocation.height = MAX (1, max_height - (gint)child->ypadding * 2);
1545               allocation.y = y + (max_height - allocation.height) / 2;
1546             }
1547           else
1548             {
1549               allocation.height = child_requisition.height;
1550               allocation.y = y + (max_height - allocation.height) / 2;
1551             }
1552
1553           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1554             allocation.x = widget->allocation.x + widget->allocation.width
1555               - (allocation.x - widget->allocation.x) - allocation.width;
1556           
1557           gtk_widget_size_allocate (child->widget, &allocation);
1558         }
1559     }
1560 }