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