]> Pileus Git - ~andy/gtk/blob - gtk/gtknotebook.c
export gtk_binary_age and gtk_interface_age.
[~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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include "gtknotebook.h"
20 #include "gtksignal.h"
21 #include "gtkmain.h"
22 #include "gtkmenu.h"
23 #include "gtkmenuitem.h"
24 #include "gtklabel.h"
25 #include <gdk/gdkkeysyms.h>
26 #include <stdio.h>
27
28
29 #define TAB_OVERLAP    2
30 #define TAB_CURVATURE  1
31 #define ARROW_SIZE     11
32 #define ARROW_SPACING  3
33 #define NOTEBOOK_INIT_SCROLL_DELAY (200)
34 #define NOTEBOOK_SCROLL_DELAY      (100)
35
36
37 enum {
38   SWITCH_PAGE,
39   LAST_SIGNAL
40 };
41
42 enum {
43   STEP_PREV,
44   STEP_NEXT
45 };
46
47 enum {
48   ARG_0,
49   ARG_TAB_POS,
50   ARG_SHOW_TABS,
51   ARG_SHOW_BORDER,
52   ARG_SCROLLABLE,
53   ARG_TAB_BORDER,
54   ARG_PAGE,
55   ARG_ENABLE_POPUP
56 };
57
58 enum {
59   CHILD_ARG_0,
60   CHILD_ARG_TAB_LABEL,
61   CHILD_ARG_MENU_LABEL,
62   CHILD_ARG_POSITION
63 };
64
65 typedef void (*GtkNotebookSignal) (GtkObject       *object,
66                                    GtkNotebookPage *arg1,
67                                    gint             arg2,
68                                    gpointer         data);
69
70 static void gtk_notebook_class_init          (GtkNotebookClass *klass);
71 static void gtk_notebook_init                (GtkNotebook      *notebook);
72 static void gtk_notebook_set_arg             (GtkObject        *object,
73                                               GtkArg           *arg,
74                                               guint             arg_id);
75 static void gtk_notebook_get_arg             (GtkObject        *object,
76                                               GtkArg           *arg,
77                                               guint             arg_id);
78 static void gtk_notebook_set_child_arg       (GtkContainer     *container,
79                                               GtkWidget        *child,
80                                               GtkArg           *arg,
81                                               guint             arg_id);
82 static void gtk_notebook_get_child_arg       (GtkContainer     *container,
83                                               GtkWidget        *child,
84                                               GtkArg           *arg,
85                                               guint             arg_id);
86 static void gtk_notebook_destroy             (GtkObject        *object);
87 static void gtk_notebook_map                 (GtkWidget        *widget);
88 static void gtk_notebook_unmap               (GtkWidget        *widget);
89 static void gtk_notebook_realize             (GtkWidget        *widget);
90 static void gtk_notebook_panel_realize       (GtkNotebook      *notebook);
91 static void gtk_notebook_size_request        (GtkWidget        *widget,
92                                               GtkRequisition   *requisition);
93 static void gtk_notebook_size_allocate       (GtkWidget        *widget,
94                                               GtkAllocation    *allocation);
95 static void gtk_notebook_paint               (GtkWidget        *widget,
96                                               GdkRectangle     *area);
97 static void gtk_notebook_draw                (GtkWidget        *widget,
98                                               GdkRectangle     *area);
99 static gint gtk_notebook_expose              (GtkWidget        *widget,
100                                               GdkEventExpose   *event);
101 static gint gtk_notebook_button_press        (GtkWidget        *widget,
102                                               GdkEventButton   *event);
103 static gint gtk_notebook_button_release      (GtkWidget        *widget,
104                                               GdkEventButton   *event);
105 static gint gtk_notebook_enter_notify        (GtkWidget        *widget,
106                                               GdkEventCrossing *event);
107 static gint gtk_notebook_leave_notify        (GtkWidget        *widget,
108                                               GdkEventCrossing *event);
109 static gint gtk_notebook_motion_notify       (GtkWidget        *widget,
110                                               GdkEventMotion   *event);
111 static gint gtk_notebook_key_press           (GtkWidget        *widget,
112                                               GdkEventKey      *event);
113 static void gtk_notebook_add                 (GtkContainer     *container,
114                                               GtkWidget        *widget);
115 static void gtk_notebook_remove              (GtkContainer     *container,
116                                               GtkWidget        *widget);
117 static void gtk_notebook_real_remove         (GtkNotebook      *notebook,
118                                               GList            *list,
119                                               guint             page_num);
120 static void gtk_notebook_foreach             (GtkContainer     *container,
121                                               GtkCallback       callback,
122                                               gpointer          callback_data);
123 static void gtk_notebook_switch_page         (GtkNotebook      *notebook,
124                                               GtkNotebookPage  *page,
125                                               guint             page_num);
126 static void gtk_notebook_draw_tab            (GtkNotebook      *notebook,
127                                               GtkNotebookPage  *page,
128                                               GdkRectangle     *area);
129 static void gtk_notebook_set_focus_child     (GtkContainer     *container,
130                                               GtkWidget        *child);
131 static gint gtk_notebook_focus_in            (GtkWidget        *widget,
132                                               GdkEventFocus    *event);
133 static gint gtk_notebook_focus_out           (GtkWidget        *widget,
134                                               GdkEventFocus    *event);
135 static void gtk_notebook_draw_focus          (GtkWidget        *widget);
136 static void gtk_notebook_focus_changed       (GtkNotebook      *notebook, 
137                                               GtkNotebookPage  *old_page);
138 static void gtk_notebook_pages_allocate      (GtkNotebook      *notebook,
139                                               GtkAllocation    *allocation);
140 static void gtk_notebook_page_allocate       (GtkNotebook      *notebook,
141                                               GtkNotebookPage  *page,
142                                               GtkAllocation    *allocation);
143 static void gtk_notebook_draw_arrow          (GtkNotebook      *notebook, 
144                                               guint             arrow);
145 static gint gtk_notebook_timer               (GtkNotebook      *notebook);
146 static gint gtk_notebook_focus               (GtkContainer     *container,
147                                               GtkDirectionType  direction);
148 static gint gtk_notebook_page_select         (GtkNotebook      *notebook);
149 static void gtk_notebook_calc_tabs           (GtkNotebook      *notebook, 
150                                               GList            *start, 
151                                               GList           **end,
152                                               gint             *tab_space,
153                                               guint             direction);
154 static void gtk_notebook_expose_tabs         (GtkNotebook      *notebook);
155 static void gtk_notebook_switch_focus_tab    (GtkNotebook      *notebook, 
156                                               GList            *new_child);
157 static void gtk_real_notebook_switch_page    (GtkNotebook      *notebook,
158                                               GtkNotebookPage  *page,
159                                               guint             page_num);
160 static void gtk_notebook_marshal_signal      (GtkObject        *object,
161                                               GtkSignalFunc     func,
162                                               gpointer          func_data,
163                                               GtkArg           *args);
164 static void gtk_notebook_menu_switch_page    (GtkWidget        *widget,
165                                               GtkNotebookPage  *page);
166 static void gtk_notebook_update_labels       (GtkNotebook      *notebook,
167                                               GList            *list,
168                                               guint             page_num);
169 static void gtk_notebook_menu_detacher       (GtkWidget        *widget,
170                                               GtkMenu          *menu);
171 static void gtk_notebook_menu_label_unparent (GtkWidget        *widget, 
172                                               gpointer          data);
173 static void gtk_notebook_menu_item_create    (GtkNotebook      *notebook, 
174                                               GtkNotebookPage  *page,
175                                               gint              position);
176 static GtkType gtk_notebook_child_type       (GtkContainer     *container);
177 static gint    gtk_notebook_find_page        (gconstpointer     a,
178                                               gconstpointer     b);
179
180
181 static GtkContainerClass *parent_class = NULL;
182 static guint notebook_signals[LAST_SIGNAL] = { 0 };
183
184 GtkType
185 gtk_notebook_get_type (void)
186 {
187   static GtkType notebook_type = 0;
188
189   if (!notebook_type)
190     {
191       GtkTypeInfo notebook_info =
192       {
193         "GtkNotebook",
194         sizeof (GtkNotebook),
195         sizeof (GtkNotebookClass),
196         (GtkClassInitFunc) gtk_notebook_class_init,
197         (GtkObjectInitFunc) gtk_notebook_init,
198         /* reserved_1 */ NULL,
199         /* reserved_2 */ NULL,
200         (GtkClassInitFunc) NULL,
201       };
202
203       notebook_type = gtk_type_unique (gtk_container_get_type (), &notebook_info);
204     }
205
206   return notebook_type;
207 }
208
209 static void
210 gtk_notebook_class_init (GtkNotebookClass *class)
211 {
212   GtkObjectClass *object_class;
213   GtkWidgetClass *widget_class;
214   GtkContainerClass *container_class;
215
216   object_class = (GtkObjectClass*) class;
217   widget_class = (GtkWidgetClass*) class;
218   container_class = (GtkContainerClass*) class;
219   parent_class = gtk_type_class (gtk_container_get_type ());
220
221   gtk_object_add_arg_type ("GtkNotebook::page", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_PAGE);
222   gtk_object_add_arg_type ("GtkNotebook::tab_pos", GTK_TYPE_POSITION_TYPE, GTK_ARG_READWRITE, ARG_TAB_POS);
223   gtk_object_add_arg_type ("GtkNotebook::tab_border", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_TAB_BORDER);
224   gtk_object_add_arg_type ("GtkNotebook::show_tabs", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_TABS);
225   gtk_object_add_arg_type ("GtkNotebook::show_border", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SHOW_BORDER);
226   gtk_object_add_arg_type ("GtkNotebook::scrollable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SCROLLABLE);
227   gtk_object_add_arg_type ("GtkNotebook::enable_popup", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_ENABLE_POPUP);
228
229   gtk_container_add_child_arg_type ("GtkNotebook::tab_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_TAB_LABEL);
230   gtk_container_add_child_arg_type ("GtkNotebook::menu_label", GTK_TYPE_STRING, GTK_ARG_READWRITE, CHILD_ARG_MENU_LABEL);
231   gtk_container_add_child_arg_type ("GtkNotebook::position", GTK_TYPE_INT, GTK_ARG_READWRITE, CHILD_ARG_POSITION);
232
233   notebook_signals[SWITCH_PAGE] =
234     gtk_signal_new ("switch_page",
235                     GTK_RUN_LAST,
236                     object_class->type,
237                     GTK_SIGNAL_OFFSET (GtkNotebookClass, switch_page),
238                     gtk_notebook_marshal_signal,
239                     GTK_TYPE_NONE, 2,
240                     GTK_TYPE_POINTER,
241                     GTK_TYPE_UINT);
242
243   gtk_object_class_add_signals (object_class, notebook_signals, LAST_SIGNAL);
244
245   object_class->set_arg = gtk_notebook_set_arg;
246   object_class->get_arg = gtk_notebook_get_arg;
247   object_class->destroy = gtk_notebook_destroy;
248
249   widget_class->map = gtk_notebook_map;
250   widget_class->unmap = gtk_notebook_unmap;
251   widget_class->realize = gtk_notebook_realize;
252   widget_class->size_request = gtk_notebook_size_request;
253   widget_class->size_allocate = gtk_notebook_size_allocate;
254   widget_class->draw = gtk_notebook_draw;
255   widget_class->expose_event = gtk_notebook_expose;
256   widget_class->button_press_event = gtk_notebook_button_press;
257   widget_class->button_release_event = gtk_notebook_button_release;
258   widget_class->enter_notify_event = gtk_notebook_enter_notify;
259   widget_class->leave_notify_event = gtk_notebook_leave_notify;
260   widget_class->motion_notify_event = gtk_notebook_motion_notify;
261   widget_class->key_press_event = gtk_notebook_key_press;
262   widget_class->focus_in_event = gtk_notebook_focus_in;
263   widget_class->focus_out_event = gtk_notebook_focus_out;
264   widget_class->draw_focus = gtk_notebook_draw_focus;
265
266   container_class->add = gtk_notebook_add;
267   container_class->remove = gtk_notebook_remove;
268   container_class->foreach = gtk_notebook_foreach;
269   container_class->focus = gtk_notebook_focus;
270   container_class->set_focus_child = gtk_notebook_set_focus_child;
271   container_class->get_child_arg = gtk_notebook_get_child_arg;
272   container_class->set_child_arg = gtk_notebook_set_child_arg;
273   container_class->child_type = gtk_notebook_child_type;
274
275   class->switch_page = gtk_real_notebook_switch_page;
276 }
277
278 static void
279 gtk_notebook_set_arg (GtkObject      *object,
280                       GtkArg         *arg,
281                       guint           arg_id)
282 {
283   GtkNotebook *notebook;
284
285   notebook = GTK_NOTEBOOK (object);
286
287   switch (arg_id)
288     {
289     case ARG_SHOW_TABS:
290       gtk_notebook_set_show_tabs (notebook, GTK_VALUE_BOOL (*arg));
291       break;
292     case ARG_SHOW_BORDER:
293       gtk_notebook_set_show_border (notebook, GTK_VALUE_BOOL (*arg));
294       break;
295     case ARG_SCROLLABLE:
296       gtk_notebook_set_scrollable (notebook, GTK_VALUE_BOOL (*arg));
297       break;
298     case ARG_ENABLE_POPUP:
299       if (GTK_VALUE_BOOL (*arg))
300         gtk_notebook_popup_enable (notebook);
301       else
302         gtk_notebook_popup_disable (notebook);
303       break;
304     case ARG_PAGE:
305       gtk_notebook_set_page (notebook, GTK_VALUE_INT (*arg));
306       break;
307     case ARG_TAB_POS:
308       gtk_notebook_set_tab_pos (notebook, GTK_VALUE_ENUM (*arg));
309       break;
310     case ARG_TAB_BORDER:
311       gtk_notebook_set_tab_border (notebook, GTK_VALUE_UINT (*arg));
312       break;
313     default:
314       break;
315     }
316 }
317
318 static void
319 gtk_notebook_get_arg (GtkObject      *object,
320                       GtkArg         *arg,
321                       guint           arg_id)
322 {
323   GtkNotebook *notebook;
324
325   notebook = GTK_NOTEBOOK (object);
326
327   switch (arg_id)
328     {
329     case ARG_SHOW_TABS:
330       GTK_VALUE_BOOL (*arg) = notebook->show_tabs;
331       break;
332     case ARG_SHOW_BORDER:
333       GTK_VALUE_BOOL (*arg) = notebook->show_border;
334       break;
335     case ARG_SCROLLABLE:
336       GTK_VALUE_BOOL (*arg) = notebook->scrollable;
337       break;
338     case ARG_ENABLE_POPUP:
339       GTK_VALUE_BOOL (*arg) = notebook->menu != NULL;
340       break;
341     case ARG_PAGE:
342       GTK_VALUE_INT (*arg) = gtk_notebook_current_page (notebook);
343       break;
344     case ARG_TAB_POS:
345       GTK_VALUE_ENUM (*arg) = notebook->tab_pos;
346       break;
347     case ARG_TAB_BORDER:
348       GTK_VALUE_UINT (*arg) = notebook->tab_border;
349       break;
350     default:
351       arg->type = GTK_TYPE_INVALID;
352       break;
353     }
354 }
355
356 static void
357 gtk_notebook_set_child_arg (GtkContainer     *container,
358                             GtkWidget        *child,
359                             GtkArg           *arg,
360                             guint             arg_id)
361 {
362   GtkNotebook *notebook;
363   GtkNotebookPage *page = NULL;
364   GList *list;
365   gint position;
366
367   notebook = GTK_NOTEBOOK (container);
368
369   switch (arg_id)
370     {
371     case CHILD_ARG_TAB_LABEL:
372       /* a NULL pointer indicates a default_tab setting, otherwise
373        * we need to set the associated label
374        */
375
376       if (!(list = g_list_find_custom (notebook->children, child,
377                                        gtk_notebook_find_page)))
378         return;
379
380       page = list->data;
381
382       if (GTK_VALUE_STRING (*arg))
383         {
384           page->default_tab = FALSE;
385           if (page->tab_label)
386             gtk_widget_unparent (page->tab_label);
387           page->tab_label = gtk_label_new (GTK_VALUE_STRING (*arg));
388           gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
389           if (notebook->show_tabs)
390             {
391               gtk_widget_show (page->tab_label);
392               gtk_notebook_pages_allocate
393                 (notebook, &(GTK_WIDGET (notebook)->allocation));
394               gtk_notebook_expose_tabs (notebook);
395             }
396         }
397       else
398         {
399           page->default_tab = TRUE;
400           if (page->tab_label)
401             gtk_widget_unparent (page->tab_label);
402           if (!notebook->show_tabs)
403             page->tab_label = NULL;
404           else
405             {
406               gchar string[32];
407
408               sprintf (string, "Page %u", g_list_index (notebook->children, page) + 1);
409               page->tab_label = gtk_label_new (string);
410               gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
411               gtk_widget_show (page->tab_label);
412               gtk_notebook_pages_allocate
413                 (notebook, &(GTK_WIDGET (notebook)->allocation));
414               gtk_notebook_expose_tabs (notebook);
415             }
416         }
417       break;
418     case CHILD_ARG_MENU_LABEL:
419
420       for (position = 0, list = notebook->children; list;
421            list = list->next, position++)
422         {
423           page = list->data;
424           if (page->child == child)
425             break;
426         }
427
428       if (page->menu_label)
429         {
430           if (notebook->menu)
431             {
432               gtk_container_remove (GTK_CONTAINER (notebook->menu), 
433                                     page->menu_label->parent);
434               gtk_widget_queue_resize (notebook->menu);
435             }
436           if (!page->default_menu)
437             gtk_widget_unref (page->menu_label);
438         }
439       if (GTK_VALUE_STRING (*arg))
440         {
441           page->menu_label = gtk_label_new (GTK_VALUE_STRING (*arg));
442           gtk_widget_ref (page->menu_label);
443           gtk_object_sink (GTK_OBJECT(page->menu_label));
444           page->default_menu = FALSE;
445         }
446       else
447         page->default_menu = TRUE;
448
449       if (notebook->menu)
450         gtk_notebook_menu_item_create (notebook, page, position);
451
452       break;
453     case CHILD_ARG_POSITION:
454       gtk_notebook_reorder_child (notebook, child, GTK_VALUE_INT (*arg));
455       break;
456     default:
457       break;
458     }
459 }
460
461 static void
462 gtk_notebook_get_child_arg (GtkContainer     *container,
463                             GtkWidget        *child,
464                             GtkArg           *arg,
465                             guint             arg_id)
466 {
467   GtkNotebook *notebook;
468   GtkNotebookPage *page = NULL;
469   GList *list;
470
471   notebook = GTK_NOTEBOOK (container);
472
473   if (!(list = g_list_find_custom (notebook->children, child,
474                                    gtk_notebook_find_page)))
475     {
476       arg->type = GTK_TYPE_INVALID;
477       return;
478     }
479
480   page = list->data;
481
482   switch (arg_id)
483     {
484     case CHILD_ARG_TAB_LABEL:
485       if (page->default_tab)
486         GTK_VALUE_STRING (*arg) = NULL;
487       else
488         {
489           if (page->tab_label && GTK_IS_LABEL (page->tab_label))
490             GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->tab_label)->label);
491           else
492             GTK_VALUE_STRING (*arg) = NULL;
493         }
494       break;
495     case CHILD_ARG_MENU_LABEL:
496       if (page->default_menu)
497         GTK_VALUE_STRING (*arg) = NULL;
498       else
499         {
500           if (page->menu_label && GTK_IS_LABEL (page->menu_label))
501             GTK_VALUE_STRING (*arg) = g_strdup (GTK_LABEL (page->menu_label)->label);
502           else
503             GTK_VALUE_STRING (*arg) = NULL;
504         }
505       break;
506     case CHILD_ARG_POSITION:
507       GTK_VALUE_INT (*arg) = g_list_position (notebook->children, list);
508       break;
509     default:
510       arg->type = GTK_TYPE_INVALID;
511       break;
512     }
513 }
514
515 static GtkType
516 gtk_notebook_child_type (GtkContainer     *container)
517 {
518   return GTK_TYPE_WIDGET;
519 }
520
521 static void
522 gtk_notebook_init (GtkNotebook *notebook)
523 {
524   GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
525
526   notebook->cur_page = NULL;
527   notebook->children = NULL;
528   notebook->first_tab = NULL;
529   notebook->focus_tab = NULL;
530   notebook->panel = NULL;
531   notebook->menu = NULL;
532
533   notebook->tab_border = 3;
534   notebook->show_tabs = TRUE;
535   notebook->show_border = TRUE;
536   notebook->tab_pos = GTK_POS_TOP;
537   notebook->scrollable = FALSE;
538   notebook->in_child = 0;
539   notebook->click_child = 0;
540   notebook->button = 0;
541   notebook->need_timer = 0;
542   notebook->child_has_focus = FALSE;
543 }
544
545 GtkWidget*
546 gtk_notebook_new (void)
547 {
548   return GTK_WIDGET (gtk_type_new (gtk_notebook_get_type ()));
549 }
550
551 static void
552 gtk_notebook_destroy (GtkObject *object)
553 {
554   GtkNotebook *notebook;
555   
556   g_return_if_fail (object != NULL);
557   g_return_if_fail (GTK_IS_NOTEBOOK (object));
558
559   notebook = GTK_NOTEBOOK (object);
560
561   if (notebook->menu)
562     gtk_notebook_popup_disable (notebook);
563
564   GTK_OBJECT_CLASS (parent_class)->destroy (object);
565 }
566
567 void
568 gtk_notebook_append_page (GtkNotebook *notebook,
569                           GtkWidget   *child,
570                           GtkWidget   *tab_label)
571 {
572   g_return_if_fail (notebook != NULL);
573   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
574   g_return_if_fail (child != NULL);
575
576   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, -1);
577 }
578
579 void
580 gtk_notebook_append_page_menu (GtkNotebook *notebook,
581                                GtkWidget   *child,
582                                GtkWidget   *tab_label,
583                                GtkWidget   *menu_label)
584 {
585   g_return_if_fail (notebook != NULL);
586   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
587   g_return_if_fail (child != NULL);
588
589   gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, -1);
590 }
591
592 void
593 gtk_notebook_prepend_page (GtkNotebook *notebook,
594                            GtkWidget   *child,
595                            GtkWidget   *tab_label)
596 {
597   g_return_if_fail (notebook != NULL);
598   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
599   g_return_if_fail (child != NULL);
600
601   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, 0);
602 }
603
604 void
605 gtk_notebook_prepend_page_menu (GtkNotebook *notebook,
606                                 GtkWidget   *child,
607                                 GtkWidget   *tab_label,
608                                 GtkWidget   *menu_label)
609 {
610   g_return_if_fail (notebook != NULL);
611   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
612   g_return_if_fail (child != NULL);
613
614   gtk_notebook_insert_page_menu (notebook, child, tab_label, menu_label, 0);
615 }
616
617 void
618 gtk_notebook_insert_page (GtkNotebook *notebook,
619                           GtkWidget   *child,
620                           GtkWidget   *tab_label,
621                           gint         position)
622 {
623   g_return_if_fail (notebook != NULL);
624   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
625   g_return_if_fail (child != NULL);
626
627   gtk_notebook_insert_page_menu (notebook, child, tab_label, NULL, position);
628 }
629
630 void
631 gtk_notebook_insert_page_menu (GtkNotebook *notebook,
632                                GtkWidget   *child,
633                                GtkWidget   *tab_label,
634                                GtkWidget   *menu_label,
635                                gint         position)
636 {
637   GtkNotebookPage *page;
638   gint nchildren;
639
640   g_return_if_fail (notebook != NULL);
641   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
642   g_return_if_fail (child != NULL);
643
644   page = g_new (GtkNotebookPage, 1);
645   page->child = child;
646   page->requisition.width = 0;
647   page->requisition.height = 0;
648   page->allocation.x = 0;
649   page->allocation.y = 0;
650   page->allocation.width = 0;
651   page->allocation.height = 0;
652   page->default_menu = FALSE;
653   page->default_tab = FALSE;
654
655   nchildren = g_list_length (notebook->children);
656   if ((position < 0) || (position > nchildren))
657     position = nchildren;
658
659   notebook->children = g_list_insert (notebook->children, page, position);
660
661   if (!tab_label)
662     {
663       page->default_tab = TRUE;
664       if (notebook->show_tabs)
665         tab_label = gtk_label_new ("");
666     }
667   page->tab_label = tab_label;
668   page->menu_label = menu_label;
669
670   if (!menu_label)
671     page->default_menu = TRUE;
672   else  
673     {
674       gtk_widget_ref (page->menu_label);
675       gtk_object_sink (GTK_OBJECT(page->menu_label));
676     }
677
678   if (notebook->menu)
679     gtk_notebook_menu_item_create (notebook, page, position);
680
681   gtk_notebook_update_labels 
682     (notebook, g_list_nth (notebook->children, position), position + 1);
683
684   if (!notebook->first_tab)
685     notebook->first_tab = notebook->children;
686
687   gtk_widget_set_parent (child, GTK_WIDGET (notebook));
688   if (tab_label)
689     {
690       gtk_widget_set_parent (tab_label, GTK_WIDGET (notebook));
691       gtk_widget_show (tab_label);
692     }
693
694   if (!notebook->cur_page)
695     {
696       gtk_notebook_switch_page (notebook, page, 0);
697       gtk_notebook_switch_focus_tab (notebook, NULL);
698     }
699
700   if (GTK_WIDGET_VISIBLE (notebook))
701     {
702       if (GTK_WIDGET_REALIZED (notebook) &&
703           !GTK_WIDGET_REALIZED (child))
704         gtk_widget_realize (child);
705         
706       if (GTK_WIDGET_MAPPED (notebook) &&
707           !GTK_WIDGET_MAPPED (child) && notebook->cur_page == page)
708         gtk_widget_map (child);
709
710       if (tab_label)
711         {
712           if (GTK_WIDGET_REALIZED (notebook) &&
713               !GTK_WIDGET_REALIZED (tab_label))
714             gtk_widget_realize (tab_label);
715       
716           if (GTK_WIDGET_MAPPED (notebook) &&
717               !GTK_WIDGET_MAPPED (tab_label))
718             gtk_widget_map (tab_label);
719         }
720     }
721
722   if (GTK_WIDGET_VISIBLE (child) && GTK_WIDGET_VISIBLE (notebook))
723     gtk_widget_queue_resize (child);
724 }
725
726 void
727 gtk_notebook_remove_page (GtkNotebook *notebook,
728                           gint        page_num)
729 {
730   GList *list;
731
732   g_return_if_fail (notebook != NULL);
733   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
734
735   if (page_num >= 0)
736     {
737       list = g_list_nth (notebook->children, page_num);
738       if (list)
739         gtk_notebook_real_remove (notebook, list, page_num);
740     }
741   else
742     {
743       list = g_list_last (notebook->children);
744       if (list)
745         gtk_notebook_real_remove
746           (notebook, list, g_list_index (notebook->children, list->data));
747     }
748 }
749
750 static void
751 gtk_notebook_add (GtkContainer *container,
752                   GtkWidget    *widget)
753 {
754   g_return_if_fail (container != NULL);
755   g_return_if_fail (GTK_IS_NOTEBOOK (container));
756   g_return_if_fail (widget != NULL);
757
758   gtk_notebook_insert_page_menu (GTK_NOTEBOOK (container), widget, 
759                                  NULL, NULL, -1);
760 }
761
762 static void
763 gtk_notebook_remove (GtkContainer *container,
764                      GtkWidget    *widget)
765 {
766   GtkNotebook *notebook;
767   GtkNotebookPage *page;
768   GList *children;
769   guint page_num;
770
771   g_return_if_fail (container != NULL);
772   g_return_if_fail (GTK_IS_NOTEBOOK (container));
773   g_return_if_fail (widget != NULL);
774
775   notebook = GTK_NOTEBOOK (container);
776
777   children = notebook->children;
778   page_num = 0;
779   while (children)
780     {
781       page = children->data;
782       if (page->child == widget)
783         {
784           gtk_notebook_real_remove (notebook, children, page_num);
785           break;
786         }
787       page_num++;
788       children = children->next;
789     }
790 }
791
792 static void
793 gtk_notebook_real_remove (GtkNotebook *notebook,
794                           GList        *list,
795                           guint         page_num)
796 {
797   GtkNotebookPage *page;
798   GList * next_list;
799   gint need_resize = FALSE;
800       
801   if (list->prev)
802     {
803       next_list = list->prev;
804       page_num--;
805     }
806   else if (list->next)
807     {
808       next_list = list->next;
809       page_num++;
810     }
811   else 
812     next_list = NULL;
813   
814   if (notebook->cur_page == list->data)
815     { 
816       notebook->cur_page = NULL;
817       if (next_list)
818         {
819           page = next_list->data;
820           gtk_notebook_switch_page (notebook, page, page_num);
821         }
822     }
823   
824   if (list == notebook->first_tab)
825     notebook->first_tab = next_list;
826   if (list == notebook->focus_tab)
827     gtk_notebook_switch_focus_tab (notebook, next_list);
828   
829   page = list->data;
830   
831   if ((GTK_WIDGET_VISIBLE (page->child) || 
832        (page->tab_label && GTK_WIDGET_VISIBLE (page->tab_label))) 
833        && GTK_WIDGET_VISIBLE (notebook))
834     need_resize = TRUE;
835
836   gtk_widget_unparent (page->child);
837
838   if (page->tab_label)
839     gtk_widget_unparent (page->tab_label);
840
841   if (notebook->menu)
842     {
843       gtk_container_remove (GTK_CONTAINER (notebook->menu), 
844                             page->menu_label->parent);
845       gtk_widget_queue_resize (notebook->menu);
846     }
847   if (!page->default_menu)
848     gtk_widget_unref (page->menu_label);
849   
850   gtk_notebook_update_labels (notebook, list->next, page_num + 1);
851   
852   notebook->children = g_list_remove_link (notebook->children, list);
853   g_list_free (list);
854   g_free (page);
855
856   if (need_resize)
857     gtk_widget_queue_resize (GTK_WIDGET (notebook));
858
859 }
860
861 gint
862 gtk_notebook_current_page (GtkNotebook *notebook)
863 {
864   GList *children;
865   gint cur_page;
866
867   g_return_val_if_fail (notebook != NULL, -1);
868   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), -1);
869
870   if (notebook->cur_page)
871     {
872       cur_page = 0;
873       children = notebook->children;
874
875       while (children)
876         {
877           if (children->data == notebook->cur_page)
878             break;
879           children = children->next;
880           cur_page += 1;
881         }
882
883       if (!children)
884         cur_page = -1;
885     }
886   else
887     {
888       cur_page = -1;
889     }
890
891   return cur_page;
892 }
893
894 void
895 gtk_notebook_set_page (GtkNotebook *notebook,
896                        gint         page_num)
897 {
898   GList *list;
899   
900   g_return_if_fail (notebook != NULL);
901   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
902
903   if (page_num >= 0)
904     {
905       list = g_list_nth (notebook->children, page_num);
906       if (list)
907         gtk_notebook_switch_page (notebook, list->data, page_num);
908     }
909   else
910     {
911       list = g_list_last (notebook->children);
912       if (list)
913         gtk_notebook_switch_page (notebook, list->data,
914                                   g_list_index (notebook->children, list->data));
915     }
916 }
917
918 void
919 gtk_notebook_next_page (GtkNotebook *notebook)
920 {
921   GtkNotebookPage *page;
922   GList *children;
923   gint num;
924
925   g_return_if_fail (notebook != NULL);
926   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
927
928   children = notebook->children;
929   num = 0;
930   while (children)
931     {
932       if (notebook->cur_page == children->data)
933         break;
934       children = children->next;
935       num++;
936     }
937
938   if (!children)
939     return;
940
941   if (children->next)
942     {
943       children = children->next;
944       num++;
945     }
946   else
947     {
948       children = notebook->children;
949       num = 0;
950     }
951
952   page = children->data;
953   gtk_notebook_switch_page (notebook, page, num);
954 }
955
956 void
957 gtk_notebook_prev_page (GtkNotebook *notebook)
958 {
959   GtkNotebookPage *page;
960   GList *children;
961   gint num;
962
963   g_return_if_fail (notebook != NULL);
964   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
965
966   children = notebook->children;
967   num = 0;
968   while (children)
969     {
970       if (notebook->cur_page == children->data)
971         break;
972       children = children->next;
973       num++;
974     }
975
976   if (!children)
977     return;
978
979   if (children->prev)
980     {
981       children = children->prev;
982       num--;
983     }
984   else
985     {
986       while (children->next)
987         {
988           children = children->next;
989           num++;
990         }
991     }
992
993   page = children->data;
994   gtk_notebook_switch_page (notebook, page, num);
995 }
996
997 void
998 gtk_notebook_reorder_child (GtkNotebook *notebook,
999                             GtkWidget   *child,
1000                             gint         position)
1001 {
1002   GList *list;
1003   GtkNotebookPage *page;
1004   gint old_pos;
1005
1006   g_return_if_fail (notebook != NULL);
1007   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1008   g_return_if_fail (child != NULL);
1009   g_return_if_fail (GTK_IS_WIDGET (child));
1010
1011   for (old_pos = 0, list = notebook->children; list;
1012        list = list->next, old_pos++)
1013     {
1014       page = list->data;
1015       if (page->child == child)
1016         break;
1017     }
1018
1019   if (!list || old_pos == position)
1020     return;
1021
1022   notebook->children = g_list_remove_link (notebook->children, list);
1023   
1024   if (position <= 0 || !notebook->children)
1025     {
1026       list->next = notebook->children;
1027       if (list->next)
1028         list->next->prev = list;
1029       notebook->children = list;
1030     }
1031   else
1032     {
1033       GList *work;
1034
1035       if ((work = g_list_nth (notebook->children, position)))
1036         {
1037           list->prev = work->prev;
1038           if (list->prev)
1039             list->prev->next = list;
1040           list->next = work;
1041           work->prev = list;
1042         }
1043       else
1044         {
1045           work = g_list_last (notebook->children);
1046           work->next = list;
1047           list->prev = work;
1048         }
1049     }
1050
1051   if (notebook->menu)
1052     {
1053       GtkWidget *menu_item;
1054
1055       menu_item = page->menu_label->parent;
1056       gtk_container_remove (GTK_CONTAINER (menu_item), page->menu_label);
1057       gtk_container_remove (GTK_CONTAINER (notebook->menu), menu_item);
1058       gtk_notebook_menu_item_create (notebook, page, position);
1059       gtk_widget_queue_resize (notebook->menu);
1060     }
1061
1062   gtk_notebook_update_labels (notebook, notebook->children, 1);
1063
1064   if (notebook->show_tabs)
1065     {
1066       gtk_notebook_pages_allocate (notebook,
1067                                    &(GTK_WIDGET (notebook)->allocation));
1068       gtk_notebook_expose_tabs (notebook);
1069     }
1070 }
1071
1072 static void
1073 gtk_notebook_foreach (GtkContainer *container,
1074                       GtkCallback   callback,
1075                       gpointer      callback_data)
1076 {
1077   GtkNotebook *notebook;
1078   GtkNotebookPage *page;
1079   GList *children;
1080
1081   g_return_if_fail (container != NULL);
1082   g_return_if_fail (GTK_IS_NOTEBOOK (container));
1083   g_return_if_fail (callback != NULL);
1084
1085   notebook = GTK_NOTEBOOK (container);
1086
1087   children = notebook->children;
1088   while (children)
1089     {
1090       page = children->data;
1091       children = children->next;
1092       (* callback) (page->child, callback_data);
1093     }
1094 }
1095
1096 static void
1097 gtk_notebook_expose_tabs (GtkNotebook *notebook)
1098 {
1099   GtkWidget *widget;
1100   GtkNotebookPage *page;
1101   GdkEventExpose event;
1102   gint border;
1103
1104   widget = GTK_WIDGET (notebook);
1105   border = GTK_CONTAINER (notebook)->border_width;
1106
1107   page = notebook->first_tab->data;
1108
1109   event.type = GDK_EXPOSE;
1110   event.window = widget->window;
1111   event.count = 0;
1112   event.area.x = border;
1113   event.area.y = border;
1114
1115   switch (notebook->tab_pos)
1116     {
1117     case GTK_POS_BOTTOM:
1118       event.area.y = widget->allocation.height - border 
1119         - page->allocation.height - widget->style->klass->ythickness;
1120       if (notebook->first_tab->data != notebook->cur_page)
1121         event.area.y -= widget->style->klass->ythickness;
1122     case GTK_POS_TOP:
1123       event.area.width = widget->allocation.width - 2 * border;
1124       event.area.height = page->allocation.height 
1125         + widget->style->klass->ythickness;
1126       if (notebook->first_tab->data != notebook->cur_page)
1127         event.area.height += widget->style->klass->ythickness;
1128       break;
1129     case GTK_POS_RIGHT:
1130       event.area.x = widget->allocation.width - border 
1131         - page->allocation.width - widget->style->klass->xthickness;
1132       if (notebook->first_tab->data != notebook->cur_page)
1133         event.area.x -= widget->style->klass->xthickness;
1134     case GTK_POS_LEFT:
1135       event.area.width = page->allocation.width 
1136         + widget->style->klass->xthickness;
1137       event.area.height = widget->allocation.height - 2 * border;
1138       if (notebook->first_tab->data != notebook->cur_page)
1139         event.area.width += widget->style->klass->xthickness;
1140       break;
1141     }        
1142   gtk_widget_event (widget, (GdkEvent *) &event);
1143 }
1144
1145 void
1146 gtk_notebook_set_tab_pos (GtkNotebook     *notebook,
1147                           GtkPositionType  pos)
1148 {
1149   g_return_if_fail (notebook != NULL);
1150   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1151
1152   if (notebook->tab_pos != pos)
1153     {
1154       notebook->tab_pos = pos;
1155
1156       if (GTK_WIDGET_VISIBLE (notebook))
1157         {
1158           gtk_widget_queue_resize (GTK_WIDGET (notebook));
1159           if (notebook->panel)
1160             gdk_window_clear (notebook->panel);
1161         }
1162     }
1163 }
1164
1165 void
1166 gtk_notebook_set_show_tabs (GtkNotebook *notebook,
1167                             gint         show_tabs)
1168 {
1169   GtkNotebookPage *page;
1170   GList *children;
1171
1172   g_return_if_fail (notebook != NULL);
1173   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1174
1175   if (notebook->show_tabs == show_tabs)
1176     return;
1177
1178   notebook->show_tabs = show_tabs;
1179   children = notebook->children;
1180
1181   if (!show_tabs)
1182     {
1183       GTK_WIDGET_UNSET_FLAGS (notebook, GTK_CAN_FOCUS);
1184       
1185       while (children)
1186         {
1187           page = children->data;
1188           children = children->next;
1189           if (page->default_tab)
1190             {
1191               gtk_widget_destroy (page->tab_label);
1192               page->tab_label = NULL;
1193             }
1194           else
1195             gtk_widget_hide (page->tab_label);
1196         }
1197       
1198       if (notebook->panel)
1199         gdk_window_hide (notebook->panel);
1200     }
1201   else
1202     {
1203       gchar string[32];
1204       gint i = 1;
1205       
1206       GTK_WIDGET_SET_FLAGS (notebook, GTK_CAN_FOCUS);
1207       
1208       while (children)
1209         {
1210           page = children->data;
1211           children = children->next;
1212           if (page->default_tab)
1213             {
1214               sprintf (string, "Page %d", i);
1215               page->tab_label = gtk_label_new (string);
1216               gtk_widget_set_parent (page->tab_label, GTK_WIDGET (notebook));
1217             }
1218           gtk_widget_show (page->tab_label);
1219           i++;
1220         }
1221     }
1222   gtk_widget_queue_resize (GTK_WIDGET (notebook));
1223 }
1224
1225 void
1226 gtk_notebook_set_show_border (GtkNotebook *notebook,
1227                               gint         show_border)
1228 {
1229   g_return_if_fail (notebook != NULL);
1230   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1231
1232   if (notebook->show_border != show_border)
1233     {
1234       notebook->show_border = show_border;
1235
1236       if (GTK_WIDGET_VISIBLE (notebook))
1237         gtk_widget_queue_resize (GTK_WIDGET (notebook));
1238     }
1239 }
1240
1241 void
1242 gtk_notebook_set_scrollable (GtkNotebook     *notebook,
1243                              gint             scrollable)
1244 {
1245   g_return_if_fail (notebook != NULL);
1246   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1247
1248   if (scrollable != notebook->scrollable)
1249     {
1250       if ( (notebook->scrollable = (scrollable != 0)) ) 
1251         gtk_notebook_panel_realize (notebook);
1252       else if (notebook->panel)
1253         {
1254           gdk_window_destroy (notebook->panel);
1255           notebook->panel = NULL;
1256         }
1257       gtk_widget_queue_resize (GTK_WIDGET(notebook));
1258     }     
1259 }
1260
1261 static void
1262 gtk_notebook_map (GtkWidget *widget)
1263 {
1264   GtkNotebook *notebook;
1265   GtkNotebookPage *page;
1266   GList *children;
1267
1268   g_return_if_fail (widget != NULL);
1269   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1270
1271   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
1272   gdk_window_show (widget->window);
1273
1274   notebook = GTK_NOTEBOOK (widget);
1275
1276   if (notebook->cur_page && 
1277       GTK_WIDGET_VISIBLE (notebook->cur_page->child) &&
1278       !GTK_WIDGET_MAPPED (notebook->cur_page->child))
1279     gtk_widget_map (notebook->cur_page->child);
1280
1281   if (notebook->scrollable)
1282       gtk_notebook_pages_allocate (notebook, &(widget->allocation));
1283   else
1284     {
1285       children = notebook->children;
1286
1287       while (children)
1288         {
1289           page = children->data;
1290           children = children->next;
1291
1292           if (page->tab_label && 
1293               GTK_WIDGET_VISIBLE (page->child) && 
1294               !GTK_WIDGET_MAPPED (page->tab_label))
1295             gtk_widget_map (page->tab_label);
1296         }
1297     }
1298 }
1299
1300 static void
1301 gtk_notebook_unmap (GtkWidget *widget)
1302 {
1303   g_return_if_fail (widget != NULL);
1304   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1305
1306   GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
1307   gdk_window_hide (widget->window);
1308   if (GTK_NOTEBOOK (widget)->panel)
1309     gdk_window_hide (GTK_NOTEBOOK (widget)->panel);
1310 }
1311
1312 static void
1313 gtk_notebook_realize (GtkWidget *widget)
1314 {
1315   GtkNotebook *notebook;
1316   GdkWindowAttr attributes;
1317   gint attributes_mask;
1318
1319   g_return_if_fail (widget != NULL);
1320   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1321
1322   notebook = GTK_NOTEBOOK (widget);
1323   GTK_WIDGET_SET_FLAGS (notebook, GTK_REALIZED);
1324
1325   attributes.window_type = GDK_WINDOW_CHILD;
1326   attributes.x = widget->allocation.x;
1327   attributes.y = widget->allocation.y;
1328   attributes.width = widget->allocation.width;
1329   attributes.height = widget->allocation.height;
1330   attributes.wclass = GDK_INPUT_OUTPUT;
1331   attributes.visual = gtk_widget_get_visual (widget);
1332   attributes.colormap = gtk_widget_get_colormap (widget);
1333   attributes.event_mask = gtk_widget_get_events (widget);
1334   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
1335     | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK;
1336
1337   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1338
1339   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
1340   gdk_window_set_user_data (widget->window, notebook);
1341
1342   widget->style = gtk_style_attach (widget->style, widget->window);
1343   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
1344
1345   if (notebook->scrollable)
1346     gtk_notebook_panel_realize (notebook);
1347 }
1348
1349 static void
1350 gtk_notebook_panel_realize (GtkNotebook *notebook)
1351 {
1352   GtkWidget *widget;
1353   GdkWindowAttr attributes;
1354   gint attributes_mask;
1355   
1356   g_return_if_fail (notebook != NULL);
1357   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
1358   
1359   widget = GTK_WIDGET (notebook);
1360   
1361   attributes.window_type = GDK_WINDOW_CHILD;
1362   attributes.wclass = GDK_INPUT_OUTPUT;
1363   attributes.visual = gtk_widget_get_visual (widget);
1364   attributes.colormap = gtk_widget_get_colormap (widget);
1365   attributes.event_mask = gtk_widget_get_events (widget);
1366   attributes.event_mask |= GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK 
1367     | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
1368     | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK;
1369   
1370   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
1371   
1372   attributes.width = 2 * ARROW_SIZE + ARROW_SPACING;
1373   attributes.height = ARROW_SIZE;
1374
1375   attributes.x = widget->allocation.width - attributes.width - 
1376     GTK_CONTAINER (notebook)->border_width;
1377   attributes.y = widget->allocation.height - ARROW_SIZE -
1378     GTK_CONTAINER (notebook)->border_width;
1379   if (notebook->tab_pos == GTK_POS_TOP)
1380     attributes.y = GTK_CONTAINER (notebook)->border_width;
1381   else if (notebook->tab_pos == GTK_POS_LEFT)
1382     attributes.x = widget->allocation.x 
1383       + GTK_CONTAINER (notebook)->border_width;
1384
1385   
1386   notebook->panel = gdk_window_new (widget->window, &attributes, 
1387                                     attributes_mask);
1388   gtk_style_set_background (widget->style, notebook->panel, 
1389                             GTK_STATE_NORMAL);
1390   gdk_window_set_user_data (notebook->panel, widget);
1391 }
1392
1393 static void
1394 gtk_notebook_size_request (GtkWidget      *widget,
1395                            GtkRequisition *requisition)
1396 {
1397   GtkNotebook *notebook;
1398   GtkNotebookPage *page;
1399   GList *children;
1400
1401   g_return_if_fail (widget != NULL);
1402   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1403   g_return_if_fail (requisition != NULL);
1404
1405   notebook = GTK_NOTEBOOK (widget);
1406   widget->requisition.width = 0;
1407   widget->requisition.height = 0;
1408
1409   children = notebook->children;
1410   while (children)
1411     {
1412       page = children->data;
1413       children = children->next;
1414
1415       if (GTK_WIDGET_VISIBLE (page->child))
1416         {
1417           gtk_widget_size_request (page->child, &page->child->requisition);
1418           
1419           widget->requisition.width = MAX (widget->requisition.width,
1420                                            page->child->requisition.width);
1421           widget->requisition.height = MAX (widget->requisition.height,
1422                                             page->child->requisition.height);
1423         }
1424     }
1425
1426   if (notebook->show_border || notebook->show_tabs)
1427     {
1428       widget->requisition.width += widget->style->klass->xthickness * 2;
1429       widget->requisition.height += widget->style->klass->ythickness * 2;
1430
1431       if (notebook->show_tabs)
1432         {
1433           gint tab_width = 0;
1434           gint tab_height = 0;
1435           gint tab_max = 0;
1436           
1437           children = notebook->children;
1438           while (children)
1439             {
1440               page = children->data;
1441               children = children->next;
1442               
1443               if (GTK_WIDGET_VISIBLE (page->child))
1444                 {
1445                   gtk_widget_size_request (page->tab_label, 
1446                                            &page->tab_label->requisition);
1447                   
1448                   page->requisition.width = 
1449                     (page->tab_label->requisition.width +
1450                      (widget->style->klass->xthickness + notebook->tab_border)
1451                      * 2);
1452                   page->requisition.height = 
1453                     (page->tab_label->requisition.height +
1454                      (widget->style->klass->ythickness + notebook->tab_border)
1455                      * 2);
1456                   
1457                   switch (notebook->tab_pos)
1458                     {
1459                     case GTK_POS_TOP:
1460                     case GTK_POS_BOTTOM:
1461                       page->requisition.width -= TAB_OVERLAP;
1462
1463                       tab_width += page->requisition.width;
1464                       tab_height = MAX (tab_height, page->requisition.height);
1465                       tab_max = MAX (tab_max, page->requisition.width);
1466                       break;
1467                     case GTK_POS_LEFT:
1468                     case GTK_POS_RIGHT:
1469                       page->requisition.height -= TAB_OVERLAP;
1470
1471                       tab_width = MAX (tab_width, page->requisition.width);
1472                       tab_height += page->requisition.height;
1473                       tab_max = MAX (tab_max, page->requisition.height);
1474                       break;
1475                     }
1476                 }
1477             }
1478
1479           children = notebook->children;
1480
1481           if (children && children->next && notebook->scrollable) 
1482             {
1483               if ((notebook->tab_pos == GTK_POS_TOP) ||
1484                   (notebook->tab_pos == GTK_POS_BOTTOM))
1485                 {
1486                   if (widget->requisition.width < tab_width)
1487                     {
1488                       tab_width = tab_max + 2 * (ARROW_SIZE + ARROW_SPACING);
1489                       tab_height = MAX (tab_height, ARROW_SIZE);
1490                     }
1491                 }
1492               else
1493                 {
1494                   if (widget->requisition.height < tab_height)
1495                     {
1496                       tab_height = tab_max + ARROW_SIZE + ARROW_SPACING;
1497                       tab_width = MAX (tab_width, 
1498                                        ARROW_SPACING + 2 * ARROW_SIZE);
1499                     }
1500                 }
1501             }
1502
1503           while (children)
1504             {
1505               page = children->data;
1506               children = children->next;
1507               
1508               if (GTK_WIDGET_VISIBLE (page->child))
1509                 {
1510                   if ((notebook->tab_pos == GTK_POS_TOP) ||
1511                       (notebook->tab_pos == GTK_POS_BOTTOM))
1512                     page->requisition.height = tab_height;
1513                   else
1514                     page->requisition.width = tab_width;
1515                 }
1516             }
1517           
1518           switch (notebook->tab_pos)
1519             {
1520             case GTK_POS_TOP:
1521             case GTK_POS_BOTTOM:
1522               tab_width += widget->style->klass->xthickness;
1523               widget->requisition.width = MAX (widget->requisition.width, 
1524                                                tab_width);
1525               widget->requisition.height += tab_height;
1526               break;
1527             case GTK_POS_LEFT:
1528             case GTK_POS_RIGHT:
1529               tab_height += widget->style->klass->ythickness;
1530               widget->requisition.width += tab_width;
1531               widget->requisition.height = MAX (widget->requisition.height, 
1532                                                 tab_height);
1533               break;
1534             }
1535         }
1536     }
1537   widget->requisition.width += GTK_CONTAINER (widget)->border_width * 2;
1538   widget->requisition.height += GTK_CONTAINER (widget)->border_width * 2;
1539 }
1540
1541 static void
1542 gtk_notebook_size_allocate (GtkWidget     *widget,
1543                             GtkAllocation *allocation)
1544 {
1545   GtkNotebook *notebook;
1546   GtkNotebookPage *page;
1547   GtkAllocation child_allocation;
1548   GList *children;
1549
1550   g_return_if_fail (widget != NULL);
1551   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1552   g_return_if_fail (allocation != NULL);
1553
1554   widget->allocation = *allocation;
1555   if (GTK_WIDGET_REALIZED (widget))
1556     gdk_window_move_resize (widget->window,
1557                             allocation->x, allocation->y,
1558                             allocation->width, allocation->height);
1559
1560   notebook = GTK_NOTEBOOK (widget);
1561   if (notebook->children)
1562     {
1563       child_allocation.x = GTK_CONTAINER (widget)->border_width;
1564       child_allocation.y = GTK_CONTAINER (widget)->border_width;
1565       child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
1566       child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
1567
1568       if (notebook->show_tabs || notebook->show_border)
1569         {
1570           child_allocation.x += widget->style->klass->xthickness;
1571           child_allocation.y += widget->style->klass->ythickness;
1572           child_allocation.width = MAX (1, 
1573               child_allocation.width - widget->style->klass->xthickness * 2);
1574           child_allocation.height = MAX (1, 
1575               child_allocation.height - widget->style->klass->ythickness * 2);
1576
1577           if (notebook->show_tabs && notebook->children)
1578             {
1579               switch (notebook->tab_pos)
1580                 {
1581                 case GTK_POS_TOP:
1582                   child_allocation.y += notebook->cur_page->requisition.height;
1583                 case GTK_POS_BOTTOM:
1584                   child_allocation.height = MAX (1, 
1585                     child_allocation.height - notebook->cur_page->requisition.height);
1586                   break;
1587                 case GTK_POS_LEFT:
1588                   child_allocation.x += notebook->cur_page->requisition.width;
1589                 case GTK_POS_RIGHT:
1590                   child_allocation.width = MAX (1, 
1591                     child_allocation.width - notebook->cur_page->requisition.width);
1592                   break;
1593                 }
1594             }
1595         }
1596
1597       children = notebook->children;
1598       while (children)
1599         {
1600           page = children->data;
1601           children = children->next;
1602           
1603           if (GTK_WIDGET_VISIBLE (page->child))
1604             gtk_widget_size_allocate (page->child, &child_allocation);
1605         }
1606
1607       gtk_notebook_pages_allocate (notebook, allocation);
1608     }
1609 }
1610
1611 static void
1612 gtk_notebook_paint (GtkWidget    *widget,
1613                     GdkRectangle *area)
1614 {
1615   GtkNotebook *notebook;
1616   GtkNotebookPage *page;
1617   GList *children;
1618   GdkPoint points[6];
1619   gint width, height;
1620   gint x, y;
1621   gint showarrow;
1622
1623   g_return_if_fail (widget != NULL);
1624   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1625   g_return_if_fail (area != NULL);
1626
1627   if (GTK_WIDGET_DRAWABLE (widget))
1628     {
1629       notebook = GTK_NOTEBOOK (widget);
1630
1631       gdk_window_clear_area (widget->window,
1632                              area->x, area->y,
1633                              area->width, area->height);
1634
1635       if (notebook->show_tabs || notebook->show_border)
1636         {
1637           x = GTK_CONTAINER (widget)->border_width;
1638           y = GTK_CONTAINER (widget)->border_width;
1639           width = widget->allocation.width - x * 2;
1640           height = widget->allocation.height - y * 2;
1641
1642           if (notebook->show_tabs && notebook->children)
1643             {
1644
1645               if (!GTK_WIDGET_MAPPED (notebook->cur_page->tab_label))
1646                 {
1647                   GtkNotebookPage *page;
1648
1649                   page = notebook->first_tab->data;
1650
1651                   switch (notebook->tab_pos)
1652                     {
1653                     case GTK_POS_TOP:
1654                       y += page->allocation.height +
1655                         widget->style->klass->ythickness;
1656                     case GTK_POS_BOTTOM:
1657                       height -= page->allocation.height +
1658                         widget->style->klass->ythickness;
1659                       break;
1660                     case GTK_POS_LEFT:
1661                       x += page->allocation.width +
1662                         widget->style->klass->xthickness;
1663                     case GTK_POS_RIGHT:
1664                       width -= page->allocation.width +
1665                         widget->style->klass->xthickness;
1666                     break;
1667                     }
1668                   gtk_draw_shadow (widget->style, widget->window,
1669                                    GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1670                                    x, y, width, height);
1671                 }
1672               else
1673                 {
1674                   switch (notebook->tab_pos)
1675                     {
1676                     case GTK_POS_TOP:
1677                       y += notebook->cur_page->allocation.height;
1678                     case GTK_POS_BOTTOM:
1679                       height -= notebook->cur_page->allocation.height;
1680                       break;
1681                     case GTK_POS_LEFT:
1682                       x += notebook->cur_page->allocation.width;
1683                     case GTK_POS_RIGHT:
1684                       width -= notebook->cur_page->allocation.width;
1685                       break;
1686                     }
1687
1688                   switch (notebook->tab_pos)
1689                     {
1690                     case GTK_POS_TOP:
1691                       points[0].x = notebook->cur_page->allocation.x;
1692                       points[0].y = y;
1693                       points[1].x = x;
1694                       points[1].y = y;
1695                       points[2].x = x;
1696                       points[2].y = y + height - 1;
1697                       points[3].x = x + width - 1;
1698                       points[3].y = y + height - 1;
1699                       points[4].x = x + width - 1;
1700                       points[4].y = y;
1701                       points[5].x = (notebook->cur_page->allocation.x +
1702                                      notebook->cur_page->allocation.width -
1703                                      widget->style->klass->xthickness);
1704                       points[5].y = y;
1705
1706                       if (points[5].x == (x + width))
1707                         points[5].x -= 1;
1708                       break;
1709                     case GTK_POS_BOTTOM:
1710                       points[0].x = (notebook->cur_page->allocation.x +
1711                                      notebook->cur_page->allocation.width -
1712                                      widget->style->klass->xthickness);
1713                       points[0].y = y + height - 1;
1714                       points[1].x = x + width - 1;
1715                       points[1].y = y + height - 1;
1716                       points[2].x = x + width - 1;
1717                       points[2].y = y;
1718                       points[3].x = x;
1719                       points[3].y = y;
1720                       points[4].x = x;
1721                       points[4].y = y + height - 1;
1722                       points[5].x = notebook->cur_page->allocation.x;
1723                       points[5].y = y + height - 1;
1724
1725                       if (points[0].x == (x + width))
1726                         points[0].x -= 1;
1727                       break;
1728                     case GTK_POS_LEFT:
1729                       points[0].x = x;
1730                       points[0].y = (notebook->cur_page->allocation.y +
1731                                      notebook->cur_page->allocation.height -
1732                                      widget->style->klass->ythickness);
1733                       points[1].x = x;
1734                       points[1].y = y + height - 1;
1735                       points[2].x = x + width - 1;
1736                       points[2].y = y + height - 1;
1737                       points[3].x = x + width - 1;
1738                       points[3].y = y;
1739                       points[4].x = x;
1740                       points[4].y = y;
1741                       points[5].x = x;
1742                       points[5].y = notebook->cur_page->allocation.y;
1743                       
1744                       if (points[0].y == (y + height))
1745                         points[0].y -= 1;
1746                       break;
1747                     case GTK_POS_RIGHT:
1748                       points[0].x = x + width - 1;
1749                       points[0].y = notebook->cur_page->allocation.y;
1750                       points[1].x = x + width - 1;
1751                       points[1].y = y;
1752                       points[2].x = x;
1753                       points[2].y = y;
1754                       points[3].x = x;
1755                       points[3].y = y + height - 1;
1756                       points[4].x = x + width - 1;
1757                       points[4].y = y + height - 1;
1758                       points[5].x = x + width - 1;
1759                       points[5].y = (notebook->cur_page->allocation.y +
1760                                      notebook->cur_page->allocation.height -
1761                                      widget->style->klass->ythickness);
1762
1763                       if (points[5].y == (y + height))
1764                         points[5].y -= 1;
1765                       break;
1766                     }
1767                   
1768                   gtk_draw_polygon (widget->style, widget->window,
1769                                     GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1770                                     points, 6, FALSE);
1771                 }
1772               children = g_list_last (notebook->children);
1773               showarrow = FALSE;
1774
1775               while (children)
1776                 {
1777                   page = children->data;
1778                   children = children->prev;
1779
1780                   if (!GTK_WIDGET_MAPPED (page->tab_label))
1781                     showarrow = TRUE;
1782                   else if (notebook->cur_page != page)
1783                     gtk_notebook_draw_tab (notebook, page, area);
1784                 }
1785
1786               if (showarrow && notebook->scrollable && notebook->show_tabs) 
1787                 {
1788                   gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1789                   gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1790                 }
1791               if (notebook->cur_page && 
1792                   GTK_WIDGET_MAPPED(((GtkNotebookPage *)
1793                                      (notebook->cur_page))->tab_label))
1794                 gtk_notebook_draw_tab (notebook, notebook->cur_page, area);
1795             }
1796           else if (notebook->show_border)
1797             {
1798               gtk_draw_shadow (widget->style, widget->window,
1799                                GTK_STATE_NORMAL, GTK_SHADOW_OUT,
1800                                x, y, width, height);
1801             }
1802         }
1803     }
1804 }
1805
1806 static void
1807 gtk_notebook_draw (GtkWidget    *widget,
1808                    GdkRectangle *area)
1809 {
1810   GtkNotebook *notebook;
1811   GdkRectangle child_area;
1812
1813   g_return_if_fail (widget != NULL);
1814   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
1815   g_return_if_fail (area != NULL);
1816
1817   if (GTK_WIDGET_DRAWABLE (widget))
1818     {
1819       notebook = GTK_NOTEBOOK (widget);
1820
1821       gtk_notebook_paint (widget, area);
1822       gtk_widget_draw_focus (widget);
1823
1824       if (notebook->cur_page &&
1825           gtk_widget_intersect (notebook->cur_page->child, area, &child_area))
1826         gtk_widget_draw (notebook->cur_page->child, &child_area);
1827     }
1828 }
1829
1830 static gint
1831 gtk_notebook_expose (GtkWidget      *widget,
1832                      GdkEventExpose *event)
1833 {
1834   GtkNotebook *notebook;
1835   GdkEventExpose child_event;
1836
1837   g_return_val_if_fail (widget != NULL, FALSE);
1838   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1839   g_return_val_if_fail (event != NULL, FALSE);
1840
1841   if (GTK_WIDGET_DRAWABLE (widget))
1842     {
1843       notebook = GTK_NOTEBOOK (widget);
1844
1845       gtk_notebook_paint (widget, &event->area);
1846       gtk_widget_draw_focus (widget);
1847
1848       child_event = *event;
1849       if (notebook->cur_page && 
1850           GTK_WIDGET_NO_WINDOW (notebook->cur_page->child) &&
1851           gtk_widget_intersect (notebook->cur_page->child, &event->area, 
1852                                 &child_event.area))
1853         gtk_widget_event (notebook->cur_page->child, (GdkEvent*) &child_event);
1854     }
1855
1856   return FALSE;
1857 }
1858
1859 static gint
1860 gtk_notebook_button_press (GtkWidget      *widget,
1861                            GdkEventButton *event)
1862 {
1863   GtkNotebook *notebook;
1864   GtkNotebookPage *page;
1865   GList *children;
1866   gint num;
1867
1868   g_return_val_if_fail (widget != NULL, FALSE);
1869   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1870   g_return_val_if_fail (event != NULL, FALSE);
1871
1872   notebook = GTK_NOTEBOOK (widget);
1873
1874   if (event->type != GDK_BUTTON_PRESS || !notebook->children 
1875       || notebook->button)
1876     return FALSE;
1877
1878   if (event->window == notebook->panel)
1879     {
1880       if (!GTK_WIDGET_HAS_FOCUS (widget))
1881         gtk_widget_grab_focus (widget);
1882
1883       gtk_grab_add (widget);
1884       notebook->button = event->button;
1885       
1886       if (event->x <= ARROW_SIZE + ARROW_SPACING / 2)
1887         {
1888           notebook->click_child = GTK_ARROW_LEFT;
1889           if (event->button == 1)
1890             {
1891               if (!notebook->focus_tab || notebook->focus_tab->prev)
1892                 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
1893
1894               if (!notebook->timer)
1895                 {
1896                   notebook->timer = gtk_timeout_add 
1897                     (NOTEBOOK_INIT_SCROLL_DELAY, 
1898                      (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1899                   notebook->need_timer = TRUE;
1900                 }
1901             }
1902           else if (event->button == 2)
1903             gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1904           else if (event->button == 3)
1905             gtk_notebook_switch_focus_tab (notebook, notebook->children);
1906           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
1907         }
1908       else
1909         {
1910           notebook->click_child = GTK_ARROW_RIGHT;
1911           if (event->button == 1)
1912             {
1913               if (!notebook->focus_tab || notebook->focus_tab->next)
1914                 gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
1915               if (!notebook->timer)
1916                 {
1917                   notebook->timer = gtk_timeout_add 
1918                     (NOTEBOOK_INIT_SCROLL_DELAY, 
1919                      (GtkFunction) gtk_notebook_timer, (gpointer) notebook);
1920                   notebook->need_timer = TRUE;
1921                 }
1922             }      
1923           else if (event->button == 2)
1924             gtk_notebook_page_select (GTK_NOTEBOOK (widget));
1925           else if (event->button == 3)
1926             gtk_notebook_switch_focus_tab (notebook, 
1927                                            g_list_last (notebook->children));
1928           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
1929         }
1930     }
1931   else if (event->window == widget->window)
1932     {
1933       if (event->button == 3 && notebook->menu)
1934         {
1935           gtk_menu_popup (GTK_MENU (notebook->menu), NULL, NULL, 
1936                           NULL, NULL, 3, event->time);
1937           return FALSE;
1938         }
1939
1940       num = 0;
1941       children = notebook->children;
1942       while (children)
1943         {
1944           page = children->data;
1945           
1946           if (GTK_WIDGET_VISIBLE (page->child) &&
1947               page->tab_label && GTK_WIDGET_MAPPED (page->tab_label) &&
1948               (event->x >= page->allocation.x) &&
1949               (event->y >= page->allocation.y) &&
1950               (event->x <= (page->allocation.x + page->allocation.width)) &&
1951               (event->y <= (page->allocation.y + page->allocation.height)))
1952             {
1953               if (page == notebook->cur_page && notebook->focus_tab &&
1954                   notebook->focus_tab != children &&
1955                   GTK_WIDGET_HAS_FOCUS (notebook))
1956                 {
1957                   GtkNotebookPage *old_page;
1958
1959                   notebook->child_has_focus = FALSE;
1960                   old_page = (GtkNotebookPage *)
1961                               (notebook->focus_tab->data);
1962                   gtk_notebook_switch_focus_tab (notebook, children);
1963                   gtk_notebook_focus_changed (notebook, old_page);
1964                 }
1965               else
1966                 {
1967                   gtk_notebook_switch_focus_tab (notebook, children);
1968                   gtk_notebook_switch_page (notebook, page, num);
1969                   gtk_widget_grab_focus (widget);
1970                 }
1971               break;
1972             }
1973           children = children->next;
1974           num++;
1975         }
1976       if (!children && !GTK_WIDGET_HAS_FOCUS (widget))
1977         gtk_widget_grab_focus (widget);
1978     }
1979   return FALSE;
1980 }
1981
1982 static gint
1983 gtk_notebook_button_release (GtkWidget      *widget,
1984                              GdkEventButton *event)
1985 {
1986   GtkNotebook *notebook;
1987
1988   g_return_val_if_fail (widget != NULL, FALSE);
1989   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
1990   g_return_val_if_fail (event != NULL, FALSE);
1991
1992   if (event->type != GDK_BUTTON_RELEASE)
1993     return FALSE;
1994
1995   notebook = GTK_NOTEBOOK (widget);
1996
1997   if (event->button == notebook->button)
1998     {
1999       guint click_child;
2000
2001       if (notebook->timer)
2002         {
2003           gtk_timeout_remove (notebook->timer);
2004           notebook->timer = 0;
2005           notebook->need_timer = FALSE;
2006         }
2007       gtk_grab_remove (widget);
2008       click_child = notebook->click_child;
2009       notebook->click_child = 0;
2010       notebook->button = 0;
2011       gtk_notebook_draw_arrow (notebook, click_child);
2012       
2013     }
2014   return FALSE;
2015 }
2016
2017 static gint
2018 gtk_notebook_enter_notify (GtkWidget        *widget,
2019                            GdkEventCrossing *event)
2020 {
2021   GtkNotebook *notebook;
2022
2023   g_return_val_if_fail (widget != NULL, FALSE);
2024   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2025   g_return_val_if_fail (event != NULL, FALSE);
2026
2027   notebook = GTK_NOTEBOOK (widget);
2028
2029   if (event->window == notebook->panel)
2030     {
2031       gint x;
2032       gint y;
2033
2034       gdk_window_get_pointer (notebook->panel, &x, &y, NULL);
2035
2036       if (x <= ARROW_SIZE + ARROW_SPACING / 2)
2037         {
2038           notebook->in_child = GTK_ARROW_LEFT;
2039
2040           if (notebook->click_child == 0) 
2041             gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2042         }
2043       else 
2044         {
2045           notebook->in_child = GTK_ARROW_RIGHT;
2046
2047           if (notebook->click_child == 0) 
2048             gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2049         }
2050     }
2051
2052   return FALSE;
2053 }
2054
2055 static gint
2056 gtk_notebook_leave_notify (GtkWidget        *widget,
2057                            GdkEventCrossing *event)
2058 {
2059   GtkNotebook *notebook;
2060
2061   g_return_val_if_fail (widget != NULL, FALSE);
2062   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2063   g_return_val_if_fail (event != NULL, FALSE);
2064
2065   notebook = GTK_NOTEBOOK (widget);
2066
2067   if (event->window == notebook->panel && !notebook->click_child)
2068     {
2069       if (notebook->in_child == GTK_ARROW_LEFT)
2070         {
2071           notebook->in_child = 0;
2072           gtk_notebook_draw_arrow (notebook,GTK_ARROW_LEFT);
2073         }
2074       else
2075         {
2076           notebook->in_child = 0;
2077           gtk_notebook_draw_arrow (notebook,GTK_ARROW_RIGHT);
2078         }
2079     }
2080   return FALSE;
2081 }
2082
2083 static gint
2084 gtk_notebook_motion_notify (GtkWidget      *widget,
2085                             GdkEventMotion *event)
2086 {
2087   GtkNotebook *notebook;
2088
2089   g_return_val_if_fail (widget != NULL, FALSE);
2090   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2091   g_return_val_if_fail (event != NULL, FALSE);
2092
2093   notebook = GTK_NOTEBOOK (widget);
2094   
2095   if (notebook->button)
2096     return FALSE;
2097
2098   if (event->window == notebook->panel)
2099     {
2100       gint x;
2101       
2102       x = event->x;
2103       if (event->is_hint)
2104         gdk_window_get_pointer (notebook->panel, &x, NULL, NULL);
2105
2106       if (x <= ARROW_SIZE + ARROW_SPACING / 2 && 
2107           notebook->in_child == GTK_ARROW_RIGHT)
2108         {
2109           notebook->in_child = GTK_ARROW_LEFT;
2110           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2111           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2112         }
2113       else if (x > ARROW_SIZE + ARROW_SPACING / 2 && 
2114                notebook->in_child == GTK_ARROW_LEFT)
2115         {
2116           notebook->in_child = GTK_ARROW_RIGHT;
2117           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
2118           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
2119         }
2120       return FALSE;
2121     }
2122   return FALSE;
2123 }
2124
2125 static gint
2126 gtk_notebook_timer (GtkNotebook *notebook)
2127 {
2128   g_return_val_if_fail (notebook != NULL, FALSE);
2129   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
2130
2131   if (notebook->timer)
2132     {
2133       if (notebook->click_child == GTK_ARROW_LEFT)
2134         {
2135           if (!notebook->focus_tab || notebook->focus_tab->prev)
2136             gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_LEFT);
2137         }
2138       else if (notebook->click_child == GTK_ARROW_RIGHT)
2139         {
2140           if (!notebook->focus_tab || notebook->focus_tab->next)
2141             gtk_container_focus (GTK_CONTAINER (notebook), GTK_DIR_RIGHT);
2142         }
2143       
2144       if (notebook->need_timer) 
2145         {
2146           notebook->need_timer = FALSE;
2147           notebook->timer = gtk_timeout_add 
2148             (NOTEBOOK_SCROLL_DELAY, (GtkFunction) gtk_notebook_timer, 
2149              (gpointer) notebook);
2150           return FALSE;
2151         }
2152       return TRUE;
2153     }
2154   return FALSE;
2155 }
2156
2157 static void
2158 gtk_notebook_draw_arrow (GtkNotebook *notebook, guint arrow)
2159 {
2160   GtkStateType state_type;
2161   GtkShadowType shadow_type;
2162   GtkWidget *widget;
2163
2164   g_return_if_fail (notebook != NULL);
2165   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2166   
2167   widget = GTK_WIDGET(notebook);
2168
2169   if (GTK_WIDGET_DRAWABLE (notebook))
2170     {
2171       if (notebook->in_child == arrow)
2172         {
2173           if (notebook->click_child == arrow)
2174             state_type = GTK_STATE_ACTIVE;
2175           else
2176             state_type = GTK_STATE_PRELIGHT;
2177         }
2178       else
2179         state_type = GTK_STATE_NORMAL;
2180
2181       if (notebook->click_child == arrow)
2182         shadow_type = GTK_SHADOW_IN;
2183       else
2184         shadow_type = GTK_SHADOW_OUT;
2185
2186       if (arrow == GTK_ARROW_LEFT)
2187         {
2188           if (notebook->focus_tab && !notebook->focus_tab->prev)
2189             {
2190               shadow_type = GTK_SHADOW_ETCHED_IN;
2191               state_type = GTK_STATE_NORMAL;
2192             }
2193
2194           if (notebook->tab_pos == GTK_POS_LEFT ||
2195               notebook->tab_pos == GTK_POS_RIGHT)
2196             arrow = GTK_ARROW_UP;
2197           gtk_draw_arrow (widget->style, notebook->panel, state_type, 
2198                           shadow_type, arrow, TRUE, 
2199                           0, 0, ARROW_SIZE, ARROW_SIZE);
2200         }
2201       else
2202         {
2203           if (notebook->focus_tab && !notebook->focus_tab->next)
2204             {
2205               shadow_type = GTK_SHADOW_ETCHED_IN;
2206               state_type = GTK_STATE_NORMAL;
2207             }
2208
2209           if (notebook->tab_pos == GTK_POS_LEFT ||
2210               notebook->tab_pos == GTK_POS_RIGHT)
2211             arrow = GTK_ARROW_DOWN;
2212           gtk_draw_arrow (widget->style, notebook->panel, state_type, 
2213                           shadow_type, arrow, TRUE, ARROW_SIZE + ARROW_SPACING,
2214                           0, ARROW_SIZE, ARROW_SIZE);
2215         }
2216     }
2217 }
2218
2219 static void
2220 gtk_real_notebook_switch_page (GtkNotebook     *notebook,
2221                                GtkNotebookPage *page,
2222                                guint            page_num)
2223 {
2224   g_return_if_fail (notebook != NULL);
2225   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2226   g_return_if_fail (page != NULL);
2227
2228   if (notebook->cur_page == page)
2229     return;
2230
2231   if (notebook->cur_page && GTK_WIDGET_MAPPED (notebook->cur_page->child))
2232     gtk_widget_unmap (notebook->cur_page->child);
2233   
2234   notebook->cur_page = page;
2235
2236   if (!notebook->focus_tab ||
2237       notebook->focus_tab->data != (gpointer) notebook->cur_page)
2238     notebook->focus_tab = 
2239       g_list_find (notebook->children, notebook->cur_page);
2240
2241   gtk_notebook_pages_allocate (notebook, &GTK_WIDGET (notebook)->allocation);
2242
2243   if (GTK_WIDGET_MAPPED (notebook))
2244     {
2245       if (GTK_WIDGET_REALIZED (notebook->cur_page->child))
2246         gtk_widget_map (notebook->cur_page->child);
2247       else
2248         {
2249           gtk_widget_map (notebook->cur_page->child);
2250           gtk_widget_size_allocate (GTK_WIDGET (notebook), 
2251                                     &GTK_WIDGET (notebook)->allocation);
2252         }
2253     }
2254   
2255   if (GTK_WIDGET_DRAWABLE (notebook))
2256     gtk_widget_queue_draw (GTK_WIDGET (notebook));
2257 }
2258
2259 static void
2260 gtk_notebook_draw_tab (GtkNotebook     *notebook,
2261                        GtkNotebookPage *page,
2262                        GdkRectangle    *area)
2263 {
2264   GdkRectangle child_area;
2265   GdkRectangle page_area;
2266   GtkStateType state_type;
2267   GdkPoint points[6];
2268   gint n = 0;
2269  
2270   g_return_if_fail (notebook != NULL);
2271   g_return_if_fail (page != NULL);
2272   g_return_if_fail (area != NULL);
2273
2274   if (!GTK_WIDGET_MAPPED (page->tab_label))
2275     return;
2276
2277   page_area.x = page->allocation.x;
2278   page_area.y = page->allocation.y;
2279   page_area.width = page->allocation.width;
2280   page_area.height = page->allocation.height;
2281
2282   if (gdk_rectangle_intersect (&page_area, area, &child_area))
2283     {
2284       GtkWidget *widget;
2285
2286       switch (notebook->tab_pos)
2287         {
2288         case GTK_POS_TOP:
2289           if (child_area.x + child_area.width > 
2290               page->allocation.x + page->allocation.width - TAB_OVERLAP) 
2291             {
2292               points[0].x = page->allocation.x + page->allocation.width - 1;
2293               points[0].y = page->allocation.y + page->allocation.height - 1;
2294
2295               points[1].x = page->allocation.x + page->allocation.width - 1;
2296               points[1].y = page->allocation.y + TAB_CURVATURE;
2297
2298               points[2].x = page->allocation.x + page->allocation.width 
2299                 - TAB_CURVATURE - 1;
2300               points[2].y = page->allocation.y;
2301               n = 3;
2302             }
2303           else 
2304             {
2305               points[0].x = page->allocation.x + page->allocation.width 
2306                 - TAB_OVERLAP - 1;
2307               points[0].y = page->allocation.y;
2308               n = 1;
2309             }
2310           
2311           if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2312                (page == notebook->cur_page || 
2313                 page == (GtkNotebookPage *)(notebook->children->data) ||
2314                 (notebook->scrollable && 
2315                  page == (GtkNotebookPage *)(notebook->first_tab->data))) ) 
2316             {
2317               points[n].x = page->allocation.x + TAB_CURVATURE;
2318               points[n++].y = page->allocation.y;
2319             
2320               points[n].x = page->allocation.x;
2321               points[n++].y = page->allocation.y + TAB_CURVATURE;
2322
2323               points[n].x = page->allocation.x;
2324               points[n++].y = page->allocation.y + page->allocation.height - 1;
2325             }
2326           else 
2327             {
2328               points[n].x = page->allocation.x + TAB_OVERLAP;
2329               points[n++].y = page->allocation.y;
2330             }
2331           break;
2332         case GTK_POS_BOTTOM:
2333           if ( (child_area.x < page->allocation.x + TAB_OVERLAP) &&
2334                (page == notebook->cur_page || 
2335                 page == (GtkNotebookPage *)(notebook->children->data) ||
2336                 (notebook->scrollable && 
2337                  page == (GtkNotebookPage *)(notebook->first_tab->data))) ) 
2338             {
2339               points[0].x = page->allocation.x;
2340               points[0].y = page->allocation.y;
2341
2342               points[1].x = page->allocation.x;
2343               points[1].y = page->allocation.y + page->allocation.height 
2344                 - TAB_CURVATURE - 1;
2345
2346               points[2].x = page->allocation.x + TAB_CURVATURE;
2347               points[2].y = page->allocation.y + page->allocation.height - 1;
2348               n = 3;
2349             }
2350           else 
2351             {
2352               points[0].x = page->allocation.x + TAB_OVERLAP;
2353               points[0].y = page->allocation.y + page->allocation.height - 1;
2354               n = 1;
2355             }
2356
2357           if (child_area.x + child_area.width > 
2358               page->allocation.x + page->allocation.width - TAB_OVERLAP)
2359             {
2360               points[n].x = page->allocation.x + page->allocation.width 
2361                 - TAB_CURVATURE - 1;
2362               points[n++].y = page->allocation.y + page->allocation.height - 1;
2363
2364               points[n].x = page->allocation.x + page->allocation.width - 1;
2365               points[n++].y = page->allocation.y + page->allocation.height 
2366                 - TAB_CURVATURE - 1;
2367             
2368               points[n].x = page->allocation.x + page->allocation.width - 1;
2369               points[n++].y = page->allocation.y;
2370             }
2371           else 
2372             {
2373               points[n].x = page->allocation.x + page->allocation.width 
2374                 - TAB_OVERLAP - 1;
2375               points[n++].y = page->allocation.y + page->allocation.height - 1;
2376             }
2377           break;
2378         case GTK_POS_LEFT:
2379           if ( (child_area.y < page->allocation.y + TAB_OVERLAP) &&
2380                (page == notebook->cur_page || 
2381                 page == (GtkNotebookPage *)(notebook->children->data) ||
2382                 (notebook->scrollable && 
2383                  page == (GtkNotebookPage *)(notebook->first_tab->data))) )
2384             {
2385               points[0].x = page->allocation.x + page->allocation.width - 1;
2386               points[0].y = page->allocation.y;
2387               
2388               points[1].x = page->allocation.x + TAB_CURVATURE;
2389               points[1].y = page->allocation.y;
2390
2391               points[2].x = page->allocation.x;
2392               points[2].y = page->allocation.y + TAB_CURVATURE;
2393               n = 3;
2394             }
2395           else 
2396             {
2397               points[0].x = page->allocation.x;
2398               points[0].y = page->allocation.y + TAB_OVERLAP;
2399               n = 1;
2400             }
2401
2402           if (child_area.y + child_area.height > 
2403               page->allocation.y + page->allocation.height - TAB_OVERLAP) 
2404             {
2405               points[n].x = page->allocation.x;
2406               points[n++].y = page->allocation.y + page->allocation.height 
2407                 - TAB_CURVATURE - 1;
2408
2409               points[n].x = page->allocation.x + TAB_CURVATURE;
2410               points[n++].y = page->allocation.y + page->allocation.height - 1;
2411
2412               points[n].x = page->allocation.x + page->allocation.width - 1;
2413               points[n++].y = page->allocation.y + page->allocation.height - 1;
2414             }
2415           else 
2416             {
2417               points[n].x = page->allocation.x;
2418               points[n++].y = page->allocation.y + page->allocation.height 
2419                 - TAB_OVERLAP - 1;
2420             }
2421           break;
2422         case GTK_POS_RIGHT:
2423           if (child_area.y + child_area.height > 
2424               page->allocation.y + page->allocation.height - TAB_OVERLAP) 
2425             {
2426               points[0].x = page->allocation.x;
2427               points[0].y = page->allocation.y + page->allocation.height - 1;
2428
2429               points[1].x = page->allocation.x + page->allocation.width 
2430                 - TAB_CURVATURE - 1;
2431               points[1].y = page->allocation.y + page->allocation.height - 1;
2432               
2433               points[2].x = page->allocation.x + page->allocation.width - 1;
2434               points[2].y = page->allocation.y + page->allocation.height 
2435                 - TAB_CURVATURE - 1;
2436               n = 3;
2437             }
2438           else 
2439             {
2440               points[0].x = page->allocation.x + page->allocation.width - 1;
2441               points[0].y = page->allocation.y + page->allocation.height 
2442                 - TAB_OVERLAP - 1;
2443               n = 1;
2444             }
2445
2446           if ( (child_area.y < page->allocation.y + TAB_OVERLAP) && 
2447                (page == notebook->cur_page || 
2448                 page == (GtkNotebookPage *)(notebook->children->data) ||
2449                 (notebook->scrollable && 
2450                  page == (GtkNotebookPage *)(notebook->first_tab->data))) ) 
2451             {
2452               points[n].x = page->allocation.x + page->allocation.width - 1;
2453               points[n++].y = page->allocation.y + TAB_CURVATURE;
2454
2455               points[n].x = page->allocation.x + page->allocation.width 
2456                 - TAB_CURVATURE - 1;
2457               points[n++].y = page->allocation.y;
2458
2459               points[n].x = page->allocation.x;
2460               points[n++].y = page->allocation.y;
2461             }
2462           else 
2463             {
2464               points[n].x = page->allocation.x + page->allocation.width - 1;
2465               points[n++].y = page->allocation.y + TAB_OVERLAP;
2466             }
2467           break;
2468         }
2469
2470       widget = GTK_WIDGET(notebook);
2471
2472       if (notebook->cur_page == page)
2473         {
2474           state_type = GTK_STATE_NORMAL;
2475         }
2476       else 
2477         {
2478           state_type = GTK_STATE_ACTIVE;
2479           gdk_draw_rectangle (widget->window, widget->style->bg_gc[state_type],
2480                               TRUE, child_area.x, child_area.y,
2481                               child_area.width, child_area.height);
2482         }
2483       
2484       gtk_draw_polygon (widget->style, widget->window, state_type, 
2485                         GTK_SHADOW_OUT, points, n, FALSE);
2486
2487       if (gtk_widget_intersect (page->tab_label, area, &child_area))
2488         gtk_widget_draw (page->tab_label, &child_area);
2489     }
2490 }
2491
2492 static void
2493 gtk_notebook_set_focus_child (GtkContainer *container,
2494                               GtkWidget    *child)
2495 {
2496   GtkNotebook *notebook;
2497
2498   g_return_if_fail (container != NULL);
2499   g_return_if_fail (GTK_IS_NOTEBOOK (container));
2500   
2501   if (child)
2502     {
2503       g_return_if_fail (GTK_IS_WIDGET (child));
2504
2505       notebook = GTK_NOTEBOOK (container);
2506
2507       notebook->child_has_focus = TRUE;
2508       if (!notebook->focus_tab)
2509         {
2510           GList *children;
2511           GtkNotebookPage *page;
2512
2513           children = notebook->children;
2514           while (children)
2515             {
2516               page = children->data;
2517               if (page->child == child || page->tab_label == child)
2518                 gtk_notebook_switch_focus_tab (notebook, children);
2519               children = children->next;
2520             }
2521         }
2522     }
2523   parent_class->set_focus_child (container, child);
2524 }
2525
2526 static gint
2527 gtk_notebook_focus_in (GtkWidget     *widget,
2528                        GdkEventFocus *event)
2529 {
2530   g_return_val_if_fail (widget != NULL, FALSE);
2531   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2532   g_return_val_if_fail (event != NULL, FALSE);
2533
2534   GTK_NOTEBOOK (widget)->child_has_focus = FALSE;
2535   GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
2536   gtk_widget_draw_focus (widget);
2537
2538   return FALSE;
2539 }
2540
2541 static gint
2542 gtk_notebook_focus_out (GtkWidget     *widget,
2543                         GdkEventFocus *event)
2544 {
2545   g_return_val_if_fail (widget != NULL, FALSE);
2546   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
2547   g_return_val_if_fail (event != NULL, FALSE);
2548
2549   GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
2550   gtk_widget_draw_focus (widget);
2551
2552   return FALSE;
2553 }
2554
2555 static void
2556 gtk_notebook_draw_focus (GtkWidget *widget)
2557 {
2558   GtkNotebook *notebook;
2559
2560   g_return_if_fail (widget != NULL);
2561   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
2562
2563   notebook = GTK_NOTEBOOK (widget);
2564
2565   if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs &&
2566       notebook->focus_tab)
2567     {
2568       GtkNotebookPage *page;
2569       GdkGC *gc;
2570
2571       page = notebook->focus_tab->data;
2572
2573       if (GTK_WIDGET_HAS_FOCUS (widget))
2574         gc = widget->style->black_gc;
2575       else if (page == notebook->cur_page)
2576         gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2577       else
2578         gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2579
2580       gdk_draw_rectangle (widget->window, 
2581                           gc, FALSE, 
2582                           page->tab_label->allocation.x - 1, 
2583                           page->tab_label->allocation.y - 1,
2584                           page->tab_label->allocation.width + 1, 
2585                           page->tab_label->allocation.height + 1);
2586     }
2587 }
2588
2589 static void
2590 gtk_notebook_focus_changed (GtkNotebook *notebook, GtkNotebookPage *old_page)
2591 {
2592   GtkWidget *widget;
2593
2594   g_return_if_fail (notebook != NULL);
2595   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
2596
2597   widget = GTK_WIDGET (notebook);
2598
2599   if (GTK_WIDGET_DRAWABLE (widget) && notebook->show_tabs)
2600     {
2601       GdkGC *gc;
2602
2603       if (notebook->focus_tab)
2604         {
2605           GtkNotebookPage *page;
2606
2607           page = notebook->focus_tab->data;
2608
2609           if (GTK_WIDGET_HAS_FOCUS (widget))
2610             gc = widget->style->black_gc;
2611           else if (page == notebook->cur_page)
2612             gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2613           else
2614             gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2615           
2616           gdk_draw_rectangle (widget->window, 
2617                               gc, FALSE, 
2618                               page->tab_label->allocation.x - 1, 
2619                               page->tab_label->allocation.y - 1,
2620                               page->tab_label->allocation.width + 1, 
2621                               page->tab_label->allocation.height + 1);
2622         }
2623
2624       if (old_page)
2625         {
2626           if (old_page == notebook->cur_page)
2627             gc = widget->style->bg_gc[GTK_STATE_NORMAL];
2628           else
2629             gc = widget->style->bg_gc[GTK_STATE_ACTIVE];
2630          
2631           gdk_draw_rectangle (widget->window, 
2632                               gc, FALSE, 
2633                               old_page->tab_label->allocation.x - 1, 
2634                               old_page->tab_label->allocation.y - 1,
2635                               old_page->tab_label->allocation.width + 1, 
2636                               old_page->tab_label->allocation.height + 1);
2637         }
2638     }
2639 }
2640
2641 static void 
2642 gtk_notebook_calc_tabs (GtkNotebook  *notebook, 
2643                         GList        *start, 
2644                         GList       **end,
2645                         gint         *tab_space,
2646                         guint         direction)
2647 {
2648   GtkNotebookPage *page = NULL;
2649   GList *children;
2650
2651   children = start;
2652   switch (notebook->tab_pos)
2653     {
2654     case GTK_POS_TOP:
2655     case GTK_POS_BOTTOM:
2656       while (children)
2657         {
2658           page = children->data;
2659           *tab_space -= page->requisition.width;
2660           if (*tab_space < 0 || children == *end)
2661             {
2662               if (*tab_space < 0) 
2663                 {
2664                   *tab_space = - (*tab_space + page->requisition.width);
2665                   *end = children;
2666                 }
2667               break;
2668             }
2669           if (direction == STEP_NEXT)
2670             children = children->next;
2671           else
2672             children = children->prev;
2673         }
2674       break;
2675     case GTK_POS_LEFT:
2676     case GTK_POS_RIGHT:
2677       while (children)
2678         {
2679           page = children->data;
2680           *tab_space -= page->requisition.height;
2681           if (*tab_space < 0 || children == *end)
2682             {
2683               if (*tab_space < 0)
2684                 {
2685                   *tab_space = - (*tab_space + page->requisition.height);
2686                   *end = children;
2687                 }
2688               break;
2689             }
2690           if (direction == STEP_NEXT)
2691             children = children->next;
2692           else
2693             children = children->prev;
2694         }
2695       break;
2696     }
2697 }
2698
2699 static void
2700 gtk_notebook_pages_allocate (GtkNotebook   *notebook,
2701                              GtkAllocation *allocation)
2702 {
2703   GtkWidget    *widget;
2704   GtkContainer *container;
2705   GtkNotebookPage *page = NULL;
2706   GtkAllocation child_allocation;
2707   GList *children;
2708   GList *last_child = NULL;
2709   gint showarrow = FALSE;
2710   gint tab_space = 0; 
2711   gint x = 0;
2712   gint y = 0;
2713   gint i;
2714   gint n = 1;
2715   gint old_fill = 0;
2716   gint new_fill = 0;
2717   
2718   if (!notebook->show_tabs || !notebook->children)
2719     return;
2720   
2721   widget = GTK_WIDGET (notebook);
2722   container = GTK_CONTAINER (notebook);
2723   
2724   child_allocation.x = container->border_width;
2725   child_allocation.y = container->border_width;
2726   
2727   switch (notebook->tab_pos)
2728     {
2729     case GTK_POS_BOTTOM:
2730       child_allocation.y = (allocation->height -
2731                             notebook->cur_page->requisition.height -
2732                             container->border_width);
2733     case GTK_POS_TOP:
2734       child_allocation.height = notebook->cur_page->requisition.height;
2735       break;
2736     case GTK_POS_RIGHT:
2737       child_allocation.x = (allocation->width -
2738                             notebook->cur_page->requisition.width -
2739                             container->border_width);
2740     case GTK_POS_LEFT:
2741       child_allocation.width = notebook->cur_page->requisition.width;
2742       break;
2743     }
2744   
2745   if (notebook->scrollable) 
2746     {
2747       GList *focus_tab;
2748       
2749       children = notebook->children;
2750       
2751       if (notebook->focus_tab)
2752         focus_tab = notebook->focus_tab;
2753       else if (notebook->first_tab)
2754         focus_tab = notebook->first_tab;
2755       else
2756         focus_tab = notebook->children;
2757
2758       switch (notebook->tab_pos)
2759         {
2760         case GTK_POS_TOP:
2761         case GTK_POS_BOTTOM:
2762           while (children)
2763             {
2764               page = children->data;
2765               children = children->next;
2766               tab_space += page->requisition.width;
2767             }
2768           if (tab_space > allocation->width - 2 * container->border_width - TAB_OVERLAP) 
2769             {
2770               showarrow = TRUE;
2771               page = focus_tab->data; 
2772               
2773               tab_space = (allocation->width - TAB_OVERLAP - page->requisition.width -
2774                            2 * (container->border_width + ARROW_SPACING + ARROW_SIZE));
2775               x = allocation->width - 2 * ARROW_SIZE - ARROW_SPACING - container->border_width;
2776               
2777               page = notebook->children->data;
2778               if (notebook->tab_pos == GTK_POS_TOP)
2779                 y = container->border_width + (page->requisition.height - ARROW_SIZE) / 2;
2780               else
2781                 y = (allocation->height - container->border_width - 
2782                      ARROW_SIZE - (page->requisition.height - ARROW_SIZE) / 2);
2783             }
2784           break;
2785         case GTK_POS_LEFT:
2786         case GTK_POS_RIGHT:
2787           while (children)
2788             {
2789               page = children->data;
2790               children = children->next;
2791               tab_space += page->requisition.height;
2792             }
2793           if (tab_space > (allocation->height - 2 * container->border_width - TAB_OVERLAP))
2794             {
2795               showarrow = TRUE;
2796               page = focus_tab->data; 
2797               tab_space = (allocation->height -
2798                            ARROW_SIZE - ARROW_SPACING - TAB_OVERLAP -
2799                            2 * container->border_width - page->requisition.height);
2800               y = allocation->height - container->border_width - ARROW_SIZE;  
2801               
2802               page = notebook->children->data;
2803               if (notebook->tab_pos == GTK_POS_LEFT)
2804                 x = (container->border_width +
2805                      (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2); 
2806               else
2807                 x = (allocation->width - container->border_width -
2808                      (2 * ARROW_SIZE -  ARROW_SPACING) -
2809                      (page->requisition.width - (2 * ARROW_SIZE - ARROW_SPACING)) / 2);
2810             }
2811           break;
2812         }
2813       if (showarrow) /* first_tab <- focus_tab */
2814         { 
2815           children = focus_tab->prev;
2816           while (children)
2817             {
2818               if (notebook->first_tab == children)
2819                 break;
2820               children = children->prev;
2821             }
2822           
2823           if (!children)
2824             notebook->first_tab = focus_tab;
2825           else
2826             gtk_notebook_calc_tabs (notebook, focus_tab->prev, 
2827                                     &(notebook->first_tab), &tab_space,
2828                                     STEP_PREV);
2829           if (tab_space <= 0)
2830             {
2831               notebook->first_tab = notebook->first_tab->next;
2832               if (!notebook->first_tab)
2833                 notebook->first_tab = focus_tab;
2834               last_child = focus_tab->next; 
2835             }
2836           else /* focus_tab -> end */   
2837             {
2838               if (!notebook->first_tab)
2839                 notebook->first_tab = notebook->children;
2840               
2841               children = NULL;
2842               gtk_notebook_calc_tabs (notebook, focus_tab->next, 
2843                                       &children, &tab_space, STEP_NEXT);
2844               
2845               if (tab_space <= 0) 
2846                 last_child = children;
2847               else /* start <- first_tab */
2848                 {
2849                   last_child = NULL;
2850                   children = NULL;
2851                   gtk_notebook_calc_tabs (notebook,notebook->first_tab->prev,
2852                                           &children, &tab_space, STEP_PREV);
2853                   if (children)
2854                     notebook->first_tab = children->next;
2855                   else
2856                     notebook->first_tab = notebook->children;
2857                 }
2858             }
2859           
2860           if (GTK_WIDGET_REALIZED (notebook))
2861             {
2862               gdk_window_move (notebook->panel, x, y);
2863               gdk_window_show (notebook->panel);
2864             }
2865           
2866           if (tab_space < 0) 
2867             {
2868               tab_space = -tab_space;
2869               n = 0;
2870               children = notebook->first_tab;
2871               while (children != last_child)
2872                 {
2873                   children = children->next;
2874                   n++;
2875                 }
2876             }
2877           else 
2878             tab_space = 0;
2879           
2880           children = notebook->children;
2881           while (children != notebook->first_tab)
2882             {
2883               page = children->data;
2884               children = children->next;
2885               
2886               if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2887                 gtk_widget_unmap (page->tab_label);
2888               
2889             }
2890           children = last_child;
2891           while (children)
2892             {
2893               page = children->data;
2894               children = children->next;
2895               
2896               if (page->tab_label && GTK_WIDGET_MAPPED (page->tab_label))
2897                 gtk_widget_unmap (page->tab_label);
2898             }
2899         }
2900       else /* !showarrow */
2901         {
2902           notebook->first_tab = notebook->children;
2903           tab_space = 0;
2904           if (GTK_WIDGET_REALIZED (notebook))
2905             gdk_window_hide (notebook->panel);
2906         }
2907       children = notebook->first_tab;
2908     }
2909   else
2910     children = notebook->children;
2911   
2912   i = 1;
2913   while (children != last_child)
2914     {
2915       page = children->data;
2916       children = children->next;
2917       
2918       if (GTK_WIDGET_VISIBLE (page->child))
2919         {
2920           new_fill = (tab_space * i++) / n;
2921           switch (notebook->tab_pos)
2922             {
2923             case GTK_POS_TOP:
2924             case GTK_POS_BOTTOM:
2925               child_allocation.width = page->requisition.width + TAB_OVERLAP + new_fill - old_fill;
2926               break;
2927             case GTK_POS_LEFT:
2928             case GTK_POS_RIGHT:
2929               child_allocation.height = page->requisition.height + TAB_OVERLAP + new_fill - old_fill;
2930               break;
2931             }
2932           old_fill = new_fill;
2933           gtk_notebook_page_allocate (notebook, page, &child_allocation);
2934           
2935           switch (notebook->tab_pos)
2936             {
2937             case GTK_POS_TOP:
2938             case GTK_POS_BOTTOM:
2939               child_allocation.x += child_allocation.width - TAB_OVERLAP;
2940               break;
2941             case GTK_POS_LEFT:
2942             case GTK_POS_RIGHT:
2943               child_allocation.y += child_allocation.height - TAB_OVERLAP;
2944               break;
2945             }
2946           
2947           if (GTK_WIDGET_REALIZED (notebook) &&
2948               page->tab_label && !GTK_WIDGET_MAPPED (page->tab_label))
2949             gtk_widget_map (page->tab_label);
2950         }
2951     }
2952 }
2953
2954 static void
2955 gtk_notebook_page_allocate (GtkNotebook     *notebook,
2956                             GtkNotebookPage *page,
2957                             GtkAllocation   *allocation)
2958 {
2959   GtkAllocation child_allocation;
2960   gint xthickness, ythickness;
2961
2962   g_return_if_fail (notebook != NULL);
2963   g_return_if_fail (page != NULL);
2964   g_return_if_fail (allocation != NULL);
2965
2966   page->allocation = *allocation;
2967
2968   xthickness = GTK_WIDGET (notebook)->style->klass->xthickness;
2969   ythickness = GTK_WIDGET (notebook)->style->klass->ythickness;
2970
2971   if (notebook->cur_page != page)
2972     {
2973       switch (notebook->tab_pos)
2974         {
2975         case GTK_POS_TOP:
2976           page->allocation.y += ythickness;
2977         case GTK_POS_BOTTOM:
2978           page->allocation.height -= ythickness;
2979           break;
2980         case GTK_POS_LEFT:
2981           page->allocation.x += xthickness;
2982         case GTK_POS_RIGHT:
2983           page->allocation.width -= xthickness;
2984           break;
2985         }
2986     }
2987
2988   switch (notebook->tab_pos)
2989     {
2990     case GTK_POS_TOP:
2991       child_allocation.x = xthickness + notebook->tab_border;
2992       child_allocation.y = ythickness + notebook->tab_border + page->allocation.y;
2993       child_allocation.width = page->allocation.width - child_allocation.x * 2;
2994       child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
2995       child_allocation.x += page->allocation.x;
2996       break;
2997     case GTK_POS_BOTTOM:
2998       child_allocation.x = xthickness + notebook->tab_border;
2999       child_allocation.width = page->allocation.width - child_allocation.x * 2;
3000       child_allocation.height = page->allocation.height - ythickness - 2 * notebook->tab_border;
3001       child_allocation.x += page->allocation.x;
3002       child_allocation.y = page->allocation.y + notebook->tab_border;
3003       break;
3004     case GTK_POS_LEFT:
3005       child_allocation.x = xthickness + notebook->tab_border + page->allocation.x;
3006       child_allocation.y = ythickness + notebook->tab_border;
3007       child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3008       child_allocation.height = page->allocation.height - child_allocation.y * 2;
3009       child_allocation.y += page->allocation.y;
3010       break;
3011     case GTK_POS_RIGHT:
3012       child_allocation.y = ythickness + notebook->tab_border;
3013       child_allocation.width = page->allocation.width - xthickness - 2 * notebook->tab_border;
3014       child_allocation.height = page->allocation.height - child_allocation.y * 2;
3015       child_allocation.x = page->allocation.x + notebook->tab_border;
3016       child_allocation.y += page->allocation.y;
3017       break;
3018     }
3019
3020   if (page->tab_label)
3021     gtk_widget_size_allocate (page->tab_label, &child_allocation);
3022 }
3023
3024 static void
3025 gtk_notebook_menu_switch_page (GtkWidget *widget,
3026                                GtkNotebookPage *page)
3027 {
3028   GtkNotebook *notebook;
3029   GList *children;
3030   guint page_num;
3031
3032   g_return_if_fail (widget != NULL);
3033   g_return_if_fail (page != NULL);
3034
3035   notebook = GTK_NOTEBOOK (gtk_menu_get_attach_widget 
3036                            (GTK_MENU (widget->parent)));
3037
3038   if (notebook->cur_page == page)
3039     return;
3040
3041   page_num = 0;
3042   children = notebook->children;
3043   while (children && children->data != page)
3044     {
3045       children = children->next;
3046       page_num++;
3047     }
3048
3049   gtk_signal_emit (GTK_OBJECT (notebook), 
3050                    notebook_signals[SWITCH_PAGE], 
3051                    page,
3052                    page_num);
3053 }
3054
3055 static void
3056 gtk_notebook_switch_page (GtkNotebook     *notebook,
3057                           GtkNotebookPage *page,
3058                           guint            page_num)
3059
3060   g_return_if_fail (notebook != NULL);
3061   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3062   g_return_if_fail (page != NULL);
3063  
3064   if (notebook->cur_page == page)
3065     return;
3066
3067   gtk_signal_emit (GTK_OBJECT (notebook), 
3068                    notebook_signals[SWITCH_PAGE], 
3069                    page,
3070                    page_num);
3071 }
3072
3073 static void
3074 gtk_notebook_marshal_signal (GtkObject      *object,
3075                              GtkSignalFunc   func,
3076                              gpointer        func_data,
3077                              GtkArg         *args)
3078 {
3079   GtkNotebookSignal rfunc;
3080
3081   rfunc = (GtkNotebookSignal) func;
3082
3083   (* rfunc) (object, GTK_VALUE_POINTER (args[0]), GTK_VALUE_INT (args[1]),
3084              func_data);
3085 }
3086
3087 static gint
3088 gtk_notebook_focus (GtkContainer     *container,
3089                     GtkDirectionType  direction)
3090 {
3091   GtkNotebook *notebook;
3092   GtkWidget *focus_child;
3093   GtkNotebookPage *page = NULL;
3094   GtkNotebookPage *old_page = NULL;
3095   gint return_val;
3096
3097   g_return_val_if_fail (container != NULL, FALSE);
3098   g_return_val_if_fail (GTK_IS_NOTEBOOK (container), FALSE);
3099
3100   notebook = GTK_NOTEBOOK (container);
3101
3102   if (!GTK_WIDGET_SENSITIVE (container) || !notebook->children)
3103     return FALSE;
3104
3105   focus_child = container->focus_child;
3106   gtk_container_set_focus_child (container, NULL);
3107
3108   if (!notebook->show_tabs)
3109     {
3110       if (GTK_WIDGET_VISIBLE (notebook->cur_page->child))
3111         {
3112           if (GTK_IS_CONTAINER (notebook->cur_page->child))
3113             {
3114               if (gtk_container_focus 
3115                   (GTK_CONTAINER (notebook->cur_page->child), direction))
3116                 return TRUE;
3117             }
3118           else if (GTK_WIDGET_CAN_FOCUS (notebook->cur_page->child))
3119             {
3120               if (!focus_child)
3121                 {
3122                   gtk_widget_grab_focus (notebook->cur_page->child);
3123                   return TRUE;
3124                 }
3125             }
3126         }
3127       return FALSE;
3128     }
3129
3130   if (notebook->focus_tab)
3131     old_page = notebook->focus_tab->data;
3132
3133   return_val = FALSE;
3134
3135   if (focus_child && old_page && focus_child == old_page->child &&
3136       notebook->child_has_focus)
3137     {
3138       if (GTK_WIDGET_VISIBLE (old_page->child))
3139         {
3140           if (GTK_IS_CONTAINER (old_page->child) &&
3141               !GTK_WIDGET_HAS_FOCUS (old_page->child))
3142             {
3143               if (gtk_container_focus (GTK_CONTAINER (old_page->child),
3144                                        direction))
3145                 return TRUE;
3146             }
3147           gtk_widget_grab_focus (GTK_WIDGET(notebook));
3148           return TRUE;
3149         }
3150       return FALSE;
3151     }
3152   
3153   switch (direction)
3154     {
3155     case GTK_DIR_TAB_FORWARD:
3156     case GTK_DIR_RIGHT:
3157     case GTK_DIR_DOWN:
3158       if (!notebook->focus_tab)
3159         gtk_notebook_switch_focus_tab (notebook, notebook->children);
3160       else
3161         gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->next);
3162         
3163       if (!notebook->focus_tab)
3164         {
3165           gtk_notebook_focus_changed (notebook, old_page);
3166           return FALSE;
3167         }
3168
3169       page = notebook->focus_tab->data;
3170       return_val = TRUE;
3171       break;
3172
3173     case GTK_DIR_TAB_BACKWARD:
3174     case GTK_DIR_LEFT:
3175     case GTK_DIR_UP:
3176       if (!notebook->focus_tab)
3177         gtk_notebook_switch_focus_tab
3178           (notebook, g_list_last (notebook->children));
3179       else
3180         gtk_notebook_switch_focus_tab (notebook, notebook->focus_tab->prev);
3181       
3182       if (!notebook->focus_tab)
3183         {
3184           gtk_notebook_focus_changed (notebook, old_page);
3185           return FALSE;
3186         }
3187       
3188       page = notebook->focus_tab->data;
3189       return_val = TRUE;
3190       break;
3191     }
3192
3193   if (return_val)
3194     {
3195       if (!GTK_WIDGET_HAS_FOCUS (container) )
3196         gtk_widget_grab_focus (GTK_WIDGET (container));
3197
3198       if (GTK_WIDGET_MAPPED (page->tab_label))
3199         gtk_notebook_focus_changed (notebook, old_page);
3200       else
3201         {
3202           gtk_notebook_pages_allocate (notebook, 
3203                                        &(GTK_WIDGET (notebook)->allocation));
3204           gtk_notebook_expose_tabs (notebook);
3205         }
3206     }
3207
3208   return return_val;
3209 }
3210
3211 static gint
3212 gtk_notebook_page_select (GtkNotebook *notebook)
3213 {
3214   g_return_val_if_fail (notebook != NULL, FALSE);
3215   g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), FALSE);
3216
3217   if (notebook->focus_tab)
3218     {
3219       GtkNotebookPage *page;
3220       GList *children;
3221       gint num;
3222
3223       page = notebook->focus_tab->data;
3224
3225       children = notebook->children;
3226       num = 0;
3227       while (children != notebook->focus_tab)
3228         {
3229           children = children->next;
3230           num++;
3231         }
3232
3233       gtk_notebook_switch_page (notebook, page, num);
3234
3235      if (GTK_WIDGET_VISIBLE (page->child))
3236        {
3237          if (GTK_IS_CONTAINER (page->child))
3238            {
3239              if (gtk_container_focus (GTK_CONTAINER (page->child), 
3240                                       GTK_DIR_TAB_FORWARD))
3241                return TRUE;
3242            }
3243          else if (GTK_WIDGET_CAN_FOCUS (page->child))
3244            {
3245              gtk_widget_grab_focus (page->child);
3246              return TRUE;
3247            }
3248        }
3249     }
3250   return FALSE;
3251 }
3252
3253 static void
3254 gtk_notebook_switch_focus_tab (GtkNotebook *notebook, 
3255                                GList       *new_child)
3256 {
3257   GList *old_tab;
3258   GtkNotebookPage *old_page = NULL;
3259   GtkNotebookPage *page;
3260
3261   g_return_if_fail (notebook != NULL);
3262   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3263
3264   if (notebook->focus_tab == new_child)
3265     return;
3266     
3267   old_tab = notebook->focus_tab;
3268   notebook->focus_tab = new_child;
3269
3270   if (notebook->scrollable)
3271     {
3272       if ((new_child == NULL) != (old_tab == NULL))
3273         {
3274           gdk_window_clear (notebook->panel);
3275           gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3276           gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3277           
3278         }
3279       else
3280         {
3281           if ((old_tab->prev == NULL) != (new_child->prev == NULL))
3282             {
3283               gdk_window_clear_area (notebook->panel, 0, 0,
3284                                      ARROW_SIZE, ARROW_SIZE);
3285               gtk_notebook_draw_arrow (notebook, GTK_ARROW_LEFT);
3286             }
3287           if ((old_tab->next == NULL) != (new_child->next == NULL))
3288             {
3289               gdk_window_clear_area (notebook->panel,
3290                                      ARROW_SIZE + ARROW_SPACING, 0,
3291                                      ARROW_SIZE, ARROW_SIZE);
3292               gtk_notebook_draw_arrow (notebook, GTK_ARROW_RIGHT);
3293             }
3294         }
3295     }
3296   
3297   if (!notebook->focus_tab)
3298     return;
3299
3300   if (old_tab)
3301     old_page = old_tab->data;
3302
3303   page = notebook->focus_tab->data;
3304   if (GTK_WIDGET_MAPPED (page->tab_label))
3305     gtk_notebook_focus_changed (notebook, old_page);
3306   else
3307     {
3308       gtk_notebook_pages_allocate (notebook,
3309                                    &(GTK_WIDGET (notebook)->allocation));
3310       gtk_notebook_expose_tabs (notebook);
3311     }
3312 }
3313
3314 static gint
3315 gtk_notebook_key_press (GtkWidget   *widget,
3316                         GdkEventKey *event)
3317 {
3318   GtkNotebook *notebook;
3319   GtkDirectionType direction = 0;
3320   gint return_val;
3321   
3322   g_return_val_if_fail (widget != NULL, FALSE);
3323   g_return_val_if_fail (GTK_IS_NOTEBOOK (widget), FALSE);
3324   g_return_val_if_fail (event != NULL, FALSE);
3325   
3326   notebook = GTK_NOTEBOOK (widget);
3327   return_val = TRUE;
3328
3329   if (!notebook->children || !notebook->show_tabs)
3330     return FALSE;
3331
3332   switch (event->keyval)
3333     {
3334     case GDK_Up:
3335       direction = GTK_DIR_UP;
3336       break;
3337     case GDK_Left:
3338       direction = GTK_DIR_LEFT;
3339       break;
3340     case GDK_Down:
3341       direction = GTK_DIR_DOWN;
3342       break;
3343     case GDK_Right:
3344       direction = GTK_DIR_RIGHT;
3345       break;
3346     case GDK_Tab:
3347     case GDK_ISO_Left_Tab:
3348       if (event->state & GDK_SHIFT_MASK)
3349         direction = GTK_DIR_TAB_BACKWARD;
3350       else
3351         direction = GTK_DIR_TAB_FORWARD;
3352       break;
3353     case GDK_Home:
3354       gtk_notebook_switch_focus_tab (notebook, notebook->children);
3355       return TRUE;
3356     case GDK_End:
3357       gtk_notebook_switch_focus_tab (notebook, 
3358                                      g_list_last (notebook->children));
3359       return TRUE;
3360     case GDK_Return:
3361     case GDK_space:
3362       gtk_notebook_page_select (GTK_NOTEBOOK (widget));
3363       return TRUE;
3364     default:
3365       return_val = FALSE;
3366     }
3367   if (return_val)
3368     return gtk_container_focus (GTK_CONTAINER (widget), direction);
3369   return return_val;
3370 }
3371
3372 void
3373 gtk_notebook_set_tab_border (GtkNotebook *notebook,
3374                              guint        tab_border)
3375 {
3376   g_return_if_fail (notebook != NULL);
3377   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3378
3379   if (notebook->tab_border != tab_border)
3380     {
3381       notebook->tab_border = tab_border;
3382
3383       if (GTK_WIDGET_VISIBLE (notebook) && notebook->show_tabs)
3384         gtk_widget_queue_resize (GTK_WIDGET (notebook));
3385     }
3386 }
3387
3388 static void
3389 gtk_notebook_update_labels (GtkNotebook *notebook,
3390                             GList       *list,
3391                             guint        page_num)
3392 {
3393   GtkNotebookPage *page;
3394   gchar string[32];
3395
3396   while (list)
3397     {
3398       page = list->data;
3399       list = list->next;
3400       sprintf (string, "Page %u", page_num);
3401       if (notebook->show_tabs && page->default_tab)
3402         gtk_label_set (GTK_LABEL (page->tab_label), string);
3403       if (notebook->menu && page->default_menu)
3404         {
3405           if (GTK_IS_LABEL (page->tab_label))
3406             gtk_label_set (GTK_LABEL (page->menu_label), GTK_LABEL (page->tab_label)->label);
3407           else
3408             gtk_label_set (GTK_LABEL (page->menu_label), string);
3409         }
3410       page_num++;
3411     }  
3412 }
3413
3414 static void
3415 gtk_notebook_menu_item_create (GtkNotebook     *notebook, 
3416                                GtkNotebookPage *page,
3417                                gint             position)
3418 {              
3419   GtkWidget *menu_item;
3420
3421   if (page->default_menu)
3422     {
3423       if (page->tab_label && GTK_IS_LABEL (page->tab_label))
3424         page->menu_label = gtk_label_new (GTK_LABEL (page->tab_label)->label);
3425       else
3426         page->menu_label = gtk_label_new ("");
3427       gtk_misc_set_alignment (GTK_MISC (page->menu_label), 0.0, 0.5);
3428     }
3429
3430   gtk_widget_show (page->menu_label);
3431   menu_item = gtk_menu_item_new ();
3432   gtk_widget_freeze_accelerators (menu_item);
3433   gtk_container_add (GTK_CONTAINER (menu_item), page->menu_label);
3434   gtk_menu_insert (GTK_MENU (notebook->menu), menu_item, position);
3435   gtk_signal_connect (GTK_OBJECT (menu_item), "activate",
3436                       GTK_SIGNAL_FUNC (gtk_notebook_menu_switch_page), page);
3437   gtk_widget_show (menu_item);
3438 }
3439
3440 void
3441 gtk_notebook_popup_enable (GtkNotebook *notebook)
3442 {
3443   GtkNotebookPage *page;
3444   GList *children;
3445
3446   g_return_if_fail (notebook != NULL);
3447   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3448   
3449   if (notebook->menu)
3450     return;
3451
3452   notebook->menu = gtk_menu_new ();
3453   
3454   children = notebook->children;
3455   while (children)
3456     {
3457       page = children->data;
3458       children = children->next;
3459       gtk_notebook_menu_item_create (notebook, page, -1);
3460     }
3461   gtk_notebook_update_labels (notebook, notebook->children,1);
3462
3463   gtk_menu_attach_to_widget (GTK_MENU (notebook->menu), GTK_WIDGET (notebook),
3464                              gtk_notebook_menu_detacher);
3465 }
3466
3467 static void
3468 gtk_notebook_menu_label_unparent (GtkWidget *widget, 
3469                                   gpointer  data)
3470 {
3471   gtk_widget_unparent (GTK_BIN(widget)->child);
3472   GTK_BIN(widget)->child = NULL;
3473 }
3474
3475 void       
3476 gtk_notebook_popup_disable  (GtkNotebook *notebook)
3477 {
3478   g_return_if_fail (notebook != NULL);
3479   g_return_if_fail (GTK_IS_NOTEBOOK (notebook));
3480
3481   if (!notebook->menu)
3482     return;
3483
3484   gtk_container_foreach (GTK_CONTAINER (notebook->menu),
3485                          (GtkCallback) gtk_notebook_menu_label_unparent, NULL);
3486   gtk_widget_destroy (notebook->menu);
3487 }
3488
3489 static void
3490 gtk_notebook_menu_detacher (GtkWidget *widget,
3491                             GtkMenu   *menu)
3492 {
3493   GtkNotebook *notebook;
3494   
3495   g_return_if_fail (widget != NULL);
3496   g_return_if_fail (GTK_IS_NOTEBOOK (widget));
3497
3498   notebook = GTK_NOTEBOOK (widget);
3499   g_return_if_fail (notebook->menu == (GtkWidget*) menu);
3500
3501   notebook->menu = NULL;
3502 }
3503
3504 static gint
3505 gtk_notebook_find_page (gconstpointer    a,
3506                         gconstpointer    b)
3507 {
3508   return (((GtkNotebookPage *) a)->child != b);
3509 }