]> Pileus Git - ~andy/gtk/blob - gtk/gtknotebook.c
main part for GtkArgSetFunc/GtkArgGetFunc implementation.
[~andy/gtk] / gtk / gtknotebook.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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include "gtknotebook.h"
19 #include "gtksignal.h"
20
21
22 #define CHILD_SPACING  2
23 #define TAB_OVERLAP    2
24 #define TAB_CURVATURE  1
25
26
27 enum {
28   SWITCH_PAGE,
29   LAST_SIGNAL
30 };
31
32 typedef void (*GtkNotebookSignal) (GtkObject *object,
33                                    gpointer   arg1,
34                                    gpointer   data);
35
36 static void gtk_notebook_class_init     (GtkNotebookClass *klass);
37 static void gtk_notebook_init           (GtkNotebook      *notebook);
38 static void gtk_notebook_destroy        (GtkObject        *object);
39 static void gtk_notebook_map            (GtkWidget        *widget);
40 static void gtk_notebook_unmap          (GtkWidget        *widget);
41 static void gtk_notebook_realize        (GtkWidget        *widget);
42 static void gtk_notebook_unrealize      (GtkWidget        *widget);
43 static void gtk_notebook_size_request   (GtkWidget        *widget,
44                                          GtkRequisition   *requisition);
45 static void gtk_notebook_size_allocate  (GtkWidget        *widget,
46                                          GtkAllocation    *allocation);
47 static void gtk_notebook_paint          (GtkWidget        *widget,
48                                          GdkRectangle     *area);
49 static void gtk_notebook_draw           (GtkWidget        *widget,
50                                          GdkRectangle     *area);
51 static gint gtk_notebook_expose         (GtkWidget        *widget,
52                                          GdkEventExpose   *event);
53 static gint gtk_notebook_button_press   (GtkWidget        *widget,
54                                          GdkEventButton   *event);
55 static void gtk_notebook_add            (GtkContainer     *container,
56                                          GtkWidget        *widget);
57 static void gtk_notebook_remove         (GtkContainer     *container,
58                                          GtkWidget        *widget);
59 static void gtk_notebook_foreach        (GtkContainer     *container,
60                                          GtkCallback       callback,
61                                          gpointer          callback_data);
62 static void gtk_notebook_switch_page    (GtkNotebook      *notebook,
63                                          GtkNotebookPage  *page);
64 static void gtk_notebook_draw_tab       (GtkNotebook      *notebook,
65                                          GtkNotebookPage  *page,
66                                          GdkRectangle     *area);
67 static void gtk_notebook_pages_allocate (GtkNotebook      *notebook,
68                                          GtkAllocation    *allocation);
69 static void gtk_notebook_page_allocate  (GtkNotebook      *notebook,
70                                          GtkNotebookPage  *page,
71                                          GtkAllocation    *allocation);
72
73 static void gtk_real_notebook_switch_page (GtkNotebook     *notebook,
74                                            GtkNotebookPage *page);
75
76 static void gtk_notebook_marshal_signal (GtkObject      *object,
77                                          GtkSignalFunc   func,
78                                          gpointer        func_data,
79                                          GtkArg         *args);
80
81 static GtkContainerClass *parent_class = NULL;
82 static gint notebook_signals[LAST_SIGNAL] = { 0 };
83
84 guint
85 gtk_notebook_get_type ()
86 {
87   static guint notebook_type = 0;
88
89   if (!notebook_type)
90     {
91       GtkTypeInfo notebook_info =
92       {
93         "GtkNotebook",
94         sizeof (GtkNotebook),
95         sizeof (GtkNotebookClass),
96         (GtkClassInitFunc) gtk_notebook_class_init,
97         (GtkObjectInitFunc) gtk_notebook_init,
98         (GtkArgSetFunc) NULL,
99         (GtkArgGetFunc) NULL,
100       };
101
102       notebook_type = gtk_type_unique (gtk_container_get_type (), &notebook_info);
103     }
104
105   return notebook_type;
106 }
107
108 static void
109 gtk_notebook_class_init (GtkNotebookClass *class)
110 {
111   GtkObjectClass *object_class;
112   GtkWidgetClass *widget_class;
113   GtkContainerClass *container_class;
114
115   object_class = (GtkObjectClass*) class;
116   widget_class = (GtkWidgetClass*) class;
117   container_class = (GtkContainerClass*) class;
118
119   parent_class = gtk_type_class (gtk_container_get_type ());
120
121   notebook_signals[SWITCH_PAGE] =
122     gtk_signal_new ("switch_page",
123                     GTK_RUN_LAST,
124                     object_class->type,
125                     GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
126                     gtk_notebook_marshal_signal,
127                     GTK_TYPE_NONE, 1,
128                     GTK_TYPE_POINTER);
129
130   gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
131
132   object_class->destroy = gtk_notebook_destroy;
133
134   widget_class->map = gtk_notebook_map;
135   widget_class->unmap = gtk_notebook_unmap;
136   widget_class->realize = gtk_notebook_realize;
137   widget_class->unrealize = gtk_notebook_unrealize;
138   widget_class->size_request = gtk_notebook_size_request;
139   widget_class->size_allocate = gtk_notebook_size_allocate;
140   widget_class->draw = gtk_notebook_draw;
141   widget_class->expose_event = gtk_notebook_expose;
142   widget_class->button_press_event = gtk_notebook_button_press;
143
144   container_class->add = gtk_notebook_add;
145   container_class->remove = gtk_notebook_remove;
146   container_class->foreach = gtk_notebook_foreach;
147
148   class->switch_page = gtk_real_notebook_switch_page;
149 }
150
151 static void
152 gtk_notebook_init (GtkNotebook *notebook)
153 {
154   notebook->cur_page = NULL;
155   notebook->children = NULL;
156   notebook->show_tabs = TRUE;
157   notebook->show_border = TRUE;
158   notebook->tab_pos = GTK_POS_TOP;
159 }
160
161 GtkWidget*
162 gtk_notebook_new ()
163 {
164   return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
165 }
166
167 void
168 gtk_notebook_append_page (GtkNotebook *notebook,
169                           GtkWidget   *child,
170                           GtkWidget   *tab_label)
171 {
172   g_return_if_fail (notebook != NULL);
173   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
174   g_return_if_fail (child != NULL);
175   g_return_if_fail (tab_label != NULL);
176
177   gtk_notebook_insert_page (notebook, child, tab_label, -1);
178 }
179
180 void
181 gtk_notebook_prepend_page (GtkNotebook *notebook,
182                            GtkWidget   *child,
183                            GtkWidget   *tab_label)
184 {
185   g_return_if_fail (notebook != NULL);
186   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
187   g_return_if_fail (child != NULL);
188   g_return_if_fail (tab_label != NULL);
189
190   gtk_notebook_insert_page (notebook, child, tab_label, 0);
191 }
192
193 void
194 gtk_notebook_insert_page (GtkNotebook *notebook,
195                           GtkWidget   *child,
196                           GtkWidget   *tab_label,
197                           gint         position)
198 {
199   GtkNotebookPage *page;
200   gint nchildren;
201
202   g_return_if_fail (notebook != NULL);
203   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
204   g_return_if_fail (child != NULL);
205   g_return_if_fail (tab_label != NULL);
206
207   page = g_new (GtkNotebookPage, 1);
208   page->child = child;
209   page->tab_label = tab_label;
210   page->requisition.width = 0;
211   page->requisition.height = 0;
212   page->allocation.x = 0;
213   page->allocation.y = 0;
214   page->allocation.width = 0;
215   page->allocation.height = 0;
216
217   nchildren = g_list_length (notebook->children);
218   if ((position < 0) || (position > nchildren))
219     position = nchildren;
220
221   notebook->children = g_list_insert (notebook->children, page, position);
222
223   if (!notebook->cur_page)
224     notebook->cur_page = page;
225
226   gtk_widget_show (tab_label);
227   gtk_widget_set_parent (child, GTK_WIDGET (notebook));
228   gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
229
230   if (GTK_WIDGET_VISIBLE (notebook))
231     {
232       if (GTK_WIDGET_REALIZED (notebook) &&
233           !GTK_WIDGET_REALIZED (child))
234         gtk_widget_realize (child);
235         
236
237       if (GTK_WIDGET_MAPPED (notebook) &&
238           !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
239         gtk_widget_map (child);
240
241       if (GTK_WIDGET_REALIZED (notebook) &&
242           !GTK_WIDGET_REALIZED (tab_label))
243         gtk_widget_realize (tab_label);
244       
245       if (GTK_WIDGET_MAPPED (notebook) &&
246           !GTK_WIDGET_MAPPED (tab_label))
247         gtk_widget_map (tab_label);
248     }
249
250   if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
251     gtk_widget_queue_resize (child);
252 }
253
254 void
255 gtk_notebook_remove_page (GtkNotebook *notebook,
256                           gint         page_num)
257 {
258   GtkNotebookPage *page;
259   GList *tmp_list;
260
261   g_return_if_fail (notebook != NULL);
262   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
263
264   tmp_list = g_list_nth (notebook->children, page_num);
265   if (tmp_list)
266     {
267       page = tmp_list->data;
268
269       if (notebook->cur_page == page)
270         gtk_notebook_prev_page (notebook);
271       if (notebook->cur_page == page)
272         notebook->cur_page = NULL;
273
274       notebook->children = g_list_remove_link (notebook->children, tmp_list);
275       g_list_free (tmp_list);
276       g_free (page);
277     }
278 }
279
280 gint
281 gtk_notebook_current_page (GtkNotebook *notebook)
282 {
283   GList *children;
284   gint cur_page;
285
286   g_return_val_if_fail (notebook != NULL, -1);
287   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
288
289   if (notebook->cur_page)
290     {
291       cur_page = 0;
292       children = notebook->children;
293
294       while (children)
295         {
296           if (children->data == notebook->cur_page)
297             break;
298           children = children->next;
299           cur_page += 1;
300         }
301
302       if (!children)
303         cur_page = -1;
304     }
305   else
306     {
307       cur_page = -1;
308     }
309
310   return cur_page;
311 }
312
313 void
314 gtk_notebook_set_page (GtkNotebook *notebook,
315                        gint         page_num)
316 {
317   GtkNotebookPage *page;
318   GList *tmp_list;
319
320   g_return_if_fail (notebook != NULL);
321   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
322
323   tmp_list = g_list_nth (notebook->children, page_num);
324   if (tmp_list)
325     {
326       page = tmp_list->data;
327       gtk_notebook_switch_page (notebook, page);
328     }
329 }
330
331 void
332 gtk_notebook_next_page (GtkNotebook *notebook)
333 {
334   GtkNotebookPage *page;
335   GList *children;
336
337   g_return_if_fail (notebook != NULL);
338   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
339
340   children = notebook->children;
341   while (children)
342     {
343       page = children->data;
344
345       if (notebook->cur_page == page)
346         {
347           children = children->next;
348           if (!children)
349             children = notebook->children;
350           page = children->data;
351
352           gtk_notebook_switch_page (notebook, page);
353         }
354
355       children = children->next;
356     }
357 }
358
359 void
360 gtk_notebook_prev_page (GtkNotebook *notebook)
361 {
362   GtkNotebookPage *page;
363   GList *children;
364
365   g_return_if_fail (notebook != NULL);
366   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
367
368   children = notebook->children;
369   while (children)
370     {
371       page = children->data;
372
373       if (notebook->cur_page == page)
374         {
375           children = children->prev;
376           if (!children)
377             children = g_list_last (notebook->children);
378           page = children->data;
379
380           gtk_notebook_switch_page (notebook, page);
381         }
382
383       children = children->next;
384     }
385 }
386
387 void
388 gtk_notebook_set_tab_pos (GtkNotebook     *notebook,
389                           GtkPositionType  pos)
390 {
391   g_return_if_fail (notebook != NULL);
392   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
393
394   if (notebook->tab_pos != pos)
395     {
396       notebook->tab_pos = pos;
397
398       if (GTK_WIDGET_VISIBLE (notebook))
399         gtk_widget_queue_resize (GTK_WIDGET (notebook));
400     }
401 }
402
403 void
404 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
405                             gint         show_tabs)
406 {
407   g_return_if_fail (notebook != NULL);
408   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
409
410   if (notebook->show_tabs != show_tabs)
411     {
412       notebook->show_tabs = show_tabs;
413
414       if (GTK_WIDGET_VISIBLE (notebook))
415         gtk_widget_queue_resize (GTK_WIDGET (notebook));
416     }
417 }
418
419 void
420 gtk_notebook_set_show_border (GtkNotebook *notebook,
421                               gint         show_border)
422 {
423   g_return_if_fail (notebook != NULL);
424   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
425
426   if (notebook->show_border != show_border)
427     {
428       notebook->show_border = show_border;
429
430       if (GTK_WIDGET_VISIBLE (notebook))
431         gtk_widget_queue_resize (GTK_WIDGET (notebook));
432     }
433 }
434
435 static void
436 gtk_notebook_destroy (GtkObject *object)
437 {
438   GtkNotebook *notebook;
439   GtkNotebookPage *page;
440   GList *children;
441
442   g_return_if_fail (object != NULL);
443   g_return_if_fail (GTK_IS_NOTEBOOK (object));
444
445   notebook = GTK_NOTEBOOK (object);
446
447   children = notebook->children;
448   while (children)
449     {
450       page = children->data;
451       children = children->next;
452
453       page->child->parent = NULL;
454       page->tab_label->parent = NULL;
455
456       gtk_object_unref (GTK_OBJECT (page->child));
457       gtk_object_unref (GTK_OBJECT (page->tab_label));
458
459       gtk_widget_destroy (page->child);
460       gtk_widget_destroy (page->tab_label);
461
462       g_free (page);
463     }
464
465   g_list_free (notebook->children);
466
467   if (GTK_OBJECT_CLASS (parent_class)->destroy)
468     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
469 }
470
471 static void
472 gtk_notebook_map (GtkWidget *widget)
473 {
474   GtkNotebook *notebook;
475   GtkNotebookPage *page;
476   GList *children;
477
478   g_return_if_fail (widget != NULL);
479   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
480
481   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
482   gdk_window_show (widget->window);
483
484   notebook = GTK_NOTEBOOK (widget);
485
486   if (notebook->cur_page &&
487       GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
488       !GTK_WIDGET_MAPPED (notebook->cur_page->child))
489     gtk_widget_map (notebook->cur_page->child);
490
491   children = notebook->children;
492   while (children)
493     {
494       page = children->data;
495       children = children->next;
496
497       if (GTK_WIDGET_VISIBLE (page->child) &&
498           !GTK_WIDGET_MAPPED (page->tab_label))
499         gtk_widget_map (page->tab_label);
500     }
501 }
502
503 static void
504 gtk_notebook_unmap (GtkWidget *widget)
505 {
506   g_return_if_fail (widget != NULL);
507   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
508
509   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
510   gdk_window_hide (widget->window);
511 }
512
513 static void
514 gtk_notebook_realize (GtkWidget *widget)
515 {
516   GtkNotebook *notebook;
517   GdkWindowAttr attributes;
518   gint attributes_mask;
519
520   g_return_if_fail (widget != NULL);
521   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
522
523   notebook = GTK_NOTEBOOK (widget);
524   GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
525
526   attributes.window_type = GDK_WINDOW_CHILD;
527   attributes.x = widget->allocation.x;
528   attributes.y = widget->allocation.y;
529   attributes.width = widget->allocation.width;
530   attributes.height = widget->allocation.height;
531   attributes.wclass = GDK_INPUT_OUTPUT;
532   attributes.visual = gtk_widget_get_visual (widget);
533   attributes.colormap = gtk_widget_get_colormap (widget);
534   attributes.event_mask = gtk_widget_get_events (widget);
535   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
536
537   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
538
539   widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
540   gdk_window_set_user_data (widget->window, notebook);
541
542   widget->style = gtk_style_attach (widget->style, widget->window);
543   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
544 }
545
546 static void
547 gtk_notebook_unrealize (GtkWidget *widget)
548 {
549   g_return_if_fail (widget != NULL);
550   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
551
552   GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED | GTK_MAPPED);
553
554   gtk_style_detach (widget->style);
555   gdk_window_destroy (widget->window);
556   widget->window = NULL;
557 }
558
559 static void
560 gtk_notebook_size_request (GtkWidget      *widget,
561                            GtkRequisition *requisition)
562 {
563   GtkNotebook *notebook;
564   GtkNotebookPage *page;
565   GList *children;
566   gint tab_width;
567   gint tab_height;
568
569   g_return_if_fail (widget != NULL);
570   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
571   g_return_if_fail (requisition != NULL);
572
573   notebook = GTK_NOTEBOOK (widget);
574   widget->requisition.width = 0;
575   widget->requisition.height = 0;
576
577   children = notebook->children;
578   while (children)
579     {
580       page = children->data;
581       children = children->next;
582
583       if (GTK_WIDGET_VISIBLE (page->child))
584         {
585           gtk_widget_size_request (page->child, &page->child->requisition);
586           
587           widget->requisition.width = MAX (widget->requisition.width,
588                                            page->child->requisition.width);
589           widget->requisition.height = MAX (widget->requisition.height,
590                                             page->child->requisition.height);
591         }
592     }
593
594   widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
595   widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
596
597   if (notebook->show_tabs)
598     {
599       widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
600       widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
601
602       tab_width = 0;
603       tab_height = 0;
604
605       children = notebook->children;
606       while (children)
607         {
608           page = children->data;
609           children = children->next;
610
611           if (GTK_WIDGET_VISIBLE (page->child))
612             {
613               gtk_widget_size_request (page->tab_label, &page->tab_label->requisition);
614
615               page->requisition.width = (page->tab_label->requisition.width +
616                                          (GTK_WIDGET (widget)->style->klass->xthickness +
617                                           CHILD_SPACING) * 2);
618               page->requisition.height = (page->tab_label->requisition.height +
619                                           (GTK_WIDGET (widget)->style->klass->ythickness +
620                                            CHILD_SPACING) * 2);
621
622               switch (notebook->tab_pos)
623                 {
624                 case GTK_POS_TOP:
625                 case GTK_POS_BOTTOM:
626                   page->requisition.width -= TAB_OVERLAP;
627                   page->requisition.height -= GTK_WIDGET (widget)->style->klass->ythickness;
628
629                   tab_width += page->requisition.width;
630                   tab_height = MAX (tab_height, page->requisition.height);
631                   break;
632                 case GTK_POS_LEFT:
633                 case GTK_POS_RIGHT:
634                   page->requisition.width -= GTK_WIDGET (widget)->style->klass->xthickness;
635                   page->requisition.height -= TAB_OVERLAP;
636
637                   tab_width = MAX (tab_width, page->requisition.width);
638                   tab_height += page->requisition.height;
639                   break;
640                 }
641             }
642         }
643
644       children = notebook->children;
645       while (children)
646         {
647           page = children->data;
648           children = children->next;
649
650           if (GTK_WIDGET_VISIBLE (page->child))
651             {
652               if ((notebook->tab_pos == GTK_POS_TOP) ||
653                   (notebook->tab_pos == GTK_POS_BOTTOM))
654                 page->requisition.height = tab_height;
655               else
656                 page->requisition.width = tab_width;
657             }
658         }
659
660       switch (notebook->tab_pos)
661         {
662         case GTK_POS_TOP:
663         case GTK_POS_BOTTOM:
664           tab_width += GTK_WIDGET (widget)->style->klass->xthickness;
665           widget->requisition.width = MAX (widget->requisition.width, tab_width);
666           widget->requisition.height += tab_height;
667           break;
668         case GTK_POS_LEFT:
669         case GTK_POS_RIGHT:
670           tab_height += GTK_WIDGET (widget)->style->klass->ythickness;
671           widget->requisition.width += tab_width;
672           widget->requisition.height = MAX (widget->requisition.height, tab_height);
673           break;
674         }
675     }
676   else if (notebook->show_border)
677     {
678       widget->requisition.width += GTK_WIDGET (widget)->style->klass->xthickness * 2;
679       widget->requisition.height += GTK_WIDGET (widget)->style->klass->ythickness * 2;
680     }
681 }
682
683 static void
684 gtk_notebook_size_allocate (GtkWidget     *widget,
685                             GtkAllocation *allocation)
686 {
687   GtkNotebook *notebook;
688   GtkNotebookPage *page;
689   GtkAllocation child_allocation;
690   GList *children;
691
692   g_return_if_fail (widget != NULL);
693   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
694   g_return_if_fail (allocation != NULL);
695
696   widget->allocation = *allocation;
697   if (GTK_WIDGET_REALIZED (widget))
698     gdk_window_move_resize (widget->window,
699                             allocation->x, allocation->y,
700                             allocation->width, allocation->height);
701
702   notebook = GTK_NOTEBOOK (widget);
703   if (notebook->children)
704     {
705       child_allocation.x = GTK_CONTAINER (widget)->border_width;
706       child_allocation.y = GTK_CONTAINER (widget)->border_width;
707       child_allocation.width = allocation->width - child_allocation.x * 2;
708       child_allocation.height = allocation->height - child_allocation.y * 2;
709
710       if (notebook->show_tabs || notebook->show_border)
711         {
712           child_allocation.x += GTK_WIDGET (widget)->style->klass->xthickness;
713           child_allocation.y += GTK_WIDGET (widget)->style->klass->ythickness;
714           child_allocation.width -= GTK_WIDGET (widget)->style->klass->xthickness * 2;
715           child_allocation.height -= GTK_WIDGET (widget)->style->klass->ythickness * 2;
716
717           if (notebook->show_tabs && notebook->children)
718             {
719               switch (notebook->tab_pos)
720                 {
721                 case GTK_POS_TOP:
722                   child_allocation.y += notebook->cur_page->requisition.height;
723                 case GTK_POS_BOTTOM:
724                   child_allocation.height -= notebook->cur_page->requisition.height;
725                   break;
726                 case GTK_POS_LEFT:
727                   child_allocation.x += notebook->cur_page->requisition.width;
728                 case GTK_POS_RIGHT:
729                   child_allocation.width -= notebook->cur_page->requisition.width;
730                   break;
731                 }
732             }
733         }
734
735       children = notebook->children;
736       while (children)
737         {
738           page = children->data;
739           children = children->next;
740           
741           if (GTK_WIDGET_VISIBLE (page->child))
742             gtk_widget_size_allocate (page->child, &child_allocation);
743         }
744
745       if (notebook->show_tabs && notebook->children)
746         gtk_notebook_pages_allocate (notebook, allocation);
747     }
748 }
749
750 static void
751 gtk_notebook_paint (GtkWidget    *widget,
752                     GdkRectangle *area)
753 {
754   GtkNotebook *notebook;
755   GtkNotebookPage *page;
756   GList *children;
757   GdkPoint points[6];
758   gint width, height;
759   gint x, y;
760
761   g_return_if_fail (widget != NULL);
762   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
763   g_return_if_fail (area != NULL);
764
765   if (GTK_WIDGET_DRAWABLE (widget))
766     {
767       notebook = GTK_NOTEBOOK (widget);
768
769       gdk_window_clear_area (widget->window,
770                              area->x, area->y,
771                              area->width, area->height);
772
773       if (notebook->show_tabs || notebook->show_border)
774         {
775           x = GTK_CONTAINER (widget)->border_width;
776           y = GTK_CONTAINER (widget)->border_width;
777           width = widget->allocation.width - x * 2;
778           height = widget->allocation.height - y * 2;
779
780           if (notebook->show_tabs && notebook->children)
781             {
782               switch (notebook->tab_pos)
783                 {
784                 case GTK_POS_TOP:
785                   y += notebook->cur_page->allocation.height;
786                 case GTK_POS_BOTTOM:
787                   height -= notebook->cur_page->allocation.height;
788                   break;
789                 case GTK_POS_LEFT:
790                   x += notebook->cur_page->allocation.width;
791                 case GTK_POS_RIGHT:
792                   width -= notebook->cur_page->allocation.width;
793                   break;
794                 }
795
796               switch (notebook->tab_pos)
797                 {
798                 case GTK_POS_TOP:
799                   points[0].x = notebook->cur_page->allocation.x;
800                   points[0].y = y;
801                   points[1].x = x;
802                   points[1].y = y;
803                   points[2].x = x;
804                   points[2].y = y + height - 1;
805                   points[3].x = x + width - 1;
806                   points[3].y = y + height - 1;
807                   points[4].x = x + width - 1;
808                   points[4].y = y;
809                   points[5].x = (notebook->cur_page->allocation.x +
810                                  notebook->cur_page->allocation.width -
811                                  GTK_WIDGET (notebook)->style->klass->xthickness);
812                   points[5].y = y;
813
814                   if (points[5].x == (x + width))
815                     points[5].x -= 1;
816                   break;
817                 case GTK_POS_BOTTOM:
818                   points[0].x = (notebook->cur_page->allocation.x +
819                                  notebook->cur_page->allocation.width -
820                                  GTK_WIDGET (notebook)->style->klass->xthickness);
821                   points[0].y = y + height - 1;
822                   points[1].x = x + width - 1;
823                   points[1].y = y + height - 1;
824                   points[2].x = x + width - 1;
825                   points[2].y = y;
826                   points[3].x = x;
827                   points[3].y = y;
828                   points[4].x = x;
829                   points[4].y = y + height - 1;
830                   points[5].x = notebook->cur_page->allocation.x;
831                   points[5].y = y + height - 1;
832
833                   if (points[0].x == (x + width))
834                     points[0].x -= 1;
835                   break;
836                 case GTK_POS_LEFT:
837                   points[0].x = x;
838                   points[0].y = (notebook->cur_page->allocation.y +
839                                  notebook->cur_page->allocation.height -
840                                  GTK_WIDGET (notebook)->style->klass->ythickness);
841                   points[1].x = x;
842                   points[1].y = y + height - 1;
843                   points[2].x = x + width - 1;
844                   points[2].y = y + height - 1;
845                   points[3].x = x + width - 1;
846                   points[3].y = y;
847                   points[4].x = x;
848                   points[4].y = y;
849                   points[5].x = x;
850                   points[5].y = notebook->cur_page->allocation.y;
851
852                   if (points[0].y == (y + height))
853                     points[0].y -= 1;
854                   break;
855                 case GTK_POS_RIGHT:
856                   points[0].x = x + width - 1;
857                   points[0].y = notebook->cur_page->allocation.y;
858                   points[1].x = x + width - 1;
859                   points[1].y = y;
860                   points[2].x = x;
861                   points[2].y = y;
862                   points[3].x = x;
863                   points[3].y = y + height - 1;
864                   points[4].x = x + width - 1;
865                   points[4].y = y + height - 1;
866                   points[5].x = x + width - 1;
867                   points[5].y = (notebook->cur_page->allocation.y +
868                                  notebook->cur_page->allocation.height -
869                                  GTK_WIDGET (notebook)->style->klass->ythickness);
870
871                   if (points[5].y == (y + height))
872                     points[5].y -= 1;
873                   break;
874                 }
875
876               gtk_draw_polygon (widget->style, widget->window,
877                                 GTK_STATE_NORMAL, GTK_SHADOW_OUT,
878                                 points, 6, FALSE);
879
880               children = g_list_last (notebook->children);
881               while (children)
882                 {
883                   page = children->data;
884                   children = children->prev;
885
886                   if (notebook->cur_page != page)
887                     gtk_notebook_draw_tab (notebook, page, area);
888                 }
889
890               if (notebook->cur_page)
891                 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
892             }
893           else if (notebook->show_border)
894             {
895               gtk_draw_shadow (widget->style, widget->window,
896                                GTK_STATE_NORMAL, GTK_SHADOW_OUT,
897                                x, y, width, height);
898             }
899         }
900     }
901 }
902
903 static void
904 gtk_notebook_draw (GtkWidget    *widget,
905                    GdkRectangle *area)
906 {
907   GtkNotebook *notebook;
908   GdkRectangle child_area;
909
910   g_return_if_fail (widget != NULL);
911   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
912   g_return_if_fail (area != NULL);
913
914   if (GTK_WIDGET_DRAWABLE (widget))
915     {
916       notebook = GTK_NOTEBOOK (widget);
917
918       gtk_notebook_paint (widget, area);
919
920       if (notebook->cur_page &&
921           gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
922         gtk_widget_draw (notebook->cur_page->child, &child_area);
923     }
924 }
925
926 static gint
927 gtk_notebook_expose (GtkWidget      *widget,
928                      GdkEventExpose *event)
929 {
930   GtkNotebook *notebook;
931   GdkEventExpose child_event;
932
933   g_return_val_if_fail (widget != NULL, FALSE);
934   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
935   g_return_val_if_fail (event != NULL, FALSE);
936
937   if (GTK_WIDGET_DRAWABLE (widget))
938     {
939       notebook = GTK_NOTEBOOK (widget);
940
941       gtk_notebook_paint (widget, &event->area);
942
943       child_event = *event;
944       if (notebook->cur_page && GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
945           gtk_widget_intersect (notebook->cur_page->child, &event->area, &child_event.area))
946         gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
947     }
948
949   return FALSE;
950 }
951
952 static gint
953 gtk_notebook_button_press (GtkWidget      *widget,
954                            GdkEventButton *event)
955 {
956   GtkNotebook *notebook;
957   GtkNotebookPage *page;
958   GList *children;
959
960   g_return_val_if_fail (widget != NULL, FALSE);
961   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
962   g_return_val_if_fail (event != NULL, FALSE);
963
964   if ((event->type != GDK_BUTTON_PRESS) ||
965       (event->window != widget->window))
966     return FALSE;
967
968   notebook = GTK_NOTEBOOK (widget);
969
970   children = notebook->children;
971   while (children)
972     {
973       page = children->data;
974
975       if (GTK_WIDGET_VISIBLE (page->child) &&
976           (event->x >= page->allocation.x) &&
977           (event->y >= page->allocation.y) &&
978           (event->x <= (page->allocation.x + page->allocation.width)) &&
979           (event->y <= (page->allocation.y + page->allocation.height)))
980         {
981           gtk_notebook_switch_page (notebook, page);
982           break;
983         }
984       children = children->next;
985     }
986
987   return FALSE;
988 }
989
990 static void
991 gtk_notebook_add (GtkContainer *container,
992                   GtkWidget    *widget)
993 {
994   g_warning ("gtk_notebook_add: use gtk_notebook_{append,prepend}_page instead\n");
995 }
996
997 static void
998 gtk_notebook_remove (GtkContainer *container,
999                      GtkWidget    *widget)
1000 {
1001   GtkNotebook *notebook;
1002   GtkNotebookPage *page;
1003   GList *children;
1004
1005   g_return_if_fail (container != NULL);
1006   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1007   g_return_if_fail (widget != NULL);
1008
1009   notebook = GTK_NOTEBOOK (container);
1010
1011   children = notebook->children;
1012   while (children)
1013     {
1014       page = children->data;
1015
1016       if (page->child == widget)
1017         {
1018           gtk_widget_unparent (page->child);
1019           gtk_widget_unparent (page->tab_label);
1020
1021           notebook->children = g_list_remove_link (notebook->children, children);
1022           g_list_free (children);
1023           g_free (page);
1024
1025           if (GTK_WIDGET_VISIBLE (widget) && GTK_WIDGET_VISIBLE (container))
1026             gtk_widget_queue_resize (GTK_WIDGET (container));
1027
1028           break;
1029         }
1030
1031       children = children->next;
1032     }
1033 }
1034
1035 static void
1036 gtk_notebook_foreach (GtkContainer *container,
1037                       GtkCallback   callback,
1038                       gpointer      callback_data)
1039 {
1040   GtkNotebook *notebook;
1041   GtkNotebookPage *page;
1042   GList *children;
1043
1044   g_return_if_fail (container != NULL);
1045   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1046   g_return_if_fail (callback != NULL);
1047
1048   notebook = GTK_NOTEBOOK (container);
1049
1050   children = notebook->children;
1051   while (children)
1052     {
1053       page = children->data;
1054       children = children->next;
1055
1056       (* callback) (page->child, callback_data);
1057     }
1058 }
1059
1060 static void
1061 gtk_real_notebook_switch_page (GtkNotebook     *notebook,
1062                                GtkNotebookPage *page)
1063 {
1064   g_return_if_fail (notebook != NULL);
1065   g_return_if_fail (page != NULL);
1066
1067   if (notebook->cur_page != page)
1068     {
1069       if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
1070         gtk_widget_unmap (notebook->cur_page->child);
1071
1072       notebook->cur_page = page;
1073       gtk_notebook_pages_allocate (notebook, &GTK_WIDGET (notebook)->allocation);
1074
1075       if (GTK_WIDGET_MAPPED (notebook))
1076         {
1077           if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
1078             {
1079               gtk_widget_map (notebook->cur_page->child);
1080             }
1081           else
1082             {
1083               gtk_widget_map (notebook->cur_page->child);
1084               gtk_widget_size_allocate (GTK_WIDGET (notebook), 
1085                                         &GTK_WIDGET (notebook)->allocation);
1086             }
1087         }
1088
1089       if (GTK_WIDGET_DRAWABLE (notebook))
1090         gtk_widget_queue_draw (GTK_WIDGET (notebook));
1091     }
1092 }
1093
1094
1095 static void
1096 gtk_notebook_draw_tab (GtkNotebook     *notebook,
1097                        GtkNotebookPage *page,
1098                        GdkRectangle    *area)
1099 {
1100   GdkRectangle child_area;
1101   GdkRectangle page_area;
1102   GtkStateType state_type;
1103   GdkPoint points[6];
1104   gint n;
1105  
1106   g_return_if_fail (notebook != NULL);
1107   g_return_if_fail (page != NULL);
1108   g_return_if_fail (area != NULL);
1109
1110   page_area.x = page->allocation.x;
1111   page_area.y = page->allocation.y;
1112   page_area.width = page->allocation.width;
1113   page_area.height = page->allocation.height;
1114
1115   if (gdk_rectangle_intersect (&page_area, area, &child_area))
1116     {
1117       GtkWidget *widget;
1118
1119       switch (notebook->tab_pos)
1120         {
1121         case GTK_POS_TOP:
1122           if( child_area.x + child_area.width > 
1123               page->allocation.x + page->allocation.width - TAB_OVERLAP ) 
1124             {
1125               points[0].x = page->allocation.x + page->allocation.width - 1;
1126               points[0].y = page->allocation.y + page->allocation.height - 1;
1127
1128               points[1].x = page->allocation.x + page->allocation.width - 1;
1129               points[1].y = page->allocation.y + TAB_CURVATURE;
1130
1131               points[2].x = page->allocation.x + page->allocation.width 
1132                 - TAB_CURVATURE - 1;
1133               points[2].y = page->allocation.y;
1134               n = 3;
1135             }
1136           else 
1137             {
1138               points[0].x = page->allocation.x + page->allocation.width 
1139                 - TAB_OVERLAP - 1;
1140               points[0].y = page->allocation.y;
1141               n = 1;
1142             }
1143           
1144           if( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1145               (page == notebook->cur_page || 
1146                page == (GtkNotebookPage *)(notebook->children->data)) ) 
1147             {
1148               points[n].x = page->allocation.x + TAB_CURVATURE;
1149               points[n++].y = page->allocation.y;
1150             
1151               points[n].x = page->allocation.x;
1152               points[n++].y = page->allocation.y + TAB_CURVATURE;
1153
1154               points[n].x = page->allocation.x;
1155               points[n++].y = page->allocation.y + page->allocation.height - 1;
1156             }
1157           else 
1158             {
1159               points[n].x = page->allocation.x + TAB_OVERLAP;
1160               points[n++].y = page->allocation.y;
1161             }
1162           break;
1163         case GTK_POS_BOTTOM:
1164           if( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
1165               (page == notebook->cur_page || 
1166                page == (GtkNotebookPage *)(notebook->children->data)) ) 
1167             {
1168               points[0].x = page->allocation.x;
1169               points[0].y = page->allocation.y;
1170
1171               points[1].x = page->allocation.x;
1172               points[1].y = page->allocation.y + page->allocation.height 
1173                 - TAB_CURVATURE - 1;
1174
1175               points[2].x = page->allocation.x + TAB_CURVATURE;
1176               points[2].y = page->allocation.y + page->allocation.height - 1;
1177               n = 3;
1178             }
1179           else 
1180             {
1181               points[0].x = page->allocation.x + TAB_OVERLAP;
1182               points[0].y = page->allocation.y + page->allocation.height - 1;
1183               n = 1;
1184             }
1185
1186           if( child_area.x + child_area.width > 
1187               page->allocation.x + page->allocation.width - TAB_OVERLAP ) 
1188             {
1189               points[n].x = page->allocation.x + page->allocation.width 
1190                 - TAB_CURVATURE - 1;
1191               points[n++].y = page->allocation.y + page->allocation.height - 1;
1192
1193               points[n].x = page->allocation.x + page->allocation.width - 1;
1194               points[n++].y = page->allocation.y + page->allocation.height 
1195                 - TAB_CURVATURE - 1;
1196             
1197               points[n].x = page->allocation.x + page->allocation.width - 1;
1198               points[n++].y = page->allocation.y;
1199             }
1200           else 
1201             {
1202               points[n].x = page->allocation.x + page->allocation.width 
1203                 - TAB_OVERLAP - 1;
1204               points[n++].y = page->allocation.y + page->allocation.height - 1;
1205             }
1206           break;
1207         case GTK_POS_LEFT:
1208           if( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
1209               (page == notebook->cur_page || 
1210                page == (GtkNotebookPage *)(notebook->children->data)) ) 
1211             {
1212               points[0].x = page->allocation.x + page->allocation.width - 1;
1213               points[0].y = page->allocation.y;
1214               
1215               points[1].x = page->allocation.x + TAB_CURVATURE;
1216               points[1].y = page->allocation.y;
1217
1218               points[2].x = page->allocation.x;
1219               points[2].y = page->allocation.y + TAB_CURVATURE;
1220               n = 3;
1221             }
1222           else 
1223             {
1224               points[0].x = page->allocation.x;
1225               points[0].y = page->allocation.y + TAB_OVERLAP;
1226               n = 1;
1227             }
1228
1229           if( child_area.y + child_area.height > 
1230               page->allocation.y + page->allocation.height - TAB_OVERLAP ) 
1231             {
1232               points[n].x = page->allocation.x;
1233               points[n++].y = page->allocation.y + page->allocation.height 
1234                 - TAB_CURVATURE - 1;
1235
1236               points[n].x = page->allocation.x + TAB_CURVATURE;
1237               points[n++].y = page->allocation.y + page->allocation.height - 1;
1238
1239               points[n].x = page->allocation.x + page->allocation.width - 1;
1240               points[n++].y = page->allocation.y + page->allocation.height - 1;
1241             }
1242           else 
1243             {
1244               points[n].x = page->allocation.x;
1245               points[n++].y = page->allocation.y + page->allocation.height 
1246                 - TAB_OVERLAP - 1;
1247             }
1248           break;
1249         case GTK_POS_RIGHT:
1250           if( child_area.y + child_area.height > 
1251               page->allocation.y + page->allocation.height - TAB_OVERLAP ) 
1252             {
1253               points[0].x = page->allocation.x;
1254               points[0].y = page->allocation.y + page->allocation.height - 1;
1255
1256               points[1].x = page->allocation.x + page->allocation.width 
1257                 - TAB_CURVATURE - 1;
1258               points[1].y = page->allocation.y + page->allocation.height - 1;
1259               
1260               points[2].x = page->allocation.x + page->allocation.width - 1;
1261               points[2].y = page->allocation.y + page->allocation.height 
1262                 - TAB_CURVATURE - 1;
1263               n = 3;
1264             }
1265           else 
1266             {
1267               points[0].x = page->allocation.x + page->allocation.width - 1;
1268               points[0].y = page->allocation.y + page->allocation.height 
1269                 - TAB_OVERLAP - 1;
1270               n = 1;
1271             }
1272
1273           if( (child_area.y < page->allocation.y + TAB_OVERLAP) && 
1274               (page == notebook->cur_page || 
1275                page == (GtkNotebookPage *)(notebook->children->data)) ) 
1276             {
1277               points[n].x = page->allocation.x + page->allocation.width - 1;
1278               points[n++].y = page->allocation.y + TAB_CURVATURE;
1279
1280               points[n].x = page->allocation.x + page->allocation.width 
1281                 - TAB_CURVATURE - 1;
1282               points[n++].y = page->allocation.y;
1283
1284               points[n].x = page->allocation.x;
1285               points[n++].y = page->allocation.y;
1286             }
1287           else 
1288             {
1289               points[n].x = page->allocation.x + page->allocation.width - 1;
1290               points[n++].y = page->allocation.y + TAB_OVERLAP;
1291             }
1292           break;
1293         }
1294
1295       widget = GTK_WIDGET(notebook);
1296
1297       if (notebook->cur_page == page)
1298         state_type = GTK_STATE_NORMAL;
1299       else 
1300         {
1301           state_type = GTK_STATE_ACTIVE;
1302         
1303           gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
1304                               TRUE, child_area.x, child_area.y,
1305                               child_area.width, child_area.height);
1306         }
1307
1308       gtk_draw_polygon (widget->style, widget->window, state_type, 
1309                         GTK_SHADOW_OUT, points, n, FALSE);
1310         
1311       if (gtk_widget_intersect (page->tab_label, area, &child_area))
1312         gtk_widget_draw (page->tab_label, &child_area);
1313     }
1314 }
1315
1316
1317 static void
1318 gtk_notebook_pages_allocate (GtkNotebook   *notebook,
1319                              GtkAllocation *allocation)
1320 {
1321   GtkNotebookPage *page;
1322   GtkAllocation child_allocation;
1323   GList *children;
1324
1325   if (notebook->show_tabs && notebook->children)
1326     {
1327       child_allocation.x = GTK_CONTAINER (notebook)->border_width;
1328       child_allocation.y = GTK_CONTAINER (notebook)->border_width;
1329
1330       switch (notebook->tab_pos)
1331         {
1332         case GTK_POS_BOTTOM:
1333           child_allocation.y = allocation->height - notebook->cur_page->requisition.height;
1334         case GTK_POS_TOP:
1335           child_allocation.height = notebook->cur_page->requisition.height;
1336           break;
1337         case GTK_POS_RIGHT:
1338           child_allocation.x = allocation->width - notebook->cur_page->requisition.width;
1339         case GTK_POS_LEFT:
1340           child_allocation.width = notebook->cur_page->requisition.width;
1341           break;
1342         }
1343
1344       children = notebook->children;
1345       while (children)
1346         {
1347           page = children->data;
1348           children = children->next;
1349
1350           if (GTK_WIDGET_VISIBLE (page->child))
1351             {
1352               switch (notebook->tab_pos)
1353                 {
1354                 case GTK_POS_TOP:
1355                 case GTK_POS_BOTTOM:
1356                   child_allocation.width = page->requisition.width + TAB_OVERLAP;
1357                   break;
1358                 case GTK_POS_LEFT:
1359                 case GTK_POS_RIGHT:
1360                   child_allocation.height = page->requisition.height + TAB_OVERLAP;
1361                   break;
1362                 }
1363
1364               gtk_notebook_page_allocate (notebook, page, &child_allocation);
1365
1366               switch (notebook->tab_pos)
1367                 {
1368                 case GTK_POS_TOP:
1369                 case GTK_POS_BOTTOM:
1370                   child_allocation.x += child_allocation.width - TAB_OVERLAP;
1371                   break;
1372                 case GTK_POS_LEFT:
1373                 case GTK_POS_RIGHT:
1374                   child_allocation.y += child_allocation.height - TAB_OVERLAP;
1375                   break;
1376                 }
1377             }
1378         }
1379     }
1380 }
1381
1382 static void
1383 gtk_notebook_page_allocate (GtkNotebook     *notebook,
1384                             GtkNotebookPage *page,
1385                             GtkAllocation   *allocation)
1386 {
1387   GtkAllocation child_allocation;
1388   gint xthickness, ythickness;
1389
1390   g_return_if_fail (notebook != NULL);
1391   g_return_if_fail (page != NULL);
1392   g_return_if_fail (allocation != NULL);
1393
1394   page->allocation = *allocation;
1395
1396   xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
1397   ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
1398
1399   if (notebook->cur_page != page)
1400     {
1401       switch (notebook->tab_pos)
1402         {
1403         case GTK_POS_TOP:
1404           page->allocation.y += ythickness;
1405         case GTK_POS_BOTTOM:
1406           page->allocation.height -= ythickness;
1407           break;
1408         case GTK_POS_LEFT:
1409           page->allocation.x += xthickness;
1410         case GTK_POS_RIGHT:
1411           page->allocation.width -= xthickness;
1412           break;
1413         }
1414     }
1415
1416   switch (notebook->tab_pos)
1417     {
1418     case GTK_POS_TOP:
1419       child_allocation.x = xthickness + CHILD_SPACING;
1420       child_allocation.y = ythickness + CHILD_SPACING;
1421       child_allocation.width = page->allocation.width - child_allocation.x * 2;
1422       child_allocation.height = page->allocation.height - child_allocation.y;
1423       child_allocation.x += page->allocation.x;
1424       child_allocation.y += page->allocation.y;
1425       break;
1426     case GTK_POS_BOTTOM:
1427       child_allocation.x = xthickness + CHILD_SPACING;
1428       child_allocation.y = ythickness + CHILD_SPACING;
1429       child_allocation.width = page->allocation.width - child_allocation.x * 2;
1430       child_allocation.height = page->allocation.height - child_allocation.y;
1431       child_allocation.x += page->allocation.x;
1432       child_allocation.y = page->allocation.y;
1433       break;
1434     case GTK_POS_LEFT:
1435       child_allocation.x = xthickness + CHILD_SPACING;
1436       child_allocation.y = ythickness + CHILD_SPACING;
1437       child_allocation.width = page->allocation.width - child_allocation.x;
1438       child_allocation.height = page->allocation.height - child_allocation.y * 2;
1439       child_allocation.x += page->allocation.x;
1440       child_allocation.y += page->allocation.y;
1441       break;
1442     case GTK_POS_RIGHT:
1443       child_allocation.x = xthickness + CHILD_SPACING;
1444       child_allocation.y = ythickness + CHILD_SPACING;
1445       child_allocation.width = page->allocation.width - child_allocation.x;
1446       child_allocation.height = page->allocation.height - child_allocation.y * 2;
1447       child_allocation.x = page->allocation.x;
1448       child_allocation.y += page->allocation.y;
1449       break;
1450     }
1451
1452   gtk_widget_size_allocate (page->tab_label, &child_allocation);
1453 }
1454
1455 static void
1456 gtk_notebook_switch_page (GtkNotebook *notebook, GtkNotebookPage *page)
1457 {
1458   gtk_signal_emit (GTK_OBJECT (notebook), notebook_signals[SWITCH_PAGE], page);
1459 }
1460
1461 static void
1462 gtk_notebook_marshal_signal (GtkObject      *object,
1463                              GtkSignalFunc   func,
1464                              gpointer        func_data,
1465                              GtkArg         *args)
1466 {
1467   GtkNotebookSignal rfunc;
1468
1469   rfunc = (GtkNotebookSignal) func;
1470
1471   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
1472 }