]> Pileus Git - ~andy/gtk/blob - gtk/gtktable.c
Remove all references to offscreen flag which was no longer used.
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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-1999.  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_VISIBLE (GTK_WIDGET (table)))
542     {
543       if (GTK_WIDGET_REALIZED (GTK_WIDGET (table)) &&
544           !GTK_WIDGET_REALIZED (child))
545         gtk_widget_realize (child);
546       
547       if (GTK_WIDGET_MAPPED (GTK_WIDGET (table)) &&
548           !GTK_WIDGET_MAPPED (child))
549         gtk_widget_map (child);
550     }
551   
552   if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (table))
553     gtk_widget_queue_resize (child);
554 }
555
556 void
557 gtk_table_attach_defaults (GtkTable  *table,
558                            GtkWidget *widget,
559                            guint      left_attach,
560                            guint      right_attach,
561                            guint      top_attach,
562                            guint      bottom_attach)
563 {
564   gtk_table_attach (table, widget,
565                     left_attach, right_attach,
566                     top_attach, bottom_attach,
567                     GTK_EXPAND | GTK_FILL,
568                     GTK_EXPAND | GTK_FILL,
569                     0, 0);
570 }
571
572 void
573 gtk_table_set_row_spacing (GtkTable *table,
574                            guint     row,
575                            guint     spacing)
576 {
577   g_return_if_fail (table != NULL);
578   g_return_if_fail (GTK_IS_TABLE (table));
579   g_return_if_fail (row + 1 < table->nrows);
580   
581   if (table->rows[row].spacing != spacing)
582     {
583       table->rows[row].spacing = spacing;
584       
585       if (GTK_WIDGET_VISIBLE (table))
586         gtk_widget_queue_resize (GTK_WIDGET (table));
587     }
588 }
589
590 void
591 gtk_table_set_col_spacing (GtkTable *table,
592                            guint     column,
593                            guint     spacing)
594 {
595   g_return_if_fail (table != NULL);
596   g_return_if_fail (GTK_IS_TABLE (table));
597   g_return_if_fail (column + 1 < table->ncols);
598   
599   if (table->cols[column].spacing != spacing)
600     {
601       table->cols[column].spacing = spacing;
602       
603       if (GTK_WIDGET_VISIBLE (table))
604         gtk_widget_queue_resize (GTK_WIDGET (table));
605     }
606 }
607
608 void
609 gtk_table_set_row_spacings (GtkTable *table,
610                             guint     spacing)
611 {
612   guint row;
613   
614   g_return_if_fail (table != NULL);
615   g_return_if_fail (GTK_IS_TABLE (table));
616   
617   table->row_spacing = spacing;
618   for (row = 0; row + 1 < table->nrows; row++)
619     table->rows[row].spacing = spacing;
620   
621   if (GTK_WIDGET_VISIBLE (table))
622     gtk_widget_queue_resize (GTK_WIDGET (table));
623 }
624
625 void
626 gtk_table_set_col_spacings (GtkTable *table,
627                             guint     spacing)
628 {
629   guint col;
630   
631   g_return_if_fail (table != NULL);
632   g_return_if_fail (GTK_IS_TABLE (table));
633   
634   table->column_spacing = spacing;
635   for (col = 0; col + 1 < table->ncols; col++)
636     table->cols[col].spacing = spacing;
637   
638   if (GTK_WIDGET_VISIBLE (table))
639     gtk_widget_queue_resize (GTK_WIDGET (table));
640 }
641
642 void
643 gtk_table_set_homogeneous (GtkTable *table,
644                            gboolean  homogeneous)
645 {
646   g_return_if_fail (table != NULL);
647   g_return_if_fail (GTK_IS_TABLE (table));
648
649   homogeneous = (homogeneous != 0);
650   if (homogeneous != table->homogeneous)
651     {
652       table->homogeneous = homogeneous;
653       
654       if (GTK_WIDGET_VISIBLE (table))
655         gtk_widget_queue_resize (GTK_WIDGET (table));
656     }
657 }
658
659 static void
660 gtk_table_finalize (GObject *object)
661 {
662   GtkTable *table;
663   
664   g_return_if_fail (GTK_IS_TABLE (object));
665   
666   table = GTK_TABLE (object);
667   
668   g_free (table->rows);
669   g_free (table->cols);
670   
671   G_OBJECT_CLASS (parent_class)->finalize (object);
672 }
673
674 static void
675 gtk_table_map (GtkWidget *widget)
676 {
677   GtkTable *table;
678   GtkTableChild *child;
679   GList *children;
680   
681   g_return_if_fail (widget != NULL);
682   g_return_if_fail (GTK_IS_TABLE (widget));
683   
684   table = GTK_TABLE (widget);
685   GTK_WIDGET_SET_FLAGS (table, GTK_MAPPED);
686   
687   children = table->children;
688   while (children)
689     {
690       child = children->data;
691       children = children->next;
692       
693       if (GTK_WIDGET_VISIBLE (child->widget) &&
694           !GTK_WIDGET_MAPPED (child->widget))
695         gtk_widget_map (child->widget);
696     }
697 }
698
699 static void
700 gtk_table_unmap (GtkWidget *widget)
701 {
702   GtkTable *table;
703   GtkTableChild *child;
704   GList *children;
705   
706   g_return_if_fail (widget != NULL);
707   g_return_if_fail (GTK_IS_TABLE (widget));
708   
709   table = GTK_TABLE (widget);
710   GTK_WIDGET_UNSET_FLAGS (table, GTK_MAPPED);
711   
712   children = table->children;
713   while (children)
714     {
715       child = children->data;
716       children = children->next;
717       
718       if (GTK_WIDGET_VISIBLE (child->widget) &&
719           GTK_WIDGET_MAPPED (child->widget))
720         gtk_widget_unmap (child->widget);
721     }
722 }
723
724 static void
725 gtk_table_draw (GtkWidget    *widget,
726                 GdkRectangle *area)
727 {
728   GtkTable *table;
729   GtkTableChild *child;
730   GList *children;
731   GdkRectangle child_area;
732   
733   g_return_if_fail (widget != NULL);
734   g_return_if_fail (GTK_IS_TABLE (widget));
735   
736   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
737     {
738       table = GTK_TABLE (widget);
739       
740       children = table->children;
741       while (children)
742         {
743           child = children->data;
744           children = children->next;
745           
746           if (gtk_widget_intersect (child->widget, area, &child_area))
747             gtk_widget_draw (child->widget, &child_area);
748         }
749     }
750 }
751
752 static gint
753 gtk_table_expose (GtkWidget      *widget,
754                   GdkEventExpose *event)
755 {
756   GtkTable *table;
757   GtkTableChild *child;
758   GList *children;
759   GdkEventExpose child_event;
760   
761   g_return_val_if_fail (widget != NULL, FALSE);
762   g_return_val_if_fail (GTK_IS_TABLE (widget), FALSE);
763   
764   if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_MAPPED (widget))
765     {
766       table = GTK_TABLE (widget);
767       
768       child_event = *event;
769       
770       children = table->children;
771       while (children)
772         {
773           child = children->data;
774           children = children->next;
775           
776           if (GTK_WIDGET_NO_WINDOW (child->widget) &&
777               gtk_widget_intersect (child->widget, &event->area, &child_event.area))
778             gtk_widget_event (child->widget, (GdkEvent*) &child_event);
779         }
780     }
781   
782   return FALSE;
783 }
784
785 static void
786 gtk_table_size_request (GtkWidget      *widget,
787                         GtkRequisition *requisition)
788 {
789   GtkTable *table;
790   gint row, col;
791   
792   g_return_if_fail (widget != NULL);
793   g_return_if_fail (GTK_IS_TABLE (widget));
794   g_return_if_fail (requisition != NULL);
795   
796   table = GTK_TABLE (widget);
797   
798   requisition->width = 0;
799   requisition->height = 0;
800   
801   gtk_table_size_request_init (table);
802   gtk_table_size_request_pass1 (table);
803   gtk_table_size_request_pass2 (table);
804   gtk_table_size_request_pass3 (table);
805   gtk_table_size_request_pass2 (table);
806   
807   for (col = 0; col < table->ncols; col++)
808     requisition->width += table->cols[col].requisition;
809   for (col = 0; col + 1 < table->ncols; col++)
810     requisition->width += table->cols[col].spacing;
811   
812   for (row = 0; row < table->nrows; row++)
813     requisition->height += table->rows[row].requisition;
814   for (row = 0; row + 1 < table->nrows; row++)
815     requisition->height += table->rows[row].spacing;
816   
817   requisition->width += GTK_CONTAINER (table)->border_width * 2;
818   requisition->height += GTK_CONTAINER (table)->border_width * 2;
819 }
820
821 static void
822 gtk_table_size_allocate (GtkWidget     *widget,
823                          GtkAllocation *allocation)
824 {
825   GtkTable *table;
826   
827   g_return_if_fail (widget != NULL);
828   g_return_if_fail (GTK_IS_TABLE (widget));
829   g_return_if_fail (allocation != NULL);
830   
831   widget->allocation = *allocation;
832   table = GTK_TABLE (widget);
833   
834   gtk_table_size_allocate_init (table);
835   gtk_table_size_allocate_pass1 (table);
836   gtk_table_size_allocate_pass2 (table);
837 }
838
839 static void
840 gtk_table_add (GtkContainer *container,
841                GtkWidget    *widget)
842 {
843   g_return_if_fail (container != NULL);
844   g_return_if_fail (GTK_IS_TABLE (container));
845   g_return_if_fail (widget != NULL);
846   
847   gtk_table_attach_defaults (GTK_TABLE (container), widget, 0, 1, 0, 1);
848 }
849
850 static void
851 gtk_table_remove (GtkContainer *container,
852                   GtkWidget    *widget)
853 {
854   GtkTable *table;
855   GtkTableChild *child;
856   GList *children;
857   
858   g_return_if_fail (container != NULL);
859   g_return_if_fail (GTK_IS_TABLE (container));
860   g_return_if_fail (widget != NULL);
861   
862   table = GTK_TABLE (container);
863   children = table->children;
864   
865   while (children)
866     {
867       child = children->data;
868       children = children->next;
869       
870       if (child->widget == widget)
871         {
872           gboolean was_visible = GTK_WIDGET_VISIBLE (widget);
873           
874           gtk_widget_unparent (widget);
875           
876           table->children = g_list_remove (table->children, child);
877           g_free (child);
878           
879           if (was_visible && GTK_WIDGET_VISIBLE (container))
880             gtk_container_queue_resize (container);
881           break;
882         }
883     }
884 }
885
886 static void
887 gtk_table_forall (GtkContainer *container,
888                   gboolean      include_internals,
889                   GtkCallback   callback,
890                   gpointer      callback_data)
891 {
892   GtkTable *table;
893   GtkTableChild *child;
894   GList *children;
895   
896   g_return_if_fail (container != NULL);
897   g_return_if_fail (GTK_IS_TABLE (container));
898   g_return_if_fail (callback != NULL);
899   
900   table = GTK_TABLE (container);
901   children = table->children;
902   
903   while (children)
904     {
905       child = children->data;
906       children = children->next;
907       
908       (* callback) (child->widget, callback_data);
909     }
910 }
911
912 static void
913 gtk_table_size_request_init (GtkTable *table)
914 {
915   GtkTableChild *child;
916   GList *children;
917   gint row, col;
918   
919   for (row = 0; row < table->nrows; row++)
920     table->rows[row].requisition = 0;
921   for (col = 0; col < table->ncols; col++)
922     table->cols[col].requisition = 0;
923   
924   children = table->children;
925   while (children)
926     {
927       child = children->data;
928       children = children->next;
929       
930       if (GTK_WIDGET_VISIBLE (child->widget))
931         gtk_widget_size_request (child->widget, NULL);
932     }
933 }
934
935 static void
936 gtk_table_size_request_pass1 (GtkTable *table)
937 {
938   GtkTableChild *child;
939   GList *children;
940   gint width;
941   gint height;
942   
943   children = table->children;
944   while (children)
945     {
946       child = children->data;
947       children = children->next;
948       
949       if (GTK_WIDGET_VISIBLE (child->widget))
950         {
951           GtkRequisition child_requisition;
952           gtk_widget_get_child_requisition (child->widget, &child_requisition);
953
954           /* Child spans a single column.
955            */
956           if (child->left_attach == (child->right_attach - 1))
957             {
958               width = child_requisition.width + child->xpadding * 2;
959               table->cols[child->left_attach].requisition = MAX (table->cols[child->left_attach].requisition, width);
960             }
961           
962           /* Child spans a single row.
963            */
964           if (child->top_attach == (child->bottom_attach - 1))
965             {
966               height = child_requisition.height + child->ypadding * 2;
967               table->rows[child->top_attach].requisition = MAX (table->rows[child->top_attach].requisition, height);
968             }
969         }
970     }
971 }
972
973 static void
974 gtk_table_size_request_pass2 (GtkTable *table)
975 {
976   gint max_width;
977   gint max_height;
978   gint row, col;
979   
980   if (table->homogeneous)
981     {
982       max_width = 0;
983       max_height = 0;
984       
985       for (col = 0; col < table->ncols; col++)
986         max_width = MAX (max_width, table->cols[col].requisition);
987       for (row = 0; row < table->nrows; row++)
988         max_height = MAX (max_height, table->rows[row].requisition);
989       
990       for (col = 0; col < table->ncols; col++)
991         table->cols[col].requisition = max_width;
992       for (row = 0; row < table->nrows; row++)
993         table->rows[row].requisition = max_height;
994     }
995 }
996
997 static void
998 gtk_table_size_request_pass3 (GtkTable *table)
999 {
1000   GtkTableChild *child;
1001   GList *children;
1002   gint width, height;
1003   gint row, col;
1004   gint extra;
1005   
1006   children = table->children;
1007   while (children)
1008     {
1009       child = children->data;
1010       children = children->next;
1011       
1012       if (GTK_WIDGET_VISIBLE (child->widget))
1013         {
1014           /* Child spans multiple columns.
1015            */
1016           if (child->left_attach != (child->right_attach - 1))
1017             {
1018               GtkRequisition child_requisition;
1019
1020               gtk_widget_get_child_requisition (child->widget, &child_requisition);
1021               
1022               /* Check and see if there is already enough space
1023                *  for the child.
1024                */
1025               width = 0;
1026               for (col = child->left_attach; col < child->right_attach; col++)
1027                 {
1028                   width += table->cols[col].requisition;
1029                   if ((col + 1) < child->right_attach)
1030                     width += table->cols[col].spacing;
1031                 }
1032               
1033               /* If we need to request more space for this child to fill
1034                *  its requisition, then divide up the needed space evenly
1035                *  amongst the columns it spans.
1036                */
1037               if (width < child_requisition.width + child->xpadding * 2)
1038                 {
1039                   width = child_requisition.width + child->xpadding * 2 - width;
1040                   
1041                   for (col = child->left_attach; col < child->right_attach; col++)
1042                     {
1043                       extra = width / (child->right_attach - col);
1044                       table->cols[col].requisition += extra;
1045                       width -= extra;
1046                     }
1047                 }
1048             }
1049           
1050           /* Child spans multiple rows.
1051            */
1052           if (child->top_attach != (child->bottom_attach - 1))
1053             {
1054               GtkRequisition child_requisition;
1055
1056               gtk_widget_get_child_requisition (child->widget, &child_requisition);
1057
1058               /* Check and see if there is already enough space
1059                *  for the child.
1060                */
1061               height = 0;
1062               for (row = child->top_attach; row < child->bottom_attach; row++)
1063                 {
1064                   height += table->rows[row].requisition;
1065                   if ((row + 1) < child->bottom_attach)
1066                     height += table->rows[row].spacing;
1067                 }
1068               
1069               /* If we need to request more space for this child to fill
1070                *  its requisition, then divide up the needed space evenly
1071                *  amongst the columns it spans.
1072                */
1073               if (height < child_requisition.height + child->ypadding * 2)
1074                 {
1075                   height = child_requisition.height + child->ypadding * 2 - height;
1076                   
1077                   for (row = child->top_attach; row < child->bottom_attach; row++)
1078                     {
1079                       extra = height / (child->bottom_attach - row);
1080                       table->rows[row].requisition += extra;
1081                       height -= extra;
1082                     }
1083                 }
1084             }
1085         }
1086     }
1087 }
1088
1089 static void
1090 gtk_table_size_allocate_init (GtkTable *table)
1091 {
1092   GtkTableChild *child;
1093   GList *children;
1094   gint row, col;
1095   gint has_expand;
1096   gint has_shrink;
1097   
1098   /* Initialize the rows and cols.
1099    *  By default, rows and cols do not expand and do shrink.
1100    *  Those values are modified by the children that occupy
1101    *  the rows and cols.
1102    */
1103   for (col = 0; col < table->ncols; col++)
1104     {
1105       table->cols[col].allocation = table->cols[col].requisition;
1106       table->cols[col].need_expand = FALSE;
1107       table->cols[col].need_shrink = TRUE;
1108       table->cols[col].expand = FALSE;
1109       table->cols[col].shrink = TRUE;
1110       table->cols[col].empty = TRUE;
1111     }
1112   for (row = 0; row < table->nrows; row++)
1113     {
1114       table->rows[row].allocation = table->rows[row].requisition;
1115       table->rows[row].need_expand = FALSE;
1116       table->rows[row].need_shrink = TRUE;
1117       table->rows[row].expand = FALSE;
1118       table->rows[row].shrink = TRUE;
1119       table->rows[row].empty = TRUE;
1120     }
1121   
1122   /* Loop over all the children and adjust the row and col values
1123    *  based on whether the children want to be allowed to expand
1124    *  or shrink. This loop handles children that occupy a single
1125    *  row or column.
1126    */
1127   children = table->children;
1128   while (children)
1129     {
1130       child = children->data;
1131       children = children->next;
1132       
1133       if (GTK_WIDGET_VISIBLE (child->widget))
1134         {
1135           if (child->left_attach == (child->right_attach - 1))
1136             {
1137               if (child->xexpand)
1138                 table->cols[child->left_attach].expand = TRUE;
1139               
1140               if (!child->xshrink)
1141                 table->cols[child->left_attach].shrink = FALSE;
1142               
1143               table->cols[child->left_attach].empty = FALSE;
1144             }
1145           
1146           if (child->top_attach == (child->bottom_attach - 1))
1147             {
1148               if (child->yexpand)
1149                 table->rows[child->top_attach].expand = TRUE;
1150               
1151               if (!child->yshrink)
1152                 table->rows[child->top_attach].shrink = FALSE;
1153
1154               table->rows[child->top_attach].empty = FALSE;
1155             }
1156         }
1157     }
1158   
1159   /* Loop over all the children again and this time handle children
1160    *  which span multiple rows or columns.
1161    */
1162   children = table->children;
1163   while (children)
1164     {
1165       child = children->data;
1166       children = children->next;
1167       
1168       if (GTK_WIDGET_VISIBLE (child->widget))
1169         {
1170           if (child->left_attach != (child->right_attach - 1))
1171             {
1172               for (col = child->left_attach; col < child->right_attach; col++)
1173                 table->cols[col].empty = FALSE;
1174
1175               if (child->xexpand)
1176                 {
1177                   has_expand = FALSE;
1178                   for (col = child->left_attach; col < child->right_attach; col++)
1179                     if (table->cols[col].expand)
1180                       {
1181                         has_expand = TRUE;
1182                         break;
1183                       }
1184                   
1185                   if (!has_expand)
1186                     for (col = child->left_attach; col < child->right_attach; col++)
1187                       table->cols[col].need_expand = TRUE;
1188                 }
1189               
1190               if (!child->xshrink)
1191                 {
1192                   has_shrink = TRUE;
1193                   for (col = child->left_attach; col < child->right_attach; col++)
1194                     if (!table->cols[col].shrink)
1195                       {
1196                         has_shrink = FALSE;
1197                         break;
1198                       }
1199                   
1200                   if (has_shrink)
1201                     for (col = child->left_attach; col < child->right_attach; col++)
1202                       table->cols[col].need_shrink = FALSE;
1203                 }
1204             }
1205           
1206           if (child->top_attach != (child->bottom_attach - 1))
1207             {
1208               for (row = child->top_attach; row < child->bottom_attach; row++)
1209                 table->rows[row].empty = FALSE;
1210
1211               if (child->yexpand)
1212                 {
1213                   has_expand = FALSE;
1214                   for (row = child->top_attach; row < child->bottom_attach; row++)
1215                     if (table->rows[row].expand)
1216                       {
1217                         has_expand = TRUE;
1218                         break;
1219                       }
1220                   
1221                   if (!has_expand)
1222                     for (row = child->top_attach; row < child->bottom_attach; row++)
1223                       table->rows[row].need_expand = TRUE;
1224                 }
1225               
1226               if (!child->yshrink)
1227                 {
1228                   has_shrink = TRUE;
1229                   for (row = child->top_attach; row < child->bottom_attach; row++)
1230                     if (!table->rows[row].shrink)
1231                       {
1232                         has_shrink = FALSE;
1233                         break;
1234                       }
1235                   
1236                   if (has_shrink)
1237                     for (row = child->top_attach; row < child->bottom_attach; row++)
1238                       table->rows[row].need_shrink = FALSE;
1239                 }
1240             }
1241         }
1242     }
1243   
1244   /* Loop over the columns and set the expand and shrink values
1245    *  if the column can be expanded or shrunk.
1246    */
1247   for (col = 0; col < table->ncols; col++)
1248     {
1249       if (table->cols[col].empty)
1250         {
1251           table->cols[col].expand = FALSE;
1252           table->cols[col].shrink = FALSE;
1253         }
1254       else
1255         {
1256           if (table->cols[col].need_expand)
1257             table->cols[col].expand = TRUE;
1258           if (!table->cols[col].need_shrink)
1259             table->cols[col].shrink = FALSE;
1260         }
1261     }
1262   
1263   /* Loop over the rows and set the expand and shrink values
1264    *  if the row can be expanded or shrunk.
1265    */
1266   for (row = 0; row < table->nrows; row++)
1267     {
1268       if (table->rows[row].empty)
1269         {
1270           table->rows[row].expand = FALSE;
1271           table->rows[row].shrink = FALSE;
1272         }
1273       else
1274         {
1275           if (table->rows[row].need_expand)
1276             table->rows[row].expand = TRUE;
1277           if (!table->rows[row].need_shrink)
1278             table->rows[row].shrink = FALSE;
1279         }
1280     }
1281 }
1282
1283 static void
1284 gtk_table_size_allocate_pass1 (GtkTable *table)
1285 {
1286   gint real_width;
1287   gint real_height;
1288   gint width, height;
1289   gint row, col;
1290   gint nexpand;
1291   gint nshrink;
1292   gint extra;
1293   
1294   /* If we were allocated more space than we requested
1295    *  then we have to expand any expandable rows and columns
1296    *  to fill in the extra space.
1297    */
1298   
1299   real_width = GTK_WIDGET (table)->allocation.width - GTK_CONTAINER (table)->border_width * 2;
1300   real_height = GTK_WIDGET (table)->allocation.height - GTK_CONTAINER (table)->border_width * 2;
1301   
1302   if (table->homogeneous)
1303     {
1304       nexpand = 0;
1305       for (col = 0; col < table->ncols; col++)
1306         if (table->cols[col].expand)
1307           {
1308             nexpand += 1;
1309             break;
1310           }
1311       
1312       if (nexpand > 0)
1313         {
1314           width = real_width;
1315           
1316           for (col = 0; col + 1 < table->ncols; col++)
1317             width -= table->cols[col].spacing;
1318           
1319           for (col = 0; col < table->ncols; col++)
1320             {
1321               extra = width / (table->ncols - col);
1322               table->cols[col].allocation = MAX (1, extra);
1323               width -= extra;
1324             }
1325         }
1326     }
1327   else
1328     {
1329       width = 0;
1330       nexpand = 0;
1331       nshrink = 0;
1332       
1333       for (col = 0; col < table->ncols; col++)
1334         {
1335           width += table->cols[col].requisition;
1336           if (table->cols[col].expand)
1337             nexpand += 1;
1338           if (table->cols[col].shrink)
1339             nshrink += 1;
1340         }
1341       for (col = 0; col + 1 < table->ncols; col++)
1342         width += table->cols[col].spacing;
1343       
1344       /* Check to see if we were allocated more width than we requested.
1345        */
1346       if ((width < real_width) && (nexpand >= 1))
1347         {
1348           width = real_width - width;
1349           
1350           for (col = 0; col < table->ncols; col++)
1351             if (table->cols[col].expand)
1352               {
1353                 extra = width / nexpand;
1354                 table->cols[col].allocation += extra;
1355                 
1356                 width -= extra;
1357                 nexpand -= 1;
1358               }
1359         }
1360       
1361       /* Check to see if we were allocated less width than we requested,
1362        * then shrink until we fit the size give.
1363        */
1364       if (width > real_width)
1365         {
1366           gint total_nshrink = nshrink;
1367
1368           extra = width - real_width;
1369           while (total_nshrink > 0 && extra > 0)
1370             {
1371               nshrink = total_nshrink;
1372               for (col = 0; col < table->ncols; col++)
1373                 if (table->cols[col].shrink)
1374                   {
1375                     gint allocation = table->cols[col].allocation;
1376
1377                     table->cols[col].allocation = MAX (1, (gint) table->cols[col].allocation - extra / nshrink);
1378                     extra -= allocation - table->cols[col].allocation;
1379                     nshrink -= 1;
1380                     if (table->cols[col].allocation < 2)
1381                       {
1382                         total_nshrink -= 1;
1383                         table->cols[col].shrink = FALSE;
1384                       }
1385                   }
1386             }
1387         }
1388     }
1389   
1390   if (table->homogeneous)
1391     {
1392       nexpand = 0;
1393       for (row = 0; row < table->nrows; row++)
1394         if (table->rows[row].expand)
1395           {
1396             nexpand += 1;
1397             break;
1398           }
1399       
1400       if (nexpand > 0)
1401         {
1402           height = real_height;
1403           
1404           for (row = 0; row + 1 < table->nrows; row++)
1405             height -= table->rows[row].spacing;
1406           
1407           
1408           for (row = 0; row < table->nrows; row++)
1409             {
1410               extra = height / (table->nrows - row);
1411               table->rows[row].allocation = MAX (1, extra);
1412               height -= extra;
1413             }
1414         }
1415     }
1416   else
1417     {
1418       height = 0;
1419       nexpand = 0;
1420       nshrink = 0;
1421       
1422       for (row = 0; row < table->nrows; row++)
1423         {
1424           height += table->rows[row].requisition;
1425           if (table->rows[row].expand)
1426             nexpand += 1;
1427           if (table->rows[row].shrink)
1428             nshrink += 1;
1429         }
1430       for (row = 0; row + 1 < table->nrows; row++)
1431         height += table->rows[row].spacing;
1432       
1433       /* Check to see if we were allocated more height than we requested.
1434        */
1435       if ((height < real_height) && (nexpand >= 1))
1436         {
1437           height = real_height - height;
1438           
1439           for (row = 0; row < table->nrows; row++)
1440             if (table->rows[row].expand)
1441               {
1442                 extra = height / nexpand;
1443                 table->rows[row].allocation += extra;
1444                 
1445                 height -= extra;
1446                 nexpand -= 1;
1447               }
1448         }
1449       
1450       /* Check to see if we were allocated less height than we requested.
1451        * then shrink until we fit the size give.
1452        */
1453       if (height > real_height)
1454         {
1455           gint total_nshrink = nshrink;
1456           
1457           extra = height - real_height;
1458           while (total_nshrink > 0 && extra > 0)
1459             {
1460               nshrink = total_nshrink;
1461               for (row = 0; row < table->nrows; row++)
1462                 if (table->rows[row].shrink)
1463                   {
1464                     gint allocation = table->rows[row].allocation;
1465                     
1466                     table->rows[row].allocation = MAX (1, (gint) table->rows[row].allocation - extra / nshrink);
1467                     extra -= allocation - table->rows[row].allocation;
1468                     nshrink -= 1;
1469                     if (table->rows[row].allocation < 2)
1470                       {
1471                         total_nshrink -= 1;
1472                         table->rows[row].shrink = FALSE;
1473                       }
1474                   }
1475             }
1476         }
1477     }
1478 }
1479
1480 static void
1481 gtk_table_size_allocate_pass2 (GtkTable *table)
1482 {
1483   GtkTableChild *child;
1484   GList *children;
1485   gint max_width;
1486   gint max_height;
1487   gint x, y;
1488   gint row, col;
1489   GtkAllocation allocation;
1490   GtkWidget *widget = GTK_WIDGET (table);
1491   
1492   children = table->children;
1493   while (children)
1494     {
1495       child = children->data;
1496       children = children->next;
1497       
1498       if (GTK_WIDGET_VISIBLE (child->widget))
1499         {
1500           GtkRequisition child_requisition;
1501           gtk_widget_get_child_requisition (child->widget, &child_requisition);
1502
1503           x = GTK_WIDGET (table)->allocation.x + GTK_CONTAINER (table)->border_width;
1504           y = GTK_WIDGET (table)->allocation.y + GTK_CONTAINER (table)->border_width;
1505           max_width = 0;
1506           max_height = 0;
1507           
1508           for (col = 0; col < child->left_attach; col++)
1509             {
1510               x += table->cols[col].allocation;
1511               x += table->cols[col].spacing;
1512             }
1513           
1514           for (col = child->left_attach; col < child->right_attach; col++)
1515             {
1516               max_width += table->cols[col].allocation;
1517               if ((col + 1) < child->right_attach)
1518                 max_width += table->cols[col].spacing;
1519             }
1520           
1521           for (row = 0; row < child->top_attach; row++)
1522             {
1523               y += table->rows[row].allocation;
1524               y += table->rows[row].spacing;
1525             }
1526           
1527           for (row = child->top_attach; row < child->bottom_attach; row++)
1528             {
1529               max_height += table->rows[row].allocation;
1530               if ((row + 1) < child->bottom_attach)
1531                 max_height += table->rows[row].spacing;
1532             }
1533           
1534           if (child->xfill)
1535             {
1536               allocation.width = MAX (1, max_width - (gint)child->xpadding * 2);
1537               allocation.x = x + (max_width - allocation.width) / 2;
1538             }
1539           else
1540             {
1541               allocation.width = child_requisition.width;
1542               allocation.x = x + (max_width - allocation.width) / 2;
1543             }
1544           
1545           if (child->yfill)
1546             {
1547               allocation.height = MAX (1, max_height - (gint)child->ypadding * 2);
1548               allocation.y = y + (max_height - allocation.height) / 2;
1549             }
1550           else
1551             {
1552               allocation.height = child_requisition.height;
1553               allocation.y = y + (max_height - allocation.height) / 2;
1554             }
1555
1556           if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
1557             allocation.x = widget->allocation.x + widget->allocation.width
1558               - (allocation.x - widget->allocation.x) - allocation.width;
1559           
1560           gtk_widget_size_allocate (child->widget, &allocation);
1561         }
1562     }
1563 }